diff options
Diffstat (limited to 'toolkit/mozapps/webextensions/test/xpinstall')
105 files changed, 4012 insertions, 0 deletions
diff --git a/toolkit/mozapps/webextensions/test/xpinstall/.eslintrc.js b/toolkit/mozapps/webextensions/test/xpinstall/.eslintrc.js new file mode 100644 index 000000000..2852eb81d --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/.eslintrc.js @@ -0,0 +1,7 @@ +"use strict"; + +module.exports = { // eslint-disable-line no-undef + "extends": [ + "../../../../../testing/mochitest/browser.eslintrc.js" + ] +}; diff --git a/toolkit/mozapps/webextensions/test/xpinstall/amosigned.xpi b/toolkit/mozapps/webextensions/test/xpinstall/amosigned.xpi Binary files differnew file mode 100644 index 000000000..4edf91e34 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/amosigned.xpi diff --git a/toolkit/mozapps/webextensions/test/xpinstall/amosigned2.xpi b/toolkit/mozapps/webextensions/test/xpinstall/amosigned2.xpi Binary files differnew file mode 100644 index 000000000..74e877f26 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/amosigned2.xpi diff --git a/toolkit/mozapps/webextensions/test/xpinstall/authRedirect.sjs b/toolkit/mozapps/webextensions/test/xpinstall/authRedirect.sjs new file mode 100644 index 000000000..85d448e2b --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/authRedirect.sjs @@ -0,0 +1,21 @@ +// Simple script redirects to the query part of the uri if the browser +// authenticates with username "testuser" password "testpass" + +function handleRequest(request, response) { + if (request.hasHeader("Authorization")) { + if (request.getHeader("Authorization") == "Basic dGVzdHVzZXI6dGVzdHBhc3M=") { + response.setStatusLine(request.httpVersion, 302, "Found"); + response.setHeader("Location", request.queryString); + response.write("See " + request.queryString); + } + else { + response.setStatusLine(request.httpVersion, 403, "Forbidden"); + response.write("Invalid credentials"); + } + } + else { + response.setStatusLine(request.httpVersion, 401, "Authentication required"); + response.setHeader("WWW-Authenticate", "basic realm=\"XPInstall\"", false); + response.write("Unauthenticated request"); + } +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser.ini b/toolkit/mozapps/webextensions/test/xpinstall/browser.ini new file mode 100644 index 000000000..5627f47a2 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser.ini @@ -0,0 +1,119 @@ +[DEFAULT] +support-files = + amosigned.xpi + amosigned2.xpi + authRedirect.sjs + bug540558.html + bug638292.html + bug645699.html + concurrent_installs.html + cookieRedirect.sjs + corrupt.xpi + empty.xpi + enabled.html + hashRedirect.sjs + head.js + incompatible.xpi + installchrome.html + installtrigger.html + installtrigger_frame.html + multipackage.xpi + navigate.html + redirect.sjs + restartless.xpi + restartless-unsigned.xpi + signed-multipackage.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_amosigned_trigger.js] +[browser_amosigned_trigger_iframe.js] +[browser_amosigned_url.js] +[browser_auth.js] +[browser_auth2.js] +[browser_auth3.js] +[browser_auth4.js] +[browser_badargs.js] +[browser_badargs2.js] +[browser_badhash.js] +[browser_badhashtype.js] +[browser_bug540558.js] +[browser_bug611242.js] +[browser_bug638292.js] +[browser_bug645699.js] +[browser_bug672485.js] +skip-if = true # disabled due to a leak. See bug 682410. +[browser_cancel.js] +[browser_concurrent_installs.js] +[browser_cookies.js] +[browser_cookies2.js] +[browser_cookies3.js] +[browser_cookies4.js] +skip-if = true # Bug 1084646 +[browser_corrupt.js] +[browser_datauri.js] +[browser_empty.js] +[browser_enabled.js] +[browser_enabled2.js] +[browser_enabled3.js] +[browser_hash.js] +[browser_hash2.js] +[browser_httphash.js] +[browser_httphash2.js] +[browser_httphash3.js] +[browser_httphash4.js] +[browser_httphash5.js] +[browser_httphash6.js] +[browser_installchrome.js] +[browser_localfile.js] +[browser_localfile2.js] +[browser_localfile3.js] +[browser_localfile4.js] +[browser_multipackage.js] +[browser_navigateaway.js] +[browser_navigateaway2.js] +[browser_navigateaway3.js] +skip-if = (os == "mac" || os == "win") # Bug 1198261 +[browser_navigateaway4.js] +[browser_offline.js] +[browser_relative.js] +[browser_signed_multipackage.js] +skip-if = require_signing +[browser_signed_multiple.js] +skip-if = require_signing +[browser_signed_naming.js] +skip-if = require_signing +[browser_signed_tampered.js] +skip-if = require_signing +[browser_signed_trigger.js] +skip-if = require_signing +[browser_signed_untrusted.js] +skip-if = require_signing +[browser_signed_url.js] +skip-if = require_signing +[browser_softwareupdate.js] +[browser_switchtab.js] +[browser_trigger_redirect.js] +[browser_unsigned_trigger.js] +skip-if = require_signing +[browser_unsigned_trigger_iframe.js] +skip-if = require_signing +[browser_unsigned_trigger_xorigin.js] +[browser_unsigned_url.js] +skip-if = require_signing +[browser_whitelist.js] +[browser_whitelist2.js] +[browser_whitelist3.js] +[browser_whitelist4.js] +[browser_whitelist5.js] +[browser_whitelist6.js] +[browser_whitelist7.js] diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_amosigned_trigger.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_amosigned_trigger.js new file mode 100644 index 000000000..d61ef7362 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_amosigned_trigger.js @@ -0,0 +1,56 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through an InstallTrigger call in web +// content. +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.finalContentEvent = "InstallComplete"; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: TESTROOT + "amosigned.xpi", + IconURL: TESTROOT + "icon.png", + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function confirm_install(window) { + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "XPI Test", "Should have seen the name"); + is(items[0].url, TESTROOT + "amosigned.xpi", "Should have listed the correct url for the item"); + is(items[0].icon, TESTROOT + "icon.png", "Should have listed the correct icon for the item"); + is(items[0].signed, "false", "Should have listed the item as unsigned"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +const finish_test = Task.async(function*(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + const results = yield ContentTask.spawn(gBrowser.selectedBrowser, null, () => { + return { + return: content.document.getElementById("return").textContent, + status: content.document.getElementById("status").textContent, + } + }) + + is(results.return, "true", "installTrigger should have claimed success"); + is(results.status, "0", "Callback should have seen a success"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +}); diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_amosigned_trigger_iframe.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_amosigned_trigger_iframe.js new file mode 100644 index 000000000..66564afaa --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_amosigned_trigger_iframe.js @@ -0,0 +1,57 @@ +// ---------------------------------------------------------------------------- +// Test for bug 589598 - Ensure that installing through InstallTrigger +// works in an iframe in web content. + +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.finalContentEvent = "InstallComplete"; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var inner_url = encodeURIComponent(TESTROOT + "installtrigger.html?" + encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: TESTROOT + "amosigned.xpi", + IconURL: TESTROOT + "icon.png", + toString: function() { return this.URL; } + } + }))); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger_frame.html?" + inner_url); +} + +function confirm_install(window) { + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "XPI Test", "Should have seen the name"); + is(items[0].url, TESTROOT + "amosigned.xpi", "Should have listed the correct url for the item"); + is(items[0].icon, TESTROOT + "icon.png", "Should have listed the correct icon for the item"); + is(items[0].signed, "false", "Should have listed the item as unsigned"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +const finish_test = Task.async(function*(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + const results = yield ContentTask.spawn(gBrowser.selectedBrowser, null, () => { + return { + return: content.frames[0].document.getElementById("return").textContent, + status: content.frames[0].document.getElementById("status").textContent, + } + }) + + is(results.return, "true", "installTrigger in iframe should have claimed success"); + is(results.status, "0", "Callback in iframe should have seen a success"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +}); diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_amosigned_url.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_amosigned_url.js new file mode 100644 index 000000000..f6c39b7bb --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_amosigned_url.js @@ -0,0 +1,35 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on by navigating directly to the url +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + gBrowser.selectedTab = gBrowser.addTab("about:blank"); + BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => { + gBrowser.loadURI(TESTROOT + "amosigned.xpi"); + }); +} + +function confirm_install(window) { + let items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "XPI Test", "Should have had the filename for the item name"); + is(items[0].url, TESTROOT + "amosigned.xpi", "Should have listed the correct url for the item"); + is(items[0].icon, "", "Should have listed no icon for the item"); + is(items[0].signed, "false", "Should have listed the item as unsigned"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_auth.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_auth.js new file mode 100644 index 000000000..1bfa7696f --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_auth.js @@ -0,0 +1,47 @@ +// ---------------------------------------------------------------------------- +// Test whether an install succeeds when authentication is required +// This verifies bug 312473 +function test() { + Harness.authenticationCallback = get_auth_info; + Harness.downloadFailedCallback = download_failed; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var prefs = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefBranch); + prefs.setIntPref("network.auth.subresource-http-auth-allow", 2); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "authRedirect.sjs?" + TESTROOT + "amosigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function get_auth_info() { + return [ "testuser", "testpass" ]; +} + +function download_failed(install) { + ok(false, "Install should not have failed"); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + var authMgr = Components.classes['@mozilla.org/network/http-auth-manager;1'] + .getService(Components.interfaces.nsIHttpAuthManager); + authMgr.clearAll(); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_auth2.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_auth2.js new file mode 100644 index 000000000..80942a9f4 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_auth2.js @@ -0,0 +1,46 @@ +// ---------------------------------------------------------------------------- +// Test whether an install fails when authentication is required and bad +// credentials are given +// This verifies bug 312473 +function test() { + requestLongerTimeout(2); + Harness.authenticationCallback = get_auth_info; + Harness.downloadFailedCallback = download_failed; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "authRedirect.sjs?" + TESTROOT + "amosigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function get_auth_info() { + return [ "baduser", "badpass" ]; +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_NETWORK_FAILURE, "Install should have failed"); +} + +function install_ended(install, addon) { + ok(false, "Add-on should not have installed"); + install.cancel(); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + var authMgr = Components.classes['@mozilla.org/network/http-auth-manager;1'] + .getService(Components.interfaces.nsIHttpAuthManager); + authMgr.clearAll(); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_auth3.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_auth3.js new file mode 100644 index 000000000..4973a1b35 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_auth3.js @@ -0,0 +1,53 @@ +// ---------------------------------------------------------------------------- +// Test whether an install fails when authentication is required and it is +// canceled +// This verifies bug 312473 + +// +// Whitelisting this test. +// As part of bug 1077403, the leaking uncaught rejection should be fixed. +// +thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: this.docShell is null"); + + +function test() { + Harness.authenticationCallback = get_auth_info; + Harness.downloadFailedCallback = download_failed; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "authRedirect.sjs?" + TESTROOT + "amosigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function get_auth_info() { + return null; +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_NETWORK_FAILURE, "Install should have failed"); +} + +function install_ended(install, addon) { + ok(false, "Add-on should not have installed"); + install.cancel(); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + var authMgr = Components.classes['@mozilla.org/network/http-auth-manager;1'] + .getService(Components.interfaces.nsIHttpAuthManager); + authMgr.clearAll(); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_auth4.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_auth4.js new file mode 100644 index 000000000..a3157961d --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_auth4.js @@ -0,0 +1,52 @@ +// +// Whitelisting this test. +// As part of bug 1077403, the leaking uncaught rejection should be fixed. +// +thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: this.docShell is null"); + + +// ---------------------------------------------------------------------------- +// Test whether a request for auth for an XPI switches to the appropriate tab +var gNewTab; + +function test() { + Harness.authenticationCallback = get_auth_info; + Harness.downloadFailedCallback = download_failed; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "authRedirect.sjs?" + TESTROOT + "amosigned.xpi" + })); + gNewTab = gBrowser.addTab(); + gBrowser.getBrowserForTab(gNewTab).loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function get_auth_info() { + is(gBrowser.selectedTab, gNewTab, "Should have focused the tab loading the XPI"); + return [ "testuser", "testpass" ]; +} + +function download_failed(install) { + ok(false, "Install should not have failed"); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + var authMgr = Components.classes['@mozilla.org/network/http-auth-manager;1'] + .getService(Components.interfaces.nsIHttpAuthManager); + authMgr.clearAll(); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeTab(gNewTab); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_badargs.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_badargs.js new file mode 100644 index 000000000..b4b1110b0 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_badargs.js @@ -0,0 +1,38 @@ +// ---------------------------------------------------------------------------- +// Test whether passing a simple string to InstallTrigger.install throws an +// exception +function test() { + waitForExplicitFinish(); + + var triggers = encodeURIComponent(JSON.stringify(TESTROOT + "amosigned.xpi")); + gBrowser.selectedTab = gBrowser.addTab(); + + ContentTask.spawn(gBrowser.selectedBrowser, null, function() { + return new Promise(resolve => { + addEventListener("load", () => { + content.addEventListener("InstallTriggered", () => { + resolve(content.document.getElementById("return").textContent); + }); + }, true); + }); + }).then(page_loaded); + + // In non-e10s the exception in the content page would trigger a test failure + if (!gMultiProcessBrowser) + expectUncaughtException(); + + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function page_loaded(result) { + is(result, "exception", "installTrigger should have failed"); + + // In non-e10s the exception from the page is thrown after the event so we + // have to spin the event loop to make sure it arrives so expectUncaughtException + // sees it. + executeSoon(() => { + gBrowser.removeCurrentTab(); + finish(); + }); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_badargs2.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_badargs2.js new file mode 100644 index 000000000..7137df318 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_badargs2.js @@ -0,0 +1,42 @@ +// ---------------------------------------------------------------------------- +// Test whether passing an undefined url InstallTrigger.install throws an +// exception +function test() { + waitForExplicitFinish(); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: undefined + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + + ContentTask.spawn(gBrowser.selectedBrowser, null, function() { + return new Promise(resolve => { + addEventListener("load", () => { + content.addEventListener("InstallTriggered", () => { + resolve(content.document.getElementById("return").textContent); + }); + }, true); + }); + }).then(page_loaded); + + // In non-e10s the exception in the content page would trigger a test failure + if (!gMultiProcessBrowser) + expectUncaughtException(); + + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function page_loaded(result) { + is(result, "exception", "installTrigger should have failed"); + + // In non-e10s the exception from the page is thrown after the event so we + // have to spin the event loop to make sure it arrives so expectUncaughtException + // sees it. + executeSoon(() => { + gBrowser.removeCurrentTab(); + finish(); + }); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_badhash.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_badhash.js new file mode 100644 index 000000000..9a26a77e4 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_badhash.js @@ -0,0 +1,33 @@ +// ---------------------------------------------------------------------------- +// Test whether an install fails when an invalid hash is included +// This verifies bug 302284 +function test() { + Harness.downloadFailedCallback = download_failed; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: TESTROOT + "amosigned.xpi", + Hash: "sha1:643b08418599ddbd1ea8a511c90696578fb844b9", + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_INCORRECT_HASH, "Install should fail"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + Services.perms.remove(makeURI("http://example.com/"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_badhashtype.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_badhashtype.js new file mode 100644 index 000000000..a9de9e4f0 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_badhashtype.js @@ -0,0 +1,33 @@ +// ---------------------------------------------------------------------------- +// Test whether an install fails when an unknown hash type is included +// This verifies bug 302284 +function test() { + Harness.downloadFailedCallback = download_failed; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: TESTROOT + "amosigned.xpi", + Hash: "foo:3d0dc22e1f394e159b08aaf5f0f97de4d5c65f4f", + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_INCORRECT_HASH, "Install should fail"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + Services.perms.remove(makeURI("http://example.com/"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_bug540558.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_bug540558.js new file mode 100644 index 000000000..4e7e20717 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_bug540558.js @@ -0,0 +1,25 @@ +// ---------------------------------------------------------------------------- +// Tests that calling InstallTrigger.installChrome works +function test() { + Harness.installEndedCallback = check_xpi_install; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "bug540558.html"); +} + +function check_xpi_install(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_bug611242.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_bug611242.js new file mode 100644 index 000000000..4f3cd087f --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_bug611242.js @@ -0,0 +1,17 @@ +// ---------------------------------------------------------------------------- +// Test whether setting a new property in InstallTrigger then persists to other +// page loads +add_task(function* test() { + yield BrowserTestUtils.withNewTab({ gBrowser, url: TESTROOT + "enabled.html" }, function* (browser) { + yield ContentTask.spawn(browser, null, () => { + content.wrappedJSObject.InstallTrigger.enabled.k = function() { }; + }); + + BrowserTestUtils.loadURI(browser, TESTROOT2 + "enabled.html"); + yield BrowserTestUtils.browserLoaded(browser); + yield ContentTask.spawn(browser, null, () => { + is(content.wrappedJSObject.InstallTrigger.enabled.k, undefined, "Property should not be defined"); + }); + }); +}); +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_bug638292.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_bug638292.js new file mode 100644 index 000000000..0d96e7cbe --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_bug638292.js @@ -0,0 +1,40 @@ +// ---------------------------------------------------------------------------- +// Test whether an InstallTrigger.enabled is working +add_task(function * () +{ + let testtab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, TESTROOT + "bug638292.html"); + + function* verify(link, button) + { + info("Clicking " + link); + + let waitForNewTabPromise = BrowserTestUtils.waitForNewTab(gBrowser); + + yield BrowserTestUtils.synthesizeMouseAtCenter("#" + link, { button: button }, + gBrowser.selectedBrowser); + + let newtab = yield waitForNewTabPromise; + + yield BrowserTestUtils.browserLoaded(newtab.linkedBrowser); + + let result = yield ContentTask.spawn(newtab.linkedBrowser, { }, function* () { + return (content.document.getElementById("enabled").textContent == "true"); + }); + + ok(result, "installTrigger for " + link + " should have been enabled"); + + // Focus the old tab (link3 is opened in the background) + if (link != "link3") { + yield BrowserTestUtils.switchTab(gBrowser, testtab); + } + gBrowser.removeTab(newtab); + } + + yield* verify("link1", 0); + yield* verify("link2", 0); + yield* verify("link3", 1); + + gBrowser.removeCurrentTab(); +}); + + diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_bug645699.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_bug645699.js new file mode 100644 index 000000000..f32d2c9d2 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_bug645699.js @@ -0,0 +1,36 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through an InstallTrigger call in web +// content. This should be blocked by the whitelist check. +// This verifies bug 645699 +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installBlockedCallback = allow_blocked; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.org/"), "install", pm.ALLOW_ACTION); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "bug645699.html"); +} + +function allow_blocked(installInfo) { + is(installInfo.browser, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); + is(installInfo.originatingURI.spec, gBrowser.currentURI.spec, "Install should have been triggered by the right uri"); + return false; +} + +function confirm_install(window) { + ok(false, "Should not see the install dialog"); + return false; +} + +function finish_test(count) { + is(count, 0, "0 Add-ons should have been successfully installed"); + Services.perms.remove(makeURI("http://addons.mozilla.org"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_bug672485.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_bug672485.js new file mode 100644 index 000000000..81d89c025 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_bug672485.js @@ -0,0 +1,52 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +var gWindowWatcher = null; + +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installCancelledCallback = cancelled_install; + Harness.installEndedCallback = complete_install; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + gWindowWatcher = Services.ww; + delete Services.ww; + is(Services.ww, undefined, "Services.ww should now be undefined"); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "amosigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function confirm_install(window) { + ok(false, "Should not see the install dialog"); + return false; +} + +function cancelled_install() { + ok(true, "Install should b cancelled"); +} + +function complete_install() { + ok(false, "Install should not have completed"); + return false; +} + +function finish_test(count) { + is(count, 0, "0 Add-ons should have been successfully installed"); + + gBrowser.removeCurrentTab(); + + Services.ww = gWindowWatcher; + + Services.perms.remove(makeURI("http://example.com"), "install"); + + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_cancel.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_cancel.js new file mode 100644 index 000000000..e30d7a0e5 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_cancel.js @@ -0,0 +1,60 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// ---------------------------------------------------------------------------- +// Tests that cancelling multiple installs doesn't fail +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "amosigned.xpi", + "Unsigned XPI 2": TESTROOT + "amosigned2.xpi", + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function get_item(items, url) { + for (let item of items) { + if (item.url == url) + return item; + } + ok(false, "Item for " + url + " was not listed"); + return null; +} + +function confirm_install(window) { + let items = window.document.getElementById("itemList").childNodes; + is(items.length, 2, "Should be 2 items listed in the confirmation dialog"); + let item = get_item(items, TESTROOT + "amosigned.xpi"); + if (item) { + is(item.name, "XPI Test", "Should have seen the name from the trigger list"); + is(item.signed, "false", "Should have listed the item as signed"); + } + item = get_item(items, TESTROOT + "amosigned2.xpi"); + if (item) { + is(item.name, "Signed XPI Test", "Should have seen the name from the trigger list"); + is(item.signed, "false", "Should have listed the item as signed"); + } + return false; +} + +function install_ended(install, addon) { + ok(false, "Should not have seen installs complete"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_concurrent_installs.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_concurrent_installs.js new file mode 100644 index 000000000..bf919d89c --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_concurrent_installs.js @@ -0,0 +1,127 @@ +// Test that having two frames that request installs at the same time doesn't +// cause callback ID conflicts (discussed in bug 926712) + +var gConcurrentTabs = []; +var gQueuedForInstall = []; +var gResults = []; + +function frame_script() { + /* globals addMessageListener, sendAsyncMessage*/ + addMessageListener("Test:StartInstall", () => { + content.document.getElementById("installnow").click() + }); + + addEventListener("load", () => { + sendAsyncMessage("Test:Loaded"); + + content.addEventListener("InstallComplete", (e) => { + sendAsyncMessage("Test:InstallComplete", e.detail); + }, true); + }, true); +} + +var gAddonAndWindowListener = { + onOpenWindow: function(win) { + var window = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow); + info("Window opened"); + + waitForFocus(function() { + info("Focused!"); + // Initially the accept button is disabled on a countdown timer + let button = window.document.documentElement.getButton("accept"); + button.disabled = false; + if (gQueuedForInstall.length > 0) { + // Start downloading the next add-on while we accept this dialog: + installNext(); + } + window.document.documentElement.acceptDialog(); + }, window); + }, + onCloseWindow: function(win) { }, + onInstallEnded: function(install) { + install.cancel(); + }, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIWindowMediatorListener]) +}; + +function installNext() { + let tab = gQueuedForInstall.shift(); + tab.linkedBrowser.messageManager.sendAsyncMessage("Test:StartInstall"); +} + +function winForTab(t) { + return t.linkedBrowser.contentWindow; +} + +function createTab(url) { + let tab = gBrowser.addTab(url); + tab.linkedBrowser.messageManager.loadFrameScript("data:,(" + frame_script.toString() + ")();", true); + + tab.linkedBrowser.messageManager.addMessageListener("Test:InstallComplete", ({data}) => { + gResults.push(data); + if (gResults.length == 2) { + executeSoon(endThisTest); + } + }); + + return tab; +} + +function test() { + waitForExplicitFinish(); + + Services.prefs.setBoolPref(PREF_LOGGING_ENABLED, true); + Services.prefs.setBoolPref(PREF_INSTALL_REQUIRESECUREORIGIN, false); + Services.wm.addListener(gAddonAndWindowListener); + AddonManager.addInstallListener(gAddonAndWindowListener); + registerCleanupFunction(function() { + Services.wm.removeListener(gAddonAndWindowListener); + AddonManager.removeInstallListener(gAddonAndWindowListener); + Services.prefs.clearUserPref(PREF_LOGGING_ENABLED); + Services.prefs.clearUserPref(PREF_INSTALL_REQUIRESECUREORIGIN); + + Services.perms.remove(makeURI("http://example.com"), "install"); + Services.perms.remove(makeURI("http://example.org"), "install"); + + while (gConcurrentTabs.length) { + gBrowser.removeTab(gConcurrentTabs.shift()); + } + }); + + let pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + pm.add(makeURI("http://example.org/"), "install", pm.ALLOW_ACTION); + + gConcurrentTabs.push(createTab(TESTROOT + "concurrent_installs.html")); + gConcurrentTabs.push(createTab(TESTROOT2 + "concurrent_installs.html")); + + let promises = gConcurrentTabs.map((t) => { + return new Promise(resolve => { + t.linkedBrowser.messageManager.addMessageListener("Test:Loaded", resolve); + }); + }); + + Promise.all(promises).then(() => { + gQueuedForInstall = [...gConcurrentTabs]; + installNext(); + }); +} + +function endThisTest() { + is(gResults.length, 2, "Should have two urls"); + isnot(gResults[0].loc, gResults[1].loc, "Should not have results from the same page."); + isnot(gResults[0].xpi, gResults[1].xpi, "Should not have the same XPIs."); + for (let i = 0; i < 2; i++) { + let {loc, xpi} = gResults[i]; + if (loc.includes("example.org")) { + ok(xpi.includes("example.org"), "Should get .org XPI for .org loc"); + } else if (loc.includes("example.com")) { + ok(xpi.includes("example.com"), "Should get .com XPI for .com loc"); + } else { + ok(false, "Should never get anything that isn't from example.org or example.com"); + } + } + + finish(); +} + diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_cookies.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_cookies.js new file mode 100644 index 000000000..541ac8333 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_cookies.js @@ -0,0 +1,30 @@ +// ---------------------------------------------------------------------------- +// Test that an install that requires cookies to be sent fails when no cookies +// are set +// This verifies bug 462739 +function test() { + Harness.downloadFailedCallback = download_failed; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Cookie check": TESTROOT + "cookieRedirect.sjs?" + TESTROOT + "amosigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_NETWORK_FAILURE, "Install should fail"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_cookies2.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_cookies2.js new file mode 100644 index 000000000..1ef2b482f --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_cookies2.js @@ -0,0 +1,40 @@ +// ---------------------------------------------------------------------------- +// Test that an install that requires cookies to be sent succeeds when cookies +// are set +// This verifies bug 462739 +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var cm = Components.classes["@mozilla.org/cookiemanager;1"] + .getService(Components.interfaces.nsICookieManager2); + cm.add("example.com", "/browser/" + RELATIVE_DIR, "xpinstall", "true", false, + false, true, (Date.now() / 1000) + 60, {}); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Cookie check": TESTROOT + "cookieRedirect.sjs?" + TESTROOT + "amosigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + var cm = Components.classes["@mozilla.org/cookiemanager;1"] + .getService(Components.interfaces.nsICookieManager2); + cm.remove("example.com", "xpinstall", "/browser/" + RELATIVE_DIR, false, {}); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_cookies3.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_cookies3.js new file mode 100644 index 000000000..833562d15 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_cookies3.js @@ -0,0 +1,44 @@ +// ---------------------------------------------------------------------------- +// Test that an install that requires cookies to be sent succeeds when cookies +// are set and third party cookies are disabled. +// This verifies bug 462739 +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var cm = Components.classes["@mozilla.org/cookiemanager;1"] + .getService(Components.interfaces.nsICookieManager2); + cm.add("example.com", "/browser/" + RELATIVE_DIR, "xpinstall", "true", false, + false, true, (Date.now() / 1000) + 60, {}); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + Services.prefs.setIntPref("network.cookie.cookieBehavior", 1); + + var triggers = encodeURIComponent(JSON.stringify({ + "Cookie check": TESTROOT + "cookieRedirect.sjs?" + TESTROOT + "amosigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + var cm = Components.classes["@mozilla.org/cookiemanager;1"] + .getService(Components.interfaces.nsICookieManager2); + cm.remove("example.com", "xpinstall", "/browser/" + RELATIVE_DIR, false, {}); + + Services.prefs.clearUserPref("network.cookie.cookieBehavior"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_cookies4.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_cookies4.js new file mode 100644 index 000000000..792146c64 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_cookies4.js @@ -0,0 +1,43 @@ +// ---------------------------------------------------------------------------- +// Test that an install that requires cookies to be sent fails when cookies +// are set and third party cookies are disabled and the request is to a third +// party. +// This verifies bug 462739 +function test() { + Harness.downloadFailedCallback = download_failed; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var cm = Components.classes["@mozilla.org/cookiemanager;1"] + .getService(Components.interfaces.nsICookieManager2); + cm.add("example.org", "/browser/" + RELATIVE_DIR, "xpinstall", "true", false, + false, true, (Date.now() / 1000) + 60, {}); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + Services.prefs.setIntPref("network.cookie.cookieBehavior", 1); + + var triggers = encodeURIComponent(JSON.stringify({ + "Cookie check": TESTROOT2 + "cookieRedirect.sjs?" + TESTROOT + "amosigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_NETWORK_FAILURE, "Install should fail"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + var cm = Components.classes["@mozilla.org/cookiemanager;1"] + .getService(Components.interfaces.nsICookieManager2); + cm.remove("example.org", "xpinstall", "/browser/" + RELATIVE_DIR, false, {}); + + Services.prefs.clearUserPref("network.cookie.cookieBehavior"); + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_corrupt.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_corrupt.js new file mode 100644 index 000000000..bd4d27fb0 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_corrupt.js @@ -0,0 +1,38 @@ +// ---------------------------------------------------------------------------- +// Test whether an install fails when the xpi is corrupt. +function test() { + Harness.downloadFailedCallback = download_failed; + Harness.installsCompletedCallback = finish_test; + Harness.finalContentEvent = "InstallComplete"; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Corrupt XPI": TESTROOT + "corrupt.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_CORRUPT_FILE, "Install should fail"); +} + +const finish_test = Task.async(function*(count) { + is(count, 0, "No add-ons should have been installed"); + Services.perms.remove(makeURI("http://example.com"), "install"); + + const results = yield ContentTask.spawn(gBrowser.selectedBrowser, null, () => { + return { + return: content.document.getElementById("return").textContent, + status: content.document.getElementById("status").textContent, + } + }) + + is(results.status, "-207", "Callback should have seen the failure"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +}); diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_datauri.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_datauri.js new file mode 100644 index 000000000..a8bdbde39 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_datauri.js @@ -0,0 +1,37 @@ +// ---------------------------------------------------------------------------- +// Checks that a chained redirect through a data URI and javascript is blocked + +function setup_redirect(aSettings) { + var url = TESTROOT + "redirect.sjs?mode=setup"; + for (var name in aSettings) { + url += "&" + name + "=" + encodeURIComponent(aSettings[name]); + } + + var req = new XMLHttpRequest(); + req.open("GET", url, false); + req.send(null); +} + +function test() { + Harness.installOriginBlockedCallback = install_blocked; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + setup_redirect({ + "Location": "data:text/html,<script>window.location.href='" + TESTROOT + "amosigned.xpi'</script>" + }); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "redirect.sjs?mode=redirect"); +} + +function install_blocked(installInfo) { +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_empty.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_empty.js new file mode 100644 index 000000000..64ca5e6b9 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_empty.js @@ -0,0 +1,28 @@ +// ---------------------------------------------------------------------------- +// Test whether an install fails when there is no install script present. +function test() { + Harness.downloadFailedCallback = download_failed; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Empty XPI": TESTROOT + "empty.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_CORRUPT_FILE, "Install should fail"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_enabled.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_enabled.js new file mode 100644 index 000000000..adbec9499 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_enabled.js @@ -0,0 +1,29 @@ +// ---------------------------------------------------------------------------- +// Test whether an InstallTrigger.enabled is working +function test() { + waitForExplicitFinish(); + + gBrowser.selectedTab = gBrowser.addTab(); + + ContentTask.spawn(gBrowser.selectedBrowser, TESTROOT + "enabled.html", function (url) { + return new Promise(resolve => { + function page_loaded() { + content.removeEventListener("PageLoaded", page_loaded, false); + resolve(content.document.getElementById("enabled").textContent); + } + + function load_listener() { + removeEventListener("load", load_listener, true); + content.addEventListener("PageLoaded", page_loaded, false); + } + + addEventListener("load", load_listener, true); + + content.location.href = url; + }); + }).then(text => { + is(text, "true", "installTrigger should have been enabled"); + gBrowser.removeCurrentTab(); + finish(); + }); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_enabled2.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_enabled2.js new file mode 100644 index 000000000..cc1b8a8b2 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_enabled2.js @@ -0,0 +1,32 @@ +// ---------------------------------------------------------------------------- +// Test whether an InstallTrigger.enabled is working +function test() { + waitForExplicitFinish(); + + Services.prefs.setBoolPref("xpinstall.enabled", false); + + gBrowser.selectedTab = gBrowser.addTab(); + + ContentTask.spawn(gBrowser.selectedBrowser, TESTROOT + "enabled.html", function (url) { + return new Promise(resolve => { + function page_loaded() { + content.removeEventListener("PageLoaded", page_loaded, false); + resolve(content.document.getElementById("enabled").textContent); + } + + function load_listener() { + removeEventListener("load", load_listener, true); + content.addEventListener("PageLoaded", page_loaded, false); + } + + addEventListener("load", load_listener, true); + + content.location.href = url; + }); + }).then(text => { + is(text, "false", "installTrigger should have not been enabled"); + Services.prefs.clearUserPref("xpinstall.enabled"); + gBrowser.removeCurrentTab(); + finish(); + }); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_enabled3.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_enabled3.js new file mode 100644 index 000000000..15bad4ba9 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_enabled3.js @@ -0,0 +1,52 @@ +// ---------------------------------------------------------------------------- +// Test whether an InstallTrigger.install call fails when xpinstall is disabled +function test() { + Harness.installDisabledCallback = install_disabled; + Harness.installBlockedCallback = allow_blocked; + Harness.installConfirmCallback = confirm_install; + Harness.setup(); + + Services.prefs.setBoolPref("xpinstall.enabled", false); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "amosigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + + ContentTask.spawn(gBrowser.selectedBrowser, TESTROOT + "installtrigger.html?" + triggers, url => { + return new Promise(resolve => { + function page_loaded() { + content.removeEventListener("PageLoaded", page_loaded, false); + resolve(content.document.getElementById("return").textContent); + } + + function load_listener() { + removeEventListener("load", load_listener, true); + content.addEventListener("InstallTriggered", page_loaded, false); + } + + addEventListener("load", load_listener, true); + + content.location.href = url; + }); + }).then(text => { + is(text, "false", "installTrigger should have not been enabled"); + Services.prefs.clearUserPref("xpinstall.enabled"); + gBrowser.removeCurrentTab(); + Harness.finish(); + }); +} + +function install_disabled(installInfo) { + ok(true, "Saw installation disabled"); +} + +function allow_blocked(installInfo) { + ok(false, "Should never see the blocked install notification"); + return false; +} + +function confirm_install(window) { + ok(false, "Should never see an install confirmation dialog"); + return false; +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_hash.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_hash.js new file mode 100644 index 000000000..4c45bd184 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_hash.js @@ -0,0 +1,34 @@ +// ---------------------------------------------------------------------------- +// Test whether an install succeeds when a valid hash is included +// This verifies bug 302284 +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: TESTROOT + "amosigned.xpi", + Hash: "sha1:36ffb0acfd9c6e9682473aaebaab394d38b473c9", + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_hash2.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_hash2.js new file mode 100644 index 000000000..4c8e262c7 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_hash2.js @@ -0,0 +1,34 @@ +// ---------------------------------------------------------------------------- +// Test whether an install succeeds using case-insensitive hashes +// This verifies bug 603021 +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: TESTROOT + "amosigned.xpi", + Hash: "sha1:36FFB0ACFD9C6E9682473AAEBAAB394D38B473C9", + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_httphash.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_httphash.js new file mode 100644 index 000000000..6a1222797 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_httphash.js @@ -0,0 +1,39 @@ +// ---------------------------------------------------------------------------- +// Test whether an install succeeds when a valid hash is included in the HTTPS +// request +// This verifies bug 591070 +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false); + + var url = "https://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs"; + url += "?sha1:36ffb0acfd9c6e9682473aaebaab394d38b473c9|" + TESTROOT + "amosigned.xpi"; + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: url, + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_httphash2.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_httphash2.js new file mode 100644 index 000000000..2d930d221 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_httphash2.js @@ -0,0 +1,39 @@ +// ---------------------------------------------------------------------------- +// Test whether an install fails when a invalid hash is included in the HTTPS +// request +// This verifies bug 591070 +function test() { + Harness.downloadFailedCallback = download_failed; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false); + + var url = "https://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs"; + url += "?sha1:foobar|" + TESTROOT + "amosigned.xpi"; + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: url, + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_INCORRECT_HASH, "Download should fail"); +} + +function finish_test(count) { + is(count, 0, "0 Add-ons should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_httphash3.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_httphash3.js new file mode 100644 index 000000000..5f3ef23ca --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_httphash3.js @@ -0,0 +1,39 @@ +// ---------------------------------------------------------------------------- +// Tests that the HTTPS hash is ignored when InstallTrigger is passed a hash. +// This verifies bug 591070 +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false); + + var url = "https://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs"; + url += "?sha1:foobar|" + TESTROOT + "amosigned.xpi"; + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: url, + Hash: "sha1:36ffb0acfd9c6e9682473aaebaab394d38b473c9", + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_httphash4.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_httphash4.js new file mode 100644 index 000000000..3983662af --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_httphash4.js @@ -0,0 +1,36 @@ +// ---------------------------------------------------------------------------- +// Test that hashes are ignored in the headers of HTTP requests +// This verifies bug 591070 +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var url = "http://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs"; + url += "?sha1:foobar|" + TESTROOT + "amosigned.xpi"; + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: url, + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_httphash5.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_httphash5.js new file mode 100644 index 000000000..407158e4f --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_httphash5.js @@ -0,0 +1,40 @@ +// ---------------------------------------------------------------------------- +// Test that only the first HTTPS hash is used +// This verifies bug 591070 +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false); + + var url = "https://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs"; + url += "?sha1:36ffb0acfd9c6e9682473aaebaab394d38b473c9|"; + url += "https://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs"; + url += "?sha1:foobar|" + TESTROOT + "amosigned.xpi"; + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: url, + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_httphash6.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_httphash6.js new file mode 100644 index 000000000..5e1da8175 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_httphash6.js @@ -0,0 +1,83 @@ +// ---------------------------------------------------------------------------- +// Tests that a new hash is accepted when restarting a failed download +// This verifies bug 593535 +function setup_redirect(aSettings) { + var url = "https://example.com/browser/" + RELATIVE_DIR + "redirect.sjs?mode=setup"; + for (var name in aSettings) { + url += "&" + name + "=" + aSettings[name]; + } + + var req = new XMLHttpRequest(); + req.open("GET", url, false); + req.send(null); +} + +var gInstall = null; + +function test() { + Harness.downloadFailedCallback = download_failed; + Harness.installsCompletedCallback = finish_failed_download; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false); + + // Set up the redirect to give a bad hash + setup_redirect({ + "X-Target-Digest": "sha1:foo", + "Location": "http://example.com/browser/" + RELATIVE_DIR + "amosigned.xpi" + }); + + var url = "https://example.com/browser/" + RELATIVE_DIR + "redirect.sjs?mode=redirect"; + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: url, + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_INCORRECT_HASH, "Should have seen a hash failure"); + // Stash the failed download while the harness cleans itself up + gInstall = install; +} + +function finish_failed_download() { + // Setup to track the successful re-download + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + // Give it the right hash this time + setup_redirect({ + "X-Target-Digest": "sha1:36ffb0acfd9c6e9682473aaebaab394d38b473c9", + "Location": "http://example.com/browser/" + RELATIVE_DIR + "amosigned.xpi" + }); + + // The harness expects onNewInstall events for all installs that are about to start + Harness.onNewInstall(gInstall); + + // Restart the install as a regular webpage install so the harness tracks it + AddonManager.installAddonsFromWebpage("application/x-xpinstall", + gBrowser.selectedBrowser, + gBrowser.contentPrincipal, [gInstall]); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_installchrome.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_installchrome.js new file mode 100644 index 000000000..2380a4df2 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_installchrome.js @@ -0,0 +1,25 @@ +// ---------------------------------------------------------------------------- +// Tests that calling InstallTrigger.installChrome works +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installchrome.html? " + encodeURIComponent(TESTROOT + "amosigned.xpi")); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_localfile.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_localfile.js new file mode 100644 index 000000000..997f386a6 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_localfile.js @@ -0,0 +1,35 @@ +// ---------------------------------------------------------------------------- +// Tests installing an local file works when loading the url +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var cr = Components.classes["@mozilla.org/chrome/chrome-registry;1"] + .getService(Components.interfaces.nsIChromeRegistry); + + var chromeroot = extractChromeRoot(gTestPath); + var xpipath = chromeroot + "unsigned.xpi"; + try { + xpipath = cr.convertChromeURL(makeURI(chromeroot + "amosigned.xpi")).spec; + } catch (ex) { + // scenario where we are running from a .jar and already extracted + } + + gBrowser.selectedTab = gBrowser.addTab("about:blank"); + BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => { + gBrowser.loadURI(xpipath); + }); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_localfile2.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_localfile2.js new file mode 100644 index 000000000..b0e3ffc42 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_localfile2.js @@ -0,0 +1,38 @@ +// ---------------------------------------------------------------------------- +// Test whether an install fails if the url is a local file when requested from +// web content +add_task(function* test() { + var cr = Components.classes["@mozilla.org/chrome/chrome-registry;1"] + .getService(Components.interfaces.nsIChromeRegistry); + + var chromeroot = getChromeRoot(gTestPath); + var xpipath = chromeroot + "amosigned.xpi"; + try { + xpipath = cr.convertChromeURL(makeURI(xpipath)).spec; + } catch (ex) { + // scenario where we are running from a .jar and already extracted + } + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": xpipath + })); + + // In non-e10s the exception in the content page would trigger a test failure + if (!gMultiProcessBrowser) + expectUncaughtException(); + + let URI = TESTROOT + "installtrigger.html?" + triggers; + yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, function* (browser) { + yield ContentTask.spawn(browser, URI, function* (URI) { + content.location.href = URI; + + let loaded = ContentTaskUtils.waitForEvent(this, "load", true); + let installTriggered = ContentTaskUtils.waitForEvent(this, "InstallTriggered", true, null, true); + yield Promise.all([ loaded, installTriggered ]); + + let doc = content.document; + is(doc.getElementById("return").textContent, "exception", "installTrigger should have failed"); + }); + }); +}); +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_localfile3.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_localfile3.js new file mode 100644 index 000000000..891b85ebc --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_localfile3.js @@ -0,0 +1,41 @@ +// ---------------------------------------------------------------------------- +// Tests installing an add-on from a local file with whitelisting disabled. +// This should be blocked by the whitelist check. +function test() { + Harness.installBlockedCallback = allow_blocked; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + // Disable direct request whitelisting, installing from file should be blocked. + Services.prefs.setBoolPref("xpinstall.whitelist.directRequest", false); + + var cr = Components.classes["@mozilla.org/chrome/chrome-registry;1"] + .getService(Components.interfaces.nsIChromeRegistry); + + var chromeroot = extractChromeRoot(gTestPath); + var xpipath = chromeroot + "amosigned.xpi"; + try { + xpipath = cr.convertChromeURL(makeURI(xpipath)).spec; + } catch (ex) { + // scenario where we are running from a .jar and already extracted + } + + gBrowser.selectedTab = gBrowser.addTab("about:blank"); + BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => { + gBrowser.loadURI(xpipath); + }); +} + +function allow_blocked(installInfo) { + ok(true, "Seen blocked"); + return false; +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + + Services.prefs.clearUserPref("xpinstall.whitelist.directRequest"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_localfile4.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_localfile4.js new file mode 100644 index 000000000..5203c3153 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_localfile4.js @@ -0,0 +1,41 @@ +// ---------------------------------------------------------------------------- +// Tests installing an add-on from a local file with whitelisting disabled. +// This should be blocked by the whitelist check. +function test() { + Harness.installBlockedCallback = allow_blocked; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + // Disable file request whitelisting, installing by file referrer should be blocked. + Services.prefs.setBoolPref("xpinstall.whitelist.fileRequest", false); + + var cr = Components.classes["@mozilla.org/chrome/chrome-registry;1"] + .getService(Components.interfaces.nsIChromeRegistry); + + var chromeroot = extractChromeRoot(gTestPath); + var xpipath = chromeroot; + try { + xpipath = cr.convertChromeURL(makeURI(chromeroot)).spec; + } catch (ex) { + // scenario where we are running from a .jar and already extracted + } + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "amosigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(xpipath + "installtrigger.html?" + triggers); +} + +function allow_blocked(installInfo) { + ok(true, "Seen blocked"); + return false; +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + + Services.prefs.clearUserPref("xpinstall.whitelist.fileRequest"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_multipackage.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_multipackage.js new file mode 100644 index 000000000..d022d713a --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_multipackage.js @@ -0,0 +1,52 @@ +// ---------------------------------------------------------------------------- +// Tests installing an signed add-on by navigating directly to the url +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + gBrowser.selectedTab = gBrowser.addTab("about:blank"); + BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => { + gBrowser.loadURI(TESTROOT + "multipackage.xpi"); + }); +} + +function get_item(items, name) { + for (let item of items) { + if (item.name == name) + return item; + } + ok(false, "Item for " + name + " was not listed"); + return null; +} + +function confirm_install(window) { + let items = window.document.getElementById("itemList").childNodes; + is(items.length, 2, "Should be 2 items listed in the confirmation dialog"); + + let item = get_item(items, "XPI Test"); + if (item) { + is(item.signed, "false", "Should not have listed the item as signed"); + is(item.icon, "", "Should have listed no icon for the item"); + } + + item = get_item(items, "Signed XPI Test"); + if (item) { + is(item.signed, "false", "Should have listed the item as signed"); + is(item.icon, "", "Should have listed no icon for the item"); + } + + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 2, "2 Add-ons should have been successfully installed"); + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_navigateaway.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_navigateaway.js new file mode 100644 index 000000000..f092edb8c --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_navigateaway.js @@ -0,0 +1,36 @@ +// ---------------------------------------------------------------------------- +// Tests that navigating away from the initiating page during the install +// doesn't break the install. +// This verifies bug 473060 +function test() { + Harness.downloadProgressCallback = download_progress; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "amosigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_progress(addon, value, maxValue) { + gBrowser.loadURI(TESTROOT + "enabled.html"); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_navigateaway2.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_navigateaway2.js new file mode 100644 index 000000000..a41662e1e --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_navigateaway2.js @@ -0,0 +1,34 @@ +// ---------------------------------------------------------------------------- +// Tests that closing the initiating page during the install cancels the install +// to avoid spoofing the user. +function test() { + Harness.downloadProgressCallback = download_progress; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "amosigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_progress(addon, value, maxValue) { + gBrowser.removeCurrentTab(); +} + +function install_ended(install, addon) { + ok(false, "Should not have seen installs complete"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_navigateaway3.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_navigateaway3.js new file mode 100644 index 000000000..3948d5649 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_navigateaway3.js @@ -0,0 +1,38 @@ +// ---------------------------------------------------------------------------- +// Tests that navigating to a new origin cancels ongoing installs. + +// Block the modal install UI from showing. +Services.prefs.setBoolPref(PREF_CUSTOM_CONFIRMATION_UI, true); + +function test() { + Harness.downloadProgressCallback = download_progress; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "amosigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_progress(addon, value, maxValue) { + gBrowser.loadURI(TESTROOT2 + "enabled.html"); +} + +function install_ended(install, addon) { + ok(false, "Should not have seen installs complete"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_navigateaway4.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_navigateaway4.js new file mode 100644 index 000000000..61844c5a1 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_navigateaway4.js @@ -0,0 +1,44 @@ +// ---------------------------------------------------------------------------- +// Tests that navigating to a new origin cancels ongoing installs and closes +// the install UI. +var sawUnload = null; + +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "amosigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function confirm_install(window) { + sawUnload = BrowserTestUtils.waitForEvent(window, "unload"); + + gBrowser.loadURI(TESTROOT2 + "enabled.html"); + + return Harness.leaveOpen; +} + +function install_ended(install, addon) { + ok(false, "Should not have seen installs complete"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + sawUnload.then(() => { + ok(true, "The install UI should have closed itself."); + gBrowser.removeCurrentTab(); + Harness.finish(); + }); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_offline.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_offline.js new file mode 100644 index 000000000..eb4ac391f --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_offline.js @@ -0,0 +1,62 @@ +var proxyPrefValue; + +// ---------------------------------------------------------------------------- +// Tests that going offline cancels an in progress download. +function test() { + Harness.downloadProgressCallback = download_progress; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "amosigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_progress(addon, value, maxValue) { + try { + // Tests always connect to localhost, and per bug 87717, localhost is now + // reachable in offline mode. To avoid this, disable any proxy. + proxyPrefValue = Services.prefs.getIntPref("network.proxy.type"); + Services.prefs.setIntPref("network.proxy.type", 0); + Services.io.manageOfflineStatus = false; + Services.io.offline = true; + } catch (ex) { + } +} + +function finish_test(count) { + function wait_for_online() { + info("Checking if the browser is still offline..."); + + let tab = gBrowser.selectedTab; + ContentTask.spawn(tab.linkedBrowser, null, function*() { + yield ContentTaskUtils.waitForEvent(this, "DOMContentLoaded", true); + return content.document.documentURI; + }).then(url => { + info("loaded: " + url); + if (/^about:neterror\?e=netOffline/.test(url)) { + wait_for_online(); + } else { + gBrowser.removeCurrentTab(); + Harness.finish(); + } + }); + tab.linkedBrowser.loadURI("http://example.com/"); + } + + is(count, 0, "No add-ons should have been installed"); + try { + Services.prefs.setIntPref("network.proxy.type", proxyPrefValue); + Services.io.offline = false; + } catch (ex) { + } + + Services.perms.remove(makeURI("http://example.com"), "install"); + + wait_for_online(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_relative.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_relative.js new file mode 100644 index 000000000..3599f47d1 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_relative.js @@ -0,0 +1,55 @@ +// ---------------------------------------------------------------------------- +// Tests that InstallTrigger deals with relative urls correctly. +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.finalContentEvent = "InstallComplete"; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: "amosigned.xpi", + IconURL: "icon.png", + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function confirm_install(window) { + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "XPI Test", "Should have seen the name"); + is(items[0].url, TESTROOT + "amosigned.xpi", "Should have listed the correct url for the item"); + is(items[0].icon, TESTROOT + "icon.png", "Should have listed the correct icon for the item"); + is(items[0].signed, "false", "Should have listed the item as unsigned"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +const finish_test = Task.async(function*(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + const results = yield ContentTask.spawn(gBrowser.selectedBrowser, null, () => { + return { + return: content.document.getElementById("return").textContent, + status: content.document.getElementById("status").textContent, + } + }) + + is(results.return, "true", "installTrigger should have claimed success"); + is(results.status, "0", "Callback should have seen a success"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +}); diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_multipackage.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_multipackage.js new file mode 100644 index 000000000..7341f3082 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_multipackage.js @@ -0,0 +1,53 @@ +// ---------------------------------------------------------------------------- +// Tests installing an signed add-on by navigating directly to the url +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + gBrowser.selectedTab = gBrowser.addTab("about:blank"); + BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => { + gBrowser.loadURI(TESTROOT + "signed-multipackage.xpi"); + }); +} + +function get_item(items, name) { + for (let item of items) { + if (item.name == name) + return item; + } + ok(false, "Item for " + name + " was not listed"); + return null; +} + +function confirm_install(window) { + let items = window.document.getElementById("itemList").childNodes; + is(items.length, 2, "Should be 2 items listed in the confirmation dialog"); + + let item = get_item(items, "XPI Test"); + if (item) { + is(item.signed, "false", "Should not have listed the item as signed"); + is(item.icon, "", "Should have listed no icon for the item"); + } + + item = get_item(items, "Signed XPI Test"); + if (item) { + is(item.cert, "(Object Signer)", "Should have seen the signer"); + is(item.signed, "true", "Should have listed the item as signed"); + is(item.icon, "", "Should have listed no icon for the item"); + } + + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 2, "2 Add-ons should have been successfully installed"); + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_multiple.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_multiple.js new file mode 100644 index 000000000..9dda1aaeb --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_multiple.js @@ -0,0 +1,72 @@ +// ---------------------------------------------------------------------------- +// Tests installing two signed add-ons in the same trigger works. +// This verifies bug 453545 +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Signed XPI": TESTROOT + "signed.xpi", + "Signed XPI 2": TESTROOT + "signed2.xpi", + "Signed XPI 3": TESTROOT + "signed-no-o.xpi", + "Signed XPI 4": TESTROOT + "signed-no-cn.xpi", + "Signed XPI 5": TESTROOT + "unsigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function get_item(items, url) { + for (let item of items) { + if (item.url == url) + return item; + } + ok(false, "Item for " + url + " was not listed"); + return null; +} + +function confirm_install(window) { + + var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"]. + getService(Components.interfaces.nsIStringBundleService); + var bundle = sbs.createBundle("chrome://mozapps/locale/xpinstall/xpinstallConfirm.properties"); + + var expectedIntroString = bundle.formatStringFromName("itemWarnIntroMultiple", ["5"], 1); + + var introStringNode = window.document.getElementById("itemWarningIntro"); + is(introStringNode.textContent, expectedIntroString, "Should have the correct intro string"); + + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 5, "Should be 5 items listed in the confirmation dialog"); + let item = get_item(items, TESTROOT + "signed.xpi"); + if (item) { + is(item.name, "Signed XPI Test", "Should have seen the name from the trigger list"); + is(item.cert, "(Object Signer)", "Should have seen the signer"); + is(item.signed, "true", "Should have listed the item as signed"); + } + item = get_item(items, TESTROOT + "signed2.xpi"); + if (item) { + is(item.name, "Signed XPI Test", "Should have seen the name from the trigger list"); + is(item.cert, "(Object Signer)", "Should have seen the signer"); + is(item.signed, "true", "Should have listed the item as signed"); + } + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 5, "5 Add-ons should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_naming.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_naming.js new file mode 100644 index 000000000..5c3f79045 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_naming.js @@ -0,0 +1,67 @@ +// ---------------------------------------------------------------------------- +// Tests that the correct signer is presented for combinations of O and CN present. +// The signed files have (when present) O=Mozilla Testing, CN=Object Signer +// This verifies bug 372980 +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Signed XPI (O and CN)": TESTROOT + "signed.xpi", + "Signed XPI (CN)": TESTROOT + "signed-no-o.xpi", + "Signed XPI (O)": TESTROOT + "signed-no-cn.xpi", + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function get_item(items, url) { + for (let item of items) { + if (item.url == url) + return item; + } + ok(false, "Item for " + url + " was not listed"); + return null; +} + +function confirm_install(window) { + let items = window.document.getElementById("itemList").childNodes; + is(items.length, 3, "Should be 3 items listed in the confirmation dialog"); + let item = get_item(items, TESTROOT + "signed.xpi"); + if (item) { + is(item.name, "Signed XPI Test", "Should have seen the name from the trigger list"); + is(item.cert, "(Object Signer)", "Should have seen the signer"); + is(item.signed, "true", "Should have listed the item as signed"); + } + item = get_item(items, TESTROOT + "signed-no-o.xpi"); + if (item) { + is(item.name, "Signed XPI Test (No Org)", "Should have seen the name from the trigger list"); + is(item.cert, "(Object Signer)", "Should have seen the signer"); + is(item.signed, "true", "Should have listed the item as signed"); + } + item = get_item(items, TESTROOT + "signed-no-cn.xpi"); + if (item) { + is(item.name, "Signed XPI Test (No Common Name)", "Should have seen the name from the trigger list"); + is(item.cert, "(Mozilla Testing)", "Should have seen the signer"); + is(item.signed, "true", "Should have listed the item as signed"); + } + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 3, "3 Add-ons should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_tampered.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_tampered.js new file mode 100644 index 000000000..fc798d66a --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_tampered.js @@ -0,0 +1,33 @@ +// ---------------------------------------------------------------------------- +// Tests installing a signed add-on that has been tampered with after signing. +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.downloadFailedCallback = download_failed; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Tampered Signed XPI": TESTROOT + "signed-tampered.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function confirm_install(window) { + ok(false, "Should not offer to install"); +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_CORRUPT_FILE, "Install should fail"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_trigger.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_trigger.js new file mode 100644 index 000000000..8f1ae2d87 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_trigger.js @@ -0,0 +1,41 @@ +// ---------------------------------------------------------------------------- +// Tests installing an signed add-on through an InstallTrigger call in web +// content. +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Signed XPI": TESTROOT + "signed.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function confirm_install(window) { + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "Signed XPI Test", "Should have seen the name from the trigger list"); + is(items[0].url, TESTROOT + "signed.xpi", "Should have listed the correct url for the item"); + is(items[0].cert, "(Object Signer)", "Should have seen the signer"); + is(items[0].signed, "true", "Should have listed the item as signed"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_untrusted.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_untrusted.js new file mode 100644 index 000000000..d5fa9ae01 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_untrusted.js @@ -0,0 +1,41 @@ +// ---------------------------------------------------------------------------- +// Tests installing an add-on signed by an untrusted certificate through an +// InstallTrigger call in web content. +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Untrusted Signed XPI": TESTROOT + "signed-untrusted.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function confirm_install(window) { + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "Signed XPI Test", "Should have had the filename for the item name"); + is(items[0].url, TESTROOT + "signed-untrusted.xpi", "Should have listed the correct url for the item"); + is(items[0].icon, "", "Should have listed no icon for the item"); + is(items[0].signed, "false", "Should have listed the item as unsigned"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_url.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_url.js new file mode 100644 index 000000000..33cda6e4c --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_signed_url.js @@ -0,0 +1,34 @@ +// ---------------------------------------------------------------------------- +// Tests installing an signed add-on by navigating directly to the url +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + gBrowser.selectedTab = gBrowser.addTab("about:blank"); + BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => { + gBrowser.loadURI(TESTROOT + "signed.xpi"); + }); +} + +function confirm_install(window) { + let items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "Signed XPI Test", "Should have had the name"); + is(items[0].url, TESTROOT + "signed.xpi", "Should have listed the correct url for the item"); + is(items[0].cert, "(Object Signer)", "Should have seen the signer"); + is(items[0].signed, "true", "Should have listed the item as signed"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_softwareupdate.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_softwareupdate.js new file mode 100644 index 000000000..16e20f3e9 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_softwareupdate.js @@ -0,0 +1,25 @@ +// ---------------------------------------------------------------------------- +// Tests that calling InstallTrigger.startSoftwareUpdate works +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "startsoftwareupdate.html? " + encodeURIComponent(TESTROOT + "amosigned.xpi")); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_switchtab.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_switchtab.js new file mode 100644 index 000000000..9bbb59400 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_switchtab.js @@ -0,0 +1,49 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through an InstallTrigger call in web +// content. +var expectedTab = null; + +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: TESTROOT + "amosigned.xpi", + IconURL: TESTROOT + "icon.png", + toString: function() { return this.URL; } + } + })); + expectedTab = gBrowser.addTab(); + expectedTab.linkedBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function confirm_install(window) { + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "XPI Test", "Should have seen the name"); + is(items[0].url, TESTROOT + "amosigned.xpi", "Should have listed the correct url for the item"); + is(items[0].icon, TESTROOT + "icon.png", "Should have listed the correct icon for the item"); + is(items[0].signed, "false", "Should have listed the item as unsigned"); + + is(gBrowser.selectedTab, expectedTab, "Should have switched to the installing tab."); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeTab(expectedTab); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_trigger_redirect.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_trigger_redirect.js new file mode 100644 index 000000000..9c0543602 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_trigger_redirect.js @@ -0,0 +1,41 @@ +// ---------------------------------------------------------------------------- +// Tests that the InstallTrigger callback can redirect to a relative url. +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.finalContentEvent = "InstallComplete"; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "triggerredirect.html"); +} + +function confirm_install(window) { + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "XPI Test", "Should have seen the name"); + is(items[0].url, TESTROOT + "amosigned.xpi", "Should have listed the correct url for the item"); + is(items[0].icon, TESTROOT + "icon.png", "Should have listed the correct icon for the item"); + is(items[0].signed, "false", "Should have listed the item as unsigned"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + var doc = gBrowser.contentDocument; + is(gBrowser.currentURI.spec, TESTROOT + "triggerredirect.html#foo", "Should have redirected"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_unsigned_trigger.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_unsigned_trigger.js new file mode 100644 index 000000000..006879439 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_unsigned_trigger.js @@ -0,0 +1,56 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through an InstallTrigger call in web +// content. +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.finalContentEvent = "InstallComplete"; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: TESTROOT + "unsigned.xpi", + IconURL: TESTROOT + "icon.png", + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function confirm_install(window) { + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "XPI Test", "Should have seen the name"); + is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); + is(items[0].icon, TESTROOT + "icon.png", "Should have listed the correct icon for the item"); + is(items[0].signed, "false", "Should have listed the item as unsigned"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +const finish_test = Task.async(function*(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + const results = yield ContentTask.spawn(gBrowser.selectedBrowser, null, () => { + return { + return: content.document.getElementById("return").textContent, + status: content.document.getElementById("status").textContent, + } + }) + + is(results.return, "true", "installTrigger should have claimed success"); + is(results.status, "0", "Callback should have seen a success"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +}); diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_unsigned_trigger_iframe.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_unsigned_trigger_iframe.js new file mode 100644 index 000000000..b9df6615e --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_unsigned_trigger_iframe.js @@ -0,0 +1,57 @@ +// ---------------------------------------------------------------------------- +// Test for bug 589598 - Ensure that installing through InstallTrigger +// works in an iframe in web content. + +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.finalContentEvent = "InstallComplete"; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var inner_url = encodeURIComponent(TESTROOT + "installtrigger.html?" + encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: TESTROOT + "unsigned.xpi", + IconURL: TESTROOT + "icon.png", + toString: function() { return this.URL; } + } + }))); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger_frame.html?" + inner_url); +} + +function confirm_install(window) { + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "XPI Test", "Should have seen the name"); + is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); + is(items[0].icon, TESTROOT + "icon.png", "Should have listed the correct icon for the item"); + is(items[0].signed, "false", "Should have listed the item as unsigned"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +const finish_test = Task.async(function*(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove(makeURI("http://example.com"), "install"); + + const results = yield ContentTask.spawn(gBrowser.selectedBrowser, null, () => { + return { + return: content.frames[0].document.getElementById("return").textContent, + status: content.frames[0].document.getElementById("status").textContent, + } + }) + + is(results.return, "true", "installTrigger in iframe should have claimed success"); + is(results.status, "0", "Callback in iframe should have seen a success"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +}); diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_unsigned_trigger_xorigin.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_unsigned_trigger_xorigin.js new file mode 100644 index 000000000..b0875fc99 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_unsigned_trigger_xorigin.js @@ -0,0 +1,38 @@ +// ---------------------------------------------------------------------------- +// Ensure that an inner frame from a different origin can't initiate an install + +var wasOriginBlocked = false; + +function test() { + Harness.installOriginBlockedCallback = install_blocked; + Harness.installsCompletedCallback = finish_test; + Harness.finalContentEvent = "InstallComplete"; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var inner_url = encodeURIComponent(TESTROOT + "installtrigger.html?" + encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: TESTROOT + "amosigned.xpi", + IconURL: TESTROOT + "icon.png", + toString: function() { return this.URL; } + } + }))); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT2 + "installtrigger_frame.html?" + inner_url); +} + +function install_blocked(installInfo) { + wasOriginBlocked = true; +} + +function finish_test(count) { + ok(wasOriginBlocked, "Should have been blocked due to the cross origin request."); + + is(count, 0, "No add-ons should have been installed"); + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_unsigned_url.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_unsigned_url.js new file mode 100644 index 000000000..e103dffd3 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_unsigned_url.js @@ -0,0 +1,35 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on by navigating directly to the url +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + gBrowser.selectedTab = gBrowser.addTab("about:blank"); + BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => { + gBrowser.loadURI(TESTROOT + "unsigned.xpi"); + }); +} + +function confirm_install(window) { + let items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "XPI Test", "Should have had the filename for the item name"); + is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); + is(items[0].icon, "", "Should have listed no icon for the item"); + is(items[0].signed, "false", "Should have listed the item as unsigned"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist.js new file mode 100644 index 000000000..ad3d645f5 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist.js @@ -0,0 +1,53 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through an InstallTrigger call in web +// content. This should be blocked by the whitelist check. +// This verifies bug 252830 +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installBlockedCallback = allow_blocked; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "amosigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function allow_blocked(installInfo) { + is(installInfo.browser, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); + is(installInfo.originatingURI.spec, gBrowser.currentURI.spec, "Install should have been triggered by the right uri"); + return true; +} + +function confirm_install(window) { + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "XPI Test", "Should have seen the name from the trigger list"); + is(items[0].url, TESTROOT + "amosigned.xpi", "Should have listed the correct url for the item"); + is(items[0].signed, "false", "Should have listed the item as unsigned"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +const finish_test = Task.async(function*(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + const results = yield ContentTask.spawn(gBrowser.selectedBrowser, null, () => { + return { + return: content.document.getElementById("return").textContent, + status: content.document.getElementById("status").textContent, + } + }) + + is(results.return, "false", "installTrigger should seen a failure"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +}); +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist2.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist2.js new file mode 100644 index 000000000..fd9e944e8 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist2.js @@ -0,0 +1,31 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through an InstallTrigger call in web +// content. This should be blocked by the whitelist check because the source +// is not whitelisted, even though the target is. +function test() { + Harness.installBlockedCallback = allow_blocked; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.org/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT2 + "amosigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function allow_blocked(installInfo) { + is(installInfo.browser, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); + is(installInfo.originatingURI.spec, gBrowser.currentURI.spec, "Install should have been triggered by the right uri"); + return false; +} + +function finish_test() { + Services.perms.remove(makeURI("http://example.org"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist3.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist3.js new file mode 100644 index 000000000..6f4306df6 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist3.js @@ -0,0 +1,28 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through a navigation. Should not be +// blocked since the referer is whitelisted. +var url = TESTROOT2 + "navigate.html?" + encodeURIComponent(TESTROOT + "amosigned.xpi"); + +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.org/"), "install", pm.ALLOW_ACTION); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(url); +} + +function confirm_install(window) { + return false; +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + Services.perms.remove(makeURI("http://example.org"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist4.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist4.js new file mode 100644 index 000000000..e4c47cda5 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist4.js @@ -0,0 +1,30 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through a navigation. Should be +// blocked since the referer is not whitelisted even though the target is. +var url = TESTROOT2 + "navigate.html?" + encodeURIComponent(TESTROOT + "amosigned.xpi"); + +function test() { + Harness.installBlockedCallback = allow_blocked; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(url); +} + +function allow_blocked(installInfo) { + is(installInfo.browser, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); + is(installInfo.originatingURI.spec, url, "Install should have been triggered by the right uri"); + return false; +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + Services.perms.remove(makeURI("http://example.com"), "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist5.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist5.js new file mode 100644 index 000000000..0a9333430 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist5.js @@ -0,0 +1,25 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through a startSoftwareUpdate call in web +// content. This should be blocked by the whitelist check. +// This verifies bug 252830 +function test() { + Harness.installBlockedCallback = allow_blocked; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "startsoftwareupdate.html? " + encodeURIComponent(TESTROOT + "amosigned.xpi")); +} + +function allow_blocked(installInfo) { + is(installInfo.browser, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); + is(installInfo.originatingURI.spec, gBrowser.currentURI.spec, "Install should have been triggered by the right uri"); + return false; +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist6.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist6.js new file mode 100644 index 000000000..555f1e2fc --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist6.js @@ -0,0 +1,25 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through an installChrome call in web +// content. This should be blocked by the whitelist check. +// This verifies bug 252830 +function test() { + Harness.installBlockedCallback = allow_blocked; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installchrome.html? " + encodeURIComponent(TESTROOT + "amosigned.xpi")); +} + +function allow_blocked(installInfo) { + is(installInfo.browser, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); + is(installInfo.originatingURI.spec, gBrowser.currentURI.spec, "Install should have been triggered by the right uri"); + return false; +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist7.js b/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist7.js new file mode 100644 index 000000000..96c60ac9e --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/browser_whitelist7.js @@ -0,0 +1,32 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through a direct install request from +// web content. This should be blocked by the whitelist check because we disable +// direct request whitelisting, even though the target URI is whitelisted. +function test() { + Harness.installBlockedCallback = allow_blocked; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + // Disable direct request whitelisting, installing should be blocked. + Services.prefs.setBoolPref("xpinstall.whitelist.directRequest", false); + + gBrowser.selectedTab = gBrowser.addTab("about:blank"); + BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => { + gBrowser.loadURI(TESTROOT + "amosigned.xpi"); + }); +} + +function allow_blocked(installInfo) { + ok(true, "Seen blocked"); + return false; +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + + Services.perms.remove(makeURI("http://example.org"), "install"); + Services.prefs.clearUserPref("xpinstall.whitelist.directRequest"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/bug540558.html b/toolkit/mozapps/webextensions/test/xpinstall/bug540558.html new file mode 100644 index 000000000..286046d25 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/bug540558.html @@ -0,0 +1,23 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<!-- This page tests that window.InstallTrigger.install works --> + +<head> +<title>InstallTrigger tests</title> +<script type="text/javascript"> +function startInstall() { + window.InstallTrigger.install({ + "Unsigned XPI": "amosigned.xpi" + }); +} +</script> +</head> +<body onload="startInstall()"> +<p>InstallTrigger tests</p> +<p id="return"></p> +<p id="status"></p> +</body> +</html> diff --git a/toolkit/mozapps/webextensions/test/xpinstall/bug638292.html b/toolkit/mozapps/webextensions/test/xpinstall/bug638292.html new file mode 100644 index 000000000..198207d4b --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/bug638292.html @@ -0,0 +1,17 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<!-- This page tests InstallTrigger is defined in a new window --> + +<head> +<title>InstallTrigger tests</title> +</head> +<body> +<p>InstallTrigger tests</p> +<p><a id="link1" target="_blank" href="enabled.html">Open window with target</a></p> +<p><a id="link2" onclick="window.open(this.href); return false" href="enabled.html">Open window with JS</a></p> +<p><a id="link3" href="enabled.html">Open window with middle-click</a></p> +</body> +</html> diff --git a/toolkit/mozapps/webextensions/test/xpinstall/bug645699.html b/toolkit/mozapps/webextensions/test/xpinstall/bug645699.html new file mode 100644 index 000000000..8334c37c2 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/bug645699.html @@ -0,0 +1,31 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<head> +<title>InstallTrigger tests</title> +<script type="text/javascript"> +/* globals InstallTrigger */ +function startInstall() { + var whiteUrl = "https://example.org/"; + + try { + Object.defineProperty(window, "location", { value : { href : whiteUrl } }); + throw new Error("Object.defineProperty(window, 'location', ...) should have thrown"); + } catch (exc) { + if (!(exc instanceof TypeError)) + throw exc; + } + Object.defineProperty(document, "documentURIObject", { spec : { href : whiteUrl } }); + + InstallTrigger.install({ + "Unsigned XPI": "http://example.com/browser/toolkit/mozapps/extensions/test/xpinstall/amosigned.xpi" + }); +} +</script> +</head> +<body onload="startInstall()"> +<p>InstallTrigger tests</p> +</body> +</html> diff --git a/toolkit/mozapps/webextensions/test/xpinstall/concurrent_installs.html b/toolkit/mozapps/webextensions/test/xpinstall/concurrent_installs.html new file mode 100644 index 000000000..780409257 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/concurrent_installs.html @@ -0,0 +1,40 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<head> + <meta charset="utf-8"> +<title>Concurrent InstallTrigger tests</title> +<script type="text/javascript"> +/* globals InstallTrigger */ +function installCallback(url, status) { + document.getElementById("status").textContent = status; + + dump("Sending InstallComplete\n"); + var event = new CustomEvent("InstallComplete", {detail: {loc: location.href, xpi: url}}); + window.dispatchEvent(event); +} + +function startInstall() { + var root = location.href.replace("concurrent_installs.html", ""); + var triggers = { + "Unsigned XPI": root + "amosigned.xpi" + }; + try { + document.getElementById("return").textContent = InstallTrigger.install(triggers, installCallback); + } + catch (e) { + document.getElementById("return").textContent = "exception"; + throw e; + } +} +</script> +</head> +<body> +<p>InstallTrigger tests</p> +<button id="installnow" onclick="startInstall()">Click to install</button> +<p id="return"></p> +<p id="status"></p> +</body> +</html> diff --git a/toolkit/mozapps/webextensions/test/xpinstall/cookieRedirect.sjs b/toolkit/mozapps/webextensions/test/xpinstall/cookieRedirect.sjs new file mode 100644 index 000000000..92bccd9ec --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/cookieRedirect.sjs @@ -0,0 +1,24 @@ +// Simple script redirects to the query part of the uri if the cookie "xpinstall" +// has the value "true", otherwise gives a 500 error. + +function handleRequest(request, response) +{ + let cookie = null; + if (request.hasHeader("Cookie")) { + let cookies = request.getHeader("Cookie").split(";"); + for (let i = 0; i < cookies.length; i++) { + if (cookies[i].substring(0, 10) == "xpinstall=") + cookie = cookies[i].substring(10); + } + } + + if (cookie == "true") { + response.setStatusLine(request.httpVersion, 302, "Found"); + response.setHeader("Location", request.queryString); + response.write("See " + request.queryString); + } + else { + response.setStatusLine(request.httpVersion, 500, "Internal Server Error"); + response.write("Invalid request"); + } +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/corrupt.xpi b/toolkit/mozapps/webextensions/test/xpinstall/corrupt.xpi new file mode 100644 index 000000000..35d7bd5e5 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/corrupt.xpi @@ -0,0 +1 @@ +This is a corrupt zip file diff --git a/toolkit/mozapps/webextensions/test/xpinstall/empty.xpi b/toolkit/mozapps/webextensions/test/xpinstall/empty.xpi Binary files differnew file mode 100644 index 000000000..74ed2b817 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/empty.xpi diff --git a/toolkit/mozapps/webextensions/test/xpinstall/enabled.html b/toolkit/mozapps/webextensions/test/xpinstall/enabled.html new file mode 100644 index 000000000..370cde8fb --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/enabled.html @@ -0,0 +1,24 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<!-- This page will test if InstallTrigger seems to be enabled --> + +<head> +<title>InstallTrigger tests</title> +<script type="text/javascript"> +/* globals InstallTrigger */ +function init() { + document.getElementById("enabled").textContent = InstallTrigger.enabled() ? "true" : "false"; + dump("Sending PageLoaded\n"); + var event = new CustomEvent("PageLoaded"); + window.dispatchEvent(event); +} +</script> +</head> +<body onload="init()"> +<p>InstallTrigger tests</p> +<p id="enabled"></p> +</body> +</html> diff --git a/toolkit/mozapps/webextensions/test/xpinstall/hashRedirect.sjs b/toolkit/mozapps/webextensions/test/xpinstall/hashRedirect.sjs new file mode 100644 index 000000000..324a092a3 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/hashRedirect.sjs @@ -0,0 +1,15 @@ +// Simple script redirects takes the query part of te request and splits it on +// the | character. Anything before is included as the X-Target-Digest header +// the latter part is used as the url to redirect to + +function handleRequest(request, response) +{ + let pos = request.queryString.indexOf("|"); + let header = request.queryString.substring(0, pos); + let url = request.queryString.substring(pos + 1); + + response.setStatusLine(request.httpVersion, 302, "Found"); + response.setHeader("X-Target-Digest", header); + response.setHeader("Location", url); + response.write("See " + url); +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/head.js b/toolkit/mozapps/webextensions/test/xpinstall/head.js new file mode 100644 index 000000000..197fe3fac --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/head.js @@ -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]) +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/incompatible.xpi b/toolkit/mozapps/webextensions/test/xpinstall/incompatible.xpi Binary files differnew file mode 100644 index 000000000..262ed38a7 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/incompatible.xpi diff --git a/toolkit/mozapps/webextensions/test/xpinstall/installchrome.html b/toolkit/mozapps/webextensions/test/xpinstall/installchrome.html new file mode 100644 index 000000000..6abee2ef3 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/installchrome.html @@ -0,0 +1,22 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<!-- This page will accept a url as the uri query and pass it to InstallTrigger.installChrome --> + +<head> +<title>InstallTrigger tests</title> +<script type="text/javascript"> +/* globals InstallTrigger */ +function startInstall() { + InstallTrigger.installChrome(InstallTrigger.SKIN, + decodeURIComponent(document.location.search.substring(1)), + "test"); +} +</script> +</head> +<body onload="startInstall()"> +<p>InstallTrigger tests</p> +</body> +</html> diff --git a/toolkit/mozapps/webextensions/test/xpinstall/installtrigger.html b/toolkit/mozapps/webextensions/test/xpinstall/installtrigger.html new file mode 100644 index 000000000..65cab1ef1 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/installtrigger.html @@ -0,0 +1,44 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<!-- This page will accept some json as the uri query and pass it to InstallTrigger.install --> + +<head> +<title>InstallTrigger tests</title> +<script type="text/javascript"> +/* globals InstallTrigger */ +function installCallback(url, status) { + document.getElementById("status").textContent = status; + + dump("Sending InstallComplete\n"); + var event = new CustomEvent("InstallComplete"); + var target = window.parent ? window.parent : window; + target.dispatchEvent(event); +} + +function startInstall() { + var event = new CustomEvent("InstallTriggered"); + var text = decodeURIComponent(document.location.search.substring(1)); + var triggers = JSON.parse(text); + try { + document.getElementById("return").textContent = InstallTrigger.install(triggers, installCallback); + dump("Sending InstallTriggered\n"); + window.dispatchEvent(event); + } + catch (e) { + document.getElementById("return").textContent = "exception"; + dump("Sending InstallTriggered\n"); + window.dispatchEvent(event); + throw e; + } +} +</script> +</head> +<body onload="startInstall()"> +<p>InstallTrigger tests</p> +<p id="return"></p> +<p id="status"></p> +</body> +</html> diff --git a/toolkit/mozapps/webextensions/test/xpinstall/installtrigger_frame.html b/toolkit/mozapps/webextensions/test/xpinstall/installtrigger_frame.html new file mode 100644 index 000000000..2b302642e --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/installtrigger_frame.html @@ -0,0 +1,29 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<!-- This page will accept some url as the uri query and load it in + an inner iframe, which will run InstallTrigger.install --> + +<head> +<title>InstallTrigger frame tests</title> +<script type="text/javascript"> +function prepChild() { + // Pass our parameters over to the child + var child = window.frames[0]; + var url = decodeURIComponent(document.location.search.substr(1)); + child.location = url; +} +</script> +</head> +<body onload="prepChild()"> + +<iframe src="about:blank"> +</iframe> + +<p>InstallTrigger tests</p> +<p id="return"></p> +<p id="status"></p> +</body> +</html> diff --git a/toolkit/mozapps/webextensions/test/xpinstall/multipackage.xpi b/toolkit/mozapps/webextensions/test/xpinstall/multipackage.xpi Binary files differnew file mode 100644 index 000000000..d52f28c28 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/multipackage.xpi diff --git a/toolkit/mozapps/webextensions/test/xpinstall/navigate.html b/toolkit/mozapps/webextensions/test/xpinstall/navigate.html new file mode 100644 index 000000000..5a6903eb9 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/navigate.html @@ -0,0 +1,26 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<!-- This page will accept some url as the uri query and navigate to it by + clicking a link --> + +<head> +<title>Navigation tests</title> +<script type="text/javascript"> +function navigate() { + // Pass our parameters over to the child + var child = window.frames[0]; + var url = decodeURIComponent(document.location.search.substr(1)); + var link = document.getElementById("link"); + link.href = url; + link.click(); +} +</script> +</head> +<body onload="navigate()"> + +<p><a id="link">Test Link</a></p> +</body> +</html> diff --git a/toolkit/mozapps/webextensions/test/xpinstall/redirect.sjs b/toolkit/mozapps/webextensions/test/xpinstall/redirect.sjs new file mode 100644 index 000000000..d248bfbc7 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/redirect.sjs @@ -0,0 +1,45 @@ +// Script has two modes based on the query string. If the mode is "setup" then +// parameters from the query string configure the redirection. If the mode is +// "redirect" then a redirect is returned + +function handleRequest(request, response) +{ + let parts = request.queryString.split("&"); + let settings = {}; + + parts.forEach(function(aString) { + let [k, v] = aString.split("="); + settings[k] = decodeURIComponent(v); + }) + + if (settings.mode == "setup") { + delete settings.mode; + + // Object states must be an nsISupports + var state = { + settings: settings, + QueryInterface: function(aIid) { + if (aIid.equals(Components.interfaces.nsISupports)) + return settings; + throw Components.results.NS_ERROR_NO_INTERFACE; + } + } + state.wrappedJSObject = state; + + setObjectState("xpinstall-redirect-settings", state); + response.setStatusLine(request.httpVersion, 200, "Ok"); + response.setHeader("Content-Type", "text/plain"); + response.write("Setup complete"); + } + else if (settings.mode == "redirect") { + getObjectState("xpinstall-redirect-settings", function(aObject) { + settings = aObject.wrappedJSObject.settings; + }); + + response.setStatusLine(request.httpVersion, 302, "Found"); + for (var name in settings) { + response.setHeader(name, settings[name]); + } + response.write("Done"); + } +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/restartless-unsigned.xpi b/toolkit/mozapps/webextensions/test/xpinstall/restartless-unsigned.xpi Binary files differnew file mode 100644 index 000000000..8e76bd052 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/restartless-unsigned.xpi diff --git a/toolkit/mozapps/webextensions/test/xpinstall/restartless.xpi b/toolkit/mozapps/webextensions/test/xpinstall/restartless.xpi Binary files differnew file mode 100644 index 000000000..9fee8f60b --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/restartless.xpi diff --git a/toolkit/mozapps/webextensions/test/xpinstall/signed-multipackage.xpi b/toolkit/mozapps/webextensions/test/xpinstall/signed-multipackage.xpi Binary files differnew file mode 100644 index 000000000..11fbe1861 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/signed-multipackage.xpi diff --git a/toolkit/mozapps/webextensions/test/xpinstall/signed-no-cn.xpi b/toolkit/mozapps/webextensions/test/xpinstall/signed-no-cn.xpi Binary files differnew file mode 100644 index 000000000..90d3a3ce6 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/signed-no-cn.xpi diff --git a/toolkit/mozapps/webextensions/test/xpinstall/signed-no-o.xpi b/toolkit/mozapps/webextensions/test/xpinstall/signed-no-o.xpi Binary files differnew file mode 100644 index 000000000..19b754038 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/signed-no-o.xpi diff --git a/toolkit/mozapps/webextensions/test/xpinstall/signed-tampered.xpi b/toolkit/mozapps/webextensions/test/xpinstall/signed-tampered.xpi Binary files differnew file mode 100644 index 000000000..8c951881e --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/signed-tampered.xpi diff --git a/toolkit/mozapps/webextensions/test/xpinstall/signed-untrusted.xpi b/toolkit/mozapps/webextensions/test/xpinstall/signed-untrusted.xpi Binary files differnew file mode 100644 index 000000000..09789d189 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/signed-untrusted.xpi diff --git a/toolkit/mozapps/webextensions/test/xpinstall/signed.xpi b/toolkit/mozapps/webextensions/test/xpinstall/signed.xpi Binary files differnew file mode 100644 index 000000000..bd7f78b7c --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/signed.xpi diff --git a/toolkit/mozapps/webextensions/test/xpinstall/signed2.xpi b/toolkit/mozapps/webextensions/test/xpinstall/signed2.xpi Binary files differnew file mode 100644 index 000000000..085efbbf7 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/signed2.xpi diff --git a/toolkit/mozapps/webextensions/test/xpinstall/slowinstall.sjs b/toolkit/mozapps/webextensions/test/xpinstall/slowinstall.sjs new file mode 100644 index 000000000..5f767a8f4 --- /dev/null +++ b/toolkit/mozapps/webextensions/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); + } +} diff --git a/toolkit/mozapps/webextensions/test/xpinstall/startsoftwareupdate.html b/toolkit/mozapps/webextensions/test/xpinstall/startsoftwareupdate.html new file mode 100644 index 000000000..50083ca90 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/startsoftwareupdate.html @@ -0,0 +1,20 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<!-- This page will accept a url as the uri query and pass it to InstallTrigger.startSoftwareUpdate --> + +<head> +<title>InstallTrigger tests</title> +<script type="text/javascript"> +/* globals InstallTrigger */ +function startInstall() { + InstallTrigger.startSoftwareUpdate(decodeURIComponent(document.location.search.substring(1))); +} +</script> +</head> +<body onload="startInstall()"> +<p>InstallTrigger tests</p> +</body> +</html> diff --git a/toolkit/mozapps/webextensions/test/xpinstall/theme.xpi b/toolkit/mozapps/webextensions/test/xpinstall/theme.xpi Binary files differnew file mode 100644 index 000000000..74e650b4a --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/theme.xpi diff --git a/toolkit/mozapps/webextensions/test/xpinstall/triggerredirect.html b/toolkit/mozapps/webextensions/test/xpinstall/triggerredirect.html new file mode 100644 index 000000000..42e0e1cd0 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/triggerredirect.html @@ -0,0 +1,36 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<!-- This page will attempt an install and then try to load a new page in the tab --> + +<head> +<title>InstallTrigger tests</title> +<script type="text/javascript"> +/* globals InstallTrigger */ +function installCallback(url, status) { + document.location = "#foo"; + + dump("Sending InstallComplete\n"); + var event = new CustomEvent("InstallComplete"); + window.dispatchEvent(event); +} + +function startInstall() { + InstallTrigger.install({ + "Unsigned XPI": { + URL: "amosigned.xpi", + IconURL: "icon.png", + toString: function() { return this.URL; } + } + }, installCallback); +} +</script> +</head> +<body onload="startInstall()"> +<p>InstallTrigger tests</p> +<p id="return"></p> +<p id="status"></p> +</body> +</html> diff --git a/toolkit/mozapps/webextensions/test/xpinstall/unsigned.xpi b/toolkit/mozapps/webextensions/test/xpinstall/unsigned.xpi Binary files differnew file mode 100644 index 000000000..51b00475a --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpinstall/unsigned.xpi |