mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-12 18:27:32 +09:00
Move WebExtensions enabled Add-ons Manager
This commit is contained in:
parent
d7d16e7fbb
commit
358cd0404a
1100 changed files with 133 additions and 106 deletions
434
toolkit/mozapps/webextensions/test/xpinstall/head.js
Normal file
434
toolkit/mozapps/webextensions/test/xpinstall/head.js
Normal file
|
|
@ -0,0 +1,434 @@
|
|||
const RELATIVE_DIR = "toolkit/mozapps/extensions/test/xpinstall/";
|
||||
|
||||
const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
|
||||
const TESTROOT2 = "http://example.org/browser/" + RELATIVE_DIR;
|
||||
const XPINSTALL_URL = "chrome://mozapps/content/xpinstall/xpinstallConfirm.xul";
|
||||
const PROMPT_URL = "chrome://global/content/commonDialog.xul";
|
||||
const ADDONS_URL = "chrome://mozapps/content/extensions/extensions.xul";
|
||||
const PREF_LOGGING_ENABLED = "extensions.logging.enabled";
|
||||
const PREF_INSTALL_REQUIREBUILTINCERTS = "extensions.install.requireBuiltInCerts";
|
||||
const PREF_INSTALL_REQUIRESECUREORIGIN = "extensions.install.requireSecureOrigin";
|
||||
const PREF_CUSTOM_CONFIRMATION_UI = "xpinstall.customConfirmationUI";
|
||||
const CHROME_NAME = "mochikit";
|
||||
|
||||
function getChromeRoot(path) {
|
||||
if (path === undefined) {
|
||||
return "chrome://" + CHROME_NAME + "/content/browser/" + RELATIVE_DIR
|
||||
}
|
||||
return getRootDirectory(path);
|
||||
}
|
||||
|
||||
function extractChromeRoot(path) {
|
||||
var chromeRootPath = getChromeRoot(path);
|
||||
var jar = getJar(chromeRootPath);
|
||||
if (jar) {
|
||||
var tmpdir = extractJarToTmp(jar);
|
||||
return "file://" + tmpdir.path + "/";
|
||||
}
|
||||
return chromeRootPath;
|
||||
}
|
||||
|
||||
Services.prefs.setBoolPref(PREF_CUSTOM_CONFIRMATION_UI, false);
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref(PREF_CUSTOM_CONFIRMATION_UI);
|
||||
});
|
||||
|
||||
/**
|
||||
* This is a test harness designed to handle responding to UI during the process
|
||||
* of installing an XPI. A test can set callbacks to hear about specific parts
|
||||
* of the sequence.
|
||||
* Before use setup must be called and finish must be called afterwards.
|
||||
*/
|
||||
var Harness = {
|
||||
// If set then the callback is called when an install is attempted and
|
||||
// software installation is disabled.
|
||||
installDisabledCallback: null,
|
||||
// If set then the callback is called when an install is attempted and
|
||||
// then canceled.
|
||||
installCancelledCallback: null,
|
||||
// If set then the callback will be called when an install's origin is blocked.
|
||||
installOriginBlockedCallback: null,
|
||||
// If set then the callback will be called when an install is blocked by the
|
||||
// whitelist. The callback should return true to continue with the install
|
||||
// anyway.
|
||||
installBlockedCallback: null,
|
||||
// If set will be called in the event of authentication being needed to get
|
||||
// the xpi. Should return a 2 element array of username and password, or
|
||||
// null to not authenticate.
|
||||
authenticationCallback: null,
|
||||
// If set this will be called to allow checking the contents of the xpinstall
|
||||
// confirmation dialog. The callback should return true to continue the install.
|
||||
installConfirmCallback: null,
|
||||
// If set will be called when downloading of an item has begun.
|
||||
downloadStartedCallback: null,
|
||||
// If set will be called during the download of an item.
|
||||
downloadProgressCallback: null,
|
||||
// If set will be called when an xpi fails to download.
|
||||
downloadFailedCallback: null,
|
||||
// If set will be called when an xpi download is cancelled.
|
||||
downloadCancelledCallback: null,
|
||||
// If set will be called when downloading of an item has ended.
|
||||
downloadEndedCallback: null,
|
||||
// If set will be called when installation by the extension manager of an xpi
|
||||
// item starts
|
||||
installStartedCallback: null,
|
||||
// If set will be called when an xpi fails to install.
|
||||
installFailedCallback: null,
|
||||
// If set will be called when each xpi item to be installed completes
|
||||
// installation.
|
||||
installEndedCallback: null,
|
||||
// If set will be called when all triggered items are installed or the install
|
||||
// is canceled.
|
||||
installsCompletedCallback: null,
|
||||
// If set the harness will wait for this DOM event before calling
|
||||
// installsCompletedCallback
|
||||
finalContentEvent: null,
|
||||
|
||||
waitingForEvent: false,
|
||||
pendingCount: null,
|
||||
installCount: null,
|
||||
runningInstalls: null,
|
||||
|
||||
waitingForFinish: false,
|
||||
|
||||
// A unique value to return from the installConfirmCallback to indicate that
|
||||
// the install UI shouldn't be closed automatically
|
||||
leaveOpen: {},
|
||||
|
||||
// Setup and tear down functions
|
||||
setup: function() {
|
||||
if (!this.waitingForFinish) {
|
||||
waitForExplicitFinish();
|
||||
this.waitingForFinish = true;
|
||||
|
||||
Services.prefs.setBoolPref(PREF_INSTALL_REQUIRESECUREORIGIN, false);
|
||||
|
||||
Services.prefs.setBoolPref(PREF_LOGGING_ENABLED, true);
|
||||
Services.obs.addObserver(this, "addon-install-started", false);
|
||||
Services.obs.addObserver(this, "addon-install-disabled", false);
|
||||
Services.obs.addObserver(this, "addon-install-origin-blocked", false);
|
||||
Services.obs.addObserver(this, "addon-install-blocked", false);
|
||||
Services.obs.addObserver(this, "addon-install-failed", false);
|
||||
Services.obs.addObserver(this, "addon-install-complete", false);
|
||||
|
||||
AddonManager.addInstallListener(this);
|
||||
|
||||
Services.wm.addListener(this);
|
||||
|
||||
var self = this;
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref(PREF_LOGGING_ENABLED);
|
||||
Services.prefs.clearUserPref(PREF_INSTALL_REQUIRESECUREORIGIN);
|
||||
Services.obs.removeObserver(self, "addon-install-started");
|
||||
Services.obs.removeObserver(self, "addon-install-disabled");
|
||||
Services.obs.removeObserver(self, "addon-install-origin-blocked");
|
||||
Services.obs.removeObserver(self, "addon-install-blocked");
|
||||
Services.obs.removeObserver(self, "addon-install-failed");
|
||||
Services.obs.removeObserver(self, "addon-install-complete");
|
||||
|
||||
AddonManager.removeInstallListener(self);
|
||||
|
||||
Services.wm.removeListener(self);
|
||||
|
||||
AddonManager.getAllInstalls(function(aInstalls) {
|
||||
is(aInstalls.length, 0, "Should be no active installs at the end of the test");
|
||||
aInstalls.forEach(function(aInstall) {
|
||||
info("Install for " + aInstall.sourceURI + " is in state " + aInstall.state);
|
||||
aInstall.cancel();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
this.installCount = 0;
|
||||
this.pendingCount = 0;
|
||||
this.runningInstalls = [];
|
||||
},
|
||||
|
||||
finish: function() {
|
||||
finish();
|
||||
},
|
||||
|
||||
endTest: function() {
|
||||
let callback = this.installsCompletedCallback;
|
||||
let count = this.installCount;
|
||||
|
||||
is(this.runningInstalls.length, 0, "Should be no running installs left");
|
||||
this.runningInstalls.forEach(function(aInstall) {
|
||||
info("Install for " + aInstall.sourceURI + " is in state " + aInstall.state);
|
||||
});
|
||||
|
||||
this.installOriginBlockedCallback = null;
|
||||
this.installBlockedCallback = null;
|
||||
this.authenticationCallback = null;
|
||||
this.installConfirmCallback = null;
|
||||
this.downloadStartedCallback = null;
|
||||
this.downloadProgressCallback = null;
|
||||
this.downloadCancelledCallback = null;
|
||||
this.downloadFailedCallback = null;
|
||||
this.downloadEndedCallback = null;
|
||||
this.installStartedCallback = null;
|
||||
this.installFailedCallback = null;
|
||||
this.installEndedCallback = null;
|
||||
this.installsCompletedCallback = null;
|
||||
this.runningInstalls = null;
|
||||
|
||||
if (callback)
|
||||
executeSoon(() => callback(count));
|
||||
},
|
||||
|
||||
// Window open handling
|
||||
windowReady: function(window) {
|
||||
if (window.document.location.href == XPINSTALL_URL) {
|
||||
if (this.installBlockedCallback)
|
||||
ok(false, "Should have been blocked by the whitelist");
|
||||
this.pendingCount = window.document.getElementById("itemList").childNodes.length;
|
||||
|
||||
// If there is a confirm callback then its return status determines whether
|
||||
// to install the items or not. If not the test is over.
|
||||
let result = true;
|
||||
if (this.installConfirmCallback) {
|
||||
result = this.installConfirmCallback(window);
|
||||
if (result === this.leaveOpen)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
window.document.documentElement.cancelDialog();
|
||||
}
|
||||
else {
|
||||
// Initially the accept button is disabled on a countdown timer
|
||||
var button = window.document.documentElement.getButton("accept");
|
||||
button.disabled = false;
|
||||
window.document.documentElement.acceptDialog();
|
||||
}
|
||||
}
|
||||
else if (window.document.location.href == PROMPT_URL) {
|
||||
var promptType = window.args.promptType;
|
||||
switch (promptType) {
|
||||
case "alert":
|
||||
case "alertCheck":
|
||||
case "confirmCheck":
|
||||
case "confirm":
|
||||
case "confirmEx":
|
||||
window.document.documentElement.acceptDialog();
|
||||
break;
|
||||
case "promptUserAndPass":
|
||||
// This is a login dialog, hopefully an authentication prompt
|
||||
// for the xpi.
|
||||
if (this.authenticationCallback) {
|
||||
var auth = this.authenticationCallback();
|
||||
if (auth && auth.length == 2) {
|
||||
window.document.getElementById("loginTextbox").value = auth[0];
|
||||
window.document.getElementById("password1Textbox").value = auth[1];
|
||||
window.document.documentElement.acceptDialog();
|
||||
}
|
||||
else {
|
||||
window.document.documentElement.cancelDialog();
|
||||
}
|
||||
}
|
||||
else {
|
||||
window.document.documentElement.cancelDialog();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ok(false, "prompt type " + promptType + " not handled in test.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Install blocked handling
|
||||
|
||||
installDisabled: function(installInfo) {
|
||||
ok(!!this.installDisabledCallback, "Installation shouldn't have been disabled");
|
||||
if (this.installDisabledCallback)
|
||||
this.installDisabledCallback(installInfo);
|
||||
this.expectingCancelled = true;
|
||||
this.expectingCancelled = false;
|
||||
this.endTest();
|
||||
},
|
||||
|
||||
installCancelled: function(installInfo) {
|
||||
if (this.expectingCancelled)
|
||||
return;
|
||||
|
||||
ok(!!this.installCancelledCallback, "Installation shouldn't have been cancelled");
|
||||
if (this.installCancelledCallback)
|
||||
this.installCancelledCallback(installInfo);
|
||||
this.endTest();
|
||||
},
|
||||
|
||||
installOriginBlocked: function(installInfo) {
|
||||
ok(!!this.installOriginBlockedCallback, "Shouldn't have been blocked");
|
||||
if (this.installOriginBlockedCallback)
|
||||
this.installOriginBlockedCallback(installInfo);
|
||||
this.endTest();
|
||||
},
|
||||
|
||||
installBlocked: function(installInfo) {
|
||||
ok(!!this.installBlockedCallback, "Shouldn't have been blocked by the whitelist");
|
||||
if (this.installBlockedCallback && this.installBlockedCallback(installInfo)) {
|
||||
this.installBlockedCallback = null;
|
||||
installInfo.install();
|
||||
}
|
||||
else {
|
||||
this.expectingCancelled = true;
|
||||
installInfo.installs.forEach(function(install) {
|
||||
install.cancel();
|
||||
});
|
||||
this.expectingCancelled = false;
|
||||
this.endTest();
|
||||
}
|
||||
},
|
||||
|
||||
// nsIWindowMediatorListener
|
||||
|
||||
onWindowTitleChange: function(window, title) {
|
||||
},
|
||||
|
||||
onOpenWindow: function(window) {
|
||||
var domwindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindow);
|
||||
var self = this;
|
||||
waitForFocus(function() {
|
||||
self.windowReady(domwindow);
|
||||
}, domwindow);
|
||||
},
|
||||
|
||||
onCloseWindow: function(window) {
|
||||
},
|
||||
|
||||
// Addon Install Listener
|
||||
|
||||
onNewInstall: function(install) {
|
||||
this.runningInstalls.push(install);
|
||||
|
||||
if (this.finalContentEvent && !this.waitingForEvent) {
|
||||
this.waitingForEvent = true;
|
||||
info("Waiting for " + this.finalContentEvent);
|
||||
let mm = gBrowser.selectedBrowser.messageManager;
|
||||
mm.loadFrameScript(`data:,content.addEventListener("${this.finalContentEvent}", () => { sendAsyncMessage("Test:GotNewInstallEvent"); });`, false);
|
||||
let win = gBrowser.contentWindow;
|
||||
let listener = () => {
|
||||
info("Saw " + this.finalContentEvent);
|
||||
mm.removeMessageListener("Test:GotNewInstallEvent", listener);
|
||||
this.waitingForEvent = false;
|
||||
if (this.pendingCount == 0)
|
||||
this.endTest();
|
||||
}
|
||||
mm.addMessageListener("Test:GotNewInstallEvent", listener);
|
||||
}
|
||||
},
|
||||
|
||||
onDownloadStarted: function(install) {
|
||||
this.pendingCount++;
|
||||
if (this.downloadStartedCallback)
|
||||
this.downloadStartedCallback(install);
|
||||
},
|
||||
|
||||
onDownloadProgress: function(install) {
|
||||
if (this.downloadProgressCallback)
|
||||
this.downloadProgressCallback(install);
|
||||
},
|
||||
|
||||
onDownloadEnded: function(install) {
|
||||
if (this.downloadEndedCallback)
|
||||
this.downloadEndedCallback(install);
|
||||
},
|
||||
|
||||
onDownloadCancelled: function(install) {
|
||||
isnot(this.runningInstalls.indexOf(install), -1,
|
||||
"Should only see cancelations for started installs");
|
||||
this.runningInstalls.splice(this.runningInstalls.indexOf(install), 1);
|
||||
|
||||
if (this.downloadCancelledCallback)
|
||||
this.downloadCancelledCallback(install);
|
||||
this.checkTestEnded();
|
||||
},
|
||||
|
||||
onDownloadFailed: function(install) {
|
||||
if (this.downloadFailedCallback)
|
||||
this.downloadFailedCallback(install);
|
||||
this.checkTestEnded();
|
||||
},
|
||||
|
||||
onInstallStarted: function(install) {
|
||||
if (this.installStartedCallback)
|
||||
this.installStartedCallback(install);
|
||||
},
|
||||
|
||||
onInstallEnded: function(install, addon) {
|
||||
if (this.installEndedCallback)
|
||||
this.installEndedCallback(install, addon);
|
||||
this.installCount++;
|
||||
this.checkTestEnded();
|
||||
},
|
||||
|
||||
onInstallFailed: function(install) {
|
||||
if (this.installFailedCallback)
|
||||
this.installFailedCallback(install);
|
||||
this.checkTestEnded();
|
||||
},
|
||||
|
||||
checkTestEnded: function() {
|
||||
if (--this.pendingCount == 0 && !this.waitingForEvent)
|
||||
this.endTest();
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
var installInfo = subject.QueryInterface(Components.interfaces.amIWebInstallInfo);
|
||||
switch (topic) {
|
||||
case "addon-install-started":
|
||||
is(this.runningInstalls.length, installInfo.installs.length,
|
||||
"Should have seen the expected number of installs started");
|
||||
break;
|
||||
case "addon-install-disabled":
|
||||
this.installDisabled(installInfo);
|
||||
break;
|
||||
case "addon-install-cancelled":
|
||||
this.installCancelled(installInfo);
|
||||
break;
|
||||
case "addon-install-origin-blocked":
|
||||
this.installOriginBlocked(installInfo);
|
||||
break;
|
||||
case "addon-install-blocked":
|
||||
this.installBlocked(installInfo);
|
||||
break;
|
||||
case "addon-install-failed":
|
||||
installInfo.installs.forEach(function(aInstall) {
|
||||
isnot(this.runningInstalls.indexOf(aInstall), -1,
|
||||
"Should only see failures for started installs");
|
||||
|
||||
ok(aInstall.error != 0 || aInstall.addon.appDisabled,
|
||||
"Failed installs should have an error or be appDisabled");
|
||||
|
||||
this.runningInstalls.splice(this.runningInstalls.indexOf(aInstall), 1);
|
||||
}, this);
|
||||
break;
|
||||
case "addon-install-complete":
|
||||
installInfo.installs.forEach(function(aInstall) {
|
||||
isnot(this.runningInstalls.indexOf(aInstall), -1,
|
||||
"Should only see completed events for started installs");
|
||||
|
||||
is(aInstall.error, 0, "Completed installs should have no error");
|
||||
ok(!aInstall.appDisabled, "Completed installs should not be appDisabled");
|
||||
|
||||
// Complete installs are either in the INSTALLED or CANCELLED state
|
||||
// since the test may cancel installs the moment they complete.
|
||||
ok(aInstall.state == AddonManager.STATE_INSTALLED ||
|
||||
aInstall.state == AddonManager.STATE_CANCELLED,
|
||||
"Completed installs should be in the right state");
|
||||
|
||||
this.runningInstalls.splice(this.runningInstalls.indexOf(aInstall), 1);
|
||||
}, this);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
Ci.nsIWindowMediatorListener,
|
||||
Ci.nsISupports])
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue