diff --git a/addon-sdk/source/python-lib/cuddlefish/prefs.py b/addon-sdk/source/python-lib/cuddlefish/prefs.py
index 3ba611dad16f..73ab41d4e588 100644
--- a/addon-sdk/source/python-lib/cuddlefish/prefs.py
+++ b/addon-sdk/source/python-lib/cuddlefish/prefs.py
@@ -55,12 +55,13 @@ DEFAULT_NO_CONNECTIONS_PREFS = {
'browser.newtab.url' : 'about:blank',
'browser.search.update': False,
'browser.search.suggest.enabled' : False,
+ 'browser.safebrowsing.downloads.remote.url': 'http://localhost/safebrowsing-dummy/downloads',
+ 'browser.safebrowsing.malware.enabled' : False,
'browser.safebrowsing.phishing.enabled' : False,
'browser.safebrowsing.provider.google.updateURL': 'http://localhost/safebrowsing-dummy/update',
'browser.safebrowsing.provider.google.gethashURL': 'http://localhost/safebrowsing-dummy/gethash',
'browser.safebrowsing.provider.google4.updateURL': 'http://localhost/safebrowsing4-dummy/update',
'browser.safebrowsing.provider.google4.gethashURL': 'http://localhost/safebrowsing4-dummy/gethash',
- 'browser.safebrowsing.malware.reportURL': 'http://localhost/safebrowsing-dummy/malwarereport',
'browser.selfsupport.url': 'https://localhost/selfsupport-dummy',
'browser.safebrowsing.provider.mozilla.gethashURL': 'http://localhost/safebrowsing-dummy/gethash',
'browser.safebrowsing.provider.mozilla.updateURL': 'http://localhost/safebrowsing-dummy/update',
@@ -118,6 +119,7 @@ DEFAULT_FIREFOX_PREFS = {
# Make url-classifier updates so rare that they won't affect tests.
'urlclassifier.updateinterval' : 172800,
# Point the url-classifier to a nonexistent local URL for fast failures.
+ 'browser.safebrowsing.downloads.remote.url': 'http://localhost/safebrowsing-dummy/downloads',
'browser.safebrowsing.provider.google.gethashURL' : 'http://localhost/safebrowsing-dummy/gethash',
'browser.safebrowsing.provider.google.updateURL' : 'http://localhost/safebrowsing-dummy/update',
'browser.safebrowsing.provider.google4.gethashURL' : 'http://localhost/safebrowsing4-dummy/gethash',
diff --git a/addon-sdk/source/test/preferences/no-connections.json b/addon-sdk/source/test/preferences/no-connections.json
index 1bb62dbedc25..24aa94683c6d 100644
--- a/addon-sdk/source/test/preferences/no-connections.json
+++ b/addon-sdk/source/test/preferences/no-connections.json
@@ -15,6 +15,8 @@
"browser.newtab.url": "about:blank",
"browser.search.update": false,
"browser.search.suggest.enabled": false,
+ "browser.safebrowsing.downloads.remote.url": "http://localhost/safebrowsing-dummy/downloads",
+ "browser.safebrowsing.malware.enabled": false,
"browser.safebrowsing.phishing.enabled": false,
"browser.safebrowsing.provider.google.updateURL": "http://localhost/safebrowsing-dummy/update",
"browser.safebrowsing.provider.google.gethashURL": "http://localhost/safebrowsing-dummy/gethash",
diff --git a/browser/base/content/aboutDialog-appUpdater.js b/browser/base/content/aboutDialog-appUpdater.js
index 3ce4bf8fa49a..e0bd4d77ab27 100644
--- a/browser/base/content/aboutDialog-appUpdater.js
+++ b/browser/base/content/aboutDialog-appUpdater.js
@@ -175,6 +175,14 @@ appUpdater.prototype =
if (button) {
if (aChildID == "downloadAndInstall") {
let updateVersion = gAppUpdater.update.displayVersion;
+ // Include the build ID if this is an "a#" (nightly or aurora) build
+ if (/a\d+$/.test(updateVersion)) {
+ let buildID = gAppUpdater.update.buildID;
+ let year = buildID.slice(0, 4);
+ let month = buildID.slice(4, 6);
+ let day = buildID.slice(6, 8);
+ updateVersion += ` (${year}-${month}-${day})`;
+ }
button.label = this.bundle.formatStringFromName("update.downloadAndInstallButton.label", [updateVersion], 1);
button.accessKey = this.bundle.GetStringFromName("update.downloadAndInstallButton.accesskey");
}
diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js
index 6b4697ec03a7..6a7ad60b998d 100644
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -482,7 +482,7 @@ var PlacesCommandHook = {
try {
info.title = docInfo.isErrorPage ?
- (await PlacesUtils.promisePlaceInfo(aBrowser.currentURI)).title :
+ (await PlacesUtils.history.fetch(aBrowser.currentURI)).title :
aBrowser.contentTitle;
info.title = info.title || url.href;
description = docInfo.description;
diff --git a/browser/base/content/moz.build b/browser/base/content/moz.build
index ce1e2ec93551..b85cd710a886 100644
--- a/browser/base/content/moz.build
+++ b/browser/base/content/moz.build
@@ -25,9 +25,6 @@ with Files("newtab/**"):
with Files("pageinfo/**"):
BUG_COMPONENT = ("Firefox", "Page Info Window")
-with Files("sync/**"):
- BUG_COMPONENT = ("Firefox", "Sync")
-
with Files("test/alerts/**"):
BUG_COMPONENT = ("Toolkit", "Notifications and Alerts")
diff --git a/browser/base/content/sync/aboutSyncTabs-bindings.xml b/browser/base/content/sync/aboutSyncTabs-bindings.xml
deleted file mode 100644
index 60cf18607423..000000000000
--- a/browser/base/content/sync/aboutSyncTabs-bindings.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/browser/base/content/sync/aboutSyncTabs.css b/browser/base/content/sync/aboutSyncTabs.css
deleted file mode 100644
index 5a353175b1ef..000000000000
--- a/browser/base/content/sync/aboutSyncTabs.css
+++ /dev/null
@@ -1,11 +0,0 @@
-/* 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/. */
-
-richlistitem[type="tab"] {
- -moz-binding: url(chrome://browser/content/sync/aboutSyncTabs-bindings.xml#tab-listing);
-}
-
-richlistitem[type="client"] {
- -moz-binding: url(chrome://browser/content/sync/aboutSyncTabs-bindings.xml#client-listing);
-}
diff --git a/browser/base/content/sync/aboutSyncTabs.js b/browser/base/content/sync/aboutSyncTabs.js
deleted file mode 100644
index fb9e5c57cb32..000000000000
--- a/browser/base/content/sync/aboutSyncTabs.js
+++ /dev/null
@@ -1,305 +0,0 @@
-/* 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/. */
-
-/* import-globals-from ../utilityOverlay.js */
-
-var Cu = Components.utils;
-
-Cu.import("resource://services-common/utils.js");
-Cu.import("resource://services-sync/main.js");
-Cu.import("resource:///modules/PlacesUIUtils.jsm");
-Cu.import("resource://gre/modules/AppConstants.jsm");
-Cu.import("resource://gre/modules/PlacesUtils.jsm", this);
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "Promise",
- "resource://gre/modules/Promise.jsm");
-
-var RemoteTabViewer = {
- _tabsList: null,
-
- init() {
- Services.obs.addObserver(this, "weave:service:login:finish");
- Services.obs.addObserver(this, "weave:engine:sync:finish");
-
- this._tabsList = document.getElementById("tabsList");
-
- this.buildList(true);
- },
-
- uninit() {
- Services.obs.removeObserver(this, "weave:service:login:finish");
- Services.obs.removeObserver(this, "weave:engine:sync:finish");
- },
-
- createItem(attrs) {
- let item = document.createElement("richlistitem");
-
- // Copy the attributes from the argument into the item.
- for (let attr in attrs) {
- item.setAttribute(attr, attrs[attr]);
- }
-
- if (attrs["type"] == "tab") {
- item.label = attrs.title != "" ? attrs.title : attrs.url;
- }
-
- return item;
- },
-
- filterTabs(event) {
- let val = event.target.value.toLowerCase();
- let numTabs = this._tabsList.getRowCount();
- let clientTabs = 0;
- let currentClient = null;
-
- for (let i = 0; i < numTabs; i++) {
- let item = this._tabsList.getItemAtIndex(i);
- let hide = false;
- if (item.getAttribute("type") == "tab") {
- if (!item.getAttribute("url").toLowerCase().includes(val) &&
- !item.getAttribute("title").toLowerCase().includes(val)) {
- hide = true;
- } else {
- clientTabs++;
- }
- } else if (item.getAttribute("type") == "client") {
- if (currentClient) {
- if (clientTabs == 0) {
- currentClient.hidden = true;
- }
- }
- currentClient = item;
- clientTabs = 0;
- }
- item.hidden = hide;
- }
- if (clientTabs == 0) {
- currentClient.hidden = true;
- }
- },
-
- openSelected() {
- let items = this._tabsList.selectedItems;
- let urls = [];
- for (let i = 0; i < items.length; i++) {
- if (items[i].getAttribute("type") == "tab") {
- urls.push(items[i].getAttribute("url"));
- let index = this._tabsList.getIndexOfItem(items[i]);
- this._tabsList.removeItemAt(index);
- }
- }
- if (urls.length) {
- getTopWin().gBrowser.loadTabs(urls);
- this._tabsList.clearSelection();
- }
- },
-
- bookmarkSingleTab() {
- let item = this._tabsList.selectedItems[0];
- let uri = Weave.Utils.makeURI(item.getAttribute("url"));
- let title = item.getAttribute("title");
- PlacesUIUtils.showBookmarkDialog({ action: "add"
- , type: "bookmark"
- , uri
- , title
- , hiddenRows: [ "description"
- , "location"
- , "loadInSidebar"
- , "keyword" ]
- }, window.top);
- },
-
- bookmarkSelectedTabs() {
- let items = this._tabsList.selectedItems;
- let URIs = [];
- for (let i = 0; i < items.length; i++) {
- if (items[i].getAttribute("type") == "tab") {
- let uri = Weave.Utils.makeURI(items[i].getAttribute("url"));
- if (!uri) {
- continue;
- }
-
- URIs.push(uri);
- }
- }
- if (URIs.length) {
- PlacesUIUtils.showBookmarkDialog({ action: "add"
- , type: "folder"
- , URIList: URIs
- , hiddenRows: [ "description" ]
- }, window.top);
- }
- },
-
- getIcon(iconUri, defaultIcon) {
- try {
- let iconURI = Weave.Utils.makeURI(iconUri);
- return PlacesUtils.favicons.getFaviconLinkForIcon(iconURI).spec;
- } catch (ex) {
- // Do nothing.
- }
-
- // Just give the provided default icon or the system's default.
- return defaultIcon || PlacesUtils.favicons.defaultFavicon.spec;
- },
-
- _waitingForBuildList: false,
-
- _buildListRequested: false,
-
- buildList(forceSync) {
- if (this._waitingForBuildList) {
- this._buildListRequested = true;
- return;
- }
-
- this._waitingForBuildList = true;
- this._buildListRequested = false;
-
- this._clearTabList();
-
- if (Weave.Service.isLoggedIn) {
- this._refetchTabs(forceSync);
- this._generateWeaveTabList();
- } else {
- // XXXzpao We should say something about not being logged in & not having data
- // or tell the appropriate condition. (bug 583344)
- }
-
- this._waitingForBuildList = false;
- if (this._buildListRequested) {
- CommonUtils.nextTick(this.buildList, this);
- }
- },
-
- _clearTabList() {
- let list = this._tabsList;
-
- // Clear out existing richlistitems.
- let count = list.getRowCount();
- if (count > 0) {
- for (let i = count - 1; i >= 0; i--) {
- list.removeItemAt(i);
- }
- }
- },
-
- _generateWeaveTabList() {
- let engine = Weave.Service.engineManager.get("tabs");
- let list = this._tabsList;
-
- let seenURLs = new Set();
- let localURLs = engine.getOpenURLs();
-
- for (let [, client] of Object.entries(engine.getAllClients())) {
- // Create the client node, but don't add it in-case we don't show any tabs
- let appendClient = true;
-
- client.tabs.forEach(function({title, urlHistory, icon}) {
- let url = urlHistory[0];
- if (!url || localURLs.has(url) || seenURLs.has(url)) {
- return;
- }
- seenURLs.add(url);
-
- if (appendClient) {
- let attrs = {
- type: "client",
- clientName: client.clientName,
- class: Weave.Service.clientsEngine.isMobile(client.id) ? "mobile" : "desktop"
- };
- let clientEnt = this.createItem(attrs);
- list.appendChild(clientEnt);
- appendClient = false;
- clientEnt.disabled = true;
- }
- let attrs = {
- type: "tab",
- title: title || url,
- url,
- icon: this.getIcon(icon),
- }
- let tab = this.createItem(attrs);
- list.appendChild(tab);
- }, this);
- }
- },
-
- adjustContextMenu(event) {
- let mode = "all";
- switch (this._tabsList.selectedItems.length) {
- case 0:
- break;
- case 1:
- mode = "single"
- break;
- default:
- mode = "multiple";
- break;
- }
-
- let menu = document.getElementById("tabListContext");
- let el = menu.firstChild;
- while (el) {
- let showFor = el.getAttribute("showFor");
- if (showFor) {
- el.hidden = showFor != mode && showFor != "all";
- }
-
- el = el.nextSibling;
- }
- },
-
- _refetchTabs(force) {
- if (!force) {
- // Don't bother refetching tabs if we already did so recently
- let lastFetch = Services.prefs.getIntPref("services.sync.lastTabFetch", 0);
-
- let now = Math.floor(Date.now() / 1000);
- if (now - lastFetch < 30) {
- return false;
- }
- }
-
- // Ask Sync to just do the tabs engine if it can.
- Weave.Service.sync(["tabs"]);
- Services.prefs.setIntPref("services.sync.lastTabFetch",
- Math.floor(Date.now() / 1000));
-
- return true;
- },
-
- observe(subject, topic, data) {
- switch (topic) {
- case "weave:service:login:finish":
- // A login has finished, which means that a Sync is about to start and
- // we will eventually get to the "tabs" engine - but try and force the
- // tab engine to sync first by passing |true| for the forceSync param.
- this.buildList(true);
- break;
- case "weave:engine:sync:finish":
- if (data == "tabs") {
- // The tabs engine just finished, so re-build the list without
- // forcing a new sync of the tabs engine.
- this.buildList(false);
- }
- break;
- }
- },
-
- handleClick(event) {
- if (event.target.getAttribute("type") != "tab") {
- return;
- }
-
- if (event.button == 1) {
- let url = event.target.getAttribute("url");
- openUILink(url, event);
- let index = this._tabsList.getIndexOfItem(event.target);
- this._tabsList.removeItemAt(index);
- }
- }
-}
diff --git a/browser/base/content/sync/aboutSyncTabs.xul b/browser/base/content/sync/aboutSyncTabs.xul
deleted file mode 100644
index 4247fd7e6475..000000000000
--- a/browser/base/content/sync/aboutSyncTabs.xul
+++ /dev/null
@@ -1,68 +0,0 @@
-
-
-
-
-
-
-
-
-
- %aboutSyncTabsDTD;
-]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/browser/base/content/test/general/browser.ini b/browser/base/content/test/general/browser.ini
index 3ba8b59aa487..a4be0358b2cf 100644
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -506,8 +506,6 @@ skip-if = os == "linux" || os == "mac" # No tabs in titlebar on linux
[browser_tabkeynavigation.js]
skip-if = (os == "mac" && !e10s) # Bug 1237713 - OSX eats keypresses for some reason
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
-[browser_tabopen_reflows.js]
-# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_tabs_close_beforeunload.js]
support-files =
close_beforeunload_opens_second_tab.html
@@ -584,9 +582,6 @@ skip-if = (os == "win" && !debug)
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_web_channel.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
-[browser_windowopen_reflows.js]
-skip-if = os == "mac" # bug 1339317
-# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_zbug569342.js]
skip-if = e10s || debug # Bug 1094240 - has findbar-related failures
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
diff --git a/browser/base/content/test/general/browser_tabopen_reflows.js b/browser/base/content/test/general/browser_tabopen_reflows.js
deleted file mode 100644
index e3bdf4e1bf89..000000000000
--- a/browser/base/content/test/general/browser_tabopen_reflows.js
+++ /dev/null
@@ -1,145 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-XPCOMUtils.defineLazyGetter(this, "docShell", () => {
- return window.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShell);
-});
-
-const EXPECTED_REFLOWS = [
- // tabbrowser.adjustTabstrip() call after tabopen animation has finished
- "adjustTabstrip@chrome://browser/content/tabbrowser.xml|" +
- "_handleNewTab@chrome://browser/content/tabbrowser.xml|" +
- "onxbltransitionend@chrome://browser/content/tabbrowser.xml|",
-
- // switching focus in updateCurrentBrowser() causes reflows
- "_adjustFocusAfterTabSwitch@chrome://browser/content/tabbrowser.xml|" +
- "updateCurrentBrowser@chrome://browser/content/tabbrowser.xml|" +
- "onselect@chrome://browser/content/browser.xul|",
-
- // switching focus in openLinkIn() causes reflows
- "openLinkIn@chrome://browser/content/utilityOverlay.js|" +
- "openUILinkIn@chrome://browser/content/utilityOverlay.js|" +
- "BrowserOpenTab@chrome://browser/content/browser.js|",
-
- // selection change notification may cause querying the focused editor content
- // by IME and that will cause reflow.
- "select@chrome://global/content/bindings/textbox.xml|" +
- "focusAndSelectUrlBar@chrome://browser/content/browser.js|" +
- "openLinkIn@chrome://browser/content/utilityOverlay.js|" +
- "openUILinkIn@chrome://browser/content/utilityOverlay.js|" +
- "BrowserOpenTab@chrome://browser/content/browser.js|",
-
-];
-
-const PREF_PRELOAD = "browser.newtab.preload";
-const PREF_NEWTAB_DIRECTORYSOURCE = "browser.newtabpage.directory.source";
-
-/*
- * This test ensures that there are no unexpected
- * uninterruptible reflows when opening new tabs.
- */
-add_task(async function() {
- let DirectoryLinksProvider = Cu.import("resource:///modules/DirectoryLinksProvider.jsm", {}).DirectoryLinksProvider;
- let NewTabUtils = Cu.import("resource://gre/modules/NewTabUtils.jsm", {}).NewTabUtils;
- let Promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
-
- // resolves promise when directory links are downloaded and written to disk
- function watchLinksChangeOnce() {
- return new Promise(resolve => {
- let observer = {
- onManyLinksChanged: () => {
- DirectoryLinksProvider.removeObserver(observer);
- NewTabUtils.links.populateCache(() => {
- NewTabUtils.allPages.update();
- resolve();
- }, true);
- }
- };
- observer.onDownloadFail = observer.onManyLinksChanged;
- DirectoryLinksProvider.addObserver(observer);
- });
- }
-
- let gOrigDirectorySource = Services.prefs.getCharPref(PREF_NEWTAB_DIRECTORYSOURCE);
- registerCleanupFunction(() => {
- Services.prefs.clearUserPref(PREF_PRELOAD);
- Services.prefs.setCharPref(PREF_NEWTAB_DIRECTORYSOURCE, gOrigDirectorySource);
- return watchLinksChangeOnce();
- });
-
- Services.prefs.setBoolPref(PREF_PRELOAD, false);
- // set directory source to dummy/empty links
- Services.prefs.setCharPref(PREF_NEWTAB_DIRECTORYSOURCE, 'data:application/json,{"test":1}');
-
- // run tests when directory source change completes
- await watchLinksChangeOnce();
-
- // Perform a click in the top left of content to ensure the mouse isn't
- // hovering over any of the tiles
- let target = gBrowser.selectedBrowser;
- let rect = target.getBoundingClientRect();
- let left = rect.left + 1;
- let top = rect.top + 1;
-
- let utils = window.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils);
- utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0);
- utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0);
-
- // Add a reflow observer and open a new tab.
- docShell.addWeakReflowObserver(observer);
- BrowserOpenTab();
-
- // Wait until the tabopen animation has finished.
- await waitForTransitionEnd();
-
- // Remove reflow observer and clean up.
- docShell.removeWeakReflowObserver(observer);
- gBrowser.removeCurrentTab();
-});
-
-var observer = {
- reflow(start, end) {
- // Gather information about the current code path.
- let path = (new Error().stack).split("\n").slice(1).map(line => {
- return line.replace(/:\d+:\d+$/, "");
- }).join("|");
- let pathWithLineNumbers = (new Error().stack).split("\n").slice(1).join("|");
-
- // Stack trace is empty. Reflow was triggered by native code.
- if (path === "") {
- return;
- }
-
- // Check if this is an expected reflow.
- for (let stack of EXPECTED_REFLOWS) {
- if (path.startsWith(stack)) {
- ok(true, "expected uninterruptible reflow '" + stack + "'");
- return;
- }
- }
-
- ok(false, "unexpected uninterruptible reflow '" + pathWithLineNumbers + "'");
- },
-
- reflowInterruptible(start, end) {
- // We're not interested in interruptible reflows.
- },
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIReflowObserver,
- Ci.nsISupportsWeakReference])
-};
-
-function waitForTransitionEnd() {
- return new Promise(resolve => {
- let tab = gBrowser.selectedTab;
- tab.addEventListener("transitionend", function onEnd(event) {
- if (event.propertyName === "max-width") {
- tab.removeEventListener("transitionend", onEnd);
- resolve();
- }
- });
- });
-}
diff --git a/browser/base/content/test/general/browser_windowopen_reflows.js b/browser/base/content/test/general/browser_windowopen_reflows.js
deleted file mode 100644
index 5cdda1ee6848..000000000000
--- a/browser/base/content/test/general/browser_windowopen_reflows.js
+++ /dev/null
@@ -1,117 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-const EXPECTED_REFLOWS = [
- // handleEvent flushes layout to get the tabstrip width after a resize.
- "handleEvent@chrome://browser/content/tabbrowser.xml|",
-
- // Loading a tab causes a reflow.
- "loadTabs@chrome://browser/content/tabbrowser.xml|" +
- "loadOneOrMoreURIs@chrome://browser/content/browser.js|" +
- "_delayedStartup@chrome://browser/content/browser.js|",
-
- // Selecting the address bar causes a reflow.
- "select@chrome://global/content/bindings/textbox.xml|" +
- "focusAndSelectUrlBar@chrome://browser/content/browser.js|" +
- "_delayedStartup@chrome://browser/content/browser.js|",
-
- // Focusing the content area causes a reflow.
- "_delayedStartup@chrome://browser/content/browser.js|",
-];
-
-if (Services.appinfo.OS == "WINNT" || Services.appinfo.OS == "Darwin") {
- // TabsInTitlebar._update causes a reflow on OS X and Windows trying to do calculations
- // since layout info is already dirty. This doesn't seem to happen before
- // MozAfterPaint on Linux.
- EXPECTED_REFLOWS.push("rect@chrome://browser/content/browser-tabsintitlebar.js|" +
- "_update@chrome://browser/content/browser-tabsintitlebar.js|" +
- "updateAppearance@chrome://browser/content/browser-tabsintitlebar.js|" +
- "handleEvent@chrome://browser/content/tabbrowser.xml|");
-}
-
-if (Services.appinfo.OS == "Darwin") {
- // _onOverflow causes a reflow getting widths.
- EXPECTED_REFLOWS.push("_onOverflow@resource:///modules/CustomizableUI.jsm|" +
- "init@resource:///modules/CustomizableUI.jsm|" +
- "observe@resource:///modules/CustomizableUI.jsm|" +
- "_delayedStartup@chrome://browser/content/browser.js|");
- // Same as above since in packaged builds there are no function names and the resource URI includes "app"
- EXPECTED_REFLOWS.push("@resource://app/modules/CustomizableUI.jsm|" +
- "@resource://app/modules/CustomizableUI.jsm|" +
- "@resource://app/modules/CustomizableUI.jsm|" +
- "_delayedStartup@chrome://browser/content/browser.js|");
-}
-
-/*
- * This test ensures that there are no unexpected
- * uninterruptible reflows when opening new windows.
- */
-function test() {
- waitForExplicitFinish();
-
- // Add a reflow observer and open a new window
- let win = OpenBrowserWindow();
- let docShell = win.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShell);
- docShell.addWeakReflowObserver(observer);
-
- // Wait until the mozafterpaint event occurs.
- waitForMozAfterPaint(win, function paintListener() {
- // Remove reflow observer and clean up.
- docShell.removeWeakReflowObserver(observer);
- win.close();
-
- finish();
- });
-}
-
-var observer = {
- reflow(start, end) {
- // Gather information about the current code path.
- let stack = new Error().stack;
- let path = stack.split("\n").slice(1).map(line => {
- return line.replace(/:\d+:\d+$/, "");
- }).join("|");
- let pathWithLineNumbers = (new Error().stack).split("\n").slice(1).join("|");
-
- // Stack trace is empty. Reflow was triggered by native code.
- if (path === "") {
- return;
- }
-
- // Check if this is an expected reflow.
- for (let expectedStack of EXPECTED_REFLOWS) {
- if (path.startsWith(expectedStack) ||
- // Accept an empty function name for gBrowserInit._delayedStartup or TabsInTitlebar._update to workaround bug 906578.
- path.startsWith(expectedStack.replace(/(^|\|)(gBrowserInit\._delayedStartup|TabsInTitlebar\._update)@/, "$1@"))) {
- ok(true, "expected uninterruptible reflow '" + expectedStack + "'");
- return;
- }
- }
-
- ok(false, "unexpected uninterruptible reflow '" + pathWithLineNumbers + "'");
- },
-
- reflowInterruptible(start, end) {
- // We're not interested in interruptible reflows.
- },
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIReflowObserver,
- Ci.nsISupportsWeakReference])
-};
-
-function waitForMozAfterPaint(win, callback) {
- let dwu = win.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils);
- let lastTransactionId = dwu.lastTransactionId;
-
- win.addEventListener("MozAfterPaint", function onEnd(event) {
- if (event.target != win || event.transactionId <= lastTransactionId)
- return;
- win.removeEventListener("MozAfterPaint", onEnd);
- executeSoon(callback);
- });
-}
diff --git a/browser/base/content/test/windows/.eslintrc.js b/browser/base/content/test/performance/.eslintrc.js
similarity index 100%
rename from browser/base/content/test/windows/.eslintrc.js
rename to browser/base/content/test/performance/.eslintrc.js
diff --git a/browser/base/content/test/performance/browser.ini b/browser/base/content/test/performance/browser.ini
new file mode 100644
index 000000000000..acb6c701e2d4
--- /dev/null
+++ b/browser/base/content/test/performance/browser.ini
@@ -0,0 +1,7 @@
+[DEFAULT]
+support-files =
+ head.js
+[browser_tabclose_reflows.js]
+[browser_tabopen_reflows.js]
+[browser_toolbariconcolor_restyles.js]
+[browser_windowopen_reflows.js]
diff --git a/browser/base/content/test/performance/browser_tabclose_reflows.js b/browser/base/content/test/performance/browser_tabclose_reflows.js
new file mode 100644
index 000000000000..dce28f5323ed
--- /dev/null
+++ b/browser/base/content/test/performance/browser_tabclose_reflows.js
@@ -0,0 +1,71 @@
+"use strict";
+
+/**
+ * WHOA THERE: We should never be adding new things to EXPECTED_REFLOWS. This
+ * is a whitelist that should slowly go away as we improve the performance of
+ * the front-end. Instead of adding more reflows to the whitelist, you should
+ * be modifying your code to avoid the reflow.
+ *
+ * See https://developer.mozilla.org/en-US/Firefox/Performance_best_practices_for_Firefox_fe_engineers
+ * for tips on how to do that.
+ */
+const EXPECTED_REFLOWS = [
+ [
+ "_adjustFocusAfterTabSwitch@chrome://browser/content/tabbrowser.xml",
+ ],
+];
+
+if (gMultiProcessBrowser) {
+ EXPECTED_REFLOWS.push(
+ [
+ "_adjustFocusAfterTabSwitch@chrome://browser/content/tabbrowser.xml",
+ ],
+ );
+}
+
+/*
+ * This test ensures that there are no unexpected
+ * uninterruptible reflows when closing new tabs.
+ */
+add_task(async function() {
+ // If we've got a preloaded browser, get rid of it so that it
+ // doesn't interfere with the test if it's loading. We have to
+ // do this before we disable preloading or changing the new tab
+ // URL, otherwise _getPreloadedBrowser will return null, despite
+ // the preloaded browser existing.
+ let preloaded = gBrowser._getPreloadedBrowser();
+ if (preloaded) {
+ preloaded.remove();
+ }
+
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.newtab.preload", false]],
+ });
+
+ let aboutNewTabService = Cc["@mozilla.org/browser/aboutnewtab-service;1"]
+ .getService(Ci.nsIAboutNewTabService);
+ aboutNewTabService.newTabURL = "about:blank";
+
+ registerCleanupFunction(() => {
+ aboutNewTabService.resetNewTabURL();
+ });
+
+ // Because the tab strip is a scrollable frame, we can't use the
+ // default dirtying function from withReflowObserver and reliably
+ // get reflows for the strip. Instead, we provide a node that's
+ // already in the scrollable frame to dirty - in this case, the
+ // original tab.
+ let origTab = gBrowser.selectedTab;
+
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
+ await BrowserTestUtils.waitForCondition(() => tab._fullyOpen);
+
+ // Add a reflow observer and open a new tab.
+ await withReflowObserver(async function() {
+ let switchDone = BrowserTestUtils.waitForEvent(window, "TabSwitchDone");
+ gBrowser.removeTab(tab, { animate: true });
+ await BrowserTestUtils.waitForEvent(tab, "transitionend",
+ false, e => e.propertyName === "max-width");
+ await switchDone;
+ }, EXPECTED_REFLOWS, window, origTab);
+});
diff --git a/browser/base/content/test/performance/browser_tabopen_reflows.js b/browser/base/content/test/performance/browser_tabopen_reflows.js
new file mode 100644
index 000000000000..4159c28901dc
--- /dev/null
+++ b/browser/base/content/test/performance/browser_tabopen_reflows.js
@@ -0,0 +1,108 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * WHOA THERE: We should never be adding new things to EXPECTED_REFLOWS. This
+ * is a whitelist that should slowly go away as we improve the performance of
+ * the front-end. Instead of adding more reflows to the whitelist, you should
+ * be modifying your code to avoid the reflow.
+ *
+ * See https://developer.mozilla.org/en-US/Firefox/Performance_best_practices_for_Firefox_fe_engineers
+ * for tips on how to do that.
+ */
+const EXPECTED_REFLOWS = [
+ // selection change notification may cause querying the focused editor content
+ // by IME and that will cause reflow.
+ [
+ "select@chrome://global/content/bindings/textbox.xml",
+ "focusAndSelectUrlBar@chrome://browser/content/browser.js",
+ "openLinkIn@chrome://browser/content/utilityOverlay.js",
+ "openUILinkIn@chrome://browser/content/utilityOverlay.js",
+ "BrowserOpenTab@chrome://browser/content/browser.js",
+ ],
+
+ // selection change notification may cause querying the focused editor content
+ // by IME and that will cause reflow.
+ [
+ "select@chrome://global/content/bindings/textbox.xml",
+ "focusAndSelectUrlBar@chrome://browser/content/browser.js",
+ "openLinkIn@chrome://browser/content/utilityOverlay.js",
+ "openUILinkIn@chrome://browser/content/utilityOverlay.js",
+ "BrowserOpenTab@chrome://browser/content/browser.js",
+ ],
+
+ [
+ "select@chrome://global/content/bindings/textbox.xml",
+ "focusAndSelectUrlBar@chrome://browser/content/browser.js",
+ "openLinkIn@chrome://browser/content/utilityOverlay.js",
+ "openUILinkIn@chrome://browser/content/utilityOverlay.js",
+ "BrowserOpenTab@chrome://browser/content/browser.js",
+ ],
+
+ [
+ "openLinkIn@chrome://browser/content/utilityOverlay.js",
+ "openUILinkIn@chrome://browser/content/utilityOverlay.js",
+ "BrowserOpenTab@chrome://browser/content/browser.js",
+ ],
+];
+
+if (!gMultiProcessBrowser) {
+ EXPECTED_REFLOWS.push(
+ [
+ "_adjustFocusAfterTabSwitch@chrome://browser/content/tabbrowser.xml",
+ "updateCurrentBrowser@chrome://browser/content/tabbrowser.xml",
+ "onselect@chrome://browser/content/browser.xul",
+ ],
+ );
+}
+
+/*
+ * This test ensures that there are no unexpected
+ * uninterruptible reflows when opening new tabs.
+ */
+add_task(async function() {
+ // If we've got a preloaded browser, get rid of it so that it
+ // doesn't interfere with the test if it's loading. We have to
+ // do this before we disable preloading or changing the new tab
+ // URL, otherwise _getPreloadedBrowser will return null, despite
+ // the preloaded browser existing.
+ let preloaded = gBrowser._getPreloadedBrowser();
+ if (preloaded) {
+ preloaded.remove();
+ }
+
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.newtab.preload", false]],
+ });
+
+ let aboutNewTabService = Cc["@mozilla.org/browser/aboutnewtab-service;1"]
+ .getService(Ci.nsIAboutNewTabService);
+ aboutNewTabService.newTabURL = "about:blank";
+
+ registerCleanupFunction(() => {
+ aboutNewTabService.resetNewTabURL();
+ });
+
+ // Because the tab strip is a scrollable frame, we can't use the
+ // default dirtying function from withReflowObserver and reliably
+ // get reflows for the strip. Instead, we provide a node that's
+ // already in the scrollable frame to dirty - in this case, the
+ // original tab.
+ let origTab = gBrowser.selectedTab;
+
+ // Add a reflow observer and open a new tab.
+ await withReflowObserver(async function() {
+ let switchDone = BrowserTestUtils.waitForEvent(window, "TabSwitchDone");
+ BrowserOpenTab();
+ await BrowserTestUtils.waitForEvent(gBrowser.selectedTab, "transitionend",
+ false, e => e.propertyName === "max-width");
+ await switchDone;
+ }, EXPECTED_REFLOWS, window, origTab);
+
+ let switchDone = BrowserTestUtils.waitForEvent(window, "TabSwitchDone");
+ await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+ await switchDone;
+});
+
diff --git a/browser/base/content/test/windows/browser_toolbariconcolor_restyles.js b/browser/base/content/test/performance/browser_toolbariconcolor_restyles.js
similarity index 100%
rename from browser/base/content/test/windows/browser_toolbariconcolor_restyles.js
rename to browser/base/content/test/performance/browser_toolbariconcolor_restyles.js
diff --git a/browser/base/content/test/performance/browser_windowopen_reflows.js b/browser/base/content/test/performance/browser_windowopen_reflows.js
new file mode 100644
index 000000000000..b8c4b3b56a5f
--- /dev/null
+++ b/browser/base/content/test/performance/browser_windowopen_reflows.js
@@ -0,0 +1,73 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * WHOA THERE: We should never be adding new things to EXPECTED_REFLOWS. This
+ * is a whitelist that should slowly go away as we improve the performance of
+ * the front-end. Instead of adding more reflows to the whitelist, you should
+ * be modifying your code to avoid the reflow.
+ *
+ * See https://developer.mozilla.org/en-US/Firefox/Performance_best_practices_for_Firefox_fe_engineers
+ * for tips on how to do that.
+ */
+const EXPECTED_REFLOWS = [
+ // Selecting the address bar causes two reflows, unfortunately.
+ [
+ "select@chrome://global/content/bindings/textbox.xml",
+ "focusAndSelectUrlBar@chrome://browser/content/browser.js",
+ "_delayedStartup@chrome://browser/content/browser.js",
+ ],
+
+ // Selecting the address bar causes two reflows, unfortunately.
+ [
+ "select@chrome://global/content/bindings/textbox.xml",
+ "focusAndSelectUrlBar@chrome://browser/content/browser.js",
+ "_delayedStartup@chrome://browser/content/browser.js",
+ ],
+];
+
+if (Services.appinfo.OS == "Darwin") {
+ // TabsInTitlebar._update causes a reflow on OS X trying to do calculations
+ // since layout info is already dirty. This doesn't seem to happen before
+ // MozAfterPaint on Linux.
+ EXPECTED_REFLOWS.push(
+ [
+ "rect@chrome://browser/content/browser-tabsintitlebar.js",
+ "_update@chrome://browser/content/browser-tabsintitlebar.js",
+ "updateAppearance@chrome://browser/content/browser-tabsintitlebar.js",
+ "handleEvent@chrome://browser/content/tabbrowser.xml",
+ ],
+ );
+}
+
+if (Services.appinfo.OS == "WINNT" || Services.appinfo.OS == "Darwin") {
+ EXPECTED_REFLOWS.push(
+ [
+ "handleEvent@chrome://browser/content/tabbrowser.xml",
+ "inferFromText@chrome://browser/content/browser.js",
+ "handleEvent@chrome://browser/content/browser.js",
+ ],
+ );
+}
+
+/*
+ * This test ensures that there are no unexpected
+ * uninterruptible reflows when opening new windows.
+ */
+add_task(async function() {
+ let win = OpenBrowserWindow();
+
+ await withReflowObserver(async function() {
+ let resizeEvent = BrowserTestUtils.waitForEvent(win, "resize");
+ let delayedStartup =
+ TestUtils.topicObserved("browser-delayed-startup-finished",
+ subject => subject == win);
+ await resizeEvent;
+ await delayedStartup;
+ }, EXPECTED_REFLOWS, win);
+
+ await BrowserTestUtils.closeWindow(win);
+});
+
diff --git a/browser/base/content/test/performance/head.js b/browser/base/content/test/performance/head.js
new file mode 100644
index 000000000000..54fa9c49a28b
--- /dev/null
+++ b/browser/base/content/test/performance/head.js
@@ -0,0 +1,155 @@
+/**
+ * Async utility function for ensuring that no unexpected uninterruptible
+ * reflows occur during some period of time in a window.
+ *
+ * The helper works by running a JS function before each event is
+ * dispatched that attempts to dirty the layout tree - the idea being
+ * that this puts us in the "worst case scenario" so that any JS
+ * that attempts to query for layout or style information will cause
+ * a reflow to fire. We also dirty the layout tree after each reflow
+ * occurs, for good measure.
+ *
+ * This sounds good in theory, but it's trickier in practice due to
+ * various optimizations in our Layout engine. The default function
+ * for dirtying the layout tree adds a margin to the first element
+ * child it finds in the window to a maximum of 3px, and then goes
+ * back to 0px again and loops.
+ *
+ * This is not sufficient for reflows that we expect to happen within
+ * scrollable frames, as Gecko is able to side-step reflowing the
+ * contents of a scrollable frame if outer frames are dirtied. Because
+ * of this, it's currently possible to override the default node to
+ * dirty with one more appropriate for the test.
+ *
+ * It is also theoretically possible for enough events to fire between
+ * reflows such that the before and after state of the layout tree is
+ * exactly the same, meaning that no reflow is required, which opens
+ * us up to missing expected reflows. This seems to be possible in
+ * theory, but hasn't yet shown up in practice - it's just something
+ * to be aware of.
+ *
+ * Bug 1363361 has been filed for a more reliable way of dirtying layout.
+ *
+ * @param testFn (async function)
+ * The async function that will exercise the browser activity that is
+ * being tested for reflows.
+ * @param expectedStacks (Array, optional)
+ * An Array of Arrays representing stacks.
+ *
+ * Example:
+ *
+ * [
+ * // This reflow is caused by lorem ipsum
+ * [
+ * "select@chrome://global/content/bindings/textbox.xml",
+ * "focusAndSelectUrlBar@chrome://browser/content/browser.js",
+ * "openLinkIn@chrome://browser/content/utilityOverlay.js",
+ * "openUILinkIn@chrome://browser/content/utilityOverlay.js",
+ * "BrowserOpenTab@chrome://browser/content/browser.js",
+ * ],
+ *
+ * // This reflow is caused by lorem ipsum
+ * [
+ * "get_scrollPosition@chrome://global/content/bindings/scrollbox.xml",
+ * "_fillTrailingGap@chrome://browser/content/tabbrowser.xml",
+ * "_handleNewTab@chrome://browser/content/tabbrowser.xml",
+ * "onxbltransitionend@chrome://browser/content/tabbrowser.xml",
+ * ],
+ *
+ * ]
+ *
+ * Note that line numbers are not included in the stacks.
+ *
+ * Order of the reflows doesn't matter. Expected reflows that aren't seen
+ * will cause an assertion failure. When this argument is not passed,
+ * it defaults to the empty Array, meaning no reflows are expected.
+ * @param window (browser window, optional)
+ * The browser window to monitor. Defaults to the current window.
+ * @param elemToDirty (DOM node, optional)
+ * Callers can provide a custom DOM node to change some layout style
+ * on in the event that the action being tested is occurring within
+ * a scrollable frame. Otherwise, withReflowObserver defaults to dirtying
+ * the first element child of the window.
+ */
+async function withReflowObserver(testFn, expectedStacks = [], win = window, elemToDirty) {
+ if (!elemToDirty) {
+ elemToDirty = win.document.firstElementChild;
+ }
+
+ let i = 0;
+ let dirtyFrameFn = (e) => {
+ elemToDirty.style.margin = (++i % 4) + "px";
+ };
+
+ let els = Cc["@mozilla.org/eventlistenerservice;1"]
+ .getService(Ci.nsIEventListenerService);
+
+ // We're going to remove the stacks one by one as we see them so that
+ // we can check for expected, unseen reflows, so let's clone the array.
+ expectedStacks = expectedStacks.slice(0);
+
+ let observer = {
+ reflow(start, end) {
+ // Gather information about the current code path, slicing out the current
+ // frame.
+ let path = (new Error().stack).split("\n").slice(1).map(line => {
+ return line.replace(/:\d+:\d+$/, "");
+ }).join("|");
+
+ let pathWithLineNumbers = (new Error().stack).split("\n").slice(1);
+
+ // Just in case, dirty the frame now that we've reflowed.
+ dirtyFrameFn();
+
+ // Stack trace is empty. Reflow was triggered by native code, which
+ // we ignore.
+ if (path === "") {
+ return;
+ }
+
+ let index = expectedStacks.findIndex(stack => path.startsWith(stack.join("|")));
+
+ if (index != -1) {
+ Assert.ok(true, "expected uninterruptible reflow: '" +
+ JSON.stringify(pathWithLineNumbers, null, "\t") + "'");
+ expectedStacks.splice(index, 1);
+ } else {
+ Assert.ok(false, "unexpected uninterruptible reflow \n" +
+ JSON.stringify(pathWithLineNumbers, null, "\t") + "\n");
+ }
+ },
+
+ reflowInterruptible(start, end) {
+ // We're not interested in interruptible reflows.
+ },
+
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIReflowObserver,
+ Ci.nsISupportsWeakReference])
+ };
+
+ let docShell = win.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShell);
+ docShell.addWeakReflowObserver(observer);
+
+ els.addListenerForAllEvents(win, dirtyFrameFn, true);
+
+ try {
+ dirtyFrameFn();
+ await testFn();
+ } finally {
+ for (let remainder of expectedStacks) {
+ Assert.ok(false,
+ `Unused expected reflow: ${JSON.stringify(remainder, null, "\t")}.\n` +
+ "This is probably a good thing - just remove it from the " +
+ "expected list.");
+ }
+
+
+ els.removeListenerForAllEvents(win, dirtyFrameFn, true);
+ docShell.removeWeakReflowObserver(observer);
+
+ elemToDirty.style.margin = "";
+ }
+}
+
diff --git a/browser/base/content/test/windows/browser.ini b/browser/base/content/test/windows/browser.ini
deleted file mode 100644
index 442cf06669b7..000000000000
--- a/browser/base/content/test/windows/browser.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[DEFAULT]
-[browser_toolbariconcolor_restyles.js]
diff --git a/browser/base/jar.mn b/browser/base/jar.mn
index 1c01b77c3650..f99ed1632e33 100644
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -129,10 +129,6 @@ browser.jar:
content/browser/pageinfo/permissions.js (content/pageinfo/permissions.js)
content/browser/pageinfo/security.js (content/pageinfo/security.js)
content/browser/robot.ico (content/robot.ico)
- content/browser/sync/aboutSyncTabs.xul (content/sync/aboutSyncTabs.xul)
- content/browser/sync/aboutSyncTabs.js (content/sync/aboutSyncTabs.js)
- content/browser/sync/aboutSyncTabs.css (content/sync/aboutSyncTabs.css)
- content/browser/sync/aboutSyncTabs-bindings.xml (content/sync/aboutSyncTabs-bindings.xml)
content/browser/safeMode.css (content/safeMode.css)
content/browser/safeMode.js (content/safeMode.js)
content/browser/safeMode.xul (content/safeMode.xul)
diff --git a/browser/base/moz.build b/browser/base/moz.build
index 4f74f6b9c2f7..ba444d157413 100644
--- a/browser/base/moz.build
+++ b/browser/base/moz.build
@@ -22,6 +22,7 @@ BROWSER_CHROME_MANIFESTS += [
'content/test/general/browser.ini',
'content/test/newtab/browser.ini',
'content/test/pageinfo/browser.ini',
+ 'content/test/performance/browser.ini',
'content/test/permissions/browser.ini',
'content/test/plugins/browser.ini',
'content/test/popupNotifications/browser.ini',
@@ -38,7 +39,6 @@ BROWSER_CHROME_MANIFESTS += [
'content/test/urlbar/browser.ini',
'content/test/webextensions/browser.ini',
'content/test/webrtc/browser.ini',
- 'content/test/windows/browser.ini',
]
if CONFIG['MOZ_UPDATER']:
diff --git a/browser/components/about/AboutRedirector.cpp b/browser/components/about/AboutRedirector.cpp
index b9de6a318722..7ba29c23533e 100644
--- a/browser/components/about/AboutRedirector.cpp
+++ b/browser/components/about/AboutRedirector.cpp
@@ -80,8 +80,6 @@ static const RedirEntry kRedirMap[] = {
nsIAboutModule::ALLOW_SCRIPT },
{ "welcomeback", "chrome://browser/content/aboutWelcomeBack.xhtml",
nsIAboutModule::ALLOW_SCRIPT },
- { "sync-tabs", "chrome://browser/content/sync/aboutSyncTabs.xul",
- nsIAboutModule::ALLOW_SCRIPT },
// Linkable because of indexeddb use (bug 1228118)
{ "home", "chrome://browser/content/abouthome/aboutHome.xhtml",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
diff --git a/browser/components/build/nsModule.cpp b/browser/components/build/nsModule.cpp
index f85d8812c01d..fbeb8244e0fd 100644
--- a/browser/components/build/nsModule.cpp
+++ b/browser/components/build/nsModule.cpp
@@ -97,7 +97,6 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "searchreset", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "sessionrestore", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "welcomeback", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
- { NS_ABOUT_MODULE_CONTRACTID_PREFIX "sync-tabs", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "home", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "newtab", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "preferences", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
diff --git a/browser/components/contextualidentity/test/browser/browser_eme.js b/browser/components/contextualidentity/test/browser/browser_eme.js
index dd8cdd3f7339..25e4851d08d2 100644
--- a/browser/components/contextualidentity/test/browser/browser_eme.js
+++ b/browser/components/contextualidentity/test/browser/browser_eme.js
@@ -103,7 +103,7 @@ add_task(async function test() {
let access = await content.navigator.requestMediaKeySystemAccess("org.w3.clearkey",
[{
initDataTypes: [aKeyInfo.initDataType],
- videoCapabilities: [{contentType: "video/webm"}],
+ videoCapabilities: [{contentType: 'video/webm; codecs="vp9"'}],
sessionTypes: ["persistent-license"],
persistentState: "required",
}]);
@@ -156,7 +156,7 @@ add_task(async function test() {
let access = await content.navigator.requestMediaKeySystemAccess("org.w3.clearkey",
[{
initDataTypes: [aKeyInfo.initDataType],
- videoCapabilities: [{contentType: "video/webm"}],
+ videoCapabilities: [{contentType: 'video/webm; codecs="vp9"'}],
sessionTypes: ["persistent-license"],
persistentState: "required",
}]);
diff --git a/browser/components/contextualidentity/test/browser/browser_forgetAPI_EME_forgetThisSite.js b/browser/components/contextualidentity/test/browser/browser_forgetAPI_EME_forgetThisSite.js
index b6e948284a12..356fe0332eda 100644
--- a/browser/components/contextualidentity/test/browser/browser_forgetAPI_EME_forgetThisSite.js
+++ b/browser/components/contextualidentity/test/browser/browser_forgetAPI_EME_forgetThisSite.js
@@ -98,7 +98,7 @@ async function setupEMEKey(browser) {
let access = await content.navigator.requestMediaKeySystemAccess("org.w3.clearkey",
[{
initDataTypes: [aKeyInfo.initDataType],
- videoCapabilities: [{contentType: "video/webm"}],
+ videoCapabilities: [{contentType: 'video/webm; codecs="vp9"'}],
sessionTypes: ["persistent-license"],
persistentState: "required",
}]);
@@ -153,7 +153,7 @@ async function checkEMEKey(browser, emeSessionId) {
let access = await content.navigator.requestMediaKeySystemAccess("org.w3.clearkey",
[{
initDataTypes: [aKeyInfo.initDataType],
- videoCapabilities: [{contentType: "video/webm"}],
+ videoCapabilities: [{contentType: 'video/webm; codecs="vp9"'}],
sessionTypes: ["persistent-license"],
persistentState: "required",
}]);
diff --git a/browser/components/extensions/ext-contextMenus.js b/browser/components/extensions/ext-contextMenus.js
index bc65d625f47a..aa422c52a44e 100644
--- a/browser/components/extensions/ext-contextMenus.js
+++ b/browser/components/extensions/ext-contextMenus.js
@@ -147,6 +147,13 @@ var gMenuBuilder = {
let menuPopup = element.firstChild;
if (menuPopup && menuPopup.childNodes.length == 1) {
let onlyChild = menuPopup.firstChild;
+
+ // Keep single checkbox items in the submenu on Linux since
+ // the extension icon overlaps the checkbox otherwise.
+ if (AppConstants.platform === "linux" && onlyChild.getAttribute("type") === "checkbox") {
+ return element;
+ }
+
onlyChild.remove();
return onlyChild;
}
diff --git a/browser/components/extensions/test/browser/browser_ext_contextMenus_checkboxes.js b/browser/components/extensions/test/browser/browser_ext_contextMenus_checkboxes.js
index 29905cadef60..6db571bc3fe7 100644
--- a/browser/components/extensions/test/browser/browser_ext_contextMenus_checkboxes.js
+++ b/browser/components/extensions/test/browser/browser_ext_contextMenus_checkboxes.js
@@ -24,26 +24,54 @@ add_task(async function() {
type: "checkbox",
});
- browser.contextMenus.create({
- type: "separator",
- });
+ browser.test.sendMessage("single-contextmenu-item-added");
- browser.contextMenus.create({
- title: "Checkbox",
- type: "checkbox",
- checked: true,
- });
+ browser.test.onMessage.addListener(msg => {
+ if (msg !== "add-additional-menu-items") {
+ return;
+ }
- browser.contextMenus.create({
- title: "Checkbox",
- type: "checkbox",
- });
+ browser.contextMenus.create({
+ type: "separator",
+ });
- browser.test.notifyPass("contextmenus-checkboxes");
+ browser.contextMenus.create({
+ title: "Checkbox",
+ type: "checkbox",
+ checked: true,
+ });
+
+ browser.contextMenus.create({
+ title: "Checkbox",
+ type: "checkbox",
+ });
+
+ browser.test.notifyPass("contextmenus-checkboxes");
+ });
},
});
await extension.startup();
+
+ await extension.awaitMessage("single-contextmenu-item-added");
+
+ async function testSingleCheckboxItem() {
+ let extensionMenuRoot = await openExtensionContextMenu();
+
+ // On Linux, the single menu item should be contained in a submenu.
+ if (AppConstants.platform === "linux") {
+ let items = extensionMenuRoot.getElementsByAttribute("type", "checkbox");
+ is(items.length, 1, "single checkbox should be in the submenu on Linux");
+ await closeContextMenu();
+ } else {
+ is(extensionMenuRoot, null, "there should be no submenu for a single checkbox item");
+ await closeContextMenu();
+ }
+ }
+
+ await testSingleCheckboxItem();
+
+ extension.sendMessage("add-additional-menu-items");
await extension.awaitFinish("contextmenus-checkboxes");
function confirmCheckboxStates(extensionMenuRoot, expectedStates) {
diff --git a/browser/components/extensions/test/browser/browser_ext_getViews.js b/browser/components/extensions/test/browser/browser_ext_getViews.js
index 53470eb745f0..3e6ae598869c 100644
--- a/browser/components/extensions/test/browser/browser_ext_getViews.js
+++ b/browser/components/extensions/test/browser/browser_ext_getViews.js
@@ -14,17 +14,12 @@ function genericChecker() {
browser.test.onMessage.addListener((msg, ...args) => {
if (msg == kind + "-check-views") {
- let windowId = args[0];
let counts = {
- "background": 0,
- "tab": 0,
- "popup": 0,
- "kind": 0,
- "window": 0,
+ background: 0,
+ tab: 0,
+ popup: 0,
+ kind: 0,
};
- if (Number.isInteger(windowId)) {
- counts.window = browser.extension.getViews({windowId: windowId}).length;
- }
if (kind !== "background") {
counts.kind = browser.extension.getViews({type: kind}).length;
}
@@ -48,8 +43,13 @@ function genericChecker() {
} else {
browser.test.sendMessage("counts", counts);
}
+ } else if (msg == kind + "-getViews-with-filter") {
+ let filter = args[0];
+ let count = browser.extension.getViews(filter).length;
+ browser.test.sendMessage("getViews-count", count);
} else if (msg == kind + "-open-tab") {
- browser.tabs.create({windowId: args[0], url: browser.runtime.getURL("tab.html")});
+ browser.tabs.create({windowId: args[0], url: browser.runtime.getURL("tab.html")})
+ .then((tab) => browser.test.sendMessage("opened-tab", tab.id));
} else if (msg == kind + "-close-tab") {
browser.tabs.query({
windowId: args[0],
@@ -112,28 +112,40 @@ add_task(async function() {
async function openTab(winId) {
extension.sendMessage("background-open-tab", winId);
await extension.awaitMessage("tab-ready");
+ return extension.awaitMessage("opened-tab");
}
- async function checkViews(kind, tabCount, popupCount, kindCount, windowId = undefined, windowCount = 0) {
- extension.sendMessage(kind + "-check-views", windowId);
+ async function checkViews(kind, tabCount, popupCount, kindCount) {
+ extension.sendMessage(kind + "-check-views");
let counts = await extension.awaitMessage("counts");
is(counts.background, 1, "background count correct");
is(counts.tab, tabCount, "tab count correct");
is(counts.popup, popupCount, "popup count correct");
is(counts.kind, kindCount, "count for type correct");
- is(counts.window, windowCount, "count for window correct");
+ }
+
+ async function checkViewsWithFilter(filter, expectedCount) {
+ extension.sendMessage("background-getViews-with-filter", filter);
+ let count = await extension.awaitMessage("getViews-count");
+ is(count, expectedCount, `count for ${JSON.stringify(filter)} correct`);
}
await checkViews("background", 0, 0, 0);
+ await checkViewsWithFilter({windowId: -1}, 1);
+ await checkViewsWithFilter({tabId: -1}, 1);
- await openTab(winId1);
+ let tabId1 = await openTab(winId1);
- await checkViews("background", 1, 0, 0, winId1, 1);
+ await checkViews("background", 1, 0, 0);
await checkViews("tab", 1, 0, 1);
+ await checkViewsWithFilter({windowId: winId1}, 1);
+ await checkViewsWithFilter({tabId: tabId1}, 1);
- await openTab(winId2);
+ let tabId2 = await openTab(winId2);
- await checkViews("background", 2, 0, 0, winId2, 1);
+ await checkViews("background", 2, 0, 0);
+ await checkViewsWithFilter({windowId: winId2}, 1);
+ await checkViewsWithFilter({tabId: tabId2}, 1);
async function triggerPopup(win, callback) {
await clickBrowserAction(extension, win);
@@ -153,18 +165,24 @@ add_task(async function() {
await new Promise(resolve => win1.setTimeout(resolve, 10));
await triggerPopup(win1, async function() {
- await checkViews("background", 2, 1, 0, winId1, 2);
+ await checkViews("background", 2, 1, 0);
await checkViews("popup", 2, 1, 1);
+ await checkViewsWithFilter({windowId: winId1}, 2);
+ await checkViewsWithFilter({type: "popup", tabId: -1}, 1);
});
await triggerPopup(win2, async function() {
- await checkViews("background", 2, 1, 0, winId2, 2);
+ await checkViews("background", 2, 1, 0);
await checkViews("popup", 2, 1, 1);
+ await checkViewsWithFilter({windowId: winId2}, 2);
+ await checkViewsWithFilter({type: "popup", tabId: -1}, 1);
});
info("checking counts after popups");
- await checkViews("background", 2, 0, 0, winId1, 1);
+ await checkViews("background", 2, 0, 0);
+ await checkViewsWithFilter({windowId: winId1}, 1);
+ await checkViewsWithFilter({tabId: -1}, 1);
info("closing one tab");
diff --git a/browser/components/migration/tests/marionette/test_refresh_firefox.py b/browser/components/migration/tests/marionette/test_refresh_firefox.py
index 00b72cce658c..889b2abba9d0 100644
--- a/browser/components/migration/tests/marionette/test_refresh_firefox.py
+++ b/browser/components/migration/tests/marionette/test_refresh_firefox.py
@@ -170,35 +170,22 @@ class TestFirefoxRefresh(MarionetteTestCase):
self.assertEqual(titleInBookmarks, self._bookmarkText)
def checkHistory(self):
- historyResults = self.runAsyncCode("""
- let placeInfos = [];
- PlacesUtils.asyncHistory.getPlacesInfo(makeURI(arguments[0]), {
- handleError(resultCode, place) {
- placeInfos = null;
- marionetteScriptFinished("Unexpected error in fetching visit: " + resultCode);
- },
- handleResult(placeInfo) {
- placeInfos.push(placeInfo);
- },
- handleCompletion() {
- if (placeInfos) {
- if (!placeInfos.length) {
- marionetteScriptFinished("No visits found");
- } else {
- marionetteScriptFinished(placeInfos);
- }
- }
- },
+ historyResult = self.runAsyncCode("""
+ PlacesUtils.history.fetch(arguments[0]).then(pageInfo => {
+ if (!pageInfo) {
+ marionetteScriptFinished("No visits found");
+ } else {
+ marionetteScriptFinished(pageInfo);
+ }
+ }).catch(e => {
+ marionetteScriptFinished("Unexpected error in fetching page: " + e);
});
""", script_args=[self._historyURL])
- if type(historyResults) == str:
- self.fail(historyResults)
+ if type(historyResult) == str:
+ self.fail(historyResult)
return
- historyCount = len(historyResults)
- self.assertEqual(historyCount, 1, "Should have exactly 1 entry for URI, got %d" % historyCount)
- if historyCount == 1:
- self.assertEqual(historyResults[0]['title'], self._historyTitle)
+ self.assertEqual(historyResult['title'], self._historyTitle)
def checkFormHistory(self):
formFieldResults = self.runAsyncCode("""
diff --git a/browser/components/places/content/bookmarkProperties.js b/browser/components/places/content/bookmarkProperties.js
index cdca666d00c2..d653ba23ffb5 100644
--- a/browser/components/places/content/bookmarkProperties.js
+++ b/browser/components/places/content/bookmarkProperties.js
@@ -660,7 +660,7 @@ var BookmarkPropertiesPanel = {
} else if (this._itemType == BOOKMARK_FOLDER) {
itemGuid = await PlacesTransactions.NewFolder(info).transact();
for (let uri of this._URIs) {
- let placeInfo = await PlacesUtils.promisePlaceInfo(uri);
+ let placeInfo = await PlacesUtils.history.fetch(uri);
let title = placeInfo ? placeInfo.title : "";
await PlacesTransactions.transact({ parentGuid: itemGuid, uri, title });
}
diff --git a/browser/locales/en-US/chrome/browser/aboutSyncTabs.dtd b/browser/locales/en-US/chrome/browser/aboutSyncTabs.dtd
deleted file mode 100644
index fad491bbdbb7..000000000000
--- a/browser/locales/en-US/chrome/browser/aboutSyncTabs.dtd
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/browser/locales/jar.mn b/browser/locales/jar.mn
index a68285304705..b407aa99be38 100644
--- a/browser/locales/jar.mn
+++ b/browser/locales/jar.mn
@@ -20,7 +20,6 @@
locale/browser/aboutSearchReset.dtd (%chrome/browser/aboutSearchReset.dtd)
locale/browser/aboutSessionRestore.dtd (%chrome/browser/aboutSessionRestore.dtd)
locale/browser/aboutTabCrashed.dtd (%chrome/browser/aboutTabCrashed.dtd)
- locale/browser/aboutSyncTabs.dtd (%chrome/browser/aboutSyncTabs.dtd)
locale/browser/browser.dtd (%chrome/browser/browser.dtd)
locale/browser/baseMenuOverlay.dtd (%chrome/browser/baseMenuOverlay.dtd)
locale/browser/browser.properties (%chrome/browser/browser.properties)
diff --git a/browser/themes/linux/aboutSyncTabs.css b/browser/themes/linux/aboutSyncTabs.css
deleted file mode 100644
index 18e21546602b..000000000000
--- a/browser/themes/linux/aboutSyncTabs.css
+++ /dev/null
@@ -1,105 +0,0 @@
-/* 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/. */
-
-#tabs-display,
-#tabsList {
- background-color: transparent;
- -moz-appearance: none;
- margin: 0;
-}
-
-#tabsList {
- width: 100%;
-}
-
-#tabs-display {
- background: #fff url(chrome://browser/skin/sync-bg.png) repeat-x center -80px;
-}
-
-#headers {
- background: url(chrome://browser/skin/sync-32.png) no-repeat;
- margin-top: 4px;
- width: 45em;
- height: 32px;
- margin-inline-start: 2em;
- margin-inline-end: 2em;
-}
-
-#headers:-moz-locale-dir(rtl) {
- background-position-x: 100%;
-}
-
-#tabsListHeading {
- font-size: 140%;
- font-weight: bold;
- margin-inline-start: 40px;
-}
-
-richlistitem {
- margin-inline-end: 2em;
-}
-
-richlistitem[selected="true"],
-richlistitem:focus {
- outline-style: none;
-}
-
-richlistitem[type="tab"] {
- min-height: 3em;
- border: #999999 1px solid !important;
- padding: 2px 5px;
- margin-bottom: 4px;
- margin-inline-start: 4em;
- border-radius: 6px;
- background-color: menu;
- width: 44em;
- opacity: 0.9;
- box-shadow:
- inset rgba(255, 255, 255, 0.5) 0 1px 0px,
- inset rgba(0, 0, 0, 0.1) 0 -2px 0px,
- rgba(0, 0, 0, 0.1) 0px 1px 0px;
-}
-
-richlistitem[type="tab"][selected="true"] {
- background-color: -moz-MenuHover;
-}
-
-richlistitem[type="client"] {
- min-height: 2em;
- color: #000000;
- margin-inline-start: 2em;
- margin-top: 2px;
- margin-bottom: 3px;
- width: 42em;
- border-radius: 6px;
- background-color: transparent;
- -moz-user-focus: ignore !important;
-}
-richlistitem.mobile[type="client"] {
- list-style-image: url("chrome://browser/skin/sync-mobileIcon.svg#icon");
-}
-richlistitem.desktop[type="client"] {
- list-style-image: url("chrome://browser/skin/sync-desktopIcon.svg#icon");
-}
-
-.title,
-.clientName {
- color: #000000;
- font-size: 1.1em;
-}
-
-.title[selected="true"],
-.url[selected="true"] {
- color: inherit;
-}
-
-.url {
- color: -moz-nativehyperlinktext;
- font-size: 0.95em;
-}
-
-.tabIcon {
- padding-inline-start: 2px;
- padding-top: 2px;
-}
diff --git a/browser/themes/linux/jar.mn b/browser/themes/linux/jar.mn
index b5e802c7a88f..7c34e9461d72 100644
--- a/browser/themes/linux/jar.mn
+++ b/browser/themes/linux/jar.mn
@@ -8,7 +8,6 @@ browser.jar:
#include ../shared/jar.inc.mn
skin/classic/browser/sanitizeDialog.css
skin/classic/browser/aboutSessionRestore-window-icon.png
- skin/classic/browser/aboutSyncTabs.css
* skin/classic/browser/syncedtabs/sidebar.css (syncedtabs/sidebar.css)
* skin/classic/browser/browser.css
* skin/classic/browser/compacttheme.css
@@ -99,9 +98,6 @@ browser.jar:
skin/classic/browser/tabbrowser/tab-stroke-start@2x.png (tabbrowser/tab-stroke-start@2x.png)
skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
- skin/classic/browser/sync-16.png
- skin/classic/browser/sync-32.png
- skin/classic/browser/sync-bg.png
skin/classic/browser/sync-desktopIcon.svg (../shared/sync-desktopIcon.svg)
skin/classic/browser/sync-horizontalbar.png
skin/classic/browser/sync-horizontalbar@2x.png
diff --git a/browser/themes/osx/aboutSyncTabs.css b/browser/themes/osx/aboutSyncTabs.css
deleted file mode 100644
index 18e21546602b..000000000000
--- a/browser/themes/osx/aboutSyncTabs.css
+++ /dev/null
@@ -1,105 +0,0 @@
-/* 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/. */
-
-#tabs-display,
-#tabsList {
- background-color: transparent;
- -moz-appearance: none;
- margin: 0;
-}
-
-#tabsList {
- width: 100%;
-}
-
-#tabs-display {
- background: #fff url(chrome://browser/skin/sync-bg.png) repeat-x center -80px;
-}
-
-#headers {
- background: url(chrome://browser/skin/sync-32.png) no-repeat;
- margin-top: 4px;
- width: 45em;
- height: 32px;
- margin-inline-start: 2em;
- margin-inline-end: 2em;
-}
-
-#headers:-moz-locale-dir(rtl) {
- background-position-x: 100%;
-}
-
-#tabsListHeading {
- font-size: 140%;
- font-weight: bold;
- margin-inline-start: 40px;
-}
-
-richlistitem {
- margin-inline-end: 2em;
-}
-
-richlistitem[selected="true"],
-richlistitem:focus {
- outline-style: none;
-}
-
-richlistitem[type="tab"] {
- min-height: 3em;
- border: #999999 1px solid !important;
- padding: 2px 5px;
- margin-bottom: 4px;
- margin-inline-start: 4em;
- border-radius: 6px;
- background-color: menu;
- width: 44em;
- opacity: 0.9;
- box-shadow:
- inset rgba(255, 255, 255, 0.5) 0 1px 0px,
- inset rgba(0, 0, 0, 0.1) 0 -2px 0px,
- rgba(0, 0, 0, 0.1) 0px 1px 0px;
-}
-
-richlistitem[type="tab"][selected="true"] {
- background-color: -moz-MenuHover;
-}
-
-richlistitem[type="client"] {
- min-height: 2em;
- color: #000000;
- margin-inline-start: 2em;
- margin-top: 2px;
- margin-bottom: 3px;
- width: 42em;
- border-radius: 6px;
- background-color: transparent;
- -moz-user-focus: ignore !important;
-}
-richlistitem.mobile[type="client"] {
- list-style-image: url("chrome://browser/skin/sync-mobileIcon.svg#icon");
-}
-richlistitem.desktop[type="client"] {
- list-style-image: url("chrome://browser/skin/sync-desktopIcon.svg#icon");
-}
-
-.title,
-.clientName {
- color: #000000;
- font-size: 1.1em;
-}
-
-.title[selected="true"],
-.url[selected="true"] {
- color: inherit;
-}
-
-.url {
- color: -moz-nativehyperlinktext;
- font-size: 0.95em;
-}
-
-.tabIcon {
- padding-inline-start: 2px;
- padding-top: 2px;
-}
diff --git a/browser/themes/osx/jar.mn b/browser/themes/osx/jar.mn
index 7fc7cd7ef1b8..08526e53414a 100644
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -7,7 +7,6 @@ browser.jar:
#include ../shared/jar.inc.mn
skin/classic/browser/sanitizeDialog.css
skin/classic/browser/aboutSessionRestore-window-icon.png
- skin/classic/browser/aboutSyncTabs.css
* skin/classic/browser/syncedtabs/sidebar.css (syncedtabs/sidebar.css)
* skin/classic/browser/browser.css
* skin/classic/browser/compacttheme.css
@@ -146,9 +145,6 @@ browser.jar:
skin/classic/browser/tabbrowser/tab-stroke-start@2x.png (tabbrowser/tab-stroke-start@2x.png)
skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
skin/classic/browser/tabbrowser/tabDragIndicator@2x.png (tabbrowser/tabDragIndicator@2x.png)
- skin/classic/browser/sync-16.png
- skin/classic/browser/sync-32.png
- skin/classic/browser/sync-bg.png
skin/classic/browser/sync-desktopIcon.svg (../shared/sync-desktopIcon.svg)
skin/classic/browser/sync-horizontalbar.png
skin/classic/browser/sync-horizontalbar@2x.png
diff --git a/browser/themes/shared/identity-block/identity-block.inc.css b/browser/themes/shared/identity-block/identity-block.inc.css
index 21f111cd3462..4fa9f18b9d75 100644
--- a/browser/themes/shared/identity-block/identity-block.inc.css
+++ b/browser/themes/shared/identity-block/identity-block.inc.css
@@ -170,6 +170,7 @@
transition: none;
}
+#urlbar[pageproxystate="invalid"] > #identity-box > #extension-icon,
#urlbar[pageproxystate="invalid"] > #identity-box > #tracking-protection-icon {
visibility: collapse;
}
diff --git a/browser/themes/shared/toolbarbutton-icons.inc.css b/browser/themes/shared/toolbarbutton-icons.inc.css
index 4059ad69f57a..bfc4aefd1a08 100644
--- a/browser/themes/shared/toolbarbutton-icons.inc.css
+++ b/browser/themes/shared/toolbarbutton-icons.inc.css
@@ -13,12 +13,18 @@ toolbar[brighttext] :-moz-any(@primaryToolbarButtons@) {
fill: var(--toolbarbutton-icon-fill-inverted);
}
-#back-button {
- list-style-image: url("chrome://browser/skin/back-large.svg");
+#back-button:-moz-locale-dir(rtl) > .toolbarbutton-icon,
+%ifdef MOZ_PHOTON_THEME
+#forward-button:-moz-locale-dir(rtl) > .toolbarbutton-icon,
+#reload-button:-moz-locale-dir(rtl) > .toolbarbutton-icon,
+%endif
+#nav-bar-overflow-button:-moz-locale-dir(rtl) > .toolbarbutton-icon,
+#panic-button:-moz-locale-dir(rtl) > .toolbarbutton-icon {
+ transform: scaleX(-1);
}
-#back-button:-moz-locale-dir(rtl) > .toolbarbutton-icon {
- transform: scaleX(-1);
+#back-button {
+ list-style-image: url("chrome://browser/skin/back-large.svg");
}
#forward-button {
@@ -26,10 +32,6 @@ toolbar[brighttext] :-moz-any(@primaryToolbarButtons@) {
}
%ifdef MOZ_PHOTON_THEME
-#forward-button:-moz-locale-dir(rtl) > .toolbarbutton-icon {
- transform: scaleX(-1);
-}
-
#reload-button {
list-style-image: url("chrome://browser/skin/reload.svg");
}
@@ -171,10 +173,6 @@ toolbar:not([brighttext]) #bookmarks-menu-button[cui-areatype="toolbar"][starred
list-style-image: url("chrome://browser/skin/chevron.svg");
}
-#nav-bar-overflow-button:-moz-locale-dir(rtl) > .toolbarbutton-icon {
- transform: scaleX(-1);
-}
-
#email-link-button[cui-areatype="toolbar"] {
list-style-image: url("chrome://browser/skin/mail.svg");
}
@@ -191,10 +189,6 @@ toolbar:not([brighttext]) #bookmarks-menu-button[cui-areatype="toolbar"][starred
fill: rgb(213, 32, 20);
}
-#panic-button:-moz-locale-dir(rtl) > .toolbarbutton-icon {
- transform: scaleX(-1);
-}
-
#webide-button[cui-areatype="toolbar"] {
list-style-image: url("chrome://browser/skin/webIDE.svg");
}
diff --git a/browser/themes/windows/aboutSyncTabs.css b/browser/themes/windows/aboutSyncTabs.css
deleted file mode 100644
index 18e21546602b..000000000000
--- a/browser/themes/windows/aboutSyncTabs.css
+++ /dev/null
@@ -1,105 +0,0 @@
-/* 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/. */
-
-#tabs-display,
-#tabsList {
- background-color: transparent;
- -moz-appearance: none;
- margin: 0;
-}
-
-#tabsList {
- width: 100%;
-}
-
-#tabs-display {
- background: #fff url(chrome://browser/skin/sync-bg.png) repeat-x center -80px;
-}
-
-#headers {
- background: url(chrome://browser/skin/sync-32.png) no-repeat;
- margin-top: 4px;
- width: 45em;
- height: 32px;
- margin-inline-start: 2em;
- margin-inline-end: 2em;
-}
-
-#headers:-moz-locale-dir(rtl) {
- background-position-x: 100%;
-}
-
-#tabsListHeading {
- font-size: 140%;
- font-weight: bold;
- margin-inline-start: 40px;
-}
-
-richlistitem {
- margin-inline-end: 2em;
-}
-
-richlistitem[selected="true"],
-richlistitem:focus {
- outline-style: none;
-}
-
-richlistitem[type="tab"] {
- min-height: 3em;
- border: #999999 1px solid !important;
- padding: 2px 5px;
- margin-bottom: 4px;
- margin-inline-start: 4em;
- border-radius: 6px;
- background-color: menu;
- width: 44em;
- opacity: 0.9;
- box-shadow:
- inset rgba(255, 255, 255, 0.5) 0 1px 0px,
- inset rgba(0, 0, 0, 0.1) 0 -2px 0px,
- rgba(0, 0, 0, 0.1) 0px 1px 0px;
-}
-
-richlistitem[type="tab"][selected="true"] {
- background-color: -moz-MenuHover;
-}
-
-richlistitem[type="client"] {
- min-height: 2em;
- color: #000000;
- margin-inline-start: 2em;
- margin-top: 2px;
- margin-bottom: 3px;
- width: 42em;
- border-radius: 6px;
- background-color: transparent;
- -moz-user-focus: ignore !important;
-}
-richlistitem.mobile[type="client"] {
- list-style-image: url("chrome://browser/skin/sync-mobileIcon.svg#icon");
-}
-richlistitem.desktop[type="client"] {
- list-style-image: url("chrome://browser/skin/sync-desktopIcon.svg#icon");
-}
-
-.title,
-.clientName {
- color: #000000;
- font-size: 1.1em;
-}
-
-.title[selected="true"],
-.url[selected="true"] {
- color: inherit;
-}
-
-.url {
- color: -moz-nativehyperlinktext;
- font-size: 0.95em;
-}
-
-.tabIcon {
- padding-inline-start: 2px;
- padding-top: 2px;
-}
diff --git a/browser/themes/windows/jar.mn b/browser/themes/windows/jar.mn
index 96935f9e563e..ca5ed832a5bb 100644
--- a/browser/themes/windows/jar.mn
+++ b/browser/themes/windows/jar.mn
@@ -7,7 +7,6 @@ browser.jar:
#include ../shared/jar.inc.mn
skin/classic/browser/sanitizeDialog.css
skin/classic/browser/aboutSessionRestore-window-icon.png
- skin/classic/browser/aboutSyncTabs.css
* skin/classic/browser/syncedtabs/sidebar.css (syncedtabs/sidebar.css)
* skin/classic/browser/browser.css
* skin/classic/browser/compacttheme.css
@@ -125,9 +124,6 @@ browser.jar:
skin/classic/browser/tabbrowser/tab-stroke-start.png (tabbrowser/tab-stroke-start.png)
skin/classic/browser/tabbrowser/tab-stroke-start@2x.png (tabbrowser/tab-stroke-start@2x.png)
skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
- skin/classic/browser/sync-16.png
- skin/classic/browser/sync-32.png
- skin/classic/browser/sync-bg.png
skin/classic/browser/sync-desktopIcon.svg (../shared/sync-desktopIcon.svg)
skin/classic/browser/sync-horizontalbar.png
skin/classic/browser/sync-horizontalbar@2x.png
diff --git a/build/moz.configure/init.configure b/build/moz.configure/init.configure
index 26124e950be6..2496174751e3 100644
--- a/build/moz.configure/init.configure
+++ b/build/moz.configure/init.configure
@@ -65,20 +65,19 @@ def check_build_environment(help, dist):
return result
-set_config('TOPSRCDIR', delayed_getattr(check_build_environment, 'topsrcdir'))
-set_config('TOPOBJDIR', delayed_getattr(check_build_environment, 'topobjdir'))
-set_config('MOZ_BUILD_ROOT', delayed_getattr(check_build_environment,
- 'topobjdir'))
-set_config('DIST', delayed_getattr(check_build_environment, 'dist'))
+set_config('TOPSRCDIR', check_build_environment.topsrcdir)
+set_config('TOPOBJDIR', check_build_environment.topobjdir)
+set_config('MOZ_BUILD_ROOT', check_build_environment.topobjdir)
+set_config('DIST', check_build_environment.dist)
add_old_configure_assignment(
- '_topsrcdir', delayed_getattr(check_build_environment, 'topsrcdir'))
+ '_topsrcdir', check_build_environment.topsrcdir)
add_old_configure_assignment(
- '_objdir', delayed_getattr(check_build_environment, 'topobjdir'))
+ '_objdir', check_build_environment.topobjdir)
add_old_configure_assignment(
- 'MOZ_BUILD_ROOT', delayed_getattr(check_build_environment, 'topobjdir'))
+ 'MOZ_BUILD_ROOT', check_build_environment.topobjdir)
add_old_configure_assignment(
- 'DIST', delayed_getattr(check_build_environment, 'dist'))
+ 'DIST', check_build_environment.dist)
option(env='MOZ_AUTOMATION', help='Enable options for automated builds')
set_config('MOZ_AUTOMATION', depends_if('MOZ_AUTOMATION')(lambda x: True))
@@ -558,21 +557,20 @@ def target_variables(target):
INTEL_ARCHITECTURE=target.cpu in ('x86', 'x86_64') or None,
)
-set_config('OS_TARGET', delayed_getattr(target_variables, 'OS_TARGET'))
+set_config('OS_TARGET', target_variables.OS_TARGET)
add_old_configure_assignment('OS_TARGET',
- delayed_getattr(target_variables, 'OS_TARGET'))
-set_config('OS_ARCH', delayed_getattr(target_variables, 'OS_ARCH'))
+ target_variables.OS_TARGET)
+set_config('OS_ARCH', target_variables.OS_ARCH)
add_old_configure_assignment('OS_ARCH',
- delayed_getattr(target_variables, 'OS_ARCH'))
-set_config('OS_TEST', delayed_getattr(target_variables, 'OS_TEST'))
+ target_variables.OS_ARCH)
+set_config('OS_TEST', target_variables.OS_TEST)
add_old_configure_assignment('OS_TEST',
- delayed_getattr(target_variables, 'OS_TEST'))
-set_config('CPU_ARCH', delayed_getattr(target, 'cpu'))
-add_old_configure_assignment('CPU_ARCH', delayed_getattr(target, 'cpu'))
-set_config('INTEL_ARCHITECTURE', delayed_getattr(target_variables,
- 'INTEL_ARCHITECTURE'))
-set_config('TARGET_CPU', delayed_getattr(target, 'raw_cpu'))
-set_config('TARGET_OS', delayed_getattr(target, 'raw_os'))
+ target_variables.OS_TEST)
+set_config('CPU_ARCH', target.cpu)
+add_old_configure_assignment('CPU_ARCH', target.cpu)
+set_config('INTEL_ARCHITECTURE', target_variables.INTEL_ARCHITECTURE)
+set_config('TARGET_CPU', target.raw_cpu)
+set_config('TARGET_OS', target.raw_os)
@depends(host)
@@ -585,10 +583,10 @@ def host_variables(host):
HOST_OS_ARCH=os_arch,
)
-set_config('HOST_CPU_ARCH', delayed_getattr(host, 'cpu'))
-set_config('HOST_OS_ARCH', delayed_getattr(host_variables, 'HOST_OS_ARCH'))
+set_config('HOST_CPU_ARCH', host.cpu)
+set_config('HOST_OS_ARCH', host_variables.HOST_OS_ARCH)
add_old_configure_assignment('HOST_OS_ARCH',
- delayed_getattr(host_variables, 'HOST_OS_ARCH'))
+ host_variables.HOST_OS_ARCH)
@depends(target)
def target_is_windows(target):
@@ -717,19 +715,14 @@ def milestone(build_env, _):
is_nightly=is_nightly,
is_release_or_beta=is_release_or_beta)
-@depends(milestone)
-def is_nightly(milestone):
- return milestone.is_nightly
-
-set_config('GRE_MILESTONE', delayed_getattr(milestone, 'version'))
-set_config('NIGHTLY_BUILD', is_nightly)
-set_define('NIGHTLY_BUILD', is_nightly)
-add_old_configure_assignment('NIGHTLY_BUILD',
- is_nightly)
-set_config('RELEASE_OR_BETA', delayed_getattr(milestone, 'is_release_or_beta'))
-set_define('RELEASE_OR_BETA', delayed_getattr(milestone, 'is_release_or_beta'))
+set_config('GRE_MILESTONE', milestone.version)
+set_config('NIGHTLY_BUILD', milestone.is_nightly)
+set_define('NIGHTLY_BUILD', milestone.is_nightly)
+add_old_configure_assignment('NIGHTLY_BUILD', milestone.is_nightly)
+set_config('RELEASE_OR_BETA', milestone.is_release_or_beta)
+set_define('RELEASE_OR_BETA', milestone.is_release_or_beta)
add_old_configure_assignment('RELEASE_OR_BETA',
- delayed_getattr(milestone, 'is_release_or_beta'))
+ milestone.is_release_or_beta)
# The app update channel is 'default' when not supplied. The value is used in
# the application's confvars.sh (and is made available to a project specific
diff --git a/build/moz.configure/keyfiles.configure b/build/moz.configure/keyfiles.configure
index faaf97b0c717..7c880a741e7d 100644
--- a/build/moz.configure/keyfiles.configure
+++ b/build/moz.configure/keyfiles.configure
@@ -60,5 +60,5 @@ def id_and_secret_keyfile(desc):
name = desc.upper().replace(' ', '_')
- set_config('MOZ_%s_CLIENTID' % name, delayed_getattr(content, 'id'))
- set_config('MOZ_%s_KEY' % name, delayed_getattr(content, 'secret'))
+ set_config('MOZ_%s_CLIENTID' % name, content.id)
+ set_config('MOZ_%s_KEY' % name, content.secret)
diff --git a/build/moz.configure/toolchain.configure b/build/moz.configure/toolchain.configure
index e23cbcfe9e32..a136542f4537 100644
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -27,9 +27,9 @@ def yasm_version(yasm):
# Until we move all the yasm consumers out of old-configure.
# bug 1257904
add_old_configure_assignment('_YASM_MAJOR_VERSION',
- delayed_getattr(yasm_version, 'major'))
+ yasm_version.major)
add_old_configure_assignment('_YASM_MINOR_VERSION',
- delayed_getattr(yasm_version, 'minor'))
+ yasm_version.minor)
@depends(yasm, target)
def yasm_asflags(yasm, target):
@@ -645,7 +645,7 @@ def compiler(language, host_or_target, c_compiler=None, other_compiler=None,
# result from check_prog as CC/CXX/HOST_CC/HOST_CXX and b) have to let
# old-configure AC_SUBST it (because it's autoconf doing it, not us)
compiler = check_prog('_%s' % var, what=what, progs=default_compilers,
- input=delayed_getattr(provided_compiler, 'compiler'),
+ input=provided_compiler.compiler,
paths=toolchain_search_path)
@depends(compiler, provided_compiler, compiler_wrapper, host_or_target)
@@ -791,11 +791,11 @@ def compiler(language, host_or_target, c_compiler=None, other_compiler=None,
# old-configure to do some of its still existing checks.
if language == 'C':
set_config(
- '%s_TYPE' % var, delayed_getattr(valid_compiler, 'type'))
+ '%s_TYPE' % var, valid_compiler.type)
add_old_configure_assignment(
- '%s_TYPE' % var, delayed_getattr(valid_compiler, 'type'))
+ '%s_TYPE' % var, valid_compiler.type)
add_old_configure_assignment(
- '%s_VERSION' % var, delayed_getattr(valid_compiler, 'version'))
+ '%s_VERSION' % var, valid_compiler.version)
valid_compiler = compiler_class(valid_compiler)
diff --git a/build/moz.configure/util.configure b/build/moz.configure/util.configure
index fa4eb5ab54a7..e3a552d82a29 100644
--- a/build/moz.configure/util.configure
+++ b/build/moz.configure/util.configure
@@ -366,27 +366,6 @@ always = dependable(True)
never = dependable(False)
-# Some @depends function return namespaces, and one could want to use one
-# specific attribute from such a namespace as a "value" given to functions
-# such as `set_config`. But those functions do not take immediate values.
-# The `delayed_getattr` function allows access to attributes from the result
-# of a @depends function in a non-immediate manner.
-# @depends('--option')
-# def option(value)
-# return namespace(foo=value)
-# set_config('FOO', delayed_getattr(option, 'foo')
-@template
-def delayed_getattr(func, key):
- @depends(func)
- def result(value):
- # The @depends function we're being passed may have returned
- # None, or an object that simply doesn't have the wanted key.
- # In that case, just return None.
- return getattr(value, key, None)
-
- return result
-
-
# Like @depends, but the decorated function is only called if one of the
# arguments it would be called with has a positive value (bool(value) is True)
@template
diff --git a/build/moz.configure/windows.configure b/build/moz.configure/windows.configure
index b1dc8e2c2bbc..3b01154a8508 100644
--- a/build/moz.configure/windows.configure
+++ b/build/moz.configure/windows.configure
@@ -153,7 +153,7 @@ def valid_windows_sdk_dir(compiler, windows_sdk_dir, target_version,
add_old_configure_assignment(
'WINDOWSSDKDIR',
- delayed_getattr(valid_windows_sdk_dir, 'path'))
+ valid_windows_sdk_dir.path)
add_old_configure_assignment(
'MOZ_WINSDK_MAXVER',
depends(valid_windows_sdk_dir)(
diff --git a/config/rules.mk b/config/rules.mk
index 6f5b489e8154..94cc5556e3d0 100644
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -973,6 +973,7 @@ define CARGO_BUILD
env $(environment_cleaner) $(rustflags_override) \
CARGO_TARGET_DIR=$(CARGO_TARGET_DIR) \
RUSTC=$(RUSTC) \
+ MOZ_SRC=$(topsrcdir) \
MOZ_DIST=$(ABS_DIST) \
LIBCLANG_PATH=$(MOZ_LIBCLANG_PATH) \
CLANG_PATH=$(MOZ_CLANG_PATH) \
diff --git a/devtools/.eslintrc.js b/devtools/.eslintrc.js
index 58e7e67b1554..c927e5d25410 100644
--- a/devtools/.eslintrc.js
+++ b/devtools/.eslintrc.js
@@ -28,6 +28,8 @@ module.exports = {
"setInterval": true,
"setTimeout": true,
"uneval": true,
+ "TextDecoder": true,
+ "TextEncoder": true,
"URL": true,
"WebSocket": true,
"XMLHttpRequest": true
diff --git a/devtools/client/framework/source-map-url-service.js b/devtools/client/framework/source-map-url-service.js
index e8df5a86d0b9..89589b4bd920 100644
--- a/devtools/client/framework/source-map-url-service.js
+++ b/devtools/client/framework/source-map-url-service.js
@@ -83,7 +83,13 @@ SourceMapURLService.prototype.originalPositionFor = async function (url, line, c
await this._sourceMapService.getOriginalURLs(urlInfo);
const location = { sourceId: urlInfo.id, line, column, sourceUrl: url };
let resolvedLocation = await this._sourceMapService.getOriginalLocation(location);
- return resolvedLocation === location ? null : resolvedLocation;
+ if (!resolvedLocation ||
+ (resolvedLocation.line === location.line &&
+ resolvedLocation.column === location.column &&
+ resolvedLocation.sourceUrl === location.sourceUrl)) {
+ return null;
+ }
+ return resolvedLocation;
};
exports.SourceMapURLService = SourceMapURLService;
diff --git a/devtools/client/inspector/test/browser.ini b/devtools/client/inspector/test/browser.ini
index 3a957850fd4b..e42ec4d24eee 100644
--- a/devtools/client/inspector/test/browser.ini
+++ b/devtools/client/inspector/test/browser.ini
@@ -68,6 +68,7 @@ skip-if = os == "mac" # Full keyboard navigation on OSX only works if Full Keybo
[browser_inspector_highlighter-02.js]
[browser_inspector_highlighter-03.js]
[browser_inspector_highlighter-04.js]
+[browser_inspector_highlighter-05.js]
[browser_inspector_highlighter-by-type.js]
[browser_inspector_highlighter-cancel.js]
[browser_inspector_highlighter-comments.js]
diff --git a/devtools/client/inspector/test/browser_inspector_highlighter-05.js b/devtools/client/inspector/test/browser_inspector_highlighter-05.js
new file mode 100644
index 000000000000..70829ec542f8
--- /dev/null
+++ b/devtools/client/inspector/test/browser_inspector_highlighter-05.js
@@ -0,0 +1,69 @@
+/* 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/. */
+
+"use strict";
+
+// This is testing that the Anonymous Content is properly inserted into the document.
+// Usually that is happening during the "interactive" state of the document, to have them
+// ready as soon as possible.
+// However, in some conditions, that's not possible since we don't have access yet to
+// the `CustomContentContainer`, that is used to add the Anonymous Content.
+// That can happen if the page has some external resource, as , that takes time
+// to load and / or returns the wrong content. This is not happening, for instance, with
+// images.
+//
+// In those case, we want to be sure that if we're not able to insert the Anonymous
+// Content at the "interactive" state, we're doing so when the document is loaded.
+//
+// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1365075
+
+const server = createTestHTTPServer();
+const filepath = "/slow.css";
+const cssuri = `http://localhost:${server.identity.primaryPort}${filepath}`;
+
+// Register a slow css file handler so we can simulate a long loading time.
+server.registerContentType("css", "text/css");
+server.registerPathHandler(filepath, (metadata, response) => {
+ info("CSS has been requested");
+ response.processAsync();
+ setTimeout(() => {
+ info("CSS is responding");
+ response.finish();
+ }, 2000);
+});
+
+const TEST_URL = "data:text/html," + encodeURIComponent(`
+
+
+
+
+
+
+
Slow page
+
+
+`);
+
+add_task(function* () {
+ info("Open the inspector to a blank page.");
+ let { inspector, tab, testActor } = yield openInspectorForURL("about:blank");
+
+ let pageLoaded = waitForPageLoad(tab);
+
+ info("Navigate to the test url and waiting for the page to be loaded.");
+ yield navigateTo(inspector, TEST_URL);
+ yield pageLoaded;
+
+ info("Shows the box model highligher for the