summaryrefslogtreecommitdiffstats
path: root/toolkit/mozapps/update/tests/browser
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/mozapps/update/tests/browser')
-rw-r--r--toolkit/mozapps/update/tests/browser/browser.bits.ini79
-rw-r--r--toolkit/mozapps/update/tests/browser/browser.ini100
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloaded.js17
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloaded_staged.js28
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloaded_staging.js56
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloaded_stagingFailure.js31
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloading.js77
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloading_notify.js67
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloading_staging.js69
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_multiUpdate.js52
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_cantApply.js24
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_malformedXML.js22
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_noUpdate.js22
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_otherInstance.js19
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_unsupported.js22
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_downloadAuto.js62
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_downloadAuto_staging.js46
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_downloadOptIn.js44
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_downloadOptIn_staging.js52
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_patch_completeBadSize.js36
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_patch_partialBadSize.js36
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_patch_partialBadSize_complete.js38
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_patch_partialBadSize_completeBadSize.js53
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloaded.js17
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloaded_staged.js28
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloaded_staging.js59
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloaded_stagingFailure.js29
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloading.js63
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloading_staging.js72
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_multiUpdate.js52
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_check_cantApply.js24
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_check_malformedXML.js22
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_check_noUpdate.js22
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_check_otherInstance.js19
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_check_unsupported.js22
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_downloadAuto.js37
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_downloadAuto_staging.js46
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_downloadOptIn.js44
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_downloadOptIn_staging.js52
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_patch_completeBadSize.js36
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_patch_partialBadSize.js36
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_patch_partialBadSize_complete.js38
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_patch_partialBadSize_completeBadSize.js53
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_aboutPrefs_settings.js137
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_check_cantApply.js18
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_check_malformedXML.js26
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_check_unsupported.js94
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloadAutoFailures.js37
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloadAutoFailures_bgWin.js85
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloadOptIn.js26
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloadOptIn_bgWin.js68
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloadOptIn_staging.js30
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloaded.js18
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloaded_disableBITS.js31
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloaded_staged.js22
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_multiUpdate.js93
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_multiUpdate_promptWaitTime.js89
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_patch_completeBadSize.js35
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_patch_partialBadSize.js35
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_patch_partialBadSize_complete.js18
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_patch_partialBadSize_completeBadSize.js35
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_sp_patch_completeApplyFailure.js23
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_sp_patch_partialApplyFailure.js22
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_sp_patch_partialApplyFailure_complete.js22
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_sp_patch_partialApplyFailure_completeBadSize.js32
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_doorhanger_sp_patch_partialApplyFailure_complete_staging.js28
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_elevationDialog.js139
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_telemetry_updatePing_downloaded_ready.js69
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_telemetry_updatePing_staged_ready.js73
-rw-r--r--toolkit/mozapps/update/tests/browser/downloadPage.html13
-rw-r--r--toolkit/mozapps/update/tests/browser/head.js1189
-rw-r--r--toolkit/mozapps/update/tests/browser/testConstants.js7
72 files changed, 4337 insertions, 0 deletions
diff --git a/toolkit/mozapps/update/tests/browser/browser.bits.ini b/toolkit/mozapps/update/tests/browser/browser.bits.ini
new file mode 100644
index 0000000000..d3cb7182c3
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser.bits.ini
@@ -0,0 +1,79 @@
+[DEFAULT]
+skip-if = os != 'win'
+reason = BITS is only available on Windows.
+dupe-manifest =
+tags = appupdate bits
+head = head.js
+support-files =
+ ../data/shared.js
+ ../data/sharedUpdateXML.js
+ ../data/app_update.sjs
+ downloadPage.html
+ testConstants.js
+
+prefs =
+ app.update.BITS.enabled=true
+ app.update.langpack.enabled=true
+
+# BITS Download Tests
+#####################
+
+# About Dialog Application Update Tests
+[browser_aboutDialog_bc_downloading.js]
+[browser_aboutDialog_bc_downloading_staging.js]
+[browser_aboutDialog_bc_downloading_notify.js]
+[browser_aboutDialog_bc_downloaded.js]
+[browser_aboutDialog_bc_downloaded_staging.js]
+[browser_aboutDialog_bc_downloaded_staged.js]
+[browser_aboutDialog_bc_downloaded_stagingFailure.js]
+[browser_aboutDialog_fc_downloadAuto.js]
+[browser_aboutDialog_fc_downloadAuto_staging.js]
+[browser_aboutDialog_fc_downloadOptIn.js]
+[browser_aboutDialog_fc_downloadOptIn_staging.js]
+[browser_aboutDialog_fc_patch_completeBadSize.js]
+[browser_aboutDialog_fc_patch_partialBadSize.js]
+[browser_aboutDialog_fc_patch_partialBadSize_complete.js]
+[browser_aboutDialog_fc_patch_partialBadSize_completeBadSize.js]
+[browser_aboutDialog_bc_multiUpdate.js]
+
+# about:preferences Application Update Tests
+[browser_aboutPrefs_bc_downloading.js]
+[browser_aboutPrefs_bc_downloading_staging.js]
+[browser_aboutPrefs_bc_downloaded.js]
+[browser_aboutPrefs_bc_downloaded_staging.js]
+[browser_aboutPrefs_bc_downloaded_stagingFailure.js]
+[browser_aboutPrefs_bc_downloaded_staged.js]
+[browser_aboutPrefs_fc_downloadAuto.js]
+[browser_aboutPrefs_fc_downloadAuto_staging.js]
+[browser_aboutPrefs_fc_downloadOptIn.js]
+[browser_aboutPrefs_fc_downloadOptIn_staging.js]
+[browser_aboutPrefs_fc_patch_completeBadSize.js]
+[browser_aboutPrefs_fc_patch_partialBadSize.js]
+[browser_aboutPrefs_fc_patch_partialBadSize_complete.js]
+[browser_aboutPrefs_fc_patch_partialBadSize_completeBadSize.js]
+[browser_aboutPrefs_bc_multiUpdate.js]
+
+# Doorhanger Application Update Tests
+[browser_doorhanger_bc_downloaded.js]
+[browser_doorhanger_bc_downloaded_staged.js]
+[browser_doorhanger_bc_downloadAutoFailures.js]
+[browser_doorhanger_bc_downloadAutoFailures_bgWin.js]
+[browser_doorhanger_bc_downloadOptIn.js]
+[browser_doorhanger_bc_downloadOptIn_bgWin.js]
+[browser_doorhanger_bc_downloadOptIn_staging.js]
+[browser_doorhanger_bc_patch_completeBadSize.js]
+[browser_doorhanger_bc_patch_partialBadSize.js]
+[browser_doorhanger_bc_patch_partialBadSize_complete.js]
+[browser_doorhanger_bc_patch_partialBadSize_completeBadSize.js]
+[browser_doorhanger_sp_patch_completeApplyFailure.js]
+[browser_doorhanger_sp_patch_partialApplyFailure.js]
+[browser_doorhanger_sp_patch_partialApplyFailure_complete.js]
+[browser_doorhanger_sp_patch_partialApplyFailure_complete_staging.js]
+[browser_doorhanger_sp_patch_partialApplyFailure_completeBadSize.js]
+[browser_doorhanger_bc_downloaded_disableBITS.js]
+[browser_doorhanger_bc_multiUpdate.js]
+[browser_doorhanger_bc_multiUpdate_promptWaitTime.js]
+
+# Telemetry Update Ping Tests
+[browser_telemetry_updatePing_downloaded_ready.js]
+[browser_telemetry_updatePing_staged_ready.js]
diff --git a/toolkit/mozapps/update/tests/browser/browser.ini b/toolkit/mozapps/update/tests/browser/browser.ini
new file mode 100644
index 0000000000..eb62df68c3
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser.ini
@@ -0,0 +1,100 @@
+[DEFAULT]
+dupe-manifest =
+tags = appupdate internal
+head = head.js
+support-files =
+ ../data/shared.js
+ ../data/sharedUpdateXML.js
+ ../data/app_update.sjs
+ downloadPage.html
+ testConstants.js
+prefs =
+ app.update.BITS.enabled=false
+ app.update.langpack.enabled=true
+
+# About Dialog Application Update Tests
+[browser_aboutDialog_bc_downloading.js]
+[browser_aboutDialog_bc_downloading_staging.js]
+[browser_aboutDialog_bc_downloading_notify.js]
+[browser_aboutDialog_bc_downloaded.js]
+[browser_aboutDialog_bc_downloaded_staging.js]
+[browser_aboutDialog_bc_downloaded_stagingFailure.js]
+[browser_aboutDialog_bc_downloaded_staged.js]
+[browser_aboutDialog_fc_downloadAuto.js]
+skip-if = tsan # Bug 1683730
+[browser_aboutDialog_fc_downloadAuto_staging.js]
+[browser_aboutDialog_fc_downloadOptIn.js]
+[browser_aboutDialog_fc_downloadOptIn_staging.js]
+[browser_aboutDialog_fc_patch_completeBadSize.js]
+[browser_aboutDialog_fc_patch_partialBadSize.js]
+[browser_aboutDialog_fc_patch_partialBadSize_complete.js]
+[browser_aboutDialog_fc_patch_partialBadSize_completeBadSize.js]
+[browser_aboutDialog_fc_check_cantApply.js]
+skip-if = os != 'win'
+reason = test must be able to prevent file deletion.
+[browser_aboutDialog_fc_check_malformedXML.js]
+[browser_aboutDialog_fc_check_noUpdate.js]
+[browser_aboutDialog_fc_check_otherInstance.js]
+skip-if = os != 'win'
+reason = Windows only feature.
+[browser_aboutDialog_fc_check_unsupported.js]
+[browser_aboutDialog_bc_multiUpdate.js]
+
+# about:preferences Application Update Tests
+[browser_aboutPrefs_bc_downloading.js]
+[browser_aboutPrefs_bc_downloading_staging.js]
+[browser_aboutPrefs_bc_downloaded.js]
+[browser_aboutPrefs_bc_downloaded_staging.js]
+[browser_aboutPrefs_bc_downloaded_stagingFailure.js]
+[browser_aboutPrefs_bc_downloaded_staged.js]
+[browser_aboutPrefs_fc_downloadAuto.js]
+[browser_aboutPrefs_fc_downloadAuto_staging.js]
+[browser_aboutPrefs_fc_downloadOptIn.js]
+[browser_aboutPrefs_fc_downloadOptIn_staging.js]
+[browser_aboutPrefs_fc_patch_completeBadSize.js]
+[browser_aboutPrefs_fc_patch_partialBadSize.js]
+[browser_aboutPrefs_fc_patch_partialBadSize_complete.js]
+[browser_aboutPrefs_fc_patch_partialBadSize_completeBadSize.js]
+[browser_aboutPrefs_fc_check_cantApply.js]
+skip-if = os != 'win'
+reason = test must be able to prevent file deletion.
+[browser_aboutPrefs_fc_check_malformedXML.js]
+[browser_aboutPrefs_fc_check_noUpdate.js]
+[browser_aboutPrefs_fc_check_otherInstance.js]
+skip-if = os != 'win'
+reason = Windows only feature.
+[browser_aboutPrefs_fc_check_unsupported.js]
+[browser_aboutPrefs_settings.js]
+[browser_aboutPrefs_bc_multiUpdate.js]
+
+# Doorhanger Application Update Tests
+[browser_doorhanger_bc_check_cantApply.js]
+skip-if = os != 'win'
+reason = test must be able to prevent file deletion.
+[browser_doorhanger_bc_check_malformedXML.js]
+[browser_doorhanger_bc_check_unsupported.js]
+[browser_doorhanger_bc_downloaded.js]
+[browser_doorhanger_bc_downloaded_staged.js]
+[browser_doorhanger_bc_downloadAutoFailures.js]
+[browser_doorhanger_bc_downloadAutoFailures_bgWin.js]
+[browser_doorhanger_bc_downloadOptIn.js]
+[browser_doorhanger_bc_downloadOptIn_bgWin.js]
+[browser_doorhanger_bc_downloadOptIn_staging.js]
+[browser_doorhanger_bc_patch_completeBadSize.js]
+[browser_doorhanger_bc_patch_partialBadSize.js]
+[browser_doorhanger_bc_patch_partialBadSize_complete.js]
+[browser_doorhanger_bc_patch_partialBadSize_completeBadSize.js]
+[browser_doorhanger_sp_patch_completeApplyFailure.js]
+[browser_doorhanger_sp_patch_partialApplyFailure.js]
+[browser_doorhanger_sp_patch_partialApplyFailure_complete.js]
+[browser_doorhanger_sp_patch_partialApplyFailure_complete_staging.js]
+[browser_doorhanger_sp_patch_partialApplyFailure_completeBadSize.js]
+[browser_doorhanger_bc_multiUpdate.js]
+[browser_doorhanger_bc_multiUpdate_promptWaitTime.js]
+
+# Elevation Dialog Tests
+[browser_elevationDialog.js]
+
+# Telemetry Update Ping Tests
+[browser_telemetry_updatePing_downloaded_ready.js]
+[browser_telemetry_updatePing_staged_ready.js]
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloaded.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloaded.js
new file mode 100644
index 0000000000..0955750c93
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloaded.js
@@ -0,0 +1,17 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog background check for updates
+// with the update downloaded when the About Dialog is opened.
+add_task(async function aboutDialog_backgroundCheck_downloaded() {
+ let params = { backgroundUpdate: true, waitForUpdateState: STATE_PENDING };
+ await runAboutDialogUpdateTest(params, [
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloaded_staged.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloaded_staged.js
new file mode 100644
index 0000000000..2d7bd64d05
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloaded_staged.js
@@ -0,0 +1,28 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog background check for updates
+// with the update downloaded and staged when the About Dialog is opened.
+add_task(async function aboutDialog_backgroundCheck_downloaded_staged() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_STAGING_ENABLED, true]],
+ });
+
+ // Since the partial should be successful specify an invalid size for the
+ // complete update.
+ let params = {
+ queryString: "&invalidCompleteSize=1",
+ backgroundUpdate: true,
+ continueFile: CONTINUE_STAGING,
+ waitForUpdateState: STATE_APPLIED,
+ };
+ await runAboutDialogUpdateTest(params, [
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_APPLIED },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloaded_staging.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloaded_staging.js
new file mode 100644
index 0000000000..b5dad7157f
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloaded_staging.js
@@ -0,0 +1,56 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog background check for updates
+// with the update downloaded and the About Dialog opened during staging.
+add_task(async function aboutDialog_backgroundCheck_downloaded_staging() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_STAGING_ENABLED, true]],
+ });
+
+ let lankpackCall = mockLangpackInstall();
+
+ // Since the partial should be successful specify an invalid size for the
+ // complete update.
+ let params = {
+ queryString: "&invalidCompleteSize=1",
+ backgroundUpdate: true,
+ waitForUpdateState: STATE_PENDING,
+ };
+ await runAboutDialogUpdateTest(params, [
+ {
+ panelId: "applying",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: CONTINUE_STAGING,
+ },
+ async aboutDialog => {
+ // Once the state is applied but langpacks aren't complete the about
+ // dialog should still be showing applying.
+ TestUtils.waitForCondition(() => {
+ return readStatusFile() == STATE_APPLIED;
+ });
+
+ let updateDeck = aboutDialog.document.getElementById("updateDeck");
+ is(
+ updateDeck.selectedPanel.id,
+ "applying",
+ "UI should still show as applying."
+ );
+
+ let { appVersion, resolve } = await lankpackCall;
+ is(
+ appVersion,
+ Services.appinfo.version,
+ "Should see the right app version."
+ );
+ resolve();
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_APPLIED },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloaded_stagingFailure.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloaded_stagingFailure.js
new file mode 100644
index 0000000000..de78cc7602
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloaded_stagingFailure.js
@@ -0,0 +1,31 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog background check for updates
+// with the update downloaded and staging has failed when the About Dialog is
+// opened.
+add_task(
+ async function aboutDialog_backgroundCheck_downloaded_stagingFailure() {
+ gEnv.set("MOZ_TEST_STAGING_ERROR", "1");
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_STAGING_ENABLED, true]],
+ });
+
+ // Since the partial should be successful specify an invalid size for the
+ // complete update.
+ let params = {
+ queryString: "&completePatchOnly=1",
+ backgroundUpdate: true,
+ waitForUpdateState: STATE_PENDING,
+ };
+ await runAboutDialogUpdateTest(params, [
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: null,
+ },
+ ]);
+ }
+);
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloading.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloading.js
new file mode 100644
index 0000000000..9ecf7a3582
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloading.js
@@ -0,0 +1,77 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog background check for updates
+// with the About Dialog opened during downloading.
+add_task(async function aboutDialog_backgroundCheck_downloading() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_NOTIFYDURINGDOWNLOAD, false]],
+ });
+
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ downloadInfo[0] = { patchType: "partial", bitsResult: "0" };
+ } else {
+ downloadInfo[0] = { patchType: "partial", internalResult: "0" };
+ }
+
+ let lankpackCall = mockLangpackInstall();
+
+ // Since the partial should be successful specify an invalid size for the
+ // complete update.
+ let params = {
+ queryString: "&useSlowDownloadMar=1&invalidCompleteSize=1",
+ backgroundUpdate: true,
+ waitForUpdateState: STATE_DOWNLOADING,
+ };
+ await runAboutDialogUpdateTest(params, [
+ async function aboutDialog_downloading() {
+ is(
+ PanelUI.notificationPanel.state,
+ "closed",
+ "The window's doorhanger is closed."
+ );
+ ok(
+ !PanelUI.menuButton.hasAttribute("badge-status"),
+ "The window does not have a badge."
+ );
+ },
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ async aboutDialog => {
+ // Once the state is pending but langpacks aren't complete the about
+ // dialog should still be showing downloading.
+ TestUtils.waitForCondition(() => {
+ return readStatusFile() == STATE_PENDING;
+ });
+
+ let updateDeck = aboutDialog.document.getElementById("updateDeck");
+ is(
+ updateDeck.selectedPanel.id,
+ "downloading",
+ "UI should still show as downloading."
+ );
+
+ let { appVersion, resolve } = await lankpackCall;
+ is(
+ appVersion,
+ Services.appinfo.version,
+ "Should see the right app version."
+ );
+ resolve();
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: null,
+ },
+ ]);
+
+ await SpecialPowers.popPrefEnv();
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloading_notify.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloading_notify.js
new file mode 100644
index 0000000000..cf067efe7d
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloading_notify.js
@@ -0,0 +1,67 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog background check for updates with the
+// "notify during download" feature turned on.
+add_task(async function aboutDialog_backgroundCheck_downloading_notify() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_NOTIFYDURINGDOWNLOAD, true]],
+ });
+
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ downloadInfo[0] = { patchType: "partial", bitsResult: "0" };
+ } else {
+ downloadInfo[0] = { patchType: "partial", internalResult: "0" };
+ }
+
+ // Since the partial should be successful specify an invalid size for the
+ // complete update.
+ let params = {
+ queryString: "&useSlowDownloadMar=1&invalidCompleteSize=1",
+ backgroundUpdate: true,
+ waitForUpdateState: STATE_DOWNLOADING,
+ };
+ await runAboutDialogUpdateTest(params, [
+ async function aboutDialog_downloading_notification() {
+ await TestUtils.waitForCondition(
+ () => PanelUI.menuButton.hasAttribute("badge-status"),
+ "Waiting for update badge",
+ undefined,
+ 200
+ ).catch(e => {
+ // Instead of throwing let the check below fail the test.
+ logTestInfo(e);
+ });
+ is(
+ PanelUI.notificationPanel.state,
+ "closed",
+ "The window's doorhanger is closed."
+ );
+ ok(
+ PanelUI.menuButton.hasAttribute("badge-status"),
+ "The window has a badge."
+ );
+ is(
+ PanelUI.menuButton.getAttribute("badge-status"),
+ "update-downloading",
+ "The downloading badge is showing for the background window"
+ );
+ },
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: null,
+ },
+ ]);
+
+ await SpecialPowers.popPrefEnv();
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloading_staging.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloading_staging.js
new file mode 100644
index 0000000000..0fa7354bea
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_downloading_staging.js
@@ -0,0 +1,69 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog background check for updates
+// with the About Dialog opened during downloading and stages the update.
+add_task(async function aboutDialog_backgroundCheck_downloading_staging() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_STAGING_ENABLED, true]],
+ });
+
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ downloadInfo[0] = { patchType: "partial", bitsResult: "0" };
+ } else {
+ downloadInfo[0] = { patchType: "partial", internalResult: "0" };
+ }
+
+ let lankpackCall = mockLangpackInstall();
+
+ // Since the partial should be successful specify an invalid size for the
+ // complete update.
+ let params = {
+ queryString: "&useSlowDownloadMar=1&invalidCompleteSize=1",
+ backgroundUpdate: true,
+ waitForUpdateState: STATE_DOWNLOADING,
+ };
+ await runAboutDialogUpdateTest(params, [
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ {
+ panelId: "applying",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: CONTINUE_STAGING,
+ },
+ async aboutDialog => {
+ // Once the state is applied but langpacks aren't complete the about
+ // dialog should still be showing applying.
+ TestUtils.waitForCondition(() => {
+ return readStatusFile() == STATE_APPLIED;
+ });
+
+ let updateDeck = aboutDialog.document.getElementById("updateDeck");
+ is(
+ updateDeck.selectedPanel.id,
+ "applying",
+ "UI should still show as applying."
+ );
+
+ let { appVersion, resolve } = await lankpackCall;
+ is(
+ appVersion,
+ Services.appinfo.version,
+ "Should see the right app version."
+ );
+ resolve();
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_APPLIED },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_multiUpdate.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_multiUpdate.js
new file mode 100644
index 0000000000..b6c893ea15
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_bc_multiUpdate.js
@@ -0,0 +1,52 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const FIRST_UPDATE_VERSION = "999998.0";
+const SECOND_UPDATE_VERSION = "999999.0";
+
+function prepareToDownloadVersion(version) {
+ setUpdateURL(
+ URL_HTTP_UPDATE_SJS +
+ `?detailsURL=${gDetailsURL}&promptWaitTime=0&appVersion=${version}`
+ );
+}
+
+add_task(async function aboutDialog_backgroundCheck_multiUpdate() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_STAGING_ENABLED, true]],
+ });
+
+ let params = {
+ version: FIRST_UPDATE_VERSION,
+ backgroundUpdate: true,
+ waitForUpdateState: STATE_PENDING,
+ };
+ await runAboutDialogUpdateTest(params, [
+ {
+ panelId: "applying",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: CONTINUE_STAGING,
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_APPLIED },
+ continueFile: null,
+ },
+ () => {
+ prepareToDownloadVersion(SECOND_UPDATE_VERSION);
+ gAUS.checkForBackgroundUpdates();
+ },
+ {
+ panelId: "applying",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: CONTINUE_STAGING,
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_APPLIED },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_cantApply.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_cantApply.js
new file mode 100644
index 0000000000..cd659ef74b
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_cantApply.js
@@ -0,0 +1,24 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog foreground check for updates
+// without the ability to apply updates.
+add_task(async function aboutDialog_foregroundCheck_cantApply() {
+ lockWriteTestFile();
+
+ let params = {};
+ await runAboutDialogUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "manualUpdate",
+ checkActiveUpdate: null,
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_malformedXML.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_malformedXML.js
new file mode 100644
index 0000000000..c5ad9df03f
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_malformedXML.js
@@ -0,0 +1,22 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog foreground check for updates
+// with a malformed update XML file.
+add_task(async function aboutDialog_foregroundCheck_malformedXML() {
+ let params = { queryString: "&xmlMalformed=1" };
+ await runAboutDialogUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "noUpdatesFound",
+ checkActiveUpdate: null,
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_noUpdate.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_noUpdate.js
new file mode 100644
index 0000000000..2bd23cddf0
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_noUpdate.js
@@ -0,0 +1,22 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog foreground check for updates
+// with no update available.
+add_task(async function aboutDialog_foregroundCheck_noUpdate() {
+ let params = { queryString: "&noUpdates=1" };
+ await runAboutDialogUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "noUpdatesFound",
+ checkActiveUpdate: null,
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_otherInstance.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_otherInstance.js
new file mode 100644
index 0000000000..fa1110effd
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_otherInstance.js
@@ -0,0 +1,19 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog foreground check for updates
+// with another application instance handling updates.
+add_task(async function aboutDialog_foregroundCheck_otherInstance() {
+ setOtherInstanceHandlingUpdates();
+
+ let params = {};
+ await runAboutDialogUpdateTest(params, [
+ {
+ panelId: "otherInstanceHandlingUpdates",
+ checkActiveUpdate: null,
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_unsupported.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_unsupported.js
new file mode 100644
index 0000000000..22e3425967
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_check_unsupported.js
@@ -0,0 +1,22 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog foreground check for updates
+// with an unsupported update.
+add_task(async function aboutDialog_foregroundCheck_unsupported() {
+ let params = { queryString: "&unsupported=1" };
+ await runAboutDialogUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "unsupportedSystem",
+ checkActiveUpdate: null,
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_downloadAuto.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_downloadAuto.js
new file mode 100644
index 0000000000..a80c9deac8
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_downloadAuto.js
@@ -0,0 +1,62 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog foreground check for updates
+// with an automatic download.
+add_task(async function aboutDialog_foregroundCheck_downloadAuto() {
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ downloadInfo[0] = { patchType: "partial", bitsResult: "0" };
+ } else {
+ downloadInfo[0] = { patchType: "partial", internalResult: "0" };
+ }
+
+ // Since the partial should be successful specify an invalid size for the
+ // complete update.
+ let params = { queryString: "&invalidCompleteSize=1&promptWaitTime=0" };
+ await runAboutDialogUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ async function aboutDialog_restart_notification() {
+ await TestUtils.waitForCondition(
+ () => PanelUI.menuButton.hasAttribute("badge-status"),
+ "Waiting for update badge",
+ undefined,
+ 200
+ ).catch(e => {
+ // Instead of throwing let the check below fail the test.
+ logTestInfo(e);
+ });
+ is(
+ PanelUI.notificationPanel.state,
+ "closed",
+ "The window's doorhanger is closed."
+ );
+ ok(
+ PanelUI.menuButton.hasAttribute("badge-status"),
+ "The window has a badge."
+ );
+ is(
+ PanelUI.menuButton.getAttribute("badge-status"),
+ "update-restart",
+ "The restart badge is showing for the background window"
+ );
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_downloadAuto_staging.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_downloadAuto_staging.js
new file mode 100644
index 0000000000..e212b0c611
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_downloadAuto_staging.js
@@ -0,0 +1,46 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog foreground check for updates
+// with an automatic download and update staging.
+add_task(async function aboutDialog_foregroundCheck_downloadAuto_staging() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_STAGING_ENABLED, true]],
+ });
+
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ downloadInfo[0] = { patchType: "partial", bitsResult: "0" };
+ } else {
+ downloadInfo[0] = { patchType: "partial", internalResult: "0" };
+ }
+
+ // Since the partial should be successful specify an invalid size for the
+ // complete update.
+ let params = { queryString: "&invalidCompleteSize=1" };
+ await runAboutDialogUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ {
+ panelId: "applying",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: CONTINUE_STAGING,
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_APPLIED },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_downloadOptIn.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_downloadOptIn.js
new file mode 100644
index 0000000000..5a2ff513ad
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_downloadOptIn.js
@@ -0,0 +1,44 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog foreground check for updates
+// with a manual download.
+add_task(async function aboutDialog_foregroundCheck_downloadOptIn() {
+ await UpdateUtils.setAppUpdateAutoEnabled(false);
+
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ downloadInfo[0] = { patchType: "partial", bitsResult: "0" };
+ } else {
+ downloadInfo[0] = { patchType: "partial", internalResult: "0" };
+ }
+
+ // Since the partial should be successful specify an invalid size for the
+ // complete update.
+ let params = { queryString: "&invalidCompleteSize=1" };
+ await runAboutDialogUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "downloadAndInstall",
+ checkActiveUpdate: null,
+ continueFile: null,
+ },
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_downloadOptIn_staging.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_downloadOptIn_staging.js
new file mode 100644
index 0000000000..3ed331ec64
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_downloadOptIn_staging.js
@@ -0,0 +1,52 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog foreground check for updates
+// with a manual download and update staging.
+add_task(async function aboutDialog_foregroundCheck_downloadOptIn_staging() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_STAGING_ENABLED, true]],
+ });
+ await UpdateUtils.setAppUpdateAutoEnabled(false);
+
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ downloadInfo[0] = { patchType: "partial", bitsResult: "0" };
+ } else {
+ downloadInfo[0] = { patchType: "partial", internalResult: "0" };
+ }
+
+ // Since the partial should be successful specify an invalid size for the
+ // complete update.
+ let params = { queryString: "&invalidCompleteSize=1" };
+ await runAboutDialogUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "downloadAndInstall",
+ checkActiveUpdate: null,
+ continueFile: null,
+ },
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ {
+ panelId: "applying",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: CONTINUE_STAGING,
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_APPLIED },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_patch_completeBadSize.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_patch_completeBadSize.js
new file mode 100644
index 0000000000..fdc7d3407e
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_patch_completeBadSize.js
@@ -0,0 +1,36 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog foreground check for updates
+// with a complete bad size patch.
+add_task(async function aboutDialog_foregroundCheck_completeBadSize() {
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ downloadInfo[0] = { patchType: "complete", bitsResult: gBadSizeResult };
+ downloadInfo[1] = { patchType: "complete", internalResult: gBadSizeResult };
+ } else {
+ downloadInfo[0] = { patchType: "complete", internalResult: gBadSizeResult };
+ }
+
+ let params = { queryString: "&completePatchOnly=1&invalidCompleteSize=1" };
+ await runAboutDialogUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ {
+ panelId: "downloadFailed",
+ checkActiveUpdate: null,
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_patch_partialBadSize.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_patch_partialBadSize.js
new file mode 100644
index 0000000000..411fb25969
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_patch_partialBadSize.js
@@ -0,0 +1,36 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog foreground check for updates
+// with a partial bad size patch.
+add_task(async function aboutDialog_foregroundCheck_partialBadSize() {
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ 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" };
+ await runAboutDialogUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ {
+ panelId: "downloadFailed",
+ checkActiveUpdate: null,
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_patch_partialBadSize_complete.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_patch_partialBadSize_complete.js
new file mode 100644
index 0000000000..396be1e930
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_patch_partialBadSize_complete.js
@@ -0,0 +1,38 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog foreground check for updates
+// with a partial bad size patch and a complete patch.
+add_task(async function aboutDialog_foregroundCheck_partialBadSize_complete() {
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ downloadInfo[0] = { patchType: "partial", bitsResult: gBadSizeResult };
+ downloadInfo[1] = { patchType: "partial", internalResult: gBadSizeResult };
+ downloadInfo[2] = { patchType: "complete", bitsResult: "0" };
+ } else {
+ downloadInfo[0] = { patchType: "partial", internalResult: gBadSizeResult };
+ downloadInfo[1] = { patchType: "complete", internalResult: "0" };
+ }
+
+ let params = { queryString: "&invalidPartialSize=1" };
+ await runAboutDialogUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_patch_partialBadSize_completeBadSize.js b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_patch_partialBadSize_completeBadSize.js
new file mode 100644
index 0000000000..fb10250a49
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutDialog_fc_patch_partialBadSize_completeBadSize.js
@@ -0,0 +1,53 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog foreground check for updates
+// with a partial bad size patch and a complete bad size patch.
+add_task(
+ async function aboutDialog_foregroundCheck_partialBadSize_completeBadSize() {
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ downloadInfo[0] = { patchType: "partial", bitsResult: gBadSizeResult };
+ downloadInfo[1] = {
+ patchType: "partial",
+ internalResult: gBadSizeResult,
+ };
+ downloadInfo[2] = { patchType: "complete", bitsResult: gBadSizeResult };
+ downloadInfo[3] = {
+ patchType: "complete",
+ internalResult: gBadSizeResult,
+ };
+ } else {
+ downloadInfo[0] = {
+ patchType: "partial",
+ internalResult: gBadSizeResult,
+ };
+ downloadInfo[1] = {
+ patchType: "complete",
+ internalResult: gBadSizeResult,
+ };
+ }
+
+ let params = { queryString: "&invalidPartialSize=1&invalidCompleteSize=1" };
+ await runAboutDialogUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ {
+ panelId: "downloadFailed",
+ checkActiveUpdate: null,
+ continueFile: null,
+ },
+ ]);
+ }
+);
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloaded.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloaded.js
new file mode 100644
index 0000000000..6df4ee7ff5
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloaded.js
@@ -0,0 +1,17 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for about:preferences background check for updates
+// with the update downloaded when about:preferences is opened.
+add_task(async function aboutPrefs_backgroundCheck_downloaded() {
+ let params = { backgroundUpdate: true, waitForUpdateState: STATE_PENDING };
+ await runAboutPrefsUpdateTest(params, [
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloaded_staged.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloaded_staged.js
new file mode 100644
index 0000000000..749a8f0b07
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloaded_staged.js
@@ -0,0 +1,28 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for about:preferences background check for updates
+// with the update downloaded and staged when about:preferences is opened.
+add_task(async function aboutPrefs_backgroundCheck_downloaded_staged() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_STAGING_ENABLED, true]],
+ });
+
+ // Since the partial should be successful specify an invalid size for the
+ // complete update.
+ let params = {
+ queryString: "&invalidCompleteSize=1",
+ backgroundUpdate: true,
+ continueFile: CONTINUE_STAGING,
+ waitForUpdateState: STATE_APPLIED,
+ };
+ await runAboutPrefsUpdateTest(params, [
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_APPLIED },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloaded_staging.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloaded_staging.js
new file mode 100644
index 0000000000..2d607031f9
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloaded_staging.js
@@ -0,0 +1,59 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for about:preferences background check for updates
+// with the update downloaded and about:preferences opened during staging.
+add_task(async function aboutPrefs_backgroundCheck_downloaded_staged() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_STAGING_ENABLED, true]],
+ });
+
+ let lankpackCall = mockLangpackInstall();
+
+ // Since the partial should be successful specify an invalid size for the
+ // complete update.
+ let params = {
+ queryString: "&invalidCompleteSize=1",
+ backgroundUpdate: true,
+ waitForUpdateState: STATE_PENDING,
+ };
+ await runAboutPrefsUpdateTest(params, [
+ {
+ panelId: "applying",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: CONTINUE_STAGING,
+ },
+ async tab => {
+ // Once the state is pending but langpacks aren't complete the about
+ // dialog should still be showing downloading.
+ TestUtils.waitForCondition(() => {
+ return readStatusFile() == STATE_APPLIED;
+ });
+
+ let updateDeckId = await SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [],
+ () => {
+ return content.document.getElementById("updateDeck").selectedPanel.id;
+ }
+ );
+
+ is(updateDeckId, "applying", "UI should still show as applying.");
+
+ let { appVersion, resolve } = await lankpackCall;
+ is(
+ appVersion,
+ Services.appinfo.version,
+ "Should see the right app version."
+ );
+ resolve();
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_APPLIED },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloaded_stagingFailure.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloaded_stagingFailure.js
new file mode 100644
index 0000000000..3d3d56b2d7
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloaded_stagingFailure.js
@@ -0,0 +1,29 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for about:preferences background check for updates
+// with the update downloaded and staging has failed when the about:preferences
+// is opened.
+add_task(async function aboutPrefs_backgroundCheck_downloaded_stagingFailure() {
+ gEnv.set("MOZ_TEST_STAGING_ERROR", "1");
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_STAGING_ENABLED, true]],
+ });
+
+ // Since the partial should be successful specify an invalid size for the
+ // complete update.
+ let params = {
+ queryString: "&completePatchOnly=1",
+ backgroundUpdate: true,
+ waitForUpdateState: STATE_PENDING,
+ };
+ await runAboutDialogUpdateTest(params, [
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloading.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloading.js
new file mode 100644
index 0000000000..716652c6f6
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloading.js
@@ -0,0 +1,63 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for about:preferences background check for updates
+// with about:preferences opened during downloading.
+add_task(async function aboutPrefs_backgroundCheck_downloading() {
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ downloadInfo[0] = { patchType: "partial", bitsResult: "0" };
+ } else {
+ downloadInfo[0] = { patchType: "partial", internalResult: "0" };
+ }
+
+ let lankpackCall = mockLangpackInstall();
+
+ // Since the partial should be successful specify an invalid size for the
+ // complete update.
+ let params = {
+ queryString: "&useSlowDownloadMar=1&invalidCompleteSize=1",
+ backgroundUpdate: true,
+ waitForUpdateState: STATE_DOWNLOADING,
+ };
+ await runAboutPrefsUpdateTest(params, [
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ async tab => {
+ // Once the state is pending but langpacks aren't complete the about
+ // dialog should still be showing downloading.
+ TestUtils.waitForCondition(() => {
+ return readStatusFile() == STATE_PENDING;
+ });
+
+ let updateDeckId = await SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [],
+ () => {
+ return content.document.getElementById("updateDeck").selectedPanel.id;
+ }
+ );
+
+ is(updateDeckId, "downloading", "UI should still show as downloading.");
+
+ let { appVersion, resolve } = await lankpackCall;
+ is(
+ appVersion,
+ Services.appinfo.version,
+ "Should see the right app version."
+ );
+ resolve();
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloading_staging.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloading_staging.js
new file mode 100644
index 0000000000..ea325d5c34
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_downloading_staging.js
@@ -0,0 +1,72 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for about:preferences background check for updates
+// with about:preferences opened during downloading and stages the update.
+add_task(async function aboutPrefs_backgroundCheck_downloading_staging() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_STAGING_ENABLED, true]],
+ });
+
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ downloadInfo[0] = { patchType: "partial", bitsResult: "0" };
+ } else {
+ downloadInfo[0] = { patchType: "partial", internalResult: "0" };
+ }
+
+ let lankpackCall = mockLangpackInstall();
+
+ // Since the partial should be successful specify an invalid size for the
+ // complete update.
+ let params = {
+ queryString: "&useSlowDownloadMar=1&invalidCompleteSize=1",
+ backgroundUpdate: true,
+ waitForUpdateState: STATE_DOWNLOADING,
+ };
+ await runAboutPrefsUpdateTest(params, [
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ {
+ panelId: "applying",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: CONTINUE_STAGING,
+ },
+ async tab => {
+ // Once the state is pending but langpacks aren't complete the about
+ // dialog should still be showing downloading.
+ TestUtils.waitForCondition(() => {
+ return readStatusFile() == STATE_APPLIED;
+ });
+
+ let updateDeckId = await SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [],
+ () => {
+ return content.document.getElementById("updateDeck").selectedPanel.id;
+ }
+ );
+
+ is(updateDeckId, "applying", "UI should still show as applying.");
+
+ let { appVersion, resolve } = await lankpackCall;
+ is(
+ appVersion,
+ Services.appinfo.version,
+ "Should see the right app version."
+ );
+ resolve();
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_APPLIED },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_multiUpdate.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_multiUpdate.js
new file mode 100644
index 0000000000..9ccf593db5
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_bc_multiUpdate.js
@@ -0,0 +1,52 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const FIRST_UPDATE_VERSION = "999998.0";
+const SECOND_UPDATE_VERSION = "999999.0";
+
+function prepareToDownloadVersion(version) {
+ setUpdateURL(
+ URL_HTTP_UPDATE_SJS +
+ `?detailsURL=${gDetailsURL}&promptWaitTime=0&appVersion=${version}`
+ );
+}
+
+add_task(async function aboutPrefs_backgroundCheck_multiUpdate() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_STAGING_ENABLED, true]],
+ });
+
+ let params = {
+ version: FIRST_UPDATE_VERSION,
+ backgroundUpdate: true,
+ waitForUpdateState: STATE_PENDING,
+ };
+ await runAboutPrefsUpdateTest(params, [
+ {
+ panelId: "applying",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: CONTINUE_STAGING,
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_APPLIED },
+ continueFile: null,
+ },
+ () => {
+ prepareToDownloadVersion(SECOND_UPDATE_VERSION);
+ gAUS.checkForBackgroundUpdates();
+ },
+ {
+ panelId: "applying",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: CONTINUE_STAGING,
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_APPLIED },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_check_cantApply.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_check_cantApply.js
new file mode 100644
index 0000000000..aac9b33134
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_check_cantApply.js
@@ -0,0 +1,24 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for about:preferences foreground check for updates
+// without the ability to apply updates.
+add_task(async function aboutPrefs_foregroundCheck_cantApply() {
+ lockWriteTestFile();
+
+ let params = {};
+ await runAboutPrefsUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "manualUpdate",
+ checkActiveUpdate: null,
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_check_malformedXML.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_check_malformedXML.js
new file mode 100644
index 0000000000..f59f6d48b3
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_check_malformedXML.js
@@ -0,0 +1,22 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for about:preferences foreground check for updates
+// with a malformed update XML file.
+add_task(async function aboutPrefs_foregroundCheck_malformedXML() {
+ let params = { queryString: "&xmlMalformed=1" };
+ await runAboutPrefsUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "noUpdatesFound",
+ checkActiveUpdate: null,
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_check_noUpdate.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_check_noUpdate.js
new file mode 100644
index 0000000000..a8f6c072f7
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_check_noUpdate.js
@@ -0,0 +1,22 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for about:preferences foreground check for updates
+// with no update available.
+add_task(async function aboutPrefs_foregroundCheck_noUpdate() {
+ let params = { queryString: "&noUpdates=1" };
+ await runAboutPrefsUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "noUpdatesFound",
+ checkActiveUpdate: null,
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_check_otherInstance.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_check_otherInstance.js
new file mode 100644
index 0000000000..271c8f2837
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_check_otherInstance.js
@@ -0,0 +1,19 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for about:preferences foreground check for updates
+// with another application instance handling updates.
+add_task(async function aboutPrefs_foregroundCheck_otherInstance() {
+ setOtherInstanceHandlingUpdates();
+
+ let params = {};
+ await runAboutPrefsUpdateTest(params, [
+ {
+ panelId: "otherInstanceHandlingUpdates",
+ checkActiveUpdate: null,
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_check_unsupported.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_check_unsupported.js
new file mode 100644
index 0000000000..e18ce31bc4
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_check_unsupported.js
@@ -0,0 +1,22 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for about:preferences foreground check for updates
+// with an unsupported update.
+add_task(async function aboutPrefs_foregroundCheck_unsupported() {
+ let params = { queryString: "&unsupported=1" };
+ await runAboutPrefsUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "unsupportedSystem",
+ checkActiveUpdate: null,
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_downloadAuto.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_downloadAuto.js
new file mode 100644
index 0000000000..bd5fd18289
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_downloadAuto.js
@@ -0,0 +1,37 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for about:preferences foreground check for updates
+// with an automatic download.
+add_task(async function aboutPrefs_foregroundCheck_downloadAuto() {
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ downloadInfo[0] = { patchType: "partial", bitsResult: "0" };
+ } else {
+ downloadInfo[0] = { patchType: "partial", internalResult: "0" };
+ }
+
+ // Since the partial should be successful specify an invalid size for the
+ // complete update.
+ let params = { queryString: "&invalidCompleteSize=1" };
+ await runAboutPrefsUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_downloadAuto_staging.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_downloadAuto_staging.js
new file mode 100644
index 0000000000..1d9d082edd
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_downloadAuto_staging.js
@@ -0,0 +1,46 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for about:preferences foreground check for updates
+// with an automatic download and update staging.
+add_task(async function aboutPrefs_foregroundCheck_downloadAuto_staging() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_STAGING_ENABLED, true]],
+ });
+
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ downloadInfo[0] = { patchType: "partial", bitsResult: "0" };
+ } else {
+ downloadInfo[0] = { patchType: "partial", internalResult: "0" };
+ }
+
+ // Since the partial should be successful specify an invalid size for the
+ // complete update.
+ let params = { queryString: "&invalidCompleteSize=1" };
+ await runAboutPrefsUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ {
+ panelId: "applying",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: CONTINUE_STAGING,
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_APPLIED },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_downloadOptIn.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_downloadOptIn.js
new file mode 100644
index 0000000000..115e875b74
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_downloadOptIn.js
@@ -0,0 +1,44 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for about:preferences foreground check for updates
+// with a manual download.
+add_task(async function aboutPrefs_foregroundCheck_downloadOptIn() {
+ await UpdateUtils.setAppUpdateAutoEnabled(false);
+
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ downloadInfo[0] = { patchType: "partial", bitsResult: "0" };
+ } else {
+ downloadInfo[0] = { patchType: "partial", internalResult: "0" };
+ }
+
+ // Since the partial should be successful specify an invalid size for the
+ // complete update.
+ let params = { queryString: "&invalidCompleteSize=1" };
+ await runAboutPrefsUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "downloadAndInstall",
+ checkActiveUpdate: null,
+ continueFile: null,
+ },
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_downloadOptIn_staging.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_downloadOptIn_staging.js
new file mode 100644
index 0000000000..cff5d74701
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_downloadOptIn_staging.js
@@ -0,0 +1,52 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for about:preferences foreground check for updates
+// with a manual download and update staging.
+add_task(async function aboutPrefs_foregroundCheck_downloadOptIn_staging() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_STAGING_ENABLED, true]],
+ });
+ await UpdateUtils.setAppUpdateAutoEnabled(false);
+
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ downloadInfo[0] = { patchType: "partial", bitsResult: "0" };
+ } else {
+ downloadInfo[0] = { patchType: "partial", internalResult: "0" };
+ }
+
+ // Since the partial should be successful specify an invalid size for the
+ // complete update.
+ let params = { queryString: "&invalidCompleteSize=1" };
+ await runAboutPrefsUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "downloadAndInstall",
+ checkActiveUpdate: null,
+ continueFile: null,
+ },
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ {
+ panelId: "applying",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: CONTINUE_STAGING,
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_APPLIED },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_patch_completeBadSize.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_patch_completeBadSize.js
new file mode 100644
index 0000000000..a36d3d9807
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_patch_completeBadSize.js
@@ -0,0 +1,36 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for about:preferences foreground check for updates
+// with a complete bad size patch.
+add_task(async function aboutPrefs_foregroundCheck_completeBadSize() {
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ downloadInfo[0] = { patchType: "complete", bitsResult: gBadSizeResult };
+ downloadInfo[1] = { patchType: "complete", internalResult: gBadSizeResult };
+ } else {
+ downloadInfo[0] = { patchType: "complete", internalResult: gBadSizeResult };
+ }
+
+ let params = { queryString: "&completePatchOnly=1&invalidCompleteSize=1" };
+ await runAboutPrefsUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ {
+ panelId: "downloadFailed",
+ checkActiveUpdate: null,
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_patch_partialBadSize.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_patch_partialBadSize.js
new file mode 100644
index 0000000000..060acd405a
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_patch_partialBadSize.js
@@ -0,0 +1,36 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for about:preferences foreground check for updates
+// with a partial bad size patch.
+add_task(async function aboutPrefs_foregroundCheck_partialBadSize() {
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ 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" };
+ await runAboutPrefsUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ {
+ panelId: "downloadFailed",
+ checkActiveUpdate: null,
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_patch_partialBadSize_complete.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_patch_partialBadSize_complete.js
new file mode 100644
index 0000000000..c6e5b5b20b
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_patch_partialBadSize_complete.js
@@ -0,0 +1,38 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for about:preferences foreground check for updates
+// with a partial bad size patch and a complete patch.
+add_task(async function aboutPrefs_foregroundCheck_partialBadSize_complete() {
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ downloadInfo[0] = { patchType: "partial", bitsResult: gBadSizeResult };
+ downloadInfo[1] = { patchType: "partial", internalResult: gBadSizeResult };
+ downloadInfo[2] = { patchType: "complete", bitsResult: "0" };
+ } else {
+ downloadInfo[0] = { patchType: "partial", internalResult: gBadSizeResult };
+ downloadInfo[1] = { patchType: "complete", internalResult: "0" };
+ }
+
+ let params = { queryString: "&invalidPartialSize=1" };
+ await runAboutPrefsUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ {
+ panelId: "apply",
+ checkActiveUpdate: { state: STATE_PENDING },
+ continueFile: null,
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_patch_partialBadSize_completeBadSize.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_patch_partialBadSize_completeBadSize.js
new file mode 100644
index 0000000000..62abdc3af5
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_fc_patch_partialBadSize_completeBadSize.js
@@ -0,0 +1,53 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for about:preferences foreground check for updates
+// with a partial bad size patch and a complete bad size patch.
+add_task(
+ async function aboutPrefs_foregroundCheck_partialBadSize_completeBadSize() {
+ let downloadInfo = [];
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_BITS_ENABLED)) {
+ downloadInfo[0] = { patchType: "partial", bitsResult: gBadSizeResult };
+ downloadInfo[1] = {
+ patchType: "partial",
+ internalResult: gBadSizeResult,
+ };
+ downloadInfo[2] = { patchType: "complete", bitsResult: gBadSizeResult };
+ downloadInfo[3] = {
+ patchType: "complete",
+ internalResult: gBadSizeResult,
+ };
+ } else {
+ downloadInfo[0] = {
+ patchType: "partial",
+ internalResult: gBadSizeResult,
+ };
+ downloadInfo[1] = {
+ patchType: "complete",
+ internalResult: gBadSizeResult,
+ };
+ }
+
+ let params = { queryString: "&invalidPartialSize=1&invalidCompleteSize=1" };
+ await runAboutPrefsUpdateTest(params, [
+ {
+ panelId: "checkingForUpdates",
+ checkActiveUpdate: null,
+ continueFile: CONTINUE_CHECK,
+ },
+ {
+ panelId: "downloading",
+ checkActiveUpdate: { state: STATE_DOWNLOADING },
+ continueFile: CONTINUE_DOWNLOAD,
+ downloadInfo,
+ },
+ {
+ panelId: "downloadFailed",
+ checkActiveUpdate: null,
+ continueFile: null,
+ },
+ ]);
+ }
+);
diff --git a/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_settings.js b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_settings.js
new file mode 100644
index 0000000000..8e40e2bbcf
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_aboutPrefs_settings.js
@@ -0,0 +1,137 @@
+/* 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/.
+ */
+
+ChromeUtils.import("resource://gre/modules/osfile.jsm", this);
+
+// Changes, then verifies the value of app.update.auto via the about:preferences
+// UI. Requires a tab with about:preferences open to be passed in.
+async function changeAndVerifyPref(tab, newConfigValue) {
+ await SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [{ newConfigValue }],
+ async function({ newConfigValue }) {
+ let radioId = newConfigValue ? "autoDesktop" : "manualDesktop";
+ let radioElement = content.document.getElementById(radioId);
+ radioElement.click();
+ }
+ );
+
+ // On Windows, we really need to wait for the change to finish being
+ // written to the disk before we go to verify anything. Unfortunately, it
+ // would be difficult to check for quick changes to the attributes of the
+ // about:preferences controls (to wait for the controls to be disabled and
+ // re-enabled). So instead, just start the verification by asking the
+ // Application Update Service for the value of app.update.auto. It already
+ // serializes reads and writes to the app update config file, so this will not
+ // resolve until the file write is complete.
+ let configValueRead = await UpdateUtils.getAppUpdateAutoEnabled();
+ is(
+ configValueRead,
+ newConfigValue,
+ "Value returned should have matched the expected value"
+ );
+
+ // Only Windows currently has the update configuration JSON file.
+ if (AppConstants.platform == "win") {
+ let configFile = getUpdateDirFile(FILE_UPDATE_CONFIG_JSON);
+ let decoder = new TextDecoder();
+ let fileContents = await OS.File.read(configFile.path);
+ let saveObject = JSON.parse(decoder.decode(fileContents));
+ is(
+ saveObject["app.update.auto"],
+ newConfigValue,
+ "Value in file should match expected"
+ );
+ }
+
+ await SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [{ newConfigValue }],
+ async function({ newConfigValue }) {
+ let updateRadioGroup = content.document.getElementById(
+ "updateRadioGroup"
+ );
+ is(
+ updateRadioGroup.value,
+ `${newConfigValue}`,
+ "Update preference should match expected"
+ );
+ }
+ );
+}
+
+add_task(async function testUpdateAutoPrefUI() {
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:preferences"
+ );
+
+ await changeAndVerifyPref(tab, true);
+ ok(
+ !gUpdateManager.downloadingUpdate,
+ "There should not be a downloading update"
+ );
+ ok(!gUpdateManager.readyUpdate, "There should not be a ready update");
+
+ await changeAndVerifyPref(tab, false);
+ ok(
+ !gUpdateManager.downloadingUpdate,
+ "There should not be a downloading update"
+ );
+ ok(!gUpdateManager.readyUpdate, "There should not be a ready update");
+
+ let patchProps = { state: STATE_PENDING };
+ let patches = getLocalPatchString(patchProps);
+ let updateProps = { checkInterval: "1" };
+ let updates = getLocalUpdateString(updateProps, patches);
+ writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
+ writeStatusFile(STATE_PENDING);
+ reloadUpdateManagerData();
+ ok(!!gUpdateManager.readyUpdate, "There should be a ready update");
+
+ // A value of 0 will keep the update and a value of 1 will discard the update
+ // when the prompt service is called when the value of app.update.auto is
+ // changed to false.
+ let discardUpdate = 0;
+ let { prompt } = Services;
+ let promptService = {
+ QueryInterface: ChromeUtils.generateQI(["nsIPromptService"]),
+ confirmEx(...args) {
+ promptService._confirmExArgs = args;
+ return discardUpdate;
+ },
+ };
+ Services.prompt = promptService;
+ registerCleanupFunction(() => {
+ Services.prompt = prompt;
+ });
+
+ // Setting the value to false will call the prompt service and with 1 for
+ // discardUpdate the update won't be discarded so there should still be an
+ // active update.
+ discardUpdate = 1;
+ await changeAndVerifyPref(tab, false);
+ ok(!!gUpdateManager.readyUpdate, "There should be a ready update");
+
+ // Setting the value to true should not call the prompt service so there
+ // should still be an active update even with a value of 0 for
+ // discardUpdate.
+ discardUpdate = 0;
+ await changeAndVerifyPref(tab, true);
+ ok(!!gUpdateManager.readyUpdate, "There should be a ready update");
+
+ // Setting the value to false will call the prompt service and with 0 for
+ // discardUpdate the update should be discarded so there should not be an
+ // active update.
+ discardUpdate = 0;
+ await changeAndVerifyPref(tab, false);
+ ok(
+ !gUpdateManager.downloadingUpdate,
+ "There should not be a downloading update"
+ );
+ ok(!gUpdateManager.readyUpdate, "There should not be a ready update");
+
+ await BrowserTestUtils.removeTab(tab);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_check_cantApply.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_check_cantApply.js
new file mode 100644
index 0000000000..90f4c385cc
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_check_cantApply.js
@@ -0,0 +1,18 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function doorhanger_bc_check_cantApply() {
+ lockWriteTestFile();
+
+ let params = { checkAttempts: 1, queryString: "&promptWaitTime=0" };
+ await runDoorhangerUpdateTest(params, [
+ {
+ notificationId: "update-manual",
+ button: "button",
+ checkActiveUpdate: null,
+ pageURLs: { whatsNew: gDetailsURL, manual: URL_MANUAL_UPDATE },
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_check_malformedXML.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_check_malformedXML.js
new file mode 100644
index 0000000000..d83bc70b6f
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_check_malformedXML.js
@@ -0,0 +1,26 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function doorhanger_bc_check_malformedXML() {
+ const maxBackgroundErrors = 10;
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_BACKGROUNDMAXERRORS, maxBackgroundErrors]],
+ });
+
+ let params = {
+ checkAttempts: maxBackgroundErrors,
+ queryString: "&xmlMalformed=1",
+ };
+ await runDoorhangerUpdateTest(params, [
+ {
+ // If the update check fails 10 consecutive attempts then the manual
+ // update doorhanger.
+ notificationId: "update-manual",
+ button: "button",
+ checkActiveUpdate: null,
+ pageURLs: { whatsNew: gDetailsURL, manual: URL_MANUAL_UPDATE },
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_check_unsupported.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_check_unsupported.js
new file mode 100644
index 0000000000..17471a0160
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_check_unsupported.js
@@ -0,0 +1,94 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for doorhanger background check for updates
+// with an unsupported update.
+add_task(async function doorhanger_bc_check_unsupported() {
+ let params = { checkAttempts: 1, queryString: "&unsupported=1" };
+ await runDoorhangerUpdateTest(params, [
+ {
+ notificationId: "update-unsupported",
+ button: "button",
+ pageURLs: { manual: gDetailsURL },
+ },
+ async function doorhanger_unsupported_persist() {
+ await TestUtils.waitForCondition(
+ () => PanelUI.menuButton.hasAttribute("badge-status"),
+ "Waiting for update badge",
+ undefined,
+ 200
+ ).catch(e => {
+ // Instead of throwing let the check below fail the test.
+ logTestInfo(e);
+ });
+ is(
+ PanelUI.notificationPanel.state,
+ "closed",
+ "The window's doorhanger is closed."
+ );
+ ok(
+ PanelUI.menuButton.hasAttribute("badge-status"),
+ "The window has a badge."
+ );
+ is(
+ PanelUI.menuButton.getAttribute("badge-status"),
+ "update-unsupported",
+ "The correct badge is showing for the background window"
+ );
+
+ // Test persistence of the badge when the client has restarted by
+ // resetting the UpdateListener.
+ UpdateListener.reset();
+ is(
+ PanelUI.notificationPanel.state,
+ "closed",
+ "The window's doorhanger is closed."
+ );
+ ok(
+ !PanelUI.menuButton.hasAttribute("badge-status"),
+ "The window does not have a badge."
+ );
+ UpdateListener.init();
+ is(
+ PanelUI.notificationPanel.state,
+ "closed",
+ "The window's doorhanger is closed."
+ );
+ ok(
+ PanelUI.menuButton.hasAttribute("badge-status"),
+ "The window has a badge."
+ );
+ is(
+ PanelUI.menuButton.getAttribute("badge-status"),
+ "update-unsupported",
+ "The correct badge is showing for the background window."
+ );
+ },
+ ]);
+
+ params = {
+ checkAttempts: 1,
+ queryString: "&invalidCompleteSize=1&promptWaitTime=0",
+ };
+ await runDoorhangerUpdateTest(params, [
+ {
+ notificationId: "update-restart",
+ button: "secondaryButton",
+ checkActiveUpdate: { state: STATE_PENDING },
+ },
+ async function doorhanger_unsupported_removed() {
+ // Test that finding an update removes the app.update.unsupported.url
+ // preference.
+ let unsupportedURL = Services.prefs.getCharPref(
+ PREF_APP_UPDATE_UNSUPPORTED_URL,
+ null
+ );
+ ok(
+ !unsupportedURL,
+ "The " + PREF_APP_UPDATE_UNSUPPORTED_URL + " preference was removed."
+ );
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloadAutoFailures.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloadAutoFailures.js
new file mode 100644
index 0000000000..23b2569ad9
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloadAutoFailures.js
@@ -0,0 +1,37 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function doorhanger_bc_downloadAutoFailures() {
+ const maxBackgroundErrors = 5;
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_BACKGROUNDMAXERRORS, maxBackgroundErrors]],
+ });
+
+ let params = { checkAttempts: 1, queryString: "&badURL=1" };
+ await runDoorhangerUpdateTest(params, [
+ {
+ // If the update download fails maxBackgroundErrors download attempts then
+ // show the update available prompt.
+ notificationId: "update-available",
+ button: "button",
+ checkActiveUpdate: null,
+ pageURLs: { whatsNew: gDefaultWhatsNewURL },
+ },
+ {
+ notificationId: "update-available",
+ button: "button",
+ checkActiveUpdate: null,
+ pageURLs: { whatsNew: gDefaultWhatsNewURL },
+ },
+ {
+ // If the update process is unable to install the update show the manual
+ // update doorhanger.
+ notificationId: "update-manual",
+ button: "button",
+ checkActiveUpdate: null,
+ pageURLs: { whatsNew: gDefaultWhatsNewURL, manual: URL_MANUAL_UPDATE },
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloadAutoFailures_bgWin.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloadAutoFailures_bgWin.js
new file mode 100644
index 0000000000..d8cec82ae5
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloadAutoFailures_bgWin.js
@@ -0,0 +1,85 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function doorhanger_bc_downloadAutoFailures_bgWin() {
+ function getBackgroundWindowHandler(destroyWindow) {
+ return async function() {
+ await TestUtils.waitForCondition(
+ () => PanelUI.menuButton.hasAttribute("badge-status"),
+ "Background window has a badge.",
+ undefined,
+ 200
+ ).catch(e => {
+ // Instead of throwing let the check below fail the test.
+ logTestInfo(e);
+ });
+ ok(
+ PanelUI.menuButton.hasAttribute("badge-status"),
+ "PanelUI.menuButton should have a 'badge-status' attribute"
+ );
+ is(
+ PanelUI.notificationPanel.state,
+ "closed",
+ "The doorhanger is not showing for the background window"
+ );
+ is(
+ PanelUI.menuButton.getAttribute("badge-status"),
+ "update-available",
+ "The badge is showing for the background window"
+ );
+
+ checkWhatsNewLink(
+ extraWindow,
+ "update-available-whats-new",
+ gDefaultWhatsNewURL
+ );
+ let buttonEl = getNotificationButton(
+ extraWindow,
+ "update-available",
+ "button"
+ );
+ buttonEl.click();
+
+ if (destroyWindow) {
+ // The next popup may be shown during closeWindow or promiseFocus
+ // calls.
+ let waitForPopupShown = new Promise(resolve => {
+ window.addEventListener(
+ "popupshown",
+ () => {
+ executeSoon(resolve);
+ },
+ { once: true }
+ );
+ });
+ await BrowserTestUtils.closeWindow(extraWindow);
+ await SimpleTest.promiseFocus(window);
+ await waitForPopupShown;
+ }
+ };
+ }
+
+ const maxBackgroundErrors = 5;
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_BACKGROUNDMAXERRORS, maxBackgroundErrors]],
+ });
+
+ let extraWindow = await BrowserTestUtils.openNewBrowserWindow();
+ await SimpleTest.promiseFocus(extraWindow);
+
+ let params = { checkAttempts: 1, queryString: "&badURL=1", popupShown: true };
+ await runDoorhangerUpdateTest(params, [
+ getBackgroundWindowHandler(false),
+ getBackgroundWindowHandler(true),
+ {
+ // If the update process is unable to install the update show the manual
+ // update doorhanger.
+ notificationId: "update-manual",
+ button: "button",
+ checkActiveUpdate: null,
+ pageURLs: { whatsNew: gDefaultWhatsNewURL, manual: URL_MANUAL_UPDATE },
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloadOptIn.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloadOptIn.js
new file mode 100644
index 0000000000..ece7033ecc
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloadOptIn.js
@@ -0,0 +1,26 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function doorhanger_bc_downloadOptIn() {
+ await UpdateUtils.setAppUpdateAutoEnabled(false);
+
+ let params = {
+ checkAttempts: 1,
+ queryString: "&invalidCompleteSize=1&promptWaitTime=0",
+ };
+ await runDoorhangerUpdateTest(params, [
+ {
+ notificationId: "update-available",
+ button: "button",
+ checkActiveUpdate: null,
+ pageURLs: { whatsNew: gDefaultWhatsNewURL },
+ },
+ {
+ notificationId: "update-restart",
+ button: "secondaryButton",
+ checkActiveUpdate: { state: STATE_PENDING },
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloadOptIn_bgWin.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloadOptIn_bgWin.js
new file mode 100644
index 0000000000..f09d6a9ea8
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloadOptIn_bgWin.js
@@ -0,0 +1,68 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function doorhanger_bc_downloadOptIn_bgWin() {
+ function getBackgroundWindowHandler() {
+ return async function() {
+ await TestUtils.waitForCondition(
+ () => PanelUI.menuButton.hasAttribute("badge-status"),
+ "Background window has a badge.",
+ undefined,
+ 200
+ ).catch(e => {
+ // Instead of throwing let the check below fail the test.
+ logTestInfo(e);
+ });
+ ok(
+ PanelUI.menuButton.hasAttribute("badge-status"),
+ "PanelUI.menuButton should have a 'badge-status' attribute"
+ );
+ is(
+ PanelUI.notificationPanel.state,
+ "closed",
+ "The doorhanger is not showing for the background window"
+ );
+ is(
+ PanelUI.menuButton.getAttribute("badge-status"),
+ "update-available",
+ "The badge is showing for the background window"
+ );
+ let popupShownPromise = BrowserTestUtils.waitForEvent(
+ PanelUI.notificationPanel,
+ "popupshown"
+ );
+ await BrowserTestUtils.closeWindow(extraWindow);
+ await SimpleTest.promiseFocus(window);
+ await popupShownPromise;
+
+ checkWhatsNewLink(
+ window,
+ "update-available-whats-new",
+ gDefaultWhatsNewURL
+ );
+ let buttonEl = getNotificationButton(
+ window,
+ "update-available",
+ "button"
+ );
+ buttonEl.click();
+ };
+ }
+
+ await UpdateUtils.setAppUpdateAutoEnabled(false);
+
+ let extraWindow = await BrowserTestUtils.openNewBrowserWindow();
+ await SimpleTest.promiseFocus(extraWindow);
+
+ let params = { checkAttempts: 1, queryString: "&promptWaitTime=0" };
+ await runDoorhangerUpdateTest(params, [
+ getBackgroundWindowHandler(),
+ {
+ notificationId: "update-restart",
+ button: "secondaryButton",
+ checkActiveUpdate: { state: STATE_PENDING },
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloadOptIn_staging.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloadOptIn_staging.js
new file mode 100644
index 0000000000..79b9a3d934
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloadOptIn_staging.js
@@ -0,0 +1,30 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function doorhanger_bc_downloadOptIn_staging() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ // Tests the app.update.promptWaitTime pref
+ [PREF_APP_UPDATE_PROMPTWAITTIME, 0],
+ [PREF_APP_UPDATE_STAGING_ENABLED, true],
+ ],
+ });
+ await UpdateUtils.setAppUpdateAutoEnabled(false);
+
+ let params = { checkAttempts: 1, queryString: "&invalidCompleteSize=1" };
+ await runDoorhangerUpdateTest(params, [
+ {
+ notificationId: "update-available",
+ button: "button",
+ checkActiveUpdate: null,
+ pageURLs: { whatsNew: gDefaultWhatsNewURL },
+ },
+ {
+ notificationId: "update-restart",
+ button: "secondaryButton",
+ checkActiveUpdate: { state: STATE_APPLIED },
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloaded.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloaded.js
new file mode 100644
index 0000000000..e29dad26fa
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloaded.js
@@ -0,0 +1,18 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function doorhanger_bc_downloaded() {
+ let params = {
+ checkAttempts: 1,
+ queryString: "&invalidCompleteSize=1&promptWaitTime=0",
+ };
+ await runDoorhangerUpdateTest(params, [
+ {
+ notificationId: "update-restart",
+ button: "secondaryButton",
+ checkActiveUpdate: { state: STATE_PENDING },
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloaded_disableBITS.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloaded_disableBITS.js
new file mode 100644
index 0000000000..5f89c95322
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloaded_disableBITS.js
@@ -0,0 +1,31 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function doorhanger_bc_downloaded_disableBITS() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_BITS_ENABLED, true]],
+ });
+
+ let params = {
+ checkAttempts: 1,
+ queryString: "&promptWaitTime=0&disableBITS=true",
+ };
+ await runDoorhangerUpdateTest(params, [
+ {
+ notificationId: "update-restart",
+ button: "secondaryButton",
+ checkActiveUpdate: { state: STATE_PENDING },
+ },
+ ]);
+
+ let patch = getPatchOfType(
+ "partial",
+ gUpdateManager.readyUpdate
+ ).QueryInterface(Ci.nsIWritablePropertyBag);
+ ok(
+ !patch.getProperty("bitsId"),
+ "The selected patch should not have a bitsId property"
+ );
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloaded_staged.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloaded_staged.js
new file mode 100644
index 0000000000..50416608f2
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_downloaded_staged.js
@@ -0,0 +1,22 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function doorhanger_bc_downloaded_staged() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_STAGING_ENABLED, true]],
+ });
+
+ let params = {
+ checkAttempts: 1,
+ queryString: "&invalidCompleteSize=1&promptWaitTime=0",
+ };
+ await runDoorhangerUpdateTest(params, [
+ {
+ notificationId: "update-restart",
+ button: "secondaryButton",
+ checkActiveUpdate: { state: STATE_APPLIED },
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_multiUpdate.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_multiUpdate.js
new file mode 100644
index 0000000000..07e7bf51fa
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_multiUpdate.js
@@ -0,0 +1,93 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * This test downloads 2 updates sequentially, and ensures that the doorhanger
+ * and badge do what they are supposed to do:
+ * First thing after the first download, the doorhanger should be displayed.
+ * Then download the next update.
+ * While that update stages, the badge should be hidden to prevent restarting
+ * to update while the update is staging.
+ * Once the staging completes, the badge should return. The doorhanger should
+ * not be shown at this time, because it has already been shown this
+ * session.
+ */
+
+const FIRST_UPDATE_VERSION = "999998.0";
+const SECOND_UPDATE_VERSION = "999999.0";
+
+function prepareToDownloadVersion(version) {
+ setUpdateURL(
+ URL_HTTP_UPDATE_SJS +
+ `?detailsURL=${gDetailsURL}&promptWaitTime=0&appVersion=${version}`
+ );
+}
+
+add_task(async function doorhanger_bc_multiUpdate() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_STAGING_ENABLED, true]],
+ });
+
+ let params = {
+ checkAttempts: 1,
+ queryString: "&promptWaitTime=0",
+ version: FIRST_UPDATE_VERSION,
+ slowStaging: true,
+ };
+ await runDoorhangerUpdateTest(params, [
+ () => {
+ return continueFileHandler(CONTINUE_STAGING);
+ },
+ {
+ notificationId: "update-restart",
+ button: "secondaryButton",
+ checkActiveUpdate: { state: STATE_APPLIED },
+ },
+ async () => {
+ is(
+ PanelUI.menuButton.getAttribute("badge-status"),
+ "update-restart",
+ "Should have restart badge"
+ );
+
+ prepareToDownloadVersion(SECOND_UPDATE_VERSION);
+ let updateSwapped = waitForEvent("update-swap");
+ gAUS.checkForBackgroundUpdates();
+ await updateSwapped;
+ // The badge should be hidden while we swap from one update to the other
+ // to prevent restarting to update while staging is occurring. But since
+ // it will be waiting on the same event we are waiting on, wait an
+ // additional tick to let the other update-swap listeners run.
+ await TestUtils.waitForTick();
+
+ is(
+ PanelUI.menuButton.getAttribute("badge-status"),
+ "",
+ "Should not have restart badge during staging"
+ );
+
+ await continueFileHandler(CONTINUE_STAGING);
+
+ try {
+ await TestUtils.waitForCondition(
+ () =>
+ PanelUI.menuButton.getAttribute("badge-status") == "update-restart",
+ "Waiting for update restart badge to return after staging"
+ );
+ } catch (ex) {}
+
+ is(
+ PanelUI.menuButton.getAttribute("badge-status"),
+ "update-restart",
+ "Restart badge should be restored after staging completes"
+ );
+ is(
+ PanelUI.notificationPanel.state,
+ "closed",
+ "Should not open a second doorhanger"
+ );
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_multiUpdate_promptWaitTime.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_multiUpdate_promptWaitTime.js
new file mode 100644
index 0000000000..00c61bcbb4
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_multiUpdate_promptWaitTime.js
@@ -0,0 +1,89 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * This test downloads 2 updates sequentially, and ensures that the doorhanger
+ * and badge do what they are supposed to do. However, the first update has a
+ * long promptWaitTime, and the second has a short one and the badge wait time
+ * is set to 0. This should result in this behavior:
+ * First thing after the first download, the badge should be displayed, but
+ * not the doorhanger.
+ * Then download the next update.
+ * While that update stages, the badge should be hidden to prevent restarting
+ * to update while the update is staging.
+ * Once the staging completes, the doorhanger should be shown. Despite the
+ * long promptWaitTime of the initial update, this patch's short wait time
+ * means that the doorhanger should be shown soon rather than in a long
+ * time.
+ */
+
+const FIRST_UPDATE_VERSION = "999998.0";
+const SECOND_UPDATE_VERSION = "999999.0";
+const LONG_PROMPT_WAIT_TIME_SEC = 10 * 60 * 60; // 10 hours
+
+function prepareToDownloadVersion(version, promptWaitTime) {
+ setUpdateURL(
+ URL_HTTP_UPDATE_SJS +
+ `?detailsURL=${gDetailsURL}&promptWaitTime=${promptWaitTime}&appVersion=${version}`
+ );
+}
+
+add_task(async function doorhanger_bc_multiUpdate() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ [PREF_APP_UPDATE_STAGING_ENABLED, true],
+ [PREF_APP_UPDATE_BADGEWAITTIME, 0],
+ ],
+ });
+
+ let params = {
+ checkAttempts: 1,
+ queryString: `&promptWaitTime=${LONG_PROMPT_WAIT_TIME_SEC}`,
+ version: FIRST_UPDATE_VERSION,
+ slowStaging: true,
+ };
+ await runDoorhangerUpdateTest(params, [
+ async () => {
+ await continueFileHandler(CONTINUE_STAGING);
+
+ try {
+ await TestUtils.waitForCondition(
+ () =>
+ PanelUI.menuButton.getAttribute("badge-status") == "update-restart",
+ "Waiting for update restart badge to return after staging"
+ );
+ } catch (ex) {}
+
+ is(
+ PanelUI.menuButton.getAttribute("badge-status"),
+ "update-restart",
+ "Should have restart badge"
+ );
+
+ prepareToDownloadVersion(SECOND_UPDATE_VERSION, 0);
+ let updateSwapped = waitForEvent("update-swap");
+ gAUS.checkForBackgroundUpdates();
+ await updateSwapped;
+ // The badge should be hidden while we swap from one update to the other
+ // to prevent restarting to update while staging is occurring. But since
+ // it will be waiting on the same event we are waiting on, wait an
+ // additional tick to let the other update-swap listeners run.
+ await TestUtils.waitForTick();
+
+ is(
+ PanelUI.menuButton.getAttribute("badge-status"),
+ "",
+ "Should not have restart badge during staging"
+ );
+
+ await continueFileHandler(CONTINUE_STAGING);
+ },
+ {
+ notificationId: "update-restart",
+ button: "secondaryButton",
+ checkActiveUpdate: { state: STATE_APPLIED },
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_patch_completeBadSize.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_patch_completeBadSize.js
new file mode 100644
index 0000000000..505e4a9ccc
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_patch_completeBadSize.js
@@ -0,0 +1,35 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function doorhanger_bc_patch_completeBadSize() {
+ let params = {
+ checkAttempts: 1,
+ queryString: "&completePatchOnly=1&invalidCompleteSize=1",
+ };
+ await runDoorhangerUpdateTest(params, [
+ {
+ // If the update download fails maxBackgroundErrors download attempts then
+ // show the update available prompt.
+ notificationId: "update-available",
+ button: "button",
+ checkActiveUpdate: null,
+ pageURLs: { whatsNew: gDefaultWhatsNewURL },
+ },
+ {
+ notificationId: "update-available",
+ button: "button",
+ checkActiveUpdate: null,
+ pageURLs: { whatsNew: gDefaultWhatsNewURL },
+ },
+ {
+ // If the update process is unable to install the update show the manual
+ // update doorhanger.
+ notificationId: "update-manual",
+ button: "button",
+ checkActiveUpdate: null,
+ pageURLs: { whatsNew: gDefaultWhatsNewURL, manual: URL_MANUAL_UPDATE },
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_patch_partialBadSize.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_patch_partialBadSize.js
new file mode 100644
index 0000000000..2db72f6b49
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_patch_partialBadSize.js
@@ -0,0 +1,35 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function doorhanger_bc_patch_partialBadSize() {
+ let params = {
+ checkAttempts: 1,
+ queryString: "&partialPatchOnly=1&invalidPartialSize=1",
+ };
+ await runDoorhangerUpdateTest(params, [
+ {
+ // If the update download fails maxBackgroundErrors download attempts then
+ // show the update available prompt.
+ notificationId: "update-available",
+ button: "button",
+ checkActiveUpdate: null,
+ pageURLs: { whatsNew: gDefaultWhatsNewURL },
+ },
+ {
+ notificationId: "update-available",
+ button: "button",
+ checkActiveUpdate: null,
+ pageURLs: { whatsNew: gDefaultWhatsNewURL },
+ },
+ {
+ // If the update process is unable to install the update show the manual
+ // update doorhanger.
+ notificationId: "update-manual",
+ button: "button",
+ checkActiveUpdate: null,
+ pageURLs: { whatsNew: gDefaultWhatsNewURL, manual: URL_MANUAL_UPDATE },
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_patch_partialBadSize_complete.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_patch_partialBadSize_complete.js
new file mode 100644
index 0000000000..f3c9b1f51f
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_patch_partialBadSize_complete.js
@@ -0,0 +1,18 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function doorhanger_bc_patch_partialBadSize_complete() {
+ let params = {
+ checkAttempts: 1,
+ queryString: "&invalidPartialSize=1&promptWaitTime=0",
+ };
+ await runDoorhangerUpdateTest(params, [
+ {
+ notificationId: "update-restart",
+ button: "secondaryButton",
+ checkActiveUpdate: { state: STATE_PENDING },
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_patch_partialBadSize_completeBadSize.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_patch_partialBadSize_completeBadSize.js
new file mode 100644
index 0000000000..4a84571e15
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_patch_partialBadSize_completeBadSize.js
@@ -0,0 +1,35 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function doorhanger_bc_patch_partialBadSize_completeBadSize() {
+ let params = {
+ checkAttempts: 1,
+ queryString: "&invalidPartialSize=1&invalidCompleteSize=1",
+ };
+ await runDoorhangerUpdateTest(params, [
+ {
+ // If the update download fails maxBackgroundErrors download attempts then
+ // show the update available prompt.
+ notificationId: "update-available",
+ button: "button",
+ checkActiveUpdate: null,
+ pageURLs: { whatsNew: gDefaultWhatsNewURL },
+ },
+ {
+ notificationId: "update-available",
+ button: "button",
+ checkActiveUpdate: null,
+ pageURLs: { whatsNew: gDefaultWhatsNewURL },
+ },
+ {
+ // If the update process is unable to install the update show the manual
+ // update doorhanger.
+ notificationId: "update-manual",
+ button: "button",
+ checkActiveUpdate: null,
+ pageURLs: { whatsNew: gDefaultWhatsNewURL, manual: URL_MANUAL_UPDATE },
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_sp_patch_completeApplyFailure.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_sp_patch_completeApplyFailure.js
new file mode 100644
index 0000000000..616b399c21
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_sp_patch_completeApplyFailure.js
@@ -0,0 +1,23 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function doorhanger_sp_patch_completeApplyFailure() {
+ let patchProps = { state: STATE_PENDING };
+ let patches = getLocalPatchString(patchProps);
+ let updateProps = { checkInterval: "1" };
+ let updates = getLocalUpdateString(updateProps, patches);
+
+ let params = { updates };
+ await runDoorhangerUpdateTest(params, [
+ {
+ // If the update process is unable to install the update show the manual
+ // update doorhanger.
+ notificationId: "update-manual",
+ button: "button",
+ checkActiveUpdate: null,
+ pageURLs: { whatsNew: gDefaultWhatsNewURL, manual: URL_MANUAL_UPDATE },
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_sp_patch_partialApplyFailure.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_sp_patch_partialApplyFailure.js
new file mode 100644
index 0000000000..a390627b59
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_sp_patch_partialApplyFailure.js
@@ -0,0 +1,22 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function doorhanger_sp_patch_partialApplyFailure() {
+ let patchProps = { type: "partial", state: STATE_PENDING };
+ let patches = getLocalPatchString(patchProps);
+ let updateProps = { isCompleteUpdate: "false", checkInterval: "1" };
+ let updates = getLocalUpdateString(updateProps, patches);
+
+ let params = { updates };
+ await runDoorhangerUpdateTest(params, [
+ {
+ // If there is only an invalid patch show the manual update doorhanger.
+ notificationId: "update-manual",
+ button: "button",
+ checkActiveUpdate: null,
+ pageURLs: { whatsNew: gDefaultWhatsNewURL, manual: URL_MANUAL_UPDATE },
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_sp_patch_partialApplyFailure_complete.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_sp_patch_partialApplyFailure_complete.js
new file mode 100644
index 0000000000..bf533dab04
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_sp_patch_partialApplyFailure_complete.js
@@ -0,0 +1,22 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function doorhanger_sp_patch_partialApplyFailure_complete() {
+ let patchProps = { type: "partial", state: STATE_PENDING };
+ let patches = getLocalPatchString(patchProps);
+ patchProps = { selected: "false" };
+ patches += getLocalPatchString(patchProps);
+ let updateProps = { isCompleteUpdate: "false", promptWaitTime: "0" };
+ let updates = getLocalUpdateString(updateProps, patches);
+
+ let params = { updates };
+ await runDoorhangerUpdateTest(params, [
+ {
+ notificationId: "update-restart",
+ button: "secondaryButton",
+ checkActiveUpdate: { state: STATE_PENDING },
+ },
+ ]);
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_sp_patch_partialApplyFailure_completeBadSize.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_sp_patch_partialApplyFailure_completeBadSize.js
new file mode 100644
index 0000000000..4c5f2279f2
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_sp_patch_partialApplyFailure_completeBadSize.js
@@ -0,0 +1,32 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(
+ async function doorhanger_sp_patch_partialApplyFailure_completeBadSize() {
+ // Because of the way the test is simulating failure it has to pretend it has
+ // already retried.
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_DOWNLOAD_MAXATTEMPTS, 0]],
+ });
+
+ let patchProps = { type: "partial", state: STATE_PENDING };
+ let patches = getLocalPatchString(patchProps);
+ patchProps = { size: "1234", selected: "false" };
+ patches += getLocalPatchString(patchProps);
+ let updateProps = { isCompleteUpdate: "false" };
+ let updates = getLocalUpdateString(updateProps, patches);
+
+ let params = { updates };
+ await runDoorhangerUpdateTest(params, [
+ {
+ // If there is only an invalid patch show the manual update doorhanger.
+ notificationId: "update-manual",
+ button: "button",
+ checkActiveUpdate: null,
+ pageURLs: { whatsNew: gDefaultWhatsNewURL, manual: URL_MANUAL_UPDATE },
+ },
+ ]);
+ }
+);
diff --git a/toolkit/mozapps/update/tests/browser/browser_doorhanger_sp_patch_partialApplyFailure_complete_staging.js b/toolkit/mozapps/update/tests/browser/browser_doorhanger_sp_patch_partialApplyFailure_complete_staging.js
new file mode 100644
index 0000000000..a99c04b0be
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_sp_patch_partialApplyFailure_complete_staging.js
@@ -0,0 +1,28 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(
+ async function doorhanger_sp_patch_partialApplyFailure_complete_staging() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_STAGING_ENABLED, true]],
+ });
+
+ let patchProps = { type: "partial", state: STATE_PENDING };
+ let patches = getLocalPatchString(patchProps);
+ patchProps = { selected: "false" };
+ patches += getLocalPatchString(patchProps);
+ let updateProps = { isCompleteUpdate: "false", promptWaitTime: "0" };
+ let updates = getLocalUpdateString(updateProps, patches);
+
+ let params = { updates };
+ await runDoorhangerUpdateTest(params, [
+ {
+ notificationId: "update-restart",
+ button: "secondaryButton",
+ checkActiveUpdate: { state: STATE_APPLIED },
+ },
+ ]);
+ }
+);
diff --git a/toolkit/mozapps/update/tests/browser/browser_elevationDialog.js b/toolkit/mozapps/update/tests/browser/browser_elevationDialog.js
new file mode 100644
index 0000000000..6aa32a7fc9
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_elevationDialog.js
@@ -0,0 +1,139 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function elevation_dialog() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_DISABLEDFORTESTING, false]],
+ });
+
+ // Create a mock of nsIAppStartup's quit method so clicking the restart button
+ // won't restart the application.
+ let { startup } = Services;
+ let appStartup = {
+ QueryInterface: ChromeUtils.generateQI(["nsIAppStartup"]),
+ quit(mode) {
+ if (elevationDialog) {
+ elevationDialog.close();
+ elevationDialog = null;
+ }
+ },
+ };
+ Services.startup = appStartup;
+ registerCleanupFunction(() => {
+ Services.startup = startup;
+ });
+
+ registerCleanupFunction(async () => {
+ let win = Services.wm.getMostRecentWindow("Update:Elevation");
+ if (win) {
+ win.close();
+ await TestUtils.waitForCondition(
+ () => !Services.wm.getMostRecentWindow("Update:Elevation"),
+ "The Update Elevation dialog should have closed"
+ );
+ }
+ });
+
+ // Test clicking the "Restart Later" button
+ let elevationDialog = await waitForElevationDialog();
+ await TestUtils.waitForTick();
+ elevationDialog.document.getElementById("elevateExtra2").click();
+ await TestUtils.waitForCondition(
+ () => !Services.wm.getMostRecentWindow("Update:Elevation"),
+ "The Update Elevation dialog should have closed"
+ );
+ ok(!!gUpdateManager.readyUpdate, "There should be a ready update");
+ is(
+ gUpdateManager.readyUpdate.state,
+ STATE_PENDING_ELEVATE,
+ "The ready update state should equal " + STATE_PENDING_ELEVATE
+ );
+ is(
+ readStatusFile(),
+ STATE_PENDING_ELEVATE,
+ "The status file state should equal " + STATE_PENDING_ELEVATE
+ );
+
+ // Test clicking the "No Thanks" button
+ elevationDialog = await waitForElevationDialog();
+ await TestUtils.waitForTick();
+ elevationDialog.document.getElementById("elevateExtra1").click();
+ await TestUtils.waitForCondition(
+ () => !Services.wm.getMostRecentWindow("Update:Elevation"),
+ "The Update Elevation dialog should have closed"
+ );
+ ok(!gUpdateManager.readyUpdate, "There should not be a ready update");
+ is(
+ readStatusFile(),
+ STATE_NONE,
+ "The status file state should equal " + STATE_NONE
+ );
+
+ // Test clicking the "Restart <brandShortName>" button
+ elevationDialog = await waitForElevationDialog();
+ await TestUtils.waitForTick();
+ elevationDialog.document.getElementById("elevateAccept").click();
+ await TestUtils.waitForCondition(
+ () => !Services.wm.getMostRecentWindow("Update:Elevation"),
+ "The Update Elevation dialog should have closed"
+ );
+ ok(!!gUpdateManager.readyUpdate, "There should be a ready update");
+ is(
+ gUpdateManager.readyUpdate.state,
+ STATE_PENDING_ELEVATE,
+ "The active update state should equal " + STATE_PENDING_ELEVATE
+ );
+ is(
+ readStatusFile(),
+ STATE_PENDING,
+ "The status file state should equal " + STATE_PENDING
+ );
+});
+
+/**
+ * Waits for the Update Elevation Dialog to load.
+ *
+ * @return A promise that returns the domWindow for the Update Elevation Dialog
+ * and resolves when the Update Elevation Dialog loads.
+ */
+function waitForElevationDialog() {
+ return new Promise(resolve => {
+ var listener = {
+ onOpenWindow: aXULWindow => {
+ debugDump("Update Elevation dialog shown...");
+ Services.wm.removeListener(listener);
+
+ async function elevationDialogOnLoad() {
+ domwindow.removeEventListener("load", elevationDialogOnLoad, true);
+ let chromeURI =
+ "chrome://mozapps/content/update/updateElevation.xhtml";
+ is(
+ domwindow.document.location.href,
+ chromeURI,
+ "Update Elevation appeared"
+ );
+ resolve(domwindow);
+ }
+
+ var domwindow = aXULWindow.docShell.domWindow;
+ domwindow.addEventListener("load", elevationDialogOnLoad, true);
+ },
+ onCloseWindow: aXULWindow => {},
+ };
+
+ Services.wm.addListener(listener);
+ // Add the active-update.xml and update.status files used for these tests,
+ // reload the update manager, and then simulate startup so the Update
+ // Elevation Dialog is opened.
+ let patchProps = { state: STATE_PENDING_ELEVATE };
+ let patches = getLocalPatchString(patchProps);
+ let updateProps = { checkInterval: "1" };
+ let updates = getLocalUpdateString(updateProps, patches);
+ writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
+ writeStatusFile(STATE_PENDING_ELEVATE);
+ reloadUpdateManagerData();
+ testPostUpdateProcessing();
+ });
+}
diff --git a/toolkit/mozapps/update/tests/browser/browser_telemetry_updatePing_downloaded_ready.js b/toolkit/mozapps/update/tests/browser/browser_telemetry_updatePing_downloaded_ready.js
new file mode 100644
index 0000000000..01070dd1a6
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_telemetry_updatePing_downloaded_ready.js
@@ -0,0 +1,69 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+ChromeUtils.import(
+ "resource://testing-common/TelemetryArchiveTesting.jsm",
+ this
+);
+
+/**
+ * Test that UpdatePing telemetry with a payload reason of ready is sent for a
+ * staged update.
+ *
+ * Please note that this is really a Telemetry test, not an
+ * "update UI" test like the rest of the tests in this directory.
+ * This test does not live in toolkit/components/telemetry/tests to prevent
+ * duplicating the code for all the test dependencies. Unfortunately, due
+ * to a limitation in the build system, we were not able to simply reference
+ * the dependencies as "support-files" in the test manifest.
+ */
+add_task(async function telemetry_updatePing_ready() {
+ let archiveChecker = new TelemetryArchiveTesting.Checker();
+ await archiveChecker.promiseInit();
+
+ let updateParams = "";
+ await runTelemetryUpdateTest(updateParams, "update-downloaded");
+
+ // We cannot control when the ping will be generated/archived after we trigger
+ // an update, so let's make sure to have one before moving on with validation.
+ let updatePing;
+ await TestUtils.waitForCondition(
+ async function() {
+ // Check that the ping made it into the Telemetry archive.
+ // The test data is defined in ../data/sharedUpdateXML.js
+ updatePing = await archiveChecker.promiseFindPing("update", [
+ [["payload", "reason"], "ready"],
+ [["payload", "targetBuildId"], "20080811053724"],
+ ]);
+ return !!updatePing;
+ },
+ "Make sure the ping is generated before trying to validate it.",
+ 500,
+ 100
+ );
+
+ ok(updatePing, "The 'update' ping must be correctly sent.");
+
+ // We don't know the exact value for the other fields, so just check
+ // that they're available.
+ for (let f of ["targetVersion", "targetChannel", "targetDisplayVersion"]) {
+ ok(
+ f in updatePing.payload,
+ `${f} must be available in the update ping payload.`
+ );
+ ok(
+ typeof updatePing.payload[f] == "string",
+ `${f} must have the correct format.`
+ );
+ }
+
+ // Also make sure that the ping contains both a client id and an
+ // environment section.
+ ok("clientId" in updatePing, "The update ping must report a client id.");
+ ok(
+ "environment" in updatePing,
+ "The update ping must report the environment."
+ );
+});
diff --git a/toolkit/mozapps/update/tests/browser/browser_telemetry_updatePing_staged_ready.js b/toolkit/mozapps/update/tests/browser/browser_telemetry_updatePing_staged_ready.js
new file mode 100644
index 0000000000..4d87fab5e7
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_telemetry_updatePing_staged_ready.js
@@ -0,0 +1,73 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+ChromeUtils.import(
+ "resource://testing-common/TelemetryArchiveTesting.jsm",
+ this
+);
+
+/**
+ * Test that UpdatePing telemetry with a payload reason of ready is sent for a
+ * staged update.
+ *
+ * Please note that this is really a Telemetry test, not an
+ * "update UI" test like the rest of the tests in this directory.
+ * This test does not live in toolkit/components/telemetry/tests to prevent
+ * duplicating the code for all the test dependencies. Unfortunately, due
+ * to a limitation in the build system, we were not able to simply reference
+ * the dependencies as "support-files" in the test manifest.
+ */
+add_task(async function telemetry_updatePing_ready() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_STAGING_ENABLED, true]],
+ });
+
+ let archiveChecker = new TelemetryArchiveTesting.Checker();
+ await archiveChecker.promiseInit();
+
+ let updateParams = "";
+ await runTelemetryUpdateTest(updateParams, "update-staged");
+
+ // We cannot control when the ping will be generated/archived after we trigger
+ // an update, so let's make sure to have one before moving on with validation.
+ let updatePing;
+ await TestUtils.waitForCondition(
+ async function() {
+ // Check that the ping made it into the Telemetry archive.
+ // The test data is defined in ../data/sharedUpdateXML.js
+ updatePing = await archiveChecker.promiseFindPing("update", [
+ [["payload", "reason"], "ready"],
+ [["payload", "targetBuildId"], "20080811053724"],
+ ]);
+ return !!updatePing;
+ },
+ "Make sure the ping is generated before trying to validate it.",
+ 500,
+ 100
+ );
+
+ ok(updatePing, "The 'update' ping must be correctly sent.");
+
+ // We don't know the exact value for the other fields, so just check
+ // that they're available.
+ for (let f of ["targetVersion", "targetChannel", "targetDisplayVersion"]) {
+ ok(
+ f in updatePing.payload,
+ `${f} must be available in the update ping payload.`
+ );
+ ok(
+ typeof updatePing.payload[f] == "string",
+ `${f} must have the correct format.`
+ );
+ }
+
+ // Also make sure that the ping contains both a client id and an
+ // environment section.
+ ok("clientId" in updatePing, "The update ping must report a client id.");
+ ok(
+ "environment" in updatePing,
+ "The update ping must report the environment."
+ );
+});
diff --git a/toolkit/mozapps/update/tests/browser/downloadPage.html b/toolkit/mozapps/update/tests/browser/downloadPage.html
new file mode 100644
index 0000000000..4810e2e0d6
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/downloadPage.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Download page</title>
+ <meta charset="utf-8">
+</head>
+<body>
+<!-- just use simple.mar since we have it available and it will result in a download dialog -->
+<a id="download-link" href="http://example.com/browser/browser/base/content/test/appUpdate/simple.mar" data-link-type="download">
+ Download
+</a>
+</body>
+</html>
diff --git a/toolkit/mozapps/update/tests/browser/head.js b/toolkit/mozapps/update/tests/browser/head.js
new file mode 100644
index 0000000000..7f77ad44df
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/head.js
@@ -0,0 +1,1189 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const { AppConstants } = ChromeUtils.import(
+ "resource://gre/modules/AppConstants.jsm"
+);
+
+ChromeUtils.defineModuleGetter(
+ this,
+ "AppMenuNotifications",
+ "resource://gre/modules/AppMenuNotifications.jsm"
+);
+ChromeUtils.defineModuleGetter(
+ this,
+ "DownloadUtils",
+ "resource://gre/modules/DownloadUtils.jsm"
+);
+ChromeUtils.defineModuleGetter(
+ this,
+ "UpdateListener",
+ "resource://gre/modules/UpdateListener.jsm"
+);
+const { XPIInstall } = ChromeUtils.import(
+ "resource://gre/modules/addons/XPIInstall.jsm"
+);
+
+const BIN_SUFFIX = AppConstants.platform == "win" ? ".exe" : "";
+const FILE_UPDATER_BIN =
+ "updater" + (AppConstants.platform == "macosx" ? ".app" : BIN_SUFFIX);
+const FILE_UPDATER_BIN_BAK = FILE_UPDATER_BIN + ".bak";
+
+const LOG_FUNCTION = info;
+
+const MAX_UPDATE_COPY_ATTEMPTS = 10;
+
+const DATA_URI_SPEC =
+ "chrome://mochitests/content/browser/toolkit/mozapps/update/tests/browser/";
+/* import-globals-from testConstants.js */
+Services.scriptloader.loadSubScript(DATA_URI_SPEC + "testConstants.js", this);
+
+var gURLData = URL_HOST + "/" + REL_PATH_DATA;
+const URL_MANUAL_UPDATE = gURLData + "downloadPage.html";
+
+const gBadSizeResult = Cr.NS_ERROR_UNEXPECTED.toString();
+
+/* import-globals-from ../data/shared.js */
+Services.scriptloader.loadSubScript(DATA_URI_SPEC + "shared.js", this);
+
+let gOriginalUpdateAutoValue = null;
+
+// Some elements append a trailing /. After the chrome tests are removed this
+// code can be changed so URL_HOST already has a trailing /.
+const gDetailsURL = URL_HOST + "/";
+const gDefaultWhatsNewURL = URL_HTTP_UPDATE_SJS + "?uiURL=DETAILS";
+
+// Set to true to log additional information for debugging. To log additional
+// information for individual tests set gDebugTest to false here and to true
+// globally in the test.
+gDebugTest = false;
+
+// This is to accommodate the TV task which runs the tests with --verify.
+requestLongerTimeout(10);
+
+/**
+ * Common tasks to perform for all tests before each one has started.
+ */
+add_task(async function setupTestCommon() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ [PREF_APP_UPDATE_BADGEWAITTIME, 1800],
+ [PREF_APP_UPDATE_DOWNLOAD_ATTEMPTS, 0],
+ [PREF_APP_UPDATE_DOWNLOAD_MAXATTEMPTS, 2],
+ [PREF_APP_UPDATE_LOG, gDebugTest],
+ [PREF_APP_UPDATE_PROMPTWAITTIME, 3600],
+ [PREF_APP_UPDATE_SERVICE_ENABLED, false],
+ // Disable activity stream to prevent errors when opening pages during
+ // TV runs. See bug 1548422 for an example.
+ ["browser.library.activity-stream.enabled", false],
+ ],
+ });
+
+ // We need to keep the update sync manager from thinking two instances are
+ // running because of the mochitest parent instance, which means we need to
+ // override the directory service with a fake executable path and then reset
+ // the lock. But leaving the directory service overridden causes problems for
+ // these tests, so we need to restore the real service immediately after.
+ // To form the path, we'll use the real executable path with a token appended
+ // (the path needs to be absolute, but not to point to a real file).
+ // This block is loosely copied from adjustGeneralPaths() in another update
+ // test file, xpcshellUtilsAUS.js, but this is a much more limited version;
+ // it's been copied here both because the full function is overkill and also
+ // because making it general enough to run in both xpcshell and mochitest
+ // would have been unreasonably difficult.
+ let exePath = Services.dirsvc.get(XRE_EXECUTABLE_FILE, Ci.nsIFile);
+ let dirProvider = {
+ getFile: function AGP_DP_getFile(aProp, aPersistent) {
+ // Set the value of persistent to false so when this directory provider is
+ // unregistered it will revert back to the original provider.
+ aPersistent.value = false;
+ switch (aProp) {
+ case XRE_EXECUTABLE_FILE:
+ exePath.append("browser-test");
+ return exePath;
+ }
+ return null;
+ },
+ QueryInterface: ChromeUtils.generateQI(["nsIDirectoryServiceProvider"]),
+ };
+ let ds = Services.dirsvc.QueryInterface(Ci.nsIDirectoryService);
+ ds.QueryInterface(Ci.nsIProperties).undefine(XRE_EXECUTABLE_FILE);
+ ds.registerProvider(dirProvider);
+
+ let syncManager = Cc["@mozilla.org/updates/update-sync-manager;1"].getService(
+ Ci.nsIUpdateSyncManager
+ );
+ syncManager.resetLock();
+
+ ds.unregisterProvider(dirProvider);
+
+ setUpdateTimerPrefs();
+ reloadUpdateManagerData(true);
+ removeUpdateFiles(true);
+ UpdateListener.reset();
+ AppMenuNotifications.removeNotification(/.*/);
+ // Most app update mochitest-browser-chrome tests expect auto update to be
+ // enabled. Those that don't will explicitly change this.
+ await setAppUpdateAutoEnabledHelper(true);
+});
+
+/**
+ * Common tasks to perform for all tests after each one has finished.
+ */
+registerCleanupFunction(async () => {
+ AppMenuNotifications.removeNotification(/.*/);
+ gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "");
+ gEnv.set("MOZ_TEST_SLOW_SKIP_UPDATE_STAGE", "");
+ gEnv.set("MOZ_TEST_STAGING_ERROR", "");
+ UpdateListener.reset();
+ AppMenuNotifications.removeNotification(/.*/);
+ reloadUpdateManagerData(true);
+ // Pass false when the log files are needed for troubleshooting the tests.
+ removeUpdateFiles(true);
+ // Always try to restore the original updater files. If none of the updater
+ // backup files are present then this is just a no-op.
+ await finishTestRestoreUpdaterBackup();
+ // Reset the update lock once again so that we know the lock we're
+ // interested in here will be closed properly (normally that happens during
+ // XPCOM shutdown, but that isn't consistent during tests).
+ let syncManager = Cc["@mozilla.org/updates/update-sync-manager;1"].getService(
+ Ci.nsIUpdateSyncManager
+ );
+ syncManager.resetLock();
+});
+
+/**
+ * Overrides the add-ons manager language pack staging with a mocked version.
+ * The returned promise resolves when language pack staging begins returning an
+ * object with the new appVersion and platformVersion and functions to resolve
+ * or reject the install.
+ */
+function mockLangpackInstall() {
+ let original = XPIInstall.stageLangpacksForAppUpdate;
+ registerCleanupFunction(() => {
+ XPIInstall.stageLangpacksForAppUpdate = original;
+ });
+
+ let stagingCall = PromiseUtils.defer();
+ XPIInstall.stageLangpacksForAppUpdate = (appVersion, platformVersion) => {
+ let result = PromiseUtils.defer();
+ stagingCall.resolve({
+ appVersion,
+ platformVersion,
+ resolve: result.resolve,
+ reject: result.reject,
+ });
+
+ return result.promise;
+ };
+
+ return stagingCall.promise;
+}
+
+/**
+ * Creates and locks the app update write test file so it is possible to test
+ * when the user doesn't have write access to update. Since this is only
+ * possible on Windows the function throws when it is called on other platforms.
+ * This uses registerCleanupFunction to remove the lock and the file when the
+ * test completes.
+ *
+ * @throws If the function is called on a platform other than Windows.
+ */
+function lockWriteTestFile() {
+ if (AppConstants.platform != "win") {
+ throw new Error("Windows only test function called");
+ }
+ let file = getUpdateDirFile(FILE_UPDATE_TEST).QueryInterface(
+ Ci.nsILocalFileWin
+ );
+ // Remove the file if it exists just in case.
+ if (file.exists()) {
+ file.fileAttributesWin |= file.WFA_READWRITE;
+ file.fileAttributesWin &= ~file.WFA_READONLY;
+ file.remove(false);
+ }
+ file.create(file.NORMAL_FILE_TYPE, 0o444);
+ file.fileAttributesWin |= file.WFA_READONLY;
+ file.fileAttributesWin &= ~file.WFA_READWRITE;
+ registerCleanupFunction(() => {
+ file.fileAttributesWin |= file.WFA_READWRITE;
+ file.fileAttributesWin &= ~file.WFA_READONLY;
+ file.remove(false);
+ });
+}
+
+/**
+ * Closes the update mutex handle in nsUpdateService.js if it exists and then
+ * creates a new update mutex handle so the update code thinks there is another
+ * instance of the application handling updates.
+ *
+ * @throws If the function is called on a platform other than Windows.
+ */
+function setOtherInstanceHandlingUpdates() {
+ if (AppConstants.platform != "win") {
+ throw new Error("Windows only test function called");
+ }
+ gAUS.observe(null, "test-close-handle-update-mutex", "");
+ let handle = createMutex(getPerInstallationMutexName());
+ registerCleanupFunction(() => {
+ closeHandle(handle);
+ });
+}
+
+/**
+ * Gets the update version info for the update url parameters to send to
+ * app_update.sjs.
+ *
+ * @param aAppVersion (optional)
+ * The application version for the update snippet. If not specified the
+ * current application version will be used.
+ * @return The url parameters for the application and platform version to send
+ * to app_update.sjs.
+ */
+function getVersionParams(aAppVersion) {
+ let appInfo = Services.appinfo;
+ return "&appVersion=" + (aAppVersion ? aAppVersion : appInfo.version);
+}
+
+/**
+ * Prevent nsIUpdateTimerManager from notifying nsIApplicationUpdateService
+ * to check for updates by setting the app update last update time to the
+ * current time minus one minute in seconds and the interval time to 12 hours
+ * in seconds.
+ */
+function setUpdateTimerPrefs() {
+ let now = Math.round(Date.now() / 1000) - 60;
+ Services.prefs.setIntPref(PREF_APP_UPDATE_LASTUPDATETIME, now);
+ Services.prefs.setIntPref(PREF_APP_UPDATE_INTERVAL, 43200);
+}
+
+/*
+ * Sets the value of the App Auto Update setting and sets it back to the
+ * original value at the start of the test when the test finishes.
+ *
+ * @param enabled
+ * The value to set App Auto Update to.
+ */
+async function setAppUpdateAutoEnabledHelper(enabled) {
+ if (gOriginalUpdateAutoValue == null) {
+ gOriginalUpdateAutoValue = await UpdateUtils.getAppUpdateAutoEnabled();
+ registerCleanupFunction(async () => {
+ await UpdateUtils.setAppUpdateAutoEnabled(gOriginalUpdateAutoValue);
+ });
+ }
+ await UpdateUtils.setAppUpdateAutoEnabled(enabled);
+}
+
+/**
+ * Gets the specified button for the notification.
+ *
+ * @param win
+ * The window to get the notification button for.
+ * @param notificationId
+ * The ID of the notification to get the button for.
+ * @param button
+ * The anonid of the button to get.
+ * @return The button element.
+ */
+function getNotificationButton(win, notificationId, button) {
+ let notification = win.document.getElementById(
+ `appMenu-${notificationId}-notification`
+ );
+ ok(!notification.hidden, `${notificationId} notification is showing`);
+ return notification[button];
+}
+
+/**
+ * Ensures that the "What's new" link with the provided ID is displayed and
+ * matches the url parameter provided.
+ *
+ * @param win
+ * The window to get the "What's new" link for.
+ * @param id
+ * The ID of the "What's new" link element.
+ * @param url
+ * The URL to check against.
+ */
+function checkWhatsNewLink(win, id, url) {
+ let whatsNewLink = win.document.getElementById(id);
+ ok(!whatsNewLink.hidden, "What's new link is not hidden.");
+ is(whatsNewLink.href, url, `What's new link href should equal ${url}`);
+}
+
+/**
+ * For staging tests the test updater must be used and this restores the backed
+ * up real updater if it exists and tries again on failure since Windows debug
+ * builds at times leave the file in use. After success moveRealUpdater is
+ * called to continue the setup of the test updater.
+ */
+function setupTestUpdater() {
+ return (async function() {
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_STAGING_ENABLED)) {
+ try {
+ restoreUpdaterBackup();
+ } catch (e) {
+ logTestInfo(
+ "Attempt to restore the backed up updater failed... " +
+ "will try again, Exception: " +
+ e
+ );
+ await TestUtils.waitForTick();
+ await setupTestUpdater();
+ return;
+ }
+ await moveRealUpdater();
+ }
+ })();
+}
+
+/**
+ * Backs up the real updater and tries again on failure since Windows debug
+ * builds at times leave the file in use. After success it will call
+ * copyTestUpdater to continue the setup of the test updater.
+ */
+function moveRealUpdater() {
+ return (async function() {
+ try {
+ // Move away the real updater
+ let greBinDir = getGREBinDir();
+ let updater = greBinDir.clone();
+ updater.append(FILE_UPDATER_BIN);
+ updater.moveTo(greBinDir, FILE_UPDATER_BIN_BAK);
+
+ let greDir = getGREDir();
+ let updateSettingsIni = greDir.clone();
+ updateSettingsIni.append(FILE_UPDATE_SETTINGS_INI);
+ if (updateSettingsIni.exists()) {
+ updateSettingsIni.moveTo(greDir, FILE_UPDATE_SETTINGS_INI_BAK);
+ }
+
+ let precomplete = greDir.clone();
+ precomplete.append(FILE_PRECOMPLETE);
+ if (precomplete.exists()) {
+ precomplete.moveTo(greDir, FILE_PRECOMPLETE_BAK);
+ }
+ } catch (e) {
+ logTestInfo(
+ "Attempt to move the real updater out of the way failed... " +
+ "will try again, Exception: " +
+ e
+ );
+ await TestUtils.waitForTick();
+ await moveRealUpdater();
+ return;
+ }
+
+ await copyTestUpdater();
+ })();
+}
+
+/**
+ * Copies the test updater and tries again on failure since Windows debug builds
+ * at times leave the file in use.
+ */
+function copyTestUpdater(attempt = 0) {
+ return (async function() {
+ try {
+ // Copy the test updater
+ let greBinDir = getGREBinDir();
+ let testUpdaterDir = Services.dirsvc.get("CurWorkD", Ci.nsIFile);
+ let relPath = REL_PATH_DATA;
+ let pathParts = relPath.split("/");
+ for (let i = 0; i < pathParts.length; ++i) {
+ testUpdaterDir.append(pathParts[i]);
+ }
+
+ let testUpdater = testUpdaterDir.clone();
+ testUpdater.append(FILE_UPDATER_BIN);
+ testUpdater.copyToFollowingLinks(greBinDir, FILE_UPDATER_BIN);
+
+ let greDir = getGREDir();
+ let updateSettingsIni = greDir.clone();
+ updateSettingsIni.append(FILE_UPDATE_SETTINGS_INI);
+ writeFile(updateSettingsIni, UPDATE_SETTINGS_CONTENTS);
+
+ let precomplete = greDir.clone();
+ precomplete.append(FILE_PRECOMPLETE);
+ writeFile(precomplete, PRECOMPLETE_CONTENTS);
+ } catch (e) {
+ if (attempt < MAX_UPDATE_COPY_ATTEMPTS) {
+ logTestInfo(
+ "Attempt to copy the test updater failed... " +
+ "will try again, Exception: " +
+ e
+ );
+ await TestUtils.waitForTick();
+ await copyTestUpdater(attempt++);
+ }
+ }
+ })();
+}
+
+/**
+ * Restores the updater and updater related file that if there a backup exists.
+ * This is called in setupTestUpdater before the backup of the real updater is
+ * done in case the previous test failed to restore the file when a test has
+ * finished. This is also called in finishTestRestoreUpdaterBackup to restore
+ * the files when a test finishes.
+ */
+function restoreUpdaterBackup() {
+ let greBinDir = getGREBinDir();
+ let updater = greBinDir.clone();
+ let updaterBackup = greBinDir.clone();
+ updater.append(FILE_UPDATER_BIN);
+ updaterBackup.append(FILE_UPDATER_BIN_BAK);
+ if (updaterBackup.exists()) {
+ if (updater.exists()) {
+ updater.remove(true);
+ }
+ updaterBackup.moveTo(greBinDir, FILE_UPDATER_BIN);
+ }
+
+ let greDir = getGREDir();
+ let updateSettingsIniBackup = greDir.clone();
+ updateSettingsIniBackup.append(FILE_UPDATE_SETTINGS_INI_BAK);
+ if (updateSettingsIniBackup.exists()) {
+ let updateSettingsIni = greDir.clone();
+ updateSettingsIni.append(FILE_UPDATE_SETTINGS_INI);
+ if (updateSettingsIni.exists()) {
+ updateSettingsIni.remove(false);
+ }
+ updateSettingsIniBackup.moveTo(greDir, FILE_UPDATE_SETTINGS_INI);
+ }
+
+ let precomplete = greDir.clone();
+ let precompleteBackup = greDir.clone();
+ precomplete.append(FILE_PRECOMPLETE);
+ precompleteBackup.append(FILE_PRECOMPLETE_BAK);
+ if (precompleteBackup.exists()) {
+ if (precomplete.exists()) {
+ precomplete.remove(false);
+ }
+ precompleteBackup.moveTo(greDir, FILE_PRECOMPLETE);
+ } else if (precomplete.exists()) {
+ if (readFile(precomplete) == PRECOMPLETE_CONTENTS) {
+ precomplete.remove(false);
+ }
+ }
+}
+
+/**
+ * When a test finishes this will repeatedly attempt to restore the real updater
+ * and the other files for the updater if a backup of the file exists.
+ */
+function finishTestRestoreUpdaterBackup() {
+ return (async function() {
+ try {
+ // Windows debug builds keep the updater file in use for a short period of
+ // time after the updater process exits.
+ restoreUpdaterBackup();
+ } catch (e) {
+ logTestInfo(
+ "Attempt to restore the backed up updater failed... " +
+ "will try again, Exception: " +
+ e
+ );
+
+ await TestUtils.waitForTick();
+ await finishTestRestoreUpdaterBackup();
+ }
+ })();
+}
+
+/**
+ * Waits for the About Dialog to load.
+ *
+ * @return A promise that returns the domWindow for the About Dialog and
+ * resolves when the About Dialog loads.
+ */
+function waitForAboutDialog() {
+ return new Promise(resolve => {
+ var listener = {
+ onOpenWindow: aXULWindow => {
+ debugDump("About dialog shown...");
+ Services.wm.removeListener(listener);
+
+ async function aboutDialogOnLoad() {
+ domwindow.removeEventListener("load", aboutDialogOnLoad, true);
+ let chromeURI = "chrome://browser/content/aboutDialog.xhtml";
+ is(
+ domwindow.document.location.href,
+ chromeURI,
+ "About dialog appeared"
+ );
+ resolve(domwindow);
+ }
+
+ var domwindow = aXULWindow.docShell.domWindow;
+ domwindow.addEventListener("load", aboutDialogOnLoad, true);
+ },
+ onCloseWindow: aXULWindow => {},
+ };
+
+ Services.wm.addListener(listener);
+ openAboutDialog();
+ });
+}
+
+/**
+ * Return the first UpdatePatch with the given type.
+ *
+ * @param type
+ * The type of the patch ("complete" or "partial")
+ * @param update
+ * The nsIUpdate to select a patch from.
+ * @return A nsIUpdatePatch object matching the type specified
+ */
+function getPatchOfType(type, update) {
+ if (update) {
+ for (let i = 0; i < update.patchCount; ++i) {
+ let patch = update.getPatchAt(i);
+ if (patch && patch.type == type) {
+ return patch;
+ }
+ }
+ }
+ return null;
+}
+
+/**
+ * Runs a Doorhanger update test. This will set various common prefs for
+ * updating and runs the provided list of steps.
+ *
+ * @param params
+ * An object containing parameters used to run the test.
+ * @param steps
+ * An array of test steps to perform. A step will either be an object
+ * containing expected conditions and actions or a function to call.
+ * @return A promise which will resolve once all of the steps have been run.
+ */
+function runDoorhangerUpdateTest(params, steps) {
+ function processDoorhangerStep(step) {
+ if (typeof step == "function") {
+ return step();
+ }
+
+ const { notificationId, button, checkActiveUpdate, pageURLs } = step;
+ return (async function() {
+ if (!params.popupShown && !PanelUI.isNotificationPanelOpen) {
+ await BrowserTestUtils.waitForEvent(
+ PanelUI.notificationPanel,
+ "popupshown"
+ );
+ }
+ const shownNotificationId = AppMenuNotifications.activeNotification.id;
+ is(
+ shownNotificationId,
+ notificationId,
+ "The right notification showed up."
+ );
+
+ if (checkActiveUpdate) {
+ let activeUpdate =
+ checkActiveUpdate.state == STATE_DOWNLOADING
+ ? gUpdateManager.downloadingUpdate
+ : gUpdateManager.readyUpdate;
+ ok(!!activeUpdate, "There should be an active update");
+ is(
+ activeUpdate.state,
+ checkActiveUpdate.state,
+ `The active update state should equal ${checkActiveUpdate.state}`
+ );
+ } else {
+ ok(
+ !gUpdateManager.downloadingUpdate,
+ "There should not be a downloading update"
+ );
+ ok(!gUpdateManager.readyUpdate, "There should not be a ready update");
+ }
+
+ if (pageURLs && pageURLs.whatsNew !== undefined) {
+ checkWhatsNewLink(
+ window,
+ `${notificationId}-whats-new`,
+ pageURLs.whatsNew
+ );
+ }
+
+ let buttonEl = getNotificationButton(window, notificationId, button);
+ buttonEl.click();
+
+ if (pageURLs && pageURLs.manual !== undefined) {
+ await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
+ is(
+ gBrowser.selectedBrowser.currentURI.spec,
+ pageURLs.manual,
+ `The page's url should equal ${pageURLs.manual}`
+ );
+ gBrowser.removeTab(gBrowser.selectedTab);
+ }
+ })();
+ }
+
+ return (async function() {
+ if (params.slowStaging) {
+ gEnv.set("MOZ_TEST_SLOW_SKIP_UPDATE_STAGE", "1");
+ } else {
+ gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "1");
+ }
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ [PREF_APP_UPDATE_DISABLEDFORTESTING, false],
+ [PREF_APP_UPDATE_URL_DETAILS, gDetailsURL],
+ [PREF_APP_UPDATE_URL_MANUAL, URL_MANUAL_UPDATE],
+ ],
+ });
+
+ await setupTestUpdater();
+
+ let queryString = params.queryString ? params.queryString : "";
+ let updateURL =
+ URL_HTTP_UPDATE_SJS +
+ "?detailsURL=" +
+ gDetailsURL +
+ queryString +
+ getVersionParams(params.version);
+ setUpdateURL(updateURL);
+
+ if (params.checkAttempts) {
+ // Perform a background check doorhanger test.
+ executeSoon(() => {
+ (async function() {
+ gAUS.checkForBackgroundUpdates();
+ for (var i = 0; i < params.checkAttempts - 1; i++) {
+ await waitForEvent("update-error", "check-attempt-failed");
+ gAUS.checkForBackgroundUpdates();
+ }
+ })();
+ });
+ } else {
+ // Perform a startup processing doorhanger test.
+ writeStatusFile(STATE_FAILED_CRC_ERROR);
+ writeUpdatesToXMLFile(getLocalUpdatesXMLString(params.updates), true);
+ reloadUpdateManagerData();
+ testPostUpdateProcessing();
+ }
+
+ for (let step of steps) {
+ await processDoorhangerStep(step);
+ }
+ })();
+}
+
+/**
+ * Runs an About Dialog update test. This will set various common prefs for
+ * updating and runs the provided list of steps.
+ *
+ * @param params
+ * An object containing parameters used to run the test.
+ * @param steps
+ * An array of test steps to perform. A step will either be an object
+ * containing expected conditions and actions or a function to call.
+ * @return A promise which will resolve once all of the steps have been run.
+ */
+function runAboutDialogUpdateTest(params, steps) {
+ let aboutDialog;
+ function processAboutDialogStep(step) {
+ if (typeof step == "function") {
+ return step(aboutDialog);
+ }
+
+ const { panelId, checkActiveUpdate, continueFile, downloadInfo } = step;
+ return (async function() {
+ let updateDeck = aboutDialog.document.getElementById("updateDeck");
+ await TestUtils.waitForCondition(
+ () =>
+ updateDeck.selectedPanel && updateDeck.selectedPanel.id == panelId,
+ "Waiting for the expected panel ID: " + panelId,
+ 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);
+ });
+ let selectedPanel = updateDeck.selectedPanel;
+ is(selectedPanel.id, panelId, "The panel ID should equal " + panelId);
+
+ if (checkActiveUpdate) {
+ let activeUpdate =
+ checkActiveUpdate.state == STATE_DOWNLOADING
+ ? gUpdateManager.downloadingUpdate
+ : gUpdateManager.readyUpdate;
+ ok(!!activeUpdate, "There should be an active update");
+ is(
+ activeUpdate.state,
+ checkActiveUpdate.state,
+ "The active update state should equal " + checkActiveUpdate.state
+ );
+ } else {
+ ok(
+ !gUpdateManager.downloadingUpdate,
+ "There should not be a downloading update"
+ );
+ ok(!gUpdateManager.readyUpdate, "There should not be a ready 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,
+ gUpdateManager.downloadingUpdate
+ );
+ // 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);
+ });
+ is(
+ "" + patch.getProperty(resultName),
+ data[resultName],
+ "The patch property " +
+ resultName +
+ " value should equal " +
+ data[resultName]
+ );
+
+ // Check the download status text. It should be something like,
+ // "1.4 of 1.4 KB".
+ let expectedText = DownloadUtils.getTransferTotal(
+ data[resultName] == gBadSizeResult ? 0 : patch.size,
+ patch.size
+ );
+ Assert.ok(
+ expectedText,
+ "Sanity check: Expected download status text should be non-empty"
+ );
+ Assert.equal(
+ aboutDialog.downloadStatus.textContent,
+ expectedText,
+ "Download status text should be correct"
+ );
+ }
+ }
+ } else if (continueFile) {
+ await continueFileHandler(continueFile);
+ }
+
+ let linkPanels = ["downloadFailed", "manualUpdate", "unsupportedSystem"];
+ if (linkPanels.includes(panelId)) {
+ // The unsupportedSystem panel uses the update's detailsURL and the
+ // downloadFailed and manualUpdate panels use the app.update.url.manual
+ // preference.
+ let link = selectedPanel.querySelector("label.text-link");
+ is(
+ link.href,
+ gDetailsURL,
+ `The panel's link href should equal ${gDetailsURL}`
+ );
+ }
+
+ let buttonPanels = ["downloadAndInstall", "apply"];
+ if (buttonPanels.includes(panelId)) {
+ let buttonEl = selectedPanel.querySelector("button");
+ await TestUtils.waitForCondition(
+ () => aboutDialog.document.activeElement == buttonEl,
+ "The button should receive focus"
+ );
+ ok(!buttonEl.disabled, "The button should be enabled");
+ // Don't click the button on the apply panel since this will restart the
+ // application.
+ if (panelId != "apply") {
+ buttonEl.click();
+ }
+ }
+ })();
+ }
+
+ return (async function() {
+ 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(params.version);
+ if (params.backgroundUpdate) {
+ setUpdateURL(updateURL);
+ gAUS.checkForBackgroundUpdates();
+ if (params.continueFile) {
+ await continueFileHandler(params.continueFile);
+ }
+ if (params.waitForUpdateState) {
+ let whichUpdate =
+ params.waitForUpdateState == STATE_DOWNLOADING
+ ? "downloadingUpdate"
+ : "readyUpdate";
+ await TestUtils.waitForCondition(
+ () =>
+ gUpdateManager[whichUpdate] &&
+ gUpdateManager[whichUpdate].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.
+ is(
+ gUpdateManager[whichUpdate].state,
+ params.waitForUpdateState,
+ "The update state value should equal " + params.waitForUpdateState
+ );
+ }
+ } else {
+ updateURL += "&slowUpdateCheck=1&useSlowDownloadMar=1";
+ setUpdateURL(updateURL);
+ }
+
+ aboutDialog = await waitForAboutDialog();
+ registerCleanupFunction(() => {
+ aboutDialog.close();
+ });
+
+ for (let step of steps) {
+ await processAboutDialogStep(step);
+ }
+ })();
+}
+
+/**
+ * Runs an about:preferences update test. This will set various common prefs for
+ * updating and runs the provided list of steps.
+ *
+ * @param params
+ * An object containing parameters used to run the test.
+ * @param steps
+ * An array of test steps to perform. A step will either be an object
+ * containing expected conditions and actions or a function to call.
+ * @return A promise which will resolve once all of the steps have been run.
+ */
+function runAboutPrefsUpdateTest(params, steps) {
+ let tab;
+ function processAboutPrefsStep(step) {
+ if (typeof step == "function") {
+ return step(tab);
+ }
+
+ const { panelId, checkActiveUpdate, continueFile, downloadInfo } = step;
+ return (async function() {
+ await SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [{ panelId }],
+ async ({ panelId }) => {
+ let updateDeck = content.document.getElementById("updateDeck");
+ await ContentTaskUtils.waitForCondition(
+ () =>
+ updateDeck.selectedPanel &&
+ updateDeck.selectedPanel.id == panelId,
+ "Waiting for the expected panel ID: " + panelId,
+ 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. Use info here
+ // instead of logTestInfo since logTestInfo isn't available in the
+ // content task.
+ info(e);
+ });
+ is(
+ updateDeck.selectedPanel.id,
+ panelId,
+ "The panel ID should equal " + panelId
+ );
+ }
+ );
+
+ if (checkActiveUpdate) {
+ let activeUpdate =
+ checkActiveUpdate.state == STATE_DOWNLOADING
+ ? gUpdateManager.downloadingUpdate
+ : gUpdateManager.readyUpdate;
+ ok(!!activeUpdate, "There should be an active update");
+ is(
+ activeUpdate.state,
+ checkActiveUpdate.state,
+ "The active update state should equal " + checkActiveUpdate.state
+ );
+ } else {
+ ok(
+ !gUpdateManager.downloadingUpdate,
+ "There should not be a downloading update"
+ );
+ ok(!gUpdateManager.readyUpdate, "There should not be a ready 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,
+ gUpdateManager.downloadingUpdate
+ );
+ // 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);
+ });
+ is(
+ "" + patch.getProperty(resultName),
+ data[resultName],
+ "The patch property " +
+ resultName +
+ " value should equal " +
+ data[resultName]
+ );
+
+ // Check the download status text. It should be something like,
+ // "Downloading update — 1.4 of 1.4 KB". We check only the second
+ // part to make sure that the downloaded size is updated correctly.
+ let actualText = await SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [],
+ () => content.document.getElementById("downloading").textContent
+ );
+ let expectedSuffix = DownloadUtils.getTransferTotal(
+ data[resultName] == gBadSizeResult ? 0 : patch.size,
+ patch.size
+ );
+ Assert.ok(
+ expectedSuffix,
+ "Sanity check: Expected download status text should be non-empty"
+ );
+ Assert.ok(
+ actualText.endsWith(expectedSuffix),
+ "Download status text should end as expected: " +
+ JSON.stringify({ actualText, expectedSuffix })
+ );
+ }
+ }
+ } else if (continueFile) {
+ await continueFileHandler(continueFile);
+ }
+
+ await SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [{ panelId, gDetailsURL }],
+ async ({ panelId, gDetailsURL }) => {
+ let linkPanels = [
+ "downloadFailed",
+ "manualUpdate",
+ "unsupportedSystem",
+ ];
+ if (linkPanels.includes(panelId)) {
+ let selectedPanel = content.document.getElementById("updateDeck")
+ .selectedPanel;
+ // The unsupportedSystem panel uses the update's detailsURL and the
+ // downloadFailed and manualUpdate panels use the app.update.url.manual
+ // preference.
+ let selector = "label.text-link";
+ // The downloadFailed panel in about:preferences uses an anchor
+ // instead of a label for the link.
+ if (selectedPanel.id == "downloadFailed") {
+ selector = "a.text-link";
+ }
+ let link = selectedPanel.querySelector(selector);
+ is(
+ link.href,
+ gDetailsURL,
+ `The panel's link href should equal ${gDetailsURL}`
+ );
+ }
+
+ let buttonPanels = ["downloadAndInstall", "apply"];
+ if (buttonPanels.includes(panelId)) {
+ let selectedPanel = content.document.getElementById("updateDeck")
+ .selectedPanel;
+ let buttonEl = selectedPanel.querySelector("button");
+ // Note: The about:preferences doesn't focus the button like the
+ // About Dialog does.
+ ok(!buttonEl.disabled, "The button should be enabled");
+ // Don't click the button on the apply panel since this will restart
+ // the application.
+ if (selectedPanel.id != "apply") {
+ buttonEl.click();
+ }
+ }
+ }
+ );
+ })();
+ }
+
+ return (async function() {
+ 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(params.version);
+ if (params.backgroundUpdate) {
+ setUpdateURL(updateURL);
+ gAUS.checkForBackgroundUpdates();
+ if (params.continueFile) {
+ await continueFileHandler(params.continueFile);
+ }
+ if (params.waitForUpdateState) {
+ // Wait until the update state equals the expected value before
+ // displaying the UI.
+ let whichUpdate =
+ params.waitForUpdateState == STATE_DOWNLOADING
+ ? "downloadingUpdate"
+ : "readyUpdate";
+ await TestUtils.waitForCondition(
+ () =>
+ gUpdateManager[whichUpdate] &&
+ gUpdateManager[whichUpdate].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);
+ });
+ is(
+ gUpdateManager[whichUpdate].state,
+ params.waitForUpdateState,
+ "The update state value should equal " + params.waitForUpdateState
+ );
+ }
+ } else {
+ updateURL += "&slowUpdateCheck=1&useSlowDownloadMar=1";
+ setUpdateURL(updateURL);
+ }
+
+ tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:preferences"
+ );
+ registerCleanupFunction(async () => {
+ await BrowserTestUtils.removeTab(tab);
+ });
+
+ // Scroll the UI into view so it is easier to troubleshoot tests.
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
+ content.document.getElementById("updatesCategory").scrollIntoView();
+ });
+
+ for (let step of steps) {
+ await processAboutPrefsStep(step);
+ }
+ })();
+}
+
+/**
+ * Removes the modified update-settings.ini file so the updater will fail to
+ * stage an update.
+ */
+function removeUpdateSettingsIni() {
+ if (Services.prefs.getBoolPref(PREF_APP_UPDATE_STAGING_ENABLED)) {
+ let greDir = getGREDir();
+ let updateSettingsIniBak = greDir.clone();
+ updateSettingsIniBak.append(FILE_UPDATE_SETTINGS_INI_BAK);
+ if (updateSettingsIniBak.exists()) {
+ let updateSettingsIni = greDir.clone();
+ updateSettingsIni.append(FILE_UPDATE_SETTINGS_INI);
+ updateSettingsIni.remove(false);
+ }
+ }
+}
+
+/**
+ * Runs a telemetry update test. This will set various common prefs for
+ * updating, checks for an update, and waits for the specified observer
+ * notification.
+ *
+ * @param updateParams
+ * Params which will be sent to app_update.sjs.
+ * @param event
+ * The observer notification to wait for before proceeding.
+ * @param stageFailure (optional)
+ * Whether to force a staging failure by removing the modified
+ * update-settings.ini file.
+ * @return A promise which will resolve after the .
+ */
+function runTelemetryUpdateTest(updateParams, event, stageFailure = false) {
+ return (async function() {
+ Services.telemetry.clearScalars();
+ gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "1");
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREF_APP_UPDATE_DISABLEDFORTESTING, false]],
+ });
+
+ await setupTestUpdater();
+
+ if (stageFailure) {
+ removeUpdateSettingsIni();
+ }
+
+ let updateURL =
+ URL_HTTP_UPDATE_SJS +
+ "?detailsURL=" +
+ gDetailsURL +
+ updateParams +
+ getVersionParams();
+ setUpdateURL(updateURL);
+ gAUS.checkForBackgroundUpdates();
+ await waitForEvent(event);
+ })();
+}
diff --git a/toolkit/mozapps/update/tests/browser/testConstants.js b/toolkit/mozapps/update/tests/browser/testConstants.js
new file mode 100644
index 0000000000..915391054b
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/testConstants.js
@@ -0,0 +1,7 @@
+const REL_PATH_DATA = "browser/toolkit/mozapps/update/tests/browser/";
+const URL_HOST = "http://127.0.0.1:8888";
+const URL_PATH_UPDATE_XML = "/" + REL_PATH_DATA + "app_update.sjs";
+const URL_HTTP_UPDATE_SJS = URL_HOST + URL_PATH_UPDATE_XML;
+const CONTINUE_CHECK = "continueCheck";
+const CONTINUE_DOWNLOAD = "continueDownload";
+const CONTINUE_STAGING = "continueStaging";