|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 "use strict"; |
|
6 |
|
7 /* static functions */ |
|
8 const DEBUG = false; |
|
9 |
|
10 function debug(aStr) { |
|
11 if (DEBUG) |
|
12 dump("AlarmsManager: " + aStr + "\n"); |
|
13 } |
|
14 |
|
15 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; |
|
16 |
|
17 Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
18 Cu.import("resource://gre/modules/Services.jsm"); |
|
19 Cu.import("resource://gre/modules/DOMRequestHelper.jsm"); |
|
20 |
|
21 const ALARMSMANAGER_CONTRACTID = "@mozilla.org/alarmsManager;1"; |
|
22 const ALARMSMANAGER_CID = Components.ID("{fea1e884-9b05-11e1-9b64-87a7016c3860}"); |
|
23 const nsIDOMMozAlarmsManager = Ci.nsIDOMMozAlarmsManager; |
|
24 const nsIClassInfo = Ci.nsIClassInfo; |
|
25 |
|
26 function AlarmsManager() |
|
27 { |
|
28 debug("Constructor"); |
|
29 } |
|
30 |
|
31 AlarmsManager.prototype = { |
|
32 |
|
33 __proto__: DOMRequestIpcHelper.prototype, |
|
34 |
|
35 classID : ALARMSMANAGER_CID, |
|
36 |
|
37 QueryInterface : XPCOMUtils.generateQI([nsIDOMMozAlarmsManager, |
|
38 Ci.nsIDOMGlobalPropertyInitializer, |
|
39 Ci.nsISupportsWeakReference, |
|
40 Ci.nsIObserver]), |
|
41 |
|
42 classInfo : XPCOMUtils.generateCI({ classID: ALARMSMANAGER_CID, |
|
43 contractID: ALARMSMANAGER_CONTRACTID, |
|
44 classDescription: "AlarmsManager", |
|
45 interfaces: [nsIDOMMozAlarmsManager], |
|
46 flags: nsIClassInfo.DOM_OBJECT }), |
|
47 |
|
48 add: function add(aDate, aRespectTimezone, aData) { |
|
49 debug("add()"); |
|
50 |
|
51 if (!this._manifestURL) { |
|
52 debug("Cannot add alarms for non-installed apps."); |
|
53 throw Components.results.NS_ERROR_FAILURE; |
|
54 } |
|
55 |
|
56 if (!aDate) { |
|
57 throw Components.results.NS_ERROR_INVALID_ARG; |
|
58 } |
|
59 |
|
60 let isIgnoreTimezone = true; |
|
61 switch (aRespectTimezone) { |
|
62 case "honorTimezone": |
|
63 isIgnoreTimezone = false; |
|
64 break; |
|
65 |
|
66 case "ignoreTimezone": |
|
67 isIgnoreTimezone = true; |
|
68 break; |
|
69 |
|
70 default: |
|
71 throw Components.results.NS_ERROR_INVALID_ARG; |
|
72 break; |
|
73 } |
|
74 |
|
75 // Run JSON.stringify() in the sand box with the principal of the calling |
|
76 // web page to ensure no cross-origin object is involved. A "Permission |
|
77 // Denied" error will be thrown in case of privilege violation. |
|
78 let sandbox = new Cu.Sandbox(this._window.document.nodePrincipal); |
|
79 sandbox.data = aData; |
|
80 let data = Cu.evalInSandbox("JSON.stringify(data)", sandbox); |
|
81 let request = this.createRequest(); |
|
82 this._cpmm.sendAsyncMessage( |
|
83 "AlarmsManager:Add", |
|
84 { requestId: this.getRequestId(request), |
|
85 date: aDate, |
|
86 ignoreTimezone: isIgnoreTimezone, |
|
87 data: JSON.parse(data), |
|
88 pageURL: this._pageURL, |
|
89 manifestURL: this._manifestURL } |
|
90 ); |
|
91 return request; |
|
92 }, |
|
93 |
|
94 remove: function remove(aId) { |
|
95 debug("remove()"); |
|
96 |
|
97 this._cpmm.sendAsyncMessage( |
|
98 "AlarmsManager:Remove", |
|
99 { id: aId, manifestURL: this._manifestURL } |
|
100 ); |
|
101 }, |
|
102 |
|
103 getAll: function getAll() { |
|
104 debug("getAll()"); |
|
105 |
|
106 let request = this.createRequest(); |
|
107 this._cpmm.sendAsyncMessage( |
|
108 "AlarmsManager:GetAll", |
|
109 { requestId: this.getRequestId(request), manifestURL: this._manifestURL } |
|
110 ); |
|
111 return request; |
|
112 }, |
|
113 |
|
114 receiveMessage: function receiveMessage(aMessage) { |
|
115 debug("receiveMessage(): " + aMessage.name); |
|
116 |
|
117 let json = aMessage.json; |
|
118 let request = this.getRequest(json.requestId); |
|
119 |
|
120 if (!request) { |
|
121 debug("No request stored! " + json.requestId); |
|
122 return; |
|
123 } |
|
124 |
|
125 switch (aMessage.name) { |
|
126 case "AlarmsManager:Add:Return:OK": |
|
127 Services.DOMRequest.fireSuccess(request, json.id); |
|
128 break; |
|
129 |
|
130 case "AlarmsManager:GetAll:Return:OK": |
|
131 // We don't need to expose everything to the web content. |
|
132 let alarms = []; |
|
133 json.alarms.forEach(function trimAlarmInfo(aAlarm) { |
|
134 let alarm = { "id": aAlarm.id, |
|
135 "date": aAlarm.date, |
|
136 "respectTimezone": aAlarm.ignoreTimezone ? |
|
137 "ignoreTimezone" : "honorTimezone", |
|
138 "data": aAlarm.data }; |
|
139 alarms.push(alarm); |
|
140 }); |
|
141 Services.DOMRequest.fireSuccess(request, |
|
142 Cu.cloneInto(alarms, this._window)); |
|
143 break; |
|
144 |
|
145 case "AlarmsManager:Add:Return:KO": |
|
146 Services.DOMRequest.fireError(request, json.errorMsg); |
|
147 break; |
|
148 |
|
149 case "AlarmsManager:GetAll:Return:KO": |
|
150 Services.DOMRequest.fireError(request, json.errorMsg); |
|
151 break; |
|
152 |
|
153 default: |
|
154 debug("Wrong message: " + aMessage.name); |
|
155 break; |
|
156 } |
|
157 this.removeRequest(json.requestId); |
|
158 }, |
|
159 |
|
160 // nsIDOMGlobalPropertyInitializer implementation |
|
161 init: function init(aWindow) { |
|
162 debug("init()"); |
|
163 |
|
164 // Set navigator.mozAlarms to null. |
|
165 if (!Services.prefs.getBoolPref("dom.mozAlarms.enabled")) { |
|
166 return null; |
|
167 } |
|
168 |
|
169 // Only pages with perm set can use the alarms. |
|
170 let principal = aWindow.document.nodePrincipal; |
|
171 let perm = |
|
172 Services.perms.testExactPermissionFromPrincipal(principal, "alarms"); |
|
173 if (perm != Ci.nsIPermissionManager.ALLOW_ACTION) { |
|
174 return null; |
|
175 } |
|
176 |
|
177 // SystemPrincipal documents do not have any origin. |
|
178 // Reject them for now. |
|
179 if (!principal.URI) { |
|
180 return null; |
|
181 } |
|
182 |
|
183 this._cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"] |
|
184 .getService(Ci.nsISyncMessageSender); |
|
185 |
|
186 // Add the valid messages to be listened. |
|
187 this.initDOMRequestHelper(aWindow, ["AlarmsManager:Add:Return:OK", |
|
188 "AlarmsManager:Add:Return:KO", |
|
189 "AlarmsManager:GetAll:Return:OK", |
|
190 "AlarmsManager:GetAll:Return:KO"]); |
|
191 |
|
192 // Get the manifest URL if this is an installed app |
|
193 let appsService = Cc["@mozilla.org/AppsService;1"] |
|
194 .getService(Ci.nsIAppsService); |
|
195 this._pageURL = principal.URI.spec; |
|
196 this._manifestURL = appsService.getManifestURLByLocalId(principal.appId); |
|
197 this._window = aWindow; |
|
198 }, |
|
199 |
|
200 // Called from DOMRequestIpcHelper. |
|
201 uninit: function uninit() { |
|
202 debug("uninit()"); |
|
203 }, |
|
204 } |
|
205 |
|
206 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([AlarmsManager]) |