Bug 757762 - Lightning's alarms too late / internal time is wrong. r+a=philipp BETA_BASE_20130401
authorMatthew Mecca <matthew.mecca@gmail.com>
Sat, 23 Feb 2013 19:08:53 -0500
changeset 14964 884489720bf64bcb5c1a2ca5582d2389e32959b8
parent 14963 93713f6b80f814abf7dbb4fbb76df1e03fff9323
child 14965 9d4b7e33de3109b9b604aced9c6b2c74345e1688
push idunknown
push userunknown
push dateunknown
bugs757762
Bug 757762 - Lightning's alarms too late / internal time is wrong. r+a=philipp
calendar/base/src/calAlarmService.js
--- a/calendar/base/src/calAlarmService.js
+++ b/calendar/base/src/calAlarmService.js
@@ -3,16 +3,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 Components.utils.import("resource://calendar/modules/calUtils.jsm");
 Components.utils.import("resource://calendar/modules/calAlarmUtils.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 const kHoursBetweenUpdates = 6;
+const kSleepMonitorInterval = 60000;
+const kSleepMonitorTolerance = 1000;
 
 function nowUTC() {
     return cal.jsDateToDateTime(new Date()).getInTimezone(cal.UTC());
 }
 
 function newTimerWithCallback(aCallback, aDelay, aRepeating) {
     let timer = Components.classes["@mozilla.org/timer;1"]
                           .createInstance(Components.interfaces.nsITimer);
@@ -25,16 +27,48 @@ function newTimerWithCallback(aCallback,
 
 function calAlarmService() {
     this.wrappedJSObject = this;
 
     this.mLoadedCalendars = {};
     this.mTimerMap = {};
     this.mObservers = new calListenerBag(Components.interfaces.calIAlarmServiceObserver);
 
+    this.mSleepMonitor = {
+        service: this,
+        interval: kSleepMonitorInterval,
+        timer: null,
+        expected: null,
+
+        checkExpected: function sm_checkExpected() {
+            let now = Date.now();
+            if (now - this.expected > kSleepMonitorTolerance) {
+                cal.LOG("[calAlarmService] Sleep cycle detected, reloading alarms");
+                this.service.shutdown();
+                this.service.startup();
+            } else {
+                this.expected = now + this.interval;
+            }
+        },
+
+        start: function sm_start() {
+            this.stop();
+            this.expected = Date.now() + this.interval;
+            this.timer = newTimerWithCallback(this.checkExpected.bind(this),
+                                              this.interval, true);
+        },
+
+        stop: function sm_stop() {
+            if (this.timer) {
+                this.timer.cancel();
+                this.timer = null;
+            }
+        }
+    };
+
     this.calendarObserver = {
         alarmService: this,
 
         QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIObserver]),
 
         // calIObserver:
         onStartBatch: function() { },
         onEndBatch: function() { },
@@ -266,16 +300,22 @@ calAlarmService.prototype = {
                 this.alarmService.findAlarms(getCalendarManager().getCalendars({}),
                                              start, until);
             }
         };
         timerCallback.notify();
 
         this.mUpdateTimer = newTimerWithCallback(timerCallback, kHoursBetweenUpdates * 3600000, true);
 
+        // The sleep monitor needs to be started on platforms that don't support wake_notification
+        if (Services.appinfo.OS != "WINNT" && Services.appinfo.OS != "Darwin") {
+            cal.LOG("[calAlarmService] Starting sleep monitor.");
+            this.mSleepMonitor.start();
+        }
+
         this.mStarted = true;
     },
 
     shutdown: function cAS_shutdown() {
         if (!this.mStarted) {
             return;
         }
 
@@ -298,16 +338,18 @@ calAlarmService.prototype = {
         }
 
         this.mRangeEnd = null;
 
         Services.obs.removeObserver(this, "profile-after-change");
         Services.obs.removeObserver(this, "xpcom-shutdown");
         Services.obs.removeObserver(this, "wake_notification");
 
+        this.mSleepMonitor.stop();
+
         this.mStarted = false;
     },
 
     observeCalendar: function cAS_observeCalendar(calendar) {
         calendar.addObserver(this.calendarObserver);
     },
 
     unobserveCalendar: function cAS_unobserveCalendar(calendar) {