diff --git a/build/mobile/b2gautomation.py b/build/mobile/b2gautomation.py index dbcb3d02aec..75a93c6e08a 100644 --- a/build/mobile/b2gautomation.py +++ b/build/mobile/b2gautomation.py @@ -357,11 +357,10 @@ class B2GRemoteAutomation(Automation): if (!testUtils.hasOwnProperty("specialPowersObserver")) { let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"] .getService(Components.interfaces.mozIJSSubScriptLoader); - loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.js", + loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.jsm", testUtils); testUtils.specialPowersObserver = new testUtils.SpecialPowersObserver(); testUtils.specialPowersObserver.init(); - testUtils.specialPowersObserver._loadFrameScript(); } """) diff --git a/dom/ipc/tests/test_bug1086684.html b/dom/ipc/tests/test_bug1086684.html index 227191e1894..f4483d9b5c9 100644 --- a/dom/ipc/tests/test_bug1086684.html +++ b/dom/ipc/tests/test_bug1086684.html @@ -21,7 +21,7 @@ "use strict"; let { MockFilePicker } = - Components.utils.import("resource://specialpowers/MockFilePicker.jsm", {}); + Components.utils.import("chrome://specialpowers/content/MockFilePicker.jsm", {}); function parentReady(message) { MockFilePicker.init(content); diff --git a/testing/marionette/client/marionette/marionette_test.py b/testing/marionette/client/marionette/marionette_test.py index 9501604a432..92c026bef7f 100644 --- a/testing/marionette/client/marionette/marionette_test.py +++ b/testing/marionette/client/marionette/marionette_test.py @@ -558,11 +558,10 @@ setReq.onerror = function() { if (!testUtils.hasOwnProperty("specialPowersObserver")) { let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"] .getService(Components.interfaces.mozIJSSubScriptLoader); - loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.js", + loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.jsm", testUtils); testUtils.specialPowersObserver = new testUtils.SpecialPowersObserver(); testUtils.specialPowersObserver.init(); - testUtils.specialPowersObserver._loadFrameScript(); } """) diff --git a/testing/marionette/jar.mn b/testing/marionette/jar.mn index 634a4b29b04..b9599dbc1d4 100644 --- a/testing/marionette/jar.mn +++ b/testing/marionette/jar.mn @@ -31,15 +31,13 @@ marionette.jar: % content specialpowers %content/ content/specialpowers.js (../specialpowers/content/specialpowers.js) - content/SpecialPowersObserver.js (../specialpowers/components/SpecialPowersObserver.js) + content/SpecialPowersObserver.jsm (../specialpowers/content/SpecialPowersObserver.jsm) * content/specialpowersAPI.js (../specialpowers/content/specialpowersAPI.js) content/SpecialPowersObserverAPI.js (../specialpowers/content/SpecialPowersObserverAPI.js) content/ChromePowers.js (../mochitest/tests/SimpleTest/ChromePowers.js) content/MozillaLogger.js (../specialpowers/content/MozillaLogger.js) - -% resource specialpowers %modules/ - modules/MockFilePicker.jsm (../specialpowers/content/MockFilePicker.jsm) - modules/MockColorPicker.jsm (../specialpowers/content/MockColorPicker.jsm) - modules/MockPermissionPrompt.jsm (../specialpowers/content/MockPermissionPrompt.jsm) - modules/MockPaymentsUIGlue.jsm (../specialpowers/content/MockPaymentsUIGlue.jsm) - modules/Assert.jsm (../modules/Assert.jsm) + content/MockFilePicker.jsm (../specialpowers/content/MockFilePicker.jsm) + content/MockColorPicker.jsm (../specialpowers/content/MockColorPicker.jsm) + content/MockPermissionPrompt.jsm (../specialpowers/content/MockPermissionPrompt.jsm) + content/MockPaymentsUIGlue.jsm (../specialpowers/content/MockPaymentsUIGlue.jsm) + content/Assert.jsm (../modules/Assert.jsm) diff --git a/testing/mochitest/b2g_start_script.js b/testing/mochitest/b2g_start_script.js index 452c09e7b63..37c1c6acd1d 100644 --- a/testing/mochitest/b2g_start_script.js +++ b/testing/mochitest/b2g_start_script.js @@ -85,7 +85,7 @@ container.addEventListener('mozbrowsershowmodalprompt', function (e) { if (outOfProcess) { let specialpowers = {}; let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader); - loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.js", specialpowers); + loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.jsm", specialpowers); let specialPowersObserver = new specialpowers.SpecialPowersObserver(); let mm = container.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader.messageManager; diff --git a/testing/mochitest/mochitest_options.py b/testing/mochitest/mochitest_options.py index 52ec3355e5d..9dabaab79e9 100644 --- a/testing/mochitest/mochitest_options.py +++ b/testing/mochitest/mochitest_options.py @@ -899,6 +899,8 @@ class B2GArguments(ArgumentContainer): defaults = { 'logFile': 'mochitest.log', + # Specialpowers is integrated with marionette for b2g, + # see marionette's jar.mn. 'extensionsToExclude': ['specialpowers'], # See dependencies of bug 1038943. 'defaultLeakThreshold': 5536, diff --git a/testing/mochitest/runtestsb2g.py b/testing/mochitest/runtestsb2g.py index b7190b84d3e..9205c39c7fd 100644 --- a/testing/mochitest/runtestsb2g.py +++ b/testing/mochitest/runtestsb2g.py @@ -234,11 +234,10 @@ class B2GMochitest(MochitestUtilsMixin): if (!testUtils.hasOwnProperty("specialPowersObserver")) { let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"] .getService(Components.interfaces.mozIJSSubScriptLoader); - loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.js", + loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.jsm", testUtils); testUtils.specialPowersObserver = new testUtils.SpecialPowersObserver(); testUtils.specialPowersObserver.init(); - testUtils.specialPowersObserver._loadFrameScript(); } """) diff --git a/testing/specialpowers/Makefile.in b/testing/specialpowers/Makefile.in index b20132f62ba..c75be3c2d03 100644 --- a/testing/specialpowers/Makefile.in +++ b/testing/specialpowers/Makefile.in @@ -3,8 +3,8 @@ # 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/. - TEST_EXTENSIONS_DIR = $(DEPTH)/testing/specialpowers +XPI_PKGNAME = specialpowers@mozilla.org include $(topsrcdir)/config/rules.mk diff --git a/testing/specialpowers/bootstrap.js b/testing/specialpowers/bootstrap.js new file mode 100644 index 00000000000..346fd6ab583 --- /dev/null +++ b/testing/specialpowers/bootstrap.js @@ -0,0 +1,39 @@ +/* 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/. */ + +Components.utils.import("resource://gre/modules/Services.jsm"); + +var spObserver; + +function startup(data, reason) { + let observer = {}; + Components.utils.import("chrome://specialpowers/content/SpecialPowersObserver.jsm", observer); + + let registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); + registrar.registerFactory( + observer.SpecialPowersObserver.prototype.classID, + "SpecialPowersObserver", + observer.SpecialPowersObserver.prototype.contractID, + observer.SpecialPowersObserverFactory + ); + + spObserver = new observer.SpecialPowersObserver(); + spObserver.init(); +} + +function shutdown(data, reason) { + let observer = {}; + Components.utils.import("chrome://specialpowers/content/SpecialPowersObserver.jsm", observer); + + let registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); + registrar.unregisterFactory( + observer.SpecialPowersObserver.prototype.classID, + observer.SpecialPowersObserverFactory + ); + + spObserver.uninit(); +} + +function install(data, reason) {} +function uninstall(data, reason) {} diff --git a/testing/specialpowers/components/SpecialPowersObserver.js b/testing/specialpowers/components/SpecialPowersObserver.js deleted file mode 100644 index 22442271f40..00000000000 --- a/testing/specialpowers/components/SpecialPowersObserver.js +++ /dev/null @@ -1,323 +0,0 @@ -/* 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/. */ - -// Based on: -// https://bugzilla.mozilla.org/show_bug.cgi?id=549539 -// https://bug549539.bugzilla.mozilla.org/attachment.cgi?id=429661 -// https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_1.9.3 -// http://mxr.mozilla.org/mozilla-central/source/toolkit/components/console/hudservice/HUDService.jsm#3240 -// https://developer.mozilla.org/en/how_to_build_an_xpcom_component_in_javascript - -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); -Components.utils.import("resource://gre/modules/Services.jsm"); -Components.utils.importGlobalProperties(['File']); - -if (typeof(Cc) == "undefined") { - const Cc = Components.classes; - const Ci = Components.interfaces; -} - -const CHILD_SCRIPT = "chrome://specialpowers/content/specialpowers.js" -const CHILD_SCRIPT_API = "chrome://specialpowers/content/specialpowersAPI.js" -const CHILD_LOGGER_SCRIPT = "chrome://specialpowers/content/MozillaLogger.js" - - -// Glue to add in the observer API to this object. This allows us to share code with chrome tests -var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"] - .getService(Components.interfaces.mozIJSSubScriptLoader); -loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserverAPI.js"); - -/* XPCOM gunk */ -this.SpecialPowersObserver = function SpecialPowersObserver() { - this._isFrameScriptLoaded = false; - this._mmIsGlobal = true; - this._messageManager = Cc["@mozilla.org/globalmessagemanager;1"]. - getService(Ci.nsIMessageBroadcaster); -} - - -SpecialPowersObserver.prototype = new SpecialPowersObserverAPI(); - - SpecialPowersObserver.prototype.classDescription = "Special powers Observer for use in testing."; - SpecialPowersObserver.prototype.classID = Components.ID("{59a52458-13e0-4d93-9d85-a637344f29a1}"); - SpecialPowersObserver.prototype.contractID = "@mozilla.org/special-powers-observer;1"; - SpecialPowersObserver.prototype.QueryInterface = XPCOMUtils.generateQI([Components.interfaces.nsIObserver]); - SpecialPowersObserver.prototype._xpcom_categories = [{category: "profile-after-change", service: true }]; - - SpecialPowersObserver.prototype.observe = function(aSubject, aTopic, aData) - { - switch (aTopic) { - case "profile-after-change": - this.init(); - break; - - case "chrome-document-global-created": - this._loadFrameScript(); - break; - - case "http-on-modify-request": - if (aSubject instanceof Ci.nsIChannel) { - let uri = aSubject.URI.spec; - this._sendAsyncMessage("specialpowers-http-notify-request", { uri: uri }); - } - break; - - case "xpcom-shutdown": - this.uninit(); - break; - - default: - this._observe(aSubject, aTopic, aData); - break; - } - }; - - SpecialPowersObserver.prototype._loadFrameScript = function() - { - if (!this._isFrameScriptLoaded) { - // Register for any messages our API needs us to handle - this._messageManager.addMessageListener("SPPrefService", this); - this._messageManager.addMessageListener("SPProcessCrashService", this); - this._messageManager.addMessageListener("SPPingService", this); - this._messageManager.addMessageListener("SpecialPowers.Quit", this); - this._messageManager.addMessageListener("SpecialPowers.Focus", this); - this._messageManager.addMessageListener("SpecialPowers.CreateFiles", this); - this._messageManager.addMessageListener("SpecialPowers.RemoveFiles", this); - this._messageManager.addMessageListener("SPPermissionManager", this); - this._messageManager.addMessageListener("SPWebAppService", this); - this._messageManager.addMessageListener("SPObserverService", this); - this._messageManager.addMessageListener("SPLoadChromeScript", this); - this._messageManager.addMessageListener("SPChromeScriptMessage", this); - this._messageManager.addMessageListener("SPQuotaManager", this); - this._messageManager.addMessageListener("SPSetTestPluginEnabledState", this); - this._messageManager.addMessageListener("SPLoadExtension", this); - this._messageManager.addMessageListener("SPStartupExtension", this); - this._messageManager.addMessageListener("SPUnloadExtension", this); - this._messageManager.addMessageListener("SPExtensionMessage", this); - this._messageManager.addMessageListener("SPCleanUpSTSData", this); - - this._messageManager.loadFrameScript(CHILD_LOGGER_SCRIPT, true); - this._messageManager.loadFrameScript(CHILD_SCRIPT_API, true); - this._messageManager.loadFrameScript(CHILD_SCRIPT, true); - this._isFrameScriptLoaded = true; - this._createdFiles = null; - } - }; - - SpecialPowersObserver.prototype._sendAsyncMessage = function(msgname, msg) - { - if (this._mmIsGlobal) { - this._messageManager.broadcastAsyncMessage(msgname, msg); - } - else { - this._messageManager.sendAsyncMessage(msgname, msg); - } - }; - - SpecialPowersObserver.prototype._receiveMessage = function(aMessage) { - return this._receiveMessageAPI(aMessage); - }; - - SpecialPowersObserver.prototype.init = function(messageManager) - { - var obs = Services.obs; - obs.addObserver(this, "xpcom-shutdown", false); - obs.addObserver(this, "chrome-document-global-created", false); - - // Register special testing modules. - var testsURI = Cc["@mozilla.org/file/directory_service;1"]. - getService(Ci.nsIProperties). - get("ProfD", Ci.nsILocalFile); - testsURI.append("tests.manifest"); - var ioSvc = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - var manifestFile = ioSvc.newFileURI(testsURI). - QueryInterface(Ci.nsIFileURL).file; - - Components.manager.QueryInterface(Ci.nsIComponentRegistrar). - autoRegister(manifestFile); - - obs.addObserver(this, "http-on-modify-request", false); - - if (messageManager) { - this._messageManager = messageManager; - this._mmIsGlobal = false; - - this._loadFrameScript(); - } - }; - - SpecialPowersObserver.prototype.uninit = function() - { - var obs = Services.obs; - obs.removeObserver(this, "chrome-document-global-created"); - obs.removeObserver(this, "http-on-modify-request"); - obs.removeObserver(this, "xpcom-shutdown"); - this._registerObservers._topics.forEach(function(element) { - obs.removeObserver(this._registerObservers, element); - }); - this._removeProcessCrashObservers(); - - if (this._isFrameScriptLoaded) { - this._messageManager.removeMessageListener("SPPrefService", this); - this._messageManager.removeMessageListener("SPProcessCrashService", this); - this._messageManager.removeMessageListener("SPPingService", this); - this._messageManager.removeMessageListener("SpecialPowers.Quit", this); - this._messageManager.removeMessageListener("SpecialPowers.Focus", this); - this._messageManager.removeMessageListener("SpecialPowers.CreateFiles", this); - this._messageManager.removeMessageListener("SpecialPowers.RemoveFiles", this); - this._messageManager.removeMessageListener("SPPermissionManager", this); - this._messageManager.removeMessageListener("SPWebAppService", this); - this._messageManager.removeMessageListener("SPObserverService", this); - this._messageManager.removeMessageListener("SPLoadChromeScript", this); - this._messageManager.removeMessageListener("SPChromeScriptMessage", this); - this._messageManager.removeMessageListener("SPQuotaManager", this); - this._messageManager.removeMessageListener("SPSetTestPluginEnabledState", this); - this._messageManager.removeMessageListener("SPLoadExtension", this); - this._messageManager.removeMessageListener("SPStartupExtension", this); - this._messageManager.removeMessageListener("SPUnloadExtension", this); - this._messageManager.removeMessageListener("SPExtensionMessage", this); - this._messageManager.removeMessageListener("SPCleanUpSTSData", this); - - this._messageManager.removeDelayedFrameScript(CHILD_LOGGER_SCRIPT); - this._messageManager.removeDelayedFrameScript(CHILD_SCRIPT_API); - this._messageManager.removeDelayedFrameScript(CHILD_SCRIPT); - this._isFrameScriptLoaded = false; - } - - this._mmIsGlobal = true; - this._messageManager = Cc["@mozilla.org/globalmessagemanager;1"]. - getService(Ci.nsIMessageBroadcaster); - }; - - SpecialPowersObserver.prototype._addProcessCrashObservers = function() { - if (this._processCrashObserversRegistered) { - return; - } - - var obs = Components.classes["@mozilla.org/observer-service;1"] - .getService(Components.interfaces.nsIObserverService); - - obs.addObserver(this, "plugin-crashed", false); - obs.addObserver(this, "ipc:content-shutdown", false); - this._processCrashObserversRegistered = true; - }; - - SpecialPowersObserver.prototype._removeProcessCrashObservers = function() { - if (!this._processCrashObserversRegistered) { - return; - } - - var obs = Components.classes["@mozilla.org/observer-service;1"] - .getService(Components.interfaces.nsIObserverService); - - obs.removeObserver(this, "plugin-crashed"); - obs.removeObserver(this, "ipc:content-shutdown"); - this._processCrashObserversRegistered = false; - }; - - SpecialPowersObserver.prototype._registerObservers = { - _self: null, - _topics: [], - _add: function(topic) { - if (this._topics.indexOf(topic) < 0) { - this._topics.push(topic); - Services.obs.addObserver(this, topic, false); - } - }, - observe: function (aSubject, aTopic, aData) { - var msg = { aData: aData }; - switch (aTopic) { - case "perm-changed": - var permission = aSubject.QueryInterface(Ci.nsIPermission); - - // specialPowersAPI will consume this value, and it is used as a - // fake permission, but only type and principal.appId will be used. - // - // We need to ensure that it looks the same as a real permission, - // so we fake these properties. - msg.permission = { - principal: { - originAttributes: {appId: permission.principal.appId} - }, - type: permission.type - }; - default: - this._self._sendAsyncMessage("specialpowers-" + aTopic, msg); - } - } - }; - - /** - * messageManager callback function - * This will get requests from our API in the window and process them in chrome for it - **/ - SpecialPowersObserver.prototype.receiveMessage = function(aMessage) { - switch(aMessage.name) { - case "SPPingService": - if (aMessage.json.op == "ping") { - aMessage.target - .QueryInterface(Ci.nsIFrameLoaderOwner) - .frameLoader - .messageManager - .sendAsyncMessage("SPPingService", { op: "pong" }); - } - break; - case "SpecialPowers.Quit": - let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci.nsIAppStartup); - appStartup.quit(Ci.nsIAppStartup.eForceQuit); - break; - case "SpecialPowers.Focus": - aMessage.target.focus(); - break; - case "SpecialPowers.CreateFiles": - let filePaths = new Array; - if (!this.createdFiles) { - this._createdFiles = new Array; - } - let createdFiles = this._createdFiles; - try { - aMessage.data.forEach(function(request) { - let testFile = Services.dirsvc.get("ProfD", Ci.nsIFile); - testFile.append(request.name); - let outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream); - outStream.init(testFile, 0x02 | 0x08 | 0x20, // PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE - 0666, 0); - if (request.data) { - outStream.write(request.data, request.data.length); - outStream.close(); - } - filePaths.push(new File(testFile.path)); - createdFiles.push(testFile); - }); - aMessage.target - .QueryInterface(Ci.nsIFrameLoaderOwner) - .frameLoader - .messageManager - .sendAsyncMessage("SpecialPowers.FilesCreated", filePaths); - } catch (e) { - aMessage.target - .QueryInterface(Ci.nsIFrameLoaderOwner) - .frameLoader - .messageManager - .sendAsyncMessage("SpecialPowers.FilesError", e.toString()); - } - - break; - case "SpecialPowers.RemoveFiles": - if (this._createdFiles) { - this._createdFiles.forEach(function (testFile) { - try { - testFile.remove(false); - } catch (e) {} - }); - this._createdFiles = null; - } - break; - default: - return this._receiveMessage(aMessage); - } - }; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SpecialPowersObserver]); diff --git a/testing/specialpowers/content/SpecialPowersObserver.jsm b/testing/specialpowers/content/SpecialPowersObserver.jsm new file mode 100644 index 00000000000..7471cd401ca --- /dev/null +++ b/testing/specialpowers/content/SpecialPowersObserver.jsm @@ -0,0 +1,322 @@ +/* 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/. */ + +// Based on: +// https://bugzilla.mozilla.org/show_bug.cgi?id=549539 +// https://bug549539.bugzilla.mozilla.org/attachment.cgi?id=429661 +// https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_1.9.3 +// http://mxr.mozilla.org/mozilla-central/source/toolkit/components/console/hudservice/HUDService.jsm#3240 +// https://developer.mozilla.org/en/how_to_build_an_xpcom_component_in_javascript + +var EXPORTED_SYMBOLS = ["SpecialPowersObserver", "SpecialPowersObserverFactory"]; + +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); +Components.utils.importGlobalProperties(['File']); + +if (typeof(Cc) == "undefined") { + const Cc = Components.classes; + const Ci = Components.interfaces; +} + +const CHILD_SCRIPT = "chrome://specialpowers/content/specialpowers.js" +const CHILD_SCRIPT_API = "chrome://specialpowers/content/specialpowersAPI.js" +const CHILD_LOGGER_SCRIPT = "chrome://specialpowers/content/MozillaLogger.js" + + +// Glue to add in the observer API to this object. This allows us to share code with chrome tests +var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"] + .getService(Components.interfaces.mozIJSSubScriptLoader); +loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserverAPI.js"); + +/* XPCOM gunk */ +this.SpecialPowersObserver = function SpecialPowersObserver() { + this._isFrameScriptLoaded = false; + this._mmIsGlobal = true; + this._messageManager = Cc["@mozilla.org/globalmessagemanager;1"]. + getService(Ci.nsIMessageBroadcaster); +} + + +SpecialPowersObserver.prototype = new SpecialPowersObserverAPI(); + +SpecialPowersObserver.prototype.classDescription = "Special powers Observer for use in testing."; +SpecialPowersObserver.prototype.classID = Components.ID("{59a52458-13e0-4d93-9d85-a637344f29a1}"); +SpecialPowersObserver.prototype.contractID = "@mozilla.org/special-powers-observer;1"; +SpecialPowersObserver.prototype.QueryInterface = XPCOMUtils.generateQI([Components.interfaces.nsIObserver]); + +SpecialPowersObserver.prototype.observe = function(aSubject, aTopic, aData) +{ + switch (aTopic) { + case "chrome-document-global-created": + this._loadFrameScript(); + break; + + case "http-on-modify-request": + if (aSubject instanceof Ci.nsIChannel) { + let uri = aSubject.URI.spec; + this._sendAsyncMessage("specialpowers-http-notify-request", { uri: uri }); + } + break; + + default: + this._observe(aSubject, aTopic, aData); + break; + } +}; + +SpecialPowersObserver.prototype._loadFrameScript = function() +{ + if (!this._isFrameScriptLoaded) { + // Register for any messages our API needs us to handle + this._messageManager.addMessageListener("SPPrefService", this); + this._messageManager.addMessageListener("SPProcessCrashService", this); + this._messageManager.addMessageListener("SPPingService", this); + this._messageManager.addMessageListener("SpecialPowers.Quit", this); + this._messageManager.addMessageListener("SpecialPowers.Focus", this); + this._messageManager.addMessageListener("SpecialPowers.CreateFiles", this); + this._messageManager.addMessageListener("SpecialPowers.RemoveFiles", this); + this._messageManager.addMessageListener("SPPermissionManager", this); + this._messageManager.addMessageListener("SPWebAppService", this); + this._messageManager.addMessageListener("SPObserverService", this); + this._messageManager.addMessageListener("SPLoadChromeScript", this); + this._messageManager.addMessageListener("SPChromeScriptMessage", this); + this._messageManager.addMessageListener("SPQuotaManager", this); + this._messageManager.addMessageListener("SPSetTestPluginEnabledState", this); + this._messageManager.addMessageListener("SPLoadExtension", this); + this._messageManager.addMessageListener("SPStartupExtension", this); + this._messageManager.addMessageListener("SPUnloadExtension", this); + this._messageManager.addMessageListener("SPExtensionMessage", this); + this._messageManager.addMessageListener("SPCleanUpSTSData", this); + + this._messageManager.loadFrameScript(CHILD_LOGGER_SCRIPT, true); + this._messageManager.loadFrameScript(CHILD_SCRIPT_API, true); + this._messageManager.loadFrameScript(CHILD_SCRIPT, true); + this._isFrameScriptLoaded = true; + this._createdFiles = null; + } +}; + +SpecialPowersObserver.prototype._sendAsyncMessage = function(msgname, msg) +{ + if (this._mmIsGlobal) { + this._messageManager.broadcastAsyncMessage(msgname, msg); + } + else { + this._messageManager.sendAsyncMessage(msgname, msg); + } +}; + +SpecialPowersObserver.prototype._receiveMessage = function(aMessage) { + return this._receiveMessageAPI(aMessage); +}; + +SpecialPowersObserver.prototype.init = function(messageManager) +{ + var obs = Services.obs; + obs.addObserver(this, "chrome-document-global-created", false); + + // Register special testing modules. + var testsURI = Cc["@mozilla.org/file/directory_service;1"]. + getService(Ci.nsIProperties). + get("ProfD", Ci.nsILocalFile); + testsURI.append("tests.manifest"); + var ioSvc = Cc["@mozilla.org/network/io-service;1"]. + getService(Ci.nsIIOService); + var manifestFile = ioSvc.newFileURI(testsURI). + QueryInterface(Ci.nsIFileURL).file; + + Components.manager.QueryInterface(Ci.nsIComponentRegistrar). + autoRegister(manifestFile); + + obs.addObserver(this, "http-on-modify-request", false); + + if (messageManager) { + this._messageManager = messageManager; + this._mmIsGlobal = false; + } + + this._loadFrameScript(); +}; + +SpecialPowersObserver.prototype.uninit = function() +{ + var obs = Services.obs; + obs.removeObserver(this, "chrome-document-global-created"); + obs.removeObserver(this, "http-on-modify-request"); + this._registerObservers._topics.forEach(function(element) { + obs.removeObserver(this._registerObservers, element); + }); + this._removeProcessCrashObservers(); + + if (this._isFrameScriptLoaded) { + this._messageManager.removeMessageListener("SPPrefService", this); + this._messageManager.removeMessageListener("SPProcessCrashService", this); + this._messageManager.removeMessageListener("SPPingService", this); + this._messageManager.removeMessageListener("SpecialPowers.Quit", this); + this._messageManager.removeMessageListener("SpecialPowers.Focus", this); + this._messageManager.removeMessageListener("SpecialPowers.CreateFiles", this); + this._messageManager.removeMessageListener("SpecialPowers.RemoveFiles", this); + this._messageManager.removeMessageListener("SPPermissionManager", this); + this._messageManager.removeMessageListener("SPWebAppService", this); + this._messageManager.removeMessageListener("SPObserverService", this); + this._messageManager.removeMessageListener("SPLoadChromeScript", this); + this._messageManager.removeMessageListener("SPChromeScriptMessage", this); + this._messageManager.removeMessageListener("SPQuotaManager", this); + this._messageManager.removeMessageListener("SPSetTestPluginEnabledState", this); + this._messageManager.removeMessageListener("SPLoadExtension", this); + this._messageManager.removeMessageListener("SPStartupExtension", this); + this._messageManager.removeMessageListener("SPUnloadExtension", this); + this._messageManager.removeMessageListener("SPExtensionMessage", this); + this._messageManager.removeMessageListener("SPCleanUpSTSData", this); + + this._messageManager.removeDelayedFrameScript(CHILD_LOGGER_SCRIPT); + this._messageManager.removeDelayedFrameScript(CHILD_SCRIPT_API); + this._messageManager.removeDelayedFrameScript(CHILD_SCRIPT); + this._isFrameScriptLoaded = false; + } + + this._mmIsGlobal = true; + this._messageManager = Cc["@mozilla.org/globalmessagemanager;1"]. + getService(Ci.nsIMessageBroadcaster); +}; + +SpecialPowersObserver.prototype._addProcessCrashObservers = function() { + if (this._processCrashObserversRegistered) { + return; + } + + var obs = Components.classes["@mozilla.org/observer-service;1"] + .getService(Components.interfaces.nsIObserverService); + + obs.addObserver(this, "plugin-crashed", false); + obs.addObserver(this, "ipc:content-shutdown", false); + this._processCrashObserversRegistered = true; +}; + +SpecialPowersObserver.prototype._removeProcessCrashObservers = function() { + if (!this._processCrashObserversRegistered) { + return; + } + + var obs = Components.classes["@mozilla.org/observer-service;1"] + .getService(Components.interfaces.nsIObserverService); + + obs.removeObserver(this, "plugin-crashed"); + obs.removeObserver(this, "ipc:content-shutdown"); + this._processCrashObserversRegistered = false; +}; + +SpecialPowersObserver.prototype._registerObservers = { + _self: null, + _topics: [], + _add: function(topic) { + if (this._topics.indexOf(topic) < 0) { + this._topics.push(topic); + Services.obs.addObserver(this, topic, false); + } + }, + observe: function (aSubject, aTopic, aData) { + var msg = { aData: aData }; + switch (aTopic) { + case "perm-changed": + var permission = aSubject.QueryInterface(Ci.nsIPermission); + + // specialPowersAPI will consume this value, and it is used as a + // fake permission, but only type and principal.appId will be used. + // + // We need to ensure that it looks the same as a real permission, + // so we fake these properties. + msg.permission = { + principal: { + originAttributes: {appId: permission.principal.appId} + }, + type: permission.type + }; + default: + this._self._sendAsyncMessage("specialpowers-" + aTopic, msg); + } + } +}; + +/** + * messageManager callback function + * This will get requests from our API in the window and process them in chrome for it + **/ +SpecialPowersObserver.prototype.receiveMessage = function(aMessage) { + switch(aMessage.name) { + case "SPPingService": + if (aMessage.json.op == "ping") { + aMessage.target + .QueryInterface(Ci.nsIFrameLoaderOwner) + .frameLoader + .messageManager + .sendAsyncMessage("SPPingService", { op: "pong" }); + } + break; + case "SpecialPowers.Quit": + let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci.nsIAppStartup); + appStartup.quit(Ci.nsIAppStartup.eForceQuit); + break; + case "SpecialPowers.Focus": + aMessage.target.focus(); + break; + case "SpecialPowers.CreateFiles": + let filePaths = new Array; + if (!this.createdFiles) { + this._createdFiles = new Array; + } + let createdFiles = this._createdFiles; + try { + aMessage.data.forEach(function(request) { + let testFile = Services.dirsvc.get("ProfD", Ci.nsIFile); + testFile.append(request.name); + let outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream); + outStream.init(testFile, 0x02 | 0x08 | 0x20, // PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE + 0666, 0); + if (request.data) { + outStream.write(request.data, request.data.length); + outStream.close(); + } + filePaths.push(new File(testFile.path)); + createdFiles.push(testFile); + }); + aMessage.target + .QueryInterface(Ci.nsIFrameLoaderOwner) + .frameLoader + .messageManager + .sendAsyncMessage("SpecialPowers.FilesCreated", filePaths); + } catch (e) { + aMessage.target + .QueryInterface(Ci.nsIFrameLoaderOwner) + .frameLoader + .messageManager + .sendAsyncMessage("SpecialPowers.FilesError", e.toString()); + } + + break; + case "SpecialPowers.RemoveFiles": + if (this._createdFiles) { + this._createdFiles.forEach(function (testFile) { + try { + testFile.remove(false); + } catch (e) {} + }); + this._createdFiles = null; + } + break; + default: + return this._receiveMessage(aMessage); + } +}; + +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SpecialPowersObserver]); +this.SpecialPowersObserverFactory = Object.freeze({ + createInstance: function(outer, id) { + if (outer) { throw Components.results.NS_ERROR_NO_AGGREGATION }; + return new SpecialPowersObserver(); + }, + loadFactory: function(lock){}, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]) +}); diff --git a/testing/specialpowers/content/SpecialPowersObserverAPI.js b/testing/specialpowers/content/SpecialPowersObserverAPI.js index f22b668bf1c..8b240352128 100644 --- a/testing/specialpowers/content/SpecialPowersObserverAPI.js +++ b/testing/specialpowers/content/SpecialPowersObserverAPI.js @@ -459,7 +459,7 @@ SpecialPowersObserverAPI.prototype = { Object.defineProperty(sb, "assert", { get: function () { let scope = Components.utils.createObjectIn(sb); - Services.scriptloader.loadSubScript("resource://specialpowers/Assert.jsm", + Services.scriptloader.loadSubScript("chrome://specialpowers/content/Assert.jsm", scope); let assert = new scope.Assert(reporter); diff --git a/testing/specialpowers/content/specialpowers.js b/testing/specialpowers/content/specialpowers.js index 1208616fcb1..be12beeebbc 100644 --- a/testing/specialpowers/content/specialpowers.js +++ b/testing/specialpowers/content/specialpowers.js @@ -213,10 +213,9 @@ SpecialPowers.prototype.nestedFrameSetup = function() { }); }); - let specialPowersBase = "chrome://specialpowers/content/"; - mm.loadFrameScript(specialPowersBase + "MozillaLogger.js", false); - mm.loadFrameScript(specialPowersBase + "specialpowersAPI.js", false); - mm.loadFrameScript(specialPowersBase + "specialpowers.js", false); + mm.loadFrameScript("chrome://specialpowers/content/MozillaLogger.js", false); + mm.loadFrameScript("chrome://specialpowers/content/specialpowersAPI.js", false); + mm.loadFrameScript("chrome://specialpowers/content/specialpowers.js", false); let frameScript = "SpecialPowers.prototype.IsInNestedFrame=true;"; mm.loadFrameScript("data:," + frameScript, false); diff --git a/testing/specialpowers/content/specialpowersAPI.js b/testing/specialpowers/content/specialpowersAPI.js index 7536222e2ab..f744adf6c37 100644 --- a/testing/specialpowers/content/specialpowersAPI.js +++ b/testing/specialpowers/content/specialpowersAPI.js @@ -11,10 +11,10 @@ var Ci = Components.interfaces; var Cc = Components.classes; var Cu = Components.utils; -Cu.import("resource://specialpowers/MockFilePicker.jsm"); -Cu.import("resource://specialpowers/MockColorPicker.jsm"); -Cu.import("resource://specialpowers/MockPermissionPrompt.jsm"); -Cu.import("resource://specialpowers/MockPaymentsUIGlue.jsm"); +Cu.import("chrome://specialpowers/content/MockFilePicker.jsm"); +Cu.import("chrome://specialpowers/content/MockColorPicker.jsm"); +Cu.import("chrome://specialpowers/content/MockPermissionPrompt.jsm"); +Cu.import("chrome://specialpowers/content/MockPaymentsUIGlue.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); diff --git a/testing/specialpowers/install.rdf b/testing/specialpowers/install.rdf index bb459cfe6b6..6bf0c914dee 100644 --- a/testing/specialpowers/install.rdf +++ b/testing/specialpowers/install.rdf @@ -5,8 +5,9 @@ special-powers@mozilla.org - 2010.07.23 + 2015.11.16 2 + true @@ -14,7 +15,8 @@ toolkit@mozilla.org #expand __MOZILLA_VERSION_U__ -#expand __MOZILLA_VERSION_U__ + + * diff --git a/testing/specialpowers/jar.mn b/testing/specialpowers/jar.mn index f58be5e9219..90793bb33de 100644 --- a/testing/specialpowers/jar.mn +++ b/testing/specialpowers/jar.mn @@ -1,17 +1,12 @@ specialpowers.jar: -% content specialpowers %content/ +% content specialpowers %content/ contentaccessible=true content/specialpowers.js (content/specialpowers.js) * content/specialpowersAPI.js (content/specialpowersAPI.js) content/SpecialPowersObserverAPI.js (content/SpecialPowersObserverAPI.js) + content/SpecialPowersObserver.jsm (content/SpecialPowersObserver.jsm) content/MozillaLogger.js (content/MozillaLogger.js) - -% resource specialpowers %modules/ - modules/MockFilePicker.jsm (content/MockFilePicker.jsm) - modules/MockColorPicker.jsm (content/MockColorPicker.jsm) - modules/MockPermissionPrompt.jsm (content/MockPermissionPrompt.jsm) - modules/MockPaymentsUIGlue.jsm (content/MockPaymentsUIGlue.jsm) - modules/Assert.jsm (../modules/Assert.jsm) - -% component {59a52458-13e0-4d93-9d85-a637344f29a1} components/SpecialPowersObserver.js -% contract @mozilla.org/special-powers-observer;1 {59a52458-13e0-4d93-9d85-a637344f29a1} -% category profile-after-change @mozilla.org/special-powers-observer;1 @mozilla.org/special-powers-observer;1 + content/MockFilePicker.jsm (content/MockFilePicker.jsm) + content/MockColorPicker.jsm (content/MockColorPicker.jsm) + content/MockPermissionPrompt.jsm (content/MockPermissionPrompt.jsm) + content/MockPaymentsUIGlue.jsm (content/MockPaymentsUIGlue.jsm) + content/Assert.jsm (../modules/Assert.jsm) diff --git a/testing/specialpowers/moz.build b/testing/specialpowers/moz.build index 5f90d54507c..d6d23dbe5ff 100644 --- a/testing/specialpowers/moz.build +++ b/testing/specialpowers/moz.build @@ -4,10 +4,6 @@ # 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/. -EXTRA_COMPONENTS += [ - 'components/SpecialPowersObserver.js', -] - XPI_NAME = 'specialpowers' JAR_MANIFESTS += ['jar.mn'] @@ -15,4 +11,7 @@ JAR_MANIFESTS += ['jar.mn'] USE_EXTENSION_MANIFEST = True NO_JS_MANIFEST = True -DIST_FILES += ['install.rdf'] +DIST_FILES += [ + 'bootstrap.js', + 'install.rdf', +] diff --git a/testing/testsuite-targets.mk b/testing/testsuite-targets.mk index 04a333c70e6..00532636205 100644 --- a/testing/testsuite-targets.mk +++ b/testing/testsuite-targets.mk @@ -374,6 +374,7 @@ PKG_STAGE = $(DIST)/test-stage stage-all: \ stage-config \ stage-mach \ + stage-extensions \ stage-mochitest \ stage-xpcshell \ stage-jstests \ @@ -550,6 +551,14 @@ stage-marionette: make-stage-dir stage-instrumentation-tests: make-stage-dir $(MAKE) -C $(DEPTH)/testing/instrumentation stage-package +TEST_EXTENSIONS := \ + specialpowers@mozilla.org.xpi \ + $(NULL) + +stage-extensions: make-stage-dir + $(NSINSTALL) -D $(PKG_STAGE)/extensions/ + @$(foreach ext,$(TEST_EXTENSIONS), cp -RL $(DIST)/xpi-stage/$(ext) $(PKG_STAGE)/extensions;) + .PHONY: \ mochitest \ mochitest-plain \ diff --git a/toolkit/mozapps/update/tests/chrome/utils.js b/toolkit/mozapps/update/tests/chrome/utils.js index b0c00ed3386..3da17d2aca5 100644 --- a/toolkit/mozapps/update/tests/chrome/utils.js +++ b/toolkit/mozapps/update/tests/chrome/utils.js @@ -1300,9 +1300,12 @@ function setupAddons(aCallback) { // checking plugins compatibility information isn't supported at this // time (also see bug 566787). Also, SCOPE_APPLICATION add-ons are // excluded by app update so there is no reason to disable them. + // Specialpowers is excluded as the test harness requires it to run + // the tests. if (aAddon.type != "plugin" && !aAddon.appDisabled && !aAddon.userDisabled && - aAddon.scope != AddonManager.SCOPE_APPLICATION) { + aAddon.scope != AddonManager.SCOPE_APPLICATION && + aAddon.id != "special-powers@mozilla.org") { disabledAddons.push(aAddon); aAddon.userDisabled = true; }