Bug 1219442 - Re-write specialpowers as a restartless addon, r=jmaher

In order to meet the addon signing requirement for tests, specialpowers
needs to be installed at gecko runtime. This means it must be restartless.
This patch packages specialpowers as a restartless addon, but it does not
yet install it at runtime.
This commit is contained in:
Andrew Halberstadt 2015-11-05 10:00:59 -05:00
parent 051c84e08a
commit e900916435
19 changed files with 411 additions and 369 deletions

View File

@ -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();
}
""")

View File

@ -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);

View File

@ -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();
}
""")

View File

@ -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)

View File

@ -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;

View File

@ -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,

View File

@ -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();
}
""")

View File

@ -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

39
testing/specialpowers/bootstrap.js vendored Normal file
View File

@ -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) {}

View File

@ -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]);

View File

@ -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])
});

View File

@ -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);

View File

@ -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);

View File

@ -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");

View File

@ -5,8 +5,9 @@
<Description about="urn:mozilla:install-manifest">
<em:id>special-powers@mozilla.org</em:id>
<em:version>2010.07.23</em:version>
<em:version>2015.11.16</em:version>
<em:type>2</em:type>
<em:bootstrap>true</em:bootstrap>
<!-- Target Application this extension can install into,
with minimum and maximum supported versions. -->
@ -14,7 +15,8 @@
<Description>
<em:id>toolkit@mozilla.org</em:id>
#expand <em:minVersion>__MOZILLA_VERSION_U__</em:minVersion>
#expand <em:maxVersion>__MOZILLA_VERSION_U__</em:maxVersion>
<!-- Set to * so toolkit/mozapps/update/chrome tests pass. -->
<em:maxVersion>*</em:maxVersion>
</Description>
</em:targetApplication>

View File

@ -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)

View File

@ -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',
]

View File

@ -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 \

View File

@ -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;
}