author | Bob Silverberg <bsilverberg@mozilla.com> |
Thu, 20 Jul 2017 09:02:36 -0400 | |
changeset 371169 | 2ce634e4577e122b7214b350122f48061396a908 |
parent 371168 | e3dadcaf272679963974179a1334f8c2df1ef57f |
child 371170 | 1f80b3961a73ac1c0368af9e7e39ce582c9ead5a |
push id | 93039 |
push user | kwierso@gmail.com |
push date | Thu, 27 Jul 2017 01:33:28 +0000 |
treeherder | mozilla-inbound@35b0bdaacb0d [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | aswan |
bugs | 1381297 |
milestone | 56.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/toolkit/components/extensions/ExtensionSettingsStore.jsm +++ b/toolkit/components/extensions/ExtensionSettingsStore.jsm @@ -18,17 +18,17 @@ * * { * type: { // The type of settings being stored in this object, i.e., prefs. * key: { // The unique key for the setting. * initialValue, // The initial value of the setting. * precedenceList: [ * { * id, // The id of the extension requesting the setting. - * installDate, // The install date of the extension. + * installDate, // The install date of the extension, stored as a number. * value, // The value of the setting requested by the extension. * enabled // Whether the setting is currently enabled. * } * ], * }, * key: { * // ... * } @@ -48,25 +48,52 @@ Cu.import("resource://gre/modules/Servic Cu.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "AddonManager", "resource://gre/modules/AddonManager.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "JSONFile", "resource://gre/modules/JSONFile.jsm"); const JSON_FILE_NAME = "extension-settings.json"; +const JSON_FILE_VERSION = 2; const STORE_PATH = OS.Path.join(Services.dirsvc.get("ProfD", Ci.nsIFile).path, JSON_FILE_NAME); let _store; +// Test-only method to force reloading of the JSON file, by removing the +// cached file from memory. +function clearFileFromCache() { + let finalizePromise = _store.finalize(); + _store = null; + return finalizePromise; +} + +// Processes the JSON data when read from disk to convert string dates into numbers. +function dataPostProcessor(json) { + if (json.version !== JSON_FILE_VERSION) { + for (let storeType in json) { + for (let setting in json[storeType]) { + for (let extData of json[storeType][setting].precedenceList) { + if (typeof extData.installDate != "number") { + extData.installDate = new Date(extData.installDate).valueOf(); + } + } + } + } + json.version = JSON_FILE_VERSION; + } + return json; +} + // Get the internal settings store, which is persisted in a JSON file. function getStore(type) { if (!_store) { let initStore = new JSONFile({ path: STORE_PATH, + dataPostProcessor, }); initStore.ensureDataReady(); _store = initStore; } // Ensure a property exists for the given type. if (!_store.data[type]) { _store.data[type] = {}; @@ -227,17 +254,18 @@ this.ExtensionSettingsStore = { }; } let keyInfo = store.data[type][key]; // Check for this item in the precedenceList. let foundIndex = keyInfo.precedenceList.findIndex(item => item.id == id); if (foundIndex === -1) { // No item for this extension, so add a new one. let addon = await AddonManager.getAddonByID(id); - keyInfo.precedenceList.push({id, installDate: addon.installDate, value, enabled: true}); + keyInfo.precedenceList.push( + {id, installDate: addon.installDate.valueOf(), value, enabled: true}); } else { // Item already exists or this extension, so update it. keyInfo.precedenceList[foundIndex].value = value; } // Sort the list. keyInfo.precedenceList.sort(precedenceComparator); @@ -396,13 +424,26 @@ this.ExtensionSettingsStore = { } let topItem = enabledItems[0]; if (topItem.id == id) { return "controlled_by_this_extension"; } let addon = await AddonManager.getAddonByID(id); - return topItem.installDate > addon.installDate ? + return topItem.installDate > addon.installDate.valueOf() ? "controlled_by_other_extensions" : "controllable_by_this_extension"; }, + + /** + * Test-only method to force reloading of the JSON file. + * + * Note that this method simply clears the local variable that stores the + * file, so the next time the file is accessed it will be reloaded. + * + * @returns {Promise} + * A promise that resolves once the settings store has been cleared. + */ + _reloadFile() { + return clearFileFromCache(); + }, };
--- a/toolkit/components/extensions/test/xpcshell/test_ext_extensionSettingsStore.js +++ b/toolkit/components/extensions/test/xpcshell/test_ext_extensionSettingsStore.js @@ -118,16 +118,19 @@ add_task(async function test_settings_st "getSetting returns correct item with more than one item in the list."); let levelOfControl = await ExtensionSettingsStore.getLevelOfControl(extensions[extensionIndex], TEST_TYPE, key); equal( levelOfControl, "controlled_by_other_extensions", "getLevelOfControl returns correct levelOfControl when another extension is in control."); } + // Reload the settings store to emulate a browser restart. + await ExtensionSettingsStore._reloadFile(); + // Add a setting for the newest extension. for (let key of KEY_LIST) { let extensionIndex = 2; let itemToAdd = ITEMS[key][extensionIndex]; let levelOfControl = await ExtensionSettingsStore.getLevelOfControl(extensions[extensionIndex], TEST_TYPE, key); equal( levelOfControl, "controllable_by_this_extension",