From 6c5bfd7cca30eff4d9167b10e4b0b9a596656e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabrice=20Desr=C3=A9?= Date: Fri, 14 Aug 2015 16:55:09 -0700 Subject: [PATCH] Bug 1190995 - Support the new extension model in b2g r=billm --- b2g/app/b2g.js | 1 - b2g/components/ProcessGlobal.js | 4 +- b2g/installer/package-manifest.in | 3 + dom/apps/UserCustomizations.jsm | 330 +----------------- dom/apps/Webapps.jsm | 19 +- dom/apps/tests/addons/application.zip | Bin 1725 -> 1967 bytes dom/apps/tests/addons/index.html | 8 +- dom/apps/tests/addons/manifest.json | 12 + dom/apps/tests/addons/manifest.webapp | 7 - dom/apps/tests/addons/script.js | 9 +- dom/apps/tests/addons/script2.js | 10 +- .../BrowserElementChildPreload.js | 1 - dom/browser-element/BrowserElementParent.js | 2 + dom/ipc/extensions.js | 15 + dom/ipc/jar.mn | 1 + dom/ipc/preload.js | 5 - .../res/SubstitutingProtocolHandler.cpp | 3 +- toolkit/components/extensions/Extension.jsm | 4 +- .../extensions/ExtensionContent.jsm | 20 +- .../extensions/ExtensionManagement.jsm | 5 +- .../extensions/ExtensionStorage.jsm | 4 +- .../components/extensions/ExtensionUtils.jsm | 5 +- toolkit/components/extensions/ext-alarms.js | 2 + .../extensions/ext-notifications.js | 2 + toolkit/components/extensions/ext-runtime.js | 2 + toolkit/components/extensions/ext-storage.js | 2 + .../extensions/ext-webNavigation.js | 4 + .../components/extensions/ext-webRequest.js | 4 + toolkit/modules/addons/MatchPattern.jsm | 8 +- 29 files changed, 124 insertions(+), 368 deletions(-) create mode 100644 dom/apps/tests/addons/manifest.json create mode 100644 dom/ipc/extensions.js diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index 02e25fece8b..d7f064aafd6 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -1174,4 +1174,3 @@ pref("dom.presentation.device.name", "Firefox OS"); // Enable notification of performance timing pref("dom.performance.enable_notify_performance_timing", true); - diff --git a/b2g/components/ProcessGlobal.js b/b2g/components/ProcessGlobal.js index 4a7716e49a9..94326ad5049 100644 --- a/b2g/components/ProcessGlobal.js +++ b/b2g/components/ProcessGlobal.js @@ -165,9 +165,7 @@ ProcessGlobal.prototype = { .getService(Ci.nsIXULRuntime) .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; if (inParent) { - let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"] - .getService(Ci.nsIMessageListenerManager); - ppmm.addMessageListener("getProfD", function(message) { + Services.ppmm.addMessageListener("getProfD", function(message) { return Services.dirsvc.get("ProfD", Ci.nsIFile).path; }); diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index 4220342e30c..4ffdd98b006 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -1006,3 +1006,6 @@ bin/libfreebl_32int64_3.so #ifdef PKG_LOCALE_MANIFEST #include @PKG_LOCALE_MANIFEST@ #endif + +@RESPATH@/components/simpleServices.js +@RESPATH@/components/utils.manifest diff --git a/dom/apps/UserCustomizations.jsm b/dom/apps/UserCustomizations.jsm index aafa7223f4c..b1d17873181 100644 --- a/dom/apps/UserCustomizations.jsm +++ b/dom/apps/UserCustomizations.jsm @@ -12,38 +12,18 @@ this.EXPORTED_SYMBOLS = ["UserCustomizations"]; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/AppsUtils.jsm"); +Cu.import("resource://gre/modules/Extension.jsm"); -XPCOMUtils.defineLazyServiceGetter(this, "ppmm", - "@mozilla.org/parentprocessmessagemanager;1", - "nsIMessageBroadcaster"); - -XPCOMUtils.defineLazyServiceGetter(this, "cpmm", - "@mozilla.org/childprocessmessagemanager;1", - "nsIMessageSender"); XPCOMUtils.defineLazyServiceGetter(this, "console", "@mozilla.org/consoleservice;1", "nsIConsoleService"); -/** - * Customization scripts and CSS stylesheets can be specified in an - * application manifest with the following syntax: - * "customizations": [ - * { - * "filter": "http://youtube.com", - * "css": ["file1.css", "file2.css"], - * "scripts": ["script1.js", "script2.js"] - * } - * ] - */ function debug(aMsg) { if (!UserCustomizations._debug) { return; } - dump("-*-*- UserCustomizations (" + - (UserCustomizations._inParent ? "parent" : "child") + - "): " + aMsg + "\n"); + dump("-*-*- UserCustomizations " + aMsg + "\n"); } function log(aStr) { @@ -51,267 +31,36 @@ function log(aStr) { } this.UserCustomizations = { - _debug: false, - _items: [], - _loaded : {}, // Keep track per manifestURL of css and scripts loaded. - _windows: null, // Set of currently opened windows. - _enabled: false, - - _addItem: function(aItem) { - debug("_addItem: " + uneval(aItem)); - this._items.push(aItem); - if (this._inParent) { - ppmm.broadcastAsyncMessage("UserCustomizations:Add", [aItem]); - } - }, - - _removeItem: function(aHash) { - debug("_removeItem: " + aHash); - let index = -1; - this._items.forEach((script, pos) => { - if (script.hash == aHash ) { - index = pos; - } - }); - - if (index != -1) { - this._items.splice(index, 1); - } - - if (this._inParent) { - ppmm.broadcastAsyncMessage("UserCustomizations:Remove", aHash); - } - }, - - register: function(aManifest, aApp) { - debug("Starting customization registration for " + aApp.manifestURL); + extensions: new Map(), // id -> extension. Needed to disable extensions. + register: function(aApp) { if (!this._enabled || !aApp.enabled || aApp.role != "addon") { debug("Rejecting registration (global enabled=" + this._enabled + ") (app role=" + aApp.role + ", enabled=" + aApp.enabled + ")"); - debug(uneval(aApp)); return; } - let customizations = aManifest.customizations; - if (customizations === undefined || !Array.isArray(customizations)) { - return; - } + debug("Starting customization registration for " + aApp.manifestURL + "\n"); - let base = Services.io.newURI(aApp.origin, null, null); - - customizations.forEach(item => { - // The filter property is mandatory. - if (!item.filter || (typeof item.filter !== "string")) { - log("Mandatory filter property not found in this customization item: " + - uneval(item) + " in " + aApp.manifestURL); - return; - } - - // Create a new object with resolved urls and a hash that we reuse to - // remove items. - let custom = { - filter: item.filter, - status: aApp.appStatus, - manifestURL: aApp.manifestURL, - css: [], - scripts: [] - }; - custom.hash = AppsUtils.computeObjectHash(item); - - if (item.css && Array.isArray(item.css)) { - item.css.forEach((css) => { - custom.css.push(base.resolve(css)); - }); - } - - if (item.scripts && Array.isArray(item.scripts)) { - item.scripts.forEach((script) => { - custom.scripts.push(base.resolve(script)); - }); - } - - this._addItem(custom); + let extension = new Extension({ + id: aApp.manifestURL, + resourceURI: Services.io.newURI(aApp.origin + "/", null, null) }); - this._updateAllWindows(); + + this.extensions.set(aApp.manifestURL, extension); + extension.startup(); }, - _updateAllWindows: function() { - debug("UpdateWindows"); - if (this._inParent) { - ppmm.broadcastAsyncMessage("UserCustomizations:UpdateWindows", {}); - } - // Inject in all currently opened windows. - this._windows.forEach(this._injectInWindow.bind(this)); - }, - - unregister: function(aManifest, aApp) { + unregister: function(aApp) { if (!this._enabled) { return; } debug("Starting customization unregistration for " + aApp.manifestURL); - let customizations = aManifest.customizations; - if (customizations === undefined || !Array.isArray(customizations)) { - return; - } - - customizations.forEach(item => { - this._removeItem(AppsUtils.computeObjectHash(item)); - }); - this._unloadForManifestURL(aApp.manifestURL); - }, - - _unloadForManifestURL: function(aManifestURL) { - debug("_unloadForManifestURL " + aManifestURL); - - if (this._inParent) { - ppmm.broadcastAsyncMessage("UserCustomizations:Unload", aManifestURL); - } - - if (!this._loaded[aManifestURL]) { - return; - } - - if (this._loaded[aManifestURL].scripts && - this._loaded[aManifestURL].scripts.length > 0) { - // We can't rollback script changes, so don't even try to unload in this - // situation. - return; - } - - this._loaded[aManifestURL].css.forEach(aItem => { - try { - debug("unloading " + aItem.uri.spec); - let utils = aItem.window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - utils.removeSheet(aItem.uri, Ci.nsIDOMWindowUtils.AUTHOR_SHEET); - } catch(e) { - log("Error unloading stylesheet " + aItem.uri.spec + " : " + e); - } - }); - - this._loaded[aManifestURL] = null; - }, - - _injectItem: function(aWindow, aItem, aInjected) { - debug("Injecting item " + uneval(aItem) + " in " + aWindow.location.href); - let utils = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - - let manifestURL = aItem.manifestURL; - - // Load the stylesheets only in this window. - aItem.css.forEach(aCss => { - if (aInjected.indexOf(aCss) !== -1) { - debug("Skipping duplicated css: " + aCss); - return; - } - - let uri = Services.io.newURI(aCss, null, null); - try { - utils.loadSheet(uri, Ci.nsIDOMWindowUtils.AUTHOR_SHEET); - if (!this._loaded[manifestURL]) { - this._loaded[manifestURL] = { css: [], scripts: [] }; - } - this._loaded[manifestURL].css.push({ window: aWindow, uri: uri }); - aInjected.push(aCss); - } catch(e) { - log("Error loading stylesheet " + aCss + " : " + e); - } - }); - - let sandbox; - if (aItem.scripts.length > 0) { - sandbox = Cu.Sandbox([aWindow], - { wantComponents: false, - sandboxPrototype: aWindow }); - } - - // Load the scripts using a sandbox. - aItem.scripts.forEach(aScript => { - debug("Sandboxing " + aScript); - if (aInjected.indexOf(aScript) !== -1) { - debug("Skipping duplicated script: " + aScript); - return; - } - - try { - let options = { - target: sandbox, - charset: "UTF-8", - async: true - } - Services.scriptloader.loadSubScriptWithOptions(aScript, options); - if (!this._loaded[manifestURL]) { - this._loaded[manifestURL] = { css: [], scripts: [] }; - } - this._loaded[manifestURL].scripts.push({ sandbox: sandbox, uri: aScript }); - aInjected.push(aScript); - } catch(e) { - log("Error sandboxing " + aScript + " : " + e); - } - }); - - // Makes sure we get rid of the sandbox. - if (sandbox) { - aWindow.addEventListener("unload", () => { - Cu.nukeSandbox(sandbox); - sandbox = null; - }); - } - }, - - _injectInWindow: function(aWindow) { - debug("_injectInWindow"); - - if (!aWindow || !aWindow.document) { - return; - } - - let principal = aWindow.document.nodePrincipal; - debug("principal status: " + principal.appStatus); - - let href = aWindow.location.href; - - // The list of resources loaded in this window, used to filter out - // duplicates. - let injected = []; - - this._items.forEach((aItem) => { - // We only allow customizations to apply to apps with an equal or lower - // privilege level. - if (principal.appStatus > aItem.status) { - return; - } - - let regexp = new RegExp(aItem.filter, "g"); - if (regexp.test(href)) { - this._injectItem(aWindow, aItem, injected); - debug("Currently injected: " + injected.toString()); - } - }); - }, - - observe: function(aSubject, aTopic, aData) { - if (aTopic === "content-document-global-created") { - let window = aSubject.QueryInterface(Ci.nsIDOMWindow); - let href = window.location.href; - if (!href || href == "about:blank") { - return; - } - - let id = window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils) - .currentInnerWindowID; - this._windows.set(id, window); - - debug("document created: " + href); - this._injectInWindow(window); - } else if (aTopic === "inner-window-destroyed") { - let winId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data; - this._windows.delete(winId); + if (this.extensions.has(aApp.manifestURL)) { + this.extensions.get(aApp.manifestURL).shutdown(); + this.extensions.delete(aApp.manifestURL); } }, @@ -320,56 +69,7 @@ this.UserCustomizations = { try { this._enabled = Services.prefs.getBoolPref("dom.apps.customization.enabled"); } catch(e) {} - - if (!this._enabled) { - return; - } - - this._windows = new Map(); // Can't be a WeakMap because we need to enumerate. - this._inParent = Cc["@mozilla.org/xre/runtime;1"] - .getService(Ci.nsIXULRuntime) - .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; - - debug("init"); - - Services.obs.addObserver(this, "content-document-global-created", - /* ownsWeak */ false); - Services.obs.addObserver(this, "inner-window-destroyed", - /* ownsWeak */ false); - - if (this._inParent) { - ppmm.addMessageListener("UserCustomizations:List", this); - } else { - cpmm.addMessageListener("UserCustomizations:Add", this); - cpmm.addMessageListener("UserCustomizations:Remove", this); - cpmm.addMessageListener("UserCustomizations:Unload", this); - cpmm.addMessageListener("UserCustomizations:UpdateWindows", this); - cpmm.sendAsyncMessage("UserCustomizations:List", {}); - } }, - - receiveMessage: function(aMessage) { - let name = aMessage.name; - let data = aMessage.data; - - switch(name) { - case "UserCustomizations:List": - aMessage.target.sendAsyncMessage("UserCustomizations:Add", this._items); - break; - case "UserCustomizations:Add": - data.forEach(this._addItem, this); - break; - case "UserCustomizations:Remove": - this._removeItem(data); - break; - case "UserCustomizations:Unload": - this._unloadForManifestURL(data); - break; - case "UserCustomizations:UpdateWindows": - this._updateAllWindows(); - break; - } - } } UserCustomizations.init(); diff --git a/dom/apps/Webapps.jsm b/dom/apps/Webapps.jsm index b22224af8ea..aee7d239e90 100644 --- a/dom/apps/Webapps.jsm +++ b/dom/apps/Webapps.jsm @@ -439,7 +439,7 @@ this.DOMApplicationRegistry = { app.redirects = this.sanitizeRedirects(aResult.redirects); } app.kind = this.appKind(app, aResult.manifest); - UserCustomizations.register(aResult.manifest, app); + UserCustomizations.register(app); Langpacks.register(app, aResult.manifest); }); @@ -1164,7 +1164,7 @@ this.DOMApplicationRegistry = { this._registerSystemMessages(manifest, app); this._registerInterAppConnections(manifest, app); appsToRegister.push({ manifest: manifest, app: app }); - UserCustomizations.register(manifest, app); + UserCustomizations.register(app); Langpacks.register(app, manifest); }); this._safeToClone.resolve(); @@ -2013,10 +2013,10 @@ this.DOMApplicationRegistry = { // Update user customizations and langpacks. if (aOldManifest) { - UserCustomizations.unregister(aOldManifest, aApp); + UserCustomizations.unregister(aApp); Langpacks.unregister(aApp, aOldManifest); } - UserCustomizations.register(aNewManifest, aApp); + UserCustomizations.register(aApp); Langpacks.register(aApp, aNewManifest); }, @@ -4125,7 +4125,7 @@ this.DOMApplicationRegistry = { if (supportSystemMessages()) { this._unregisterActivities(aApp.manifest, aApp); } - UserCustomizations.unregister(aApp.manifest, aApp); + UserCustomizations.unregister(aApp); Langpacks.unregister(aApp, aApp.manifest); let dir = this._getAppDir(id); @@ -4545,10 +4545,11 @@ this.DOMApplicationRegistry = { }); // Update customization. - this.getManifestFor(app.manifestURL).then((aManifest) => { - app.enabled ? UserCustomizations.register(aManifest, app) - : UserCustomizations.unregister(aManifest, app); - }); + if (app.enabled) { + UserCustomizations.register(app); + } else { + UserCustomizations.unregister(app); + } }, getManifestFor: function(aManifestURL, aEntryPoint) { diff --git a/dom/apps/tests/addons/application.zip b/dom/apps/tests/addons/application.zip index 543587c8869ba38506c5889fa66d28755389274b..2d2ece845300a67ebd38ee5da44e12fa4acd408f 100644 GIT binary patch literal 1967 zcmWIWW@Zs#U|`^2@atr8Uw`xVcSlAB1`j3%1}+8}hRnQ_)C#?flH8oo5Kac>;*f)( zAY59(&A`a=f|-E5(yynk6Y5b^RGe|d;n5A#ds3R6tFI)A zY^hiGj6T>XJpD-Fz0cJfC(plYw{~0pY||@iLJd#;=2cj~QAF{BqIXzCPWDZwU^#)l zAk7$Ka}oBCA@OzUPI zntpt`qWpQ|WBhRw6HRRPehPoTw6#klGNP(h`Gtk`0{0ik47<|bT?x=wVm?hOer2`p z)Was7dsL>q6iqrb-+!`v{I!`|$_=OFPuw1)Z0YBIfuX@(PH{!it=YVvvRf7RynN?6 ztHo|nc>kyW32Dq6({SBNXr<{1RrOmOAh zlsWg?m!lk~>KZpKsW6h(buQRXC^W)LiALK7iyTpGzjtG{BdKP!S zZ^HllfWZT+97FzJ0@a=gv+SXX}I| z0tv?V?uK0Z{^_1DgOQ#W`wNkkYp^97b}MaTklb)7hS;fgknFXM@0y{`C>|iJeqdTa3BNvmQ0PF9X zqsG0rp4dIuAlM?jC1^w3q^CkBa{E$5|5WSW;5~E3;K9UcrpB|@XNG2|wDzkQn@?yk z*4NpU|G~9HIsHt#mQwHm&V@h9zvrdx{d4*AcPYMY)$6`l%<|LgESNj*`|WQxI*aux zrp`KiuJ70%21Ib00^ObezACB`=;mG^24!`KyNzHDR|Ps6gwY&s+T+M|$UwmLdvTYd zbm`=#+mGA?MM{>6OH5kGX)<||PwTfYW*xiP-|xR)`lBmTN^-S!VbB$aF1-mnF%wxT zpB!1VyGyS-FNM)A#K54^X5sm~ynB3WuHXN%=g!}ICg-1K@Y$Md32Zt2_HRwj#GPkC zi@UUc|6l!*@c}o;@mxTsGB89Iy>Khbn5!fSWP>m`&`TYSYriY9BMK`HjafAY8*6C;WCev4U`_(fzS*X=*d7` G3=9C$9+$fS literal 1725 zcmWIWW@Zs#U|`^25Gk18%CYF^3_V5$1}P>61}+8}hRnQ_)C#?flH8oo5Kac>_SF+Y zK)AGmn}Lz#1v3K!n3x)L(2LnnVDESBW45{cWiR9I>Se4|=nz}ebiBm)E!(Dr};Eo^zqvCdT>C~nfqt``403pcJR|C;jL_pyki#Dx>tz1MilQ{+99@+xK? z5`XOa;`rw?58IEdl7 zlA6;jKB|A(wCL6AspqK%~oWP(cPA0kC#4fnM*d?@#B^%=_*65R9I5{tpABY!>V18i9>I;zr zVzh`f?ezuuq4m4%QG?YiOSrcm?A@BM@My0%$IL+Hw=9#kEO>O+SD^fT`*%C8yx54M z?9N|nJ1#Cib13lPOQTZ9qO(n^YIhFiicYT;So-iTLyp;@X5E8~Fa8%lzjHq3=|{^6 zhi(<$S!|XX;QM;%o%uj-q}^Dn*?x5Yj01lYGG_TJ-n86k77y|W7tq-Z;DVqmW3G}U zkPX7%xG1U2N!3d(#v2#P8L5dWsYMFaTnY-w`8oMTRtiO_Db`%I2(wjzf%MWwFJBsH zE(n7I31qer+;CN30AWe(P{WOoO;5@xO$8gz$Rx*%s}z#}TEoBq%w7yz8bK`NGL02d zrlG}0fH%TC%sh&0UJ=k(j2sIz6qIA}7>b$NkqxZ{7QRSnpRgM-Qy#K$4!~j>IUNGc z1EoW(&cl@ekj>*{0h)(M4)~l0F%C1%k&R1*83#=PK=VK;0K<8#Y@o diff --git a/dom/apps/tests/addons/manifest.json b/dom/apps/tests/addons/manifest.json new file mode 100644 index 00000000000..1afc8fdb7c2 --- /dev/null +++ b/dom/apps/tests/addons/manifest.json @@ -0,0 +1,12 @@ +{ + "name": "Addon app", + "version": "1.0", + "manifest_version": 2, + "permissions": ["tabs"], + "description": "Let me inject script and css!", + "content_scripts": [ + {"matches": ["http://mochi.test/tests/dom/apps/tests/addons/index.html"], + "js": ["script.js", "script2.js", "invalid.js", "script.js"], + "css": ["style.css", "style2.css"]} + ] +} diff --git a/dom/apps/tests/addons/manifest.webapp b/dom/apps/tests/addons/manifest.webapp index 3d9e095e3aa..14c8a4c9652 100644 --- a/dom/apps/tests/addons/manifest.webapp +++ b/dom/apps/tests/addons/manifest.webapp @@ -1,12 +1,5 @@ { "name": "Addon app", "description": "Let me inject script and css!", - "customizations" : [ - { - "filter": "http://mochi.test:8888/tests/dom/apps/tests/addons", - "css": ["style.css", "style2.css", "invalid.css", "style.css"], - "scripts": ["script.js", "script2.js", "invalid.js", "script.js"] - } - ], "role": "addon" } diff --git a/dom/apps/tests/addons/script.js b/dom/apps/tests/addons/script.js index 608f9b6686f..20fcbba624d 100644 --- a/dom/apps/tests/addons/script.js +++ b/dom/apps/tests/addons/script.js @@ -1,4 +1,5 @@ -document.addEventListener("DOMContentLoaded", function() { - var head = document.getElementById("header"); - head.innerHTML = "Hello World!"; -}, false); +// Simple script that changes an element's content. + +var head = document.getElementById("header"); +head.innerHTML = "Hello World!"; + diff --git a/dom/apps/tests/addons/script2.js b/dom/apps/tests/addons/script2.js index bba0d379213..fa99b79d387 100644 --- a/dom/apps/tests/addons/script2.js +++ b/dom/apps/tests/addons/script2.js @@ -1,4 +1,6 @@ -document.addEventListener("DOMContentLoaded", function() { - var head = document.getElementById("header2"); - head.innerHTML = "Customized content"; -}, false); +// Simple script that changes an element's content. + +var head = document.getElementById("header2"); +head.innerHTML = "Customized content"; + + diff --git a/dom/browser-element/BrowserElementChildPreload.js b/dom/browser-element/BrowserElementChildPreload.js index 14a8d27afc7..ccbe01120fd 100644 --- a/dom/browser-element/BrowserElementChildPreload.js +++ b/dom/browser-element/BrowserElementChildPreload.js @@ -1732,4 +1732,3 @@ BrowserElementChild.prototype = { }; var api = new BrowserElementChild(); - diff --git a/dom/browser-element/BrowserElementParent.js b/dom/browser-element/BrowserElementParent.js index ee1ecd1e7b4..1cf6847f3ec 100644 --- a/dom/browser-element/BrowserElementParent.js +++ b/dom/browser-element/BrowserElementParent.js @@ -234,6 +234,8 @@ BrowserElementParent.prototype = { .apply(self, arguments); } }); + + this._mm.loadFrameScript("chrome://global/content/extensions.js", true); }, /** diff --git a/dom/ipc/extensions.js b/dom/ipc/extensions.js new file mode 100644 index 00000000000..5da2a31382b --- /dev/null +++ b/dom/ipc/extensions.js @@ -0,0 +1,15 @@ +/* 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"; + +dump("######################## extensions.js loaded\n"); + +Components.utils.import("resource://gre/modules/ExtensionContent.jsm"); + +ExtensionContent.init(this); + +addEventListener("unload", () => { + ExtensionContent.uninit(this); +}); diff --git a/dom/ipc/jar.mn b/dom/ipc/jar.mn index e009460ae90..d1b0587b115 100644 --- a/dom/ipc/jar.mn +++ b/dom/ipc/jar.mn @@ -10,5 +10,6 @@ toolkit.jar: content/global/BrowserElementCopyPaste.js (../browser-element/BrowserElementCopyPaste.js) content/global/BrowserElementPanning.js (../browser-element/BrowserElementPanning.js) * content/global/BrowserElementPanningAPZDisabled.js (../browser-element/BrowserElementPanningAPZDisabled.js) + content/global/extensions.js (extensions.js) content/global/manifestMessages.js (manifestMessages.js) content/global/preload.js (preload.js) diff --git a/dom/ipc/preload.js b/dom/ipc/preload.js index 165933e924c..ed09d174808 100644 --- a/dom/ipc/preload.js +++ b/dom/ipc/preload.js @@ -27,11 +27,6 @@ const BrowserElementIsPreloaded = true; Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/SettingsDB.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - try { - if (Services.prefs.getBoolPref("dom.apps.customization.enabled")) { - Cu.import("resource://gre/modules/UserCustomizations.jsm"); - } - } catch(e) {} Cc["@mozilla.org/appshell/appShellService;1"].getService(Ci["nsIAppShellService"]); Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci["nsIWindowMediator"]); diff --git a/netwerk/protocol/res/SubstitutingProtocolHandler.cpp b/netwerk/protocol/res/SubstitutingProtocolHandler.cpp index 6fa355dded0..1c283cc09ce 100644 --- a/netwerk/protocol/res/SubstitutingProtocolHandler.cpp +++ b/netwerk/protocol/res/SubstitutingProtocolHandler.cpp @@ -308,7 +308,8 @@ SubstitutingProtocolHandler::SetSubstitution(const nsACString& root, nsIURI *bas nsresult rv = baseURI->GetScheme(scheme); NS_ENSURE_SUCCESS(rv, rv); if (!scheme.Equals(mScheme)) { - if (mEnforceFileOrJar && !scheme.EqualsLiteral("file") && !scheme.EqualsLiteral("jar")) { + if (mEnforceFileOrJar && !scheme.EqualsLiteral("file") && !scheme.EqualsLiteral("jar") + && !scheme.EqualsLiteral("app")) { NS_WARNING("Refusing to create substituting URI to non-file:// target"); return NS_ERROR_INVALID_ARG; } diff --git a/toolkit/components/extensions/Extension.jsm b/toolkit/components/extensions/Extension.jsm index 33246b740bd..7626c5c7479 100644 --- a/toolkit/components/extensions/Extension.jsm +++ b/toolkit/components/extensions/Extension.jsm @@ -4,7 +4,7 @@ "use strict"; -const EXPORTED_SYMBOLS = ["Extension"]; +this.EXPORTED_SYMBOLS = ["Extension"]; /* * This file is the main entry point for extensions. When an extension @@ -306,7 +306,7 @@ let GlobalManager = { // We create one instance of this class per extension. |addonData| // comes directly from bootstrap.js when initializing. -function Extension(addonData) +this.Extension = function(addonData) { let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator); let uuid = uuidGenerator.generateUUID().number; diff --git a/toolkit/components/extensions/ExtensionContent.jsm b/toolkit/components/extensions/ExtensionContent.jsm index 81ea03e9212..a457f3a0653 100644 --- a/toolkit/components/extensions/ExtensionContent.jsm +++ b/toolkit/components/extensions/ExtensionContent.jsm @@ -4,7 +4,7 @@ "use strict"; -const EXPORTED_SYMBOLS = ["ExtensionContent"]; +this.EXPORTED_SYMBOLS = ["ExtensionContent"]; /* * This file handles the content process side of extensions. It mainly @@ -19,6 +19,7 @@ const Cr = Components.results; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/AppConstants.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "ExtensionManagement", "resource://gre/modules/ExtensionManagement.jsm"); @@ -147,8 +148,20 @@ Script.prototype = { let scheduled = this.run_at || "document_idle"; if (shouldRun(scheduled)) { for (let url of this.js) { + // On gonk we need to load the resources asynchronously because the + // app: channels only support asyncOpen. This is safe only in the + // `document_idle` state. + if (AppConstants.platform == "gonk" && scheduled != "document_idle") { + Cu.reportError(`Script injection: ignoring ${url} at ${scheduled}`); + } url = extension.baseURI.resolve(url); - Services.scriptloader.loadSubScript(url, sandbox); + + let options = { + target: sandbox, + charset: "UTF-8", + async: AppConstants.platform == "gonk" + } + Services.scriptloader.loadSubScriptWithOptions(url, options); } if (this.options.jsCode) { @@ -225,6 +238,7 @@ ExtensionContext.prototype = { callOnClose(obj) { this.onClose.add(obj); + Cu.nukeSandbox(this.sandbox); }, forgetOnClose(obj) { @@ -476,7 +490,7 @@ let ExtensionManager = { } }; -let ExtensionContent = { +this.ExtensionContent = { globals: new Map(), init(global) { diff --git a/toolkit/components/extensions/ExtensionManagement.jsm b/toolkit/components/extensions/ExtensionManagement.jsm index a79735f5440..995f2513b9e 100644 --- a/toolkit/components/extensions/ExtensionManagement.jsm +++ b/toolkit/components/extensions/ExtensionManagement.jsm @@ -4,7 +4,7 @@ "use strict"; -const EXPORTED_SYMBOLS = ["ExtensionManagement"]; +this.EXPORTED_SYMBOLS = ["ExtensionManagement"]; const Ci = Components.interfaces; const Cc = Components.classes; @@ -188,7 +188,7 @@ let Service = { }, }; -let ExtensionManagement = { +this.ExtensionManagement = { startupExtension: Service.startupExtension.bind(Service), shutdownExtension: Service.shutdownExtension.bind(Service), @@ -198,4 +198,3 @@ let ExtensionManagement = { getFrameId: Frames.getId.bind(Frames), getParentFrameId: Frames.getParentId.bind(Frames), }; - diff --git a/toolkit/components/extensions/ExtensionStorage.jsm b/toolkit/components/extensions/ExtensionStorage.jsm index 125e03ea494..8735a1d8ed4 100644 --- a/toolkit/components/extensions/ExtensionStorage.jsm +++ b/toolkit/components/extensions/ExtensionStorage.jsm @@ -4,7 +4,7 @@ "use strict"; -const EXPORTED_SYMBOLS = ["ExtensionStorage"]; +this.EXPORTED_SYMBOLS = ["ExtensionStorage"]; const Ci = Components.interfaces; const Cc = Components.classes; @@ -19,7 +19,7 @@ Cu.import("resource://gre/modules/AsyncShutdown.jsm"); let Path = OS.Path; let profileDir = OS.Constants.Path.profileDir; -let ExtensionStorage = { +this.ExtensionStorage = { cache: new Map(), listeners: new Map(), diff --git a/toolkit/components/extensions/ExtensionUtils.jsm b/toolkit/components/extensions/ExtensionUtils.jsm index a92185ab801..95890b0d932 100644 --- a/toolkit/components/extensions/ExtensionUtils.jsm +++ b/toolkit/components/extensions/ExtensionUtils.jsm @@ -4,7 +4,7 @@ "use strict"; -const EXPORTED_SYMBOLS = ["ExtensionUtils"]; +this.EXPORTED_SYMBOLS = ["ExtensionUtils"]; const Ci = Components.interfaces; const Cc = Components.classes; @@ -527,7 +527,8 @@ Messenger.prototype = { }, }; -let ExtensionUtils = { +this.ExtensionUtils = { + runSafeWithoutClone, runSafe, DefaultWeakMap, EventManager, diff --git a/toolkit/components/extensions/ext-alarms.js b/toolkit/components/extensions/ext-alarms.js index b534c674638..a4ff9eb75e1 100644 --- a/toolkit/components/extensions/ext-alarms.js +++ b/toolkit/components/extensions/ext-alarms.js @@ -1,3 +1,5 @@ +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; + Cu.import("resource://gre/modules/ExtensionUtils.jsm"); let { EventManager, diff --git a/toolkit/components/extensions/ext-notifications.js b/toolkit/components/extensions/ext-notifications.js index 0138154408c..bde585b1491 100644 --- a/toolkit/components/extensions/ext-notifications.js +++ b/toolkit/components/extensions/ext-notifications.js @@ -1,3 +1,5 @@ +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; + Cu.import("resource://gre/modules/ExtensionUtils.jsm"); let { EventManager, diff --git a/toolkit/components/extensions/ext-runtime.js b/toolkit/components/extensions/ext-runtime.js index e9c633b26c0..7771fa13709 100644 --- a/toolkit/components/extensions/ext-runtime.js +++ b/toolkit/components/extensions/ext-runtime.js @@ -1,3 +1,5 @@ +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; + Cu.import("resource://gre/modules/ExtensionUtils.jsm"); let { EventManager, diff --git a/toolkit/components/extensions/ext-storage.js b/toolkit/components/extensions/ext-storage.js index c6c1530460a..c253176b80a 100644 --- a/toolkit/components/extensions/ext-storage.js +++ b/toolkit/components/extensions/ext-storage.js @@ -1,3 +1,5 @@ +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; + XPCOMUtils.defineLazyModuleGetter(this, "ExtensionStorage", "resource://gre/modules/ExtensionStorage.jsm"); diff --git a/toolkit/components/extensions/ext-webNavigation.js b/toolkit/components/extensions/ext-webNavigation.js index 32d63f1c8be..c2fd51e1d86 100644 --- a/toolkit/components/extensions/ext-webNavigation.js +++ b/toolkit/components/extensions/ext-webNavigation.js @@ -1,3 +1,7 @@ +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + XPCOMUtils.defineLazyModuleGetter(this, "ExtensionManagement", "resource://gre/modules/ExtensionManagement.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "MatchPattern", diff --git a/toolkit/components/extensions/ext-webRequest.js b/toolkit/components/extensions/ext-webRequest.js index b6169c381c9..47d7ab0f865 100644 --- a/toolkit/components/extensions/ext-webRequest.js +++ b/toolkit/components/extensions/ext-webRequest.js @@ -1,3 +1,7 @@ +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + XPCOMUtils.defineLazyModuleGetter(this, "MatchPattern", "resource://gre/modules/MatchPattern.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "WebRequest", diff --git a/toolkit/modules/addons/MatchPattern.jsm b/toolkit/modules/addons/MatchPattern.jsm index 86f089f66f0..74c893b8833 100644 --- a/toolkit/modules/addons/MatchPattern.jsm +++ b/toolkit/modules/addons/MatchPattern.jsm @@ -6,9 +6,9 @@ const Cu = Components.utils; -const EXPORTED_SYMBOLS = ["MatchPattern"]; +this.EXPORTED_SYMBOLS = ["MatchPattern"]; -const PERMITTED_SCHEMES = ["http", "https", "file", "ftp"]; +const PERMITTED_SCHEMES = ["http", "https", "file", "ftp", "app"]; // This function converts a glob pattern (containing * and possibly ? // as wildcards) to a regular expression. @@ -37,7 +37,7 @@ function SingleMatchPattern(pat) } else if (!pat) { this.scheme = []; } else { - let re = new RegExp("^(http|https|file|ftp|\\*)://(\\*|\\*\\.[^*/]+|[^*/]+|)(/.*)$"); + let re = new RegExp("^(http|https|file|ftp|app|\\*)://(\\*|\\*\\.[^*/]+|[^*/]+|)(/.*)$"); let match = re.exec(pat); if (!match) { Cu.reportError(`Invalid match pattern: '${pat}'`); @@ -91,7 +91,7 @@ SingleMatchPattern.prototype = { } }; -function MatchPattern(pat) +this.MatchPattern = function(pat) { this.pat = pat; if (!pat) {