summaryrefslogtreecommitdiffstats
path: root/toolkit/modules/tests/xpcshell/test_GMPInstallManager.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/modules/tests/xpcshell/test_GMPInstallManager.js')
-rw-r--r--toolkit/modules/tests/xpcshell/test_GMPInstallManager.js794
1 files changed, 794 insertions, 0 deletions
diff --git a/toolkit/modules/tests/xpcshell/test_GMPInstallManager.js b/toolkit/modules/tests/xpcshell/test_GMPInstallManager.js
new file mode 100644
index 000000000..74d5ad43d
--- /dev/null
+++ b/toolkit/modules/tests/xpcshell/test_GMPInstallManager.js
@@ -0,0 +1,794 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+var {classes: Cc, interfaces: Ci, results: Cr, utils: Cu, manager: Cm} = Components;
+const URL_HOST = "http://localhost";
+
+var GMPScope = Cu.import("resource://gre/modules/GMPInstallManager.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/FileUtils.jsm");
+Cu.import("resource://testing-common/httpd.js");
+Cu.import("resource://gre/modules/Promise.jsm");
+Cu.import("resource://gre/modules/Preferences.jsm")
+Cu.import("resource://gre/modules/UpdateUtils.jsm");
+
+var { computeHash } = Cu.import("resource://gre/modules/addons/ProductAddonChecker.jsm");
+var ProductAddonCheckerScope = Cu.import("resource://gre/modules/addons/ProductAddonChecker.jsm");
+
+do_get_profile();
+
+function run_test() { Cu.import("resource://gre/modules/Preferences.jsm")
+ Preferences.set("media.gmp.log.dump", true);
+ Preferences.set("media.gmp.log.level", 0);
+ run_next_test();
+}
+
+/**
+ * Tests that the helper used for preferences works correctly
+ */
+add_task(function* test_prefs() {
+ let addon1 = "addon1", addon2 = "addon2";
+
+ GMPScope.GMPPrefs.set(GMPScope.GMPPrefs.KEY_URL, "http://not-really-used");
+ GMPScope.GMPPrefs.set(GMPScope.GMPPrefs.KEY_URL_OVERRIDE, "http://not-really-used-2");
+ GMPScope.GMPPrefs.set(GMPScope.GMPPrefs.KEY_PLUGIN_LAST_UPDATE, "1", addon1);
+ GMPScope.GMPPrefs.set(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, "2", addon1);
+ GMPScope.GMPPrefs.set(GMPScope.GMPPrefs.KEY_PLUGIN_LAST_UPDATE, "3", addon2);
+ GMPScope.GMPPrefs.set(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, "4", addon2);
+ GMPScope.GMPPrefs.set(GMPScope.GMPPrefs.KEY_PLUGIN_AUTOUPDATE, false, addon2);
+ GMPScope.GMPPrefs.set(GMPScope.GMPPrefs.KEY_CERT_CHECKATTRS, true);
+
+ do_check_eq(GMPScope.GMPPrefs.get(GMPScope.GMPPrefs.KEY_URL), "http://not-really-used");
+ do_check_eq(GMPScope.GMPPrefs.get(GMPScope.GMPPrefs.KEY_URL_OVERRIDE),
+ "http://not-really-used-2");
+ do_check_eq(GMPScope.GMPPrefs.get(GMPScope.GMPPrefs.KEY_PLUGIN_LAST_UPDATE, "", addon1), "1");
+ do_check_eq(GMPScope.GMPPrefs.get(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, "", addon1), "2");
+ do_check_eq(GMPScope.GMPPrefs.get(GMPScope.GMPPrefs.KEY_PLUGIN_LAST_UPDATE, "", addon2), "3");
+ do_check_eq(GMPScope.GMPPrefs.get(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, "", addon2), "4");
+ do_check_eq(GMPScope.GMPPrefs.get(GMPScope.GMPPrefs.KEY_PLUGIN_AUTOUPDATE, undefined, addon2),
+ false);
+ do_check_true(GMPScope.GMPPrefs.get(GMPScope.GMPPrefs.KEY_CERT_CHECKATTRS));
+ GMPScope.GMPPrefs.set(GMPScope.GMPPrefs.KEY_PLUGIN_AUTOUPDATE, true, addon2);
+});
+
+/**
+ * Tests that an uninit without a check works fine
+ */
+add_task(function* test_checkForAddons_uninitWithoutCheck() {
+ let installManager = new GMPInstallManager();
+ installManager.uninit();
+});
+
+/**
+ * Tests that an uninit without an install works fine
+ */
+add_test(function test_checkForAddons_uninitWithoutInstall() {
+ overrideXHR(200, "");
+ let installManager = new GMPInstallManager();
+ let promise = installManager.checkForAddons();
+ promise.then(res => {
+ do_check_true(res.usedFallback);
+ installManager.uninit();
+ run_next_test();
+ });
+});
+
+/**
+ * Tests that no response returned rejects
+ */
+add_test(function test_checkForAddons_noResponse() {
+ overrideXHR(200, "");
+ let installManager = new GMPInstallManager();
+ let promise = installManager.checkForAddons();
+ promise.then(res => {
+ do_check_true(res.usedFallback);
+ installManager.uninit();
+ run_next_test();
+ });
+});
+
+/**
+ * Tests that no addons element returned resolves with no addons
+ */
+add_task(function* test_checkForAddons_noAddonsElement() {
+ overrideXHR(200, "<updates></updates>");
+ let installManager = new GMPInstallManager();
+ let res = yield installManager.checkForAddons();
+ do_check_eq(res.gmpAddons.length, 0);
+ installManager.uninit();
+});
+
+/**
+ * Tests that empty addons element returned resolves with no addons
+ */
+add_task(function* test_checkForAddons_emptyAddonsElement() {
+ overrideXHR(200, "<updates><addons/></updates>");
+ let installManager = new GMPInstallManager();
+ let res = yield installManager.checkForAddons();
+ do_check_eq(res.gmpAddons.length, 0);
+ installManager.uninit();
+});
+
+/**
+ * Tests that a response with the wrong root element rejects
+ */
+add_test(function test_checkForAddons_wrongResponseXML() {
+ overrideXHR(200, "<digits_of_pi>3.141592653589793....</digits_of_pi>");
+ let installManager = new GMPInstallManager();
+ let promise = installManager.checkForAddons();
+ promise.then(res => {
+ do_check_true(res.usedFallback);
+ installManager.uninit();
+ run_next_test();
+ });
+});
+
+/**
+ * Tests that a 404 error works as expected
+ */
+add_test(function test_checkForAddons_404Error() {
+ overrideXHR(404, "");
+ let installManager = new GMPInstallManager();
+ let promise = installManager.checkForAddons();
+ promise.then(res => {
+ do_check_true(res.usedFallback);
+ installManager.uninit();
+ run_next_test();
+ });
+});
+
+/**
+ * Tests that a xhr abort() works as expected
+ */
+add_test(function test_checkForAddons_abort() {
+ let overriddenXhr = overrideXHR(200, "", { dropRequest: true} );
+ let installManager = new GMPInstallManager();
+ let promise = installManager.checkForAddons();
+ overriddenXhr.abort();
+ promise.then(res => {
+ do_check_true(res.usedFallback);
+ installManager.uninit();
+ run_next_test();
+ });
+});
+
+/**
+ * Tests that a defensive timeout works as expected
+ */
+add_test(function test_checkForAddons_timeout() {
+ overrideXHR(200, "", { dropRequest: true, timeout: true });
+ let installManager = new GMPInstallManager();
+ let promise = installManager.checkForAddons();
+ promise.then(res => {
+ do_check_true(res.usedFallback);
+ installManager.uninit();
+ run_next_test();
+ });
+});
+
+/**
+ * Tests that we throw correctly in case of ssl certification error.
+ */
+add_test(function test_checkForAddons_bad_ssl() {
+ //
+ // Add random stuff that cause CertUtil to require https.
+ //
+ let PREF_KEY_URL_OVERRIDE_BACKUP =
+ Preferences.get(GMPScope.GMPPrefs.KEY_URL_OVERRIDE, undefined);
+ Preferences.reset(GMPScope.GMPPrefs.KEY_URL_OVERRIDE);
+
+ let CERTS_BRANCH_DOT_ONE = GMPScope.GMPPrefs.KEY_CERTS_BRANCH + ".1";
+ let PREF_CERTS_BRANCH_DOT_ONE_BACKUP =
+ Preferences.get(CERTS_BRANCH_DOT_ONE, undefined);
+ Services.prefs.setCharPref(CERTS_BRANCH_DOT_ONE, "funky value");
+
+
+ overrideXHR(200, "");
+ let installManager = new GMPInstallManager();
+ let promise = installManager.checkForAddons();
+ promise.then(res => {
+ do_check_true(res.usedFallback);
+ installManager.uninit();
+ if (PREF_KEY_URL_OVERRIDE_BACKUP) {
+ Preferences.set(GMPScope.GMPPrefs.KEY_URL_OVERRIDE,
+ PREF_KEY_URL_OVERRIDE_BACKUP);
+ }
+ if (PREF_CERTS_BRANCH_DOT_ONE_BACKUP) {
+ Preferences.set(CERTS_BRANCH_DOT_ONE,
+ PREF_CERTS_BRANCH_DOT_ONE_BACKUP);
+ }
+ run_next_test();
+ });
+});
+
+/**
+ * Tests that gettinga a funky non XML response works as expected
+ */
+add_test(function test_checkForAddons_notXML() {
+ overrideXHR(200, "3.141592653589793....");
+ let installManager = new GMPInstallManager();
+ let promise = installManager.checkForAddons();
+
+ promise.then(res => {
+ do_check_true(res.usedFallback);
+ installManager.uninit();
+ run_next_test();
+ });
+});
+
+/**
+ * Tests that getting a response with a single addon works as expected
+ */
+add_task(function* test_checkForAddons_singleAddon() {
+ let responseXML =
+ "<?xml version=\"1.0\"?>" +
+ "<updates>" +
+ " <addons>" +
+ " <addon id=\"gmp-gmpopenh264\"" +
+ " URL=\"http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip\"" +
+ " hashFunction=\"sha256\"" +
+ " hashValue=\"1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
+ " version=\"1.1\"/>" +
+ " </addons>" +
+ "</updates>"
+ overrideXHR(200, responseXML);
+ let installManager = new GMPInstallManager();
+ let res = yield installManager.checkForAddons();
+ do_check_eq(res.gmpAddons.length, 1);
+ let gmpAddon = res.gmpAddons[0];
+ do_check_eq(gmpAddon.id, "gmp-gmpopenh264");
+ do_check_eq(gmpAddon.URL, "http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip");
+ do_check_eq(gmpAddon.hashFunction, "sha256");
+ do_check_eq(gmpAddon.hashValue, "1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee");
+ do_check_eq(gmpAddon.version, "1.1");
+ do_check_eq(gmpAddon.size, undefined);
+ do_check_true(gmpAddon.isValid);
+ do_check_false(gmpAddon.isInstalled);
+ installManager.uninit();
+});
+
+/**
+ * Tests that getting a response with a single addon with the optional size
+ * attribute parses as expected.
+ */
+add_task(function* test_checkForAddons_singleAddonWithSize() {
+ let responseXML =
+ "<?xml version=\"1.0\"?>" +
+ "<updates>" +
+ " <addons>" +
+ " <addon id=\"openh264-plugin-no-at-symbol\"" +
+ " URL=\"http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip\"" +
+ " hashFunction=\"sha256\"" +
+ " size=\"42\"" +
+ " hashValue=\"1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
+ " version=\"1.1\"/>" +
+ " </addons>" +
+ "</updates>"
+ overrideXHR(200, responseXML);
+ let installManager = new GMPInstallManager();
+ let res = yield installManager.checkForAddons();
+ do_check_eq(res.gmpAddons.length, 1);
+ let gmpAddon = res.gmpAddons[0];
+ do_check_eq(gmpAddon.id, "openh264-plugin-no-at-symbol");
+ do_check_eq(gmpAddon.URL, "http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip");
+ do_check_eq(gmpAddon.hashFunction, "sha256");
+ do_check_eq(gmpAddon.hashValue, "1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee");
+ do_check_eq(gmpAddon.size, 42);
+ do_check_eq(gmpAddon.version, "1.1");
+ do_check_true(gmpAddon.isValid);
+ do_check_false(gmpAddon.isInstalled);
+ installManager.uninit();
+});
+
+/**
+ * Tests that checking for multiple addons work correctly.
+ * Also tests that invalid addons work correctly.
+ */
+add_task(function* test_checkForAddons_multipleAddonNoUpdatesSomeInvalid() {
+ let responseXML =
+ "<?xml version=\"1.0\"?>" +
+ "<updates>" +
+ " <addons>" +
+ // valid openh264
+ " <addon id=\"gmp-gmpopenh264\"" +
+ " URL=\"http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip\"" +
+ " hashFunction=\"sha256\"" +
+ " hashValue=\"1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
+ " version=\"1.1\"/>" +
+ // valid not openh264
+ " <addon id=\"NOT-gmp-gmpopenh264\"" +
+ " URL=\"http://127.0.0.1:8011/NOT-gmp-gmpopenh264-1.1.zip\"" +
+ " hashFunction=\"sha512\"" +
+ " hashValue=\"141592656f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
+ " version=\"9.1\"/>" +
+ // noid
+ " <addon notid=\"NOT-gmp-gmpopenh264\"" +
+ " URL=\"http://127.0.0.1:8011/NOT-gmp-gmpopenh264-1.1.zip\"" +
+ " hashFunction=\"sha512\"" +
+ " hashValue=\"141592656f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
+ " version=\"9.1\"/>" +
+ // no URL
+ " <addon id=\"NOT-gmp-gmpopenh264\"" +
+ " notURL=\"http://127.0.0.1:8011/NOT-gmp-gmpopenh264-1.1.zip\"" +
+ " hashFunction=\"sha512\"" +
+ " hashValue=\"141592656f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
+ " version=\"9.1\"/>" +
+ // no hash function
+ " <addon id=\"NOT-gmp-gmpopenh264\"" +
+ " URL=\"http://127.0.0.1:8011/NOT-gmp-gmpopenh264-1.1.zip\"" +
+ " nothashFunction=\"sha512\"" +
+ " hashValue=\"141592656f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
+ " version=\"9.1\"/>" +
+ // no hash function
+ " <addon id=\"NOT-gmp-gmpopenh264\"" +
+ " URL=\"http://127.0.0.1:8011/NOT-gmp-gmpopenh264-1.1.zip\"" +
+ " hashFunction=\"sha512\"" +
+ " nothashValue=\"141592656f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
+ " version=\"9.1\"/>" +
+ // not version
+ " <addon id=\"NOT-gmp-gmpopenh264\"" +
+ " URL=\"http://127.0.0.1:8011/NOT-gmp-gmpopenh264-1.1.zip\"" +
+ " hashFunction=\"sha512\"" +
+ " hashValue=\"141592656f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
+ " notversion=\"9.1\"/>" +
+ " </addons>" +
+ "</updates>"
+ overrideXHR(200, responseXML);
+ let installManager = new GMPInstallManager();
+ let res = yield installManager.checkForAddons();
+ do_check_eq(res.gmpAddons.length, 7);
+ let gmpAddon = res.gmpAddons[0];
+ do_check_eq(gmpAddon.id, "gmp-gmpopenh264");
+ do_check_eq(gmpAddon.URL, "http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip");
+ do_check_eq(gmpAddon.hashFunction, "sha256");
+ do_check_eq(gmpAddon.hashValue, "1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee");
+ do_check_eq(gmpAddon.version, "1.1");
+ do_check_true(gmpAddon.isValid);
+ do_check_false(gmpAddon.isInstalled);
+
+ gmpAddon = res.gmpAddons[1];
+ do_check_eq(gmpAddon.id, "NOT-gmp-gmpopenh264");
+ do_check_eq(gmpAddon.URL, "http://127.0.0.1:8011/NOT-gmp-gmpopenh264-1.1.zip");
+ do_check_eq(gmpAddon.hashFunction, "sha512");
+ do_check_eq(gmpAddon.hashValue, "141592656f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee");
+ do_check_eq(gmpAddon.version, "9.1");
+ do_check_true(gmpAddon.isValid);
+ do_check_false(gmpAddon.isInstalled);
+
+ for (let i = 2; i < res.gmpAddons.length; i++) {
+ do_check_false(res.gmpAddons[i].isValid);
+ do_check_false(res.gmpAddons[i].isInstalled);
+ }
+ installManager.uninit();
+});
+
+/**
+ * Tests that checking for addons when there are also updates available
+ * works as expected.
+ */
+add_task(function* test_checkForAddons_updatesWithAddons() {
+ let responseXML =
+ "<?xml version=\"1.0\"?>" +
+ " <updates>" +
+ " <update type=\"minor\" displayVersion=\"33.0a1\" appVersion=\"33.0a1\" platformVersion=\"33.0a1\" buildID=\"20140628030201\">" +
+ " <patch type=\"complete\" URL=\"http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/2014/06/2014-06-28-03-02-01-mozilla-central/firefox-33.0a1.en-US.mac.complete.mar\" hashFunction=\"sha512\" hashValue=\"f3f90d71dff03ae81def80e64bba3e4569da99c9e15269f731c2b167c4fc30b3aed9f5fee81c19614120230ca333e73a5e7def1b8e45d03135b2069c26736219\" size=\"85249896\"/>" +
+ " </update>" +
+ " <addons>" +
+ " <addon id=\"gmp-gmpopenh264\"" +
+ " URL=\"http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip\"" +
+ " hashFunction=\"sha256\"" +
+ " hashValue=\"1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
+ " version=\"1.1\"/>" +
+ " </addons>" +
+ "</updates>"
+ overrideXHR(200, responseXML);
+ let installManager = new GMPInstallManager();
+ let res = yield installManager.checkForAddons();
+ do_check_eq(res.gmpAddons.length, 1);
+ let gmpAddon = res.gmpAddons[0];
+ do_check_eq(gmpAddon.id, "gmp-gmpopenh264");
+ do_check_eq(gmpAddon.URL, "http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip");
+ do_check_eq(gmpAddon.hashFunction, "sha256");
+ do_check_eq(gmpAddon.hashValue, "1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee");
+ do_check_eq(gmpAddon.version, "1.1");
+ do_check_true(gmpAddon.isValid);
+ do_check_false(gmpAddon.isInstalled);
+ installManager.uninit();
+});
+
+/**
+ * Tests that installing found addons works as expected
+ */
+function* test_checkForAddons_installAddon(id, includeSize, wantInstallReject) {
+ do_print("Running installAddon for id: " + id +
+ ", includeSize: " + includeSize +
+ " and wantInstallReject: " + wantInstallReject);
+ let httpServer = new HttpServer();
+ let dir = FileUtils.getDir("TmpD", [], true);
+ httpServer.registerDirectory("/", dir);
+ httpServer.start(-1);
+ let testserverPort = httpServer.identity.primaryPort;
+ let zipFileName = "test_" + id + "_GMP.zip";
+
+ let zipURL = URL_HOST + ":" + testserverPort + "/" + zipFileName;
+ do_print("zipURL: " + zipURL);
+
+ let data = "e~=0.5772156649";
+ let zipFile = createNewZipFile(zipFileName, data);
+ let hashFunc = "sha256";
+ let expectedDigest = yield computeHash(hashFunc, zipFile.path);
+ let fileSize = zipFile.fileSize;
+ if (wantInstallReject) {
+ fileSize = 1;
+ }
+
+ let responseXML =
+ "<?xml version=\"1.0\"?>" +
+ "<updates>" +
+ " <addons>" +
+ " <addon id=\"" + id + "-gmp-gmpopenh264\"" +
+ " URL=\"" + zipURL + "\"" +
+ " hashFunction=\"" + hashFunc + "\"" +
+ " hashValue=\"" + expectedDigest + "\"" +
+ (includeSize ? " size=\"" + fileSize + "\"" : "") +
+ " version=\"1.1\"/>" +
+ " </addons>" +
+ "</updates>"
+
+ overrideXHR(200, responseXML);
+ let installManager = new GMPInstallManager();
+ let res = yield installManager.checkForAddons();
+ do_check_eq(res.gmpAddons.length, 1);
+ let gmpAddon = res.gmpAddons[0];
+ do_check_false(gmpAddon.isInstalled);
+
+ try {
+ let extractedPaths = yield installManager.installAddon(gmpAddon);
+ if (wantInstallReject) {
+ do_check_true(false); // installAddon() should have thrown.
+ }
+ do_check_eq(extractedPaths.length, 1);
+ let extractedPath = extractedPaths[0];
+
+ do_print("Extracted path: " + extractedPath);
+
+ let extractedFile = Cc["@mozilla.org/file/local;1"].
+ createInstance(Ci.nsIFile);
+ extractedFile.initWithPath(extractedPath);
+ do_check_true(extractedFile.exists());
+ let readData = readStringFromFile(extractedFile);
+ do_check_eq(readData, data);
+
+ // Make sure the prefs are set correctly
+ do_check_true(!!GMPScope.GMPPrefs.get(
+ GMPScope.GMPPrefs.KEY_PLUGIN_LAST_UPDATE, "", gmpAddon.id));
+ do_check_eq(GMPScope.GMPPrefs.get(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, "",
+ gmpAddon.id),
+ "1.1");
+ do_check_eq(GMPScope.GMPPrefs.get(GMPScope.GMPPrefs.KEY_PLUGIN_ABI, "",
+ gmpAddon.id),
+ UpdateUtils.ABI);
+ // Make sure it reports as being installed
+ do_check_true(gmpAddon.isInstalled);
+
+ // Cleanup
+ extractedFile.parent.remove(true);
+ zipFile.remove(false);
+ httpServer.stop(function() {});
+ installManager.uninit();
+ } catch (ex) {
+ zipFile.remove(false);
+ if (!wantInstallReject) {
+ do_throw("install update should not reject " + ex.message);
+ }
+ }
+}
+
+add_task(test_checkForAddons_installAddon.bind(null, "1", true, false));
+add_task(test_checkForAddons_installAddon.bind(null, "2", false, false));
+add_task(test_checkForAddons_installAddon.bind(null, "3", true, true));
+
+/**
+ * Tests simpleCheckAndInstall when autoupdate is disabled for a GMP
+ */
+add_task(function* test_simpleCheckAndInstall_autoUpdateDisabled() {
+ GMPScope.GMPPrefs.set(GMPScope.GMPPrefs.KEY_PLUGIN_AUTOUPDATE, false, GMPScope.OPEN_H264_ID);
+ let responseXML =
+ "<?xml version=\"1.0\"?>" +
+ "<updates>" +
+ " <addons>" +
+ // valid openh264
+ " <addon id=\"gmp-gmpopenh264\"" +
+ " URL=\"http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip\"" +
+ " hashFunction=\"sha256\"" +
+ " hashValue=\"1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
+ " version=\"1.1\"/>" +
+ " </addons>" +
+ "</updates>"
+
+ overrideXHR(200, responseXML);
+ let installManager = new GMPInstallManager();
+ let result = yield installManager.simpleCheckAndInstall();
+ do_check_eq(result.status, "nothing-new-to-install");
+ Preferences.reset(GMPScope.GMPPrefs.KEY_UPDATE_LAST_CHECK);
+ GMPScope.GMPPrefs.set(GMPScope.GMPPrefs.KEY_PLUGIN_AUTOUPDATE, true, GMPScope.OPEN_H264_ID);
+});
+
+/**
+ * Tests simpleCheckAndInstall nothing to install
+ */
+add_task(function* test_simpleCheckAndInstall_nothingToInstall() {
+ let responseXML =
+ "<?xml version=\"1.0\"?>" +
+ "<updates>" +
+ "</updates>"
+
+ overrideXHR(200, responseXML);
+ let installManager = new GMPInstallManager();
+ let result = yield installManager.simpleCheckAndInstall();
+ do_check_eq(result.status, "nothing-new-to-install");
+});
+
+/**
+ * Tests simpleCheckAndInstall too frequent
+ */
+add_task(function* test_simpleCheckAndInstall_tooFrequent() {
+ let responseXML =
+ "<?xml version=\"1.0\"?>" +
+ "<updates>" +
+ "</updates>"
+
+ overrideXHR(200, responseXML);
+ let installManager = new GMPInstallManager();
+ let result = yield installManager.simpleCheckAndInstall();
+ do_check_eq(result.status, "too-frequent-no-check");
+});
+
+/**
+ * Tests that installing addons when there is no server works as expected
+ */
+add_test(function test_installAddon_noServer() {
+ let dir = FileUtils.getDir("TmpD", [], true);
+ let zipFileName = "test_GMP.zip";
+ let zipURL = URL_HOST + ":0/" + zipFileName;
+
+ let data = "e~=0.5772156649";
+ let zipFile = createNewZipFile(zipFileName, data);
+
+ let responseXML =
+ "<?xml version=\"1.0\"?>" +
+ "<updates>" +
+ " <addons>" +
+ " <addon id=\"gmp-gmpopenh264\"" +
+ " URL=\"" + zipURL + "\"" +
+ " hashFunction=\"sha256\"" +
+ " hashValue=\"11221cbda000347b054028b527a60e578f919cb10f322ef8077d3491c6fcb474\"" +
+ " version=\"1.1\"/>" +
+ " </addons>" +
+ "</updates>"
+
+ overrideXHR(200, responseXML);
+ let installManager = new GMPInstallManager();
+ let checkPromise = installManager.checkForAddons();
+ checkPromise.then(res => {
+ do_check_eq(res.gmpAddons.length, 1);
+ let gmpAddon = res.gmpAddons[0];
+
+ GMPInstallManager.overrideLeaveDownloadedZip = true;
+ let installPromise = installManager.installAddon(gmpAddon);
+ installPromise.then(extractedPaths => {
+ do_throw("No server for install should reject");
+ }, err => {
+ do_check_true(!!err);
+ installManager.uninit();
+ run_next_test();
+ });
+ }, () => {
+ do_throw("check should not reject for install no server");
+ });
+});
+
+/**
+ * Returns the read stream into a string
+ */
+function readStringFromInputStream(inputStream) {
+ let sis = Cc["@mozilla.org/scriptableinputstream;1"].
+ createInstance(Ci.nsIScriptableInputStream);
+ sis.init(inputStream);
+ let text = sis.read(sis.available());
+ sis.close();
+ return text;
+}
+
+/**
+ * Reads a string of text from a file.
+ * This function only works with ASCII text.
+ */
+function readStringFromFile(file) {
+ if (!file.exists()) {
+ do_print("readStringFromFile - file doesn't exist: " + file.path);
+ return null;
+ }
+ let fis = Cc["@mozilla.org/network/file-input-stream;1"].
+ createInstance(Ci.nsIFileInputStream);
+ fis.init(file, FileUtils.MODE_RDONLY, FileUtils.PERMS_FILE, 0);
+ return readStringFromInputStream(fis);
+}
+
+/**
+ * Bare bones XMLHttpRequest implementation for testing onprogress, onerror,
+ * and onload nsIDomEventListener handleEvent.
+ */
+function makeHandler(aVal) {
+ if (typeof aVal == "function")
+ return { handleEvent: aVal };
+ return aVal;
+}
+/**
+ * Constructs a mock xhr which is used for testing different aspects
+ * of responses.
+ */
+function xhr(inputStatus, inputResponse, options) {
+ this.inputStatus = inputStatus;
+ this.inputResponse = inputResponse;
+ this.status = 0;
+ this.responseXML = null;
+ this._aborted = false;
+ this._onabort = null;
+ this._onprogress = null;
+ this._onerror = null;
+ this._onload = null;
+ this._onloadend = null;
+ this._ontimeout = null;
+ this._url = null;
+ this._method = null;
+ this._timeout = 0;
+ this._notified = false;
+ this._options = options || {};
+}
+xhr.prototype = {
+ overrideMimeType: function(aMimetype) { },
+ setRequestHeader: function(aHeader, aValue) { },
+ status: null,
+ channel: { set notificationCallbacks(aVal) { } },
+ open: function(aMethod, aUrl) {
+ this.channel.originalURI = Services.io.newURI(aUrl, null, null);
+ this._method = aMethod; this._url = aUrl;
+ },
+ abort: function() {
+ this._dropRequest = true;
+ this._notify(["abort", "loadend"]);
+ },
+ responseXML: null,
+ responseText: null,
+ send: function(aBody) {
+ do_execute_soon(function() {
+ try {
+ if (this._options.dropRequest) {
+ if (this._timeout > 0 && this._options.timeout) {
+ this._notify(["timeout", "loadend"]);
+ }
+ return;
+ }
+ this.status = this.inputStatus;
+ this.responseText = this.inputResponse;
+ try {
+ let parser = Cc["@mozilla.org/xmlextras/domparser;1"].
+ createInstance(Ci.nsIDOMParser);
+ this.responseXML = parser.parseFromString(this.inputResponse,
+ "application/xml");
+ } catch (e) {
+ this.responseXML = null;
+ }
+ if (this.inputStatus === 200) {
+ this._notify(["load", "loadend"]);
+ } else {
+ this._notify(["error", "loadend"]);
+ }
+ } catch (ex) {
+ do_throw(ex);
+ }
+ }.bind(this));
+ },
+ set onabort(aValue) { this._onabort = makeHandler(aValue); },
+ get onabort() { return this._onabort; },
+ set onprogress(aValue) { this._onprogress = makeHandler(aValue); },
+ get onprogress() { return this._onprogress; },
+ set onerror(aValue) { this._onerror = makeHandler(aValue); },
+ get onerror() { return this._onerror; },
+ set onload(aValue) { this._onload = makeHandler(aValue); },
+ get onload() { return this._onload; },
+ set onloadend(aValue) { this._onloadend = makeHandler(aValue); },
+ get onloadend() { return this._onloadend; },
+ set ontimeout(aValue) { this._ontimeout = makeHandler(aValue); },
+ get ontimeout() { return this._ontimeout; },
+ set timeout(aValue) { this._timeout = aValue; },
+ _notify: function(events) {
+ if (this._notified) {
+ return;
+ }
+ this._notified = true;
+ for (let item of events) {
+ let k = "on" + item;
+ if (this[k]) {
+ do_print("Notifying " + item);
+ let e = {
+ target: this,
+ type: item,
+ };
+ this[k](e);
+ } else {
+ do_print("Notifying " + item + ", but there are no listeners");
+ }
+ }
+ },
+ addEventListener: function(aEvent, aValue, aCapturing) {
+ eval("this._on" + aEvent + " = aValue");
+ },
+ flags: Ci.nsIClassInfo.SINGLETON,
+ getScriptableHelper: () => null,
+ getInterfaces: function(aCount) {
+ let interfaces = [Ci.nsISupports];
+ aCount.value = interfaces.length;
+ return interfaces;
+ },
+ classDescription: "XMLHttpRequest",
+ contractID: "@mozilla.org/xmlextras/xmlhttprequest;1",
+ classID: Components.ID("{c9b37f43-4278-4304-a5e0-600991ab08cb}"),
+ createInstance: function(aOuter, aIID) {
+ if (aOuter == null)
+ return this.QueryInterface(aIID);
+ throw Cr.NS_ERROR_NO_AGGREGATION;
+ },
+ QueryInterface: function(aIID) {
+ if (aIID.equals(Ci.nsIClassInfo) ||
+ aIID.equals(Ci.nsISupports))
+ return this;
+ throw Cr.NS_ERROR_NO_INTERFACE;
+ },
+ get wrappedJSObject() { return this; }
+};
+
+/**
+ * Helper used to overrideXHR requests (no matter to what URL) with the
+ * specified status and response.
+ * @param status The status you want to get back when an XHR request is made
+ * @param response The response you want to get back when an XHR request is made
+ */
+function overrideXHR(status, response, options) {
+ overrideXHR.myxhr = new xhr(status, response, options);
+ ProductAddonCheckerScope.CreateXHR = function() {
+ return overrideXHR.myxhr;
+ };
+ return overrideXHR.myxhr;
+}
+
+/**
+ * Creates a new zip file containing a file with the specified data
+ * @param zipName The name of the zip file
+ * @param data The data to go inside the zip for the filename entry1.info
+ */
+function createNewZipFile(zipName, data) {
+ // Create a zip file which will be used for extracting
+ let stream = Cc["@mozilla.org/io/string-input-stream;1"].
+ createInstance(Ci.nsIStringInputStream);
+ stream.setData(data, data.length);
+ let zipWriter = Cc["@mozilla.org/zipwriter;1"].
+ createInstance(Components.interfaces.nsIZipWriter);
+ let zipFile = FileUtils.getFile("TmpD", [zipName]);
+ if (zipFile.exists()) {
+ zipFile.remove(false);
+ }
+ // From prio.h
+ const PR_RDWR = 0x04;
+ const PR_CREATE_FILE = 0x08;
+ const PR_TRUNCATE = 0x20;
+ zipWriter.open(zipFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
+ zipWriter.addEntryStream("entry1.info", Date.now(),
+ Ci.nsIZipWriter.COMPRESSION_BEST, stream, false);
+ zipWriter.close();
+ stream.close();
+ do_print("zip file created on disk at: " + zipFile.path);
+ return zipFile;
+}