Commit bbfcdc85 authored by Mark Banner's avatar Mark Banner
Browse files

Bug 1607498 - If an update via the about dialog is cancelled due to staying on...

Bug 1607498 - If an update via the about dialog is cancelled due to staying on a page, ensure the dialog is reset to the apply state. r=application-update-reviewers,bytesized

Differential Revision: https://phabricator.services.mozilla.com/D146805
parent c3e54c97
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -245,9 +245,14 @@ appUpdater.prototype = {
      return;
    }

    Services.startup.quit(
    if (
      !Services.startup.quit(
        Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart
    );
      )
    ) {
      // Either the user or the hidden window aborted the quit process.
      gAppUpdater.selectPanel("apply");
    }
  },

  /**
+2 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ prefs =
[browser_aboutDialog_bc_downloaded_staging.js]
[browser_aboutDialog_bc_downloaded_stagingFailure.js]
[browser_aboutDialog_bc_downloaded_staged.js]
[browser_aboutDialog_fc_apply_blocked.js]
[browser_aboutDialog_fc_downloadAuto.js]
skip-if = tsan # Bug 1683730
[browser_aboutDialog_fc_downloadAuto_staging.js]
@@ -41,6 +42,7 @@ reason = Windows only feature.
[browser_aboutDialog_bc_multiUpdate.js]

# about:preferences Application Update Tests
[browser_aboutPrefs_fc_apply_blocked.js]
[browser_aboutPrefs_bc_downloading.js]
[browser_aboutPrefs_bc_downloading_staging.js]
[browser_aboutPrefs_bc_downloaded.js]
+94 −0
Original line number Diff line number Diff line
/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

const { PromptTestUtils } = ChromeUtils.import(
  "resource://testing-common/PromptTestUtils.jsm"
);

const BUILDER_URL = "https://example.com/document-builder.sjs?html=";
const PAGE_MARKUP = `
<html>
<head>
  <script>
    window.onbeforeunload = function() {
      return true;
    };
  </script>
</head>
<body>TEST PAGE</body>
</html>
`;
const TEST_URL = BUILDER_URL + encodeURI(PAGE_MARKUP);

add_setup(async () => {
  await SpecialPowers.pushPrefEnv({
    set: [["dom.require_user_interaction_for_beforeunload", false]],
  });
});

// Test for About Dialog foreground check for updates
// and apply but restart is blocked by a page.
add_task(async function aboutDialog_foregroundCheck_apply_blocked() {
  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);

  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 aboutDialog;
  let handlePromise = (async () => {
    let dialog = await PromptTestUtils.waitForPrompt(window, {
      modalType: Ci.nsIPrompt.MODAL_TYPE_CONTENT,
      promptType: "confirmEx",
    });
    Assert.equal(
      aboutDialog.gAppUpdater.selectedPanel.id,
      "restarting",
      "The restarting panel should be displayed"
    );

    await PromptTestUtils.handlePrompt(dialog, { buttonNumClick: 1 });
  })();

  // 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 getAboutDialogHandle(dialog) {
      aboutDialog = dialog;
    },
    {
      panelId: "apply",
      checkActiveUpdate: { state: STATE_PENDING },
      continueFile: null,
      forceApply: true,
    },
    async function ensureDialogHasBeenCanceled() {
      await handlePromise;
    },
    // A final check to ensure that we are back in the apply state.
    {
      panelId: "apply",
      checkActiveUpdate: { state: STATE_PENDING },
      continueFile: null,
    },
  ]);

  BrowserTestUtils.removeTab(tab, { skipPermitUnload: true });
});
+96 −0
Original line number Diff line number Diff line
/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

const { PromptTestUtils } = ChromeUtils.import(
  "resource://testing-common/PromptTestUtils.jsm"
);

const BUILDER_URL = "https://example.com/document-builder.sjs?html=";
const PAGE_MARKUP = `
<html>
<head>
  <script>
    window.onbeforeunload = function() {
      return true;
    };
  </script>
</head>
<body>TEST PAGE</body>
</html>
`;
const TEST_URL = BUILDER_URL + encodeURI(PAGE_MARKUP);

add_setup(async () => {
  await SpecialPowers.pushPrefEnv({
    set: [["dom.require_user_interaction_for_beforeunload", false]],
  });
});

// Test for About Dialog foreground check for updates
// and apply but restart is blocked by a page.
add_task(async function aboutDialog_foregroundCheck_apply_blocked() {
  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);

  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 prefsTab;
  let handlePromise = (async () => {
    let dialog = await PromptTestUtils.waitForPrompt(window, {
      modalType: Ci.nsIPrompt.MODAL_TYPE_CONTENT,
      promptType: "confirmEx",
    });
    await SpecialPowers.spawn(prefsTab.linkedBrowser, [], async () => {
      Assert.equal(
        content.gAppUpdater.selectedPanel.id,
        "restarting",
        "The restarting panel should be displayed"
      );
    });

    await PromptTestUtils.handlePrompt(dialog, { buttonNumClick: 1 });
  })();

  // Since the partial should be successful specify an invalid size for the
  // complete update.
  let params = { queryString: "&invalidCompleteSize=1&promptWaitTime=0" };
  await runAboutPrefsUpdateTest(params, [
    {
      panelId: "checkingForUpdates",
      checkActiveUpdate: null,
      continueFile: CONTINUE_CHECK,
    },
    {
      panelId: "downloading",
      checkActiveUpdate: { state: STATE_DOWNLOADING },
      continueFile: CONTINUE_DOWNLOAD,
      downloadInfo,
    },
    async function getPrefsTab(tab) {
      prefsTab = tab;
    },
    {
      panelId: "apply",
      checkActiveUpdate: { state: STATE_PENDING },
      continueFile: null,
      forceApply: true,
    },
    async function ensureDialogHasBeenCanceled() {
      await handlePromise;
    },
    // A final check to ensure that we are back in the apply state.
    {
      panelId: "apply",
      checkActiveUpdate: { state: STATE_PENDING },
      continueFile: null,
    },
  ]);

  BrowserTestUtils.removeTab(tab, { skipPermitUnload: true });
});
+18 −6
Original line number Diff line number Diff line
@@ -658,7 +658,13 @@ function runAboutDialogUpdateTest(params, steps) {
      return step(aboutDialog);
    }

    const { panelId, checkActiveUpdate, continueFile, downloadInfo } = step;
    const {
      panelId,
      checkActiveUpdate,
      continueFile,
      downloadInfo,
      forceApply,
    } = step;
    return (async function() {
      await TestUtils.waitForCondition(
        () =>
@@ -776,7 +782,7 @@ function runAboutDialogUpdateTest(params, steps) {
        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") {
        if (panelId != "apply" || forceApply) {
          buttonEl.click();
        }
      }
@@ -865,7 +871,13 @@ function runAboutPrefsUpdateTest(params, steps) {
      return step(tab);
    }

    const { panelId, checkActiveUpdate, continueFile, downloadInfo } = step;
    const {
      panelId,
      checkActiveUpdate,
      continueFile,
      downloadInfo,
      forceApply,
    } = step;
    return (async function() {
      await SpecialPowers.spawn(
        tab.linkedBrowser,
@@ -977,8 +989,8 @@ function runAboutPrefsUpdateTest(params, steps) {

      await SpecialPowers.spawn(
        tab.linkedBrowser,
        [{ panelId, gDetailsURL }],
        async ({ panelId, gDetailsURL }) => {
        [{ panelId, gDetailsURL, forceApply }],
        async ({ panelId, gDetailsURL, forceApply }) => {
          let linkPanels = [
            "downloadFailed",
            "manualUpdate",
@@ -1012,7 +1024,7 @@ function runAboutPrefsUpdateTest(params, steps) {
            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") {
            if (selectedPanel.id != "apply" || forceApply) {
              buttonEl.click();
            }
          }