mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-12 14:37:50 +00:00
ecb5f27751
* * * Bug 804480 - Intermittent test_addons_store.js test_addons_store.js | test failed (with xpcshell return code: 0), | Error: 1 or more add-ons failed to install. r=gps
464 lines
13 KiB
JavaScript
464 lines
13 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
"use strict";
|
|
|
|
Cu.import("resource://services-common/preferences.js");
|
|
Cu.import("resource://services-sync/addonutils.js");
|
|
Cu.import("resource://services-sync/engines/addons.js");
|
|
Cu.import("resource://services-sync/service.js");
|
|
Cu.import("resource://services-sync/util.js");
|
|
|
|
const HTTP_PORT = 8888;
|
|
|
|
let prefs = new Preferences();
|
|
|
|
prefs.set("extensions.getAddons.get.url", "http://localhost:8888/search/guid:%IDS%");
|
|
loadAddonTestFunctions();
|
|
startupManager();
|
|
|
|
Service.engineManager.register(AddonsEngine);
|
|
let engine = Service.engineManager.get("addons");
|
|
let tracker = engine._tracker;
|
|
let store = engine._store;
|
|
let reconciler = engine._reconciler;
|
|
|
|
/**
|
|
* Create a AddonsRec for this application with the fields specified.
|
|
*
|
|
* @param id Sync GUID of record
|
|
* @param addonId ID of add-on
|
|
* @param enabled Boolean whether record is enabled
|
|
* @param deleted Boolean whether record was deleted
|
|
*/
|
|
function createRecordForThisApp(id, addonId, enabled, deleted) {
|
|
return {
|
|
id: id,
|
|
addonID: addonId,
|
|
enabled: enabled,
|
|
deleted: !!deleted,
|
|
applicationID: Services.appinfo.ID,
|
|
source: "amo"
|
|
};
|
|
}
|
|
|
|
function createAndStartHTTPServer(port) {
|
|
try {
|
|
let server = new HttpServer();
|
|
|
|
let bootstrap1XPI = ExtensionsTestPath("/addons/test_bootstrap1_1.xpi");
|
|
|
|
server.registerFile("/search/guid:bootstrap1%40tests.mozilla.org",
|
|
do_get_file("bootstrap1-search.xml"));
|
|
server.registerFile("/bootstrap1.xpi", do_get_file(bootstrap1XPI));
|
|
|
|
server.registerFile("/search/guid:missing-xpi%40tests.mozilla.org",
|
|
do_get_file("missing-xpi-search.xml"));
|
|
|
|
server.start(port);
|
|
|
|
return server;
|
|
} catch (ex) {
|
|
_("Got exception starting HTTP server on port " + port);
|
|
_("Error: " + Utils.exceptionStr(ex));
|
|
do_throw(ex);
|
|
}
|
|
}
|
|
|
|
function run_test() {
|
|
initTestLogging("Trace");
|
|
Log4Moz.repository.getLogger("Sync.Engine.Addons").level = Log4Moz.Level.Trace;
|
|
Log4Moz.repository.getLogger("Sync.AddonsRepository").level =
|
|
Log4Moz.Level.Trace;
|
|
|
|
reconciler.startListening();
|
|
|
|
run_next_test();
|
|
}
|
|
|
|
add_test(function test_remove() {
|
|
_("Ensure removing add-ons from deleted records works.");
|
|
|
|
let addon = installAddon("test_bootstrap1_1");
|
|
let record = createRecordForThisApp(addon.syncGUID, addon.id, true, true);
|
|
|
|
let failed = store.applyIncomingBatch([record]);
|
|
do_check_eq(0, failed.length);
|
|
|
|
let newAddon = getAddonFromAddonManagerByID(addon.id);
|
|
do_check_eq(null, newAddon);
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_apply_enabled() {
|
|
_("Ensures that changes to the userEnabled flag apply.");
|
|
|
|
let addon = installAddon("test_bootstrap1_1");
|
|
do_check_true(addon.isActive);
|
|
do_check_false(addon.userDisabled);
|
|
|
|
_("Ensure application of a disable record works as expected.");
|
|
let records = [];
|
|
records.push(createRecordForThisApp(addon.syncGUID, addon.id, false, false));
|
|
let failed = store.applyIncomingBatch(records);
|
|
do_check_eq(0, failed.length);
|
|
addon = getAddonFromAddonManagerByID(addon.id);
|
|
do_check_true(addon.userDisabled);
|
|
records = [];
|
|
|
|
_("Ensure enable record works as expected.");
|
|
records.push(createRecordForThisApp(addon.syncGUID, addon.id, true, false));
|
|
failed = store.applyIncomingBatch(records);
|
|
do_check_eq(0, failed.length);
|
|
addon = getAddonFromAddonManagerByID(addon.id);
|
|
do_check_false(addon.userDisabled);
|
|
records = [];
|
|
|
|
_("Ensure enabled state updates don't apply if the ignore pref is set.");
|
|
records.push(createRecordForThisApp(addon.syncGUID, addon.id, false, false));
|
|
Svc.Prefs.set("addons.ignoreUserEnabledChanges", true);
|
|
failed = store.applyIncomingBatch(records);
|
|
do_check_eq(0, failed.length);
|
|
addon = getAddonFromAddonManagerByID(addon.id);
|
|
do_check_false(addon.userDisabled);
|
|
records = [];
|
|
|
|
uninstallAddon(addon);
|
|
Svc.Prefs.reset("addons.ignoreUserEnabledChanges");
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_ignore_different_appid() {
|
|
_("Ensure that incoming records with a different application ID are ignored.");
|
|
|
|
// We test by creating a record that should result in an update.
|
|
let addon = installAddon("test_bootstrap1_1");
|
|
do_check_false(addon.userDisabled);
|
|
|
|
let record = createRecordForThisApp(addon.syncGUID, addon.id, false, false);
|
|
record.applicationID = "FAKE_ID";
|
|
|
|
let failed = store.applyIncomingBatch([record]);
|
|
do_check_eq(0, failed.length);
|
|
|
|
let newAddon = getAddonFromAddonManagerByID(addon.id);
|
|
do_check_false(addon.userDisabled);
|
|
|
|
uninstallAddon(addon);
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_ignore_unknown_source() {
|
|
_("Ensure incoming records with unknown source are ignored.");
|
|
|
|
let addon = installAddon("test_bootstrap1_1");
|
|
|
|
let record = createRecordForThisApp(addon.syncGUID, addon.id, false, false);
|
|
record.source = "DUMMY_SOURCE";
|
|
|
|
let failed = store.applyIncomingBatch([record]);
|
|
do_check_eq(0, failed.length);
|
|
|
|
let newAddon = getAddonFromAddonManagerByID(addon.id);
|
|
do_check_false(addon.userDisabled);
|
|
|
|
uninstallAddon(addon);
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_apply_uninstall() {
|
|
_("Ensures that uninstalling an add-on from a record works.");
|
|
|
|
let addon = installAddon("test_bootstrap1_1");
|
|
|
|
let records = [];
|
|
records.push(createRecordForThisApp(addon.syncGUID, addon.id, true, true));
|
|
let failed = store.applyIncomingBatch(records);
|
|
do_check_eq(0, failed.length);
|
|
|
|
addon = getAddonFromAddonManagerByID(addon.id);
|
|
do_check_eq(null, addon);
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_addon_syncability() {
|
|
_("Ensure isAddonSyncable functions properly.");
|
|
|
|
Svc.Prefs.set("addons.ignoreRepositoryChecking", true);
|
|
Svc.Prefs.set("addons.trustedSourceHostnames",
|
|
"addons.mozilla.org,other.example.com");
|
|
|
|
do_check_false(store.isAddonSyncable(null));
|
|
|
|
let addon = installAddon("test_bootstrap1_1");
|
|
do_check_true(store.isAddonSyncable(addon));
|
|
|
|
let dummy = {};
|
|
const KEYS = ["id", "syncGUID", "type", "scope", "foreignInstall"];
|
|
for each (let k in KEYS) {
|
|
dummy[k] = addon[k];
|
|
}
|
|
|
|
do_check_true(store.isAddonSyncable(dummy));
|
|
|
|
dummy.type = "UNSUPPORTED";
|
|
do_check_false(store.isAddonSyncable(dummy));
|
|
dummy.type = addon.type;
|
|
|
|
dummy.scope = 0;
|
|
do_check_false(store.isAddonSyncable(dummy));
|
|
dummy.scope = addon.scope;
|
|
|
|
dummy.foreignInstall = true;
|
|
do_check_false(store.isAddonSyncable(dummy));
|
|
dummy.foreignInstall = false;
|
|
|
|
uninstallAddon(addon);
|
|
|
|
do_check_false(store.isSourceURITrusted(null));
|
|
|
|
function createURI(s) {
|
|
let service = Components.classes["@mozilla.org/network/io-service;1"]
|
|
.getService(Components.interfaces.nsIIOService);
|
|
return service.newURI(s, null, null);
|
|
}
|
|
|
|
let trusted = [
|
|
"https://addons.mozilla.org/foo",
|
|
"https://other.example.com/foo"
|
|
];
|
|
|
|
let untrusted = [
|
|
"http://addons.mozilla.org/foo", // non-https
|
|
"ftps://addons.mozilla.org/foo", // non-https
|
|
"https://untrusted.example.com/foo", // non-trusted hostname`
|
|
];
|
|
|
|
for each (let uri in trusted) {
|
|
do_check_true(store.isSourceURITrusted(createURI(uri)));
|
|
}
|
|
|
|
for each (let uri in untrusted) {
|
|
do_check_false(store.isSourceURITrusted(createURI(uri)));
|
|
}
|
|
|
|
Svc.Prefs.set("addons.trustedSourceHostnames", "");
|
|
for each (let uri in trusted) {
|
|
do_check_false(store.isSourceURITrusted(createURI(uri)));
|
|
}
|
|
|
|
Svc.Prefs.set("addons.trustedSourceHostnames", "addons.mozilla.org");
|
|
do_check_true(store.isSourceURITrusted(createURI("https://addons.mozilla.org/foo")));
|
|
|
|
Svc.Prefs.reset("addons.trustedSourceHostnames");
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_ignore_hotfixes() {
|
|
_("Ensure that hotfix extensions are ignored.");
|
|
|
|
Svc.Prefs.set("addons.ignoreRepositoryChecking", true);
|
|
|
|
// A hotfix extension is one that has the id the same as the
|
|
// extensions.hotfix.id pref.
|
|
let prefs = new Preferences("extensions.");
|
|
|
|
let addon = installAddon("test_bootstrap1_1");
|
|
do_check_true(store.isAddonSyncable(addon));
|
|
|
|
let dummy = {};
|
|
const KEYS = ["id", "syncGUID", "type", "scope", "foreignInstall"];
|
|
for each (let k in KEYS) {
|
|
dummy[k] = addon[k];
|
|
}
|
|
|
|
// Basic sanity check.
|
|
do_check_true(store.isAddonSyncable(dummy));
|
|
|
|
prefs.set("hotfix.id", dummy.id);
|
|
do_check_false(store.isAddonSyncable(dummy));
|
|
|
|
// Verify that int values don't throw off checking.
|
|
let prefSvc = Cc["@mozilla.org/preferences-service;1"]
|
|
.getService(Ci.nsIPrefService)
|
|
.getBranch("extensions.");
|
|
// Need to delete pref before changing type.
|
|
prefSvc.deleteBranch("hotfix.id");
|
|
prefSvc.setIntPref("hotfix.id", 0xdeadbeef);
|
|
|
|
do_check_true(store.isAddonSyncable(dummy));
|
|
|
|
uninstallAddon(addon);
|
|
|
|
Svc.Prefs.reset("addons.ignoreRepositoryChecking");
|
|
prefs.reset("hotfix.id");
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
|
|
add_test(function test_get_all_ids() {
|
|
_("Ensures that getAllIDs() returns an appropriate set.");
|
|
|
|
Svc.Prefs.set("addons.ignoreRepositoryChecking", true);
|
|
|
|
_("Installing two addons.");
|
|
let addon1 = installAddon("test_install1");
|
|
let addon2 = installAddon("test_bootstrap1_1");
|
|
|
|
_("Ensure they're syncable.");
|
|
do_check_true(store.isAddonSyncable(addon1));
|
|
do_check_true(store.isAddonSyncable(addon2));
|
|
|
|
let ids = store.getAllIDs();
|
|
|
|
do_check_eq("object", typeof(ids));
|
|
do_check_eq(2, Object.keys(ids).length);
|
|
do_check_true(addon1.syncGUID in ids);
|
|
do_check_true(addon2.syncGUID in ids);
|
|
|
|
addon1.install.cancel();
|
|
uninstallAddon(addon2);
|
|
|
|
Svc.Prefs.reset("addons.ignoreRepositoryChecking");
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_change_item_id() {
|
|
_("Ensures that changeItemID() works properly.");
|
|
|
|
let addon = installAddon("test_bootstrap1_1");
|
|
|
|
let oldID = addon.syncGUID;
|
|
let newID = Utils.makeGUID();
|
|
|
|
store.changeItemID(oldID, newID);
|
|
|
|
let newAddon = getAddonFromAddonManagerByID(addon.id);
|
|
do_check_neq(null, newAddon);
|
|
do_check_eq(newID, newAddon.syncGUID);
|
|
|
|
uninstallAddon(newAddon);
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_create() {
|
|
_("Ensure creating/installing an add-on from a record works.");
|
|
|
|
// Set this so that getInstallFromSearchResult doesn't end up
|
|
// failing the install due to an insecure source URI scheme.
|
|
Svc.Prefs.set("addons.ignoreRepositoryChecking", true);
|
|
let server = createAndStartHTTPServer(HTTP_PORT);
|
|
|
|
let addon = installAddon("test_bootstrap1_1");
|
|
let id = addon.id;
|
|
uninstallAddon(addon);
|
|
|
|
let guid = Utils.makeGUID();
|
|
let record = createRecordForThisApp(guid, id, true, false);
|
|
|
|
let failed = store.applyIncomingBatch([record]);
|
|
do_check_eq(0, failed.length);
|
|
|
|
let newAddon = getAddonFromAddonManagerByID(id);
|
|
do_check_neq(null, newAddon);
|
|
do_check_eq(guid, newAddon.syncGUID);
|
|
do_check_false(newAddon.userDisabled);
|
|
|
|
uninstallAddon(newAddon);
|
|
|
|
Svc.Prefs.reset("addons.ignoreRepositoryChecking");
|
|
server.stop(run_next_test);
|
|
});
|
|
|
|
add_test(function test_create_missing_search() {
|
|
_("Ensures that failed add-on searches are handled gracefully.");
|
|
|
|
let server = createAndStartHTTPServer(HTTP_PORT);
|
|
|
|
// The handler for this ID is not installed, so a search should 404.
|
|
const id = "missing@tests.mozilla.org";
|
|
let guid = Utils.makeGUID();
|
|
let record = createRecordForThisApp(guid, id, true, false);
|
|
|
|
let failed = store.applyIncomingBatch([record]);
|
|
do_check_eq(1, failed.length);
|
|
do_check_eq(guid, failed[0]);
|
|
|
|
let addon = getAddonFromAddonManagerByID(id);
|
|
do_check_eq(null, addon);
|
|
|
|
server.stop(run_next_test);
|
|
});
|
|
|
|
add_test(function test_create_bad_install() {
|
|
_("Ensures that add-ons without a valid install are handled gracefully.");
|
|
|
|
let server = createAndStartHTTPServer(HTTP_PORT);
|
|
|
|
// The handler returns a search result but the XPI will 404.
|
|
const id = "missing-xpi@tests.mozilla.org";
|
|
let guid = Utils.makeGUID();
|
|
let record = createRecordForThisApp(guid, id, true, false);
|
|
|
|
let failed = store.applyIncomingBatch([record]);
|
|
do_check_eq(1, failed.length);
|
|
do_check_eq(guid, failed[0]);
|
|
|
|
let addon = getAddonFromAddonManagerByID(id);
|
|
do_check_eq(null, addon);
|
|
|
|
server.stop(run_next_test);
|
|
});
|
|
|
|
add_test(function test_wipe() {
|
|
_("Ensures that wiping causes add-ons to be uninstalled.");
|
|
|
|
let addon1 = installAddon("test_bootstrap1_1");
|
|
|
|
Svc.Prefs.set("addons.ignoreRepositoryChecking", true);
|
|
store.wipe();
|
|
|
|
let addon = getAddonFromAddonManagerByID(addon1.id);
|
|
do_check_eq(null, addon);
|
|
|
|
Svc.Prefs.reset("addons.ignoreRepositoryChecking");
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_wipe_and_install() {
|
|
_("Ensure wipe followed by install works.");
|
|
|
|
// This tests the reset sync flow where remote data is replaced by local. The
|
|
// receiving client will see a wipe followed by a record which should undo
|
|
// the wipe.
|
|
let installed = installAddon("test_bootstrap1_1");
|
|
|
|
let record = createRecordForThisApp(installed.syncGUID, installed.id, true,
|
|
false);
|
|
|
|
Svc.Prefs.set("addons.ignoreRepositoryChecking", true);
|
|
store.wipe();
|
|
|
|
let deleted = getAddonFromAddonManagerByID(installed.id);
|
|
do_check_null(deleted);
|
|
|
|
// Re-applying the record can require re-fetching the XPI.
|
|
let server = createAndStartHTTPServer(HTTP_PORT);
|
|
|
|
store.applyIncoming(record);
|
|
|
|
let fetched = getAddonFromAddonManagerByID(record.addonID);
|
|
do_check_true(!!fetched);
|
|
|
|
Svc.Prefs.reset("addons.ignoreRepositoryChecking");
|
|
server.stop(run_next_test);
|
|
});
|