Bug 714358 System time change implementation, r=mounir
authorSteven Lee <slee@mozilla.com>
Tue, 11 Sep 2012 02:40:00 -0400
changeset 106810 9efd6fc80405b40a892786f21fe3fe08c0de72a9
parent 106809 d059d752c212d0deecf1e7bd0a764bf51dce272d
child 106811 0a941f6df7f652e8161b5adadc6930ecb10c7955
push idunknown
push userunknown
push dateunknown
reviewersmounir
bugs714358
milestone18.0a1
Bug 714358 System time change implementation, r=mounir
dom/time/nsIDOMTimeManager.idl
hal/Hal.cpp
hal/Hal.h
hal/HalTypes.h
hal/gonk/GonkHal.cpp
hal/sandbox/PHal.ipdl
hal/sandbox/SandboxHal.cpp
--- a/dom/time/nsIDOMTimeManager.idl
+++ b/dom/time/nsIDOMTimeManager.idl
@@ -11,10 +11,10 @@ interface nsIDOMMozTimeManager : nsISupp
    *
    * The |time| argument can be either a Date object or a number.
    *
    * - If |time| is a number, it's interpreted as seconds since the epoch 
    *   (midnight UTC on January 1, 1970)
    * - If |time| is a Date object, |set(time)| is equivalent to 
    *   |set(time.getTime())|.
    */
-  void set(in jsval time);
+  [implicit_jscontext] void set(in jsval time);
 };
--- a/hal/Hal.cpp
+++ b/hal/Hal.cpp
@@ -401,17 +401,49 @@ bool SetLight(LightType light, const hal
 }
 
 bool GetLight(LightType light, hal::LightConfiguration* aConfig)
 {
   AssertMainThread();
   RETURN_PROXY_IF_SANDBOXED(GetLight(light, aConfig));
 }
 
+static StaticAutoPtr<ObserverList<SystemTimeChange>> sSystemTimeObserver;
 
+static void
+InitializeSystemTimeChangeObserver()
+{
+  if (!sSystemTimeObserver) {
+    sSystemTimeObserver = new ObserverList<SystemTimeChange>;
+    ClearOnShutdown(&sSystemTimeObserver);
+  }
+}
+
+void
+RegisterSystemTimeChangeObserver(SystemTimeObserver *aObserver)
+{
+  AssertMainThread();
+  InitializeSystemTimeChangeObserver();
+  sSystemTimeObserver->AddObserver(aObserver);
+}
+
+void
+UnregisterSystemTimeChangeObserver(SystemTimeObserver *aObserver)
+{
+  AssertMainThread();
+  sSystemTimeObserver->RemoveObserver(aObserver);
+}
+
+void
+NotifySystemTimeChange(const hal::SystemTimeChange& aReason)
+{
+  InitializeSystemTimeChangeObserver();
+  sSystemTimeObserver->Broadcast(aReason);
+}
+ 
 void 
 AdjustSystemClock(int32_t aDeltaMilliseconds)
 {
   AssertMainThread();
   PROXY_IF_SANDBOXED(AdjustSystemClock(aDeltaMilliseconds));
 }
 
 void 
--- a/hal/Hal.h
+++ b/hal/Hal.h
@@ -45,16 +45,18 @@ namespace hal {
 typedef Observer<void_t> AlarmObserver;
 typedef Observer<ScreenConfiguration> ScreenConfigurationObserver;
 
 class WindowIdentifier;
 
 extern PRLogModuleInfo *sHalLog;
 #define HAL_LOG(msg) PR_LOG(mozilla::hal::sHalLog, PR_LOG_DEBUG, msg)
 
+typedef Observer<SystemTimeChange> SystemTimeObserver;
+
 } // namespace hal
 
 namespace MOZ_HAL_NAMESPACE {
 
 /**
  * Turn the default vibrator device on/off per the pattern specified
  * by |pattern|.  Each element in the pattern is the number of
  * milliseconds to turn the vibrator on or off.  The first element in
@@ -251,16 +253,34 @@ void SetTimezone(const nsCString& aTimez
 
 /**
  * Get timezone
  * http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
  */
 nsCString GetTimezone();
 
 /**
+ * Register observer for system time changed notification.
+ * @param aObserver The observer that should be added.
+ */
+void RegisterSystemTimeChangeObserver(hal::SystemTimeObserver* aObserver);
+
+/**
+ * Unregister the observer for system time changed.
+ * @param aObserver The observer that should be removed.
+ */
+void UnregisterSystemTimeChangeObserver(hal::SystemTimeObserver* aObserver);
+
+/**
+ * Notify of a change in the system cloeck or time zone.
+ * @param aReason
+ */
+void NotifySystemTimeChange(const hal::SystemTimeChange& aReason);
+
+/**
  * Reboot the device.
  */
 void Reboot();
 
 /**
  * Power off the device.
  */
 void PowerOff();
--- a/hal/HalTypes.h
+++ b/hal/HalTypes.h
@@ -69,16 +69,23 @@ enum ProcessPriority {
  */
 enum WakeLockControl {
   WAKE_LOCK_REMOVE_ONE = -1,
   WAKE_LOCK_NO_CHANGE  = 0,
   WAKE_LOCK_ADD_ONE    = 1,
   NUM_WAKE_LOCK
 };
 
+enum SystemTimeChange {
+  SYS_TIME_CHANGE_UNKNOWN = -1,
+  SYS_TIME_CHANGE_CLOCK,
+  SYS_TIME_CHANGE_TZ,
+  SYS_TIME_CHANGE_GUARD
+};
+
 } // namespace hal
 } // namespace mozilla
 
 namespace IPC {
 
 /**
  * Light type serializer.
  */
@@ -141,12 +148,21 @@ struct ParamTraits<mozilla::hal::SwitchD
 
 template <>
 struct ParamTraits<mozilla::hal::ProcessPriority>:
   public EnumSerializer<mozilla::hal::ProcessPriority,
                         mozilla::hal::PROCESS_PRIORITY_BACKGROUND,
                         mozilla::hal::NUM_PROCESS_PRIORITY> {
 };
 
-
+/**
+ * SystemTimeChange serializer.
+ */
+template <>
+struct ParamTraits<mozilla::hal::SystemTimeChange>
+  : public EnumSerializer<mozilla::hal::SystemTimeChange,
+                          mozilla::hal::SYS_TIME_CHANGE_UNKNOWN,
+                          mozilla::hal::SYS_TIME_CHANGE_GUARD>
+{};
+ 
 } // namespace IPC
 
 #endif // mozilla_hal_Types_h
--- a/hal/gonk/GonkHal.cpp
+++ b/hal/gonk/GonkHal.cpp
@@ -576,16 +576,20 @@ static int
 sys_clock_settime(clockid_t clk_id, const struct timespec *tp)
 {
   return syscall(__NR_clock_settime, clk_id, tp);
 }
 
 void 
 AdjustSystemClock(int32_t aDeltaMilliseconds)
 {
+  if (aDeltaMilliseconds == 0) {
+    return;
+  }
+  
   struct timespec now;
   
   // Preventing context switch before setting system clock 
   sched_yield();
   clock_gettime(CLOCK_REALTIME, &now);
   now.tv_sec += aDeltaMilliseconds/1000;
   now.tv_nsec += (aDeltaMilliseconds%1000)*NsecPerMsec;
   if (now.tv_nsec >= NsecPerSec)
@@ -595,26 +599,36 @@ AdjustSystemClock(int32_t aDeltaMillisec
   }
 
   if (now.tv_nsec < 0)
   {
     now.tv_nsec += NsecPerSec;
     now.tv_sec -= 1;  
   }
   // we need to have root privilege. 
-  sys_clock_settime(CLOCK_REALTIME, &now);   
+  if (sys_clock_settime(CLOCK_REALTIME, &now) != 0) {
+    NS_ERROR("sys_clock_settime failed");
+    return;
+  }
+  
+  hal::NotifySystemTimeChange(hal::SYS_TIME_CHANGE_CLOCK);
 }
 
 void 
 SetTimezone(const nsCString& aTimezoneSpec)
-{ 
+{
+  if (aTimezoneSpec.Equals(GetTimezone())) {
+    return;
+  }
+
   property_set("persist.sys.timezone", aTimezoneSpec.get());
   // this function is automatically called by the other time conversion 
   // functions that depend on the timezone. To be safe, we call it manually.  
   tzset();
+  hal::NotifySystemTimeChange(hal::SYS_TIME_CHANGE_TZ);
 }
 
 nsCString 
 GetTimezone()
 {
   char timezone[32];
   property_get("persist.sys.timezone", timezone, "");
   return nsCString(timezone);
--- a/hal/sandbox/PHal.ipdl
+++ b/hal/sandbox/PHal.ipdl
@@ -19,16 +19,17 @@ using mozilla::hal::LightMode;
 using mozilla::hal::SensorType;
 using mozilla::hal::SensorAccuracyType;
 using mozilla::hal::WakeLockControl;
 using mozilla::hal::SwitchState;
 using mozilla::hal::SwitchDevice;
 using mozilla::hal::ProcessPriority;
 using nsIntRect;
 using PRTime;
+using mozilla::hal::SystemTimeChange;
 
 namespace mozilla {
 
 namespace hal {
 struct BatteryInformation {
   double level;
   bool   charging;
   double remainingTime;
@@ -81,16 +82,17 @@ sync protocol PHal {
     manager PContent;
 
 child:
     NotifyBatteryChange(BatteryInformation aBatteryInfo);
     NotifyNetworkChange(NetworkInformation aNetworkInfo);
     NotifyWakeLockChange(WakeLockInformation aWakeLockInfo);
     NotifyScreenConfigurationChange(ScreenConfiguration aScreenOrientation);
     NotifySwitchChange(SwitchEvent aEvent);
+    NotifySystemTimeChange(SystemTimeChange aReason); 
 
 parent:
     Vibrate(uint32_t[] pattern, uint64_t[] id, PBrowser browser);
     CancelVibrate(uint64_t[] id, PBrowser browser);
 
     EnableBatteryNotifications();
     DisableBatteryNotifications();
     sync GetCurrentBatteryInformation()
--- a/hal/sandbox/SandboxHal.cpp
+++ b/hal/sandbox/SandboxHal.cpp
@@ -671,16 +671,21 @@ public:
   virtual bool
   RecvSetProcessPriority(const int& aPid, const ProcessPriority& aPriority)
   {
     // TODO As a security check, we should ensure that aPid is either the pid
     // of our child, or the pid of one of the child's children.
     hal::SetProcessPriority(aPid, aPriority);
     return true;
   }
+
+  void Notify(const SystemTimeChange& aReason)
+  {
+    unused << SendNotifySystemTimeChange(aReason);
+  }
 };
 
 class HalChild : public PHalChild {
 public:
   virtual bool
   RecvNotifyBatteryChange(const BatteryInformation& aBatteryInfo) MOZ_OVERRIDE {
     hal::NotifyBatteryChange(aBatteryInfo);
     return true;
@@ -707,16 +712,22 @@ public:
     return true;
   }
 
   virtual bool
   RecvNotifySwitchChange(const mozilla::hal::SwitchEvent& aEvent) MOZ_OVERRIDE {
     hal::NotifySwitchChange(aEvent);
     return true;
   }
+
+  virtual bool
+  RecvNotifySystemTimeChange(const SystemTimeChange& aReason) {
+    hal::NotifySystemTimeChange(aReason);
+    return true;
+  }
 };
 
 bool
 HalChild::RecvNotifySensorChange(const hal::SensorData &aSensorData) {
   hal::NotifySensorChange(aSensorData);
   
   return true;
 }