Backed out 4 changesets (bug 1647320, bug 1647359) for failures on /test_json_cache.js. CLOSED TREE

Backed out changeset fdf086cfd0f9 (bug 1647359)
Backed out changeset b39278706c66 (bug 1647359)
Backed out changeset 65c58515f2cb (bug 1647359)
Backed out changeset 7ebc3ec422ec (bug 1647320)
This commit is contained in:
Csoregi Natalia 2020-06-29 21:54:32 +03:00
Родитель 0d8b17e46b
Коммит 5b4873516d
7 изменённых файлов: 340 добавлений и 399 удалений

Просмотреть файл

@ -639,7 +639,7 @@ EngineStore.prototype = {
_cloneEngine(aEngine) {
var clonedObj = {};
for (let i of ["name", "alias", "iconURI"]) {
for (var i in aEngine) {
clonedObj[i] = aEngine[i];
}
clonedObj.originalEngine = aEngine;
@ -738,7 +738,7 @@ EngineStore.prototype = {
reloadIcons() {
this._engines.forEach(function(e) {
e.iconURI = e.originalEngine.iconURI;
e.uri = e.originalEngine.uri;
});
},
};

Просмотреть файл

@ -46,6 +46,9 @@ XPCOMUtils.defineLazyGetter(this, "gEncoder", function() {
return new TextEncoder();
});
// Delay for batching invalidation of the JSON cache (ms)
const CACHE_INVALIDATION_DELAY = 1000;
const CACHE_FILENAME = "search.json.mozlz4";
/**
@ -59,12 +62,6 @@ class SearchCache {
constructor(searchService) {
this._searchService = searchService;
}
QueryInterface = ChromeUtils.generateQI([Ci.nsIObserver]);
// Delay for batching invalidation of the JSON cache (ms)
static CACHE_INVALIDATION_DELAY = 1000;
/**
* A reference to the pending DeferredTask, if there is one.
*/
@ -96,32 +93,14 @@ class SearchCache {
*/
_searchService;
addObservers() {
Services.obs.addObserver(this, SearchUtils.TOPIC_ENGINE_MODIFIED);
Services.obs.addObserver(this, SearchUtils.TOPIC_SEARCH_SERVICE);
}
/**
* Cleans up, removing observers.
*/
removeObservers() {
Services.obs.removeObserver(this, SearchUtils.TOPIC_ENGINE_MODIFIED);
Services.obs.removeObserver(this, SearchUtils.TOPIC_SEARCH_SERVICE);
}
/**
* Reads the cache file.
*
* @param {string} origin
* If this parameter is "test", then the cache will not be written. As
* some tests manipulate the cache directly, we allow turning off writing to
* avoid writing stale cache data.
* @returns {object}
* Returns the cache file data.
*/
async get(origin = "") {
async get() {
let json;
await this._ensurePendingWritesCompleted(origin);
try {
let cacheFilePath = OS.Path.join(
OS.Constants.Path.profileDir,
@ -156,15 +135,15 @@ class SearchCache {
* Queues writing the cache until after CACHE_INVALIDATION_DELAY. If there
* is a currently queued task then it will be restarted.
*/
_delayedWrite() {
delayedWrite() {
if (this._batchTask) {
this._batchTask.disarm();
} else {
let task = async () => {
logConsole.debug("batchTask: Invalidating engine cache");
await this._write();
await this.write();
};
this._batchTask = new DeferredTask(task, this.CACHE_INVALIDATION_DELAY);
this._batchTask = new DeferredTask(task, CACHE_INVALIDATION_DELAY);
}
this._batchTask.arm();
}
@ -177,11 +156,9 @@ class SearchCache {
* some tests manipulate the cache directly, we allow turning off writing to
* avoid writing stale cache data.
*/
async _ensurePendingWritesCompleted(origin = "") {
async ensurePendingWritesCompleted(origin = "") {
// Before we read the cache file, first make sure all pending tasks are clear.
if (!this._batchTask) {
return;
}
if (this._batchTask) {
logConsole.debug("finalizing batch task");
let task = this._batchTask;
this._batchTask = null;
@ -193,11 +170,12 @@ class SearchCache {
await task.finalize();
}
}
}
/**
* Writes the cache to disk (no delay).
*/
async _write() {
async write() {
if (this._batchTask) {
this._batchTask.disarm();
}
@ -260,7 +238,7 @@ class SearchCache {
*/
setAttribute(name, val) {
this._metaData[name] = val;
this._delayedWrite();
this.delayedWrite();
}
/**
@ -273,10 +251,8 @@ class SearchCache {
* The value to set.
*/
setVerifiedAttribute(name, val) {
this._metaData[name] = val;
this._metaData[this.getHashName(name)] = getVerificationHash(val);
console.log(this._metaData);
this._delayedWrite();
this.setAttribute(name, val);
this.setAttribute(this.getHashName(name), getVerificationHash(val));
}
/**
@ -353,28 +329,4 @@ class SearchCache {
}
}
}
// nsIObserver
observe(engine, topic, verb) {
switch (topic) {
case SearchUtils.TOPIC_ENGINE_MODIFIED:
switch (verb) {
case SearchUtils.MODIFIED_TYPE.ADDED:
case SearchUtils.MODIFIED_TYPE.CHANGED:
case SearchUtils.MODIFIED_TYPE.REMOVED:
this._delayedWrite();
break;
}
break;
case SearchUtils.TOPIC_SEARCH_SERVICE:
switch (verb) {
case "init-complete":
case "reinit-complete":
case "engines-reloaded":
this._delayedWrite();
break;
}
break;
}
}
}

Просмотреть файл

@ -137,29 +137,26 @@ function ENSURE_WARN(assertion, message, resultCode) {
}
}
/**
* Load listener
*/
class loadListener {
_bytes = [];
_callback = null;
_channel = null;
_countRead = 0;
_engine = null;
_stream = null;
QueryInterface = ChromeUtils.generateQI([
function loadListener(channel, engine, callback) {
this._channel = channel;
this._bytes = [];
this._engine = engine;
this._callback = callback;
}
loadListener.prototype = {
_callback: null,
_channel: null,
_countRead: 0,
_engine: null,
_stream: null,
QueryInterface: ChromeUtils.generateQI([
Ci.nsIRequestObserver,
Ci.nsIStreamListener,
Ci.nsIChannelEventSink,
Ci.nsIInterfaceRequestor,
Ci.nsIProgressEventSink,
]);
constructor(channel, engine, callback) {
this._channel = channel;
this._engine = engine;
this._callback = callback;
}
]),
// nsIRequestObserver
onStartRequest(request) {
@ -167,7 +164,7 @@ class loadListener {
this._stream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(
Ci.nsIBinaryInputStream
);
}
},
onStopRequest(request, statusCode) {
logConsole.debug("loadListener: Stopping request:", request.name);
@ -185,7 +182,7 @@ class loadListener {
this._callback(this._bytes, this._engine);
this._channel = null;
this._engine = null;
}
},
// nsIStreamListener
onDataAvailable(request, inputStream, offset, count) {
@ -194,23 +191,23 @@ class loadListener {
// Get a byte array of the data
this._bytes = this._bytes.concat(this._stream.readByteArray(count));
this._countRead += count;
}
},
// nsIChannelEventSink
asyncOnChannelRedirect(oldChannel, newChannel, flags, callback) {
this._channel = newChannel;
callback.onRedirectVerifyCallback(Cr.NS_OK);
}
},
// nsIInterfaceRequestor
getInterface(iid) {
return this.QueryInterface(iid);
}
},
// nsIProgressEventSink
onProgress(request, progress, progressMax) {}
onStatus(request, status, statusArg) {}
}
onProgress(request, progress, progressMax) {},
onStatus(request, status, statusArg) {},
};
/**
* Tries to rescale an icon to a given size.
@ -542,14 +539,7 @@ function getInternalAliases(engine) {
}
/**
* EngineURL holds a query URL and all associated parameters.
*/
class EngineURL {
params = [];
rels = [];
/**
* Constructor
* Creates an engineURL object, which holds the query URL and all parameters.
*
* @param {string} mimeType
* The name of the MIME type of the search results returned by this URL.
@ -567,7 +557,7 @@ class EngineURL {
*
* @throws NS_ERROR_NOT_IMPLEMENTED if aType is unsupported.
*/
constructor(mimeType, requestMethod, template, resultDomain) {
function EngineURL(mimeType, requestMethod, template, resultDomain) {
if (!mimeType || !requestMethod || !template) {
throw Components.Exception(
"missing mimeType, method or template for EngineURL!",
@ -587,6 +577,8 @@ class EngineURL {
this.type = type;
this.method = method;
this.params = [];
this.rels = [];
var templateURI = SearchUtils.makeURI(template);
if (!templateURI) {
@ -615,11 +607,11 @@ class EngineURL {
// If no resultDomain was specified in the engine definition file, use the
// host from the template.
this.resultDomain = resultDomain || this.templateHost;
}
}
EngineURL.prototype = {
addParam(name, value, purpose) {
this.params.push(new QueryParameter(name, value, purpose));
}
},
/**
* Adds a MozParam to the parameters list for this URL. For purpose based params
@ -651,7 +643,7 @@ class EngineURL {
} else {
this.addParam(param.name, param.value || undefined, purpose);
}
}
},
getSubmission(searchTerms, engine, purpose) {
var url = ParamSubstitution(this.template, searchTerms, engine);
@ -724,16 +716,16 @@ class EngineURL {
}
return new Submission(Services.io.newURI(url), postData);
}
},
_getTermsParameterName() {
let queryParam = this.params.find(p => p.value == "{" + USER_DEFINED + "}");
return queryParam ? queryParam.name : "";
}
},
_hasRelation(rel) {
return this.rels.some(e => e == rel.toLowerCase());
}
},
_initWithJSON(json) {
if (!json.params) {
@ -750,7 +742,7 @@ class EngineURL {
this.addParam(param.name, param.value, param.purpose || undefined);
}
}
}
},
/**
* Creates a JavaScript object that represents this URL.
@ -774,76 +766,11 @@ class EngineURL {
}
return json;
}
}
},
};
/**
* SearchEngine represents WebExtension based search engines.
*/
class SearchEngine {
QueryInterface = ChromeUtils.generateQI([Ci.nsISearchEngine]);
// Data set by the user.
_metaData = {};
// The data describing the engine, in the form of an XML document element.
_data = null;
// Anonymized path of where we initially loaded the engine from.
// This will stay null for engines installed in the profile before we moved
// to a JSON storage.
_loadPath = null;
// The engine's description
_description = "";
// Used to store the engine to replace, if we're an update to an existing
// engine.
_engineToUpdate = null;
// Set to true if the engine has a preferred icon (an icon that should not be
// overridden by a non-preferred icon).
_hasPreferredIcon = null;
// The engine's name.
_name = null;
// The name of the charset used to submit the search terms.
_queryCharset = null;
// The engine's raw SearchForm value (URL string pointing to a search form).
__searchForm = null;
// Whether to obtain user confirmation before adding the engine. This is only
// used when the engine is first added to the list.
_confirm = null;
// Whether to set this as the current engine as soon as it is loaded. This
// is only used when the engine is first added to the list.
_useNow = null;
// A function to be invoked when this engine object's addition completes (or
// fails). Only used for installation via addEngine.
_installCallback = null;
// The number of days between update checks for new versions
_updateInterval = null;
// The url to check at for a new update
_updateURL = null;
// The url to check for a new icon
_iconUpdateURL = null;
// The extension ID if added by an extension.
_extensionID = null;
// The locale, or "DEFAULT", if required.
_locale = null;
// Whether the engine is provided by the application.
_isAppProvided = false;
// The order hint from the configuration (if any).
_orderHint = null;
// The telemetry id from the configuration (if any).
_telemetryId = null;
// Set to true once the engine has been added to the store, and the initial
// notification sent. This allows to skip sending notifications during
// initialization.
_engineAddedToStore = false;
// The alias coming from the engine definition (via webextension
// keyword field for example) may be overridden in the metaData
// with a user defined alias.
_definedAlias = null;
// The urls associated with this engine.
_urls = [];
// Internal aliases for default engines only.
__internalAliases = null;
/**
* Constructor.
* nsISearchEngine constructor.
*
* @param {object} options
* The options for this search engine. At least one of options.name,
@ -863,11 +790,17 @@ class SearchEngine {
* shipped in omni.ja or via Normandy. If it is, it will
* be treated as read-only.
*/
constructor(options = {}) {
function SearchEngine(options = {}) {
if (!("isAppProvided" in options)) {
throw new Error("isAppProvided missing from options.");
}
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.
this._definedAlias = null;
this._urls = [];
this._metaData = {};
let file, uri;
if ("name" in options) {
@ -931,10 +864,34 @@ class SearchEngine {
}
this._loadPath = this.getAnonymizedLoadPath(file, uri);
}
}
}
SearchEngine.prototype = {
// Data set by the user.
_metaData: null,
// The data describing the engine, in the form of an XML document element.
_data: null,
// Anonymized path of where we initially loaded the engine from.
// This will stay null for engines installed in the profile before we moved
// to a JSON storage.
_loadPath: null,
// The engine's description
_description: "",
// Used to store the engine to replace, if we're an update to an existing
// engine.
_engineToUpdate: null,
// Set to true if the engine has a preferred icon (an icon that should not be
// overridden by a non-preferred icon).
_hasPreferredIcon: null,
// The engine's name.
_name: null,
// The name of the charset used to submit the search terms.
_queryCharset: null,
// The engine's raw SearchForm value (URL string pointing to a search form).
__searchForm: null,
get _searchForm() {
return this.__searchForm;
}
},
set _searchForm(value) {
if (/^https?:/i.test(value)) {
this.__searchForm = value;
@ -944,7 +901,36 @@ class SearchEngine {
this._name || "the current engine"
);
}
}
},
// Whether to obtain user confirmation before adding the engine. This is only
// used when the engine is first added to the list.
_confirm: false,
// Whether to set this as the current engine as soon as it is loaded. This
// is only used when the engine is first added to the list.
_useNow: false,
// A function to be invoked when this engine object's addition completes (or
// fails). Only used for installation via addEngine.
_installCallback: null,
// The number of days between update checks for new versions
_updateInterval: null,
// The url to check at for a new update
_updateURL: null,
// The url to check for a new icon
_iconUpdateURL: null,
// The extension ID if added by an extension.
_extensionID: null,
// The locale, or "DEFAULT", if required.
_locale: null,
// Whether the engine is provided by the application.
_isAppProvided: false,
// The order hint from the configuration (if any).
_orderHint: null,
// The telemetry id from the configuration (if any).
_telemetryId: null,
// Set to true once the engine has been added to the store, and the initial
// notification sent. This allows to skip sending notifications during
// initialization.
_engineAddedToStore: false,
/**
* Retrieves the data from the engine's file asynchronously.
@ -966,7 +952,7 @@ class SearchEngine {
// Now that the data is loaded, initialize the engine object
this._initFromData();
}
},
/**
* Retrieves the engine data from a URI. Initializes the engine, flushes to
@ -999,7 +985,7 @@ class SearchEngine {
var listener = new loadListener(chan, this, this._onLoad);
chan.notificationCallbacks = listener;
chan.asyncOpen(listener);
}
},
/**
* Retrieves the engine data from a URI asynchronously and initializes it.
@ -1012,7 +998,7 @@ class SearchEngine {
await this._retrieveSearchXMLData(uri.spec);
// Now that the data is loaded, initialize the engine object
this._initFromData();
}
},
/**
* Retrieves the engine data for a given URI asynchronously.
@ -1037,7 +1023,7 @@ class SearchEngine {
request.open("GET", url, true);
request.send();
});
}
},
/**
* Attempts to find an EngineURL object in the set of EngineURLs for
@ -1059,7 +1045,7 @@ class SearchEngine {
}
return null;
}
},
_confirmAddEngine() {
var stringBundle = Services.strings.createBundle(SEARCH_BUNDLE);
@ -1108,7 +1094,7 @@ class SearchEngine {
);
return { confirmed: confirm, useNow: checked.value };
}
},
/**
* Handle the successful download of an engine. Initializes the engine and
@ -1253,7 +1239,7 @@ class SearchEngine {
if (engine._installCallback) {
engine._installCallback();
}
}
},
/**
* Creates a key by serializing an object that contains the icon's width
@ -1273,7 +1259,7 @@ class SearchEngine {
};
return JSON.stringify(keyObj);
}
},
/**
* Add an icon to the icon map used by getIconURIBySize() and getIcons().
@ -1295,7 +1281,7 @@ class SearchEngine {
this._iconMapObj = this._iconMapObj || {};
let key = this._getIconKey(width, height);
this._iconMapObj[key] = uriSpec;
}
},
/**
* Sets the .iconURI property of the engine. If both aWidth and aHeight are
@ -1405,7 +1391,7 @@ class SearchEngine {
chan.asyncOpen(listener);
break;
}
}
},
/**
* Initialize this Engine object from the collected data.
@ -1438,7 +1424,7 @@ class SearchEngine {
// No need to keep a ref to our data (which in some cases can be a document
// element) past this point
this._data = null;
}
},
/**
* Initialize an EngineURL object from metadata.
@ -1487,7 +1473,7 @@ class SearchEngine {
}
this._urls.push(url);
}
},
/**
* Initialize this Engine object from a collection of metadata.
@ -1530,7 +1516,7 @@ class SearchEngine {
}
}
this._setUrls(params);
}
},
/**
* This sets the urls for the search engine based on the supplied parameters.
@ -1575,7 +1561,7 @@ class SearchEngine {
}
this.__searchForm = params.searchForm;
}
},
/**
* Update this engine based on new metadata, used during
@ -1589,7 +1575,7 @@ class SearchEngine {
this._iconMapObj = null;
this._initFromMetadata(params.name, params);
SearchUtils.notifyAction(this, SearchUtils.MODIFIED_TYPE.CHANGED);
}
},
/**
* Overrides the urls/parameters with those of the provided extension.
@ -1611,7 +1597,7 @@ class SearchEngine {
this.setAttr("overriddenBy", params.extensionID);
this._setUrls(params);
SearchUtils.notifyAction(this, SearchUtils.MODIFIED_TYPE.CHANGED);
}
},
/**
* Resets the overrides for the engine if it has been overridden.
@ -1625,7 +1611,7 @@ class SearchEngine {
this.clearAttr("overriddenBy");
SearchUtils.notifyAction(this, SearchUtils.MODIFIED_TYPE.CHANGED);
}
}
},
/**
* Extracts data from an OpenSearch URL element and creates an EngineURL
@ -1727,7 +1713,7 @@ class SearchEngine {
}
this._urls.push(url);
}
},
/**
* Get the icon from an OpenSearch Image element.
@ -1749,7 +1735,7 @@ class SearchEngine {
}
this._setIcon(element.textContent, isPrefered, width, height);
}
},
/**
* Extract search engine information from the collected data to initialize
@ -1815,7 +1801,7 @@ class SearchEngine {
Cr.NS_ERROR_FAILURE
);
}
}
},
/**
* Init from a JSON record.
@ -1859,7 +1845,7 @@ class SearchEngine {
engineURL._initWithJSON(url);
this._urls.push(engineURL);
}
}
},
/**
* Creates a JavaScript object that represents this engine.
@ -1920,29 +1906,29 @@ class SearchEngine {
}
return json;
}
},
setAttr(name, val) {
this._metaData[name] = val;
}
},
getAttr(name) {
return this._metaData[name] || undefined;
}
},
clearAttr(name) {
delete this._metaData[name];
}
},
// nsISearchEngine
get alias() {
return this.getAttr("alias") || this._definedAlias;
}
},
set alias(val) {
var value = val ? val.trim() : null;
this.setAttr("alias", value);
SearchUtils.notifyAction(this, SearchUtils.MODIFIED_TYPE.CHANGED);
}
},
/**
* Returns the appropriate identifier to use for telemetry. It is based on
@ -1962,7 +1948,7 @@ class SearchEngine {
return telemetryId + "-addon";
}
return telemetryId;
}
},
/**
* Return the built-in identifier of app-provided engines.
@ -1973,36 +1959,36 @@ class SearchEngine {
get identifier() {
// No identifier if If the engine isn't app-provided
return this.isAppProvided ? this._shortName : null;
}
},
get description() {
return this._description;
}
},
get hidden() {
return this.getAttr("hidden") || false;
}
},
set hidden(val) {
var value = !!val;
if (value != this.hidden) {
this.setAttr("hidden", value);
SearchUtils.notifyAction(this, SearchUtils.MODIFIED_TYPE.CHANGED);
}
}
},
get iconURI() {
if (this._iconURI) {
return this._iconURI;
}
return null;
}
},
get _iconURL() {
if (!this._iconURI) {
return "";
}
return this._iconURI.spec;
}
},
// Where the engine is being loaded from: will return the URI's spec if the
// engine is being downloaded and does not yet have a file. This is only used
@ -2013,7 +1999,7 @@ class SearchEngine {
}
return this._loadPath;
}
},
// This indicates where we found the .xml file to load the engine,
// and attempts to hide user-identifiable data (such as username).
@ -2120,7 +2106,7 @@ class SearchEngine {
}
return prefix + id + suffix;
}
},
get _isDistribution() {
return !!(
@ -2130,7 +2116,7 @@ class SearchEngine {
""
)
);
}
},
get isAppProvided() {
// For the modern configuration, distribution engines are app-provided as
@ -2156,28 +2142,30 @@ class SearchEngine {
}
return false;
}
},
get _hasUpdates() {
// Whether or not the engine has an update URL
let selfURL = this._getURLOfType(SearchUtils.URL_TYPE.OPENSEARCH, "self");
return !!(this._updateURL || this._iconUpdateURL || selfURL);
}
},
get name() {
return this._name;
}
},
get searchForm() {
return this._getSearchFormWithPurpose();
}
},
/* Internal aliases for default engines only. */
__internalAliases: null,
get _internalAliases() {
if (!this.__internalAliases) {
this.__internalAliases = getInternalAliases(this);
}
return this.__internalAliases;
}
},
_getSearchFormWithPurpose(purpose) {
// First look for a <Url rel="searchform">
@ -2204,14 +2192,14 @@ class SearchEngine {
}
return ParamSubstitution(this._searchForm, "", this);
}
},
get queryCharset() {
if (this._queryCharset) {
return this._queryCharset;
}
return (this._queryCharset = "windows-1252"); // the default
}
},
get _defaultMobileResponseType() {
let type = SearchUtils.URL_TYPE.SEARCH;
@ -2237,7 +2225,7 @@ class SearchEngine {
});
return type;
}
},
// from nsISearchEngine
getSubmission(data, responseType, purpose) {
@ -2275,12 +2263,12 @@ class SearchEngine {
);
}
return url.getSubmission(submissionData, this, purpose);
}
},
// from nsISearchEngine
supportsResponseType(type) {
return this._getURLOfType(type) != null;
}
},
// from nsISearchEngine
getResultDomain(responseType) {
@ -2296,7 +2284,7 @@ class SearchEngine {
return url.resultDomain;
}
return "";
}
},
/**
* @returns {object}
@ -2326,11 +2314,14 @@ class SearchEngine {
path: templateUrl.filePath.toLowerCase(),
termsParameterName,
};
}
},
// nsISupports
QueryInterface: ChromeUtils.generateQI([Ci.nsISearchEngine]),
get wrappedJSObject() {
return this;
}
},
/**
* Returns a string with the URL to an engine's icon matching both width and
@ -2356,7 +2347,7 @@ class SearchEngine {
return this._iconMapObj[key];
}
return null;
}
},
/**
* Gets an array of all available icons. Each entry is an object with
@ -2387,7 +2378,7 @@ class SearchEngine {
}
return result;
}
},
/**
* Opens a speculative connection to the engine's search URI
@ -2449,26 +2440,22 @@ class SearchEngine {
}
}
}
}
}
},
};
/**
* Implements nsISearchSubmission.
*/
class Submission {
QueryInterface = ChromeUtils.generateQI([Ci.nsISearchSubmission]);
constructor(uri, postData = null) {
// nsISearchSubmission
function Submission(uri, postData = null) {
this._uri = uri;
this._postData = postData;
}
}
Submission.prototype = {
get uri() {
return this._uri;
}
},
get postData() {
return this._postData;
}
}
},
QueryInterface: ChromeUtils.generateQI([Ci.nsISearchSubmission]),
};
var EXPORTED_SYMBOLS = ["SearchEngine", "getVerificationHash"];

Просмотреть файл

@ -556,6 +556,7 @@ SearchService.prototype = {
// Make sure the current list of engines is persisted, without the need to wait.
logConsole.debug("_init: engines loaded, writing cache");
this._cache.write();
this._addObservers();
} catch (ex) {
this._initRV = ex.result !== undefined ? ex.result : Cr.NS_ERROR_FAILURE;
@ -1291,6 +1292,8 @@ SearchService.prototype = {
return;
}
await this._cache.ensurePendingWritesCompleted();
// Capture the current engine state, in case we need to notify below.
const prevCurrentEngine = this._currentEngine;
const prevPrivateEngine = this._currentPrivateEngine;
@ -1302,6 +1305,8 @@ SearchService.prototype = {
// engine order.
this.__sortedEngines = null;
await this._loadEngines(await this._cache.get(), true);
// Make sure the current list of engines is persisted.
await this._cache.write();
// If the defaultEngine has changed between the previous load and this one,
// dispatch the appropriate notifications.
@ -1366,6 +1371,7 @@ SearchService.prototype = {
}
this._initObservers = PromiseUtils.defer();
await this._cache.ensurePendingWritesCompleted(origin);
// Clear the engines, too, so we don't stick with the stale ones.
this._resetLocalData();
@ -1378,7 +1384,7 @@ SearchService.prototype = {
"uninit-complete"
);
let cache = await this._cache.get(origin);
let cache = await this._cache.get();
// The init flow is not going to block on a fetch from an external service,
// but we're kicking it off as soon as possible to prevent UI flickering as
// much as possible.
@ -1405,6 +1411,9 @@ SearchService.prototype = {
return;
}
// Make sure the current list of engines is persisted.
await this._cache.write();
// Typically we'll re-init as a result of a pref observer,
// so signal to 'callers' that we're done.
gInitialized = true;
@ -3335,6 +3344,7 @@ SearchService.prototype = {
case SearchUtils.MODIFIED_TYPE.ADDED:
case SearchUtils.MODIFIED_TYPE.CHANGED:
case SearchUtils.MODIFIED_TYPE.REMOVED:
this._cache.delayedWrite();
// Invalidate the map used to parse URLs to search engines.
this._parseSubmissionMap = null;
break;
@ -3447,8 +3457,6 @@ SearchService.prototype = {
Services.obs.addObserver(this, QUIT_APPLICATION_TOPIC);
Services.obs.addObserver(this, TOPIC_LOCALES_CHANGE);
this._cache.addObservers();
// The current stage of shutdown. Used to help analyze crash
// signatures in case of shutdown timeout.
let shutdownState = {
@ -3501,8 +3509,6 @@ SearchService.prototype = {
this._queuedIdle = false;
}
this._cache.removeObservers();
Services.obs.removeObserver(this, SearchUtils.TOPIC_ENGINE_MODIFIED);
Services.obs.removeObserver(this, QUIT_APPLICATION_TOPIC);
Services.obs.removeObserver(this, TOPIC_LOCALES_CHANGE);

Просмотреть файл

@ -12,7 +12,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
Region: "resource://gre/modules/Region.jsm",
RemoteSettings: "resource://services-settings/remote-settings.js",
RemoteSettingsClient: "resource://services-settings/RemoteSettingsClient.jsm",
SearchCache: "resource://gre/modules/SearchCache.jsm",
SearchEngineSelector: "resource://gre/modules/SearchEngineSelector.jsm",
SearchTestUtils: "resource://testing-common/SearchTestUtils.jsm",
Services: "resource://gre/modules/Services.jsm",
@ -70,10 +69,6 @@ Services.prefs.setBoolPref(
true
);
// For tests, allow the cache to write sooner than it would do normally so that
// the tests that need to wait for it can run a bit faster.
SearchCache.CACHE_INVALIDATION_DELAY = 250;
/**
* Load engines from test data located in particular folders.
*

Просмотреть файл

@ -156,7 +156,7 @@ add_task(async function test_cache_write() {
Services.tm.dispatchToMainThread(() => {
// Call the observe method directly to simulate a remove but not actually
// remove anything.
Services.search.wrappedJSObject._cache
Services.search
.QueryInterface(Ci.nsIObserver)
.observe(null, "browser-search-engine-modified", "engine-removed");
});

Просмотреть файл

@ -113,4 +113,5 @@ add_task(async function basic_multilocale_test() {
);
await ext.unload();
await promiseAfterCache();
});