mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 749551 - Alarm API (AlarmsManager and AlarmService). r=vivien
This commit is contained in:
parent
6cd0768686
commit
a993ee244f
@ -14,6 +14,7 @@ Cu.import('resource://gre/modules/Services.jsm');
|
||||
Cu.import('resource://gre/modules/ContactService.jsm');
|
||||
Cu.import('resource://gre/modules/SettingsChangeNotifier.jsm');
|
||||
Cu.import('resource://gre/modules/Webapps.jsm');
|
||||
Cu.import('resource://gre/modules/AlarmService.jsm');
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, 'env',
|
||||
'@mozilla.org/process/environment;1',
|
||||
|
299
dom/alarm/AlarmService.jsm
Normal file
299
dom/alarm/AlarmService.jsm
Normal file
@ -0,0 +1,299 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
/* static functions */
|
||||
const DEBUG = false;
|
||||
|
||||
function debug(aStr) {
|
||||
if (DEBUG)
|
||||
dump("AlarmService: " + aStr + "\n");
|
||||
}
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/AlarmDB.jsm");
|
||||
|
||||
let EXPORTED_SYMBOLS = ["AlarmService"];
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
|
||||
return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
|
||||
});
|
||||
|
||||
let myGlobal = this;
|
||||
|
||||
let AlarmService = {
|
||||
init: function init() {
|
||||
debug("init()");
|
||||
|
||||
this._currentTimezoneOffset = (new Date()).getTimezoneOffset();
|
||||
|
||||
let alarmHalService = this._alarmHalService = Cc["@mozilla.org/alarmHalService;1"].getService(Ci.nsIAlarmHalService);
|
||||
alarmHalService.setAlarmFiredCb(this._onAlarmFired.bind(this));
|
||||
alarmHalService.setTimezoneChangedCb(this._onTimezoneChanged.bind(this));
|
||||
|
||||
// add the messages to be listened
|
||||
const messages = ["AlarmsManager:GetAll", "AlarmsManager:Add", "AlarmsManager:Remove"];
|
||||
messages.forEach(function addMessage(msgName) {
|
||||
ppmm.addMessageListener(msgName, this);
|
||||
}.bind(this));
|
||||
|
||||
// set the indexeddb database
|
||||
let idbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"].getService(Ci.nsIIndexedDatabaseManager);
|
||||
idbManager.initWindowless(myGlobal);
|
||||
this._db = new AlarmDB(myGlobal);
|
||||
this._db.init(myGlobal);
|
||||
|
||||
// variable to save alarms waiting to be set
|
||||
this._alarmQueue = [];
|
||||
|
||||
this._restoreAlarmsFromDb();
|
||||
},
|
||||
|
||||
// getter/setter to access the current alarm set in system
|
||||
_alarm: null,
|
||||
get _currentAlarm() {
|
||||
return this._alarm;
|
||||
},
|
||||
set _currentAlarm(aAlarm) {
|
||||
this._alarm = aAlarm;
|
||||
if (!aAlarm)
|
||||
return;
|
||||
|
||||
if (!this._alarmHalService.setAlarm(this._getAlarmTime(aAlarm) / 1000, 0))
|
||||
throw Components.results.NS_ERROR_FAILURE;
|
||||
},
|
||||
|
||||
receiveMessage: function receiveMessage(aMessage) {
|
||||
debug("receiveMessage(): " + aMessage.name);
|
||||
|
||||
let json = aMessage.json;
|
||||
switch (aMessage.name) {
|
||||
case "AlarmsManager:GetAll":
|
||||
this._db.getAll(
|
||||
function getAllSuccessCb(aAlarms) {
|
||||
debug("Callback after getting alarms from database: " + JSON.stringify(aAlarms));
|
||||
ppmm.sendAsyncMessage(
|
||||
"AlarmsManager:GetAll:Return:OK",
|
||||
{ requestID: json.requestID, alarms: aAlarms }
|
||||
);
|
||||
}.bind(this),
|
||||
function getAllErrorCb(aErrorMsg) {
|
||||
ppmm.sendAsyncMessage(
|
||||
"AlarmsManager:GetAll:Return:KO",
|
||||
{ requestID: json.requestID, errorMsg: aErrorMsg }
|
||||
);
|
||||
}.bind(this)
|
||||
);
|
||||
break;
|
||||
|
||||
case "AlarmsManager:Add":
|
||||
// prepare a record for the new alarm to be added
|
||||
let newAlarm = {
|
||||
date: json.date,
|
||||
ignoreTimezone: json.ignoreTimezone,
|
||||
timezoneOffset: this._currentTimezoneOffset,
|
||||
data: json.data
|
||||
};
|
||||
|
||||
this._db.add(
|
||||
newAlarm,
|
||||
function addSuccessCb(aNewId) {
|
||||
debug("Callback after adding alarm in database.");
|
||||
|
||||
newAlarm['id'] = aNewId;
|
||||
let newAlarmTime = this._getAlarmTime(newAlarm);
|
||||
|
||||
if (newAlarmTime <= Date.now()) {
|
||||
debug("Adding a alarm that has past time. Don't set it in system.");
|
||||
this._debugCurrentAlarm();
|
||||
return;
|
||||
}
|
||||
|
||||
// if there is no alarm being set in system, set the new alarm
|
||||
if (this._currentAlarm == null) {
|
||||
this._currentAlarm = newAlarm;
|
||||
this._debugCurrentAlarm();
|
||||
return;
|
||||
}
|
||||
|
||||
// if the new alarm is earlier than the current alarm
|
||||
// swap them and push the previous alarm back to queue
|
||||
let alarmQueue = this._alarmQueue;
|
||||
let currentAlarmTime = this._getAlarmTime(this._currentAlarm);
|
||||
if (newAlarmTime < currentAlarmTime) {
|
||||
alarmQueue.unshift(this._currentAlarm);
|
||||
this._currentAlarm = newAlarm;
|
||||
this._debugCurrentAlarm();
|
||||
return;
|
||||
}
|
||||
|
||||
//push the new alarm in the queue
|
||||
alarmQueue.push(newAlarm);
|
||||
alarmQueue.sort(this._sortAlarmByTimeStamps.bind(this));
|
||||
this._debugCurrentAlarm();
|
||||
|
||||
ppmm.sendAsyncMessage(
|
||||
"AlarmsManager:Add:Return:OK",
|
||||
{ requestID: json.requestID, id: aNewId }
|
||||
);
|
||||
}.bind(this),
|
||||
function addErrorCb(aErrorMsg) {
|
||||
ppmm.sendAsyncMessage(
|
||||
"AlarmsManager:Add:Return:KO",
|
||||
{ requestID: json.requestID, errorMsg: aErrorMsg }
|
||||
);
|
||||
}.bind(this)
|
||||
);
|
||||
break;
|
||||
|
||||
case "AlarmsManager:Remove":
|
||||
this._db.remove(
|
||||
json.id,
|
||||
function removeSuccessCb() {
|
||||
debug("Callback after removing alarm from database.");
|
||||
|
||||
// if there is no alarm being set
|
||||
if (!this._currentAlarm) {
|
||||
this._debugCurrentAlarm();
|
||||
return;
|
||||
}
|
||||
|
||||
// check if the alarm to be removed is in the queue
|
||||
let alarmQueue = this._alarmQueue;
|
||||
if (this._currentAlarm.id != json.id) {
|
||||
for (let i = 0; i < alarmQueue.length; i++) {
|
||||
if (alarmQueue[i].id == json.id) {
|
||||
alarmQueue.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this._debugCurrentAlarm();
|
||||
return;
|
||||
}
|
||||
|
||||
// the alarm to be removed is the current alarm
|
||||
// reset the next alarm from queue if any
|
||||
if (alarmQueue.length) {
|
||||
this._currentAlarm = alarmQueue.shift();
|
||||
this._debugCurrentAlarm();
|
||||
return;
|
||||
}
|
||||
|
||||
// no alarm waiting to be set in the queue
|
||||
this._currentAlarm = null;
|
||||
this._debugCurrentAlarm();
|
||||
}.bind(this),
|
||||
function removeErrorCb(aErrorMsg) {
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_onAlarmFired: function _onAlarmFired() {
|
||||
debug("_onAlarmFired()");
|
||||
|
||||
if (this._currentAlarm) {
|
||||
debug("Fire system intent: " + JSON.stringify(this._currentAlarm));
|
||||
// TODO Fire a system message, see bug 755245
|
||||
this._currentAlarm = null;
|
||||
}
|
||||
|
||||
// reset the next alarm from the queue
|
||||
let nowTime = Date.now();
|
||||
let alarmQueue = this._alarmQueue;
|
||||
while (alarmQueue.length > 0) {
|
||||
let nextAlarm = alarmQueue.shift();
|
||||
let nextAlarmTime = this._getAlarmTime(nextAlarm);
|
||||
|
||||
// if the next alarm has been expired, directly
|
||||
// fire system intent for it instead of setting it
|
||||
if (nextAlarmTime <= nowTime) {
|
||||
debug("Fire system intent: " + JSON.stringify(nextAlarm));
|
||||
// TODO Fire a system message, see bug 755245
|
||||
} else {
|
||||
this._currentAlarm = nextAlarm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this._debugCurrentAlarm();
|
||||
},
|
||||
|
||||
_onTimezoneChanged: function _onTimezoneChanged(aTimezoneOffset) {
|
||||
debug("_onTimezoneChanged()");
|
||||
|
||||
this._currentTimezoneOffset = aTimezoneOffset;
|
||||
this._restoreAlarmsFromDb();
|
||||
},
|
||||
|
||||
_restoreAlarmsFromDb: function _restoreAlarmsFromDb() {
|
||||
debug("_restoreAlarmsFromDb()");
|
||||
|
||||
this._db.getAll(
|
||||
function getAllSuccessCb(aAlarms) {
|
||||
debug("Callback after getting alarms from database: " + JSON.stringify(aAlarms));
|
||||
|
||||
// clear any alarms set or queued in the cache
|
||||
let alarmQueue = this._alarmQueue;
|
||||
alarmQueue.length = 0;
|
||||
this._currentAlarm = null;
|
||||
|
||||
// only add the alarm that is valid
|
||||
let nowTime = Date.now();
|
||||
aAlarms.forEach(function addAlarm(aAlarm) {
|
||||
if (this._getAlarmTime(aAlarm) > nowTime)
|
||||
alarmQueue.push(aAlarm);
|
||||
}.bind(this));
|
||||
|
||||
// set the next alarm from queue
|
||||
if (alarmQueue.length) {
|
||||
alarmQueue.sort(this._sortAlarmByTimeStamps.bind(this));
|
||||
this._currentAlarm = alarmQueue.shift();
|
||||
}
|
||||
|
||||
this._debugCurrentAlarm();
|
||||
}.bind(this),
|
||||
function getAllErrorCb(aErrorMsg) {
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
_getAlarmTime: function _getAlarmTime(aAlarm) {
|
||||
let alarmTime = (new Date(aAlarm.date)).getTime();
|
||||
|
||||
// For an alarm specified with "ignoreTimezone",
|
||||
// it must be fired respect to the user's timezone.
|
||||
// Supposing an alarm was set at 7:00pm at Tokyo,
|
||||
// it must be gone off at 7:00pm respect to Paris'
|
||||
// local time when the user is located at Paris.
|
||||
// We can adjust the alarm UTC time by calculating
|
||||
// the difference of the orginal timezone and the
|
||||
// current timezone.
|
||||
if (aAlarm.ignoreTimezone)
|
||||
alarmTime += (this._currentTimezoneOffset - aAlarm.timezoneOffset) * 60000;
|
||||
|
||||
return alarmTime;
|
||||
},
|
||||
|
||||
_sortAlarmByTimeStamps: function _sortAlarmByTimeStamps(aAlarm1, aAlarm2) {
|
||||
return this._getAlarmTime(aAlarm1) - this._getAlarmTime(aAlarm2);
|
||||
},
|
||||
|
||||
_debugCurrentAlarm: function _debugCurrentAlarm() {
|
||||
debug("Current alarm: " + JSON.stringify(this._currentAlarm));
|
||||
debug("Alarm queue: " + JSON.stringify(this._alarmQueue));
|
||||
},
|
||||
}
|
||||
|
||||
AlarmService.init();
|
@ -4,6 +4,14 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
/* static functions */
|
||||
const DEBUG = false;
|
||||
|
||||
function debug(aStr) {
|
||||
if (DEBUG)
|
||||
dump("AlarmsManager: " + aStr + "\n");
|
||||
}
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
@ -17,6 +25,7 @@ const nsIClassInfo = Ci.nsIClassInfo;
|
||||
|
||||
function AlarmsManager()
|
||||
{
|
||||
debug("Constructor");
|
||||
}
|
||||
|
||||
AlarmsManager.prototype = {
|
||||
@ -34,19 +43,90 @@ AlarmsManager.prototype = {
|
||||
flags: nsIClassInfo.DOM_OBJECT }),
|
||||
|
||||
add: function add(aDate, aRespectTimezone, aData) {
|
||||
return null;
|
||||
debug("add()");
|
||||
|
||||
let isIgnoreTimezone = true;
|
||||
switch (aRespectTimezone) {
|
||||
case "honorTimezone":
|
||||
isIgnoreTimezone = false;
|
||||
break;
|
||||
|
||||
case "ignoreTimezone":
|
||||
isIgnoreTimezone = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
|
||||
let request = this.createRequest();
|
||||
this._cpmm.sendAsyncMessage(
|
||||
"AlarmsManager:Add",
|
||||
{ requestID: this.getRequestId(request), date: aDate, ignoreTimezone: isIgnoreTimezone, data: aData }
|
||||
);
|
||||
return request;
|
||||
},
|
||||
|
||||
remove: function remove(aId) {
|
||||
return;
|
||||
debug("remove()");
|
||||
|
||||
return this._cpmm.sendSyncMessage(
|
||||
"AlarmsManager:Remove",
|
||||
{ id: aId }
|
||||
);
|
||||
},
|
||||
|
||||
getAll: function getAll() {
|
||||
return null;
|
||||
debug("getAll()");
|
||||
|
||||
let request = this.createRequest();
|
||||
this._cpmm.sendAsyncMessage(
|
||||
"AlarmsManager:GetAll",
|
||||
{ requestID: this.getRequestId(request) }
|
||||
);
|
||||
return request;
|
||||
},
|
||||
|
||||
receiveMessage: function receiveMessage(aMessage) {
|
||||
debug("receiveMessage(): " + aMessage.name);
|
||||
|
||||
let json = aMessage.json;
|
||||
let request = this.getRequest(json.requestID);
|
||||
|
||||
if (!request) {
|
||||
debug("No request stored! " + json.requestID);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aMessage.name) {
|
||||
case "AlarmsManager:Add:Return:OK":
|
||||
Services.DOMRequest.fireSuccess(request, json.id);
|
||||
break;
|
||||
|
||||
case "AlarmsManager:GetAll:Return:OK":
|
||||
Services.DOMRequest.fireSuccess(request, json.alarms);
|
||||
break;
|
||||
|
||||
case "AlarmsManager:Add:Return:KO":
|
||||
Services.DOMRequest.fireError(request, json.errorMsg);
|
||||
break;
|
||||
|
||||
case "AlarmsManager:GetAll:Return:KO":
|
||||
Services.DOMRequest.fireError(request, json.errorMsg);
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("Wrong message: " + aMessage.name);
|
||||
break;
|
||||
}
|
||||
this.removeRequest(json.requestID);
|
||||
},
|
||||
|
||||
// nsIDOMGlobalPropertyInitializer implementation
|
||||
init: function init(aWindow) {
|
||||
debug("init()");
|
||||
|
||||
// Set navigator.mozAlarms to null.
|
||||
if (!Services.prefs.getBoolPref("dom.mozAlarms.enabled"))
|
||||
return null;
|
||||
@ -63,12 +143,16 @@ AlarmsManager.prototype = {
|
||||
if (!this.hasPrivileges)
|
||||
return null;
|
||||
|
||||
this._cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender);
|
||||
|
||||
// Add the valid messages to be listened.
|
||||
this.initHelper(aWindow, []);
|
||||
this.initHelper(aWindow, ["AlarmsManager:Add:Return:OK", "AlarmsManager:Add:Return:KO",
|
||||
"AlarmsManager:GetAll:Return:OK", "AlarmsManager:GetAll:Return:KO"]);
|
||||
},
|
||||
|
||||
// Called from DOMRequestIpcHelper.
|
||||
uninit: function uninit() {
|
||||
debug("uninit()");
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ EXTRA_COMPONENTS = \
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
AlarmDB.jsm \
|
||||
AlarmService.jsm \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
|
Loading…
Reference in New Issue
Block a user