Bug 1596258 - Add browser.experiments.urlbar.checkForBrowserUpdate and getBrowserUpdateStatus. r=mak,mixedpuppy

Differential Revision: https://phabricator.services.mozilla.com/D54397

--HG--
rename : browser/components/extensions/test/browser/.eslintrc.js => browser/components/urlbar/tests/ext/browser/.eslintrc.js
rename : browser/components/extensions/test/browser/.eslintrc.js => browser/components/urlbar/tests/ext/browser/update/.eslintrc.js
extra : moz-landing-system : lando
This commit is contained in:
Drew Willcoxon 2019-12-03 22:10:20 +00:00
Родитель d514f1eca9
Коммит f1e3a8f030
20 изменённых файлов: 633 добавлений и 151 удалений

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

@ -30,6 +30,7 @@ TESTING_JS_MODULES += [
BROWSER_CHROME_MANIFESTS += [
'tests/browser/browser.ini',
'tests/ext/browser/browser.ini',
'tests/ext/browser/update/browser.ini',
]
XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']

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

@ -35,7 +35,7 @@ var UrlbarTestUtils = {
* @param {function} options.waitForFocus The SimpleTest function
* @param {boolean} [options.fireInputEvent] whether an input event should be
* used when starting the query (simulates the user's typing, sets
* userTypedValued, etc.)
* userTypedValued, triggers engagement event telemetry, etc.)
* @param {number} [options.selectionStart] The input's selectionStart
* @param {number} [options.selectionEnd] The input's selectionEnd
*/

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

@ -1,3 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* global ExtensionAPI */
"use strict";
@ -8,6 +12,7 @@ const { XPCOMUtils } = ChromeUtils.import(
XPCOMUtils.defineLazyModuleGetters(this, {
AppMenuNotifications: "resource://gre/modules/AppMenuNotifications.jsm",
AppUpdater: "resource:///modules/AppUpdater.jsm",
BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
Preferences: "resource://gre/modules/Preferences.jsm",
ProfileAge: "resource://gre/modules/ProfileAge.jsm",
@ -30,26 +35,50 @@ XPCOMUtils.defineLazyServiceGetter(
"nsIUpdateManager"
);
XPCOMUtils.defineLazyGetter(this, "appUpdater", () => new AppUpdater());
XPCOMUtils.defineLazyGetter(this, "appUpdaterStatusToStringMap", () => {
// The AppUpdater.STATUS values have uppercase, underscored names like
// READY_FOR_RESTART. The statuses we return from this API are camel-cased
// versions of those names, like "readyForRestart". Here we convert those
// AppUpdater.STATUS names to camel-cased names and store them in a map.
let map = new Map();
for (let name in AppUpdater.STATUS) {
let parts = name.split("_").map(p => p.toLowerCase());
let string =
parts[0] +
parts
.slice(1)
.map(p => p[0].toUpperCase() + p.substring(1))
.join("");
map.set(AppUpdater.STATUS[name], string);
}
return map;
});
XPCOMUtils.defineLazyGetter(
this,
"defaultPreferences",
() => new Preferences({ defaultBranch: true })
);
function updateStateIs(prefix) {
let update = updateManager.activeUpdate;
return !!(update && update.state.startsWith(prefix));
}
this.experiments_urlbar = class extends ExtensionAPI {
getAPI() {
return {
experiments: {
urlbar: {
checkForBrowserUpdate() {
appUpdater.check();
},
engagementTelemetry: this._getDefaultSettingsAPI(
"browser.urlbar.eventTelemetry.enabled"
),
getBrowserUpdateStatus() {
return appUpdaterStatusToStringMap.get(appUpdater.status);
},
isBrowserShowingNotification() {
let window = BrowserWindowTracker.getTopWindow();
@ -106,23 +135,6 @@ this.experiments_urlbar = class extends ExtensionAPI {
return false;
},
isBrowserUpdateReadyToInstall() {
if (
!updateService.canStageUpdates ||
!Services.policies.isAllowed("appUpdate")
) {
return updateStateIs("pending");
}
if (updateStateIs("applied")) {
return true;
}
// If the state is pending and there is an error, staging failed and
// Firefox can be restarted to apply the update without staging.
let update = updateManager.activeUpdate;
let errorCode = update ? update.errorCode : 0;
return updateStateIs("pending") && errorCode != 0;
},
async lastBrowserUpdateDate() {
// Get the newest update in the update history. This isn't perfect
// because these dates are when updates are applied, not when the

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

@ -0,0 +1,7 @@
"use strict";
module.exports = {
"env": {
"webextensions": true,
},
};

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

@ -11,7 +11,6 @@ support-files =
[browser_ext_urlbar_engagementTelemetry.js]
[browser_ext_urlbar_isBrowserShowingNotification.js]
[browser_ext_urlbar_isBrowserUpdateReadyToInstall.js]
[browser_ext_urlbar_lastBrowserUpdateDate.js]
[browser_ext_urlbar_openClearHistoryDialog.js]
[browser_ext_urlbar_openViewOnFocus.js]

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

@ -1,120 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/* global browser */
// This tests the browser.experiments.urlbar.isBrowserUpdateReadyToInstall
// WebExtension Experiment API.
"use strict";
const mockUpdateManager = {
contractId: "@mozilla.org/updates/update-manager;1",
_mockClassId: Cc["@mozilla.org/uuid-generator;1"]
.getService(Ci.nsIUUIDGenerator)
.generateUUID(),
_originalClassId: "",
QueryInterface: ChromeUtils.generateQI([Ci.nsIUpdateManager]),
createInstance(outer, iiD) {
if (outer) {
throw Cr.NS_ERROR_NO_AGGREGATION;
}
return this.QueryInterface(iiD);
},
register() {
let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
if (!registrar.isCIDRegistered(this._mockClassId)) {
this._originalClassId = registrar.contractIDToCID(this.contractId);
registrar.registerFactory(
this._mockClassId,
"Unregister after testing",
this.contractId,
this
);
}
},
unregister() {
let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
registrar.unregisterFactory(this._mockClassId, this);
registrar.registerFactory(this._originalClassId, "", this.contractId, null);
},
setUpdateState(state, errorCode = 0) {
this._state = state;
this._errorCode = errorCode;
},
get activeUpdate() {
return {
type: "major",
name: "Firefox Developer Edition 49.0a2",
state: this._state,
errorCode: this._errorCode,
};
},
};
add_task(async function noUpdate() {
info("should return false when there are no updates");
await checkExtension(false);
});
add_task(async function hasUpdate() {
mockUpdateManager.register();
registerCleanupFunction(() => {
mockUpdateManager.unregister();
});
await SpecialPowers.pushPrefEnv({
set: [["app.update.staging.enabled", true]],
});
info("Should return false when an update is not ready");
for (let state of [
"downloading",
"applying",
"succeeded",
"download-failed",
"failed",
]) {
mockUpdateManager.setUpdateState(state);
await checkExtension(false);
}
info("Should return false when an update is pending with no error");
mockUpdateManager.setUpdateState("pending");
await checkExtension(false);
info("Should return true when an update is pending with error");
mockUpdateManager.setUpdateState("pending", 1);
await checkExtension(true);
info("Should return true when an update was applied");
for (let state of ["applied", "applied-service"]) {
mockUpdateManager.setUpdateState(state);
await checkExtension(true);
}
await SpecialPowers.pushPrefEnv({
set: [["app.update.staging.enabled", false]],
});
info("Should return true when an update is pending and staging is disabled");
mockUpdateManager.setUpdateState("pending");
await checkExtension(true);
});
async function checkExtension(expectedReady) {
let ext = await loadExtension(async () => {
let ready = await browser.experiments.urlbar.isBrowserUpdateReadyToInstall();
browser.test.sendMessage("ready", ready);
});
let ready = await ext.awaitMessage("ready");
Assert.equal(ready, expectedReady);
await ext.unload();
}

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

@ -43,6 +43,16 @@ add_task(async function loadSource() {
scriptSource = await (await fetch("file://" + SCRIPT_PATH)).text();
});
/**
* Loads a mock extension with our browser.experiments.urlbar API and a
* background script. Be sure to call `await ext.unload()` when you're done
* with it.
*
* @param {function} background
* This function is serialized and becomes the background script.
* @returns {object}
* The extension.
*/
async function loadExtension(background) {
let ext = ExtensionTestUtils.loadExtension({
manifest: {

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

@ -0,0 +1,7 @@
"use strict";
module.exports = {
"env": {
"webextensions": true,
},
};

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

@ -0,0 +1,23 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
[DEFAULT]
support-files =
head.js
../../api.js
../../schema.json
[browser_getBrowserUpdateStatus_downloadAndInstall.js]
[browser_getBrowserUpdateStatus_downloadFailed.js]
[browser_getBrowserUpdateStatus_manualUpdate.js]
skip-if = os != 'win'
reason = test must be able to prevent file deletion.
[browser_getBrowserUpdateStatus_neverChecked.js]
[browser_getBrowserUpdateStatus_noUpdatesFound.js]
[browser_getBrowserUpdateStatus_otherInstanceHandlingUpdates.js]
skip-if = os != 'win'
reason = Windows only feature.
[browser_getBrowserUpdateStatus_readyForRestart.js]
[browser_getBrowserUpdateStatus_unsupportedSystem.js]
[browser_getBrowserUpdateStatus_updateDisabledByPolicy.js]

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

@ -0,0 +1,38 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Adapted from:
// https://searchfox.org/mozilla-central/source/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_downloadOptIn.js
"use strict";
let params = { queryString: "&invalidCompleteSize=1" };
let downloadInfo = [];
if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED, false)) {
downloadInfo[0] = { patchType: "partial", bitsResult: "0" };
} else {
downloadInfo[0] = { patchType: "partial", internalResult: "0" };
}
let steps = [
{
panelId: "checkingForUpdates",
checkActiveUpdate: null,
continueFile: CONTINUE_CHECK,
},
{
panelId: "downloadAndInstall",
checkActiveUpdate: null,
continueFile: null,
},
];
add_getBrowserUpdateStatus_task(
params,
steps,
"downloadAndInstall",
async () => {
await UpdateUtils.setAppUpdateAutoEnabled(false);
}
);

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

@ -0,0 +1,37 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Adapted from:
// https://searchfox.org/mozilla-central/source/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_patch_partialBadSize.js
"use strict";
let downloadInfo = [];
if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED, false)) {
downloadInfo[0] = { patchType: "partial", bitsResult: gBadSizeResult };
downloadInfo[1] = { patchType: "partial", internalResult: gBadSizeResult };
} else {
downloadInfo[0] = { patchType: "partial", internalResult: gBadSizeResult };
}
let params = { queryString: "&partialPatchOnly=1&invalidPartialSize=1" };
let steps = [
{
panelId: "checkingForUpdates",
checkActiveUpdate: null,
continueFile: CONTINUE_CHECK,
},
{
panelId: "downloading",
checkActiveUpdate: { state: STATE_DOWNLOADING },
continueFile: CONTINUE_DOWNLOAD,
downloadInfo,
},
{
panelId: "downloadFailed",
checkActiveUpdate: null,
continueFile: null,
},
];
add_getBrowserUpdateStatus_task(params, steps, "downloadFailed");

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

@ -0,0 +1,25 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Adapted from:
// https://searchfox.org/mozilla-central/source/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_cantApply.js
"use strict";
let params = {};
let steps = [
{
panelId: "checkingForUpdates",
checkActiveUpdate: null,
continueFile: CONTINUE_CHECK,
},
{
panelId: "manualUpdate",
checkActiveUpdate: null,
continueFile: null,
},
];
add_getBrowserUpdateStatus_task(params, steps, "manualUpdate", () => {
lockWriteTestFile();
});

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

@ -0,0 +1,14 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
add_task(async function test() {
let ext = await loadExtension(async () => {
let status = await browser.experiments.urlbar.getBrowserUpdateStatus();
browser.test.sendMessage("done", status);
});
let status = await ext.awaitMessage("done");
Assert.equal(status, "neverChecked");
await ext.unload();
});

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

@ -0,0 +1,23 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Adapted from:
// https://searchfox.org/mozilla-central/source/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_noUpdate.js
"use strict";
let params = { queryString: "&noUpdates=1" };
let steps = [
{
panelId: "checkingForUpdates",
checkActiveUpdate: null,
continueFile: CONTINUE_CHECK,
},
{
panelId: "noUpdatesFound",
checkActiveUpdate: null,
continueFile: null,
},
];
add_getBrowserUpdateStatus_task(params, steps, "noUpdatesFound");

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

@ -0,0 +1,25 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Adapted from:
// https://searchfox.org/mozilla-central/source/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_otherInstance.js
"use strict";
let params = {};
let steps = [
{
panelId: "otherInstanceHandlingUpdates",
checkActiveUpdate: null,
continueFile: null,
},
];
add_getBrowserUpdateStatus_task(
params,
steps,
"otherInstanceHandlingUpdates",
() => {
setOtherInstanceHandlingUpdates();
}
);

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

@ -0,0 +1,27 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Adapted from:
// https://searchfox.org/mozilla-central/source/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloaded_staged.js
"use strict";
let params = {
queryString: "&invalidCompleteSize=1",
backgroundUpdate: true,
continueFile: CONTINUE_STAGING,
waitForUpdateState: STATE_APPLIED,
};
let steps = [
{
panelId: "apply",
checkActiveUpdate: { state: STATE_APPLIED },
continueFile: null,
},
];
add_getBrowserUpdateStatus_task(params, steps, "readyForRestart", async () => {
await SpecialPowers.pushPrefEnv({
set: [[PREF_APP_UPDATE_STAGING_ENABLED, true]],
});
});

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

@ -0,0 +1,23 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Adapted from:
// https://searchfox.org/mozilla-central/source/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_cantApply.js
"use strict";
let params = { queryString: "&unsupported=1" };
let steps = [
{
panelId: "checkingForUpdates",
checkActiveUpdate: null,
continueFile: CONTINUE_CHECK,
},
{
panelId: "unsupportedSystem",
checkActiveUpdate: null,
continueFile: null,
},
];
add_getBrowserUpdateStatus_task(params, steps, "unsupportedSystem");

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

@ -0,0 +1,39 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
let params = {};
let steps = [];
add_getBrowserUpdateStatus_task(
params,
steps,
"updateDisabledByPolicy",
async () => {
if (!Services.policies) {
return true;
}
const { EnterprisePolicyTesting, PoliciesPrefTracker } = ChromeUtils.import(
"resource://testing-common/EnterprisePolicyTesting.jsm",
null
);
PoliciesPrefTracker.start();
await EnterprisePolicyTesting.setupPolicyEngineWithJson({
policies: {
DisableAppUpdate: true,
},
});
registerCleanupFunction(async () => {
if (Services.policies.status != Ci.nsIEnterprisePolicies.INACTIVE) {
await EnterprisePolicyTesting.setupPolicyEngineWithJson("");
}
EnterprisePolicyTesting.resetRunOnceState();
PoliciesPrefTracker.stop();
});
return false;
}
);

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

@ -0,0 +1,277 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// This directory contains tests that check the update-related functions of
// browser.experiments.urlbar. We mock updates by using the test helpers in
// toolkit/mozapps/update/tests/browser.
"use strict";
/* import-globals-from ../../../../../../../toolkit/mozapps/update/tests/browser/head.js */
Services.scriptloader.loadSubScript(
"chrome://mochitests/content/browser/toolkit/mozapps/update/tests/browser/head.js",
this
);
const SCHEMA_BASENAME = "schema.json";
const SCRIPT_BASENAME = "api.js";
const SCHEMA_PATH = getTestFilePath(SCHEMA_BASENAME);
const SCRIPT_PATH = getTestFilePath(SCRIPT_BASENAME);
let schemaSource;
let scriptSource;
add_task(async function loadSource() {
schemaSource = await (await fetch("file://" + SCHEMA_PATH)).text();
scriptSource = await (await fetch("file://" + SCRIPT_PATH)).text();
});
/**
* Loads a mock extension with our browser.experiments.urlbar API and a
* background script. Be sure to call `await ext.unload()` when you're done
* with it.
*
* @param {function} background
* This function is serialized and becomes the background script.
* @returns {object}
* The extension.
*/
async function loadExtension(background) {
let ext = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["urlbar"],
experiment_apis: {
experiments_urlbar: {
schema: SCHEMA_BASENAME,
parent: {
scopes: ["addon_parent"],
paths: [["experiments", "urlbar"]],
script: SCRIPT_BASENAME,
},
},
},
},
files: {
[SCHEMA_BASENAME]: schemaSource,
[SCRIPT_BASENAME]: scriptSource,
},
isPrivileged: true,
background,
});
await ext.startup();
return ext;
}
/**
* The getBrowserUpdateStatus tests are all similar. Use this to add a test
* task that sets up a mock browser update and loads an extension that checks
* for updates and gets the update status.
*
* @param {object} params
* See the files in toolkit/mozapps/update/tests/browser.
* @param {array} steps
* See the files in toolkit/mozapps/update/tests/browser.
* @param {string} expectedUpdateStatus
* One of the BrowserUpdateStatus enums.
* @param {function} [setUp]
* An optional setup functon that will be called first.
*/
function add_getBrowserUpdateStatus_task(
params,
steps,
expectedUpdateStatus,
setUp
) {
add_task(async function() {
if (setUp) {
let skip = await setUp();
if (skip) {
Assert.ok(true, "Skipping test");
return;
}
}
await initUpdate(params);
let ext = await loadExtension(async () => {
browser.test.onMessage.addListener(async command => {
switch (command) {
case "check":
await browser.experiments.urlbar.checkForBrowserUpdate();
browser.test.sendMessage("done");
break;
case "get": {
let done = false;
let interval = setInterval(async () => {
let status = await browser.experiments.urlbar.getBrowserUpdateStatus();
if (status != "checking" && !done) {
done = true;
clearInterval(interval);
browser.test.sendMessage("done", status);
}
}, 100);
break;
}
}
});
});
ext.sendMessage("check");
await ext.awaitMessage("done");
await processUpdateSteps(steps);
ext.sendMessage("get");
let status = await ext.awaitMessage("done");
Assert.equal(status, expectedUpdateStatus);
await ext.unload();
});
}
/**
* Initializes a mock app update. Adapted from runAboutDialogUpdateTest:
* https://searchfox.org/mozilla-central/source/toolkit/mozapps/update/tests/browser/head.js
*
* @param {object} params
* See the files in toolkit/mozapps/update/tests/browser.
*/
async function initUpdate(params) {
gEnv.set("MOZ_TEST_SLOW_SKIP_UPDATE_STAGE", "1");
await SpecialPowers.pushPrefEnv({
set: [
[PREF_APP_UPDATE_DISABLEDFORTESTING, false],
[PREF_APP_UPDATE_URL_MANUAL, gDetailsURL],
],
});
await setupTestUpdater();
let queryString = params.queryString ? params.queryString : "";
let updateURL =
URL_HTTP_UPDATE_SJS +
"?detailsURL=" +
gDetailsURL +
queryString +
getVersionParams();
if (params.backgroundUpdate) {
setUpdateURL(updateURL);
gAUS.checkForBackgroundUpdates();
if (params.continueFile) {
await continueFileHandler(params.continueFile);
}
if (params.waitForUpdateState) {
await TestUtils.waitForCondition(
() =>
gUpdateManager.activeUpdate &&
gUpdateManager.activeUpdate.state == params.waitForUpdateState,
"Waiting for update state: " + params.waitForUpdateState,
undefined,
200
).catch(e => {
// Instead of throwing let the check below fail the test so the panel
// ID and the expected panel ID is printed in the log.
logTestInfo(e);
});
// Display the UI after the update state equals the expected value.
Assert.equal(
gUpdateManager.activeUpdate.state,
params.waitForUpdateState,
"The update state value should equal " + params.waitForUpdateState
);
}
} else {
updateURL += "&slowUpdateCheck=1&useSlowDownloadMar=1";
setUpdateURL(updateURL);
}
}
/**
* Performs steps in a mock update. Adapted from runAboutDialogUpdateTest:
* https://searchfox.org/mozilla-central/source/toolkit/mozapps/update/tests/browser/head.js
*
* @param {array} steps
* See the files in toolkit/mozapps/update/tests/browser.
*/
async function processUpdateSteps(steps) {
for (let step of steps) {
await processUpdateStep(step);
}
}
/**
* Performs a step in a mock update. Adapted from runAboutDialogUpdateTest:
* https://searchfox.org/mozilla-central/source/toolkit/mozapps/update/tests/browser/head.js
*
* @param {object} step
* See the files in toolkit/mozapps/update/tests/browser.
*/
async function processUpdateStep(step) {
if (typeof step == "function") {
step();
return;
}
const { panelId, checkActiveUpdate, continueFile, downloadInfo } = step;
if (checkActiveUpdate) {
await TestUtils.waitForCondition(
() => gUpdateManager.activeUpdate,
"Waiting for active update"
);
Assert.ok(
!!gUpdateManager.activeUpdate,
"There should be an active update"
);
Assert.equal(
gUpdateManager.activeUpdate.state,
checkActiveUpdate.state,
"The active update state should equal " + checkActiveUpdate.state
);
} else {
Assert.ok(
!gUpdateManager.activeUpdate,
"There should not be an active update"
);
}
if (panelId == "downloading") {
for (let i = 0; i < downloadInfo.length; ++i) {
let data = downloadInfo[i];
// The About Dialog tests always specify a continue file.
await continueFileHandler(continueFile);
let patch = getPatchOfType(data.patchType);
// The update is removed early when the last download fails so check
// that there is a patch before proceeding.
let isLastPatch = i == downloadInfo.length - 1;
if (!isLastPatch || patch) {
let resultName = data.bitsResult ? "bitsResult" : "internalResult";
patch.QueryInterface(Ci.nsIWritablePropertyBag);
await TestUtils.waitForCondition(
() => patch.getProperty(resultName) == data[resultName],
"Waiting for expected patch property " +
resultName +
" value: " +
data[resultName],
undefined,
200
).catch(e => {
// Instead of throwing let the check below fail the test so the
// property value and the expected property value is printed in
// the log.
logTestInfo(e);
});
Assert.equal(
patch.getProperty(resultName),
data[resultName],
"The patch property " +
resultName +
" value should equal " +
data[resultName]
);
}
}
} else if (continueFile) {
await continueFileHandler(continueFile);
}
}

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

@ -2,6 +2,14 @@
{
"namespace": "experiments.urlbar",
"description": "APIs supporting urlbar experiments",
"types": [
{
"id": "BrowserUpdateStatus",
"type": "string",
"enum": ["checking", "downloadAndInstall", "downloadFailed", "downloading", "manualUpdate", "neverChecked", "noUpdater", "noUpdatesFound", "otherInstanceHandlingUpdates", "readyForRestart", "staging", "unsupportedSystem", "updateDisabledByPolicy"],
"description": "The browser's current update state. Each value corresponds to an AppUpdater.STATUS value."
}
],
"properties": {
"engagementTelemetry": {
"$ref": "types.Setting",
@ -13,6 +21,20 @@
}
},
"functions": [
{
"name": "checkForBrowserUpdate",
"type": "function",
"async": true,
"description": "Checks for an update to the app. If an update is available and the user's preferences allow, the update will automatically be downloaded and installed. This function will not restart the browser, however.",
"parameters": []
},
{
"name": "getBrowserUpdateStatus",
"type": "function",
"async": true,
"description": "Returns the browser's current update status. The return value is one of the <code>BrowserUpdateStatus</code> enums.",
"parameters": []
},
{
"name": "isBrowserShowingNotification",
"type": "function",
@ -20,13 +42,6 @@
"description": "Returns true if the browser is showing any kind of notification.",
"parameters": []
},
{
"name": "isBrowserUpdateReadyToInstall",
"type": "function",
"async": true,
"description": "Returns true if there is an update ready to install.",
"parameters": []
},
{
"name": "lastBrowserUpdateDate",
"type": "function",