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/. */
5 const Cc = Components.classes;
6 const Ci = Components.interfaces;
7 const Cu = Components.utils;
8 const Cr = Components.results;
10 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
11 Cu.import("resource://gre/modules/Services.jsm");
12 Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
13 Cu.import("resource://gre/modules/AppsUtils.jsm");
14 Cu.import("resource://gre/modules/BrowserElementPromptService.jsm");
15 Cu.import("resource://gre/modules/AppsServiceChild.jsm");
16 Cu.import("resource://gre/modules/Preferences.jsm");
18 XPCOMUtils.defineLazyServiceGetter(this, "appsService",
19 "@mozilla.org/AppsService;1",
22 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
23 "@mozilla.org/childprocessmessagemanager;1",
26 function debug(aMsg) {
27 dump("-*- Webapps.js " + aMsg + "\n");
30 function convertAppsArray(aApps, aWindow) {
31 let apps = new aWindow.Array();
32 aApps.forEach((aApp) => {
33 let obj = createContentApplicationObject(aWindow, aApp);
39 function WebappsRegistry() {
42 WebappsRegistry.prototype = {
43 __proto__: DOMRequestIpcHelper.prototype,
45 receiveMessage: function(aMessage) {
46 let msg = aMessage.json;
48 if (aMessage.name != "Webapps:AdditionalLanguageChange") {
49 if (msg.oid != this._id) {
53 if (aMessage.name == "Webapps:GetAdditionalLanguages:Return" ||
54 aMessage.name == "Webapps:GetLocalizationResource:Return") {
55 req = this.takePromiseResolver(msg.requestID);
57 req = this.getRequest(msg.requestID);
65 switch (aMessage.name) {
66 case "Webapps:Install:Return:OK":
67 this.removeMessageListeners("Webapps:Install:Return:KO");
68 Services.DOMRequest.fireSuccess(req, createContentApplicationObject(this._window, app));
69 cpmm.sendAsyncMessage("Webapps:Install:Return:Ack",
70 { manifestURL : app.manifestURL });
72 case "Webapps:Install:Return:KO":
73 this.removeMessageListeners(aMessage.name);
74 Services.DOMRequest.fireError(req, msg.error || "DENIED");
76 case "Webapps:GetSelf:Return:OK":
77 this.removeMessageListeners(aMessage.name);
78 if (msg.apps.length) {
80 Services.DOMRequest.fireSuccess(req, createContentApplicationObject(this._window, app));
82 Services.DOMRequest.fireSuccess(req, null);
85 case "Webapps:CheckInstalled:Return:OK":
86 this.removeMessageListeners(aMessage.name);
87 Services.DOMRequest.fireSuccess(req, msg.app);
89 case "Webapps:GetInstalled:Return:OK":
90 this.removeMessageListeners(aMessage.name);
91 Services.DOMRequest.fireSuccess(req, convertAppsArray(msg.apps, this._window));
93 case "Webapps:AdditionalLanguageChange":
94 // Check if the current page is from the app receiving the event.
95 let manifestURL = AppsUtils.getAppManifestURLFromWindow(this._window);
96 if (manifestURL && manifestURL == msg.manifestURL) {
97 // Let's dispatch an "additionallanguageschange" event on the document.
98 let doc = this._window.document;
99 let event = doc.createEvent("CustomEvent");
100 event.initCustomEvent("additionallanguageschange", true, true,
101 Cu.cloneInto(msg.languages, this._window));
102 doc.dispatchEvent(event);
105 case "Webapps:GetLocalizationResource:Return":
106 this.removeMessageListeners(["Webapps:GetLocalizationResource:Return"]);
108 req.reject(new this._window.DOMError(msg.error));
110 req.resolve(Cu.cloneInto(msg.data, this._window));
114 this.removeRequest(msg.requestID);
117 _getOrigin: function(aURL) {
118 let uri = Services.io.newURI(aURL, null, null);
122 // Checks that the URL scheme is appropriate (http or https) and
123 // asynchronously fire an error on the DOM Request if it isn't.
124 _validateURL: function(aURL, aRequest) {
129 uri = Services.io.newURI(aURL, null, null);
130 if (uri.schemeIs("http") || uri.schemeIs("https")) {
134 Services.DOMRequest.fireErrorAsync(aRequest, "INVALID_URL");
138 // The scheme is incorrect, fire DOMRequest error.
140 Services.DOMRequest.fireErrorAsync(aRequest, "INVALID_URL");
147 // Checks that we run as a foreground page, and fire an error on the
148 // DOM Request if we aren't.
149 _ensureForeground: function(aRequest) {
150 let docShell = this._window.QueryInterface(Ci.nsIInterfaceRequestor)
151 .getInterface(Ci.nsIWebNavigation)
152 .QueryInterface(Ci.nsIDocShell);
153 if (docShell.isActive) {
157 Services.DOMRequest.fireErrorAsync(aRequest, "BACKGROUND_APP");
161 _prepareInstall: function(aURL, aRequest, aParams, isPackage) {
162 let installURL = this._window.location.href;
163 let requestID = this.getRequestId(aRequest);
164 let receipts = (aParams && aParams.receipts &&
165 Array.isArray(aParams.receipts)) ? aParams.receipts
167 let categories = (aParams && aParams.categories &&
168 Array.isArray(aParams.categories)) ? aParams.categories
171 let principal = this._window.document.nodePrincipal;
174 installOrigin: this._getOrigin(installURL),
175 origin: this._getOrigin(aURL),
178 categories: categories
183 requestID: requestID,
184 appId: principal.appId,
185 isBrowser: principal.isInBrowserElement,
190 // mozIDOMApplicationRegistry implementation
192 install: function(aURL, aParams) {
193 let request = this.createRequest();
195 let uri = this._validateURL(aURL, request);
197 if (uri && this._ensureForeground(request)) {
198 this.addMessageListeners("Webapps:Install:Return:KO");
199 cpmm.sendAsyncMessage("Webapps:Install",
200 this._prepareInstall(uri, request, aParams, false));
206 getSelf: function() {
207 let request = this.createRequest();
208 this.addMessageListeners("Webapps:GetSelf:Return:OK");
209 cpmm.sendAsyncMessage("Webapps:GetSelf", { origin: this._getOrigin(this._window.location.href),
210 appId: this._window.document.nodePrincipal.appId,
212 requestID: this.getRequestId(request) });
216 checkInstalled: function(aManifestURL) {
217 let manifestURL = Services.io.newURI(aManifestURL, null, this._window.document.baseURIObject);
219 let request = this.createRequest();
222 this._window.document.nodePrincipal.checkMayLoad(manifestURL, true,
225 Services.DOMRequest.fireErrorAsync(request, "CROSS_ORIGIN_CHECK_NOT_ALLOWED");
229 this.addMessageListeners("Webapps:CheckInstalled:Return:OK");
230 cpmm.sendAsyncMessage("Webapps:CheckInstalled", { origin: this._getOrigin(this._window.location.href),
231 manifestURL: manifestURL.spec,
233 requestID: this.getRequestId(request) });
237 getInstalled: function() {
238 let request = this.createRequest();
239 this.addMessageListeners("Webapps:GetInstalled:Return:OK");
240 cpmm.sendAsyncMessage("Webapps:GetInstalled", { origin: this._getOrigin(this._window.location.href),
242 requestID: this.getRequestId(request) });
247 if (!this.hasMgmtPrivilege) {
252 let mgmt = Cc["@mozilla.org/webapps/manager;1"]
253 .createInstance(Ci.nsISupports);
254 mgmt.wrappedJSObject.init(this._window, this.hasFullMgmtPrivilege);
255 mgmt.wrappedJSObject._windowId = this._id;
256 this._mgmt = mgmt.__DOM_IMPL__
258 : this._window.DOMApplicationsManager._create(this._window, mgmt.wrappedJSObject);
265 cpmm.sendAsyncMessage("Webapps:UnregisterForMessages",
266 ["Webapps:Install:Return:OK",
267 "Webapps:AdditionalLanguageChange"]);
270 installPackage: function(aURL, aParams) {
271 let request = this.createRequest();
273 let uri = this._validateURL(aURL, request);
275 if (uri && this._ensureForeground(request)) {
276 this.addMessageListeners("Webapps:Install:Return:KO");
277 cpmm.sendAsyncMessage("Webapps:InstallPackage",
278 this._prepareInstall(uri, request, aParams, true));
284 _getCurrentAppManifestURL: function() {
285 let appId = this._window.document.nodePrincipal.appId;
286 if (appId === Ci.nsIScriptSecurityManager.NO_APP_ID) {
290 return appsService.getManifestURLByLocalId(appId);
293 getAdditionalLanguages: function() {
294 let manifestURL = AppsUtils.getAppManifestURLFromWindow(this._window);
296 return new this._window.Promise((aResolve, aReject) => {
300 let langs = DOMApplicationRegistry.getAdditionalLanguages(manifestURL);
301 aResolve(Cu.cloneInto(langs, this._window));
306 getLocalizationResource: function(aLanguage, aVersion, aPath, aType) {
307 let manifestURL = AppsUtils.getAppManifestURLFromWindow(this._window);
310 return new Promise((aResolve, aReject) => {
315 this.addMessageListeners(["Webapps:GetLocalizationResource:Return"]);
316 return this.createPromise((aResolve, aReject) => {
317 cpmm.sendAsyncMessage("Webapps:GetLocalizationResource", {
318 manifestURL: manifestURL,
324 requestID: this.getPromiseResolverId({
332 // nsIDOMGlobalPropertyInitializer implementation
333 init: function(aWindow) {
334 const prefs = new Preferences();
336 this._window = aWindow;
338 this.initDOMRequestHelper(aWindow, ["Webapps:Install:Return:OK",
339 "Webapps:AdditionalLanguageChange"]);
341 let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor)
342 .getInterface(Ci.nsIDOMWindowUtils);
343 this._id = util.outerWindowID;
344 cpmm.sendAsyncMessage("Webapps:RegisterForMessages",
345 { messages: ["Webapps:Install:Return:OK",
346 "Webapps:AdditionalLanguageChange"]});
348 let principal = aWindow.document.nodePrincipal;
349 let appId = principal.appId;
350 let app = appId && appsService.getAppByLocalId(appId);
352 let isCurrentHomescreen = app &&
353 app.manifestURL == prefs.get("dom.mozApps.homescreenURL") &&
354 app.appStatus != Ci.nsIPrincipal.APP_STATUS_NOT_INSTALLED;
356 let hasWebappsPermission = Ci.nsIPermissionManager.ALLOW_ACTION ==
357 Services.perms.testExactPermissionFromPrincipal(
358 principal, "webapps-manage");
360 let hasHomescreenPermission = Ci.nsIPermissionManager.ALLOW_ACTION ==
361 Services.perms.testExactPermissionFromPrincipal(
362 principal, "homescreen-webapps-manage");
364 this.hasMgmtPrivilege = hasWebappsPermission ||
365 (isCurrentHomescreen && hasHomescreenPermission);
366 this.hasFullMgmtPrivilege = hasWebappsPermission;
369 classID: Components.ID("{fff440b3-fae2-45c1-bf03-3b5a2e432270}"),
371 QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference,
374 Ci.nsIDOMGlobalPropertyInitializer])
378 * DOMApplication object
381 function createApplicationObject(aWindow, aApp) {
382 let app = Cc["@mozilla.org/webapps/application;1"]
383 .createInstance(Ci.nsISupports);
384 app.wrappedJSObject.init(aWindow, aApp);
388 function createContentApplicationObject(aWindow, aApp) {
389 return createApplicationObject(aWindow, aApp).wrappedJSObject
390 ._prepareForContent();
393 function WebappsApplication() {
394 this.wrappedJSObject = this;
397 WebappsApplication.prototype = {
398 __proto__: DOMRequestIpcHelper.prototype,
400 init: function(aWindow, aApp) {
401 this._window = aWindow;
403 let proxyHandler = DOMApplicationRegistry.addDOMApp(this,
406 this._proxy = new Proxy(this, proxyHandler);
408 this.initDOMRequestHelper(aWindow);
412 return this._proxy.appStatus;
415 get downloadAvailable() {
416 return this._proxy.downloadAvailable;
420 return this._proxy.downloading;
424 return this._proxy.downloadSize;
427 get installOrigin() {
428 return this._proxy.installOrigin;
432 return this._proxy.installState;
436 return this._proxy.installTime;
439 get lastUpdateCheck() {
440 return this._proxy.lastUpdateCheck;
444 return this._proxy.manifestURL;
448 return this._proxy.origin;
452 return this._proxy.progress;
455 get readyToApplyDownload() {
456 return this._proxy.readyToApplyDownload;
460 return this._proxy.removable;
464 return this._proxy.updateTime;
468 return WrappedManifestCache.get(this.manifestURL,
469 this._proxy.manifest,
474 get updateManifest() {
475 return this._proxy.updateManifest ?
476 Cu.cloneInto(this._proxy.updateManifest, this._window) : null;
479 set onprogress(aCallback) {
480 this.__DOM_IMPL__.setEventHandler("onprogress", aCallback);
484 return this.__DOM_IMPL__.getEventHandler("onprogress");
487 set ondownloadsuccess(aCallback) {
488 this.__DOM_IMPL__.setEventHandler("ondownloadsuccess", aCallback);
491 get ondownloadsuccess() {
492 return this.__DOM_IMPL__.getEventHandler("ondownloadsuccess");
495 set ondownloaderror(aCallback) {
496 this.__DOM_IMPL__.setEventHandler("ondownloaderror", aCallback);
499 get ondownloaderror() {
500 return this.__DOM_IMPL__.getEventHandler("ondownloaderror");
503 set ondownloadavailable(aCallback) {
504 this.__DOM_IMPL__.setEventHandler("ondownloadavailable", aCallback);
507 get ondownloadavailable() {
508 return this.__DOM_IMPL__.getEventHandler("ondownloadavailable");
511 set ondownloadapplied(aCallback) {
512 this.__DOM_IMPL__.setEventHandler("ondownloadapplied", aCallback);
515 get ondownloadapplied() {
516 return this.__DOM_IMPL__.getEventHandler("ondownloadapplied");
520 return this._proxy.receipts || [];
523 get downloadError() {
524 // Only return DOMError when we have an error.
525 if (!this._proxy.downloadError) {
528 return new this._window.DOMError(this._proxy.downloadError);
532 return this._proxy.enabled;
535 download: function() {
536 cpmm.sendAsyncMessage("Webapps:Download",
537 { manifestURL: this.manifestURL });
540 cancelDownload: function() {
541 cpmm.sendAsyncMessage("Webapps:CancelDownload",
542 { manifestURL: this.manifestURL });
545 checkForUpdate: function() {
546 let request = this.createRequest();
548 cpmm.sendAsyncMessage("Webapps:CheckForUpdate",
549 { manifestURL: this.manifestURL,
551 requestID: this.getRequestId(request) });
555 launch: function(aStartPoint) {
556 let request = this.createRequest();
557 this.addMessageListeners(["Webapps:Launch:Return:OK",
558 "Webapps:Launch:Return:KO"]);
559 cpmm.sendAsyncMessage("Webapps:Launch", { origin: this.origin,
560 manifestURL: this.manifestURL,
561 startPoint: aStartPoint || "",
563 timestamp: Date.now(),
564 requestID: this.getRequestId(request) });
568 clearBrowserData: function() {
569 let request = this.createRequest();
571 BrowserElementPromptService.getBrowserElementChildForWindow(this._window);
573 this.addMessageListeners("Webapps:ClearBrowserData:Return");
574 browserChild.messageManager.sendAsyncMessage("Webapps:ClearBrowserData", {
575 manifestURL: this.manifestURL,
577 requestID: this.getRequestId(request)
580 Services.DOMRequest.fireErrorAsync(request, "NO_CLEARABLE_BROWSER");
585 connect: function(aKeyword, aRules) {
586 this.addMessageListeners(["Webapps:Connect:Return:OK",
587 "Webapps:Connect:Return:KO"]);
588 return this.createPromise(function (aResolve, aReject) {
589 cpmm.sendAsyncMessage("Webapps:Connect", {
592 manifestURL: this.manifestURL,
593 outerWindowID: this._id,
594 requestID: this.getPromiseResolverId({
602 getConnections: function() {
603 this.addMessageListeners("Webapps:GetConnections:Return:OK");
604 return this.createPromise(function (aResolve, aReject) {
605 cpmm.sendAsyncMessage("Webapps:GetConnections", {
606 manifestURL: this.manifestURL,
607 outerWindowID: this._id,
608 requestID: this.getPromiseResolverId({
616 addReceipt: function(receipt) {
617 let request = this.createRequest();
619 this.addMessageListeners(["Webapps:AddReceipt:Return:OK",
620 "Webapps:AddReceipt:Return:KO"]);
622 cpmm.sendAsyncMessage("Webapps:AddReceipt", { manifestURL: this.manifestURL,
625 requestID: this.getRequestId(request) });
630 removeReceipt: function(receipt) {
631 let request = this.createRequest();
633 this.addMessageListeners(["Webapps:RemoveReceipt:Return:OK",
634 "Webapps:RemoveReceipt:Return:KO"]);
636 cpmm.sendAsyncMessage("Webapps:RemoveReceipt", { manifestURL: this.manifestURL,
639 requestID: this.getRequestId(request) });
644 replaceReceipt: function(oldReceipt, newReceipt) {
645 let request = this.createRequest();
647 this.addMessageListeners(["Webapps:ReplaceReceipt:Return:OK",
648 "Webapps:ReplaceReceipt:Return:KO"]);
650 cpmm.sendAsyncMessage("Webapps:ReplaceReceipt", { manifestURL: this.manifestURL,
651 newReceipt: newReceipt,
652 oldReceipt: oldReceipt,
654 requestID: this.getRequestId(request) });
660 this.addMessageListeners(["Webapps:Export:Return"]);
661 return this.createPromise((aResolve, aReject) => {
662 cpmm.sendAsyncMessage("Webapps:Export",
663 { manifestURL: this.manifestURL,
665 requestID: this.getPromiseResolverId({
673 getLocalizedValue: function(aProperty, aLang, aEntryPoint) {
674 this.addMessageListeners(["Webapps:GetLocalizedValue:Return"]);
675 return this.createPromise((aResolve, aReject) => {
676 cpmm.sendAsyncMessage("Webapps:GetLocalizedValue",
677 { manifestURL: this.manifestURL,
682 entryPoint: aEntryPoint,
683 requestID: this.getPromiseResolverId({
691 _prepareForContent: function() {
692 if (this.__DOM_IMPL__) {
693 return this.__DOM_IMPL__;
695 return this._window.DOMApplication._create(this._window, this.wrappedJSObject);
699 WrappedManifestCache.evict(this.manifestURL, this.innerWindowID);
702 _fireEvent: function(aName) {
703 let obj = this._prepareForContent();
704 let event = new this._window.MozApplicationEvent(aName, {
707 obj.dispatchEvent(event);
710 _fireRequestResult: function(aMessage, aIsError) {
712 let msg = aMessage.data;
713 req = this.takeRequest(msg.requestID);
718 aIsError ? Services.DOMRequest.fireError(req, msg.error)
719 : Services.DOMRequest.fireSuccess(req, msg.result);
722 receiveMessage: function(aMessage) {
723 let msg = aMessage.json;
725 if (aMessage.name == "Webapps:Connect:Return:OK" ||
726 aMessage.name == "Webapps:Connect:Return:KO" ||
727 aMessage.name == "Webapps:GetConnections:Return:OK" ||
728 aMessage.name == "Webapps:Export:Return" ||
729 aMessage.name == "Webapps:GetLocalizedValue:Return") {
730 req = this.takePromiseResolver(msg.requestID);
732 req = this.takeRequest(msg.requestID);
735 if (msg.oid !== this._id || !req) {
739 switch (aMessage.name) {
740 case "Webapps:Launch:Return:KO":
741 this.removeMessageListeners(["Webapps:Launch:Return:OK",
742 "Webapps:Launch:Return:KO"]);
743 Services.DOMRequest.fireError(req, msg.error);
745 case "Webapps:Launch:Return:OK":
746 this.removeMessageListeners(["Webapps:Launch:Return:OK",
747 "Webapps:Launch:Return:KO"]);
748 Services.DOMRequest.fireSuccess(req, null);
750 case "Webapps:ClearBrowserData:Return":
751 this.removeMessageListeners(aMessage.name);
752 Services.DOMRequest.fireSuccess(req, null);
754 case "Webapps:Connect:Return:OK":
755 this.removeMessageListeners(["Webapps:Connect:Return:OK",
756 "Webapps:Connect:Return:KO"]);
757 let messagePorts = new this._window.Array();
758 msg.messagePortIDs.forEach((aPortID) => {
759 let port = new this._window.MozInterAppMessagePort(aPortID);
760 messagePorts.push(port);
762 req.resolve(messagePorts);
764 case "Webapps:Connect:Return:KO":
765 this.removeMessageListeners(["Webapps:Connect:Return:OK",
766 "Webapps:Connect:Return:KO"]);
767 req.reject("No connections registered");
769 case "Webapps:GetConnections:Return:OK":
770 this.removeMessageListeners(aMessage.name);
771 let connections = new this._window.Array();
772 msg.connections.forEach((aConnection) => {
774 new this._window.MozInterAppConnection(aConnection.keyword,
775 aConnection.pubAppManifestURL,
776 aConnection.subAppManifestURL);
777 connections.push(connection);
779 req.resolve(connections);
781 case "Webapps:AddReceipt:Return:OK":
782 this.removeMessageListeners(["Webapps:AddReceipt:Return:OK",
783 "Webapps:AddReceipt:Return:KO"]);
784 this.__DOM_IMPL__._clearCachedReceiptsValue();
785 this._proxy.receipts = msg.receipts;
786 Services.DOMRequest.fireSuccess(req, null);
788 case "Webapps:AddReceipt:Return:KO":
789 this.removeMessageListeners(["Webapps:AddReceipt:Return:OK",
790 "Webapps:AddReceipt:Return:KO"]);
791 Services.DOMRequest.fireError(req, msg.error);
793 case "Webapps:RemoveReceipt:Return:OK":
794 this.removeMessageListeners(["Webapps:RemoveReceipt:Return:OK",
795 "Webapps:RemoveReceipt:Return:KO"]);
796 this.__DOM_IMPL__._clearCachedReceiptsValue();
797 this._proxy.receipts = msg.receipts;
798 Services.DOMRequest.fireSuccess(req, null);
800 case "Webapps:RemoveReceipt:Return:KO":
801 this.removeMessageListeners(["Webapps:RemoveReceipt:Return:OK",
802 "Webapps:RemoveReceipt:Return:KO"]);
803 Services.DOMRequest.fireError(req, msg.error);
805 case "Webapps:ReplaceReceipt:Return:OK":
806 this.removeMessageListeners(["Webapps:ReplaceReceipt:Return:OK",
807 "Webapps:ReplaceReceipt:Return:KO"]);
808 this.__DOM_IMPL__._clearCachedReceiptsValue();
809 this._proxy.receipts = msg.receipts;
810 Services.DOMRequest.fireSuccess(req, null);
812 case "Webapps:ReplaceReceipt:Return:KO":
813 this.removeMessageListeners(["Webapps:ReplaceReceipt:Return:OK",
814 "Webapps:ReplaceReceipt:Return:KO"]);
815 Services.DOMRequest.fireError(req, msg.error);
817 case "Webapps:Export:Return":
818 this.removeMessageListeners(["Webapps:Export:Return"]);
820 req.resolve(Cu.cloneInto(msg.blob, this._window));
822 req.reject(new this._window.DOMError(msg.error || ""));
825 case "Webapps:GetLocalizedValue:Return":
826 this.removeMessageListeners(["Webapps:GetLocalizedValue:Return"]);
828 req.resolve(msg.value);
830 req.reject(new this._window.DOMError(msg.error || ""));
836 classID: Components.ID("{723ed303-7757-4fb0-b261-4f78b1f6bd22}"),
838 QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
840 Ci.nsISupportsWeakReference])
844 * DOMApplicationsManager object
846 function WebappsApplicationMgmt() {
847 this.wrappedJSObject = this;
850 WebappsApplicationMgmt.prototype = {
851 __proto__: DOMRequestIpcHelper.prototype,
853 init: function(aWindow, aHasFullMgmtPrivilege) {
854 this._window = aWindow;
856 this.initDOMRequestHelper(aWindow, ["Webapps:Uninstall:Return:OK",
857 "Webapps:Uninstall:Broadcast:Return:OK",
858 "Webapps:Uninstall:Return:KO",
859 "Webapps:Install:Return:OK",
860 "Webapps:GetNotInstalled:Return:OK",
861 "Webapps:Import:Return",
862 "Webapps:ExtractManifest:Return",
863 "Webapps:SetEnabled:Return"]);
864 cpmm.sendAsyncMessage("Webapps:RegisterForMessages",
866 messages: ["Webapps:Install:Return:OK",
867 "Webapps:Uninstall:Return:OK",
868 "Webapps:Uninstall:Broadcast:Return:OK",
869 "Webapps:SetEnabled:Return"]
873 if (!aHasFullMgmtPrivilege) {
874 this.getNotInstalled = null;
875 this.applyDownload = null;
880 cpmm.sendAsyncMessage("Webapps:UnregisterForMessages",
881 ["Webapps:Install:Return:OK",
882 "Webapps:Uninstall:Return:OK",
883 "Webapps:Uninstall:Broadcast:Return:OK",
884 "Webapps:SetEnabled:Return"]);
887 applyDownload: function(aApp) {
888 if (!aApp.readyToApplyDownload) {
892 let principal = this._window.document.nodePrincipal;
894 cpmm.sendAsyncMessage("Webapps:ApplyDownload",
895 { manifestURL: aApp.manifestURL },
899 uninstall: function(aApp) {
900 let request = this.createRequest();
901 let principal = this._window.document.nodePrincipal;
903 cpmm.sendAsyncMessage("Webapps:Uninstall", {
905 manifestURL: aApp.manifestURL,
907 from: this._window.location.href,
908 windowId: this._windowId,
909 requestID: this.getRequestId(request)
916 let request = this.createRequest();
917 let window = this._window;
918 DOMApplicationRegistry.getAll((aApps) => {
919 Services.DOMRequest.fireSuccessAsync(request,
920 convertAppsArray(aApps, window));
926 getNotInstalled: function() {
927 let request = this.createRequest();
928 let principal = this._window.document.nodePrincipal;
930 cpmm.sendAsyncMessage("Webapps:GetNotInstalled", {
932 requestID: this.getRequestId(request)
938 import: function(aBlob) {
939 let principal = this._window.document.nodePrincipal;
940 return this.createPromise((aResolve, aReject) => {
941 cpmm.sendAsyncMessage("Webapps:Import",
944 requestID: this.getPromiseResolverId({
947 })}, null, principal);
951 extractManifest: function(aBlob) {
952 let principal = this._window.document.nodePrincipal;
953 return this.createPromise((aResolve, aReject) => {
954 cpmm.sendAsyncMessage("Webapps:ExtractManifest",
957 requestID: this.getPromiseResolverId({
960 })}, null, principal);
964 setEnabled: function(aApp, aValue) {
965 let principal = this._window.document.nodePrincipal;
967 cpmm.sendAsyncMessage("Webapps:SetEnabled",
968 { manifestURL: aApp.manifestURL,
969 enabled: aValue }, null, principal);
973 return this.__DOM_IMPL__.getEventHandler("oninstall");
977 return this.__DOM_IMPL__.getEventHandler("onuninstall");
980 get onenabledstatechange() {
981 return this.__DOM_IMPL__.getEventHandler("onenabledstatechange");
984 set oninstall(aCallback) {
985 this.__DOM_IMPL__.setEventHandler("oninstall", aCallback);
988 set onuninstall(aCallback) {
989 this.__DOM_IMPL__.setEventHandler("onuninstall", aCallback);
992 set onenabledstatechange(aCallback) {
993 this.__DOM_IMPL__.setEventHandler("onenabledstatechange", aCallback);
996 receiveMessage: function(aMessage) {
997 let msg = aMessage.data;
1000 if (["Webapps:Import:Return",
1001 "Webapps:ExtractManifest:Return"]
1002 .indexOf(aMessage.name) != -1) {
1003 req = this.takePromiseResolver(msg.requestID);
1005 req = this.getRequest(msg.requestID);
1008 // We want Webapps:Install:Return:OK, Webapps:Uninstall:Broadcast:Return:OK
1009 // and Webapps:SetEnabled:Return
1010 // to be broadcasted to all instances of mozApps.mgmt.
1011 if (!((msg.oid == this._id && req) ||
1012 aMessage.name == "Webapps:Install:Return:OK" ||
1013 aMessage.name == "Webapps:Uninstall:Broadcast:Return:OK" ||
1014 aMessage.name == "Webapps:SetEnabled:Return")) {
1018 switch (aMessage.name) {
1019 case "Webapps:GetNotInstalled:Return:OK":
1020 Services.DOMRequest.fireSuccess(req, convertAppsArray(msg.apps, this._window));
1022 case "Webapps:Install:Return:OK":
1024 let app = createContentApplicationObject(this._window, msg.app);
1026 new this._window.MozApplicationEvent("install", { application: app });
1027 this.__DOM_IMPL__.dispatchEvent(event);
1030 case "Webapps:Uninstall:Broadcast:Return:OK":
1032 let app = createContentApplicationObject(this._window, msg);
1034 new this._window.MozApplicationEvent("uninstall", { application : app });
1035 this.__DOM_IMPL__.dispatchEvent(event);
1038 case "Webapps:Uninstall:Return:OK":
1039 Services.DOMRequest.fireSuccess(req, msg.manifestURL);
1041 case "Webapps:Uninstall:Return:KO":
1042 Services.DOMRequest.fireError(req, "NOT_INSTALLED");
1044 case "Webapps:Import:Return":
1046 req.resolve(createContentApplicationObject(this._window, msg.app));
1048 req.reject(new this._window.DOMError(msg.error || ""));
1051 case "Webapps:ExtractManifest:Return":
1053 req.resolve(Cu.cloneInto(msg.manifest, this._window));
1055 req.reject(new this._window.DOMError(msg.error || ""));
1058 case "Webapps:SetEnabled:Return":
1060 let app = createContentApplicationObject(this._window, msg);
1062 new this._window.MozApplicationEvent("enabledstatechange", { application : app });
1063 this.__DOM_IMPL__.dispatchEvent(event);
1067 if (aMessage.name !== "Webapps:Uninstall:Broadcast:Return:OK") {
1068 this.removeRequest(msg.requestID);
1072 classID: Components.ID("{8c1bca96-266f-493a-8d57-ec7a95098c15}"),
1074 QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
1076 Ci.nsISupportsWeakReference])
1079 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WebappsRegistry,
1080 WebappsApplicationMgmt,
1081 WebappsApplication]);