diff --git a/services/settings/Attachments.jsm b/services/settings/Attachments.jsm index 2bf846e4e131..21fab90a8856 100644 --- a/services/settings/Attachments.jsm +++ b/services/settings/Attachments.jsm @@ -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 { diff --git a/services/settings/Database.jsm b/services/settings/Database.jsm index 84f41ed851d3..b000ea90430f 100644 --- a/services/settings/Database.jsm +++ b/services/settings/Database.jsm @@ -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, { diff --git a/services/settings/RemoteSettingsClient.jsm b/services/settings/RemoteSettingsClient.jsm index 4eb23786bb58..1361e957964f 100644 --- a/services/settings/RemoteSettingsClient.jsm +++ b/services/settings/RemoteSettingsClient.jsm @@ -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); diff --git a/services/settings/RemoteSettingsComponents.jsm b/services/settings/RemoteSettingsComponents.jsm index a2b3141ee13f..083a215624bc 100644 --- a/services/settings/RemoteSettingsComponents.jsm +++ b/services/settings/RemoteSettingsComponents.jsm @@ -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) ); }, diff --git a/services/settings/RemoteSettingsWorker.jsm b/services/settings/RemoteSettingsWorker.jsm index 147ebb6b13d6..9fc1794f9083 100644 --- a/services/settings/RemoteSettingsWorker.jsm +++ b/services/settings/RemoteSettingsWorker.jsm @@ -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. diff --git a/services/settings/SyncHistory.jsm b/services/settings/SyncHistory.jsm index 03b2c4264646..46a43c76d7bf 100644 --- a/services/settings/SyncHistory.jsm +++ b/services/settings/SyncHistory.jsm @@ -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; } diff --git a/services/settings/Utils.jsm b/services/settings/Utils.jsm index 2f2f2a3808f7..7d0c8ccfc7d9 100644 --- a/services/settings/Utils.jsm +++ b/services/settings/Utils.jsm @@ -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 ); diff --git a/services/settings/remote-settings.js b/services/settings/remote-settings.js index f7e8e24748ae..26fe490ab2c7 100644 --- a/services/settings/remote-settings.js +++ b/services/settings/remote-settings.js @@ -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})` );