Bug 1094312 - Fix browser_
bug553455.js:test_cancel_restart by pausing the download for long enough for the progress notification to show reliably. r=Gijs, a=sledru
test_cancel_restart needs the progress notification to show reliably so it can
cancel the pending install. To ensure this a sjs script is used to
asynchronously deliever the XPI data. It starts responding but sends no data
until a second request is made to tell it to complete. So the test can start
the install, then do what it likes with the progress dialog before finally
telling the server to complete the download for the install.
--- a/browser/base/content/test/general/browser_bug553455.js
+++ b/browser/base/content/test/general/browser_bug553455.js
@@ -665,82 +665,101 @@ function test_renotify_installed() {
var triggers = encodeURIComponent(JSON.stringify({
"XPI": "unsigned.xpi"
}));
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
},
-/*function test_cancel_restart() {
+function test_cancel_restart() {
+ function complete_install(callback) {
+ let url = TESTROOT + "slowinstall.sjs?continue=true"
+ NetUtil.asyncFetch(url, callback || (() => {}));
+ }
+
// Wait for the progress notification
wait_for_notification(PROGRESS_NOTIFICATION, function(aPanel) {
let notification = aPanel.childNodes[0];
// Close the notification
let anchor = document.getElementById("addons-notification-icon");
anchor.click();
// Reopen the notification
anchor.click();
ok(PopupNotifications.isPanelOpen, "Notification should still be open");
is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
isnot(notification, aPanel.childNodes[0], "Should have reconstructed the notification UI");
notification = aPanel.childNodes[0];
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
let button = document.getAnonymousElementByAttribute(notification, "anonid", "cancel");
- // Cancel the download
- EventUtils.synthesizeMouse(button, 2, 2, {});
+ // Wait for the install to fully cancel
+ let install = notification.notification.options.installs[0];
+ install.addListener({
+ onDownloadCancelled: function() {
+ install.removeListener(this);
- // Notification should have changed to cancelled
- notification = aPanel.childNodes[0];
- is(notification.id, "addon-install-cancelled-notification", "Should have seen the cancelled notification");
+ executeSoon(function() {
+ ok(PopupNotifications.isPanelOpen, "Notification should still be open");
+ is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
+ isnot(notification, aPanel.childNodes[0], "Should have reconstructed the notification UI");
+ notification = aPanel.childNodes[0];
+ is(notification.id, "addon-install-cancelled-notification", "Should have seen the cancelled notification");
+
+ // Wait for the install confirmation dialog
+ wait_for_install_dialog(function(aWindow) {
+ // Wait for the complete notification
+ wait_for_notification("addon-install-complete-notification", function(aPanel) {
+ let notification = aPanel.childNodes[0];
+ is(notification.button.label, "Restart Now", "Should have seen the right button");
+ is(notification.getAttribute("label"),
+ "XPI Test will be installed after you restart " + gApp + ".",
+ "Should have seen the right message");
- // Wait for the install confirmation dialog
- wait_for_install_dialog(function(aWindow) {
- // Wait for the complete notification
- wait_for_notification("addon-install-complete-notification", function(aPanel) {
- let notification = aPanel.childNodes[0];
- is(notification.button.label, "Restart Now", "Should have seen the right button");
- is(notification.getAttribute("label"),
- "XPI Test will be installed after you restart " + gApp + ".",
- "Should have seen the right message");
+ AddonManager.getAllInstalls(function(aInstalls) {
+ is(aInstalls.length, 1, "Should be one pending install");
+ aInstalls[0].cancel();
+
+ Services.perms.remove("example.com", "install");
+ wait_for_notification_close(runNextTest);
+ gBrowser.removeTab(gBrowser.selectedTab);
+ });
+ });
+
+ aWindow.document.documentElement.acceptDialog();
+ });
- AddonManager.getAllInstalls(function(aInstalls) {
- is(aInstalls.length, 1, "Should be one pending install");
- aInstalls[0].cancel();
+ // Restart the download
+ EventUtils.synthesizeMouseAtCenter(notification.button, {});
- Services.perms.remove("example.com", "install");
- wait_for_notification_close(runNextTest);
- gBrowser.removeTab(gBrowser.selectedTab);
+ // Should be back to a progress notification
+ ok(PopupNotifications.isPanelOpen, "Notification should still be open");
+ is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
+ notification = aPanel.childNodes[0];
+ is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
+
+ complete_install();
});
- });
-
- aWindow.document.documentElement.acceptDialog();
+ }
});
- // Restart the download
- EventUtils.synthesizeMouse(notification.button, 20, 10, {});
-
- // Should be back to a progress notification
- ok(PopupNotifications.isPanelOpen, "Notification should still be open");
- is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
- notification = aPanel.childNodes[0];
- is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
+ // Cancel the download
+ EventUtils.synthesizeMouseAtCenter(button, {});
});
var pm = Services.perms;
pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
var triggers = encodeURIComponent(JSON.stringify({
- "XPI": "unsigned.xpi"
+ "XPI": "slowinstall.sjs?file=unsigned.xpi"
}));
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
-},*/
+},
function test_failed_security() {
Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false);
setup_redirect({
"Location": TESTROOT + "unsigned.xpi"
});
--- a/toolkit/mozapps/extensions/test/xpinstall/browser.ini
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser.ini
@@ -19,16 +19,17 @@ support-files =
redirect.sjs
restartless.xpi
signed-no-cn.xpi
signed-no-o.xpi
signed-tampered.xpi
signed-untrusted.xpi
signed.xpi
signed2.xpi
+ slowinstall.sjs
startsoftwareupdate.html
theme.xpi
triggerredirect.html
unsigned.xpi
[browser_auth.js]
[browser_auth2.js]
[browser_auth3.js]
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpinstall/slowinstall.sjs
@@ -0,0 +1,101 @@
+const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/osfile.jsm");
+Cu.import("resource://gre/modules/NetUtil.jsm");
+
+const RELATIVE_PATH = "browser/toolkit/mozapps/extensions/test/xpinstall"
+const NOTIFICATION_TOPIC = "slowinstall-complete";
+
+/**
+ * Helper function to create a JS object representing the url parameters from
+ * the request's queryString.
+ *
+ * @param aQueryString
+ * The request's query string.
+ * @return A JS object representing the url parameters from the request's
+ * queryString.
+ */
+function parseQueryString(aQueryString) {
+ var paramArray = aQueryString.split("&");
+ var regex = /^([^=]+)=(.*)$/;
+ var params = {};
+ for (var i = 0, sz = paramArray.length; i < sz; i++) {
+ var match = regex.exec(paramArray[i]);
+ if (!match)
+ throw "Bad parameter in queryString! '" + paramArray[i] + "'";
+ params[decodeURIComponent(match[1])] = decodeURIComponent(match[2]);
+ }
+
+ return params;
+}
+
+function handleRequest(aRequest, aResponse) {
+ let id = +getState("ID");
+ setState("ID", "" + (id + 1));
+
+ function LOG(str) {
+ dump("slowinstall.sjs[" + id + "]: " + str + "\n");
+ }
+
+ aResponse.setStatusLine(aRequest.httpVersion, 200, "OK");
+
+ var params = { };
+ if (aRequest.queryString)
+ params = parseQueryString(aRequest.queryString);
+
+ if (params.file) {
+ let xpiFile = "";
+
+ function complete_download() {
+ LOG("Completing download");
+ downloadPaused = false;
+
+ try {
+ // Doesn't seem to be a sane way to read using OS.File and write to an
+ // nsIOutputStream so here we are.
+ let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
+ file.initWithPath(xpiFile);
+ let stream = Cc["@mozilla.org/network/file-input-stream;1"].
+ createInstance(Ci.nsIFileInputStream);
+ stream.init(file, -1, -1, stream.DEFER_OPEN + stream.CLOSE_ON_EOF);
+
+ NetUtil.asyncCopy(stream, aResponse.bodyOutputStream, () => {
+ LOG("Download complete");
+ aResponse.finish();
+ });
+ }
+ catch (e) {
+ LOG("Exception " + e);
+ }
+ }
+
+ let waitForComplete = new Promise(resolve => {
+ function complete() {
+ Services.obs.removeObserver(complete, NOTIFICATION_TOPIC);
+ resolve();
+ }
+
+ Services.obs.addObserver(complete, NOTIFICATION_TOPIC, false);
+ });
+
+ aResponse.processAsync();
+
+ OS.File.getCurrentDirectory().then(dir => {
+ xpiFile = OS.Path.join(dir, ...RELATIVE_PATH.split("/"), params.file);
+ LOG("Starting slow download of " + xpiFile);
+
+ OS.File.stat(xpiFile).then(info => {
+ aResponse.setHeader("Content-Type", "binary/octet-stream");
+ aResponse.setHeader("Content-Length", info.size.toString());
+
+ LOG("Download paused");
+ waitForComplete.then(complete_download);
+ });
+ });
+ }
+ else if (params.continue) {
+ dump("slowinstall.sjs: Received signal to complete all current downloads.\n");
+ Services.obs.notifyObservers(null, NOTIFICATION_TOPIC, null);
+ }
+}