gecko/xpinstall/tests/harness.js

258 lines
9.2 KiB
JavaScript
Raw Normal View History

const TESTROOT = "http://example.com/browser/xpinstall/tests/";
const TESTROOT2 = "http://example.org/browser/xpinstall/tests/";
const CHROMEROOT = "chrome://mochikit/content/browser/xpinstall/tests/"
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";
/**
* 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 install is expected to be 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 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 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,
listenerIndex: null,
// Setup and tear down functions
setup: function() {
waitForExplicitFinish();
var os = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
os.addObserver(this, "xpinstall-install-blocked", false);
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
wm.addListener(this);
var em = Components.classes["@mozilla.org/extensions/manager;1"]
.getService(Components.interfaces.nsIExtensionManager);
this.listenerIndex = em.addInstallListener(this);
},
finish: function() {
var os = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
os.removeObserver(this, "xpinstall-install-blocked");
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
wm.removeListener(this);
var win = wm.getMostRecentWindow("Extension:Manager");
if (win)
win.close();
var em = Components.classes["@mozilla.org/extensions/manager;1"]
.getService(Components.interfaces.nsIExtensionManager);
em.removeInstallListenerAt(this.listenerIndex);
finish();
},
endTest: function() {
// Defer the final notification to allow things like the InstallTrigger
// callback to complete
executeSoon(this.installsCompletedCallback);
this.installBlockedCallback = null;
this.authenticationCallback = null;
this.installConfirmCallback = null;
this.downloadStartedCallback = null;
this.downloadProgressCallback = null;
this.downloadEndedCallback = null;
this.installStartedCallback = null;
this.installEndedCallback = null;
this.installsCompletedCallback = null;
},
// Window open handling
windowLoad: function(window) {
// Allow any other load handlers to execute
var self = this;
executeSoon(function() { self.windowReady(window); } );
},
windowReady: function(window) {
if (window.document.location.href == XPINSTALL_URL) {
if (this.installBlockedCallback)
ok(false, "Should have been blocked by the whitelist");
// If there is a confirm callback then its return status determines whether
// to install the items or not. If not the test is over.
if (this.installConfirmCallback && !this.installConfirmCallback(window)) {
window.document.documentElement.cancelDialog();
this.endTest();
}
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) {
switch (window.gCommonDialogParam.GetInt(3)) {
case 0: if (window.opener.document.location.href == ADDONS_URL) {
// A prompt opened by the add-ons manager is liable to be an
// xpinstall error, just close it, we'll see the error in
// onInstallEnded anyway.
window.document.documentElement.acceptDialog();
}
break;
case 2: if (window.gCommonDialogParam.GetInt(4) != 1) {
// 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;
}
}
},
// Install blocked handling
installBlocked: function() {
// The browser should have a notification box animating now
var notificationBox = gBrowser.getNotificationBox(gBrowser.selectedBrowser);
var self = this;
this.waitForNotification(notificationBox, function() { self.notificationComplete() });
},
// This delays until a notification has finished animating it. It's a bit of a
// hack due to the timeout use but should be safe.
waitForNotification: function(notificationBox, callback) {
if (!notificationBox._timer) {
callback();
return;
}
setTimeout(arguments.callee, 50, notificationBox, callback);
},
notificationComplete: function() {
ok(!!this.installBlockedCallback, "Shouldn't have been blocked by the whitelist");
var notification = gBrowser.getNotificationBox(gBrowser.selectedBrowser)
.getNotificationWithValue("xpinstall");
if (this.installBlockedCallback && this.installBlockedCallback()) {
this.installBlockedCallback = null;
notification.firstChild.click();
}
else {
notification.close();
this.endTest();
}
},
// nsIWindowMediatorListener
onWindowTitleChange: function(window, title) {
},
onOpenWindow: function(window) {
var domwindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowInternal);
var self = this;
domwindow.addEventListener("load", function() {
self.windowLoad(domwindow);
}, false);
},
onCloseWindow: function(window) {
},
// nsIAddonInstallListener
onDownloadStarted: function(addon) {
if (this.downloadStartedCallback)
this.downloadStartedCallback(addon);
},
onDownloadProgress: function(addon, value, maxValue) {
if (this.downloadProgressCallback)
this.downloadProgressCallback(addon, value, maxValue);
},
onDownloadEnded: function(addon) {
if (this.downloadEndedCallback)
this.downloadEndedCallback(addon);
},
onInstallStarted: function(addon) {
if (this.installStartedCallback)
this.installStartedCallback(addon);
},
onCompatibilityCheckStarted: function(addon) {
},
onCompatibilityCheckEnded: function(addon, status) {
},
onInstallEnded: function(addon, status) {
if (this.installEndedCallback)
this.installEndedCallback(addon, status);
},
onInstallsCompleted: function() {
this.endTest();
},
// nsIObserver
observe: function(subject, topic, data) {
// Make sure the main UI has received the event too and so has started
// displaying the notification.
var self = this;
executeSoon(function() { self.installBlocked() });
},
QueryInterface: function(iid) {
if (iid.equals(Components.interfaces.nsIObserver) ||
iid.equals(Components.interfaces.nsIAddonInstallListener) ||
iid.equals(Components.interfaces.nsIWindowMediatorListener) ||
iid.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
}
}