Bug 790527 - When rebooting/powering off, go through normal gecko shutdown. r=bsmedberg,sr=cjones
authorGene Lian <clian@mozilla.com>
Wed, 26 Sep 2012 17:12:33 +0800
changeset 108500 d31d2479d685f203b45738dd92983b7eebd6f5f6
parent 108497 2c694d8bf7a59441faba5d6266862299fa354b03
child 108501 eda2891c545b3ecbe1bef496d63876c4bcacddc2
push id1708
push userakeybl@mozilla.com
push dateMon, 19 Nov 2012 21:10:21 +0000
treeherdermozilla-esr52@2704e441363f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg, cjones
bugs790527
milestone18.0a1
Bug 790527 - When rebooting/powering off, go through normal gecko shutdown. r=bsmedberg,sr=cjones
dom/power/PowerManagerService.cpp
dom/power/PowerManagerService.h
hal/Hal.cpp
hal/Hal.h
hal/sandbox/PHal.ipdl
hal/sandbox/SandboxHal.cpp
--- a/dom/power/PowerManagerService.cpp
+++ b/dom/power/PowerManagerService.cpp
@@ -1,18 +1,20 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Hal.h"
 #include "mozilla/HalWakeLock.h"
 #include "mozilla/ClearOnShutdown.h"
+#include "mozilla/Services.h"
 #include "nsIDOMWakeLockListener.h"
 #include "nsIDOMWindow.h"
+#include "nsIObserverService.h"
 #include "PowerManagerService.h"
 #include "WakeLock.h"
 
 namespace mozilla {
 namespace dom {
 namespace power {
 
 NS_IMPL_ISUPPORTS1(PowerManagerService, nsIPowerManagerService)
@@ -75,27 +77,47 @@ PowerManagerService::Notify(const hal::W
    */
   nsAutoTArray<nsCOMPtr<nsIDOMMozWakeLockListener>, 2> listeners(mWakeLockListeners);
 
   for (uint32_t i = 0; i < listeners.Length(); ++i) {
     listeners[i]->Callback(aWakeLockInfo.topic(), state);
   }
 }
 
+void
+PowerManagerService::SyncProfile()
+{
+  // FIXME/bug 793970: We need to start a watchdog thread to force gecko
+  // to really power off or reboot if the profile synchronizing hangs.
+  nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService();
+  if (obsServ) {
+    NS_NAMED_LITERAL_STRING(context, "shutdown-persist");
+    obsServ->NotifyObservers(nullptr, "profile-change-net-teardown", context.get());
+    obsServ->NotifyObservers(nullptr, "profile-change-teardown", context.get());
+    obsServ->NotifyObservers(nullptr, "profile-before-change", context.get());
+  }
+}
+
 NS_IMETHODIMP
 PowerManagerService::Reboot()
 {
+  // To synchronize any unsaved user data before rebooting.
+  SyncProfile();
   hal::Reboot();
+  MOZ_NOT_REACHED();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PowerManagerService::PowerOff()
 {
+  // To synchronize any unsaved user data before powering off.
+  SyncProfile();
   hal::PowerOff();
+  MOZ_NOT_REACHED();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PowerManagerService::AddWakeLockListener(nsIDOMMozWakeLockListener *aListener)
 {
   if (mWakeLockListeners.Contains(aListener))
     return NS_OK;
--- a/dom/power/PowerManagerService.h
+++ b/dom/power/PowerManagerService.h
@@ -35,16 +35,18 @@ public:
 
 private:
 
   ~PowerManagerService();
 
   void ComputeWakeLockState(const hal::WakeLockInformation& aWakeLockInfo,
                             nsAString &aState);
 
+  void SyncProfile();
+
   static StaticRefPtr<PowerManagerService> sSingleton;
 
   nsTArray<nsCOMPtr<nsIDOMMozWakeLockListener> > mWakeLockListeners;
 };
 
 } // namespace power
 } // namespace dom
 } // namespace mozilla
--- a/hal/Hal.cpp
+++ b/hal/Hal.cpp
@@ -61,16 +61,22 @@ AssertMainThread()
 }
 
 bool
 InSandbox()
 {
   return GeckoProcessType_Content == XRE_GetProcessType();
 }
 
+void
+AssertMainProcess()
+{
+  MOZ_ASSERT(GeckoProcessType_Default == XRE_GetProcessType());
+}
+
 bool
 WindowIsActive(nsIDOMWindow *window)
 {
   NS_ENSURE_TRUE(window, false);
 
   nsCOMPtr<nsIDOMDocument> doc;
   window->GetDocument(getter_AddRefs(doc));
   NS_ENSURE_TRUE(doc, false);
@@ -556,22 +562,24 @@ void
 NotifyNetworkChange(const NetworkInformation& aInfo)
 {
   sNetworkObservers.CacheInformation(aInfo);
   sNetworkObservers.BroadcastCachedInformation();
 }
 
 void Reboot()
 {
+  AssertMainProcess();
   AssertMainThread();
   PROXY_IF_SANDBOXED(Reboot());
 }
 
 void PowerOff()
 {
+  AssertMainProcess();
   AssertMainThread();
   PROXY_IF_SANDBOXED(PowerOff());
 }
 
 void
 RegisterWakeLockObserver(WakeLockObserver* aObserver)
 {
   AssertMainThread();
@@ -769,22 +777,17 @@ SetAlarm(int32_t aSeconds, int32_t aNano
   // It's pointless to program an alarm nothing is going to observe ...
   MOZ_ASSERT(sAlarmObserver);
   RETURN_PROXY_IF_SANDBOXED(SetAlarm(aSeconds, aNanoseconds));
 }
 
 void
 SetProcessPriority(int aPid, ProcessPriority aPriority)
 {
-  if (InSandbox()) {
-    hal_sandbox::SetProcessPriority(aPid, aPriority);
-  }
-  else {
-    hal_impl::SetProcessPriority(aPid, aPriority);
-  }
+  PROXY_IF_SANDBOXED(SetProcessPriority(aPid, aPriority));
 }
 
 static StaticAutoPtr<ObserverList<FMRadioOperationInformation> > sFMRadioObservers;
 
 static void
 InitializeFMRadioObserver()
 {
   if (!sFMRadioObservers) {
--- a/hal/Hal.h
+++ b/hal/Hal.h
@@ -272,21 +272,25 @@ void UnregisterSystemTimeChangeObserver(
 /**
  * Notify of a change in the system cloeck or time zone.
  * @param aReason
  */
 void NotifySystemTimeChange(const hal::SystemTimeChange& aReason);
 
 /**
  * Reboot the device.
+ * 
+ * This API is currently only allowed to be used from the main process.
  */
 void Reboot();
 
 /**
  * Power off the device.
+ * 
+ * This API is currently only allowed to be used from the main process.
  */
 void PowerOff();
 
 /**
  * Enable wake lock notifications from the backend.
  *
  * This method is only used by WakeLockObserversManager.
  */
--- a/hal/sandbox/PHal.ipdl
+++ b/hal/sandbox/PHal.ipdl
@@ -138,19 +138,16 @@ parent:
     EnableSystemTimeChangeNotifications();
     DisableSystemTimeChangeNotifications();
 
     sync SetLight(LightType light, LightConfiguration aConfig)
       returns (bool status);
     sync GetLight(LightType light)
       returns (LightConfiguration aConfig, bool status);
 
-    Reboot();
-    PowerOff();
-
     ModifyWakeLock(nsString aTopic, WakeLockControl aLockAdjust, WakeLockControl aHiddenAdjust);
     EnableWakeLockNotifications();
     DisableWakeLockNotifications();
     sync GetWakeLockInfo(nsString aTopic)
       returns (WakeLockInformation aWakeLockInfo);
 
     EnableScreenConfigurationNotifications();
     DisableScreenConfigurationNotifications();
--- a/hal/sandbox/SandboxHal.cpp
+++ b/hal/sandbox/SandboxHal.cpp
@@ -213,23 +213,23 @@ void
 DisableSystemTimeChangeNotifications()
 {
   Hal()->SendDisableSystemTimeChangeNotifications();
 }
 
 void
 Reboot()
 {
-  Hal()->SendReboot();
+  NS_RUNTIMEABORT("Reboot() can't be called from sandboxed contexts.");
 }
 
 void
 PowerOff()
 {
-  Hal()->SendPowerOff();
+  NS_RUNTIMEABORT("PowerOff() can't be called from sandboxed contexts.");
 }
 
 void
 EnableSensorNotifications(SensorType aSensor) {
   Hal()->SendEnableSensorNotifications(aSensor);
 }
 
 void
@@ -631,36 +631,16 @@ public:
   virtual bool
   RecvDisableSystemTimeChangeNotifications() MOZ_OVERRIDE
   {
     hal::UnregisterSystemTimeChangeObserver(this);
     return true;
   }
 
   virtual bool
-  RecvReboot() MOZ_OVERRIDE
-  {
-    if (!AssertAppProcessPermission(this, "power")) {
-      return false;
-    }
-    hal::Reboot();
-    return true;
-  }
-
-  virtual bool
-  RecvPowerOff() MOZ_OVERRIDE
-  {
-    if (!AssertAppProcessPermission(this, "power")) {
-      return false;
-    }
-    hal::PowerOff();
-    return true;
-  }
-
-  virtual bool
   RecvEnableSensorNotifications(const SensorType &aSensor) MOZ_OVERRIDE {
     // We currently allow any content to register device-sensor
     // listeners.
     hal::RegisterSensorObserver(aSensor, this);
     return true;
   }
    
   virtual bool