mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1772097 - Part 5: Use plain object for lazy getter in services/settings/. r=markh
Differential Revision: https://phabricator.services.mozilla.com/D147920
This commit is contained in:
parent
b868c9f585
commit
4f3eafb63e
@ -7,12 +7,13 @@ var EXPORTED_SYMBOLS = ["Downloader"];
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
const lazy = {};
|
||||
XPCOMUtils.defineLazyModuleGetters(lazy, {
|
||||
RemoteSettingsWorker: "resource://services-settings/RemoteSettingsWorker.jsm",
|
||||
Utils: "resource://services-settings/Utils.jsm",
|
||||
});
|
||||
ChromeUtils.defineModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
|
||||
XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]);
|
||||
ChromeUtils.defineModuleGetter(lazy, "OS", "resource://gre/modules/osfile.jsm");
|
||||
XPCOMUtils.defineLazyGlobalGetters(lazy, ["fetch"]);
|
||||
|
||||
class DownloadError extends Error {
|
||||
constructor(url, resp) {
|
||||
@ -304,13 +305,13 @@ class Downloader {
|
||||
const {
|
||||
attachment: { filename, size, hash },
|
||||
} = record;
|
||||
const localFilePath = OS.Path.join(
|
||||
OS.Constants.Path.localProfileDir,
|
||||
const localFilePath = lazy.OS.Path.join(
|
||||
lazy.OS.Constants.Path.localProfileDir,
|
||||
...this.folders,
|
||||
filename
|
||||
);
|
||||
const localFileUrl = `file://${[
|
||||
...OS.Path.split(OS.Constants.Path.localProfileDir).components,
|
||||
...lazy.OS.Path.split(lazy.OS.Constants.Path.localProfileDir).components,
|
||||
...this.folders,
|
||||
filename,
|
||||
].join("/")}`;
|
||||
@ -319,7 +320,9 @@ class Downloader {
|
||||
|
||||
let retried = 0;
|
||||
while (true) {
|
||||
if (await RemoteSettingsWorker.checkFileHash(localFileUrl, size, hash)) {
|
||||
if (
|
||||
await lazy.RemoteSettingsWorker.checkFileHash(localFileUrl, size, hash)
|
||||
) {
|
||||
return localFileUrl;
|
||||
}
|
||||
// File does not exist or is corrupted.
|
||||
@ -370,7 +373,9 @@ class Downloader {
|
||||
if (!checkHash) {
|
||||
return buffer;
|
||||
}
|
||||
if (await RemoteSettingsWorker.checkContentHash(buffer, size, hash)) {
|
||||
if (
|
||||
await lazy.RemoteSettingsWorker.checkContentHash(buffer, size, hash)
|
||||
) {
|
||||
return buffer;
|
||||
}
|
||||
// Content is corrupted.
|
||||
@ -400,8 +405,8 @@ class Downloader {
|
||||
const {
|
||||
attachment: { filename },
|
||||
} = record;
|
||||
const path = OS.Path.join(
|
||||
OS.Constants.Path.localProfileDir,
|
||||
const path = lazy.OS.Path.join(
|
||||
lazy.OS.Constants.Path.localProfileDir,
|
||||
...this.folders,
|
||||
filename
|
||||
);
|
||||
@ -411,7 +416,7 @@ class Downloader {
|
||||
|
||||
async _baseAttachmentsURL() {
|
||||
if (!this._cdnURL) {
|
||||
const resp = await Utils.fetch(`${Utils.SERVER_URL}/`);
|
||||
const resp = await lazy.Utils.fetch(`${lazy.Utils.SERVER_URL}/`);
|
||||
let serverInfo;
|
||||
try {
|
||||
serverInfo = await resp.json();
|
||||
@ -433,7 +438,7 @@ class Downloader {
|
||||
async _fetchAttachment(url) {
|
||||
const headers = new Headers();
|
||||
headers.set("Accept-Encoding", "gzip");
|
||||
const resp = await Utils.fetch(url, { headers });
|
||||
const resp = await lazy.Utils.fetch(url, { headers });
|
||||
if (!resp.ok) {
|
||||
throw new Downloader.DownloadError(url, resp);
|
||||
}
|
||||
@ -450,7 +455,9 @@ class Downloader {
|
||||
async readBuffer() {
|
||||
const buffer = await cached.blob.arrayBuffer();
|
||||
const { size, hash } = cached.record.attachment;
|
||||
if (await RemoteSettingsWorker.checkContentHash(buffer, size, hash)) {
|
||||
if (
|
||||
await lazy.RemoteSettingsWorker.checkContentHash(buffer, size, hash)
|
||||
) {
|
||||
return buffer;
|
||||
}
|
||||
// Really unexpected, could indicate corruption in IndexedDB.
|
||||
@ -462,7 +469,7 @@ class Downloader {
|
||||
async _readAttachmentDump(attachmentId) {
|
||||
async function fetchResource(resourceUrl) {
|
||||
try {
|
||||
return await fetch(resourceUrl);
|
||||
return await lazy.fetch(resourceUrl);
|
||||
} catch (e) {
|
||||
throw new Downloader.DownloadError(resourceUrl);
|
||||
}
|
||||
@ -484,8 +491,8 @@ class Downloader {
|
||||
static _RESOURCE_BASE_URL = "resource://app/defaults";
|
||||
|
||||
async _makeDirs() {
|
||||
const dirPath = OS.Path.join(
|
||||
OS.Constants.Path.localProfileDir,
|
||||
const dirPath = lazy.OS.Path.join(
|
||||
lazy.OS.Constants.Path.localProfileDir,
|
||||
...this.folders
|
||||
);
|
||||
await IOUtils.makeDirectory(dirPath, { createAncestors: true });
|
||||
@ -493,8 +500,8 @@ class Downloader {
|
||||
|
||||
async _rmDirs() {
|
||||
for (let i = this.folders.length; i > 0; i--) {
|
||||
const dirPath = OS.Path.join(
|
||||
OS.Constants.Path.localProfileDir,
|
||||
const dirPath = lazy.OS.Path.join(
|
||||
lazy.OS.Constants.Path.localProfileDir,
|
||||
...this.folders.slice(0, i)
|
||||
);
|
||||
try {
|
||||
|
@ -7,14 +7,16 @@ const { XPCOMUtils } = ChromeUtils.import(
|
||||
);
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
const lazy = {};
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(lazy, {
|
||||
AsyncShutdown: "resource://gre/modules/AsyncShutdown.jsm",
|
||||
IDBHelpers: "resource://services-settings/IDBHelpers.jsm",
|
||||
Utils: "resource://services-settings/Utils.jsm",
|
||||
CommonUtils: "resource://services-common/utils.js",
|
||||
ObjectUtils: "resource://gre/modules/ObjectUtils.jsm",
|
||||
});
|
||||
XPCOMUtils.defineLazyGetter(this, "console", () => Utils.log);
|
||||
XPCOMUtils.defineLazyGetter(lazy, "console", () => lazy.Utils.log);
|
||||
|
||||
var EXPORTED_SYMBOLS = ["Database"];
|
||||
|
||||
@ -37,7 +39,7 @@ class Database {
|
||||
"records",
|
||||
(store, rejectTransaction) => {
|
||||
// Fast-path the (very common) no-filters case
|
||||
if (ObjectUtils.isEmpty(filters)) {
|
||||
if (lazy.ObjectUtils.isEmpty(filters)) {
|
||||
const range = IDBKeyRange.only(this.identifier);
|
||||
const request = store.index("cid").getAll(range);
|
||||
request.onsuccess = e => {
|
||||
@ -54,7 +56,7 @@ class Database {
|
||||
const cursor = event.target.result;
|
||||
if (cursor) {
|
||||
const { value } = cursor;
|
||||
if (Utils.filterObject(objFilters, value)) {
|
||||
if (lazy.Utils.filterObject(objFilters, value)) {
|
||||
results.push(value);
|
||||
}
|
||||
cursor.continue();
|
||||
@ -67,13 +69,13 @@ class Database {
|
||||
{ mode: "readonly" }
|
||||
);
|
||||
} catch (e) {
|
||||
throw new IDBHelpers.IndexedDBError(e, "list()", this.identifier);
|
||||
throw new lazy.IDBHelpers.IndexedDBError(e, "list()", this.identifier);
|
||||
}
|
||||
// Remove IDB key field from results.
|
||||
for (const result of results) {
|
||||
delete result._cid;
|
||||
}
|
||||
return order ? Utils.sortObjects(order, results) : results;
|
||||
return order ? lazy.Utils.sortObjects(order, results) : results;
|
||||
}
|
||||
|
||||
async importChanges(metadata, timestamp, records = [], options = {}) {
|
||||
@ -129,17 +131,17 @@ class Database {
|
||||
// Separate tombstones from creations/updates.
|
||||
const toDelete = records.filter(r => r.deleted);
|
||||
const toInsert = records.filter(r => !r.deleted);
|
||||
console.debug(
|
||||
lazy.console.debug(
|
||||
`${_cid} ${toDelete.length} to delete, ${toInsert.length} to insert`
|
||||
);
|
||||
// Delete local records for each tombstone.
|
||||
IDBHelpers.bulkOperationHelper(
|
||||
lazy.IDBHelpers.bulkOperationHelper(
|
||||
storeRecords,
|
||||
{
|
||||
reject: rejectTransaction,
|
||||
completion() {
|
||||
// Overwrite all other data.
|
||||
IDBHelpers.bulkOperationHelper(
|
||||
lazy.IDBHelpers.bulkOperationHelper(
|
||||
storeRecords,
|
||||
{
|
||||
reject: rejectTransaction,
|
||||
@ -156,7 +158,7 @@ class Database {
|
||||
{ desc: "importChanges() in " + _cid }
|
||||
);
|
||||
} catch (e) {
|
||||
throw new IDBHelpers.IndexedDBError(e, "importChanges()", _cid);
|
||||
throw new lazy.IDBHelpers.IndexedDBError(e, "importChanges()", _cid);
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,7 +173,7 @@ class Database {
|
||||
{ mode: "readonly" }
|
||||
);
|
||||
} catch (e) {
|
||||
throw new IDBHelpers.IndexedDBError(
|
||||
throw new lazy.IDBHelpers.IndexedDBError(
|
||||
e,
|
||||
"getLastModified()",
|
||||
this.identifier
|
||||
@ -184,7 +186,7 @@ class Database {
|
||||
// contain timestamps for last_modified. Work around this here, and return
|
||||
// the timestamp as zero, so that the entries should get updated.
|
||||
if (isNaN(entry.value)) {
|
||||
console.warn(`Local timestamp is NaN for ${this.identifier}`);
|
||||
lazy.console.warn(`Local timestamp is NaN for ${this.identifier}`);
|
||||
return 0;
|
||||
}
|
||||
return entry.value;
|
||||
@ -201,7 +203,11 @@ class Database {
|
||||
{ mode: "readonly" }
|
||||
);
|
||||
} catch (e) {
|
||||
throw new IDBHelpers.IndexedDBError(e, "getMetadata()", this.identifier);
|
||||
throw new lazy.IDBHelpers.IndexedDBError(
|
||||
e,
|
||||
"getMetadata()",
|
||||
this.identifier
|
||||
);
|
||||
}
|
||||
return entry ? entry.metadata : null;
|
||||
}
|
||||
@ -219,7 +225,7 @@ class Database {
|
||||
{ mode: "readonly" }
|
||||
);
|
||||
} catch (e) {
|
||||
throw new IDBHelpers.IndexedDBError(
|
||||
throw new lazy.IDBHelpers.IndexedDBError(
|
||||
e,
|
||||
"getAttachment()",
|
||||
this.identifier
|
||||
@ -242,7 +248,7 @@ class Database {
|
||||
{ desc: "saveAttachment(" + attachmentId + ") in " + this.identifier }
|
||||
);
|
||||
} catch (e) {
|
||||
throw new IDBHelpers.IndexedDBError(
|
||||
throw new lazy.IDBHelpers.IndexedDBError(
|
||||
e,
|
||||
"saveAttachment()",
|
||||
this.identifier
|
||||
@ -254,7 +260,7 @@ class Database {
|
||||
try {
|
||||
await this.importChanges(null, null, [], { clear: true });
|
||||
} catch (e) {
|
||||
throw new IDBHelpers.IndexedDBError(e, "clear()", this.identifier);
|
||||
throw new lazy.IDBHelpers.IndexedDBError(e, "clear()", this.identifier);
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,7 +270,7 @@ class Database {
|
||||
|
||||
async create(record) {
|
||||
if (!("id" in record)) {
|
||||
record = { ...record, id: CommonUtils.generateUUID() };
|
||||
record = { ...record, id: lazy.CommonUtils.generateUUID() };
|
||||
}
|
||||
try {
|
||||
await executeIDB(
|
||||
@ -275,7 +281,7 @@ class Database {
|
||||
{ desc: "create() in " + this.identifier }
|
||||
);
|
||||
} catch (e) {
|
||||
throw new IDBHelpers.IndexedDBError(e, "create()", this.identifier);
|
||||
throw new lazy.IDBHelpers.IndexedDBError(e, "create()", this.identifier);
|
||||
}
|
||||
return record;
|
||||
}
|
||||
@ -290,7 +296,7 @@ class Database {
|
||||
{ desc: "update() in " + this.identifier }
|
||||
);
|
||||
} catch (e) {
|
||||
throw new IDBHelpers.IndexedDBError(e, "update()", this.identifier);
|
||||
throw new lazy.IDBHelpers.IndexedDBError(e, "update()", this.identifier);
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,7 +310,7 @@ class Database {
|
||||
{ desc: "delete() in " + this.identifier }
|
||||
);
|
||||
} catch (e) {
|
||||
throw new IDBHelpers.IndexedDBError(e, "delete()", this.identifier);
|
||||
throw new lazy.IDBHelpers.IndexedDBError(e, "delete()", this.identifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -324,7 +330,7 @@ async function openIDB() {
|
||||
// IndexedDB work more than once.
|
||||
if (!gDBPromise) {
|
||||
// Open and initialize/upgrade if needed.
|
||||
gDBPromise = IDBHelpers.openIDB();
|
||||
gDBPromise = lazy.IDBHelpers.openIDB();
|
||||
}
|
||||
let db = await gDBPromise;
|
||||
if (!gDB) {
|
||||
@ -351,7 +357,7 @@ async function executeIDB(storeNames, callback, options = {}) {
|
||||
// both that and a bool we set ourselves when `profile-before-change`
|
||||
// starts.
|
||||
if (gShutdownStarted || Services.startup.shuttingDown) {
|
||||
throw new IDBHelpers.ShutdownError(
|
||||
throw new lazy.IDBHelpers.ShutdownError(
|
||||
"The application is shutting down",
|
||||
"execute()"
|
||||
);
|
||||
@ -365,7 +371,7 @@ async function executeIDB(storeNames, callback, options = {}) {
|
||||
|
||||
// Check for shutdown again as we've await'd something...
|
||||
if (!gDB && (gShutdownStarted || Services.startup.shuttingDown)) {
|
||||
throw new IDBHelpers.ShutdownError(
|
||||
throw new lazy.IDBHelpers.ShutdownError(
|
||||
"The application is shutting down",
|
||||
"execute()"
|
||||
);
|
||||
@ -373,7 +379,7 @@ async function executeIDB(storeNames, callback, options = {}) {
|
||||
|
||||
// Start the actual transaction:
|
||||
const { mode = "readwrite", desc = "" } = options;
|
||||
let { promise, transaction } = IDBHelpers.executeIDB(
|
||||
let { promise, transaction } = lazy.IDBHelpers.executeIDB(
|
||||
gDB,
|
||||
storeNames,
|
||||
mode,
|
||||
@ -469,7 +475,7 @@ function ensureShutdownBlocker() {
|
||||
return;
|
||||
}
|
||||
gShutdownBlocker = true;
|
||||
AsyncShutdown.profileBeforeChange.addBlocker(
|
||||
lazy.AsyncShutdown.profileBeforeChange.addBlocker(
|
||||
"RemoteSettingsClient - finish IDB access.",
|
||||
Database._shutdownHandler,
|
||||
{
|
||||
|
@ -11,7 +11,9 @@ const { XPCOMUtils } = ChromeUtils.import(
|
||||
);
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
const lazy = {};
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(lazy, {
|
||||
AppConstants: "resource://gre/modules/AppConstants.jsm",
|
||||
ClientEnvironmentBase:
|
||||
"resource://gre/modules/components-utils/ClientEnvironment.jsm",
|
||||
@ -28,7 +30,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
|
||||
const TELEMETRY_COMPONENT = "remotesettings";
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "console", () => Utils.log);
|
||||
XPCOMUtils.defineLazyGetter(lazy, "console", () => lazy.Utils.log);
|
||||
|
||||
/**
|
||||
* cacheProxy returns an object Proxy that will memoize properties of the target.
|
||||
@ -145,7 +147,7 @@ class UnknownCollectionError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
class AttachmentDownloader extends Downloader {
|
||||
class AttachmentDownloader extends lazy.Downloader {
|
||||
constructor(client) {
|
||||
super(client.bucketName, client.collectionName);
|
||||
this._client = client;
|
||||
@ -178,14 +180,14 @@ class AttachmentDownloader extends Downloader {
|
||||
return await super.download(record, options);
|
||||
} catch (err) {
|
||||
// Report download error.
|
||||
let status = UptakeTelemetry.STATUS.DOWNLOAD_ERROR;
|
||||
if (Utils.isOffline) {
|
||||
status = UptakeTelemetry.STATUS.NETWORK_OFFLINE_ERROR;
|
||||
let status = lazy.UptakeTelemetry.STATUS.DOWNLOAD_ERROR;
|
||||
if (lazy.Utils.isOffline) {
|
||||
status = lazy.UptakeTelemetry.STATUS.NETWORK_OFFLINE_ERROR;
|
||||
} else if (/NetworkError/.test(err.message)) {
|
||||
status = UptakeTelemetry.STATUS.NETWORK_ERROR;
|
||||
status = lazy.UptakeTelemetry.STATUS.NETWORK_ERROR;
|
||||
}
|
||||
// If the file failed to be downloaded, report it as such in Telemetry.
|
||||
await UptakeTelemetry.report(TELEMETRY_COMPONENT, status, {
|
||||
await lazy.UptakeTelemetry.report(TELEMETRY_COMPONENT, status, {
|
||||
source: this._client.identifier,
|
||||
});
|
||||
throw err;
|
||||
@ -230,7 +232,7 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
constructor(
|
||||
collectionName,
|
||||
{
|
||||
bucketName = AppConstants.REMOTE_SETTINGS_DEFAULT_BUCKET,
|
||||
bucketName = lazy.AppConstants.REMOTE_SETTINGS_DEFAULT_BUCKET,
|
||||
signerName,
|
||||
filterFunc,
|
||||
localFields = [],
|
||||
@ -242,7 +244,7 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
this.collectionName = collectionName;
|
||||
// Client is constructed with the raw bucket name (eg. "main", "security-state", "blocklist")
|
||||
// The `bucketName` will contain the `-preview` suffix if the preview mode is enabled.
|
||||
this.bucketName = Utils.actualBucketName(bucketName);
|
||||
this.bucketName = lazy.Utils.actualBucketName(bucketName);
|
||||
this.signerName = signerName;
|
||||
this.filterFunc = filterFunc;
|
||||
this.localFields = localFields;
|
||||
@ -252,12 +254,12 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
|
||||
// This attribute allows signature verification to be disabled, when running tests
|
||||
// or when pulling data from a dev server.
|
||||
this.verifySignature = AppConstants.REMOTE_SETTINGS_VERIFY_SIGNATURE;
|
||||
this.verifySignature = lazy.AppConstants.REMOTE_SETTINGS_VERIFY_SIGNATURE;
|
||||
|
||||
XPCOMUtils.defineLazyGetter(
|
||||
this,
|
||||
"db",
|
||||
() => new Database(this.identifier)
|
||||
() => new lazy.Database(this.identifier)
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyGetter(
|
||||
@ -274,7 +276,7 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
* See `RemoteSettings.enabledPreviewMode()`.
|
||||
*/
|
||||
refreshBucketName() {
|
||||
this.bucketName = Utils.actualBucketName(this.bucketName);
|
||||
this.bucketName = lazy.Utils.actualBucketName(this.bucketName);
|
||||
this.db.identifier = this.identifier;
|
||||
}
|
||||
|
||||
@ -290,8 +292,8 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
}
|
||||
|
||||
httpClient() {
|
||||
const api = new KintoHttpClient(Utils.SERVER_URL, {
|
||||
fetchFunc: Utils.fetch, // Use fetch() wrapper.
|
||||
const api = new lazy.KintoHttpClient(lazy.Utils.SERVER_URL, {
|
||||
fetchFunc: lazy.Utils.fetch, // Use fetch() wrapper.
|
||||
});
|
||||
return api.bucket(this.bucketName).collection(this.collectionName);
|
||||
}
|
||||
@ -310,7 +312,7 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
try {
|
||||
timestamp = await this.db.getLastModified();
|
||||
} catch (err) {
|
||||
console.warn(
|
||||
lazy.console.warn(
|
||||
`Error retrieving the getLastModified timestamp from ${this.identifier} RemoteSettingsClient`,
|
||||
err
|
||||
);
|
||||
@ -352,14 +354,14 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
if (!this._importingPromise) {
|
||||
// Prevent parallel loading when .get() is called multiple times.
|
||||
this._importingPromise = (async () => {
|
||||
const importedFromDump = Utils.LOAD_DUMPS
|
||||
const importedFromDump = lazy.Utils.LOAD_DUMPS
|
||||
? await this._importJSONDump()
|
||||
: -1;
|
||||
if (importedFromDump < 0) {
|
||||
// There is no JSON dump to load, force a synchronization from the server.
|
||||
// We don't want the "sync" event to be sent, since some consumers use `.get()`
|
||||
// in "sync" callbacks. See Bug 1761953
|
||||
console.debug(
|
||||
lazy.console.debug(
|
||||
`${this.identifier} Local DB is empty, pull data from server`
|
||||
);
|
||||
await this.sync({ loadDump: false, sendEvents: false });
|
||||
@ -370,17 +372,17 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
return true;
|
||||
})();
|
||||
} else {
|
||||
console.debug(`${this.identifier} Awaiting existing import.`);
|
||||
lazy.console.debug(`${this.identifier} Awaiting existing import.`);
|
||||
}
|
||||
} else if (hasLocalData && loadDumpIfNewer) {
|
||||
// Check whether the local data is older than the packaged dump.
|
||||
// If it is, load the packaged dump (which overwrites the local data).
|
||||
let lastModifiedDump = await Utils.getLocalDumpLastModified(
|
||||
let lastModifiedDump = await lazy.Utils.getLocalDumpLastModified(
|
||||
this.bucketName,
|
||||
this.collectionName
|
||||
);
|
||||
if (lastModified < lastModifiedDump) {
|
||||
console.debug(
|
||||
lazy.console.debug(
|
||||
`${this.identifier} Local DB is stale (${lastModified}), using dump instead (${lastModifiedDump})`
|
||||
);
|
||||
if (!this._importingPromise) {
|
||||
@ -394,7 +396,7 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
return importedFromDump >= 0;
|
||||
})();
|
||||
} else {
|
||||
console.debug(`${this.identifier} Awaiting existing import.`);
|
||||
lazy.console.debug(`${this.identifier} Awaiting existing import.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -425,21 +427,23 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
throw e;
|
||||
}
|
||||
Cu.reportError(e);
|
||||
let { data } = await SharedUtils.loadJSONDump(
|
||||
let { data } = await lazy.SharedUtils.loadJSONDump(
|
||||
this.bucketName,
|
||||
this.collectionName
|
||||
);
|
||||
if (data !== null) {
|
||||
console.info(`${this.identifier} falling back to JSON dump`);
|
||||
lazy.console.info(`${this.identifier} falling back to JSON dump`);
|
||||
} else {
|
||||
console.info(`${this.identifier} no dump fallback, return empty list`);
|
||||
lazy.console.info(
|
||||
`${this.identifier} no dump fallback, return empty list`
|
||||
);
|
||||
data = [];
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(filters)) {
|
||||
data = data.filter(r => Utils.filterObject(filters, r));
|
||||
if (!lazy.ObjectUtils.isEmpty(filters)) {
|
||||
data = data.filter(r => lazy.Utils.filterObject(filters, r));
|
||||
}
|
||||
if (order) {
|
||||
data = Utils.sortObjects(order, data);
|
||||
data = lazy.Utils.sortObjects(order, data);
|
||||
}
|
||||
// No need to verify signature on JSON dumps.
|
||||
// If local DB cannot be read, then we don't even try to do anything,
|
||||
@ -447,21 +451,21 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
return this._filterEntries(data);
|
||||
}
|
||||
|
||||
console.debug(
|
||||
lazy.console.debug(
|
||||
`${this.identifier} ${data.length} records before filtering.`
|
||||
);
|
||||
|
||||
if (verifySignature) {
|
||||
console.debug(
|
||||
lazy.console.debug(
|
||||
`${this.identifier} verify signature of local data on read`
|
||||
);
|
||||
const allData = ObjectUtils.isEmpty(filters)
|
||||
const allData = lazy.ObjectUtils.isEmpty(filters)
|
||||
? data
|
||||
: await this.db.list();
|
||||
const localRecords = allData.map(r => this._cleanLocalFields(r));
|
||||
const timestamp = await this.db.getLastModified();
|
||||
let metadata = await this.db.getMetadata();
|
||||
if (syncIfEmpty && ObjectUtils.isEmpty(metadata)) {
|
||||
if (syncIfEmpty && lazy.ObjectUtils.isEmpty(metadata)) {
|
||||
// No sync occured yet, may have records from dump but no metadata.
|
||||
// We don't want the "sync" event to be sent, since some consumers use `.get()`
|
||||
// in "sync" callbacks. See Bug 1761953
|
||||
@ -478,7 +482,7 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
|
||||
// Filter the records based on `this.filterFunc` results.
|
||||
const final = await this._filterEntries(data);
|
||||
console.debug(
|
||||
lazy.console.debug(
|
||||
`${this.identifier} ${final.length} records after filtering.`
|
||||
);
|
||||
return final;
|
||||
@ -492,12 +496,15 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
async sync(options) {
|
||||
// We want to know which timestamp we are expected to obtain in order to leverage
|
||||
// cache busting. We don't provide ETag because we don't want a 304.
|
||||
const { changes } = await Utils.fetchLatestChanges(Utils.SERVER_URL, {
|
||||
filters: {
|
||||
collection: this.collectionName,
|
||||
bucket: this.bucketName,
|
||||
},
|
||||
});
|
||||
const { changes } = await lazy.Utils.fetchLatestChanges(
|
||||
lazy.Utils.SERVER_URL,
|
||||
{
|
||||
filters: {
|
||||
collection: this.collectionName,
|
||||
bucket: this.bucketName,
|
||||
},
|
||||
}
|
||||
);
|
||||
if (changes.length === 0) {
|
||||
throw new RemoteSettingsClient.UnknownCollectionError(this.identifier);
|
||||
}
|
||||
@ -522,7 +529,7 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
async maybeSync(expectedTimestamp, options = {}) {
|
||||
// Should the clients try to load JSON dump? (mainly disabled in tests)
|
||||
const {
|
||||
loadDump = Utils.LOAD_DUMPS,
|
||||
loadDump = lazy.Utils.LOAD_DUMPS,
|
||||
trigger = "manual",
|
||||
sendEvents = true,
|
||||
} = options;
|
||||
@ -530,14 +537,14 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
// Make sure we don't run several synchronizations in parallel, mainly
|
||||
// in order to avoid race conditions in "sync" events listeners.
|
||||
if (this._syncRunning) {
|
||||
console.warn(`${this.identifier} sync already running`);
|
||||
lazy.console.warn(`${this.identifier} sync already running`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent network requests and IndexedDB calls to be initiated
|
||||
// during shutdown.
|
||||
if (Services.startup.shuttingDown) {
|
||||
console.warn(`${this.identifier} sync interrupted by shutdown`);
|
||||
lazy.console.warn(`${this.identifier} sync interrupted by shutdown`);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -549,7 +556,7 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
let thrownError = null;
|
||||
try {
|
||||
// If network is offline, we can't synchronize.
|
||||
if (Utils.isOffline) {
|
||||
if (lazy.Utils.isOffline) {
|
||||
throw new RemoteSettingsClient.NetworkOfflineError();
|
||||
}
|
||||
|
||||
@ -569,7 +576,7 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
const imported = await this._importJSONDump();
|
||||
// The worker only returns an integer. List the imported records to build the sync event.
|
||||
if (imported > 0) {
|
||||
console.debug(
|
||||
lazy.console.debug(
|
||||
`${this.identifier} ${imported} records loaded from JSON dump`
|
||||
);
|
||||
importedFromDump = await this.db.list();
|
||||
@ -587,13 +594,13 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
try {
|
||||
// Is local timestamp up to date with the server?
|
||||
if (expectedTimestamp == collectionLastModified) {
|
||||
console.debug(`${this.identifier} local data is up-to-date`);
|
||||
reportStatus = UptakeTelemetry.STATUS.UP_TO_DATE;
|
||||
lazy.console.debug(`${this.identifier} local data is up-to-date`);
|
||||
reportStatus = lazy.UptakeTelemetry.STATUS.UP_TO_DATE;
|
||||
|
||||
// If the data is up-to-date but don't have metadata (records loaded from dump),
|
||||
// we fetch them and validate the signature immediately.
|
||||
if (this.verifySignature && ObjectUtils.isEmpty(localMetadata)) {
|
||||
console.debug(`${this.identifier} pull collection metadata`);
|
||||
if (this.verifySignature && lazy.ObjectUtils.isEmpty(localMetadata)) {
|
||||
lazy.console.debug(`${this.identifier} pull collection metadata`);
|
||||
const metadata = await this.httpClient().getData({
|
||||
query: { _expected: expectedTimestamp },
|
||||
});
|
||||
@ -601,7 +608,7 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
// We don't bother validating the signature if the dump was just loaded. We do
|
||||
// if the dump was loaded at some other point (eg. from .get()).
|
||||
if (this.verifySignature && importedFromDump.length == 0) {
|
||||
console.debug(
|
||||
lazy.console.debug(
|
||||
`${this.identifier} verify signature of local data`
|
||||
);
|
||||
await this._validateCollectionSignature(
|
||||
@ -659,14 +666,14 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
// Signature verification failed during synchronization.
|
||||
reportStatus =
|
||||
e instanceof CorruptedDataError
|
||||
? UptakeTelemetry.STATUS.CORRUPTION_ERROR
|
||||
: UptakeTelemetry.STATUS.SIGNATURE_ERROR;
|
||||
? lazy.UptakeTelemetry.STATUS.CORRUPTION_ERROR
|
||||
: lazy.UptakeTelemetry.STATUS.SIGNATURE_ERROR;
|
||||
// If sync fails with a signature error, it's likely that our
|
||||
// local data has been modified in some way.
|
||||
// We will attempt to fix this by retrieving the whole
|
||||
// remote collection.
|
||||
try {
|
||||
console.warn(
|
||||
lazy.console.warn(
|
||||
`${this.identifier} Signature verified failed. Retry from scratch`
|
||||
);
|
||||
syncResult = await this._importChanges(
|
||||
@ -679,14 +686,14 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
} catch (e) {
|
||||
// If the signature fails again, or if an error occured during wiping out the
|
||||
// local data, then we report it as a *signature retry* error.
|
||||
reportStatus = UptakeTelemetry.STATUS.SIGNATURE_RETRY_ERROR;
|
||||
reportStatus = lazy.UptakeTelemetry.STATUS.SIGNATURE_RETRY_ERROR;
|
||||
throw e;
|
||||
}
|
||||
} else {
|
||||
// The sync has thrown for other reason than signature verification.
|
||||
// Default status for errors at this step is SYNC_ERROR.
|
||||
reportStatus = this._telemetryFromError(e, {
|
||||
default: UptakeTelemetry.STATUS.SYNC_ERROR,
|
||||
default: lazy.UptakeTelemetry.STATUS.SYNC_ERROR,
|
||||
});
|
||||
throw e;
|
||||
}
|
||||
@ -699,11 +706,11 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
try {
|
||||
await this.emit("sync", { data: filteredSyncResult });
|
||||
} catch (e) {
|
||||
reportStatus = UptakeTelemetry.STATUS.APPLY_ERROR;
|
||||
reportStatus = lazy.UptakeTelemetry.STATUS.APPLY_ERROR;
|
||||
throw e;
|
||||
}
|
||||
} else {
|
||||
console.info(
|
||||
lazy.console.info(
|
||||
`All changes are filtered by JEXL expressions for ${this.identifier}`
|
||||
);
|
||||
}
|
||||
@ -713,13 +720,13 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
// If browser is shutting down, then we can report a specific status.
|
||||
// (eg. IndexedDB will abort transactions)
|
||||
if (Services.startup.shuttingDown) {
|
||||
reportStatus = UptakeTelemetry.STATUS.SHUTDOWN_ERROR;
|
||||
reportStatus = lazy.UptakeTelemetry.STATUS.SHUTDOWN_ERROR;
|
||||
}
|
||||
// If no Telemetry status was determined yet (ie. outside sync step),
|
||||
// then introspect error, default status at this step is UNKNOWN.
|
||||
else if (reportStatus == null) {
|
||||
reportStatus = this._telemetryFromError(e, {
|
||||
default: UptakeTelemetry.STATUS.UNKNOWN_ERROR,
|
||||
default: lazy.UptakeTelemetry.STATUS.UNKNOWN_ERROR,
|
||||
});
|
||||
}
|
||||
throw e;
|
||||
@ -727,7 +734,7 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
const durationMilliseconds = new Date() - startedAt;
|
||||
// No error was reported, this is a success!
|
||||
if (reportStatus === null) {
|
||||
reportStatus = UptakeTelemetry.STATUS.SUCCESS;
|
||||
reportStatus = lazy.UptakeTelemetry.STATUS.SUCCESS;
|
||||
}
|
||||
// Report success/error status to Telemetry.
|
||||
let reportArgs = {
|
||||
@ -738,15 +745,15 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
// In Bug 1617133, we will try to break down specific errors into
|
||||
// more precise statuses by reporting the JavaScript error name
|
||||
// ("TypeError", etc.) to Telemetry on Nightly.
|
||||
const channel = UptakeTelemetry.Policy.getChannel();
|
||||
const channel = lazy.UptakeTelemetry.Policy.getChannel();
|
||||
if (
|
||||
thrownError !== null &&
|
||||
channel == "nightly" &&
|
||||
[
|
||||
UptakeTelemetry.STATUS.SYNC_ERROR,
|
||||
UptakeTelemetry.STATUS.CUSTOM_1_ERROR, // IndexedDB.
|
||||
UptakeTelemetry.STATUS.UNKNOWN_ERROR,
|
||||
UptakeTelemetry.STATUS.SHUTDOWN_ERROR,
|
||||
lazy.UptakeTelemetry.STATUS.SYNC_ERROR,
|
||||
lazy.UptakeTelemetry.STATUS.CUSTOM_1_ERROR, // IndexedDB.
|
||||
lazy.UptakeTelemetry.STATUS.UNKNOWN_ERROR,
|
||||
lazy.UptakeTelemetry.STATUS.SHUTDOWN_ERROR,
|
||||
].includes(reportStatus)
|
||||
) {
|
||||
// List of possible error names for IndexedDB:
|
||||
@ -754,13 +761,13 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
reportArgs = { ...reportArgs, errorName: thrownError.name };
|
||||
}
|
||||
|
||||
await UptakeTelemetry.report(
|
||||
await lazy.UptakeTelemetry.report(
|
||||
TELEMETRY_COMPONENT,
|
||||
reportStatus,
|
||||
reportArgs
|
||||
);
|
||||
|
||||
console.debug(`${this.identifier} sync status is ${reportStatus}`);
|
||||
lazy.console.debug(`${this.identifier} sync status is ${reportStatus}`);
|
||||
this._syncRunning = false;
|
||||
}
|
||||
}
|
||||
@ -773,26 +780,26 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
let reportStatus = options.default;
|
||||
|
||||
if (e instanceof RemoteSettingsClient.NetworkOfflineError) {
|
||||
reportStatus = UptakeTelemetry.STATUS.NETWORK_OFFLINE_ERROR;
|
||||
} else if (e instanceof IDBHelpers.ShutdownError) {
|
||||
reportStatus = UptakeTelemetry.STATUS.SHUTDOWN_ERROR;
|
||||
reportStatus = lazy.UptakeTelemetry.STATUS.NETWORK_OFFLINE_ERROR;
|
||||
} else if (e instanceof lazy.IDBHelpers.ShutdownError) {
|
||||
reportStatus = lazy.UptakeTelemetry.STATUS.SHUTDOWN_ERROR;
|
||||
} else if (/unparseable/.test(e.message)) {
|
||||
reportStatus = UptakeTelemetry.STATUS.PARSE_ERROR;
|
||||
reportStatus = lazy.UptakeTelemetry.STATUS.PARSE_ERROR;
|
||||
} else if (/NetworkError/.test(e.message)) {
|
||||
reportStatus = UptakeTelemetry.STATUS.NETWORK_ERROR;
|
||||
reportStatus = lazy.UptakeTelemetry.STATUS.NETWORK_ERROR;
|
||||
} else if (/Timeout/.test(e.message)) {
|
||||
reportStatus = UptakeTelemetry.STATUS.TIMEOUT_ERROR;
|
||||
reportStatus = lazy.UptakeTelemetry.STATUS.TIMEOUT_ERROR;
|
||||
} else if (/HTTP 5??/.test(e.message)) {
|
||||
reportStatus = UptakeTelemetry.STATUS.SERVER_ERROR;
|
||||
reportStatus = lazy.UptakeTelemetry.STATUS.SERVER_ERROR;
|
||||
} else if (/Backoff/.test(e.message)) {
|
||||
reportStatus = UptakeTelemetry.STATUS.BACKOFF;
|
||||
reportStatus = lazy.UptakeTelemetry.STATUS.BACKOFF;
|
||||
} else if (
|
||||
// Errors from kinto.js IDB adapter.
|
||||
e instanceof IDBHelpers.IndexedDBError ||
|
||||
e instanceof lazy.IDBHelpers.IndexedDBError ||
|
||||
// Other IndexedDB errors (eg. RemoteSettingsWorker).
|
||||
/IndexedDB/.test(e.message)
|
||||
) {
|
||||
reportStatus = UptakeTelemetry.STATUS.CUSTOM_1_ERROR;
|
||||
reportStatus = lazy.UptakeTelemetry.STATUS.CUSTOM_1_ERROR;
|
||||
}
|
||||
|
||||
return reportStatus;
|
||||
@ -802,15 +809,17 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
* Import the JSON files from services/settings/dump into the local DB.
|
||||
*/
|
||||
async _importJSONDump() {
|
||||
console.info(`${this.identifier} try to restore dump`);
|
||||
const result = await RemoteSettingsWorker.importJSONDump(
|
||||
lazy.console.info(`${this.identifier} try to restore dump`);
|
||||
const result = await lazy.RemoteSettingsWorker.importJSONDump(
|
||||
this.bucketName,
|
||||
this.collectionName
|
||||
);
|
||||
if (result < 0) {
|
||||
console.debug(`${this.identifier} no dump available`);
|
||||
lazy.console.debug(`${this.identifier} no dump available`);
|
||||
} else {
|
||||
console.info(`${this.identifier} imported ${result} records from dump`);
|
||||
lazy.console.info(
|
||||
`${this.identifier} imported ${result} records from dump`
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -839,9 +848,9 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
const {
|
||||
signature: { x5u, signature },
|
||||
} = metadata;
|
||||
const certChain = await (await Utils.fetch(x5u)).text();
|
||||
const certChain = await (await lazy.Utils.fetch(x5u)).text();
|
||||
// Merge remote records with local ones and serialize as canonical JSON.
|
||||
const serialized = await RemoteSettingsWorker.canonicalStringify(
|
||||
const serialized = await lazy.RemoteSettingsWorker.canonicalStringify(
|
||||
records,
|
||||
timestamp
|
||||
);
|
||||
@ -883,7 +892,7 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
const since = retry || !localTimestamp ? undefined : `"${localTimestamp}"`;
|
||||
|
||||
// Fetch collection metadata and list of changes from server.
|
||||
console.debug(
|
||||
lazy.console.debug(
|
||||
`${this.identifier} Fetch changes from server (expected=${expectedTimestamp}, since=${since})`
|
||||
);
|
||||
const {
|
||||
@ -901,7 +910,7 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
};
|
||||
// If data wasn't changed, return empty sync result.
|
||||
// This can happen when we update the signature but not the data.
|
||||
console.debug(
|
||||
lazy.console.debug(
|
||||
`${this.identifier} local timestamp: ${localTimestamp}, remote: ${remoteTimestamp}`
|
||||
);
|
||||
if (localTimestamp && remoteTimestamp < localTimestamp) {
|
||||
@ -924,7 +933,7 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
metadata
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(
|
||||
lazy.console.error(
|
||||
`${this.identifier} Signature failed ${retry ? "again" : ""} ${e}`
|
||||
);
|
||||
if (!(e instanceof InvalidSignatureError)) {
|
||||
@ -937,7 +946,7 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
// during sync, from hijacks of local DBs, we will verify
|
||||
// the signature on the data that we had before syncing.
|
||||
let localTrustworthy = false;
|
||||
console.debug(`${this.identifier} verify data before sync`);
|
||||
lazy.console.debug(`${this.identifier} verify data before sync`);
|
||||
try {
|
||||
await this._validateCollectionSignature(
|
||||
localRecords,
|
||||
@ -950,16 +959,16 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
// If it fails for other reason, keep original error and give up.
|
||||
throw sigerr;
|
||||
}
|
||||
console.debug(`${this.identifier} previous data was invalid`);
|
||||
lazy.console.debug(`${this.identifier} previous data was invalid`);
|
||||
}
|
||||
|
||||
if (!localTrustworthy && !retry) {
|
||||
// Signature failed, clear local DB because it contains
|
||||
// bad data (local + remote changes).
|
||||
console.debug(`${this.identifier} clear local data`);
|
||||
lazy.console.debug(`${this.identifier} clear local data`);
|
||||
await this.db.clear();
|
||||
// Local data was tampered, throw and it will retry from empty DB.
|
||||
console.error(`${this.identifier} local data was corrupted`);
|
||||
lazy.console.error(`${this.identifier} local data was corrupted`);
|
||||
throw new CorruptedDataError(this.identifier);
|
||||
} else if (retry) {
|
||||
// We retried already, we will restore the previous local data
|
||||
@ -986,7 +995,7 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
throw e;
|
||||
}
|
||||
} else {
|
||||
console.warn(`${this.identifier} has signature disabled`);
|
||||
lazy.console.warn(`${this.identifier} has signature disabled`);
|
||||
}
|
||||
|
||||
if (this.hasListeners("sync")) {
|
||||
@ -1008,7 +1017,7 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
syncResult.deleted = syncResult.deleted.concat(
|
||||
Array.from(oldById.values())
|
||||
);
|
||||
console.debug(
|
||||
lazy.console.debug(
|
||||
`${this.identifier} ${syncResult.created.length} created. ${syncResult.updated.length} updated. ${syncResult.deleted.length} deleted.`
|
||||
);
|
||||
}
|
||||
@ -1096,7 +1105,7 @@ class RemoteSettingsClient extends EventEmitter {
|
||||
if (!this.filterFunc) {
|
||||
return data;
|
||||
}
|
||||
const environment = cacheProxy(ClientEnvironmentBase);
|
||||
const environment = cacheProxy(lazy.ClientEnvironmentBase);
|
||||
const dataPromises = data.map(e => this.filterFunc(e, environment));
|
||||
const results = await Promise.all(dataPromises);
|
||||
return results.filter(Boolean);
|
||||
|
@ -5,8 +5,10 @@
|
||||
|
||||
var EXPORTED_SYMBOLS = ["RemoteSettingsTimer"];
|
||||
|
||||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
lazy,
|
||||
"RemoteSettings",
|
||||
"resource://services-settings/remote-settings.js"
|
||||
);
|
||||
@ -19,7 +21,7 @@ RemoteSettingsTimer.prototype = {
|
||||
|
||||
// By default, this timer fires once every 24 hours. See the "services.settings.poll_interval" pref.
|
||||
notify(timer) {
|
||||
RemoteSettings.pollChanges({ trigger: "timer" }).catch(e =>
|
||||
lazy.RemoteSettings.pollChanges({ trigger: "timer" }).catch(e =>
|
||||
Cu.reportError(e)
|
||||
);
|
||||
},
|
||||
|
@ -16,21 +16,23 @@ const { setTimeout, clearTimeout } = ChromeUtils.import(
|
||||
|
||||
var EXPORTED_SYMBOLS = ["RemoteSettingsWorker"];
|
||||
|
||||
const lazy = {};
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
lazy,
|
||||
"gMaxIdleMilliseconds",
|
||||
"services.settings.worker_idle_max_milliseconds",
|
||||
30 * 1000 // Default of 30 seconds.
|
||||
);
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
lazy,
|
||||
"AsyncShutdown",
|
||||
"resource://gre/modules/AsyncShutdown.jsm"
|
||||
);
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
lazy,
|
||||
"SharedUtils",
|
||||
"resource://services-settings/SharedUtils.jsm"
|
||||
);
|
||||
@ -128,7 +130,7 @@ class Worker {
|
||||
} else {
|
||||
this.idleTimeoutId = setTimeout(() => {
|
||||
this.stop();
|
||||
}, gMaxIdleMilliseconds);
|
||||
}, lazy.gMaxIdleMilliseconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -187,7 +189,7 @@ class Worker {
|
||||
async checkContentHash(buffer, size, hash) {
|
||||
// The implementation does little work on the current thread, so run the
|
||||
// task on the current thread instead of the worker thread.
|
||||
return SharedUtils.checkContentHash(buffer, size, hash);
|
||||
return lazy.SharedUtils.checkContentHash(buffer, size, hash);
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,7 +200,7 @@ class Worker {
|
||||
// fine. If we ever start creating more than one Worker instance, this
|
||||
// code will need adjusting to deal with that.
|
||||
try {
|
||||
AsyncShutdown.profileBeforeChange.addBlocker(
|
||||
lazy.AsyncShutdown.profileBeforeChange.addBlocker(
|
||||
"Remote Settings profile-before-change",
|
||||
async () => {
|
||||
// First, indicate we've shut down.
|
||||
|
@ -6,7 +6,9 @@ const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
const lazy = {};
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(lazy, {
|
||||
KeyValueService: "resource://gre/modules/kvstore.jsm",
|
||||
});
|
||||
|
||||
@ -109,7 +111,7 @@ class SyncHistory {
|
||||
// Get and cache a handle to the kvstore.
|
||||
const dir = PathUtils.join(PathUtils.profileDir, "settings");
|
||||
await IOUtils.makeDirectory(dir);
|
||||
this.#store = await KeyValueService.getOrCreate(dir, "synchistory");
|
||||
this.#store = await lazy.KeyValueService.getOrCreate(dir, "synchistory");
|
||||
}
|
||||
return this.#store;
|
||||
}
|
||||
|
@ -12,29 +12,31 @@ const { ServiceRequest } = ChromeUtils.import(
|
||||
"resource://gre/modules/ServiceRequest.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
const lazy = {};
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(lazy, {
|
||||
SharedUtils: "resource://services-settings/SharedUtils.jsm",
|
||||
AppConstants: "resource://gre/modules/AppConstants.jsm",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(
|
||||
this,
|
||||
lazy,
|
||||
"CaptivePortalService",
|
||||
"@mozilla.org/network/captive-portal-service;1",
|
||||
"nsICaptivePortalService"
|
||||
);
|
||||
XPCOMUtils.defineLazyServiceGetter(
|
||||
this,
|
||||
lazy,
|
||||
"gNetworkLinkService",
|
||||
"@mozilla.org/network/network-link-service;1",
|
||||
"nsINetworkLinkService"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]);
|
||||
XPCOMUtils.defineLazyGlobalGetters(lazy, ["fetch"]);
|
||||
|
||||
// Create a new instance of the ConsoleAPI so we can control the maxLogLevel with a pref.
|
||||
// See LOG_LEVELS in Console.jsm. Common examples: "all", "debug", "info", "warn", "error".
|
||||
XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
XPCOMUtils.defineLazyGetter(lazy, "log", () => {
|
||||
const { ConsoleAPI } = ChromeUtils.import(
|
||||
"resource://gre/modules/Console.jsm"
|
||||
);
|
||||
@ -45,7 +47,7 @@ XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
});
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "isRunningTests", () => {
|
||||
XPCOMUtils.defineLazyGetter(lazy, "isRunningTests", () => {
|
||||
const env = Cc["@mozilla.org/process/environment;1"].getService(
|
||||
Ci.nsIEnvironment
|
||||
);
|
||||
@ -59,13 +61,13 @@ XPCOMUtils.defineLazyGetter(this, "isRunningTests", () => {
|
||||
|
||||
// Overriding the server URL is normally disabled on Beta and Release channels,
|
||||
// except under some conditions.
|
||||
XPCOMUtils.defineLazyGetter(this, "allowServerURLOverride", () => {
|
||||
if (!AppConstants.RELEASE_OR_BETA) {
|
||||
XPCOMUtils.defineLazyGetter(lazy, "allowServerURLOverride", () => {
|
||||
if (!lazy.AppConstants.RELEASE_OR_BETA) {
|
||||
// Always allow to override the server URL on Nightly/DevEdition.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isRunningTests) {
|
||||
if (lazy.isRunningTests) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -82,14 +84,14 @@ XPCOMUtils.defineLazyGetter(this, "allowServerURLOverride", () => {
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
lazy,
|
||||
"gServerURL",
|
||||
"services.settings.server",
|
||||
AppConstants.REMOTE_SETTINGS_SERVER_URL
|
||||
lazy.AppConstants.REMOTE_SETTINGS_SERVER_URL
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
lazy,
|
||||
"gPreviewEnabled",
|
||||
"services.settings.preview_enabled",
|
||||
false
|
||||
@ -101,9 +103,9 @@ function _isUndefined(value) {
|
||||
|
||||
var Utils = {
|
||||
get SERVER_URL() {
|
||||
return allowServerURLOverride
|
||||
? gServerURL
|
||||
: AppConstants.REMOTE_SETTINGS_SERVER_URL;
|
||||
return lazy.allowServerURLOverride
|
||||
? lazy.gServerURL
|
||||
: lazy.AppConstants.REMOTE_SETTINGS_SERVER_URL;
|
||||
},
|
||||
|
||||
CHANGES_PATH: "/buckets/monitor/collections/changes/changeset",
|
||||
@ -111,21 +113,21 @@ var Utils = {
|
||||
/**
|
||||
* Logger instance.
|
||||
*/
|
||||
log,
|
||||
log: lazy.log,
|
||||
|
||||
get LOAD_DUMPS() {
|
||||
// Load dumps only if pulling data from the production server, or in tests.
|
||||
return (
|
||||
this.SERVER_URL == AppConstants.REMOTE_SETTINGS_SERVER_URL ||
|
||||
isRunningTests
|
||||
this.SERVER_URL == lazy.AppConstants.REMOTE_SETTINGS_SERVER_URL ||
|
||||
lazy.isRunningTests
|
||||
);
|
||||
},
|
||||
|
||||
get PREVIEW_MODE() {
|
||||
// We want to offer the ability to set preview mode via a preference
|
||||
// for consumers who want to pull from the preview bucket on startup.
|
||||
if (_isUndefined(this._previewModeEnabled) && allowServerURLOverride) {
|
||||
return gPreviewEnabled;
|
||||
if (_isUndefined(this._previewModeEnabled) && lazy.allowServerURLOverride) {
|
||||
return lazy.gPreviewEnabled;
|
||||
}
|
||||
return !!this._previewModeEnabled;
|
||||
},
|
||||
@ -176,11 +178,12 @@ var Utils = {
|
||||
try {
|
||||
return (
|
||||
Services.io.offline ||
|
||||
CaptivePortalService.state == CaptivePortalService.LOCKED_PORTAL ||
|
||||
!gNetworkLinkService.isLinkUp
|
||||
lazy.CaptivePortalService.state ==
|
||||
lazy.CaptivePortalService.LOCKED_PORTAL ||
|
||||
!lazy.gNetworkLinkService.isLinkUp
|
||||
);
|
||||
} catch (ex) {
|
||||
log.warn("Could not determine network status.", ex);
|
||||
lazy.log.warn("Could not determine network status.", ex);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
@ -279,7 +282,7 @@ var Utils = {
|
||||
*/
|
||||
async hasLocalDump(bucket, collection) {
|
||||
try {
|
||||
await fetch(
|
||||
await lazy.fetch(
|
||||
`resource://app/defaults/settings/${bucket}/${collection}.json`,
|
||||
{
|
||||
method: "HEAD",
|
||||
@ -303,12 +306,12 @@ var Utils = {
|
||||
if (!this._dumpStatsInitPromise) {
|
||||
this._dumpStatsInitPromise = (async () => {
|
||||
try {
|
||||
let res = await fetch(
|
||||
let res = await lazy.fetch(
|
||||
"resource://app/defaults/settings/last_modified.json"
|
||||
);
|
||||
this._dumpStats = await res.json();
|
||||
} catch (e) {
|
||||
log.warn(`Failed to load last_modified.json: ${e}`);
|
||||
lazy.log.warn(`Failed to load last_modified.json: ${e}`);
|
||||
this._dumpStats = {};
|
||||
}
|
||||
delete this._dumpStatsInitPromise;
|
||||
@ -319,7 +322,7 @@ var Utils = {
|
||||
const identifier = `${bucket}/${collection}`;
|
||||
let lastModified = this._dumpStats[identifier];
|
||||
if (lastModified === undefined) {
|
||||
const { timestamp: dumpTimestamp } = await SharedUtils.loadJSONDump(
|
||||
const { timestamp: dumpTimestamp } = await lazy.SharedUtils.loadJSONDump(
|
||||
bucket,
|
||||
collection
|
||||
);
|
||||
|
@ -17,7 +17,9 @@ const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
const lazy = {};
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(lazy, {
|
||||
AppConstants: "resource://gre/modules/AppConstants.jsm",
|
||||
UptakeTelemetry: "resource://services-common/uptake-telemetry.js",
|
||||
pushBroadcastService: "resource://gre/modules/PushBroadcastService.jsm",
|
||||
@ -29,7 +31,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
RemoteSettingsWorker: "resource://services-settings/RemoteSettingsWorker.jsm",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]);
|
||||
XPCOMUtils.defineLazyGlobalGetters(lazy, ["fetch"]);
|
||||
|
||||
const PREF_SETTINGS_BRANCH = "services.settings.";
|
||||
const PREF_SETTINGS_SERVER_BACKOFF = "server.backoff";
|
||||
@ -51,19 +53,19 @@ const BROADCAST_ID = "remote-settings/monitor_changes";
|
||||
// Signer to be used when not specified (see Ci.nsIContentSignatureVerifier).
|
||||
const DEFAULT_SIGNER = "remote-settings.content-signature.mozilla.org";
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gPrefs", () => {
|
||||
XPCOMUtils.defineLazyGetter(lazy, "gPrefs", () => {
|
||||
return Services.prefs.getBranch(PREF_SETTINGS_BRANCH);
|
||||
});
|
||||
XPCOMUtils.defineLazyGetter(this, "console", () => Utils.log);
|
||||
XPCOMUtils.defineLazyGetter(lazy, "console", () => lazy.Utils.log);
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gSyncHistory", () => {
|
||||
const prefSize = gPrefs.getIntPref(PREF_SETTINGS_SYNC_HISTORY_SIZE, 100);
|
||||
XPCOMUtils.defineLazyGetter(lazy, "gSyncHistory", () => {
|
||||
const prefSize = lazy.gPrefs.getIntPref(PREF_SETTINGS_SYNC_HISTORY_SIZE, 100);
|
||||
const size = Math.min(Math.max(prefSize, 1000), 10);
|
||||
return new SyncHistory(TELEMETRY_SOURCE_SYNC, { size });
|
||||
return new lazy.SyncHistory(TELEMETRY_SOURCE_SYNC, { size });
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
lazy,
|
||||
"gPrefBrokenSyncThreshold",
|
||||
PREF_SETTINGS_BRANCH + PREF_SETTINGS_SYNC_HISTORY_ERROR_THRESHOLD,
|
||||
10
|
||||
@ -86,7 +88,7 @@ async function jexlFilterFunc(entry, environment) {
|
||||
const context = {
|
||||
env: environment,
|
||||
};
|
||||
result = await FilterExpressions.eval(filter_expression, context);
|
||||
result = await lazy.FilterExpressions.eval(filter_expression, context);
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
@ -114,7 +116,7 @@ function remoteSettingsFunction() {
|
||||
// Get or instantiate a remote settings client.
|
||||
if (!_clients.has(collectionName)) {
|
||||
// Register a new client!
|
||||
const c = new RemoteSettingsClient(collectionName, {
|
||||
const c = new lazy.RemoteSettingsClient(collectionName, {
|
||||
...defaultOptions,
|
||||
...options,
|
||||
});
|
||||
@ -123,7 +125,7 @@ function remoteSettingsFunction() {
|
||||
// Invalidate the polling status, since we want the new collection to
|
||||
// be taken into account.
|
||||
_invalidatePolling = true;
|
||||
console.debug(`Instantiated new client ${c.identifier}`);
|
||||
lazy.console.debug(`Instantiated new client ${c.identifier}`);
|
||||
}
|
||||
return _clients.get(collectionName);
|
||||
};
|
||||
@ -145,12 +147,14 @@ function remoteSettingsFunction() {
|
||||
// this client is known but it was not registered yet (eg. calling module not "imported" yet).
|
||||
if (
|
||||
bucketName ==
|
||||
Utils.actualBucketName(AppConstants.REMOTE_SETTINGS_DEFAULT_BUCKET)
|
||||
lazy.Utils.actualBucketName(
|
||||
lazy.AppConstants.REMOTE_SETTINGS_DEFAULT_BUCKET
|
||||
)
|
||||
) {
|
||||
const c = new RemoteSettingsClient(collectionName, defaultOptions);
|
||||
const c = new lazy.RemoteSettingsClient(collectionName, defaultOptions);
|
||||
const [dbExists, localDump] = await Promise.all([
|
||||
Utils.hasLocalData(c),
|
||||
Utils.hasLocalDump(bucketName, collectionName),
|
||||
lazy.Utils.hasLocalData(c),
|
||||
lazy.Utils.hasLocalDump(bucketName, collectionName),
|
||||
]);
|
||||
if (dbExists || localDump) {
|
||||
return c;
|
||||
@ -160,7 +164,7 @@ function remoteSettingsFunction() {
|
||||
// Mainly because we cannot guess which `signerName` has to be used for example.
|
||||
// And we don't want to synchronize data for collections in the main bucket that are
|
||||
// completely unknown (ie. no database and no JSON dump).
|
||||
console.debug(`No known client for ${bucketName}/${collectionName}`);
|
||||
lazy.console.debug(`No known client for ${bucketName}/${collectionName}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -171,11 +175,11 @@ function remoteSettingsFunction() {
|
||||
*/
|
||||
async function isSynchronizationBroken() {
|
||||
// The minimum number of errors is customizable, but with a maximum.
|
||||
const threshold = Math.min(gPrefBrokenSyncThreshold, 20);
|
||||
const threshold = Math.min(lazy.gPrefBrokenSyncThreshold, 20);
|
||||
// Read history of synchronization past statuses.
|
||||
const pastEntries = await gSyncHistory.list();
|
||||
const pastEntries = await lazy.gSyncHistory.list();
|
||||
const lastSuccessIdx = pastEntries.findIndex(
|
||||
e => e.status == UptakeTelemetry.STATUS.SUCCESS
|
||||
e => e.status == lazy.UptakeTelemetry.STATUS.SUCCESS
|
||||
);
|
||||
return (
|
||||
// Only errors since last success.
|
||||
@ -201,9 +205,9 @@ function remoteSettingsFunction() {
|
||||
} = {}) => {
|
||||
// When running in full mode, we ignore last polling status.
|
||||
if (full) {
|
||||
gPrefs.clearUserPref(PREF_SETTINGS_SERVER_BACKOFF);
|
||||
gPrefs.clearUserPref(PREF_SETTINGS_LAST_UPDATE);
|
||||
gPrefs.clearUserPref(PREF_SETTINGS_LAST_ETAG);
|
||||
lazy.gPrefs.clearUserPref(PREF_SETTINGS_SERVER_BACKOFF);
|
||||
lazy.gPrefs.clearUserPref(PREF_SETTINGS_LAST_UPDATE);
|
||||
lazy.gPrefs.clearUserPref(PREF_SETTINGS_LAST_ETAG);
|
||||
}
|
||||
|
||||
let pollTelemetryArgs = {
|
||||
@ -211,11 +215,11 @@ function remoteSettingsFunction() {
|
||||
trigger,
|
||||
};
|
||||
|
||||
if (Utils.isOffline) {
|
||||
console.info("Network is offline. Give up.");
|
||||
await UptakeTelemetry.report(
|
||||
if (lazy.Utils.isOffline) {
|
||||
lazy.console.info("Network is offline. Give up.");
|
||||
await lazy.UptakeTelemetry.report(
|
||||
TELEMETRY_COMPONENT,
|
||||
UptakeTelemetry.STATUS.NETWORK_OFFLINE_ERROR,
|
||||
lazy.UptakeTelemetry.STATUS.NETWORK_OFFLINE_ERROR,
|
||||
pollTelemetryArgs
|
||||
);
|
||||
return;
|
||||
@ -224,17 +228,17 @@ function remoteSettingsFunction() {
|
||||
const startedAt = new Date();
|
||||
|
||||
// Check if the server backoff time is elapsed.
|
||||
if (gPrefs.prefHasUserValue(PREF_SETTINGS_SERVER_BACKOFF)) {
|
||||
const backoffReleaseTime = gPrefs.getCharPref(
|
||||
if (lazy.gPrefs.prefHasUserValue(PREF_SETTINGS_SERVER_BACKOFF)) {
|
||||
const backoffReleaseTime = lazy.gPrefs.getCharPref(
|
||||
PREF_SETTINGS_SERVER_BACKOFF
|
||||
);
|
||||
const remainingMilliseconds =
|
||||
parseInt(backoffReleaseTime, 10) - Date.now();
|
||||
if (remainingMilliseconds > 0) {
|
||||
// Backoff time has not elapsed yet.
|
||||
await UptakeTelemetry.report(
|
||||
await lazy.UptakeTelemetry.report(
|
||||
TELEMETRY_COMPONENT,
|
||||
UptakeTelemetry.STATUS.BACKOFF,
|
||||
lazy.UptakeTelemetry.STATUS.BACKOFF,
|
||||
pollTelemetryArgs
|
||||
);
|
||||
throw new Error(
|
||||
@ -243,11 +247,11 @@ function remoteSettingsFunction() {
|
||||
)}s.`
|
||||
);
|
||||
} else {
|
||||
gPrefs.clearUserPref(PREF_SETTINGS_SERVER_BACKOFF);
|
||||
lazy.gPrefs.clearUserPref(PREF_SETTINGS_SERVER_BACKOFF);
|
||||
}
|
||||
}
|
||||
|
||||
console.info("Start polling for changes");
|
||||
lazy.console.info("Start polling for changes");
|
||||
Services.obs.notifyObservers(
|
||||
null,
|
||||
"remote-settings:changes-poll-start",
|
||||
@ -258,11 +262,11 @@ function remoteSettingsFunction() {
|
||||
// Every time we register a new client, we have to fetch the whole list again.
|
||||
const lastEtag = _invalidatePolling
|
||||
? ""
|
||||
: gPrefs.getCharPref(PREF_SETTINGS_LAST_ETAG, "");
|
||||
: lazy.gPrefs.getCharPref(PREF_SETTINGS_LAST_ETAG, "");
|
||||
|
||||
let pollResult;
|
||||
try {
|
||||
pollResult = await Utils.fetchLatestChanges(Utils.SERVER_URL, {
|
||||
pollResult = await lazy.Utils.fetchLatestChanges(lazy.Utils.SERVER_URL, {
|
||||
expectedTimestamp,
|
||||
lastEtag,
|
||||
});
|
||||
@ -270,19 +274,19 @@ function remoteSettingsFunction() {
|
||||
// Report polling error to Uptake Telemetry.
|
||||
let reportStatus;
|
||||
if (/JSON\.parse/.test(e.message)) {
|
||||
reportStatus = UptakeTelemetry.STATUS.PARSE_ERROR;
|
||||
reportStatus = lazy.UptakeTelemetry.STATUS.PARSE_ERROR;
|
||||
} else if (/content-type/.test(e.message)) {
|
||||
reportStatus = UptakeTelemetry.STATUS.CONTENT_ERROR;
|
||||
reportStatus = lazy.UptakeTelemetry.STATUS.CONTENT_ERROR;
|
||||
} else if (/Server/.test(e.message)) {
|
||||
reportStatus = UptakeTelemetry.STATUS.SERVER_ERROR;
|
||||
reportStatus = lazy.UptakeTelemetry.STATUS.SERVER_ERROR;
|
||||
} else if (/Timeout/.test(e.message)) {
|
||||
reportStatus = UptakeTelemetry.STATUS.TIMEOUT_ERROR;
|
||||
reportStatus = lazy.UptakeTelemetry.STATUS.TIMEOUT_ERROR;
|
||||
} else if (/NetworkError/.test(e.message)) {
|
||||
reportStatus = UptakeTelemetry.STATUS.NETWORK_ERROR;
|
||||
reportStatus = lazy.UptakeTelemetry.STATUS.NETWORK_ERROR;
|
||||
} else {
|
||||
reportStatus = UptakeTelemetry.STATUS.UNKNOWN_ERROR;
|
||||
reportStatus = lazy.UptakeTelemetry.STATUS.UNKNOWN_ERROR;
|
||||
}
|
||||
await UptakeTelemetry.report(
|
||||
await lazy.UptakeTelemetry.report(
|
||||
TELEMETRY_COMPONENT,
|
||||
reportStatus,
|
||||
pollTelemetryArgs
|
||||
@ -305,9 +309,9 @@ function remoteSettingsFunction() {
|
||||
// Report polling success to Uptake Telemetry.
|
||||
const reportStatus =
|
||||
changes.length === 0
|
||||
? UptakeTelemetry.STATUS.UP_TO_DATE
|
||||
: UptakeTelemetry.STATUS.SUCCESS;
|
||||
await UptakeTelemetry.report(
|
||||
? lazy.UptakeTelemetry.STATUS.UP_TO_DATE
|
||||
: lazy.UptakeTelemetry.STATUS.SUCCESS;
|
||||
await lazy.UptakeTelemetry.report(
|
||||
TELEMETRY_COMPONENT,
|
||||
reportStatus,
|
||||
pollTelemetryArgs
|
||||
@ -315,20 +319,23 @@ function remoteSettingsFunction() {
|
||||
|
||||
// Check if the server asked the clients to back off (for next poll).
|
||||
if (backoffSeconds) {
|
||||
console.info(
|
||||
lazy.console.info(
|
||||
"Server asks clients to backoff for ${backoffSeconds} seconds"
|
||||
);
|
||||
const backoffReleaseTime = Date.now() + backoffSeconds * 1000;
|
||||
gPrefs.setCharPref(PREF_SETTINGS_SERVER_BACKOFF, backoffReleaseTime);
|
||||
lazy.gPrefs.setCharPref(PREF_SETTINGS_SERVER_BACKOFF, backoffReleaseTime);
|
||||
}
|
||||
|
||||
// Record new update time and the difference between local and server time.
|
||||
// Negative clockDifference means local time is behind server time
|
||||
// by the absolute of that value in seconds (positive means it's ahead)
|
||||
const clockDifference = Math.floor((Date.now() - serverTimeMillis) / 1000);
|
||||
gPrefs.setIntPref(PREF_SETTINGS_CLOCK_SKEW_SECONDS, clockDifference);
|
||||
lazy.gPrefs.setIntPref(PREF_SETTINGS_CLOCK_SKEW_SECONDS, clockDifference);
|
||||
const checkedServerTimeInSeconds = Math.round(serverTimeMillis / 1000);
|
||||
gPrefs.setIntPref(PREF_SETTINGS_LAST_UPDATE, checkedServerTimeInSeconds);
|
||||
lazy.gPrefs.setIntPref(
|
||||
PREF_SETTINGS_LAST_UPDATE,
|
||||
checkedServerTimeInSeconds
|
||||
);
|
||||
|
||||
// Iterate through the collections version info and initiate a synchronization
|
||||
// on the related remote settings clients.
|
||||
@ -352,7 +359,7 @@ function remoteSettingsFunction() {
|
||||
checkedServerTimeInSeconds
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
lazy.console.error(e);
|
||||
if (!firstError) {
|
||||
firstError = e;
|
||||
firstError.details = change;
|
||||
@ -374,14 +381,14 @@ function remoteSettingsFunction() {
|
||||
|
||||
if (firstError) {
|
||||
// Report the global synchronization failure. Individual uptake reports will also have been sent for each collection.
|
||||
const status = UptakeTelemetry.STATUS.SYNC_ERROR;
|
||||
await UptakeTelemetry.report(
|
||||
const status = lazy.UptakeTelemetry.STATUS.SYNC_ERROR;
|
||||
await lazy.UptakeTelemetry.report(
|
||||
TELEMETRY_COMPONENT,
|
||||
status,
|
||||
syncTelemetryArgs
|
||||
);
|
||||
// Keep track of sync failure in history.
|
||||
await gSyncHistory
|
||||
await lazy.gSyncHistory
|
||||
.store(currentEtag, status, {
|
||||
expectedTimestamp,
|
||||
errorName: firstError.name,
|
||||
@ -397,9 +404,9 @@ function remoteSettingsFunction() {
|
||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1729400
|
||||
// and https://bugzilla.mozilla.org/show_bug.cgi?id=1658597
|
||||
if (await isSynchronizationBroken()) {
|
||||
await UptakeTelemetry.report(
|
||||
await lazy.UptakeTelemetry.report(
|
||||
TELEMETRY_COMPONENT,
|
||||
UptakeTelemetry.STATUS.SYNC_BROKEN_ERROR,
|
||||
lazy.UptakeTelemetry.STATUS.SYNC_BROKEN_ERROR,
|
||||
syncTelemetryArgs
|
||||
);
|
||||
|
||||
@ -414,21 +421,21 @@ function remoteSettingsFunction() {
|
||||
}
|
||||
|
||||
// Save current Etag for next poll.
|
||||
gPrefs.setCharPref(PREF_SETTINGS_LAST_ETAG, currentEtag);
|
||||
lazy.gPrefs.setCharPref(PREF_SETTINGS_LAST_ETAG, currentEtag);
|
||||
|
||||
// Report the global synchronization success.
|
||||
const status = UptakeTelemetry.STATUS.SUCCESS;
|
||||
await UptakeTelemetry.report(
|
||||
const status = lazy.UptakeTelemetry.STATUS.SUCCESS;
|
||||
await lazy.UptakeTelemetry.report(
|
||||
TELEMETRY_COMPONENT,
|
||||
status,
|
||||
syncTelemetryArgs
|
||||
);
|
||||
// Keep track of sync success in history.
|
||||
await gSyncHistory
|
||||
await lazy.gSyncHistory
|
||||
.store(currentEtag, status)
|
||||
.catch(error => Cu.reportError(error));
|
||||
|
||||
console.info("Polling for changes done");
|
||||
lazy.console.info("Polling for changes done");
|
||||
Services.obs.notifyObservers(null, "remote-settings:changes-poll-end");
|
||||
};
|
||||
|
||||
@ -441,7 +448,7 @@ function remoteSettingsFunction() {
|
||||
*/
|
||||
remoteSettings.enablePreviewMode = enabled => {
|
||||
// Set the flag for future clients.
|
||||
Utils.enablePreviewMode(enabled);
|
||||
lazy.Utils.enablePreviewMode(enabled);
|
||||
// Enable it on existing clients.
|
||||
for (const client of _clients.values()) {
|
||||
client.refreshBucketName();
|
||||
@ -456,7 +463,7 @@ function remoteSettingsFunction() {
|
||||
const {
|
||||
changes,
|
||||
currentEtag: serverTimestamp,
|
||||
} = await Utils.fetchLatestChanges(Utils.SERVER_URL);
|
||||
} = await lazy.Utils.fetchLatestChanges(lazy.Utils.SERVER_URL);
|
||||
|
||||
const collections = await Promise.all(
|
||||
changes.map(async change => {
|
||||
@ -482,19 +489,19 @@ function remoteSettingsFunction() {
|
||||
);
|
||||
|
||||
return {
|
||||
serverURL: Utils.SERVER_URL,
|
||||
pollingEndpoint: Utils.SERVER_URL + Utils.CHANGES_PATH,
|
||||
serverURL: lazy.Utils.SERVER_URL,
|
||||
pollingEndpoint: lazy.Utils.SERVER_URL + lazy.Utils.CHANGES_PATH,
|
||||
serverTimestamp,
|
||||
localTimestamp: gPrefs.getCharPref(PREF_SETTINGS_LAST_ETAG, null),
|
||||
lastCheck: gPrefs.getIntPref(PREF_SETTINGS_LAST_UPDATE, 0),
|
||||
mainBucket: Utils.actualBucketName(
|
||||
AppConstants.REMOTE_SETTINGS_DEFAULT_BUCKET
|
||||
localTimestamp: lazy.gPrefs.getCharPref(PREF_SETTINGS_LAST_ETAG, null),
|
||||
lastCheck: lazy.gPrefs.getIntPref(PREF_SETTINGS_LAST_UPDATE, 0),
|
||||
mainBucket: lazy.Utils.actualBucketName(
|
||||
lazy.AppConstants.REMOTE_SETTINGS_DEFAULT_BUCKET
|
||||
),
|
||||
defaultSigner: DEFAULT_SIGNER,
|
||||
previewMode: Utils.PREVIEW_MODE,
|
||||
previewMode: lazy.Utils.PREVIEW_MODE,
|
||||
collections: collections.filter(c => !!c),
|
||||
history: {
|
||||
[TELEMETRY_SOURCE_SYNC]: await gSyncHistory.list(),
|
||||
[TELEMETRY_SOURCE_SYNC]: await lazy.gSyncHistory.list(),
|
||||
},
|
||||
};
|
||||
};
|
||||
@ -521,19 +528,26 @@ function remoteSettingsFunction() {
|
||||
* Startup function called from nsBrowserGlue.
|
||||
*/
|
||||
remoteSettings.init = () => {
|
||||
console.info("Initialize Remote Settings");
|
||||
lazy.console.info("Initialize Remote Settings");
|
||||
// Hook the Push broadcast and RemoteSettings polling.
|
||||
// When we start on a new profile there will be no ETag stored.
|
||||
// Use an arbitrary ETag that is guaranteed not to occur.
|
||||
// This will trigger a broadcast message but that's fine because we
|
||||
// will check the changes on each collection and retrieve only the
|
||||
// changes (e.g. nothing if we have a dump with the same data).
|
||||
const currentVersion = gPrefs.getStringPref(PREF_SETTINGS_LAST_ETAG, '"0"');
|
||||
const currentVersion = lazy.gPrefs.getStringPref(
|
||||
PREF_SETTINGS_LAST_ETAG,
|
||||
'"0"'
|
||||
);
|
||||
const moduleInfo = {
|
||||
moduleURI: __URI__,
|
||||
symbolName: "remoteSettingsBroadcastHandler",
|
||||
};
|
||||
pushBroadcastService.addListener(BROADCAST_ID, currentVersion, moduleInfo);
|
||||
lazy.pushBroadcastService.addListener(
|
||||
BROADCAST_ID,
|
||||
currentVersion,
|
||||
moduleInfo
|
||||
);
|
||||
};
|
||||
|
||||
return remoteSettings;
|
||||
@ -545,11 +559,11 @@ var remoteSettingsBroadcastHandler = {
|
||||
async receivedBroadcastMessage(version, broadcastID, context) {
|
||||
const { phase } = context;
|
||||
const isStartup = [
|
||||
pushBroadcastService.PHASES.HELLO,
|
||||
pushBroadcastService.PHASES.REGISTER,
|
||||
lazy.pushBroadcastService.PHASES.HELLO,
|
||||
lazy.pushBroadcastService.PHASES.REGISTER,
|
||||
].includes(phase);
|
||||
|
||||
console.info(
|
||||
lazy.console.info(
|
||||
`Push notification received (version=${version} phase=${phase})`
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user