зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1631898 - Handle Normandy installed system search extensions. r=Standard8
Differential Revision: https://phabricator.services.mozilla.com/D74489
This commit is contained in:
Родитель
bfb8185ee4
Коммит
06c7cbc976
|
@ -774,15 +774,16 @@ EngineURL.prototype = {
|
|||
* The file URI that points to the search engine data.
|
||||
* @param {nsIURI|string} [options.uri]
|
||||
* Represents the location of the search engine data file.
|
||||
* @param {boolean} options.isBuiltin
|
||||
* Indicates whether the engine is a app-provided or not. If it is, it will
|
||||
* @param {boolean} options.isAppProvided
|
||||
* Indicates whether the engine is provided by Firefox, either
|
||||
* shipped in omni.ja or via Normandy. If it is, it will
|
||||
* be treated as read-only.
|
||||
*/
|
||||
function SearchEngine(options = {}) {
|
||||
if (!("isBuiltin" in options)) {
|
||||
throw new Error("isBuiltin missing from options.");
|
||||
if (!("isAppProvided" in options)) {
|
||||
throw new Error("isAppProvided missing from options.");
|
||||
}
|
||||
this._isBuiltin = options.isBuiltin;
|
||||
this._isAppProvided = options.isAppProvided;
|
||||
// The alias coming from the engine definition (via webextension
|
||||
// keyword field for example) may be overridden in the metaData
|
||||
// with a user defined alias.
|
||||
|
@ -840,7 +841,7 @@ function SearchEngine(options = {}) {
|
|||
shortName = file.leafName;
|
||||
} else if (uri && uri instanceof Ci.nsIURL) {
|
||||
if (
|
||||
this._isBuiltin ||
|
||||
this._isAppProvided ||
|
||||
(gEnvironment.get("XPCSHELL_TEST_PROFILE_DIR") &&
|
||||
uri.scheme == "resource")
|
||||
) {
|
||||
|
@ -910,7 +911,7 @@ SearchEngine.prototype = {
|
|||
// The locale, or "DEFAULT", if required.
|
||||
_locale: null,
|
||||
// Whether the engine is provided by the application.
|
||||
_isBuiltin: false,
|
||||
_isAppProvided: false,
|
||||
// The order hint from the configuration (if any).
|
||||
_orderHint: null,
|
||||
// The telemetry id from the configuration (if any).
|
||||
|
@ -1859,7 +1860,7 @@ SearchEngine.prototype = {
|
|||
_iconMapObj: this._iconMapObj,
|
||||
_metaData: this._metaData,
|
||||
_urls: this._urls,
|
||||
_isBuiltin: this._isBuiltin,
|
||||
_isAppProvided: this._isAppProvided,
|
||||
_orderHint: this._orderHint,
|
||||
_telemetryId: this._telemetryId,
|
||||
};
|
||||
|
@ -2108,11 +2109,11 @@ SearchEngine.prototype = {
|
|||
// For the modern configuration, distribution engines are app-provided as
|
||||
// well and we don't have xml files as app-provided engines.
|
||||
if (gModernConfig) {
|
||||
return !!(this._extensionID && this._isBuiltin);
|
||||
return !!(this._extensionID && this._isAppProvided);
|
||||
}
|
||||
|
||||
if (this._extensionID) {
|
||||
return this._isBuiltin || this._isDistribution;
|
||||
return this._isAppProvided || this._isDistribution;
|
||||
}
|
||||
|
||||
// If we don't have a shortName, the engine is being parsed from a
|
||||
|
|
|
@ -688,7 +688,7 @@ SearchService.prototype = {
|
|||
canInstallEngine: !engine?.hidden,
|
||||
};
|
||||
}
|
||||
let params = this.getEngineParams(
|
||||
let params = await this.getEngineParams(
|
||||
extension,
|
||||
extension.manifest,
|
||||
SearchUtils.DEFAULT_TAG
|
||||
|
@ -948,7 +948,7 @@ SearchService.prototype = {
|
|||
|
||||
if (
|
||||
!rebuildCache &&
|
||||
cache.engines.filter(e => e._isBuiltin).length !=
|
||||
cache.engines.filter(e => e._isAppProvided).length !=
|
||||
cache.builtInEngineList.length
|
||||
) {
|
||||
rebuildCache = true;
|
||||
|
@ -1045,7 +1045,7 @@ SearchService.prototype = {
|
|||
if (
|
||||
!rebuildCache &&
|
||||
SearchUtils.distroID == "" &&
|
||||
cache.engines.filter(e => e._isBuiltin).length !=
|
||||
cache.engines.filter(e => e._isAppProvided).length !=
|
||||
cache.visibleDefaultEngines.length
|
||||
) {
|
||||
rebuildCache = true;
|
||||
|
@ -1564,7 +1564,7 @@ SearchService.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
_loadEnginesFromCache(cache, skipBuiltIn) {
|
||||
_loadEnginesFromCache(cache, skipAppProvided) {
|
||||
if (!cache.engines) {
|
||||
return;
|
||||
}
|
||||
|
@ -1577,7 +1577,7 @@ SearchService.prototype = {
|
|||
|
||||
let skippedEngines = 0;
|
||||
for (let engine of cache.engines) {
|
||||
if (skipBuiltIn && engine._isBuiltin) {
|
||||
if (skipAppProvided && engine._isAppProvided) {
|
||||
++skippedEngines;
|
||||
continue;
|
||||
}
|
||||
|
@ -1598,7 +1598,9 @@ SearchService.prototype = {
|
|||
try {
|
||||
let engine = new SearchEngine({
|
||||
shortName: json._shortName,
|
||||
isBuiltin: !!json._isBuiltin,
|
||||
// We renamed isBuiltin to isAppProvided in 1631898,
|
||||
// keep checking isBuiltin for older caches.
|
||||
isAppProvided: !!json._isAppProvided || !!json._isBuiltin,
|
||||
});
|
||||
engine._initWithJSON(json);
|
||||
this._addEngineToStore(engine);
|
||||
|
@ -1651,7 +1653,7 @@ SearchService.prototype = {
|
|||
file.initWithPath(osfile.path);
|
||||
addedEngine = new SearchEngine({
|
||||
fileURI: file,
|
||||
isBuiltin: true,
|
||||
isAppProvided: true,
|
||||
});
|
||||
await addedEngine._initFromFile(file);
|
||||
engines.push(addedEngine);
|
||||
|
@ -2285,11 +2287,11 @@ SearchService.prototype = {
|
|||
logConsole.debug("addEngineWithDetails: Adding", name);
|
||||
let isCurrent = false;
|
||||
|
||||
let isBuiltin = !!params.isBuiltin;
|
||||
let isAppProvided = !!params.isAppProvided;
|
||||
// We install search extensions during the init phase, both built in
|
||||
// web extensions freshly installed (via addEnginesFromExtension) or
|
||||
// user installed extensions being reenabled calling this directly.
|
||||
if (!gInitialized && !isBuiltin && !params.initEngine) {
|
||||
if (!gInitialized && !isAppProvided && !params.initEngine) {
|
||||
await this.init();
|
||||
}
|
||||
let existingEngine = this._engines.get(name);
|
||||
|
@ -2325,7 +2327,7 @@ SearchService.prototype = {
|
|||
|
||||
let newEngine = new SearchEngine({
|
||||
name,
|
||||
isBuiltin,
|
||||
isAppProvided,
|
||||
});
|
||||
newEngine._initFromMetadata(name, params);
|
||||
newEngine._loadPath = "[other]addEngineWithDetails";
|
||||
|
@ -2343,37 +2345,63 @@ SearchService.prototype = {
|
|||
return newEngine;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called from the AddonManager when it either installs a new
|
||||
* extension containing a search engine definition or an upgrade
|
||||
* to an existing one.
|
||||
*
|
||||
* @param {object} extension
|
||||
* An Extension object containing data about the extension.
|
||||
*/
|
||||
async addEnginesFromExtension(extension) {
|
||||
if (extension.addonData.builtIn) {
|
||||
logConsole.debug(
|
||||
"addEnginesFromExtension: Ignoring builtIn engine:",
|
||||
extension.id
|
||||
);
|
||||
logConsole.debug("addEnginesFromExtension: " + extension.id);
|
||||
if (extension.startupReason == "ADDON_UPGRADE") {
|
||||
return this._upgradeExtensionEngine(extension);
|
||||
}
|
||||
|
||||
let addon = await AddonManager.getAddonByID(extension.id);
|
||||
if (addon.isBuiltin || addon.isSystem) {
|
||||
let inConfig = this._searchOrder.filter(el => el.id == extension.id);
|
||||
if (gInitialized && inConfig.length) {
|
||||
return this._installExtensionEngine(
|
||||
extension,
|
||||
inConfig.map(el => el.locale)
|
||||
);
|
||||
}
|
||||
logConsole.debug("addEnginesFromExtension: Ignoring builtIn engine.");
|
||||
return [];
|
||||
}
|
||||
logConsole.debug("addEnginesFromExtension:", extension.id);
|
||||
|
||||
// If we havent started SearchService yet, store this extension
|
||||
// to install in SearchService.init().
|
||||
if (!gInitialized) {
|
||||
this._startupExtensions.add(extension);
|
||||
return [];
|
||||
}
|
||||
if (extension.startupReason == "ADDON_UPGRADE") {
|
||||
let engines = await this.getEnginesByExtensionID(extension.id);
|
||||
for (let engine of engines) {
|
||||
let manifest = extension.manifest;
|
||||
let locale = engine._locale || SearchUtils.DEFAULT_TAG;
|
||||
if (locale != SearchUtils.DEFAULT_TAG) {
|
||||
manifest = await extension.getLocalizedManifest(locale);
|
||||
}
|
||||
let params = this.getEngineParams(extension, manifest, locale);
|
||||
engine._updateFromMetadata(params);
|
||||
}
|
||||
return engines;
|
||||
}
|
||||
|
||||
return this._installExtensionEngine(extension, [SearchUtils.DEFAULT_TAG]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when we see an upgrade to an existing search extension.
|
||||
*
|
||||
* @param {object} extension
|
||||
* An Extension object containing data about the extension.
|
||||
*/
|
||||
async _upgradeExtensionEngine(extension) {
|
||||
let engines = await this.getEnginesByExtensionID(extension.id);
|
||||
for (let engine of engines) {
|
||||
let manifest = extension.manifest;
|
||||
let locale = engine._locale || SearchUtils.DEFAULT_TAG;
|
||||
if (locale != SearchUtils.DEFAULT_TAG) {
|
||||
manifest = await extension.getLocalizedManifest(locale);
|
||||
}
|
||||
let params = await this.getEngineParams(extension, manifest, locale);
|
||||
engine._updateFromMetadata(params);
|
||||
}
|
||||
return engines;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create an engine object from the search configuration details.
|
||||
*
|
||||
|
@ -2432,7 +2460,7 @@ SearchService.prototype = {
|
|||
manifest = await policy.extension.getLocalizedManifest(locale);
|
||||
}
|
||||
|
||||
let engineParams = this.getEngineParams(
|
||||
let engineParams = await this.getEngineParams(
|
||||
policy.extension,
|
||||
manifest,
|
||||
locale,
|
||||
|
@ -2443,7 +2471,7 @@ SearchService.prototype = {
|
|||
// No need to sanitize the name, as shortName uses the WebExtension id
|
||||
// which should already be sanitized.
|
||||
shortName: engineParams.shortName,
|
||||
isBuiltin: engineParams.isBuiltin,
|
||||
isAppProvided: engineParams.isAppProvided,
|
||||
});
|
||||
engine._initFromMetadata(engineParams.name, engineParams);
|
||||
engine._loadPath = "[other]addEngineWithDetails";
|
||||
|
@ -2493,13 +2521,13 @@ SearchService.prototype = {
|
|||
initEngine = false,
|
||||
isReload
|
||||
) {
|
||||
let params = this.getEngineParams(extension, manifest, locale, {
|
||||
let params = await this.getEngineParams(extension, manifest, locale, {
|
||||
initEngine,
|
||||
});
|
||||
return this.addEngineWithDetails(params.name, params, isReload);
|
||||
},
|
||||
|
||||
getEngineParams(extension, manifest, locale, engineParams = {}) {
|
||||
async getEngineParams(extension, manifest, locale, engineParams = {}) {
|
||||
let { IconDetails } = ExtensionParent;
|
||||
|
||||
// General set of icons for an engine.
|
||||
|
@ -2557,6 +2585,8 @@ SearchService.prototype = {
|
|||
"";
|
||||
let mozParams = engineParams.extraParams || searchProvider.params || [];
|
||||
|
||||
let addon = await AddonManager.getAddonByID(extension.id);
|
||||
let isAppProvided = addon.isBuiltin || addon.isSystem;
|
||||
let params = {
|
||||
name: searchProvider.name.trim(),
|
||||
shortName,
|
||||
|
@ -2572,7 +2602,7 @@ SearchService.prototype = {
|
|||
alias: searchProvider.keyword,
|
||||
extensionID: extension.id,
|
||||
locale,
|
||||
isBuiltin: extension.addonData.builtIn,
|
||||
isAppProvided,
|
||||
orderHint: engineParams.orderHint,
|
||||
// suggest_url doesn't currently get encoded.
|
||||
suggestURL: searchProvider.suggest_url,
|
||||
|
@ -2594,7 +2624,7 @@ SearchService.prototype = {
|
|||
try {
|
||||
var engine = new SearchEngine({
|
||||
uri: engineURL,
|
||||
isBuiltin: false,
|
||||
isAppProvided: false,
|
||||
});
|
||||
engine._setIcon(iconURL, false);
|
||||
engine._confirm = confirm;
|
||||
|
@ -2671,7 +2701,7 @@ SearchService.prototype = {
|
|||
this._currentPrivateEngine = null;
|
||||
}
|
||||
|
||||
if (engineToRemove._isBuiltin) {
|
||||
if (engineToRemove._isAppProvided) {
|
||||
// Just hide it (the "hidden" setter will notify) and remove its alias to
|
||||
// avoid future conflicts with other engines.
|
||||
engineToRemove.hidden = true;
|
||||
|
@ -3531,7 +3561,7 @@ var engineUpdateService = {
|
|||
logConsole.debug("updating", engine.name, updateURI.spec);
|
||||
testEngine = new SearchEngine({
|
||||
uri: updateURI,
|
||||
isBuiltin: false,
|
||||
isAppProvided: false,
|
||||
});
|
||||
testEngine._engineToUpdate = engine;
|
||||
testEngine._initFromURIAndLoad(updateURI);
|
||||
|
|
|
@ -6,7 +6,12 @@ const { XPCOMUtils } = ChromeUtils.import(
|
|||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
||||
const { MockRegistrar } = ChromeUtils.import(
|
||||
"resource://testing-common/MockRegistrar.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
AddonManager: "resource://gre/modules/AddonManager.jsm",
|
||||
AddonTestUtils: "resource://testing-common/AddonTestUtils.jsm",
|
||||
ExtensionTestUtils: "resource://testing-common/ExtensionXPCShellUtils.jsm",
|
||||
NetUtil: "resource://gre/modules/NetUtil.jsm",
|
||||
|
@ -135,10 +140,18 @@ var SearchTestUtils = Object.freeze({
|
|||
*
|
||||
* @param {object} scope
|
||||
* The global scope of the test being run.
|
||||
* @param {*} usePrivilegedSignatures
|
||||
* How to sign created addons.
|
||||
*/
|
||||
initXPCShellAddonManager(scope) {
|
||||
initXPCShellAddonManager(scope, usePrivilegedSignatures = false) {
|
||||
let scopes = AddonManager.SCOPE_PROFILE | AddonManager.SCOPE_APPLICATION;
|
||||
Services.prefs.setIntPref("extensions.enabledScopes", scopes);
|
||||
Services.prefs.setBoolPref(
|
||||
"extensions.webextensions.background-delayed-startup",
|
||||
false
|
||||
);
|
||||
ExtensionTestUtils.init(scope);
|
||||
AddonTestUtils.usePrivilegedSignatures = false;
|
||||
AddonTestUtils.usePrivilegedSignatures = usePrivilegedSignatures;
|
||||
AddonTestUtils.overrideCertDB();
|
||||
},
|
||||
|
||||
|
@ -148,46 +161,151 @@ var SearchTestUtils = Object.freeze({
|
|||
* Note: You should call `initXPCShellAddonManager` before calling this.
|
||||
*
|
||||
* @param {object} [options]
|
||||
* @param {string} [options.id]
|
||||
* The id to use for the WebExtension (postfixed by `@tests.mozilla.org`).
|
||||
* @param {string} [options.name]
|
||||
* The display name to use for the WebExtension.
|
||||
* @param {string} [options.version]
|
||||
* The version to use for the WebExtension.
|
||||
* @param {string} [options.keyword]
|
||||
* The keyword to use for the WebExtension.
|
||||
*/
|
||||
async installSearchExtension(options = {}) {
|
||||
options.id = options.id ?? "example";
|
||||
options.name = options.name ?? "Example";
|
||||
options.version = options.version ?? "1.0";
|
||||
|
||||
options.id = (options.id ?? "example") + "@tests.mozilla.org";
|
||||
let extensionInfo = {
|
||||
useAddonManager: "permanent",
|
||||
manifest: {
|
||||
version: options.version,
|
||||
applications: {
|
||||
gecko: {
|
||||
id: options.id + "@tests.mozilla.org",
|
||||
},
|
||||
},
|
||||
chrome_settings_overrides: {
|
||||
search_provider: {
|
||||
name: options.name,
|
||||
search_url: "https://example.com/",
|
||||
search_url_get_params: "?q={searchTerms}",
|
||||
},
|
||||
},
|
||||
},
|
||||
manifest: this.createEngineManifest(options),
|
||||
};
|
||||
if (options.keyword) {
|
||||
extensionInfo.manifest.chrome_settings_overrides.search_provider.keyword =
|
||||
options.keyword;
|
||||
}
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension(extensionInfo);
|
||||
await extension.startup();
|
||||
await AddonTestUtils.waitForSearchProviderStartup(extension);
|
||||
return extension;
|
||||
},
|
||||
|
||||
/**
|
||||
* Install a search engine as a system extension to simulate
|
||||
* Normandy updates. For xpcshell-tests only.
|
||||
*
|
||||
* Note: You should call `initXPCShellAddonManager` before calling this.
|
||||
*
|
||||
* @param {object} [options]
|
||||
*/
|
||||
async installSystemSearchExtension(options = {}) {
|
||||
options.id = (options.id ?? "example") + "@search.mozilla.org";
|
||||
let xpi = await AddonTestUtils.createTempWebExtensionFile({
|
||||
manifest: this.createEngineManifest(options),
|
||||
background() {
|
||||
// eslint-disable-next-line no-undef
|
||||
browser.test.sendMessage("started");
|
||||
},
|
||||
});
|
||||
let wrapper = ExtensionTestUtils.expectExtension(options.id);
|
||||
|
||||
const install = await AddonManager.getInstallForURL(`file://${xpi.path}`, {
|
||||
useSystemLocation: true,
|
||||
});
|
||||
|
||||
install.install();
|
||||
|
||||
await wrapper.awaitStartup();
|
||||
await wrapper.awaitMessage("started");
|
||||
|
||||
return wrapper;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a search engine extension manifest.
|
||||
*
|
||||
* @param {object} [options]
|
||||
* @param {string} [options.id]
|
||||
* The id to use for the WebExtension.
|
||||
* @param {string} [options.name]
|
||||
* The display name to use for the WebExtension.
|
||||
* @param {string} [options.version]
|
||||
* The version to use for the WebExtension.
|
||||
* @param {string} [options.keyword]
|
||||
* The keyword to use for the WebExtension.
|
||||
* @returns {object}
|
||||
* The generated manifest.
|
||||
*/
|
||||
createEngineManifest(options = {}) {
|
||||
options.id = options.id ?? "example@tests.mozilla.org";
|
||||
options.name = options.name ?? "Example";
|
||||
options.version = options.version ?? "1.0";
|
||||
let manifest = {
|
||||
version: options.version,
|
||||
applications: {
|
||||
gecko: {
|
||||
id: options.id,
|
||||
},
|
||||
},
|
||||
chrome_settings_overrides: {
|
||||
search_provider: {
|
||||
name: options.name,
|
||||
search_url: "https://example.com/",
|
||||
search_url_get_params: "?q={searchTerms}",
|
||||
},
|
||||
},
|
||||
};
|
||||
if (options.keyword) {
|
||||
manifest.chrome_settings_overrides.search_provider.keyword =
|
||||
options.keyword;
|
||||
}
|
||||
return manifest;
|
||||
},
|
||||
|
||||
/**
|
||||
* A mock idleService that allows us to simulate RemoteSettings
|
||||
* configuration updates.
|
||||
*/
|
||||
idleService: {
|
||||
_observers: new Set(),
|
||||
|
||||
_reset() {
|
||||
this._observers.clear();
|
||||
},
|
||||
|
||||
_fireObservers(state) {
|
||||
for (let observer of this._observers.values()) {
|
||||
observer.observe(observer, state, null);
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIIdleService]),
|
||||
idleTime: 19999,
|
||||
|
||||
addIdleObserver(observer, time) {
|
||||
this._observers.add(observer);
|
||||
},
|
||||
|
||||
removeIdleObserver(observer, time) {
|
||||
this._observers.delete(observer);
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Register the mock idleSerice.
|
||||
*
|
||||
* @param {Fun} registerCleanupFunction
|
||||
*/
|
||||
useMockIdleService(registerCleanupFunction) {
|
||||
let fakeIdleService = MockRegistrar.register(
|
||||
"@mozilla.org/widget/idleservice;1",
|
||||
SearchTestUtils.idleService
|
||||
);
|
||||
registerCleanupFunction(() => {
|
||||
MockRegistrar.unregister(fakeIdleService);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Simulates an update to the RemoteSettings configuration.
|
||||
*
|
||||
* @param {object} config
|
||||
* The new configuration.
|
||||
*/
|
||||
async updateRemoteSettingsConfig(config) {
|
||||
const reloadObserved = SearchTestUtils.promiseSearchNotification(
|
||||
"engines-reloaded"
|
||||
);
|
||||
await RemoteSettings(SearchUtils.SETTINGS_KEY).emit("sync", {
|
||||
data: { current: config },
|
||||
});
|
||||
|
||||
this.idleService._fireObservers("idle");
|
||||
await reloadObserved;
|
||||
},
|
||||
});
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
]
|
||||
}
|
||||
],
|
||||
"_isBuiltin": true,
|
||||
"_isAppProvided": true,
|
||||
"queryCharset": "UTF-8",
|
||||
"extensionID": "engine1@search.mozilla.org"
|
||||
},
|
||||
|
@ -61,7 +61,7 @@
|
|||
]
|
||||
}
|
||||
],
|
||||
"_isBuiltin": true,
|
||||
"_isAppProvided": true,
|
||||
"queryCharset": "UTF-8",
|
||||
"extensionID": "engine2@search.mozilla.org"
|
||||
},
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"_metaData": {
|
||||
"alias": "testAlias"
|
||||
},
|
||||
"_isBuiltin": true
|
||||
"_isAppProvided": true
|
||||
},
|
||||
{
|
||||
"_name": "engine2",
|
||||
|
@ -17,7 +17,7 @@
|
|||
"alias": null,
|
||||
"hidden": true
|
||||
},
|
||||
"_isBuiltin": true
|
||||
"_isAppProvided": true
|
||||
},
|
||||
{
|
||||
"_name": "Test search engine",
|
||||
|
|
|
@ -29,7 +29,7 @@ add_task(async function test_async_distribution() {
|
|||
Assert.ok(engine.isAppProvided, "Should be shown as an app-provided engine");
|
||||
|
||||
Assert.equal(
|
||||
engine.wrappedJSObject._isBuiltin,
|
||||
engine.wrappedJSObject._isAppProvided,
|
||||
true,
|
||||
"Distribution engines should still be marked as built-in"
|
||||
);
|
||||
|
|
|
@ -45,12 +45,12 @@ const enginesCache = {
|
|||
engines: [
|
||||
{
|
||||
_metaData: { alias: null },
|
||||
_isBuiltin: true,
|
||||
_isAppProvided: true,
|
||||
_name: "engine1",
|
||||
},
|
||||
{
|
||||
_metaData: { alias: null },
|
||||
_isBuiltin: true,
|
||||
_isAppProvided: true,
|
||||
_name: "engine2",
|
||||
},
|
||||
],
|
||||
|
|
|
@ -40,32 +40,6 @@ const BAD_CONFIG = [
|
|||
},
|
||||
];
|
||||
|
||||
// The mock idle service.
|
||||
var idleService = {
|
||||
_observers: new Set(),
|
||||
|
||||
_reset() {
|
||||
this._observers.clear();
|
||||
},
|
||||
|
||||
_fireObservers(state) {
|
||||
for (let observer of this._observers.values()) {
|
||||
observer.observe(observer, state, null);
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIIdleService]),
|
||||
idleTime: 19999,
|
||||
|
||||
addIdleObserver(observer, time) {
|
||||
this._observers.add(observer);
|
||||
},
|
||||
|
||||
removeIdleObserver(observer, time) {
|
||||
this._observers.delete(observer);
|
||||
},
|
||||
};
|
||||
|
||||
function listenFor(name, key) {
|
||||
let notifyObserved = false;
|
||||
let obs = (subject, topic, data) => {
|
||||
|
@ -84,14 +58,7 @@ function listenFor(name, key) {
|
|||
let configurationStub;
|
||||
|
||||
add_task(async function setup() {
|
||||
let fakeIdleService = MockRegistrar.register(
|
||||
"@mozilla.org/widget/idleservice;1",
|
||||
idleService
|
||||
);
|
||||
registerCleanupFunction(() => {
|
||||
MockRegistrar.unregister(fakeIdleService);
|
||||
});
|
||||
|
||||
SearchTestUtils.useMockIdleService(registerCleanupFunction);
|
||||
await AddonTestUtils.promiseStartupManager();
|
||||
});
|
||||
|
||||
|
|
|
@ -94,32 +94,6 @@ const DEFAULT = "Test search engine";
|
|||
// Default engine with region set to FR.
|
||||
const FR_DEFAULT = "engine-pref";
|
||||
|
||||
// The mock idle service.
|
||||
var idleService = {
|
||||
_observers: new Set(),
|
||||
|
||||
_reset() {
|
||||
this._observers.clear();
|
||||
},
|
||||
|
||||
_fireObservers(state) {
|
||||
for (let observer of this._observers.values()) {
|
||||
observer.observe(observer, state, null);
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIIdleService]),
|
||||
idleTime: 19999,
|
||||
|
||||
addIdleObserver(observer, time) {
|
||||
this._observers.add(observer);
|
||||
},
|
||||
|
||||
removeIdleObserver(observer, time) {
|
||||
this._observers.delete(observer);
|
||||
},
|
||||
};
|
||||
|
||||
function listenFor(name, key) {
|
||||
let notifyObserved = false;
|
||||
let obs = (subject, topic, data) => {
|
||||
|
@ -143,14 +117,7 @@ add_task(async function setup() {
|
|||
true
|
||||
);
|
||||
|
||||
let fakeIdleService = MockRegistrar.register(
|
||||
"@mozilla.org/widget/idleservice;1",
|
||||
idleService
|
||||
);
|
||||
registerCleanupFunction(() => {
|
||||
MockRegistrar.unregister(fakeIdleService);
|
||||
});
|
||||
|
||||
SearchTestUtils.useMockIdleService(registerCleanupFunction);
|
||||
await useTestEngines("data", null, CONFIG);
|
||||
await AddonTestUtils.promiseStartupManager();
|
||||
});
|
||||
|
@ -263,7 +230,7 @@ add_task(async function test_config_updated_engine_changes() {
|
|||
},
|
||||
});
|
||||
|
||||
idleService._fireObservers("idle");
|
||||
SearchTestUtils.idleService._fireObservers("idle");
|
||||
|
||||
await reloadObserved;
|
||||
Services.obs.removeObserver(
|
||||
|
|
|
@ -3,8 +3,12 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
AddonManager: "resource://gre/modules/AddonManager.jsm",
|
||||
ExtensionTestUtils: "resource://testing-common/ExtensionXPCShellUtils.jsm",
|
||||
});
|
||||
|
||||
const {
|
||||
createAppInfo,
|
||||
promiseRestartManager,
|
||||
promiseShutdownManager,
|
||||
promiseStartupManager,
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
SearchTestUtils.initXPCShellAddonManager(this, "system");
|
||||
|
||||
async function restart() {
|
||||
Services.search.wrappedJSObject.reset();
|
||||
await AddonTestUtils.promiseRestartManager();
|
||||
await Services.search.init(false);
|
||||
}
|
||||
|
||||
const CONFIG_DEFAULT = [
|
||||
{
|
||||
webExtension: { id: "plainengine@search.mozilla.org" },
|
||||
appliesTo: [{ included: { everywhere: true } }],
|
||||
},
|
||||
];
|
||||
|
||||
const CONFIG_UPDATED = [
|
||||
{
|
||||
webExtension: { id: "plainengine@search.mozilla.org" },
|
||||
appliesTo: [{ included: { everywhere: true } }],
|
||||
},
|
||||
{
|
||||
webExtension: { id: "example@search.mozilla.org" },
|
||||
appliesTo: [{ included: { everywhere: true } }],
|
||||
},
|
||||
];
|
||||
|
||||
async function getEngineNames() {
|
||||
let engines = await Services.search.getDefaultEngines();
|
||||
return engines.map(engine => engine._name);
|
||||
}
|
||||
|
||||
add_task(async function setup() {
|
||||
await useTestEngines("test-extensions", null, CONFIG_DEFAULT);
|
||||
await AddonTestUtils.promiseStartupManager();
|
||||
registerCleanupFunction(AddonTestUtils.promiseShutdownManager);
|
||||
SearchTestUtils.useMockIdleService(registerCleanupFunction);
|
||||
await Services.search.init();
|
||||
});
|
||||
|
||||
// Test the situation where we receive an updated configuration
|
||||
// that references an engine that doesnt exist locally as it
|
||||
// will be installed by Normandy.
|
||||
add_task(async function test_config_before_normandy() {
|
||||
// Ensure initial default setup.
|
||||
await SearchTestUtils.updateRemoteSettingsConfig(CONFIG_DEFAULT);
|
||||
await restart();
|
||||
Assert.deepEqual(await getEngineNames(), ["Plain"]);
|
||||
// Updated configuration references nonexistant engine.
|
||||
await SearchTestUtils.updateRemoteSettingsConfig(CONFIG_UPDATED);
|
||||
Assert.deepEqual(
|
||||
await getEngineNames(),
|
||||
["Plain"],
|
||||
"Updated engine hasnt been installed yet"
|
||||
);
|
||||
// Normandy then installs the engine.
|
||||
let addon = await SearchTestUtils.installSystemSearchExtension();
|
||||
Assert.deepEqual(
|
||||
await getEngineNames(),
|
||||
["Plain", "Example"],
|
||||
"Both engines are now enabled"
|
||||
);
|
||||
await addon.unload();
|
||||
});
|
||||
|
||||
// Test the situation where we receive a newly installed
|
||||
// engine from Normandy followed by the update to the
|
||||
// configuration that uses that engine.
|
||||
add_task(async function test_normandy_before_config() {
|
||||
// Ensure initial default setup.
|
||||
await SearchTestUtils.updateRemoteSettingsConfig(CONFIG_DEFAULT);
|
||||
await restart();
|
||||
Assert.deepEqual(await getEngineNames(), ["Plain"]);
|
||||
// Normandy installs the enigne.
|
||||
let addon = await SearchTestUtils.installSystemSearchExtension();
|
||||
Assert.deepEqual(
|
||||
await getEngineNames(),
|
||||
["Plain"],
|
||||
"Normandy engine ignored as not in config yet"
|
||||
);
|
||||
// Configuration is updated to use the engine.
|
||||
await SearchTestUtils.updateRemoteSettingsConfig(CONFIG_UPDATED);
|
||||
Assert.deepEqual(
|
||||
await getEngineNames(),
|
||||
["Plain", "Example"],
|
||||
"Both engines are now enabled"
|
||||
);
|
||||
await addon.unload();
|
||||
});
|
|
@ -63,6 +63,7 @@ support-files =
|
|||
[test_missing_engine.js]
|
||||
[test_sort_orders-no-hints.js]
|
||||
[test_webextensions_builtin_upgrade.js]
|
||||
[test_webextensions_normandy_upgrade.js]
|
||||
[test_distributions.js]
|
||||
skip-if = appname == "thunderbird"
|
||||
[test_maybereloadengine_order.js]
|
||||
|
|
Загрузка…
Ссылка в новой задаче