Commit ffe70d35 authored by Carsten "Tomcat" Book's avatar Carsten "Tomcat" Book
Browse files

Merge mozilla-central to mozilla-inbound

parents 8d609a03 756cf900
Loading
Loading
Loading
Loading
+3 −49
Original line number Diff line number Diff line
@@ -2878,24 +2878,6 @@ var BrowserOnClick = {
    }
  },

  handleEvent(event) {
    if (!event.isTrusted || // Don't trust synthetic events
        event.button == 2) {
      return;
    }

    let originalTarget = event.originalTarget;
    let ownerDoc = originalTarget.ownerDocument;
    if (!ownerDoc) {
      return;
    }

    if (gMultiProcessBrowser &&
        ownerDoc.documentURI.toLowerCase() == "about:newtab") {
      this.onE10sAboutNewTab(event, ownerDoc);
    }
  },

  receiveMessage(msg) {
    switch (msg.name) {
      case "Browser:CertExceptionError":
@@ -3082,28 +3064,6 @@ var BrowserOnClick = {
    }
  },

  /**
   * This functions prevents navigation from happening directly through the <a>
   * link in about:newtab (which is loaded in the parent and therefore would load
   * the next page also in the parent) and instructs the browser to open the url
   * in the current tab which will make it update the remoteness of the tab.
   */
  onE10sAboutNewTab(event, ownerDoc) {
    let isTopFrame = (ownerDoc.defaultView.parent === ownerDoc.defaultView);
    if (!isTopFrame) {
      return;
    }

    let anchorTarget = event.originalTarget.parentNode;

    if (anchorTarget instanceof HTMLAnchorElement &&
        anchorTarget.classList.contains("newtab-link")) {
      event.preventDefault();
      let where = whereToOpenLink(event, false, false);
      openLinkIn(anchorTarget.href, where, { charset: ownerDoc.characterSet, referrerURI: ownerDoc.documentURIObject });
    }
  },

  ignoreWarningButton(reason) {
    // Allow users to override and continue through to the site,
    // but add a notify bar as a reminder, so that they don't lose
@@ -4924,13 +4884,9 @@ var TabsProgressListener = {
      }
    }

    // Attach a listener to watch for "click" events bubbling up from error
    // pages and other similar pages (like about:newtab). This lets us fix bugs
    // like 401575 which require error page UI to do privileged things, without
    // letting error pages have any privilege themselves.
    // We can't look for this during onLocationChange since at that point the
    // document URI is not yet the about:-uri of the error page.

    // We used to listen for clicks in the browser here, but when that
    // became unnecessary, removing the code below caused focus issues.
    // This code should be removed. Tracked in bug 1337794.
    let isRemoteBrowser = aBrowser.isRemoteBrowser;
    // We check isRemoteBrowser here to avoid requesting the doc CPOW
    let doc = isRemoteBrowser ? null : aWebProgress.DOMWindow.document;
@@ -4945,11 +4901,9 @@ var TabsProgressListener = {
      // STATE_STOP may be received twice for documents, thus store an
      // attribute to ensure handling it just once.
      doc.documentElement.setAttribute("hasBrowserHandlers", "true");
      aBrowser.addEventListener("click", BrowserOnClick, true);
      aBrowser.addEventListener("pagehide", function onPageHide(event) {
        if (event.target.defaultView.frameElement)
          return;
        aBrowser.removeEventListener("click", BrowserOnClick, true);
        aBrowser.removeEventListener("pagehide", onPageHide, true);
        if (event.target.documentElement)
          event.target.documentElement.removeAttribute("hasBrowserHandlers");
+5 −2
Original line number Diff line number Diff line
@@ -81,6 +81,8 @@ support-files =
  browser_webext_update2.xpi
  browser_webext_update_icon1.xpi
  browser_webext_update_icon2.xpi
  browser_webext_update_perms1.xpi
  browser_webext_update_perms2.xpi
  browser_webext_update.json
  !/image/test/mochitest/blue.png
  !/toolkit/content/tests/browser/common/mockTransfer.js
@@ -252,7 +254,8 @@ skip-if = os == "mac" # decoder doctor isn't implemented on osx
skip-if = true # browser_drag.js is disabled, as it needs to be updated for the new behavior from bug 320638.
[browser_extension_permissions.js]
[browser_extension_sideloading.js]
[browser_extension_update.js]
[browser_extension_update_background.js]
[browser_extension_update_interactive.js]
[browser_favicon_change.js]
[browser_favicon_change_not_in_document.js]
[browser_findbarClose.js]
@@ -349,7 +352,7 @@ skip-if = os == 'linux' # Bug 1304272
[browser_tab_detach_restore.js]
[browser_tab_drag_drop_perwindow.js]
[browser_tab_dragdrop.js]
skip-if = buildapp == 'mulet' || (e10s && (debug || asan)) # Bug 1312436
skip-if = buildapp == 'mulet' || (e10s && (debug || os == 'linux')) # Bug 1312436
[browser_tab_dragdrop2.js]
[browser_tabbar_big_widgets.js]
skip-if = os == "linux" || os == "mac" # No tabs in titlebar on linux
+26 −38
Original line number Diff line number Diff line
@@ -71,25 +71,6 @@ class MockProvider {
  }
}

function promiseViewLoaded(tab, viewid) {
  let win = tab.linkedBrowser.contentWindow;
  if (win.gViewController && !win.gViewController.isLoading &&
      win.gViewController.currentViewId == viewid) {
     return Promise.resolve();
  }

  return new Promise(resolve => {
    function listener() {
      if (win.gViewController.currentViewId != viewid) {
        return;
      }
      win.document.removeEventListener("ViewChanged", listener);
      resolve();
    }
    win.document.addEventListener("ViewChanged", listener);
  });
}

function promisePopupNotificationShown(name) {
  return new Promise(resolve => {
    function popupshown() {
@@ -169,6 +150,17 @@ add_task(function* () {
    ExtensionsUI.emit("change");
  });

  // Navigate away from the starting page to force about:addons to load
  // in a new tab during the tests below.
  gBrowser.selectedBrowser.loadURI("about:robots");
  yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);

  registerCleanupFunction(function*() {
    // Return to about:blank when we're done
    gBrowser.selectedBrowser.loadURI("about:blank");
    yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
  });

  let changePromise = new Promise(resolve => {
    ExtensionsUI.on("change", function listener() {
      ExtensionsUI.off("change", listener);
@@ -189,22 +181,20 @@ add_task(function* () {
  is(addons.children.length, 2, "Have 2 menu entries for sideloaded extensions");

  // Click the first sideloaded extension
  let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:addons");
  let popupPromise = promisePopupNotificationShown("addon-webext-permissions");
  addons.children[0].click();

  // about:addons should load and go to the list of extensions
  let tab = yield tabPromise;
  is(tab.linkedBrowser.currentURI.spec, "about:addons", "Newly opened tab is at about:addons");
  // When we get the permissions prompt, we should be at the extensions
  // list in about:addons
  let panel = yield popupPromise;
  is(gBrowser.currentURI.spec, "about:addons", "Foreground tab is at about:addons");

  const VIEW = "addons://list/extension";
  yield promiseViewLoaded(tab, VIEW);
  let win = tab.linkedBrowser.contentWindow;
  let win = gBrowser.selectedBrowser.contentWindow;
  ok(!win.gViewController.isLoading, "about:addons view is fully loaded");
  is(win.gViewController.currentViewId, VIEW, "about:addons is at extensions list");

  // Wait for the permission prompt and cancel it
  let panel = yield popupPromise;
  // Check the contents of the notification, then choose "Cancel"
  let icon = panel.getAttribute("icon");
  is(icon, ICON_URL, "Permissions notification has the addon icon");

@@ -219,7 +209,7 @@ add_task(function* () {
  is(addon1.userDisabled, true, "Addon 1 should still be disabled");
  is(addon2.userDisabled, true, "Addon 2 should still be disabled");

  yield BrowserTestUtils.removeTab(tab);
  yield BrowserTestUtils.removeTab(gBrowser.selectedTab);

  // Should still have 1 entry in the hamburger menu
  yield PanelUI.show();
@@ -227,23 +217,21 @@ add_task(function* () {
  addons = document.getElementById("PanelUI-footer-addons");
  is(addons.children.length, 1, "Have 1 menu entry for sideloaded extensions");

  // Click the second sideloaded extension
  tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:addons");
  // Click the second sideloaded extension and wait for the notification
  popupPromise = promisePopupNotificationShown("addon-webext-permissions");
  addons.children[0].click();

  tab = yield tabPromise;
  is(tab.linkedBrowser.currentURI.spec, "about:addons", "Newly opened tab is at about:addons");
  panel = yield popupPromise;

  isnot(menuButton.getAttribute("badge-status"), "addon-alert", "Should no longer have addon alert badge");

  yield promiseViewLoaded(tab, VIEW);
  win = tab.linkedBrowser.contentWindow;
  // Again we should be at the extentions list in about:addons
  is(gBrowser.currentURI.spec, "about:addons", "Foreground tab is at about:addons");

  win = gBrowser.selectedBrowser.contentWindow;
  ok(!win.gViewController.isLoading, "about:addons view is fully loaded");
  is(win.gViewController.currentViewId, VIEW, "about:addons is at extensions list");

  // Wait for the permission prompt and accept it this time
  panel = yield popupPromise;
  // Check the notification contents, this time accept the install
  icon = panel.getAttribute("icon");
  is(icon, DEFAULT_ICON_URL, "Permissions notification has the default icon");
  disablePromise = promiseSetDisabled(mock2);
@@ -256,5 +244,5 @@ add_task(function* () {
  is(addon1.userDisabled, true, "Addon 1 should still be disabled");
  is(addon2.userDisabled, false, "Addon 2 should now be enabled");

  yield BrowserTestUtils.removeTab(tab);
  yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
+40 −98
Original line number Diff line number Diff line
@@ -74,8 +74,8 @@ function promiseInstallEvent(addon, event) {
}

// Set some prefs that apply to all the tests in this file
add_task(function setup() {
  return SpecialPowers.pushPrefEnv({set: [
add_task(function* setup() {
  yield SpecialPowers.pushPrefEnv({set: [
    // We don't have pre-pinned certificates for the local mochitest server
    ["extensions.install.requireBuiltInCerts", false],
    ["extensions.update.requireBuiltInCerts", false],
@@ -83,6 +83,17 @@ add_task(function setup() {
    // XXX remove this when prompts are enabled by default
    ["extensions.webextPermissionPrompts", true],
  ]});

  // Navigate away from the initial page so that about:addons always
  // opens in a new tab during tests
  gBrowser.selectedBrowser.loadURI("about:robots");
  yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);

  registerCleanupFunction(function*() {
    // Return to about:blank when we're done
    gBrowser.selectedBrowser.loadURI("about:blank");
    yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
  });
});

// Helper function to test background updates.
@@ -123,7 +134,7 @@ function* backgroundUpdateTest(url, id, checkIconFn) {

  // about:addons should load and go to the list of extensions
  let tab = yield tabPromise;
  is(tab.linkedBrowser.currentURI.spec, "about:addons");
  is(tab.linkedBrowser.currentURI.spec, "about:addons", "Browser is at about:addons");

  const VIEW = "addons://list/extension";
  yield promiseViewLoaded(tab, VIEW);
@@ -211,114 +222,45 @@ function checkNonDefaultIcon(icon) {
add_task(() => backgroundUpdateTest(`${URL_BASE}/browser_webext_update_icon1.xpi`,
                                    ID_ICON, checkNonDefaultIcon));

// Helper function to test a specific scenario for interactive updates.
// `checkFn` is a callable that triggers a check for updates.
// `autoUpdate` specifies whether the test should be run with
// updates applied automatically or not.
function* interactiveUpdateTest(autoUpdate, checkFn) {
// Test that an update that adds new non-promptable permissions is just
// applied without showing a notification dialog.
add_task(function*() {
  yield SpecialPowers.pushPrefEnv({set: [
    ["extensions.update.autoUpdateDefault", autoUpdate],
    // Turn on background updates
    ["extensions.update.enabled", true],

    // Point updates to the local mochitest server
    ["extensions.update.url", `${URL_BASE}/browser_webext_update.json`],
    ["extensions.update.background.url", `${URL_BASE}/browser_webext_update.json`],
  ]});

  // Trigger an update check, manually applying the update if we're testing
  // without auto-update.
  function* triggerUpdate(win, addon) {
    let manualUpdatePromise;
    if (!autoUpdate) {
      manualUpdatePromise = new Promise(resolve => {
        let listener = {
          onNewInstall() {
            AddonManager.removeInstallListener(listener);
            resolve();
          },
        };
        AddonManager.addInstallListener(listener);
      });
    }

    checkFn(win, addon);

    if (manualUpdatePromise) {
      yield manualUpdatePromise;

      let item = win.document.getElementById("addon-list")
                    .children.find(_item => _item.value == ID);
      EventUtils.synthesizeMouseAtCenter(item._updateBtn, {}, win);
    }
  }

  // Install version 1.0 of the test extension
  let addon = yield promiseInstallAddon(`${URL_BASE}/browser_webext_update1.xpi`);
  ok(addon, "Addon was installed");
  is(addon.version, "1.0", "Version 1 of the addon is installed");

  // Open add-ons manager and navigate to extensions list
  let loadPromise = new Promise(resolve => {
    let listener = (subject, topic) => {
      if (subject.location.href == "about:addons") {
        Services.obs.removeObserver(listener, topic);
        resolve(subject);
      }
    };
    Services.obs.addObserver(listener, "EM-loaded", false);
  });
  let tab = gBrowser.addTab("about:addons");
  gBrowser.selectedTab = tab;
  let win = yield loadPromise;
  let addon = yield promiseInstallAddon(`${URL_BASE}/browser_webext_update_perms1.xpi`);

  const VIEW = "addons://list/extension";
  let viewPromise = promiseViewLoaded(tab, VIEW);
  win.loadView(VIEW);
  yield viewPromise;
  ok(addon, "Addon was installed");

  // Trigger an update check
  let popupPromise = promisePopupNotificationShown("addon-webext-permissions");
  yield triggerUpdate(win, addon);
  let panel = yield popupPromise;
  let sawPopup = false;
  PopupNotifications.panel.addEventListener("popupshown",
                                            () => sawPopup = true,
                                            {once: true});

  // Click the cancel button, wait to see the cancel event
  let cancelPromise = promiseInstallEvent(addon, "onInstallCancelled");
  panel.secondaryButton.click();
  yield cancelPromise;
  // Trigger an update check and wait for the update to be applied.
  let updatePromise = promiseInstallEvent(addon, "onInstallEnded");
  AddonManagerPrivate.backgroundUpdateCheck();
  yield updatePromise;

  addon = yield AddonManager.getAddonByID(ID);
  is(addon.version, "1.0", "Should still be running the old version");
  // There should be no notifications about the update
  is(getBadgeStatus(), "", "Should not have addon alert badge");

  // Trigger a new update check
  popupPromise = promisePopupNotificationShown("addon-webext-permissions");
  yield triggerUpdate(win, addon);
  yield PanelUI.show();
  let addons = document.getElementById("PanelUI-footer-addons");
  is(addons.children.length, 0, "Have 0 updates in the PanelUI menu");
  yield PanelUI.hide();

  // This time, accept the upgrade
  let updatePromise = promiseInstallEvent(addon, "onInstallEnded");
  panel = yield popupPromise;
  panel.button.click();
  ok(!sawPopup, "Should not have seen permissions notification");

  addon = yield updatePromise;
  is(addon.version, "2.0", "Should have upgraded");
  addon = yield AddonManager.getAddonByID("update_perms@tests.mozilla.org");
  is(addon.version, "2.0", "Update should have applied");

  yield BrowserTestUtils.removeTab(tab);
  addon.uninstall();
  yield SpecialPowers.popPrefEnv();
}

// Invoke the "Check for Updates" menu item
function checkAll(win) {
  win.gViewController.doCommand("cmd_findAllUpdates");
}

// Test "Check for Updates" with both auto-update settings
add_task(() => interactiveUpdateTest(true, checkAll));
add_task(() => interactiveUpdateTest(false, checkAll));


// Invoke an invidual extension's "Find Updates" menu item
function checkOne(win, addon) {
  win.gViewController.doCommand("cmd_findItemUpdates", addon);
}

// Test "Find Updates" with both auto-update settings
add_task(() => interactiveUpdateTest(true, checkOne));
add_task(() => interactiveUpdateTest(false, checkOne));
});
+192 −0
Original line number Diff line number Diff line
const {AddonManagerPrivate} = Cu.import("resource://gre/modules/AddonManager.jsm", {});

const URL_BASE = "https://example.com/browser/browser/base/content/test/general";
const ID = "update@tests.mozilla.org";

function promiseInstallAddon(url) {
  return AddonManager.getInstallForURL(url, null, "application/x-xpinstall")
                     .then(install => {
                       ok(install, "Created install");
                       return new Promise(resolve => {
                         install.addListener({
                           onInstallEnded(_install, addon) {
                             resolve(addon);
                           },
                         });
                         install.install();
                       });
                     });
}

function promiseViewLoaded(tab, viewid) {
  let win = tab.linkedBrowser.contentWindow;
  if (win.gViewController && !win.gViewController.isLoading &&
      win.gViewController.currentViewId == viewid) {
     return Promise.resolve();
  }

  return new Promise(resolve => {
    function listener() {
      if (win.gViewController.currentViewId != viewid) {
        return;
      }
      win.document.removeEventListener("ViewChanged", listener);
      resolve();
    }
    win.document.addEventListener("ViewChanged", listener);
  });
}

function promisePopupNotificationShown(name) {
  return new Promise(resolve => {
    function popupshown() {
      let notification = PopupNotifications.getNotification(name);
      if (!notification) { return; }

      ok(notification, `${name} notification shown`);
      ok(PopupNotifications.isPanelOpen, "notification panel open");

      PopupNotifications.panel.removeEventListener("popupshown", popupshown);
      resolve(PopupNotifications.panel.firstChild);
    }

    PopupNotifications.panel.addEventListener("popupshown", popupshown);
  });
}

function promiseInstallEvent(addon, event) {
  return new Promise(resolve => {
    let listener = {};
    listener[event] = (install, ...args) => {
      if (install.addon.id == addon.id) {
        AddonManager.removeInstallListener(listener);
        resolve(...args);
      }
    };
    AddonManager.addInstallListener(listener);
  });
}

// Set some prefs that apply to all the tests in this file
add_task(function* setup() {
  yield SpecialPowers.pushPrefEnv({set: [
    // We don't have pre-pinned certificates for the local mochitest server
    ["extensions.install.requireBuiltInCerts", false],
    ["extensions.update.requireBuiltInCerts", false],

    // XXX remove this when prompts are enabled by default
    ["extensions.webextPermissionPrompts", true],
  ]});
});

// Helper function to test a specific scenario for interactive updates.
// `checkFn` is a callable that triggers a check for updates.
// `autoUpdate` specifies whether the test should be run with
// updates applied automatically or not.
function* interactiveUpdateTest(autoUpdate, checkFn) {
  yield SpecialPowers.pushPrefEnv({set: [
    ["extensions.update.autoUpdateDefault", autoUpdate],

    // Point updates to the local mochitest server
    ["extensions.update.url", `${URL_BASE}/browser_webext_update.json`],
  ]});

  // Trigger an update check, manually applying the update if we're testing
  // without auto-update.
  function* triggerUpdate(win, addon) {
    let manualUpdatePromise;
    if (!autoUpdate) {
      manualUpdatePromise = new Promise(resolve => {
        let listener = {
          onNewInstall() {
            AddonManager.removeInstallListener(listener);
            resolve();
          },
        };
        AddonManager.addInstallListener(listener);
      });
    }

    checkFn(win, addon);

    if (manualUpdatePromise) {
      yield manualUpdatePromise;

      let item = win.document.getElementById("addon-list")
                    .children.find(_item => _item.value == ID);
      EventUtils.synthesizeMouseAtCenter(item._updateBtn, {}, win);
    }
  }

  // Install version 1.0 of the test extension
  let addon = yield promiseInstallAddon(`${URL_BASE}/browser_webext_update1.xpi`);
  ok(addon, "Addon was installed");
  is(addon.version, "1.0", "Version 1 of the addon is installed");

  // Open add-ons manager and navigate to extensions list
  let loadPromise = new Promise(resolve => {
    let listener = (subject, topic) => {
      if (subject.location.href == "about:addons") {
        Services.obs.removeObserver(listener, topic);
        resolve(subject);
      }
    };
    Services.obs.addObserver(listener, "EM-loaded", false);
  });
  let tab = gBrowser.addTab("about:addons");
  gBrowser.selectedTab = tab;
  let win = yield loadPromise;

  const VIEW = "addons://list/extension";
  let viewPromise = promiseViewLoaded(tab, VIEW);
  win.loadView(VIEW);
  yield viewPromise;

  // Trigger an update check
  let popupPromise = promisePopupNotificationShown("addon-webext-permissions");
  yield triggerUpdate(win, addon);
  let panel = yield popupPromise;

  // Click the cancel button, wait to see the cancel event
  let cancelPromise = promiseInstallEvent(addon, "onInstallCancelled");
  panel.secondaryButton.click();
  yield cancelPromise;

  addon = yield AddonManager.getAddonByID(ID);
  is(addon.version, "1.0", "Should still be running the old version");

  // Trigger a new update check
  popupPromise = promisePopupNotificationShown("addon-webext-permissions");
  yield triggerUpdate(win, addon);

  // This time, accept the upgrade
  let updatePromise = promiseInstallEvent(addon, "onInstallEnded");
  panel = yield popupPromise;
  panel.button.click();

  addon = yield updatePromise;
  is(addon.version, "2.0", "Should have upgraded");

  yield BrowserTestUtils.removeTab(tab);
  addon.uninstall();
  yield SpecialPowers.popPrefEnv();
}

// Invoke the "Check for Updates" menu item
function checkAll(win) {
  win.gViewController.doCommand("cmd_findAllUpdates");
}

// Test "Check for Updates" with both auto-update settings
add_task(() => interactiveUpdateTest(true, checkAll));
add_task(() => interactiveUpdateTest(false, checkAll));


// Invoke an invidual extension's "Find Updates" menu item
function checkOne(win, addon) {
  win.gViewController.doCommand("cmd_findItemUpdates", addon);
}

// Test "Find Updates" with both auto-update settings
add_task(() => interactiveUpdateTest(true, checkOne));
add_task(() => interactiveUpdateTest(false, checkOne));
Loading