Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "mozilla/dom/ContentParent.h"
7 #include "mozilla/Hal.h"
8 #include "mozilla/HalWakeLock.h"
9 #include "mozilla/ClearOnShutdown.h"
10 #include "mozilla/Preferences.h"
11 #include "mozilla/Services.h"
12 #include "nsIDOMWakeLockListener.h"
13 #include "nsIDOMWindow.h"
14 #include "nsIObserverService.h"
15 #include "PowerManagerService.h"
16 #include "WakeLock.h"
18 // For _exit().
19 #ifdef XP_WIN
20 #include <process.h>
21 #else
22 #include <unistd.h>
23 #endif
25 #ifdef ANDROID
26 #include <android/log.h>
27 extern "C" char* PrintJSStack();
28 static void LogFunctionAndJSStack(const char* funcname) {
29 char *jsstack = PrintJSStack();
30 __android_log_print(ANDROID_LOG_INFO, "PowerManagerService", \
31 "Call to %s. The JS stack is:\n%s\n",
32 funcname,
33 jsstack ? jsstack : "<no JS stack>");
34 }
35 // bug 839452
36 #define LOG_FUNCTION_AND_JS_STACK() \
37 LogFunctionAndJSStack(__PRETTY_FUNCTION__);
38 #else
39 #define LOG_FUNCTION_AND_JS_STACK()
40 #endif
42 namespace mozilla {
43 namespace dom {
44 namespace power {
46 using namespace hal;
48 NS_IMPL_ISUPPORTS(PowerManagerService, nsIPowerManagerService)
50 /* static */ StaticRefPtr<PowerManagerService> PowerManagerService::sSingleton;
52 /* static */ already_AddRefed<PowerManagerService>
53 PowerManagerService::GetInstance()
54 {
55 if (!sSingleton) {
56 sSingleton = new PowerManagerService();
57 sSingleton->Init();
58 ClearOnShutdown(&sSingleton);
59 }
61 nsRefPtr<PowerManagerService> service = sSingleton.get();
62 return service.forget();
63 }
65 void
66 PowerManagerService::Init()
67 {
68 RegisterWakeLockObserver(this);
70 // NB: default to *enabling* the watchdog even when the pref is
71 // absent, in case the profile might be damaged and we need to
72 // restart to repair it.
73 mWatchdogTimeoutSecs =
74 Preferences::GetInt("shutdown.watchdog.timeoutSecs", 5);
75 }
77 PowerManagerService::~PowerManagerService()
78 {
79 UnregisterWakeLockObserver(this);
80 }
82 void
83 PowerManagerService::ComputeWakeLockState(const WakeLockInformation& aWakeLockInfo,
84 nsAString &aState)
85 {
86 WakeLockState state = hal::ComputeWakeLockState(aWakeLockInfo.numLocks(),
87 aWakeLockInfo.numHidden());
88 switch (state) {
89 case WAKE_LOCK_STATE_UNLOCKED:
90 aState.AssignLiteral("unlocked");
91 break;
92 case WAKE_LOCK_STATE_HIDDEN:
93 aState.AssignLiteral("locked-background");
94 break;
95 case WAKE_LOCK_STATE_VISIBLE:
96 aState.AssignLiteral("locked-foreground");
97 break;
98 }
99 }
101 void
102 PowerManagerService::Notify(const WakeLockInformation& aWakeLockInfo)
103 {
104 nsAutoString state;
105 ComputeWakeLockState(aWakeLockInfo, state);
107 /**
108 * Copy the listeners list before we walk through the callbacks
109 * because the callbacks may install new listeners. We expect no
110 * more than one listener per window, so it shouldn't be too long.
111 */
112 nsAutoTArray<nsCOMPtr<nsIDOMMozWakeLockListener>, 2> listeners(mWakeLockListeners);
114 for (uint32_t i = 0; i < listeners.Length(); ++i) {
115 listeners[i]->Callback(aWakeLockInfo.topic(), state);
116 }
117 }
119 void
120 PowerManagerService::SyncProfile()
121 {
122 nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService();
123 if (obsServ) {
124 NS_NAMED_LITERAL_STRING(context, "shutdown-persist");
125 obsServ->NotifyObservers(nullptr, "profile-change-net-teardown", context.get());
126 obsServ->NotifyObservers(nullptr, "profile-change-teardown", context.get());
127 obsServ->NotifyObservers(nullptr, "profile-before-change", context.get());
128 obsServ->NotifyObservers(nullptr, "profile-before-change2", context.get());
129 }
130 }
132 NS_IMETHODIMP
133 PowerManagerService::Reboot()
134 {
135 LOG_FUNCTION_AND_JS_STACK() // bug 839452
137 StartForceQuitWatchdog(eHalShutdownMode_Reboot, mWatchdogTimeoutSecs);
138 // To synchronize any unsaved user data before rebooting.
139 SyncProfile();
140 hal::Reboot();
141 MOZ_CRASH("hal::Reboot() shouldn't return");
142 }
144 NS_IMETHODIMP
145 PowerManagerService::PowerOff()
146 {
147 LOG_FUNCTION_AND_JS_STACK() // bug 839452
149 StartForceQuitWatchdog(eHalShutdownMode_PowerOff, mWatchdogTimeoutSecs);
150 // To synchronize any unsaved user data before powering off.
151 SyncProfile();
152 hal::PowerOff();
153 MOZ_CRASH("hal::PowerOff() shouldn't return");
154 }
156 NS_IMETHODIMP
157 PowerManagerService::Restart()
158 {
159 LOG_FUNCTION_AND_JS_STACK() // bug 839452
161 // FIXME/bug 796826 this implementation is currently gonk-specific,
162 // because it relies on the Gonk to initialize the Gecko processes to
163 // restart B2G. It's better to do it here to have a real "restart".
164 StartForceQuitWatchdog(eHalShutdownMode_Restart, mWatchdogTimeoutSecs);
165 // Ensure all content processes are dead before we continue
166 // restarting. This code is used to restart to apply updates, and
167 // if we don't join all the subprocesses, race conditions can cause
168 // them to see an inconsistent view of the application directory.
169 ContentParent::JoinAllSubprocesses();
171 // To synchronize any unsaved user data before restarting.
172 SyncProfile();
173 #ifdef XP_UNIX
174 sync();
175 #endif
176 _exit(0);
177 MOZ_CRASH("_exit() shouldn't return");
178 }
180 NS_IMETHODIMP
181 PowerManagerService::AddWakeLockListener(nsIDOMMozWakeLockListener *aListener)
182 {
183 if (mWakeLockListeners.Contains(aListener))
184 return NS_OK;
186 mWakeLockListeners.AppendElement(aListener);
187 return NS_OK;
188 }
190 NS_IMETHODIMP
191 PowerManagerService::RemoveWakeLockListener(nsIDOMMozWakeLockListener *aListener)
192 {
193 mWakeLockListeners.RemoveElement(aListener);
194 return NS_OK;
195 }
197 NS_IMETHODIMP
198 PowerManagerService::GetWakeLockState(const nsAString &aTopic, nsAString &aState)
199 {
200 WakeLockInformation info;
201 GetWakeLockInfo(aTopic, &info);
203 ComputeWakeLockState(info, aState);
205 return NS_OK;
206 }
208 already_AddRefed<WakeLock>
209 PowerManagerService::NewWakeLock(const nsAString& aTopic,
210 nsIDOMWindow* aWindow,
211 mozilla::ErrorResult& aRv)
212 {
213 nsRefPtr<WakeLock> wakelock = new WakeLock();
214 aRv = wakelock->Init(aTopic, aWindow);
215 if (aRv.Failed()) {
216 return nullptr;
217 }
219 return wakelock.forget();
220 }
222 NS_IMETHODIMP
223 PowerManagerService::NewWakeLock(const nsAString &aTopic,
224 nsIDOMWindow *aWindow,
225 nsISupports **aWakeLock)
226 {
227 mozilla::ErrorResult rv;
228 nsRefPtr<WakeLock> wakelock = NewWakeLock(aTopic, aWindow, rv);
229 if (rv.Failed()) {
230 return rv.ErrorCode();
231 }
233 nsCOMPtr<nsIDOMEventListener> eventListener = wakelock.get();
234 eventListener.forget(aWakeLock);
235 return NS_OK;
236 }
238 already_AddRefed<WakeLock>
239 PowerManagerService::NewWakeLockOnBehalfOfProcess(const nsAString& aTopic,
240 ContentParent* aContentParent)
241 {
242 nsRefPtr<WakeLock> wakelock = new WakeLock();
243 nsresult rv = wakelock->Init(aTopic, aContentParent);
244 NS_ENSURE_SUCCESS(rv, nullptr);
245 return wakelock.forget();
246 }
248 } // power
249 } // dom
250 } // mozilla