Merge mozilla-inbound to mozilla-central a=merge
authorDorel Luca <dluca@mozilla.com>
Sun, 02 Jun 2019 12:43:23 +0300
changeset 476549 afb588ff09317067dcc2558d8f14546a332d1162
parent 476516 f31bc32ead2099eb9d14663d456c0bf0b04f53e2 (current diff)
parent 476548 3057e44b38b2856ac09032f2835ce9967caace87 (diff)
child 476552 328fbe865833ad7bea3b5f306288733ba615c007
child 476558 2ced46502b550e82b1d3e8a5abc3580b9954c2bc
push id36098
push userdluca@mozilla.com
push dateSun, 02 Jun 2019 09:44:49 +0000
treeherdermozilla-central@afb588ff0931 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone69.0a1
first release with
nightly linux32
afb588ff0931 / 69.0a1 / 20190602094449 / files
nightly linux64
afb588ff0931 / 69.0a1 / 20190602094449 / files
nightly mac
afb588ff0931 / 69.0a1 / 20190602094449 / files
nightly win32
afb588ff0931 / 69.0a1 / 20190602094449 / files
nightly win64
afb588ff0931 / 69.0a1 / 20190602094449 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-inbound to mozilla-central a=merge
browser/base/content/browser.xhtml
browser/base/content/browser.xul
dom/ipc/ContentChild.cpp
layout/xul/BoxObject.cpp
layout/xul/BoxObject.h
layout/xul/nsIBoxObject.idl
layout/xul/nsPIBoxObject.h
--- a/browser/base/content/browser.xhtml
+++ b/browser/base/content/browser.xhtml
@@ -1,3 +1,1378 @@
-#define BROWSER_XHTML
-#include browser.xul
-#undef BROWSER_XHTML
+#filter substitution
+<?xml version="1.0"?>
+# -*- Mode: HTML -*-
+#
+# 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/.
+
+<!-- The "global.css" stylesheet is imported first to allow other stylesheets to
+     override rules using selectors with the same specificity. This applies to
+     both "content" and "skin" packages, which bug 1385444 will unify later. -->
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<!-- While these stylesheets are defined in Toolkit, they are only used in the
+     main browser window, so we can load them here. Bug 1474241 is on file to
+     consider moving these widgets to the "browser" folder. -->
+<?xml-stylesheet href="chrome://global/content/tabprompts.css" type="text/css"?>
+<?xml-stylesheet href="chrome://global/skin/tabprompts.css" type="text/css"?>
+
+<?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/content/tabbrowser.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/content/downloads/downloads.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/content/places/places.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/content/usercontext/usercontext.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/controlcenter/panel.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/customizableui/panelUI.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/downloads/downloads.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/searchbar.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/places/tree-icons.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/places/editBookmark.css" type="text/css"?>
+
+# All DTD information is stored in a separate file so that it can be shared by
+# hiddenWindowMac.xhtml.
+<!DOCTYPE window [
+#include browser-doctype.inc
+]>
+
+<window id="main-window"
+        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+        xmlns:svg="http://www.w3.org/2000/svg"
+        xmlns:html="http://www.w3.org/1999/xhtml"
+        xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="&mainWindow.title;"
+        title_normal="&mainWindow.title;"
+#ifdef XP_MACOSX
+        title_privatebrowsing="&mainWindow.title;&mainWindow.titlemodifiermenuseparator;&mainWindow.titlePrivateBrowsingSuffix;"
+        titledefault="&mainWindow.title;"
+        titlemodifier=""
+        titlemodifier_normal=""
+        titlemodifier_privatebrowsing="&mainWindow.titlePrivateBrowsingSuffix;"
+#else
+        title_privatebrowsing="&mainWindow.titlemodifier; &mainWindow.titlePrivateBrowsingSuffix;"
+        titlemodifier="&mainWindow.titlemodifier;"
+        titlemodifier_normal="&mainWindow.titlemodifier;"
+        titlemodifier_privatebrowsing="&mainWindow.titlemodifier; &mainWindow.titlePrivateBrowsingSuffix;"
+#endif
+#ifdef XP_WIN
+        chromemargin="0,2,2,2"
+#else
+        chromemargin="0,-1,-1,-1"
+#endif
+        tabsintitlebar="true"
+        titlemenuseparator="&mainWindow.titlemodifiermenuseparator;"
+        windowtype="navigator:browser"
+        macanimationtype="document"
+        screenX="4" screenY="4"
+        fullscreenbutton="true"
+        sizemode="normal"
+        retargetdocumentfocus="urlbar"
+        persist="screenX screenY width height sizemode"
+        mozpersist=""
+        >
+
+# All JS files which are needed by browser.xhtml and other top level windows to
+# support MacOS specific features *must* go into the global-scripts.inc file so
+# that they can be shared with macWindow.inc.xul.
+#include global-scripts.inc
+
+<script>
+  /* eslint-env mozilla/browser-window */
+  Services.scriptloader.loadSubScript("chrome://global/content/contentAreaUtils.js", this);
+  Services.scriptloader.loadSubScript("chrome://browser/content/browser-captivePortal.js", this);
+  Services.scriptloader.loadSubScript("chrome://browser/content/browser-contentblocking.js", this);
+  if (AppConstants.MOZ_DATA_REPORTING) {
+    Services.scriptloader.loadSubScript("chrome://browser/content/browser-data-submission-info-bar.js", this);
+  }
+  if (!AppConstants.MOZILLA_OFFICIAL) {
+    Services.scriptloader.loadSubScript("chrome://browser/content/browser-development-helpers.js", this);
+  }
+  Services.scriptloader.loadSubScript("chrome://browser/content/browser-media.js", this);
+  Services.scriptloader.loadSubScript("chrome://browser/content/browser-pageActions.js", this);
+  Services.scriptloader.loadSubScript("chrome://browser/content/browser-plugins.js", this);
+  Services.scriptloader.loadSubScript("chrome://browser/content/browser-sidebar.js", this);
+  Services.scriptloader.loadSubScript("chrome://browser/content/browser-tabsintitlebar.js", this);
+  Services.scriptloader.loadSubScript("chrome://browser/content/tabbrowser.js", this);
+  Services.scriptloader.loadSubScript("chrome://browser/content/tabbrowser-tab.js", this);
+  Services.scriptloader.loadSubScript("chrome://browser/content/search/autocomplete-popup.js", this);
+  Services.scriptloader.loadSubScript("chrome://browser/content/search/searchbar.js", this);
+
+  window.onload = gBrowserInit.onLoad.bind(gBrowserInit);
+  window.onunload = gBrowserInit.onUnload.bind(gBrowserInit);
+  window.onclose = WindowIsClosing;
+
+  window.addEventListener("MozBeforeInitialXULLayout",
+    gBrowserInit.onBeforeInitialXULLayout.bind(gBrowserInit), { once: true });
+
+  // The listener of DOMContentLoaded must be set on window, rather than
+  // document, because the window can go away before the event is fired.
+  // In that case, we don't want to initialize anything, otherwise we
+  // may be leaking things because they will never be destroyed after.
+  window.addEventListener("DOMContentLoaded",
+    gBrowserInit.onDOMContentLoaded.bind(gBrowserInit), { once: true });
+</script>
+
+# All sets except for popupsets (commands, keys, and stringbundles)
+# *must* go into the browser-sets.inc file so that they can be shared with other
+# top level windows in macWindow.inc.xul.
+#include browser-sets.inc
+
+  <popupset id="mainPopupSet">
+    <menupopup id="tabContextMenu"
+               onpopupshowing="if (event.target == this) TabContextMenu.updateContextMenu(this);"
+               onpopuphidden="if (event.target == this) TabContextMenu.contextTab = null;">
+      <menuitem id="context_reloadTab" data-lazy-l10n-id="reload-tab"
+                oncommand="gBrowser.reloadTab(TabContextMenu.contextTab);"/>
+      <menuitem id="context_reloadSelectedTabs" data-lazy-l10n-id="reload-tabs" hidden="true"
+                oncommand="gBrowser.reloadMultiSelectedTabs();"/>
+      <menuitem id="context_toggleMuteTab" oncommand="TabContextMenu.contextTab.toggleMuteAudio();"/>
+      <menuitem id="context_toggleMuteSelectedTabs" hidden="true"
+                oncommand="gBrowser.toggleMuteAudioOnMultiSelectedTabs(TabContextMenu.contextTab);"/>
+      <menuitem id="context_pinTab" data-lazy-l10n-id="pin-tab"
+                oncommand="gBrowser.pinTab(TabContextMenu.contextTab);"/>
+      <menuitem id="context_unpinTab" data-lazy-l10n-id="unpin-tab" hidden="true"
+                oncommand="gBrowser.unpinTab(TabContextMenu.contextTab);"/>
+      <menuitem id="context_pinSelectedTabs" data-lazy-l10n-id="pin-selected-tabs" hidden="true"
+                oncommand="gBrowser.pinMultiSelectedTabs();"/>
+      <menuitem id="context_unpinSelectedTabs" data-lazy-l10n-id="unpin-selected-tabs" hidden="true"
+                oncommand="gBrowser.unpinMultiSelectedTabs();"/>
+      <menuitem id="context_duplicateTab" data-lazy-l10n-id="duplicate-tab"
+                oncommand="duplicateTabIn(TabContextMenu.contextTab, 'tab');"/>
+      <menuitem id="context_duplicateTabs" data-lazy-l10n-id="duplicate-tabs"
+                oncommand="TabContextMenu.duplicateSelectedTabs();"/>
+      <menuseparator/>
+      <menuitem id="context_selectAllTabs" data-lazy-l10n-id="select-all-tabs"
+                oncommand="gBrowser.selectAllTabs();"/>
+      <menuitem id="context_bookmarkSelectedTabs"
+                hidden="true"
+                data-lazy-l10n-id="bookmark-selected-tabs"
+                oncommand="PlacesCommandHook.bookmarkPages(PlacesCommandHook.uniqueSelectedPages);"/>
+      <menuitem id="context_bookmarkTab"
+                data-lazy-l10n-id="bookmark-tab"
+                oncommand="PlacesCommandHook.bookmarkPages(PlacesCommandHook.getUniquePages([TabContextMenu.contextTab]));"/>
+      <menu id="context_reopenInContainer"
+            data-lazy-l10n-id="reopen-in-container"
+            hidden="true">
+        <menupopup oncommand="TabContextMenu.reopenInContainer(event);"
+                   onpopupshowing="TabContextMenu.createReopenInContainerMenu(event);"/>
+      </menu>
+      <menu id="context_moveTabOptions">
+        <menupopup id="moveTabOptionsMenu">
+          <menuitem id="context_moveToStart"
+                    data-lazy-l10n-id="move-to-start"
+                    tbattr="tabbrowser-multiple"
+                    oncommand="gBrowser.moveTabsToStart(TabContextMenu.contextTab);"/>
+          <menuitem id="context_moveToEnd"
+                    data-lazy-l10n-id="move-to-end"
+                    tbattr="tabbrowser-multiple"
+                    oncommand="gBrowser.moveTabsToEnd(TabContextMenu.contextTab);"/>
+          <menuitem id="context_openTabInWindow" data-lazy-l10n-id="move-to-new-window"
+                    tbattr="tabbrowser-multiple"
+                    oncommand="gBrowser.replaceTabsWithWindow(TabContextMenu.contextTab);"/>
+        </menupopup>
+      </menu>
+      <menu id="context_sendTabToDevice"
+            class="sync-ui-item">
+        <menupopup id="context_sendTabToDevicePopupMenu"
+                   onpopupshowing="gSync.populateSendTabToDevicesMenu(event.target, TabContextMenu.contextTab.linkedBrowser.currentURI.spec, TabContextMenu.contextTab.linkedBrowser.contentTitle, TabContextMenu.contextTab.multiselected);"/>
+      </menu>
+      <menuseparator/>
+      <menuitem id="context_closeTabsToTheEnd" data-lazy-l10n-id="close-tabs-to-the-end"
+                oncommand="gBrowser.removeTabsToTheEndFrom(TabContextMenu.contextTab, {animate: true});"/>
+      <menuitem id="context_closeOtherTabs" data-lazy-l10n-id="close-other-tabs"
+                oncommand="gBrowser.removeAllTabsBut(TabContextMenu.contextTab);"/>
+      <menuitem id="context_undoCloseTab"
+                data-lazy-l10n-id="undo-close-tab"
+                observes="History:UndoCloseTab"/>
+      <menuitem id="context_closeTab" data-lazy-l10n-id="close-tab"
+                oncommand="gBrowser.removeTab(TabContextMenu.contextTab, { animate: true });"/>
+      <menuitem id="context_closeSelectedTabs" data-lazy-l10n-id="close-tabs"
+                hidden="true"
+                oncommand="gBrowser.removeMultiSelectedTabs();"/>
+    </menupopup>
+
+    <!-- bug 415444/582485: event.stopPropagation is here for the cloned version
+         of this menupopup -->
+    <menupopup id="backForwardMenu"
+               onpopupshowing="return FillHistoryMenu(event.target);"
+               oncommand="gotoHistoryIndex(event); event.stopPropagation();"
+               onclick="checkForMiddleClick(this, event);"/>
+    <tooltip id="aHTMLTooltip" page="true"/>
+    <tooltip id="remoteBrowserTooltip"/>
+
+    <!-- for search and content formfill/pw manager -->
+
+    <panel is="autocomplete-richlistbox-popup"
+           type="autocomplete-richlistbox"
+           id="PopupAutoComplete"
+           role="group"
+           noautofocus="true"
+           hidden="true"
+           overflowpadding="4"
+           norolluponanchor="true"
+           nomaxresults="true" />
+
+    <!-- for search with one-off buttons -->
+    <panel is="search-autocomplete-richlistbox-popup"
+           type="autocomplete-richlistbox"
+           id="PopupSearchAutoComplete"
+           role="group"
+           noautofocus="true"
+           hidden="true" />
+
+    <!-- for url bar autocomplete -->
+    <panel type="autocomplete-richlistbox"
+           id="PopupAutoCompleteRichResult"
+           role="group"
+           noautofocus="true"
+           hidden="true"
+           flip="none"
+           level="parent"
+           overflowpadding="15" />
+
+    <!-- for date/time picker. consumeoutsideclicks is set to never, so that
+         clicks on the anchored input box are never consumed. -->
+    <panel id="DateTimePickerPanel"
+           type="arrow"
+           hidden="true"
+           orient="vertical"
+           noautofocus="true"
+           norolluponanchor="true"
+           consumeoutsideclicks="never"
+           level="parent"
+           tabspecific="true">
+    </panel>
+
+    <!-- for select dropdowns. The menupopup is what shows the list of options,
+         and the popuponly menulist makes things like the menuactive attributes
+         work correctly on the menupopup. ContentSelectDropdown expects the
+         popuponly menulist to be its immediate parent. -->
+    <menulist popuponly="true" id="ContentSelectDropdown" hidden="true">
+      <menupopup rolluponmousewheel="true"
+                 activateontab="true" position="after_start"
+                 level="parent"
+#ifdef XP_WIN
+                 consumeoutsideclicks="false" ignorekeys="shortcuts"
+#endif
+        />
+    </menulist>
+
+    <!-- for invalid form error message -->
+    <panel id="invalid-form-popup" type="arrow" orient="vertical" noautofocus="true" hidden="true" level="parent">
+      <description/>
+    </panel>
+
+    <panel id="editBookmarkPanel"
+           type="arrow"
+           orient="vertical"
+           ignorekeys="true"
+           hidden="true"
+           tabspecific="true"
+           aria-labelledby="editBookmarkPanelTitle">
+      <box class="panel-header">
+        <label id="editBookmarkPanelTitle"/>
+        <toolbarbutton id="editBookmarkPanelInfoButton" oncommand="StarUI.toggleRecommendation();" >
+          <image/>
+        </toolbarbutton>
+      </box>
+      <html:div id="editBookmarkPanelInfoArea">
+        <html:div id="editBookmarkPanelRecommendation"></html:div>
+        <html:div id="editBookmarkPanelFaviconContainer">
+          <html:img id="editBookmarkPanelFavicon"/>
+        </html:div>
+        <html:div id="editBookmarkPanelImage"></html:div>
+      </html:div>
+#include ../../components/places/content/editBookmarkPanel.inc.xul
+      <vbox id="editBookmarkPanelBottomContent"
+            flex="1">
+        <checkbox id="editBookmarkPanel_showForNewBookmarks"
+                  label="&editBookmark.showForNewBookmarks.label;"
+                  accesskey="&editBookmark.showForNewBookmarks.accesskey;"
+                  oncommand="StarUI.onShowForNewBookmarksCheckboxCommand();"/>
+      </vbox>
+      <hbox id="editBookmarkPanelBottomButtons"
+            class="panel-footer"
+            style="min-width: &editBookmark.panel.width;;">
+#ifndef XP_UNIX
+        <button id="editBookmarkPanelDoneButton"
+                class="editBookmarkPanelBottomButton"
+                label="&editBookmark.done.label;"
+                default="true"
+                oncommand="StarUI.panel.hidePopup();"/>
+        <button id="editBookmarkPanelRemoveButton"
+                class="editBookmarkPanelBottomButton"
+                oncommand="StarUI.removeBookmarkButtonCommand();"/>
+#else
+        <button id="editBookmarkPanelRemoveButton"
+                class="editBookmarkPanelBottomButton"
+                oncommand="StarUI.removeBookmarkButtonCommand();"/>
+        <button id="editBookmarkPanelDoneButton"
+                class="editBookmarkPanelBottomButton"
+                label="&editBookmark.done.label;"
+                default="true"
+                oncommand="StarUI.panel.hidePopup();"/>
+#endif
+      </hbox>
+    </panel>
+
+    <!-- UI tour experience -->
+    <panel id="UITourTooltip"
+           type="arrow"
+           hidden="true"
+           noautofocus="true"
+           noautohide="true"
+           align="start"
+           orient="vertical"
+           role="alert">
+     <vbox>
+      <hbox id="UITourTooltipBody">
+        <image id="UITourTooltipIcon"/>
+        <vbox flex="1">
+          <hbox id="UITourTooltipTitleContainer">
+            <label id="UITourTooltipTitle" flex="1"/>
+            <toolbarbutton id="UITourTooltipClose" class="close-icon"
+                           tooltiptext="&uiTour.infoPanel.close;"/>
+          </hbox>
+          <description id="UITourTooltipDescription" flex="1"/>
+        </vbox>
+      </hbox>
+      <hbox id="UITourTooltipButtons" flex="1" align="center"/>
+     </vbox>
+    </panel>
+    <!-- type="default" forces frames to be created so that the panel's size can be determined -->
+    <panel id="UITourHighlightContainer"
+           type="default"
+           hidden="true"
+           noautofocus="true"
+           noautohide="true"
+           flip="none"
+           consumeoutsideclicks="false"
+           mousethrough="always">
+      <box id="UITourHighlight"></box>
+    </panel>
+
+    <panel id="sidebarMenu-popup"
+           class="cui-widget-panel"
+           role="group"
+           type="arrow"
+           hidden="true"
+           flip="slide"
+           orient="vertical"
+           position="bottomcenter topleft">
+      <toolbarbutton id="sidebar-switcher-bookmarks"
+                     type="checkbox"
+                     label="&bookmarksButton.label;"
+                     class="subviewbutton subviewbutton-iconic"
+                     key="viewBookmarksSidebarKb"
+                     oncommand="SidebarUI.show('viewBookmarksSidebar');"/>
+      <toolbarbutton id="sidebar-switcher-history"
+                     type="checkbox"
+                     label="&historyButton.label;"
+                     class="subviewbutton subviewbutton-iconic"
+                     key="key_gotoHistory"
+                     oncommand="SidebarUI.show('viewHistorySidebar');"/>
+      <toolbarbutton id="sidebar-switcher-tabs"
+                     type="checkbox"
+                     label="&syncedTabs.sidebar.label;"
+                     class="subviewbutton subviewbutton-iconic sync-ui-item"
+                     oncommand="SidebarUI.show('viewTabsSidebar');"/>
+      <toolbarseparator/>
+      <!-- Extension toolbarbuttons go here. -->
+      <toolbarseparator id="sidebar-extensions-separator"/>
+      <toolbarbutton id="sidebar-reverse-position"
+                     class="subviewbutton"
+                     oncommand="SidebarUI.reversePosition()"/>
+      <toolbarseparator/>
+      <toolbarbutton label="&sidebarMenuClose.label;"
+                     class="subviewbutton"
+                     oncommand="SidebarUI.hide()"/>
+    </panel>
+
+    <menupopup id="toolbar-context-menu"
+               onpopupshowing="onViewToolbarsPopupShowing(event, document.getElementById('viewToolbarsMenuSeparator')); ToolbarContextMenu.updateDownloadsAutoHide(this); ToolbarContextMenu.updateExtension(this)">
+      <menuitem oncommand="ToolbarContextMenu.openAboutAddonsForContextAction(this.parentElement)"
+                accesskey="&customizeMenu.manageExtension.accesskey;"
+                label="&customizeMenu.manageExtension.label;"
+                contexttype="toolbaritem"
+                class="customize-context-manageExtension"/>
+      <menuitem oncommand="ToolbarContextMenu.removeExtensionForContextAction(this.parentElement)"
+                accesskey="&customizeMenu.removeExtension.accesskey;"
+                label="&customizeMenu.removeExtension.label;"
+                contexttype="toolbaritem"
+                class="customize-context-removeExtension"/>
+      <menuitem oncommand="ToolbarContextMenu.reportExtensionForContextAction(this.parentElement, 'toolbar_context_menu')"
+                accesskey="&customizeMenu.reportExtension.accesskey;"
+                label="&customizeMenu.reportExtension.label;"
+                contexttype="toolbaritem"
+                class="customize-context-reportExtension"/>
+      <menuseparator/>
+      <menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode)"
+                accesskey="&customizeMenu.pinToOverflowMenu.accesskey;"
+                label="&customizeMenu.pinToOverflowMenu.label;"
+                contexttype="toolbaritem"
+                class="customize-context-moveToPanel"/>
+      <menuitem id="toolbar-context-autohide-downloads-button"
+                oncommand="ToolbarContextMenu.onDownloadsAutoHideChange(event);"
+                type="checkbox"
+                accesskey="&customizeMenu.autoHideDownloadsButton.accesskey;"
+                label="&customizeMenu.autoHideDownloadsButton.label;"
+                contexttype="toolbaritem"/>
+      <menuitem oncommand="gCustomizeMode.removeFromArea(document.popupNode)"
+                accesskey="&customizeMenu.removeFromToolbar.accesskey;"
+                label="&customizeMenu.removeFromToolbar.label;"
+                contexttype="toolbaritem"
+                class="customize-context-removeFromToolbar"/>
+      <menuitem id="toolbar-context-reloadSelectedTab"
+                contexttype="tabbar"
+                oncommand="gBrowser.reloadMultiSelectedTabs();"
+                data-lazy-l10n-id="toolbar-context-menu-reload-selected-tab"/>
+      <menuitem id="toolbar-context-reloadSelectedTabs"
+                contexttype="tabbar"
+                oncommand="gBrowser.reloadMultiSelectedTabs();"
+                data-lazy-l10n-id="toolbar-context-menu-reload-selected-tabs"/>
+      <menuitem id="toolbar-context-bookmarkSelectedTab"
+                contexttype="tabbar"
+                oncommand="PlacesCommandHook.bookmarkPages(PlacesCommandHook.uniqueSelectedPages);"
+                data-lazy-l10n-id="toolbar-context-menu-bookmark-selected-tab"/>
+      <menuitem id="toolbar-context-bookmarkSelectedTabs"
+                contexttype="tabbar"
+                oncommand="PlacesCommandHook.bookmarkPages(PlacesCommandHook.uniqueSelectedPages);"
+                data-lazy-l10n-id="toolbar-context-menu-bookmark-selected-tabs"/>
+      <menuitem id="toolbar-context-selectAllTabs"
+                contexttype="tabbar"
+                oncommand="gBrowser.selectAllTabs();"
+                data-lazy-l10n-id="toolbar-context-menu-select-all-tabs"/>
+      <menuitem id="toolbar-context-undoCloseTab"
+                contexttype="tabbar"
+                data-lazy-l10n-id="toolbar-context-menu-undo-close-tab"
+                observes="History:UndoCloseTab"/>
+      <menuseparator/>
+      <menuseparator id="viewToolbarsMenuSeparator"/>
+      <!-- XXXgijs: we're using oncommand handler here to avoid the event being
+                    redirected to the command element, thus preventing
+                    listeners on the menupopup or further up the tree from
+                    seeing the command event pass by. The observes attribute is
+                    here so that the menuitem is still disabled and re-enabled
+                    correctly. -->
+      <menuitem oncommand="gCustomizeMode.enter()"
+                observes="cmd_CustomizeToolbars"
+                class="viewCustomizeToolbar"
+                label="&viewCustomizeToolbar.label;"
+                accesskey="&viewCustomizeToolbar.accesskey;"/>
+    </menupopup>
+
+    <menupopup id="blockedPopupOptions"
+               onpopupshowing="gPopupBlockerObserver.fillPopupList(event);"
+               onpopuphiding="gPopupBlockerObserver.onPopupHiding(event);">
+      <menuitem id="blockedPopupAllowSite"
+                accesskey="&allowPopups.accesskey;"
+                oncommand="gPopupBlockerObserver.toggleAllowPopupsForSite(event);"/>
+      <menuitem
+#ifdef XP_WIN
+                label="&editPopupSettings.label;"
+#else
+                label="&editPopupSettingsUnix.label;"
+#endif
+                accesskey="&editPopupSettings.accesskey;"
+                oncommand="gPopupBlockerObserver.editPopupSettings();"/>
+      <menuitem id="blockedPopupDontShowMessage"
+                accesskey="&dontShowMessage.accesskey;"
+                type="checkbox"
+                oncommand="gPopupBlockerObserver.dontShowMessage();"/>
+      <menuseparator id="blockedPopupsSeparator"/>
+    </menupopup>
+
+    <menupopup id="autohide-context"
+           onpopupshowing="FullScreen.getAutohide(this.firstChild);">
+      <menuitem type="checkbox" label="&fullScreenAutohide.label;"
+                accesskey="&fullScreenAutohide.accesskey;"
+                oncommand="FullScreen.setAutohide();"/>
+      <menuseparator/>
+      <menuitem label="&fullScreenExit.label;"
+                accesskey="&fullScreenExit.accesskey;"
+                oncommand="BrowserFullScreen();"/>
+    </menupopup>
+
+    <menupopup id="contentAreaContextMenu" pagemenu="#page-menu-separator"
+               onpopupshowing="if (event.target != this)
+                                 return true;
+                               gContextMenu = new nsContextMenu(this, event.shiftKey);
+                               if (gContextMenu.shouldDisplay)
+                                 updateEditUIVisibility();
+                               return gContextMenu.shouldDisplay;"
+               onpopuphiding="if (event.target != this)
+                                return;
+                              gContextMenu.hiding();
+                              gContextMenu = null;
+                              updateEditUIVisibility();">
+#include browser-context.inc
+    </menupopup>
+
+#include ../../components/places/content/placesContextMenu.inc.xul
+
+    <panel id="ctrlTab-panel" hidden="true" norestorefocus="true" level="top">
+      <hbox id="ctrlTab-previews"/>
+      <hbox id="ctrlTab-showAll-container" pack="center"/>
+    </panel>
+
+    <panel id="pageActionPanel"
+           class="cui-widget-panel"
+           role="group"
+           type="arrow"
+           hidden="true"
+           flip="slide"
+           photon="true"
+           position="bottomcenter topright"
+           tabspecific="true"
+           noautofocus="true"
+           pinTab-title="&pinTab.label;"
+           unpinTab-title="&unpinTab.label;"
+           pocket-title="&saveToPocketCmd.label;"
+           copyURL-title="&pageAction.copyLink.label;"
+           emailLink-title="&emailPageCmd.label;"
+           sendToDevice-notReadyTitle="&sendToDevice.syncNotReady.label;"
+           shareURL-title="&pageAction.shareUrl.label;"
+           shareMore-label="&pageAction.shareMore.label;">
+      <panelmultiview id="pageActionPanelMultiView"
+                      mainViewId="pageActionPanelMainView"
+                      viewCacheId="appMenu-viewCache">
+        <panelview id="pageActionPanelMainView"
+                   context="pageActionContextMenu"
+                   class="PanelUI-subView">
+          <vbox class="panel-subview-body"/>
+        </panelview>
+      </panelmultiview>
+    </panel>
+
+    <panel id="confirmation-hint"
+           role="alert"
+           type="arrow"
+           hidden="true"
+           flip="slide"
+           position="bottomcenter topright"
+           tabspecific="true"
+           noautofocus="true">
+      <hbox id="confirmation-hint-checkmark-animation-container">
+       <image id="confirmation-hint-checkmark-image"/>
+      </hbox>
+      <vbox id="confirmation-hint-message-container">
+       <label id="confirmation-hint-message"/>
+       <label id="confirmation-hint-description"/>
+      </vbox>
+    </panel>
+
+    <menupopup id="pageActionContextMenu"
+               onpopupshowing="BrowserPageActions.onContextMenuShowing(event, this);">
+      <menuitem class="pageActionContextMenuItem builtInUnpinned"
+                label="&pageAction.addToUrlbar.label;"
+                oncommand="BrowserPageActions.togglePinningForContextAction();"/>
+      <menuitem class="pageActionContextMenuItem builtInPinned"
+                label="&pageAction.removeFromUrlbar.label;"
+                oncommand="BrowserPageActions.togglePinningForContextAction();"/>
+      <menuitem class="pageActionContextMenuItem extensionUnpinned"
+                label="&pageAction.addToUrlbar.label;"
+                oncommand="BrowserPageActions.togglePinningForContextAction();"/>
+      <menuitem class="pageActionContextMenuItem extensionPinned"
+                label="&pageAction.removeFromUrlbar.label;"
+                oncommand="BrowserPageActions.togglePinningForContextAction();"/>
+      <menuseparator class="pageActionContextMenuItem extensionPinned extensionUnpinned"/>
+      <menuitem class="pageActionContextMenuItem extensionPinned extensionUnpinned"
+                label="&pageAction.manageExtension.label;"
+                oncommand="BrowserPageActions.openAboutAddonsForContextAction();"/>
+    </menupopup>
+
+#include ../../components/places/content/bookmarksHistoryTooltip.inc.xul
+
+    <tooltip id="tabbrowser-tab-tooltip" onpopupshowing="gBrowser.createTooltip(event);"/>
+
+    <tooltip id="back-button-tooltip">
+      <description class="tooltip-label" value="&backButton.tooltip;"/>
+#ifdef XP_MACOSX
+      <description class="tooltip-label" value="&backForwardButtonMenuMac.tooltip;"/>
+#else
+      <description class="tooltip-label" value="&backForwardButtonMenu.tooltip;"/>
+#endif
+    </tooltip>
+
+    <tooltip id="forward-button-tooltip">
+      <description class="tooltip-label" value="&forwardButton.tooltip;"/>
+#ifdef XP_MACOSX
+      <description class="tooltip-label" value="&backForwardButtonMenuMac.tooltip;"/>
+#else
+      <description class="tooltip-label" value="&backForwardButtonMenu.tooltip;"/>
+#endif
+    </tooltip>
+
+#include popup-notifications.inc
+
+#include ../../components/customizableui/content/panelUI.inc.xul
+#include ../../components/controlcenter/content/identityPanel.inc.xul
+#include ../../components/controlcenter/content/protectionsPanel.inc.xul
+#include ../../components/downloads/content/downloadsPanel.inc.xul
+#include browser-allTabsMenu.inc.xul
+
+    <hbox id="downloads-animation-container" mousethrough="always">
+      <vbox id="downloads-notification-anchor" hidden="true">
+        <vbox id="downloads-indicator-notification"/>
+      </vbox>
+    </hbox>
+
+    <tooltip id="dynamic-shortcut-tooltip"
+             onpopupshowing="UpdateDynamicShortcutTooltipText(this);"/>
+
+    <menupopup id="SyncedTabsSidebarContext">
+      <menuitem data-lazy-l10n-id="synced-tabs-context-open"
+                id="syncedTabsOpenSelected" where="current"/>
+      <menuitem data-lazy-l10n-id="synced-tabs-context-open-in-new-tab"
+                id="syncedTabsOpenSelectedInTab" where="tab"/>
+      <menuitem data-lazy-l10n-id="synced-tabs-context-open-in-new-window"
+                id="syncedTabsOpenSelectedInWindow" where="window"/>
+      <menuitem data-lazy-l10n-id="synced-tabs-context-open-in-new-private-window"
+                id="syncedTabsOpenSelectedInPrivateWindow" where="window" private="true"/>
+      <menuseparator/>
+      <menuitem data-lazy-l10n-id="synced-tabs-context-bookmark-single-tab"
+                id="syncedTabsBookmarkSelected"/>
+      <menuitem data-lazy-l10n-id="synced-tabs-context-copy"
+                id="syncedTabsCopySelected"/>
+      <menuseparator/>
+      <menuitem data-lazy-l10n-id="synced-tabs-context-open-all-in-tabs"
+                id="syncedTabsOpenAllInTabs"/>
+      <menuitem data-lazy-l10n-id="synced-tabs-context-manage-devices"
+                id="syncedTabsManageDevices"
+                oncommand="gSync.openDevicesManagementPage('syncedtabs-sidebar');"/>
+      <menuitem label="&syncSyncNowItem.label;"
+                accesskey="&syncSyncNowItem.accesskey;"
+                id="syncedTabsRefresh"/>
+    </menupopup>
+    <menupopup id="SyncedTabsSidebarTabsFilterContext"
+               class="textbox-contextmenu">
+      <menuitem label="&undoCmd.label;"
+                accesskey="&undoCmd.accesskey;"
+                cmd="cmd_undo"/>
+      <menuseparator/>
+      <menuitem label="&cutCmd.label;"
+                accesskey="&cutCmd.accesskey;"
+                cmd="cmd_cut"/>
+      <menuitem label="&copyCmd.label;"
+                accesskey="&copyCmd.accesskey;"
+                cmd="cmd_copy"/>
+      <menuitem label="&pasteCmd.label;"
+                accesskey="&pasteCmd.accesskey;"
+                cmd="cmd_paste"/>
+      <menuitem label="&deleteCmd.label;"
+                accesskey="&deleteCmd.accesskey;"
+                cmd="cmd_delete"/>
+      <menuseparator/>
+      <menuitem label="&selectAllCmd.label;"
+                accesskey="&selectAllCmd.accesskey;"
+                cmd="cmd_selectAll"/>
+      <menuseparator/>
+      <menuitem label="&syncSyncNowItem.label;"
+                accesskey="&syncSyncNowItem.accesskey;"
+                id="syncedTabsRefreshFilter"/>
+    </menupopup>
+
+    <hbox id="statuspanel" inactive="true" renderroot="content">
+      <hbox id="statuspanel-inner">
+        <label id="statuspanel-label"
+               role="status"
+               aria-live="off"
+               flex="1"
+               crop="end"/>
+      </hbox>
+    </hbox>
+  </popupset>
+  <box id="appMenu-viewCache" hidden="true"/>
+
+  <toolbox id="navigator-toolbox">
+
+    <vbox id="titlebar">
+      <!-- Menu -->
+      <toolbar type="menubar" id="toolbar-menubar"
+               class="browser-toolbar chromeclass-menubar titlebar-color"
+               customizable="true"
+               mode="icons"
+#ifdef MENUBAR_CAN_AUTOHIDE
+               toolbarname="&menubarCmd.label;"
+               accesskey="&menubarCmd.accesskey;"
+               autohide="true"
+#endif
+               context="toolbar-context-menu">
+        <toolbaritem id="menubar-items" align="center">
+# The entire main menubar is placed into browser-menubar.inc, so that it can be
+# shared with other top level windows in macWindow.inc.xul.
+#include browser-menubar.inc
+        </toolbaritem>
+        <spacer flex="1" skipintoolbarset="true" ordinal="1000"/>
+#include titlebar-items.inc.xul
+      </toolbar>
+
+      <toolbar id="TabsToolbar"
+               class="browser-toolbar titlebar-color"
+               fullscreentoolbar="true"
+               customizable="true"
+               customizationtarget="TabsToolbar-customization-target"
+               mode="icons"
+               aria-label="&tabsToolbar.label;"
+               context="toolbar-context-menu"
+               flex="1">
+
+        <hbox class="titlebar-spacer" type="pre-tabs"/>
+
+        <hbox flex="1" align="end" class="toolbar-items">
+          <hbox id="TabsToolbar-customization-target" flex="1">
+            <tabs id="tabbrowser-tabs"
+                  flex="1"
+                  setfocus="false"
+                  tooltip="tabbrowser-tab-tooltip"
+                  stopwatchid="FX_TAB_CLICK_MS">
+              <tab is="tabbrowser-tab" class="tabbrowser-tab" selected="true" visuallyselected="true" fadein="true"/>
+            </tabs>
+
+            <toolbarbutton id="new-tab-button"
+                           class="toolbarbutton-1 chromeclass-toolbar-additional"
+                           label="&tabCmd.label;"
+                           command="cmd_newNavigatorTab"
+                           onclick="checkForMiddleClick(this, event);"
+                           tooltip="dynamic-shortcut-tooltip"
+                           ondrop="newTabButtonObserver.onDrop(event)"
+                           ondragover="newTabButtonObserver.onDragOver(event)"
+                           ondragenter="newTabButtonObserver.onDragOver(event)"
+                           ondragexit="newTabButtonObserver.onDragExit(event)"
+                           cui-areatype="toolbar"
+                           removable="true"/>
+
+            <toolbarbutton id="alltabs-button"
+                           class="toolbarbutton-1 chromeclass-toolbar-additional tabs-alltabs-button"
+                           badged="true"
+                           oncommand="gTabsPanel.showAllTabsPanel();"
+                           label="&listAllTabs.label;"
+                           tooltiptext="&listAllTabs.label;"
+                           removable="false"/>
+          </hbox>
+        </hbox>
+
+        <hbox class="titlebar-spacer" type="post-tabs"/>
+
+#ifndef XP_MACOSX
+        <button class="accessibility-indicator" tooltiptext="&accessibilityIndicator.tooltip;"
+                aria-live="polite"/>
+        <hbox class="private-browsing-indicator"/>
+#endif
+
+#include titlebar-items.inc.xul
+
+#ifdef XP_MACOSX
+        <!-- OS X does not natively support RTL for its titlebar items, so we prevent this secondary
+             buttonbox from reversing order in RTL by forcing an LTR direction. -->
+        <hbox id="titlebar-secondary-buttonbox" dir="ltr">
+          <button class="accessibility-indicator" tooltiptext="&accessibilityIndicator.tooltip;" aria-live="polite"/>
+          <hbox class="private-browsing-indicator"/>
+          <hbox id="titlebar-fullscreen-button"/>
+        </hbox>
+#endif
+      </toolbar>
+
+    </vbox>
+
+    <toolbar id="nav-bar"
+             class="browser-toolbar"
+             aria-label="&navbarCmd.label;"
+             fullscreentoolbar="true" mode="icons" customizable="true"
+             customizationtarget="nav-bar-customization-target"
+             overflowable="true"
+             overflowbutton="nav-bar-overflow-button"
+             overflowtarget="widget-overflow-list"
+             overflowpanel="widget-overflow"
+             context="toolbar-context-menu">
+
+      <toolbartabstop/>
+      <hbox id="nav-bar-customization-target" flex="1">
+        <toolbarbutton id="back-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
+                       label="&backCmd.label;"
+                       removable="false" overflows="false"
+                       keepbroadcastattributeswhencustomizing="true"
+                       command="Browser:BackOrBackDuplicate"
+                       onclick="checkForMiddleClick(this, event);"
+                       tooltip="back-button-tooltip"
+                       context="backForwardMenu"/>
+        <toolbarbutton id="forward-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
+                       label="&forwardCmd.label;"
+                       removable="false" overflows="false"
+                       keepbroadcastattributeswhencustomizing="true"
+                       command="Browser:ForwardOrForwardDuplicate"
+                       onclick="checkForMiddleClick(this, event);"
+                       tooltip="forward-button-tooltip"
+                       context="backForwardMenu"/>
+        <toolbaritem id="stop-reload-button" class="chromeclass-toolbar-additional"
+                     title="&reloadCmd.label;"
+                     removable="true" overflows="false">
+          <toolbarbutton id="reload-button" class="toolbarbutton-1"
+                         label="&reloadCmd.label;"
+                         command="Browser:ReloadOrDuplicate"
+                         onclick="checkForMiddleClick(this, event);"
+                         tooltip="dynamic-shortcut-tooltip">
+            <box class="toolbarbutton-animatable-box">
+              <image class="toolbarbutton-animatable-image"/>
+            </box>
+          </toolbarbutton>
+          <toolbarbutton id="stop-button" class="toolbarbutton-1"
+                         label="&stopCmd.label;"
+                         command="Browser:Stop"
+                         tooltip="dynamic-shortcut-tooltip">
+            <box class="toolbarbutton-animatable-box">
+              <image class="toolbarbutton-animatable-image"/>
+            </box>
+          </toolbarbutton>
+        </toolbaritem>
+        <toolbarbutton id="home-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
+                       removable="true"
+                       label="&homeButton.label;"
+                       ondragover="homeButtonObserver.onDragOver(event)"
+                       ondragenter="homeButtonObserver.onDragOver(event)"
+                       ondrop="homeButtonObserver.onDrop(event)"
+                       ondragexit="homeButtonObserver.onDragExit(event)"
+                       key="goHome"
+                       onclick="BrowserHome(event);"
+                       cui-areatype="toolbar"
+                       tooltiptext="&homeButton.defaultPage.tooltip;"/>
+        <toolbarspring cui-areatype="toolbar" class="chromeclass-toolbar-additional"/>
+        <toolbaritem id="urlbar-container" flex="400" persist="width"
+                     removable="false"
+                     class="chromeclass-location" overflows="false">
+            <toolbartabstop/>
+            <textbox id="urlbar" flex="1"
+                     placeholder="&urlbar.placeholder2;"
+                     defaultPlaceholder="&urlbar.placeholder2;"
+                     focused="true"
+                     pageproxystate="invalid">
+              <!-- Use onclick instead of normal popup= syntax since the popup
+                   code fires onmousedown, and hence eats our favicon drag events. -->
+              <box id="identity-box" role="button"
+                   align="center"
+                   aria-label="&urlbar.viewSiteInfo.label;"
+                   onclick="gIdentityHandler.handleIdentityButtonEvent(event);"
+                   onkeypress="gIdentityHandler.handleIdentityButtonEvent(event);"
+                   ondragstart="gIdentityHandler.onDragStart(event);">
+                <image id="identity-icon"
+                       consumeanchor="identity-box"
+                       onclick="PageProxyClickHandler(event);"/>
+                <image id="sharing-icon" mousethrough="always"/>
+                <box id="tracking-protection-icon-box" animationsenabled="true">
+                  <image id="tracking-protection-icon"/>
+                  <box id="tracking-protection-icon-animatable-box" flex="1">
+                    <image id="tracking-protection-icon-animatable-image" flex="1"/>
+                  </box>
+                </box>
+                <box id="blocked-permissions-container" align="center">
+                  <image data-permission-id="geo" class="blocked-permission-icon geo-icon" role="button"
+                         tooltiptext="&urlbar.geolocationBlocked.tooltip;"/>
+                  <image data-permission-id="desktop-notification" class="blocked-permission-icon desktop-notification-icon" role="button"
+                         tooltiptext="&urlbar.webNotificationsBlocked.tooltip;"/>
+                  <image data-permission-id="camera" class="blocked-permission-icon camera-icon" role="button"
+                         tooltiptext="&urlbar.cameraBlocked.tooltip;"/>
+                  <image data-permission-id="microphone" class="blocked-permission-icon microphone-icon" role="button"
+                         tooltiptext="&urlbar.microphoneBlocked.tooltip;"/>
+                  <image data-permission-id="screen" class="blocked-permission-icon screen-icon" role="button"
+                         tooltiptext="&urlbar.screenBlocked.tooltip;"/>
+                  <image data-permission-id="persistent-storage" class="blocked-permission-icon persistent-storage-icon" role="button"
+                         tooltiptext="&urlbar.persistentStorageBlocked.tooltip;"/>
+                  <image data-permission-id="popup" class="blocked-permission-icon popup-icon" role="button"
+                         tooltiptext="&urlbar.popupBlocked.tooltip;"/>
+                  <image data-permission-id="autoplay-media" class="blocked-permission-icon autoplay-media-icon" role="button"
+                         tooltiptext="&urlbar.autoplayMediaBlocked.tooltip;"/>
+                  <image data-permission-id="canvas" class="blocked-permission-icon canvas-icon" role="button"
+                         tooltiptext="&urlbar.canvasBlocked.tooltip;"/>
+                  <image data-permission-id="plugin:flash" class="blocked-permission-icon plugin-icon" role="button"
+                         tooltiptext="&urlbar.flashPluginBlocked.tooltip;"/>
+                  <image data-permission-id="midi" class="blocked-permission-icon midi-icon" role="button"
+                         tooltiptext="&urlbar.midiBlocked.tooltip;"/>
+                  <image data-permission-id="install" class="blocked-permission-icon install-icon" role="button"
+                         tooltiptext="&urlbar.installBlocked.tooltip;"/>
+                </box>
+                <box id="notification-popup-box"
+                     hidden="true"
+                     onmouseover="document.getElementById('identity-box').classList.add('no-hover');"
+                     onmouseout="document.getElementById('identity-box').classList.remove('no-hover');"
+                     align="center">
+                  <image id="default-notification-icon" class="notification-anchor-icon" role="button"
+                         tooltiptext="&urlbar.defaultNotificationAnchor.tooltip;"/>
+                  <image id="geo-notification-icon" class="notification-anchor-icon geo-icon" role="button"
+                         tooltiptext="&urlbar.geolocationNotificationAnchor.tooltip;"/>
+                  <image id="autoplay-media-notification-icon" class="notification-anchor-icon autoplay-media-icon" role="button"
+                         tooltiptext="&urlbar.autoplayNotificationAnchor.tooltip;"/>
+                  <image id="addons-notification-icon" class="notification-anchor-icon install-icon" role="button"
+                         tooltiptext="&urlbar.addonsNotificationAnchor.tooltip;"/>
+                  <image id="canvas-notification-icon" class="notification-anchor-icon" role="button"
+                         tooltiptext="&urlbar.canvasNotificationAnchor.tooltip;"/>
+                  <image id="indexedDB-notification-icon" class="notification-anchor-icon indexedDB-icon" role="button"
+                         tooltiptext="&urlbar.indexedDBNotificationAnchor.tooltip;"/>
+                  <image id="password-notification-icon" class="notification-anchor-icon login-icon" role="button"
+                         tooltiptext="&urlbar.passwordNotificationAnchor.tooltip;"/>
+                  <stack id="plugins-notification-icon" class="notification-anchor-icon" role="button" align="center"
+                         tooltiptext="&urlbar.pluginsNotificationAnchor.tooltip;">
+                    <image class="plugin-icon" />
+                    <image id="plugin-icon-badge" />
+                  </stack>
+                  <image id="web-notifications-notification-icon" class="notification-anchor-icon desktop-notification-icon" role="button"
+                         tooltiptext="&urlbar.webNotificationAnchor.tooltip;"/>
+                  <image id="webRTC-shareDevices-notification-icon" class="notification-anchor-icon camera-icon" role="button"
+                         tooltiptext="&urlbar.webRTCShareDevicesNotificationAnchor.tooltip;"/>
+                  <image id="webRTC-shareMicrophone-notification-icon" class="notification-anchor-icon microphone-icon" role="button"
+                         tooltiptext="&urlbar.webRTCShareMicrophoneNotificationAnchor.tooltip;"/>
+                  <image id="webRTC-shareScreen-notification-icon" class="notification-anchor-icon screen-icon" role="button"
+                         tooltiptext="&urlbar.webRTCShareScreenNotificationAnchor.tooltip;"/>
+                  <image id="servicesInstall-notification-icon" class="notification-anchor-icon service-icon" role="button"
+                         tooltiptext="&urlbar.servicesNotificationAnchor.tooltip;"/>
+                  <image id="translate-notification-icon" class="notification-anchor-icon translation-icon" role="button"
+                         tooltiptext="&urlbar.translateNotificationAnchor.tooltip;"/>
+                  <image id="translated-notification-icon" class="notification-anchor-icon translation-icon in-use" role="button"
+                         tooltiptext="&urlbar.translatedNotificationAnchor.tooltip;"/>
+                  <image id="eme-notification-icon" class="notification-anchor-icon drm-icon" role="button"
+                         tooltiptext="&urlbar.emeNotificationAnchor.tooltip;"/>
+                  <image id="persistent-storage-notification-icon" class="notification-anchor-icon persistent-storage-icon" role="button"
+                         tooltiptext="&urlbar.persistentStorageNotificationAnchor.tooltip;"/>
+                  <image id="midi-notification-icon" class="notification-anchor-icon midi-icon" role="button"
+                         tooltiptext="&urlbar.midiNotificationAnchor.tooltip;"/>
+                  <image id="webauthn-notification-icon" class="notification-anchor-icon" role="button"
+                         tooltiptext="&urlbar.webAuthnAnchor.tooltip;"/>
+                  <image id="storage-access-notification-icon" class="notification-anchor-icon storage-access-icon" role="button"
+                         tooltiptext="&urlbar.storageAccessAnchor.tooltip;"/>
+                </box>
+                <image id="connection-icon"/>
+                <image id="extension-icon"/>
+                <image id="remote-control-icon"
+                       tooltiptext="&urlbar.remoteControlNotificationAnchor.tooltip;"/>
+                <hbox id="identity-icon-labels">
+                  <label id="identity-icon-label" class="plain" flex="1"/>
+                  <label id="identity-icon-country-label" class="plain"/>
+                </hbox>
+              </box>
+              <box id="urlbar-display-box" align="center">
+                <label id="switchtab" class="urlbar-display urlbar-display-switchtab" value="&urlbar.switchToTab.label;"/>
+                <label id="extension" class="urlbar-display urlbar-display-extension" value="&urlbar.extension.label;"/>
+              </box>
+              <hbox id="page-action-buttons" context="pageActionContextMenu">
+                <toolbartabstop/>
+                <hbox id="contextual-feature-recommendation" role="button" hidden="true">
+                  <hbox id="cfr-label-container">
+                    <label id="cfr-label"/>
+                  </hbox>
+                  <image id="cfr-button"
+                         class="urlbar-icon urlbar-page-action"
+                         role="presentation"/>
+                </hbox>
+                <hbox id="userContext-icons" hidden="true">
+                  <label id="userContext-label"/>
+                  <image id="userContext-indicator"/>
+                </hbox>
+                <image id="reader-mode-button"
+                       class="urlbar-icon urlbar-page-action"
+                       tooltip="dynamic-shortcut-tooltip"
+                       role="button"
+                       hidden="true"
+                       onclick="ReaderParent.buttonClick(event);"/>
+                <toolbarbutton id="urlbar-zoom-button"
+                       onclick="FullZoom.reset();"
+                       tooltip="dynamic-shortcut-tooltip"
+                       hidden="true"/>
+                <box id="pageActionSeparator" class="urlbar-page-action"/>
+                <image id="pageActionButton"
+                       class="urlbar-icon urlbar-page-action"
+                       role="button"
+                       tooltiptext="&pageActionButton.tooltip;"
+                       onmousedown="BrowserPageActions.mainButtonClicked(event);"
+                       onkeypress="BrowserPageActions.mainButtonClicked(event);"/>
+                <hbox id="pocket-button-box"
+                      hidden="true"
+                      class="urlbar-icon-wrapper urlbar-page-action"
+                      onclick="BrowserPageActions.doCommandForAction(PageActions.actionForID('pocket'), event, this);">
+                  <image id="pocket-button"
+                         class="urlbar-icon"
+                         tooltiptext="&pocketButton.tooltiptext;"
+                         role="button"/>
+                  <hbox id="pocket-button-animatable-box">
+                    <image id="pocket-button-animatable-image"
+                           tooltiptext="&pocketButton.tooltiptext;"
+                           role="presentation"/>
+                  </hbox>
+                </hbox>
+                <hbox id="star-button-box"
+                      hidden="true"
+                      class="urlbar-icon-wrapper urlbar-page-action"
+                      onclick="BrowserPageActions.doCommandForAction(PageActions.actionForID('bookmark'), event, this);">
+                  <image id="star-button"
+                         class="urlbar-icon"
+                         role="button"/>
+                  <hbox id="star-button-animatable-box">
+                    <image id="star-button-animatable-image"
+                           role="presentation"/>
+                  </hbox>
+                </hbox>
+              </hbox>
+            </textbox>
+            <toolbartabstop/>
+        </toolbaritem>
+
+        <toolbarspring cui-areatype="toolbar" class="chromeclass-toolbar-additional"/>
+
+        <!-- This is a placeholder for the Downloads Indicator.  It is visible
+             during the customization of the toolbar, in the palette, and before
+             the Downloads Indicator overlay is loaded. -->
+        <toolbarbutton id="downloads-button"
+                       class="toolbarbutton-1 chromeclass-toolbar-additional"
+                       badged="true"
+                       key="key_openDownloads"
+                       onmousedown="DownloadsIndicatorView.onCommand(event);"
+                       onkeypress="DownloadsIndicatorView.onCommand(event);"
+                       ondrop="DownloadsIndicatorView.onDrop(event);"
+                       ondragover="DownloadsIndicatorView.onDragOver(event);"
+                       ondragenter="DownloadsIndicatorView.onDragOver(event);"
+                       label="&downloads.label;"
+                       removable="true"
+                       overflows="false"
+                       cui-areatype="toolbar"
+                       hidden="true"
+                       tooltip="dynamic-shortcut-tooltip"
+                       indicator="true">
+            <!-- The panel's anchor area is smaller than the outer button, but must
+                 always be visible and must not move or resize when the indicator
+                 state changes, otherwise the panel could change its position or lose
+                 its arrow unexpectedly. -->
+            <stack id="downloads-indicator-anchor"
+                   consumeanchor="downloads-button">
+              <box id="downloads-indicator-icon"/>
+              <stack id="downloads-indicator-progress-outer">
+                <box id="downloads-indicator-progress-inner"/>
+              </stack>
+            </stack>
+          </toolbarbutton>
+
+        <toolbarbutton id="library-button" class="toolbarbutton-1 chromeclass-toolbar-additional subviewbutton-nav"
+                       removable="true"
+                       onmousedown="PanelUI.showSubView('appMenu-libraryView', this, event);"
+                       onkeypress="PanelUI.showSubView('appMenu-libraryView', this, event);"
+                       closemenu="none"
+                       cui-areatype="toolbar"
+                       tooltiptext="&libraryButton.tooltip;"
+                       label="&places.library.title;"/>
+
+        <toolbarbutton id="fxa-toolbar-menu-button" class="toolbarbutton-1 chromeclass-toolbar-additional subviewbutton-nav"
+                       badged="true"
+                       onmousedown="gSync.toggleAccountPanel('PanelUI-fxa', event)"
+                       onkeypress="gSync.toggleAccountPanel('PanelUI-fxa', event)"
+                       consumeanchor="fxa-toolbar-menu-button"
+                       closemenu="none"
+                       label="&fxa.menu.firefoxAccount;"
+                       tooltiptext="&fxa.menu.firefoxAccount;"
+                       cui-areatype="toolbar"
+                       removable="true">
+                       <vbox>
+                        <image id="fxa-avatar-image"/>
+                       </vbox>
+        </toolbarbutton>
+      </hbox>
+
+      <toolbarbutton id="nav-bar-overflow-button"
+                     class="toolbarbutton-1 chromeclass-toolbar-additional overflow-button"
+                     skipintoolbarset="true"
+                     tooltiptext="&navbarOverflow.label;">
+        <box class="toolbarbutton-animatable-box">
+          <image class="toolbarbutton-animatable-image"/>
+        </box>
+      </toolbarbutton>
+
+      <toolbaritem id="PanelUI-button"
+                   removable="false">
+        <toolbarbutton id="PanelUI-menu-button"
+                       class="toolbarbutton-1"
+                       badged="true"
+                       consumeanchor="PanelUI-button"
+                       label="&brandShortName;"
+                       tooltiptext="&appmenu.tooltip;"/>
+      </toolbaritem>
+
+      <hbox id="window-controls" hidden="true" pack="end" skipintoolbarset="true"
+            ordinal="1000">
+        <toolbarbutton id="minimize-button"
+                       tooltiptext="&fullScreenMinimize.tooltip;"
+                       oncommand="window.minimize();"/>
+
+        <toolbarbutton id="restore-button"
+#ifdef XP_MACOSX
+# Prior to 10.7 there wasn't a native fullscreen button so we use #restore-button
+# to exit fullscreen and want it to behave like other toolbar buttons.
+                       class="toolbarbutton-1"
+#endif
+                       tooltiptext="&fullScreenRestore.tooltip;"
+                       oncommand="BrowserFullScreen();"/>
+
+        <toolbarbutton id="close-button"
+                       tooltiptext="&fullScreenClose.tooltip;"
+                       oncommand="BrowserTryToCloseWindow();"/>
+      </hbox>
+
+      <box id="library-animatable-box" class="toolbarbutton-animatable-box">
+        <image class="toolbarbutton-animatable-image"/>
+      </box>
+    </toolbar>
+
+    <toolbar id="PersonalToolbar"
+             mode="icons"
+             class="browser-toolbar chromeclass-directories"
+             context="toolbar-context-menu"
+             toolbarname="&personalbarCmd.label;" accesskey="&personalbarCmd.accesskey;"
+             collapsed="true"
+             customizable="true">
+      <toolbartabstop skipintoolbarset="true"/>
+      <toolbaritem id="personal-bookmarks"
+                   title="&bookmarksToolbarItem.label;"
+                   cui-areatype="toolbar"
+                   removable="true">
+        <toolbarbutton id="bookmarks-toolbar-placeholder"
+                       class="bookmark-item"
+                       label="&bookmarksToolbarItem.label;"/>
+        <toolbarbutton id="bookmarks-toolbar-button"
+                       class="toolbarbutton-1"
+                       flex="1"
+                       label="&bookmarksToolbarItem.label;"
+                       oncommand="PlacesToolbarHelper.onPlaceholderCommand();"/>
+        <hbox flex="1"
+              id="PlacesToolbar"
+              context="placesContext"
+              onmouseup="BookmarksEventHandler.onMouseUp(event);"
+              onclick="BookmarksEventHandler.onClick(event, this._placesView);"
+              oncommand="BookmarksEventHandler.onCommand(event);"
+              tooltip="bhTooltip"
+              popupsinherittooltip="true">
+          <hbox flex="1">
+            <hbox id="PlacesToolbarDropIndicatorHolder" align="center" collapsed="true">
+              <image id="PlacesToolbarDropIndicator"
+                     mousethrough="always"
+                     collapsed="true"/>
+            </hbox>
+            <scrollbox orient="horizontal"
+                       id="PlacesToolbarItems"
+                       flex="1"/>
+            <toolbarbutton type="menu"
+                           id="PlacesChevron"
+                           class="toolbarbutton-1"
+                           mousethrough="never"
+                           collapsed="true"
+                           tooltiptext="&bookmarksToolbarChevron.tooltip;"
+                           onpopupshowing="document.getElementById('PlacesToolbar')
+                                                   ._placesView._onChevronPopupShowing(event);">
+              <menupopup id="PlacesChevronPopup"
+                         placespopup="true"
+                         tooltip="bhTooltip" popupsinherittooltip="true"
+                         context="placesContext"/>
+            </toolbarbutton>
+          </hbox>
+        </hbox>
+      </toolbaritem>
+    </toolbar>
+
+    <toolbarpalette id="BrowserToolbarPalette">
+
+      <toolbarbutton id="print-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
+#ifdef XP_MACOSX
+                     command="cmd_print"
+                     tooltip="dynamic-shortcut-tooltip"
+#else
+                     command="cmd_printPreview"
+                     tooltiptext="&printButton.tooltip;"
+#endif
+                     label="&printButton.label;"/>
+
+
+      <toolbarbutton id="new-window-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
+                     label="&newNavigatorCmd.label;"
+                     command="cmd_newNavigator"
+                     tooltip="dynamic-shortcut-tooltip"
+                     ondrop="newWindowButtonObserver.onDrop(event)"
+                     ondragover="newWindowButtonObserver.onDragOver(event)"
+                     ondragenter="newWindowButtonObserver.onDragOver(event)"
+                     ondragexit="newWindowButtonObserver.onDragExit(event)"/>
+
+      <toolbarbutton id="fullscreen-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
+                     observes="View:FullScreen"
+                     type="checkbox"
+                     label="&fullScreenCmd.label;"
+                     tooltip="dynamic-shortcut-tooltip"/>
+
+      <toolbarbutton id="bookmarks-menu-button"
+                     class="toolbarbutton-1 chromeclass-toolbar-additional subviewbutton-nav"
+                     type="menu"
+                     label="&bookmarksMenuButton2.label;"
+                     tooltip="dynamic-shortcut-tooltip"
+                     ondragenter="PlacesMenuDNDHandler.onDragEnter(event);"
+                     ondragover="PlacesMenuDNDHandler.onDragOver(event);"
+                     ondragleave="PlacesMenuDNDHandler.onDragLeave(event);"
+                     ondrop="PlacesMenuDNDHandler.onDrop(event);"
+                     oncommand="BookmarkingUI.onCommand(event);">
+        <menupopup id="BMB_bookmarksPopup"
+                   class="cui-widget-panel cui-widget-panelview cui-widget-panelWithFooter PanelUI-subView"
+                   placespopup="true"
+                   context="placesContext"
+                   openInTabs="children"
+                   side="top"
+                   onmouseup="BookmarksEventHandler.onMouseUp(event);"
+                   oncommand="BookmarksEventHandler.onCommand(event);"
+                   onclick="BookmarksEventHandler.onClick(event, this.parentNode._placesView);"
+                   onpopupshowing="BookmarkingUI.onPopupShowing(event);
+                                   BookmarkingUI.attachPlacesView(event, this);"
+                   tooltip="bhTooltip" popupsinherittooltip="true">
+          <menuitem id="BMB_viewBookmarksSidebar"
+                    class="menuitem-iconic subviewbutton"
+                    label-show="&viewBookmarksSidebar2.label;"
+                    label-hide="&hideBookmarksSidebar.label;"
+                    oncommand="SidebarUI.toggle('viewBookmarksSidebar');"/>
+          <!-- NB: temporary solution for bug 985024, this should go away soon. -->
+          <menuitem id="BMB_bookmarksShowAllTop"
+                    class="menuitem-iconic subviewbutton"
+                    label="&showAllBookmarks2.label;"
+                    command="Browser:ShowAllBookmarks"
+                    key="manBookmarkKb"/>
+          <menuseparator/>
+          <menu id="BMB_bookmarksToolbar"
+                class="menu-iconic bookmark-item subviewbutton"
+                label="&personalbarCmd.label;"
+                container="true">
+            <menupopup id="BMB_bookmarksToolbarPopup"
+                       placespopup="true"
+                       context="placesContext"
+                       onpopupshowing="if (!this.parentNode._placesView)
+                                         new PlacesMenu(event, `place:parent=${PlacesUtils.bookmarks.toolbarGuid}`,
+                                                        PlacesUIUtils.getViewForNode(this.parentNode.parentNode).options);">
+              <menuitem id="BMB_viewBookmarksToolbar"
+                        class="menuitem-iconic subviewbutton"
+                        label-show="&viewBookmarksToolbar.label;"
+                        label-hide="&hideBookmarksToolbar.label;"
+                        oncommand="BookmarkingUI.toggleBookmarksToolbar();"/>
+              <menuseparator/>
+              <!-- Bookmarks toolbar items -->
+            </menupopup>
+          </menu>
+          <menu id="BMB_unsortedBookmarks"
+                class="menu-iconic bookmark-item subviewbutton"
+                label="&bookmarksMenuButton.other.label;"
+                container="true">
+            <menupopup id="BMB_unsortedBookmarksPopup"
+                       placespopup="true"
+                       context="placesContext"
+                       onpopupshowing="if (!this.parentNode._placesView)
+                                         new PlacesMenu(event, `place:parent=${PlacesUtils.bookmarks.unfiledGuid}`,
+                                                        PlacesUIUtils.getViewForNode(this.parentNode.parentNode).options);"/>
+          </menu>
+          <menu id="BMB_mobileBookmarks"
+                class="menu-iconic bookmark-item subviewbutton"
+                label="&bookmarksMenuButton.mobile.label;"
+                hidden="true"
+                container="true">
+            <menupopup id="BMB_mobileBookmarksPopup"
+                       placespopup="true"
+                       context="placesContext"
+                       onpopupshowing="if (!this.parentNode._placesView)
+                                         new PlacesMenu(event, `place:parent=${PlacesUtils.bookmarks.mobileGuid}`,
+                                                        PlacesUIUtils.getViewForNode(this.parentNode.parentNode).options);"/>
+          </menu>
+
+          <menuseparator/>
+          <!-- Bookmarks menu items will go here -->
+          <menuitem id="BMB_bookmarksShowAll"
+                    class="subviewbutton panel-subview-footer"
+                    label="&showAllBookmarks2.label;"
+                    command="Browser:ShowAllBookmarks"
+                    key="manBookmarkKb"/>
+        </menupopup>
+      </toolbarbutton>
+
+      <toolbaritem id="search-container"
+                   class="chromeclass-toolbar-additional"
+                   title="&searchItem.title;"
+                   align="center"
+                   flex="100"
+                   persist="width">
+        <toolbartabstop/>
+        <searchbar id="searchbar" flex="1"/>
+        <toolbartabstop/>
+      </toolbaritem>
+    </toolbarpalette>
+  </toolbox>
+
+  <hbox id="fullscr-toggler" hidden="true"/>
+
+  <deck id="content-deck" flex="1" renderroot="content">
+    <hbox flex="1" id="browser">
+      <vbox id="browser-border-start" hidden="true" layer="true"/>
+      <vbox id="sidebar-box" hidden="true" class="chromeclass-extrachrome">
+        <sidebarheader id="sidebar-header" align="center">
+          <toolbarbutton id="sidebar-switcher-target" flex="1" class="tabbable">
+            <image id="sidebar-icon" consumeanchor="sidebar-switcher-target"/>
+            <label id="sidebar-title" crop="end" flex="1" control="sidebar"/>
+            <image id="sidebar-switcher-arrow"/>
+          </toolbarbutton>
+          <image id="sidebar-throbber"/>
+# To ensure the button label's intrinsic width doesn't expand the sidebar
+# if the label is long, the button needs flex=1.
+# To ensure the button doesn't expand unnecessarily for short labels, the
+# spacer should significantly out-flex the button.
+          <spacer flex="1000"/>
+          <toolbarbutton id="sidebar-close" class="close-icon tabbable" tooltiptext="&sidebarCloseButton.tooltip;" oncommand="SidebarUI.hide();"/>
+        </sidebarheader>
+        <browser id="sidebar" flex="1" autoscroll="false" disablehistory="true" disablefullscreen="true"
+                  style="min-width: 14em; width: 18em; max-width: 36em;" tooltip="aHTMLTooltip"/>
+      </vbox>
+
+      <splitter id="sidebar-splitter" class="chromeclass-extrachrome sidebar-splitter" hidden="true"/>
+      <vbox id="appcontent" flex="1">
+        <!-- gHighPriorityNotificationBox will be added here lazily. -->
+        <tabbox id="tabbrowser-tabbox"
+                flex="1" tabcontainer="tabbrowser-tabs">
+          <tabpanels id="tabbrowser-tabpanels"
+                     flex="1" class="plain" selectedIndex="0"/>
+        </tabbox>
+      </vbox>
+      <vbox id="browser-border-end" hidden="true" layer="true"/>
+    </hbox>
+    <box id="customization-container" flex="1" hidden="true"><![CDATA[
+#include ../../components/customizableui/content/customizeMode.inc.xul
+    ]]></box>
+  </deck>
+
+  <html:div id="fullscreen-warning" class="pointerlockfswarning" hidden="true" renderroot="content">
+    <html:div class="pointerlockfswarning-domain-text">
+      &fullscreenWarning.beforeDomain.label;
+      <html:span class="pointerlockfswarning-domain"/>
+      &fullscreenWarning.afterDomain.label;
+    </html:div>
+    <html:div class="pointerlockfswarning-generic-text">
+      &fullscreenWarning.generic.label;
+    </html:div>
+    <html:button id="fullscreen-exit-button"
+                 onclick="FullScreen.exitDomFullScreen();">
+#ifdef XP_MACOSX
+            &exitDOMFullscreenMac.button;
+#else
+            &exitDOMFullscreen.button;
+#endif
+    </html:button>
+  </html:div>
+
+  <html:div id="pointerlock-warning" class="pointerlockfswarning" hidden="true" renderroot="content">
+    <html:div class="pointerlockfswarning-domain-text">
+      &pointerlockWarning.beforeDomain.label;
+      <html:span class="pointerlockfswarning-domain"/>
+      &pointerlockWarning.afterDomain.label;
+    </html:div>
+    <html:div class="pointerlockfswarning-generic-text">
+      &pointerlockWarning.generic.label;
+    </html:div>
+  </html:div>
+
+  <vbox id="browser-bottombox" layer="true" renderroot="content">
+    <!-- gNotificationBox will be added here lazily. -->
+  </vbox>
+</window>
deleted file mode 100644
--- a/browser/base/content/browser.xul
+++ /dev/null
@@ -1,1379 +0,0 @@
-#filter substitution
-<?xml version="1.0"?>
-# -*- Mode: HTML -*-
-#
-# 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/.
-
-<!-- The "global.css" stylesheet is imported first to allow other stylesheets to
-     override rules using selectors with the same specificity. This applies to
-     both "content" and "skin" packages, which bug 1385444 will unify later. -->
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-
-<!-- While these stylesheets are defined in Toolkit, they are only used in the
-     main browser window, so we can load them here. Bug 1474241 is on file to
-     consider moving these widgets to the "browser" folder. -->
-<?xml-stylesheet href="chrome://global/content/tabprompts.css" type="text/css"?>
-<?xml-stylesheet href="chrome://global/skin/tabprompts.css" type="text/css"?>
-
-<?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/content/tabbrowser.css" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/content/downloads/downloads.css" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/content/places/places.css" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/content/usercontext/usercontext.css" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/controlcenter/panel.css" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/customizableui/panelUI.css" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/downloads/downloads.css" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/searchbar.css" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/places/tree-icons.css" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/places/editBookmark.css" type="text/css"?>
-
-# All DTD information is stored in a separate file so that it can be shared by
-# hiddenWindowMac.xhtml.
-<!DOCTYPE window [
-#include browser-doctype.inc
-]>
-
-<window id="main-window"
-        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-        xmlns:svg="http://www.w3.org/2000/svg"
-        xmlns:html="http://www.w3.org/1999/xhtml"
-        xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        title="&mainWindow.title;"
-        title_normal="&mainWindow.title;"
-#ifdef XP_MACOSX
-        title_privatebrowsing="&mainWindow.title;&mainWindow.titlemodifiermenuseparator;&mainWindow.titlePrivateBrowsingSuffix;"
-        titledefault="&mainWindow.title;"
-        titlemodifier=""
-        titlemodifier_normal=""
-        titlemodifier_privatebrowsing="&mainWindow.titlePrivateBrowsingSuffix;"
-#else
-        title_privatebrowsing="&mainWindow.titlemodifier; &mainWindow.titlePrivateBrowsingSuffix;"
-        titlemodifier="&mainWindow.titlemodifier;"
-        titlemodifier_normal="&mainWindow.titlemodifier;"
-        titlemodifier_privatebrowsing="&mainWindow.titlemodifier; &mainWindow.titlePrivateBrowsingSuffix;"
-#endif
-#ifdef XP_WIN
-        chromemargin="0,2,2,2"
-#else
-        chromemargin="0,-1,-1,-1"
-#endif
-        tabsintitlebar="true"
-        titlemenuseparator="&mainWindow.titlemodifiermenuseparator;"
-        windowtype="navigator:browser"
-        macanimationtype="document"
-        screenX="4" screenY="4"
-        fullscreenbutton="true"
-        sizemode="normal"
-        retargetdocumentfocus="urlbar"
-        persist="screenX screenY width height sizemode"
-#ifdef BROWSER_XHTML
-        mozpersist=""
-#endif
-        >
-
-# All JS files which are needed by browser.xul and other top level windows to
-# support MacOS specific features *must* go into the global-scripts.inc file so
-# that they can be shared with macWindow.inc.xul.
-#include global-scripts.inc
-
-<script>
-  Services.scriptloader.loadSubScript("chrome://global/content/contentAreaUtils.js", this);
-  Services.scriptloader.loadSubScript("chrome://browser/content/browser-captivePortal.js", this);
-  Services.scriptloader.loadSubScript("chrome://browser/content/browser-contentblocking.js", this);
-#ifdef MOZ_DATA_REPORTING
-  Services.scriptloader.loadSubScript("chrome://browser/content/browser-data-submission-info-bar.js", this);
-#endif
-#ifndef MOZILLA_OFFICIAL
-  Services.scriptloader.loadSubScript("chrome://browser/content/browser-development-helpers.js", this);
-#endif
-  Services.scriptloader.loadSubScript("chrome://browser/content/browser-media.js", this);
-  Services.scriptloader.loadSubScript("chrome://browser/content/browser-pageActions.js", this);
-  Services.scriptloader.loadSubScript("chrome://browser/content/browser-plugins.js", this);
-  Services.scriptloader.loadSubScript("chrome://browser/content/browser-sidebar.js", this);
-  Services.scriptloader.loadSubScript("chrome://browser/content/browser-tabsintitlebar.js", this);
-  Services.scriptloader.loadSubScript("chrome://browser/content/tabbrowser.js", this);
-  Services.scriptloader.loadSubScript("chrome://browser/content/tabbrowser-tab.js", this);
-  Services.scriptloader.loadSubScript("chrome://browser/content/search/autocomplete-popup.js", this);
-  Services.scriptloader.loadSubScript("chrome://browser/content/search/searchbar.js", this);
-
-  window.onload = gBrowserInit.onLoad.bind(gBrowserInit);
-  window.onunload = gBrowserInit.onUnload.bind(gBrowserInit);
-  window.onclose = WindowIsClosing;
-
-  window.addEventListener("MozBeforeInitialXULLayout",
-    gBrowserInit.onBeforeInitialXULLayout.bind(gBrowserInit), { once: true });
-
-  // The listener of DOMContentLoaded must be set on window, rather than
-  // document, because the window can go away before the event is fired.
-  // In that case, we don't want to initialize anything, otherwise we
-  // may be leaking things because they will never be destroyed after.
-  window.addEventListener("DOMContentLoaded",
-    gBrowserInit.onDOMContentLoaded.bind(gBrowserInit), { once: true });
-</script>
-
-# All sets except for popupsets (commands, keys, and stringbundles)
-# *must* go into the browser-sets.inc file so that they can be shared with other
-# top level windows in macWindow.inc.xul.
-#include browser-sets.inc
-
-  <popupset id="mainPopupSet">
-    <menupopup id="tabContextMenu"
-               onpopupshowing="if (event.target == this) TabContextMenu.updateContextMenu(this);"
-               onpopuphidden="if (event.target == this) TabContextMenu.contextTab = null;">
-      <menuitem id="context_reloadTab" data-lazy-l10n-id="reload-tab"
-                oncommand="gBrowser.reloadTab(TabContextMenu.contextTab);"/>
-      <menuitem id="context_reloadSelectedTabs" data-lazy-l10n-id="reload-tabs" hidden="true"
-                oncommand="gBrowser.reloadMultiSelectedTabs();"/>
-      <menuitem id="context_toggleMuteTab" oncommand="TabContextMenu.contextTab.toggleMuteAudio();"/>
-      <menuitem id="context_toggleMuteSelectedTabs" hidden="true"
-                oncommand="gBrowser.toggleMuteAudioOnMultiSelectedTabs(TabContextMenu.contextTab);"/>
-      <menuitem id="context_pinTab" data-lazy-l10n-id="pin-tab"
-                oncommand="gBrowser.pinTab(TabContextMenu.contextTab);"/>
-      <menuitem id="context_unpinTab" data-lazy-l10n-id="unpin-tab" hidden="true"
-                oncommand="gBrowser.unpinTab(TabContextMenu.contextTab);"/>
-      <menuitem id="context_pinSelectedTabs" data-lazy-l10n-id="pin-selected-tabs" hidden="true"
-                oncommand="gBrowser.pinMultiSelectedTabs();"/>
-      <menuitem id="context_unpinSelectedTabs" data-lazy-l10n-id="unpin-selected-tabs" hidden="true"
-                oncommand="gBrowser.unpinMultiSelectedTabs();"/>
-      <menuitem id="context_duplicateTab" data-lazy-l10n-id="duplicate-tab"
-                oncommand="duplicateTabIn(TabContextMenu.contextTab, 'tab');"/>
-      <menuitem id="context_duplicateTabs" data-lazy-l10n-id="duplicate-tabs"
-                oncommand="TabContextMenu.duplicateSelectedTabs();"/>
-      <menuseparator/>
-      <menuitem id="context_selectAllTabs" data-lazy-l10n-id="select-all-tabs"
-                oncommand="gBrowser.selectAllTabs();"/>
-      <menuitem id="context_bookmarkSelectedTabs"
-                hidden="true"
-                data-lazy-l10n-id="bookmark-selected-tabs"
-                oncommand="PlacesCommandHook.bookmarkPages(PlacesCommandHook.uniqueSelectedPages);"/>
-      <menuitem id="context_bookmarkTab"
-                data-lazy-l10n-id="bookmark-tab"
-                oncommand="PlacesCommandHook.bookmarkPages(PlacesCommandHook.getUniquePages([TabContextMenu.contextTab]));"/>
-      <menu id="context_reopenInContainer"
-            data-lazy-l10n-id="reopen-in-container"
-            hidden="true">
-        <menupopup oncommand="TabContextMenu.reopenInContainer(event);"
-                   onpopupshowing="TabContextMenu.createReopenInContainerMenu(event);"/>
-      </menu>
-      <menu id="context_moveTabOptions">
-        <menupopup id="moveTabOptionsMenu">
-          <menuitem id="context_moveToStart"
-                    data-lazy-l10n-id="move-to-start"
-                    tbattr="tabbrowser-multiple"
-                    oncommand="gBrowser.moveTabsToStart(TabContextMenu.contextTab);"/>
-          <menuitem id="context_moveToEnd"
-                    data-lazy-l10n-id="move-to-end"
-                    tbattr="tabbrowser-multiple"
-                    oncommand="gBrowser.moveTabsToEnd(TabContextMenu.contextTab);"/>
-          <menuitem id="context_openTabInWindow" data-lazy-l10n-id="move-to-new-window"
-                    tbattr="tabbrowser-multiple"
-                    oncommand="gBrowser.replaceTabsWithWindow(TabContextMenu.contextTab);"/>
-        </menupopup>
-      </menu>
-      <menu id="context_sendTabToDevice"
-            class="sync-ui-item">
-        <menupopup id="context_sendTabToDevicePopupMenu"
-                   onpopupshowing="gSync.populateSendTabToDevicesMenu(event.target, TabContextMenu.contextTab.linkedBrowser.currentURI.spec, TabContextMenu.contextTab.linkedBrowser.contentTitle, TabContextMenu.contextTab.multiselected);"/>
-      </menu>
-      <menuseparator/>
-      <menuitem id="context_closeTabsToTheEnd" data-lazy-l10n-id="close-tabs-to-the-end"
-                oncommand="gBrowser.removeTabsToTheEndFrom(TabContextMenu.contextTab, {animate: true});"/>
-      <menuitem id="context_closeOtherTabs" data-lazy-l10n-id="close-other-tabs"
-                oncommand="gBrowser.removeAllTabsBut(TabContextMenu.contextTab);"/>
-      <menuitem id="context_undoCloseTab"
-                data-lazy-l10n-id="undo-close-tab"
-                observes="History:UndoCloseTab"/>
-      <menuitem id="context_closeTab" data-lazy-l10n-id="close-tab"
-                oncommand="gBrowser.removeTab(TabContextMenu.contextTab, { animate: true });"/>
-      <menuitem id="context_closeSelectedTabs" data-lazy-l10n-id="close-tabs"
-                hidden="true"
-                oncommand="gBrowser.removeMultiSelectedTabs();"/>
-    </menupopup>
-
-    <!-- bug 415444/582485: event.stopPropagation is here for the cloned version
-         of this menupopup -->
-    <menupopup id="backForwardMenu"
-               onpopupshowing="return FillHistoryMenu(event.target);"
-               oncommand="gotoHistoryIndex(event); event.stopPropagation();"
-               onclick="checkForMiddleClick(this, event);"/>
-    <tooltip id="aHTMLTooltip" page="true"/>
-    <tooltip id="remoteBrowserTooltip"/>
-
-    <!-- for search and content formfill/pw manager -->
-
-    <panel is="autocomplete-richlistbox-popup"
-           type="autocomplete-richlistbox"
-           id="PopupAutoComplete"
-           role="group"
-           noautofocus="true"
-           hidden="true"
-           overflowpadding="4"
-           norolluponanchor="true"
-           nomaxresults="true" />
-
-    <!-- for search with one-off buttons -->
-    <panel is="search-autocomplete-richlistbox-popup"
-           type="autocomplete-richlistbox"
-           id="PopupSearchAutoComplete"
-           role="group"
-           noautofocus="true"
-           hidden="true" />
-
-    <!-- for url bar autocomplete -->
-    <panel type="autocomplete-richlistbox"
-           id="PopupAutoCompleteRichResult"
-           role="group"
-           noautofocus="true"
-           hidden="true"
-           flip="none"
-           level="parent"
-           overflowpadding="15" />
-
-    <!-- for date/time picker. consumeoutsideclicks is set to never, so that
-         clicks on the anchored input box are never consumed. -->
-    <panel id="DateTimePickerPanel"
-           type="arrow"
-           hidden="true"
-           orient="vertical"
-           noautofocus="true"
-           norolluponanchor="true"
-           consumeoutsideclicks="never"
-           level="parent"
-           tabspecific="true">
-    </panel>
-
-    <!-- for select dropdowns. The menupopup is what shows the list of options,
-         and the popuponly menulist makes things like the menuactive attributes
-         work correctly on the menupopup. ContentSelectDropdown expects the
-         popuponly menulist to be its immediate parent. -->
-    <menulist popuponly="true" id="ContentSelectDropdown" hidden="true">
-      <menupopup rolluponmousewheel="true"
-                 activateontab="true" position="after_start"
-                 level="parent"
-#ifdef XP_WIN
-                 consumeoutsideclicks="false" ignorekeys="shortcuts"
-#endif
-        />
-    </menulist>
-
-    <!-- for invalid form error message -->
-    <panel id="invalid-form-popup" type="arrow" orient="vertical" noautofocus="true" hidden="true" level="parent">
-      <description/>
-    </panel>
-
-    <panel id="editBookmarkPanel"
-           type="arrow"
-           orient="vertical"
-           ignorekeys="true"
-           hidden="true"
-           tabspecific="true"
-           aria-labelledby="editBookmarkPanelTitle">
-      <box class="panel-header">
-        <label id="editBookmarkPanelTitle"/>
-        <toolbarbutton id="editBookmarkPanelInfoButton" oncommand="StarUI.toggleRecommendation();" >
-          <image/>
-        </toolbarbutton>
-      </box>
-      <html:div id="editBookmarkPanelInfoArea">
-        <html:div id="editBookmarkPanelRecommendation"></html:div>
-        <html:div id="editBookmarkPanelFaviconContainer">
-          <html:img id="editBookmarkPanelFavicon"/>
-        </html:div>
-        <html:div id="editBookmarkPanelImage"></html:div>
-      </html:div>
-#include ../../components/places/content/editBookmarkPanel.inc.xul
-      <vbox id="editBookmarkPanelBottomContent"
-            flex="1">
-        <checkbox id="editBookmarkPanel_showForNewBookmarks"
-                  label="&editBookmark.showForNewBookmarks.label;"
-                  accesskey="&editBookmark.showForNewBookmarks.accesskey;"
-                  oncommand="StarUI.onShowForNewBookmarksCheckboxCommand();"/>
-      </vbox>
-      <hbox id="editBookmarkPanelBottomButtons"
-            class="panel-footer"
-            style="min-width: &editBookmark.panel.width;;">
-#ifndef XP_UNIX
-        <button id="editBookmarkPanelDoneButton"
-                class="editBookmarkPanelBottomButton"
-                label="&editBookmark.done.label;"
-                default="true"
-                oncommand="StarUI.panel.hidePopup();"/>
-        <button id="editBookmarkPanelRemoveButton"
-                class="editBookmarkPanelBottomButton"
-                oncommand="StarUI.removeBookmarkButtonCommand();"/>
-#else
-        <button id="editBookmarkPanelRemoveButton"
-                class="editBookmarkPanelBottomButton"
-                oncommand="StarUI.removeBookmarkButtonCommand();"/>
-        <button id="editBookmarkPanelDoneButton"
-                class="editBookmarkPanelBottomButton"
-                label="&editBookmark.done.label;"
-                default="true"
-                oncommand="StarUI.panel.hidePopup();"/>
-#endif
-      </hbox>
-    </panel>
-
-    <!-- UI tour experience -->
-    <panel id="UITourTooltip"
-           type="arrow"
-           hidden="true"
-           noautofocus="true"
-           noautohide="true"
-           align="start"
-           orient="vertical"
-           role="alert">
-     <vbox>
-      <hbox id="UITourTooltipBody">
-        <image id="UITourTooltipIcon"/>
-        <vbox flex="1">
-          <hbox id="UITourTooltipTitleContainer">
-            <label id="UITourTooltipTitle" flex="1"/>
-            <toolbarbutton id="UITourTooltipClose" class="close-icon"
-                           tooltiptext="&uiTour.infoPanel.close;"/>
-          </hbox>
-          <description id="UITourTooltipDescription" flex="1"/>
-        </vbox>
-      </hbox>
-      <hbox id="UITourTooltipButtons" flex="1" align="center"/>
-     </vbox>
-    </panel>
-    <!-- type="default" forces frames to be created so that the panel's size can be determined -->
-    <panel id="UITourHighlightContainer"
-           type="default"
-           hidden="true"
-           noautofocus="true"
-           noautohide="true"
-           flip="none"
-           consumeoutsideclicks="false"
-           mousethrough="always">
-      <box id="UITourHighlight"></box>
-    </panel>
-
-    <panel id="sidebarMenu-popup"
-           class="cui-widget-panel"
-           role="group"
-           type="arrow"
-           hidden="true"
-           flip="slide"
-           orient="vertical"
-           position="bottomcenter topleft">
-      <toolbarbutton id="sidebar-switcher-bookmarks"
-                     type="checkbox"
-                     label="&bookmarksButton.label;"
-                     class="subviewbutton subviewbutton-iconic"
-                     key="viewBookmarksSidebarKb"
-                     oncommand="SidebarUI.show('viewBookmarksSidebar');"/>
-      <toolbarbutton id="sidebar-switcher-history"
-                     type="checkbox"
-                     label="&historyButton.label;"
-                     class="subviewbutton subviewbutton-iconic"
-                     key="key_gotoHistory"
-                     oncommand="SidebarUI.show('viewHistorySidebar');"/>
-      <toolbarbutton id="sidebar-switcher-tabs"
-                     type="checkbox"
-                     label="&syncedTabs.sidebar.label;"
-                     class="subviewbutton subviewbutton-iconic sync-ui-item"
-                     oncommand="SidebarUI.show('viewTabsSidebar');"/>
-      <toolbarseparator/>
-      <!-- Extension toolbarbuttons go here. -->
-      <toolbarseparator id="sidebar-extensions-separator"/>
-      <toolbarbutton id="sidebar-reverse-position"
-                     class="subviewbutton"
-                     oncommand="SidebarUI.reversePosition()"/>
-      <toolbarseparator/>
-      <toolbarbutton label="&sidebarMenuClose.label;"
-                     class="subviewbutton"
-                     oncommand="SidebarUI.hide()"/>
-    </panel>
-
-    <menupopup id="toolbar-context-menu"
-               onpopupshowing="onViewToolbarsPopupShowing(event, document.getElementById('viewToolbarsMenuSeparator')); ToolbarContextMenu.updateDownloadsAutoHide(this); ToolbarContextMenu.updateExtension(this)">
-      <menuitem oncommand="ToolbarContextMenu.openAboutAddonsForContextAction(this.parentElement)"
-                accesskey="&customizeMenu.manageExtension.accesskey;"
-                label="&customizeMenu.manageExtension.label;"
-                contexttype="toolbaritem"
-                class="customize-context-manageExtension"/>
-      <menuitem oncommand="ToolbarContextMenu.removeExtensionForContextAction(this.parentElement)"
-                accesskey="&customizeMenu.removeExtension.accesskey;"
-                label="&customizeMenu.removeExtension.label;"
-                contexttype="toolbaritem"
-                class="customize-context-removeExtension"/>
-      <menuitem oncommand="ToolbarContextMenu.reportExtensionForContextAction(this.parentElement, 'toolbar_context_menu')"
-                accesskey="&customizeMenu.reportExtension.accesskey;"
-                label="&customizeMenu.reportExtension.label;"
-                contexttype="toolbaritem"
-                class="customize-context-reportExtension"/>
-      <menuseparator/>
-      <menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode)"
-                accesskey="&customizeMenu.pinToOverflowMenu.accesskey;"
-                label="&customizeMenu.pinToOverflowMenu.label;"
-                contexttype="toolbaritem"
-                class="customize-context-moveToPanel"/>
-      <menuitem id="toolbar-context-autohide-downloads-button"
-                oncommand="ToolbarContextMenu.onDownloadsAutoHideChange(event);"
-                type="checkbox"
-                accesskey="&customizeMenu.autoHideDownloadsButton.accesskey;"
-                label="&customizeMenu.autoHideDownloadsButton.label;"
-                contexttype="toolbaritem"/>
-      <menuitem oncommand="gCustomizeMode.removeFromArea(document.popupNode)"
-                accesskey="&customizeMenu.removeFromToolbar.accesskey;"
-                label="&customizeMenu.removeFromToolbar.label;"
-                contexttype="toolbaritem"
-                class="customize-context-removeFromToolbar"/>
-      <menuitem id="toolbar-context-reloadSelectedTab"
-                contexttype="tabbar"
-                oncommand="gBrowser.reloadMultiSelectedTabs();"
-                data-lazy-l10n-id="toolbar-context-menu-reload-selected-tab"/>
-      <menuitem id="toolbar-context-reloadSelectedTabs"
-                contexttype="tabbar"
-                oncommand="gBrowser.reloadMultiSelectedTabs();"
-                data-lazy-l10n-id="toolbar-context-menu-reload-selected-tabs"/>
-      <menuitem id="toolbar-context-bookmarkSelectedTab"
-                contexttype="tabbar"
-                oncommand="PlacesCommandHook.bookmarkPages(PlacesCommandHook.uniqueSelectedPages);"
-                data-lazy-l10n-id="toolbar-context-menu-bookmark-selected-tab"/>
-      <menuitem id="toolbar-context-bookmarkSelectedTabs"
-                contexttype="tabbar"
-                oncommand="PlacesCommandHook.bookmarkPages(PlacesCommandHook.uniqueSelectedPages);"
-                data-lazy-l10n-id="toolbar-context-menu-bookmark-selected-tabs"/>
-      <menuitem id="toolbar-context-selectAllTabs"
-                contexttype="tabbar"
-                oncommand="gBrowser.selectAllTabs();"
-                data-lazy-l10n-id="toolbar-context-menu-select-all-tabs"/>
-      <menuitem id="toolbar-context-undoCloseTab"
-                contexttype="tabbar"
-                data-lazy-l10n-id="toolbar-context-menu-undo-close-tab"
-                observes="History:UndoCloseTab"/>
-      <menuseparator/>
-      <menuseparator id="viewToolbarsMenuSeparator"/>
-      <!-- XXXgijs: we're using oncommand handler here to avoid the event being
-                    redirected to the command element, thus preventing
-                    listeners on the menupopup or further up the tree from
-                    seeing the command event pass by. The observes attribute is
-                    here so that the menuitem is still disabled and re-enabled
-                    correctly. -->
-      <menuitem oncommand="gCustomizeMode.enter()"
-                observes="cmd_CustomizeToolbars"
-                class="viewCustomizeToolbar"
-                label="&viewCustomizeToolbar.label;"
-                accesskey="&viewCustomizeToolbar.accesskey;"/>
-    </menupopup>
-
-    <menupopup id="blockedPopupOptions"
-               onpopupshowing="gPopupBlockerObserver.fillPopupList(event);"
-               onpopuphiding="gPopupBlockerObserver.onPopupHiding(event);">
-      <menuitem id="blockedPopupAllowSite"
-                accesskey="&allowPopups.accesskey;"
-                oncommand="gPopupBlockerObserver.toggleAllowPopupsForSite(event);"/>
-      <menuitem
-#ifdef XP_WIN
-                label="&editPopupSettings.label;"
-#else
-                label="&editPopupSettingsUnix.label;"
-#endif
-                accesskey="&editPopupSettings.accesskey;"
-                oncommand="gPopupBlockerObserver.editPopupSettings();"/>
-      <menuitem id="blockedPopupDontShowMessage"
-                accesskey="&dontShowMessage.accesskey;"
-                type="checkbox"
-                oncommand="gPopupBlockerObserver.dontShowMessage();"/>
-      <menuseparator id="blockedPopupsSeparator"/>
-    </menupopup>
-
-    <menupopup id="autohide-context"
-           onpopupshowing="FullScreen.getAutohide(this.firstChild);">
-      <menuitem type="checkbox" label="&fullScreenAutohide.label;"
-                accesskey="&fullScreenAutohide.accesskey;"
-                oncommand="FullScreen.setAutohide();"/>
-      <menuseparator/>
-      <menuitem label="&fullScreenExit.label;"
-                accesskey="&fullScreenExit.accesskey;"
-                oncommand="BrowserFullScreen();"/>
-    </menupopup>
-
-    <menupopup id="contentAreaContextMenu" pagemenu="#page-menu-separator"
-               onpopupshowing="if (event.target != this)
-                                 return true;
-                               gContextMenu = new nsContextMenu(this, event.shiftKey);
-                               if (gContextMenu.shouldDisplay)
-                                 updateEditUIVisibility();
-                               return gContextMenu.shouldDisplay;"
-               onpopuphiding="if (event.target != this)
-                                return;
-                              gContextMenu.hiding();
-                              gContextMenu = null;
-                              updateEditUIVisibility();">
-#include browser-context.inc
-    </menupopup>
-
-#include ../../components/places/content/placesContextMenu.inc.xul
-
-    <panel id="ctrlTab-panel" hidden="true" norestorefocus="true" level="top">
-      <hbox id="ctrlTab-previews"/>
-      <hbox id="ctrlTab-showAll-container" pack="center"/>
-    </panel>
-
-    <panel id="pageActionPanel"
-           class="cui-widget-panel"
-           role="group"
-           type="arrow"
-           hidden="true"
-           flip="slide"
-           photon="true"
-           position="bottomcenter topright"
-           tabspecific="true"
-           noautofocus="true"
-           pinTab-title="&pinTab.label;"
-           unpinTab-title="&unpinTab.label;"
-           pocket-title="&saveToPocketCmd.label;"
-           copyURL-title="&pageAction.copyLink.label;"
-           emailLink-title="&emailPageCmd.label;"
-           sendToDevice-notReadyTitle="&sendToDevice.syncNotReady.label;"
-           shareURL-title="&pageAction.shareUrl.label;"
-           shareMore-label="&pageAction.shareMore.label;">
-      <panelmultiview id="pageActionPanelMultiView"
-                      mainViewId="pageActionPanelMainView"
-                      viewCacheId="appMenu-viewCache">
-        <panelview id="pageActionPanelMainView"
-                   context="pageActionContextMenu"
-                   class="PanelUI-subView">
-          <vbox class="panel-subview-body"/>
-        </panelview>
-      </panelmultiview>
-    </panel>
-
-    <panel id="confirmation-hint"
-           role="alert"
-           type="arrow"
-           hidden="true"
-           flip="slide"
-           position="bottomcenter topright"
-           tabspecific="true"
-           noautofocus="true">
-      <hbox id="confirmation-hint-checkmark-animation-container">
-       <image id="confirmation-hint-checkmark-image"/>
-      </hbox>
-      <vbox id="confirmation-hint-message-container">
-       <label id="confirmation-hint-message"/>
-       <label id="confirmation-hint-description"/>
-      </vbox>
-    </panel>
-
-    <menupopup id="pageActionContextMenu"
-               onpopupshowing="BrowserPageActions.onContextMenuShowing(event, this);">
-      <menuitem class="pageActionContextMenuItem builtInUnpinned"
-                label="&pageAction.addToUrlbar.label;"
-                oncommand="BrowserPageActions.togglePinningForContextAction();"/>
-      <menuitem class="pageActionContextMenuItem builtInPinned"
-                label="&pageAction.removeFromUrlbar.label;"
-                oncommand="BrowserPageActions.togglePinningForContextAction();"/>
-      <menuitem class="pageActionContextMenuItem extensionUnpinned"
-                label="&pageAction.addToUrlbar.label;"
-                oncommand="BrowserPageActions.togglePinningForContextAction();"/>
-      <menuitem class="pageActionContextMenuItem extensionPinned"
-                label="&pageAction.removeFromUrlbar.label;"
-                oncommand="BrowserPageActions.togglePinningForContextAction();"/>
-      <menuseparator class="pageActionContextMenuItem extensionPinned extensionUnpinned"/>
-      <menuitem class="pageActionContextMenuItem extensionPinned extensionUnpinned"
-                label="&pageAction.manageExtension.label;"
-                oncommand="BrowserPageActions.openAboutAddonsForContextAction();"/>
-    </menupopup>
-
-#include ../../components/places/content/bookmarksHistoryTooltip.inc.xul
-
-    <tooltip id="tabbrowser-tab-tooltip" onpopupshowing="gBrowser.createTooltip(event);"/>
-
-    <tooltip id="back-button-tooltip">
-      <description class="tooltip-label" value="&backButton.tooltip;"/>
-#ifdef XP_MACOSX
-      <description class="tooltip-label" value="&backForwardButtonMenuMac.tooltip;"/>
-#else
-      <description class="tooltip-label" value="&backForwardButtonMenu.tooltip;"/>
-#endif
-    </tooltip>
-
-    <tooltip id="forward-button-tooltip">
-      <description class="tooltip-label" value="&forwardButton.tooltip;"/>
-#ifdef XP_MACOSX
-      <description class="tooltip-label" value="&backForwardButtonMenuMac.tooltip;"/>
-#else
-      <description class="tooltip-label" value="&backForwardButtonMenu.tooltip;"/>
-#endif
-    </tooltip>
-
-#include popup-notifications.inc
-
-#include ../../components/customizableui/content/panelUI.inc.xul
-#include ../../components/controlcenter/content/identityPanel.inc.xul
-#include ../../components/controlcenter/content/protectionsPanel.inc.xul
-#include ../../components/downloads/content/downloadsPanel.inc.xul
-#include browser-allTabsMenu.inc.xul
-
-    <hbox id="downloads-animation-container" mousethrough="always">
-      <vbox id="downloads-notification-anchor" hidden="true">
-        <vbox id="downloads-indicator-notification"/>
-      </vbox>
-    </hbox>
-
-    <tooltip id="dynamic-shortcut-tooltip"
-             onpopupshowing="UpdateDynamicShortcutTooltipText(this);"/>
-
-    <menupopup id="SyncedTabsSidebarContext">
-      <menuitem data-lazy-l10n-id="synced-tabs-context-open"
-                id="syncedTabsOpenSelected" where="current"/>
-      <menuitem data-lazy-l10n-id="synced-tabs-context-open-in-new-tab"
-                id="syncedTabsOpenSelectedInTab" where="tab"/>
-      <menuitem data-lazy-l10n-id="synced-tabs-context-open-in-new-window"
-                id="syncedTabsOpenSelectedInWindow" where="window"/>
-      <menuitem data-lazy-l10n-id="synced-tabs-context-open-in-new-private-window"
-                id="syncedTabsOpenSelectedInPrivateWindow" where="window" private="true"/>
-      <menuseparator/>
-      <menuitem data-lazy-l10n-id="synced-tabs-context-bookmark-single-tab"
-                id="syncedTabsBookmarkSelected"/>
-      <menuitem data-lazy-l10n-id="synced-tabs-context-copy"
-                id="syncedTabsCopySelected"/>
-      <menuseparator/>
-      <menuitem data-lazy-l10n-id="synced-tabs-context-open-all-in-tabs"
-                id="syncedTabsOpenAllInTabs"/>
-      <menuitem data-lazy-l10n-id="synced-tabs-context-manage-devices"
-                id="syncedTabsManageDevices"
-                oncommand="gSync.openDevicesManagementPage('syncedtabs-sidebar');"/>
-      <menuitem label="&syncSyncNowItem.label;"
-                accesskey="&syncSyncNowItem.accesskey;"
-                id="syncedTabsRefresh"/>
-    </menupopup>
-    <menupopup id="SyncedTabsSidebarTabsFilterContext"
-               class="textbox-contextmenu">
-      <menuitem label="&undoCmd.label;"
-                accesskey="&undoCmd.accesskey;"
-                cmd="cmd_undo"/>
-      <menuseparator/>
-      <menuitem label="&cutCmd.label;"
-                accesskey="&cutCmd.accesskey;"
-                cmd="cmd_cut"/>
-      <menuitem label="&copyCmd.label;"
-                accesskey="&copyCmd.accesskey;"
-                cmd="cmd_copy"/>
-      <menuitem label="&pasteCmd.label;"
-                accesskey="&pasteCmd.accesskey;"
-                cmd="cmd_paste"/>
-      <menuitem label="&deleteCmd.label;"
-                accesskey="&deleteCmd.accesskey;"
-                cmd="cmd_delete"/>
-      <menuseparator/>
-      <menuitem label="&selectAllCmd.label;"
-                accesskey="&selectAllCmd.accesskey;"
-                cmd="cmd_selectAll"/>
-      <menuseparator/>
-      <menuitem label="&syncSyncNowItem.label;"
-                accesskey="&syncSyncNowItem.accesskey;"
-                id="syncedTabsRefreshFilter"/>
-    </menupopup>
-
-    <hbox id="statuspanel" inactive="true" renderroot="content">
-      <hbox id="statuspanel-inner">
-        <label id="statuspanel-label"
-               role="status"
-               aria-live="off"
-               flex="1"
-               crop="end"/>
-      </hbox>
-    </hbox>
-  </popupset>
-  <box id="appMenu-viewCache" hidden="true"/>
-
-  <toolbox id="navigator-toolbox">
-
-    <vbox id="titlebar">
-      <!-- Menu -->
-      <toolbar type="menubar" id="toolbar-menubar"
-               class="browser-toolbar chromeclass-menubar titlebar-color"
-               customizable="true"
-               mode="icons"
-#ifdef MENUBAR_CAN_AUTOHIDE
-               toolbarname="&menubarCmd.label;"
-               accesskey="&menubarCmd.accesskey;"
-               autohide="true"
-#endif
-               context="toolbar-context-menu">
-        <toolbaritem id="menubar-items" align="center">
-# The entire main menubar is placed into browser-menubar.inc, so that it can be
-# shared with other top level windows in macWindow.inc.xul.
-#include browser-menubar.inc
-        </toolbaritem>
-        <spacer flex="1" skipintoolbarset="true" ordinal="1000"/>
-#include titlebar-items.inc.xul
-      </toolbar>
-
-      <toolbar id="TabsToolbar"
-               class="browser-toolbar titlebar-color"
-               fullscreentoolbar="true"
-               customizable="true"
-               customizationtarget="TabsToolbar-customization-target"
-               mode="icons"
-               aria-label="&tabsToolbar.label;"
-               context="toolbar-context-menu"
-               flex="1">
-
-        <hbox class="titlebar-spacer" type="pre-tabs"/>
-
-        <hbox flex="1" align="end" class="toolbar-items">
-          <hbox id="TabsToolbar-customization-target" flex="1">
-            <tabs id="tabbrowser-tabs"
-                  flex="1"
-                  setfocus="false"
-                  tooltip="tabbrowser-tab-tooltip"
-                  stopwatchid="FX_TAB_CLICK_MS">
-              <tab is="tabbrowser-tab" class="tabbrowser-tab" selected="true" visuallyselected="true" fadein="true"/>
-            </tabs>
-
-            <toolbarbutton id="new-tab-button"
-                           class="toolbarbutton-1 chromeclass-toolbar-additional"
-                           label="&tabCmd.label;"
-                           command="cmd_newNavigatorTab"
-                           onclick="checkForMiddleClick(this, event);"
-                           tooltip="dynamic-shortcut-tooltip"
-                           ondrop="newTabButtonObserver.onDrop(event)"
-                           ondragover="newTabButtonObserver.onDragOver(event)"
-                           ondragenter="newTabButtonObserver.onDragOver(event)"
-                           ondragexit="newTabButtonObserver.onDragExit(event)"
-                           cui-areatype="toolbar"
-                           removable="true"/>
-
-            <toolbarbutton id="alltabs-button"
-                           class="toolbarbutton-1 chromeclass-toolbar-additional tabs-alltabs-button"
-                           badged="true"
-                           oncommand="gTabsPanel.showAllTabsPanel();"
-                           label="&listAllTabs.label;"
-                           tooltiptext="&listAllTabs.label;"
-                           removable="false"/>
-          </hbox>
-        </hbox>
-
-        <hbox class="titlebar-spacer" type="post-tabs"/>
-
-#ifndef XP_MACOSX
-        <button class="accessibility-indicator" tooltiptext="&accessibilityIndicator.tooltip;"
-                aria-live="polite"/>
-        <hbox class="private-browsing-indicator"/>
-#endif
-
-#include titlebar-items.inc.xul
-
-#ifdef XP_MACOSX
-        <!-- OS X does not natively support RTL for its titlebar items, so we prevent this secondary
-             buttonbox from reversing order in RTL by forcing an LTR direction. -->
-        <hbox id="titlebar-secondary-buttonbox" dir="ltr">
-          <button class="accessibility-indicator" tooltiptext="&accessibilityIndicator.tooltip;" aria-live="polite"/>
-          <hbox class="private-browsing-indicator"/>
-          <hbox id="titlebar-fullscreen-button"/>
-        </hbox>
-#endif
-      </toolbar>
-
-    </vbox>
-
-    <toolbar id="nav-bar"
-             class="browser-toolbar"
-             aria-label="&navbarCmd.label;"
-             fullscreentoolbar="true" mode="icons" customizable="true"
-             customizationtarget="nav-bar-customization-target"
-             overflowable="true"
-             overflowbutton="nav-bar-overflow-button"
-             overflowtarget="widget-overflow-list"
-             overflowpanel="widget-overflow"
-             context="toolbar-context-menu">
-
-      <toolbartabstop/>
-      <hbox id="nav-bar-customization-target" flex="1">
-        <toolbarbutton id="back-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
-                       label="&backCmd.label;"
-                       removable="false" overflows="false"
-                       keepbroadcastattributeswhencustomizing="true"
-                       command="Browser:BackOrBackDuplicate"
-                       onclick="checkForMiddleClick(this, event);"
-                       tooltip="back-button-tooltip"
-                       context="backForwardMenu"/>
-        <toolbarbutton id="forward-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
-                       label="&forwardCmd.label;"
-                       removable="false" overflows="false"
-                       keepbroadcastattributeswhencustomizing="true"
-                       command="Browser:ForwardOrForwardDuplicate"
-                       onclick="checkForMiddleClick(this, event);"
-                       tooltip="forward-button-tooltip"
-                       context="backForwardMenu"/>
-        <toolbaritem id="stop-reload-button" class="chromeclass-toolbar-additional"
-                     title="&reloadCmd.label;"
-                     removable="true" overflows="false">
-          <toolbarbutton id="reload-button" class="toolbarbutton-1"
-                         label="&reloadCmd.label;"
-                         command="Browser:ReloadOrDuplicate"
-                         onclick="checkForMiddleClick(this, event);"
-                         tooltip="dynamic-shortcut-tooltip">
-            <box class="toolbarbutton-animatable-box">
-              <image class="toolbarbutton-animatable-image"/>
-            </box>
-          </toolbarbutton>
-          <toolbarbutton id="stop-button" class="toolbarbutton-1"
-                         label="&stopCmd.label;"
-                         command="Browser:Stop"
-                         tooltip="dynamic-shortcut-tooltip">
-            <box class="toolbarbutton-animatable-box">
-              <image class="toolbarbutton-animatable-image"/>
-            </box>
-          </toolbarbutton>
-        </toolbaritem>
-        <toolbarbutton id="home-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
-                       removable="true"
-                       label="&homeButton.label;"
-                       ondragover="homeButtonObserver.onDragOver(event)"
-                       ondragenter="homeButtonObserver.onDragOver(event)"
-                       ondrop="homeButtonObserver.onDrop(event)"
-                       ondragexit="homeButtonObserver.onDragExit(event)"
-                       key="goHome"
-                       onclick="BrowserHome(event);"
-                       cui-areatype="toolbar"
-                       tooltiptext="&homeButton.defaultPage.tooltip;"/>
-        <toolbarspring cui-areatype="toolbar" class="chromeclass-toolbar-additional"/>
-        <toolbaritem id="urlbar-container" flex="400" persist="width"
-                     removable="false"
-                     class="chromeclass-location" overflows="false">
-            <toolbartabstop/>
-            <textbox id="urlbar" flex="1"
-                     placeholder="&urlbar.placeholder2;"
-                     defaultPlaceholder="&urlbar.placeholder2;"
-                     focused="true"
-                     pageproxystate="invalid">
-              <!-- Use onclick instead of normal popup= syntax since the popup
-                   code fires onmousedown, and hence eats our favicon drag events. -->
-              <box id="identity-box" role="button"
-                   align="center"
-                   aria-label="&urlbar.viewSiteInfo.label;"
-                   onclick="gIdentityHandler.handleIdentityButtonEvent(event);"
-                   onkeypress="gIdentityHandler.handleIdentityButtonEvent(event);"
-                   ondragstart="gIdentityHandler.onDragStart(event);">
-                <image id="identity-icon"
-                       consumeanchor="identity-box"
-                       onclick="PageProxyClickHandler(event);"/>
-                <image id="sharing-icon" mousethrough="always"/>
-                <box id="tracking-protection-icon-box" animationsenabled="true">
-                  <image id="tracking-protection-icon"/>
-                  <box id="tracking-protection-icon-animatable-box" flex="1">
-                    <image id="tracking-protection-icon-animatable-image" flex="1"/>
-                  </box>
-                </box>
-                <box id="blocked-permissions-container" align="center">
-                  <image data-permission-id="geo" class="blocked-permission-icon geo-icon" role="button"
-                         tooltiptext="&urlbar.geolocationBlocked.tooltip;"/>
-                  <image data-permission-id="desktop-notification" class="blocked-permission-icon desktop-notification-icon" role="button"
-                         tooltiptext="&urlbar.webNotificationsBlocked.tooltip;"/>
-                  <image data-permission-id="camera" class="blocked-permission-icon camera-icon" role="button"
-                         tooltiptext="&urlbar.cameraBlocked.tooltip;"/>
-                  <image data-permission-id="microphone" class="blocked-permission-icon microphone-icon" role="button"
-                         tooltiptext="&urlbar.microphoneBlocked.tooltip;"/>
-                  <image data-permission-id="screen" class="blocked-permission-icon screen-icon" role="button"
-                         tooltiptext="&urlbar.screenBlocked.tooltip;"/>
-                  <image data-permission-id="persistent-storage" class="blocked-permission-icon persistent-storage-icon" role="button"
-                         tooltiptext="&urlbar.persistentStorageBlocked.tooltip;"/>
-                  <image data-permission-id="popup" class="blocked-permission-icon popup-icon" role="button"
-                         tooltiptext="&urlbar.popupBlocked.tooltip;"/>
-                  <image data-permission-id="autoplay-media" class="blocked-permission-icon autoplay-media-icon" role="button"
-                         tooltiptext="&urlbar.autoplayMediaBlocked.tooltip;"/>
-                  <image data-permission-id="canvas" class="blocked-permission-icon canvas-icon" role="button"
-                         tooltiptext="&urlbar.canvasBlocked.tooltip;"/>
-                  <image data-permission-id="plugin:flash" class="blocked-permission-icon plugin-icon" role="button"
-                         tooltiptext="&urlbar.flashPluginBlocked.tooltip;"/>
-                  <image data-permission-id="midi" class="blocked-permission-icon midi-icon" role="button"
-                         tooltiptext="&urlbar.midiBlocked.tooltip;"/>
-                  <image data-permission-id="install" class="blocked-permission-icon install-icon" role="button"
-                         tooltiptext="&urlbar.installBlocked.tooltip;"/>
-                </box>
-                <box id="notification-popup-box"
-                     hidden="true"
-                     onmouseover="document.getElementById('identity-box').classList.add('no-hover');"
-                     onmouseout="document.getElementById('identity-box').classList.remove('no-hover');"
-                     align="center">
-                  <image id="default-notification-icon" class="notification-anchor-icon" role="button"
-                         tooltiptext="&urlbar.defaultNotificationAnchor.tooltip;"/>
-                  <image id="geo-notification-icon" class="notification-anchor-icon geo-icon" role="button"
-                         tooltiptext="&urlbar.geolocationNotificationAnchor.tooltip;"/>
-                  <image id="autoplay-media-notification-icon" class="notification-anchor-icon autoplay-media-icon" role="button"
-                         tooltiptext="&urlbar.autoplayNotificationAnchor.tooltip;"/>
-                  <image id="addons-notification-icon" class="notification-anchor-icon install-icon" role="button"
-                         tooltiptext="&urlbar.addonsNotificationAnchor.tooltip;"/>
-                  <image id="canvas-notification-icon" class="notification-anchor-icon" role="button"
-                         tooltiptext="&urlbar.canvasNotificationAnchor.tooltip;"/>
-                  <image id="indexedDB-notification-icon" class="notification-anchor-icon indexedDB-icon" role="button"
-                         tooltiptext="&urlbar.indexedDBNotificationAnchor.tooltip;"/>
-                  <image id="password-notification-icon" class="notification-anchor-icon login-icon" role="button"
-                         tooltiptext="&urlbar.passwordNotificationAnchor.tooltip;"/>
-                  <stack id="plugins-notification-icon" class="notification-anchor-icon" role="button" align="center"
-                         tooltiptext="&urlbar.pluginsNotificationAnchor.tooltip;">
-                    <image class="plugin-icon" />
-                    <image id="plugin-icon-badge" />
-                  </stack>
-                  <image id="web-notifications-notification-icon" class="notification-anchor-icon desktop-notification-icon" role="button"
-                         tooltiptext="&urlbar.webNotificationAnchor.tooltip;"/>
-                  <image id="webRTC-shareDevices-notification-icon" class="notification-anchor-icon camera-icon" role="button"
-                         tooltiptext="&urlbar.webRTCShareDevicesNotificationAnchor.tooltip;"/>
-                  <image id="webRTC-shareMicrophone-notification-icon" class="notification-anchor-icon microphone-icon" role="button"
-                         tooltiptext="&urlbar.webRTCShareMicrophoneNotificationAnchor.tooltip;"/>
-                  <image id="webRTC-shareScreen-notification-icon" class="notification-anchor-icon screen-icon" role="button"
-                         tooltiptext="&urlbar.webRTCShareScreenNotificationAnchor.tooltip;"/>
-                  <image id="servicesInstall-notification-icon" class="notification-anchor-icon service-icon" role="button"
-                         tooltiptext="&urlbar.servicesNotificationAnchor.tooltip;"/>
-                  <image id="translate-notification-icon" class="notification-anchor-icon translation-icon" role="button"
-                         tooltiptext="&urlbar.translateNotificationAnchor.tooltip;"/>
-                  <image id="translated-notification-icon" class="notification-anchor-icon translation-icon in-use" role="button"
-                         tooltiptext="&urlbar.translatedNotificationAnchor.tooltip;"/>
-                  <image id="eme-notification-icon" class="notification-anchor-icon drm-icon" role="button"
-                         tooltiptext="&urlbar.emeNotificationAnchor.tooltip;"/>
-                  <image id="persistent-storage-notification-icon" class="notification-anchor-icon persistent-storage-icon" role="button"
-                         tooltiptext="&urlbar.persistentStorageNotificationAnchor.tooltip;"/>
-                  <image id="midi-notification-icon" class="notification-anchor-icon midi-icon" role="button"
-                         tooltiptext="&urlbar.midiNotificationAnchor.tooltip;"/>
-                  <image id="webauthn-notification-icon" class="notification-anchor-icon" role="button"
-                         tooltiptext="&urlbar.webAuthnAnchor.tooltip;"/>
-                  <image id="storage-access-notification-icon" class="notification-anchor-icon storage-access-icon" role="button"
-                         tooltiptext="&urlbar.storageAccessAnchor.tooltip;"/>
-                </box>
-                <image id="connection-icon"/>
-                <image id="extension-icon"/>
-                <image id="remote-control-icon"
-                       tooltiptext="&urlbar.remoteControlNotificationAnchor.tooltip;"/>
-                <hbox id="identity-icon-labels">
-                  <label id="identity-icon-label" class="plain" flex="1"/>
-                  <label id="identity-icon-country-label" class="plain"/>
-                </hbox>
-              </box>
-              <box id="urlbar-display-box" align="center">
-                <label id="switchtab" class="urlbar-display urlbar-display-switchtab" value="&urlbar.switchToTab.label;"/>
-                <label id="extension" class="urlbar-display urlbar-display-extension" value="&urlbar.extension.label;"/>
-              </box>
-              <hbox id="page-action-buttons" context="pageActionContextMenu">
-                <toolbartabstop/>
-                <hbox id="contextual-feature-recommendation" role="button" hidden="true">
-                  <hbox id="cfr-label-container">
-                    <label id="cfr-label"/>
-                  </hbox>
-                  <image id="cfr-button"
-                         class="urlbar-icon urlbar-page-action"
-                         role="presentation"/>
-                </hbox>
-                <hbox id="userContext-icons" hidden="true">
-                  <label id="userContext-label"/>
-                  <image id="userContext-indicator"/>
-                </hbox>
-                <image id="reader-mode-button"
-                       class="urlbar-icon urlbar-page-action"
-                       tooltip="dynamic-shortcut-tooltip"
-                       role="button"
-                       hidden="true"
-                       onclick="ReaderParent.buttonClick(event);"/>
-                <toolbarbutton id="urlbar-zoom-button"
-                       onclick="FullZoom.reset();"
-                       tooltip="dynamic-shortcut-tooltip"
-                       hidden="true"/>
-                <box id="pageActionSeparator" class="urlbar-page-action"/>
-                <image id="pageActionButton"
-                       class="urlbar-icon urlbar-page-action"
-                       role="button"
-                       tooltiptext="&pageActionButton.tooltip;"
-                       onmousedown="BrowserPageActions.mainButtonClicked(event);"
-                       onkeypress="BrowserPageActions.mainButtonClicked(event);"/>
-                <hbox id="pocket-button-box"
-                      hidden="true"
-                      class="urlbar-icon-wrapper urlbar-page-action"
-                      onclick="BrowserPageActions.doCommandForAction(PageActions.actionForID('pocket'), event, this);">
-                  <image id="pocket-button"
-                         class="urlbar-icon"
-                         tooltiptext="&pocketButton.tooltiptext;"
-                         role="button"/>
-                  <hbox id="pocket-button-animatable-box">
-                    <image id="pocket-button-animatable-image"
-                           tooltiptext="&pocketButton.tooltiptext;"
-                           role="presentation"/>
-                  </hbox>
-                </hbox>
-                <hbox id="star-button-box"
-                      hidden="true"
-                      class="urlbar-icon-wrapper urlbar-page-action"
-                      onclick="BrowserPageActions.doCommandForAction(PageActions.actionForID('bookmark'), event, this);">
-                  <image id="star-button"
-                         class="urlbar-icon"
-                         role="button"/>
-                  <hbox id="star-button-animatable-box">
-                    <image id="star-button-animatable-image"
-                           role="presentation"/>
-                  </hbox>
-                </hbox>
-              </hbox>
-            </textbox>
-            <toolbartabstop/>
-        </toolbaritem>
-
-        <toolbarspring cui-areatype="toolbar" class="chromeclass-toolbar-additional"/>
-
-        <!-- This is a placeholder for the Downloads Indicator.  It is visible
-             during the customization of the toolbar, in the palette, and before
-             the Downloads Indicator overlay is loaded. -->
-        <toolbarbutton id="downloads-button"
-                       class="toolbarbutton-1 chromeclass-toolbar-additional"
-                       badged="true"
-                       key="key_openDownloads"
-                       onmousedown="DownloadsIndicatorView.onCommand(event);"
-                       onkeypress="DownloadsIndicatorView.onCommand(event);"
-                       ondrop="DownloadsIndicatorView.onDrop(event);"
-                       ondragover="DownloadsIndicatorView.onDragOver(event);"
-                       ondragenter="DownloadsIndicatorView.onDragOver(event);"
-                       label="&downloads.label;"
-                       removable="true"
-                       overflows="false"
-                       cui-areatype="toolbar"
-                       hidden="true"
-                       tooltip="dynamic-shortcut-tooltip"
-                       indicator="true">
-            <!-- The panel's anchor area is smaller than the outer button, but must
-                 always be visible and must not move or resize when the indicator
-                 state changes, otherwise the panel could change its position or lose
-                 its arrow unexpectedly. -->
-            <stack id="downloads-indicator-anchor"
-                   consumeanchor="downloads-button">
-              <box id="downloads-indicator-icon"/>
-              <stack id="downloads-indicator-progress-outer">
-                <box id="downloads-indicator-progress-inner"/>
-              </stack>
-            </stack>
-          </toolbarbutton>
-
-        <toolbarbutton id="library-button" class="toolbarbutton-1 chromeclass-toolbar-additional subviewbutton-nav"
-                       removable="true"
-                       onmousedown="PanelUI.showSubView('appMenu-libraryView', this, event);"
-                       onkeypress="PanelUI.showSubView('appMenu-libraryView', this, event);"
-                       closemenu="none"
-                       cui-areatype="toolbar"
-                       tooltiptext="&libraryButton.tooltip;"
-                       label="&places.library.title;"/>
-
-        <toolbarbutton id="fxa-toolbar-menu-button" class="toolbarbutton-1 chromeclass-toolbar-additional subviewbutton-nav"
-                       badged="true"
-                       onmousedown="gSync.toggleAccountPanel('PanelUI-fxa', event)"
-                       onkeypress="gSync.toggleAccountPanel('PanelUI-fxa', event)"
-                       consumeanchor="fxa-toolbar-menu-button"
-                       closemenu="none"
-                       label="&fxa.menu.firefoxAccount;"
-                       tooltiptext="&fxa.menu.firefoxAccount;"
-                       cui-areatype="toolbar"
-                       removable="true">
-                       <vbox>
-                        <image id="fxa-avatar-image"/>
-                       </vbox>
-        </toolbarbutton>
-      </hbox>
-
-      <toolbarbutton id="nav-bar-overflow-button"
-                     class="toolbarbutton-1 chromeclass-toolbar-additional overflow-button"
-                     skipintoolbarset="true"
-                     tooltiptext="&navbarOverflow.label;">
-        <box class="toolbarbutton-animatable-box">
-          <image class="toolbarbutton-animatable-image"/>
-        </box>
-      </toolbarbutton>
-
-      <toolbaritem id="PanelUI-button"
-                   removable="false">
-        <toolbarbutton id="PanelUI-menu-button"
-                       class="toolbarbutton-1"
-                       badged="true"
-                       consumeanchor="PanelUI-button"
-                       label="&brandShortName;"
-                       tooltiptext="&appmenu.tooltip;"/>
-      </toolbaritem>
-
-      <hbox id="window-controls" hidden="true" pack="end" skipintoolbarset="true"
-            ordinal="1000">
-        <toolbarbutton id="minimize-button"
-                       tooltiptext="&fullScreenMinimize.tooltip;"
-                       oncommand="window.minimize();"/>
-
-        <toolbarbutton id="restore-button"
-#ifdef XP_MACOSX
-# Prior to 10.7 there wasn't a native fullscreen button so we use #restore-button
-# to exit fullscreen and want it to behave like other toolbar buttons.
-                       class="toolbarbutton-1"
-#endif
-                       tooltiptext="&fullScreenRestore.tooltip;"
-                       oncommand="BrowserFullScreen();"/>
-
-        <toolbarbutton id="close-button"
-                       tooltiptext="&fullScreenClose.tooltip;"
-                       oncommand="BrowserTryToCloseWindow();"/>
-      </hbox>
-
-      <box id="library-animatable-box" class="toolbarbutton-animatable-box">
-        <image class="toolbarbutton-animatable-image"/>
-      </box>
-    </toolbar>
-
-    <toolbar id="PersonalToolbar"
-             mode="icons"
-             class="browser-toolbar chromeclass-directories"
-             context="toolbar-context-menu"
-             toolbarname="&personalbarCmd.label;" accesskey="&personalbarCmd.accesskey;"
-             collapsed="true"
-             customizable="true">
-      <toolbartabstop skipintoolbarset="true"/>
-      <toolbaritem id="personal-bookmarks"
-                   title="&bookmarksToolbarItem.label;"
-                   cui-areatype="toolbar"
-                   removable="true">
-        <toolbarbutton id="bookmarks-toolbar-placeholder"
-                       class="bookmark-item"
-                       label="&bookmarksToolbarItem.label;"/>
-        <toolbarbutton id="bookmarks-toolbar-button"
-                       class="toolbarbutton-1"
-                       flex="1"
-                       label="&bookmarksToolbarItem.label;"
-                       oncommand="PlacesToolbarHelper.onPlaceholderCommand();"/>
-        <hbox flex="1"
-              id="PlacesToolbar"
-              context="placesContext"
-              onmouseup="BookmarksEventHandler.onMouseUp(event);"
-              onclick="BookmarksEventHandler.onClick(event, this._placesView);"
-              oncommand="BookmarksEventHandler.onCommand(event);"
-              tooltip="bhTooltip"
-              popupsinherittooltip="true">
-          <hbox flex="1">
-            <hbox id="PlacesToolbarDropIndicatorHolder" align="center" collapsed="true">
-              <image id="PlacesToolbarDropIndicator"
-                     mousethrough="always"
-                     collapsed="true"/>
-            </hbox>
-            <scrollbox orient="horizontal"
-                       id="PlacesToolbarItems"
-                       flex="1"/>
-            <toolbarbutton type="menu"
-                           id="PlacesChevron"
-                           class="toolbarbutton-1"
-                           mousethrough="never"
-                           collapsed="true"
-                           tooltiptext="&bookmarksToolbarChevron.tooltip;"
-                           onpopupshowing="document.getElementById('PlacesToolbar')
-                                                   ._placesView._onChevronPopupShowing(event);">
-              <menupopup id="PlacesChevronPopup"
-                         placespopup="true"
-                         tooltip="bhTooltip" popupsinherittooltip="true"
-                         context="placesContext"/>
-            </toolbarbutton>
-          </hbox>
-        </hbox>
-      </toolbaritem>
-    </toolbar>
-
-    <toolbarpalette id="BrowserToolbarPalette">
-
-      <toolbarbutton id="print-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
-#ifdef XP_MACOSX
-                     command="cmd_print"
-                     tooltip="dynamic-shortcut-tooltip"
-#else
-                     command="cmd_printPreview"
-                     tooltiptext="&printButton.tooltip;"
-#endif
-                     label="&printButton.label;"/>
-
-
-      <toolbarbutton id="new-window-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     label="&newNavigatorCmd.label;"
-                     command="cmd_newNavigator"
-                     tooltip="dynamic-shortcut-tooltip"
-                     ondrop="newWindowButtonObserver.onDrop(event)"
-                     ondragover="newWindowButtonObserver.onDragOver(event)"
-                     ondragenter="newWindowButtonObserver.onDragOver(event)"
-                     ondragexit="newWindowButtonObserver.onDragExit(event)"/>
-
-      <toolbarbutton id="fullscreen-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     observes="View:FullScreen"
-                     type="checkbox"
-                     label="&fullScreenCmd.label;"
-                     tooltip="dynamic-shortcut-tooltip"/>
-
-      <toolbarbutton id="bookmarks-menu-button"
-                     class="toolbarbutton-1 chromeclass-toolbar-additional subviewbutton-nav"
-                     type="menu"
-                     label="&bookmarksMenuButton2.label;"
-                     tooltip="dynamic-shortcut-tooltip"
-                     ondragenter="PlacesMenuDNDHandler.onDragEnter(event);"
-                     ondragover="PlacesMenuDNDHandler.onDragOver(event);"
-                     ondragleave="PlacesMenuDNDHandler.onDragLeave(event);"
-                     ondrop="PlacesMenuDNDHandler.onDrop(event);"
-                     oncommand="BookmarkingUI.onCommand(event);">
-        <menupopup id="BMB_bookmarksPopup"
-                   class="cui-widget-panel cui-widget-panelview cui-widget-panelWithFooter PanelUI-subView"
-                   placespopup="true"
-                   context="placesContext"
-                   openInTabs="children"
-                   side="top"
-                   onmouseup="BookmarksEventHandler.onMouseUp(event);"
-                   oncommand="BookmarksEventHandler.onCommand(event);"
-                   onclick="BookmarksEventHandler.onClick(event, this.parentNode._placesView);"
-                   onpopupshowing="BookmarkingUI.onPopupShowing(event);
-                                   BookmarkingUI.attachPlacesView(event, this);"
-                   tooltip="bhTooltip" popupsinherittooltip="true">
-          <menuitem id="BMB_viewBookmarksSidebar"
-                    class="menuitem-iconic subviewbutton"
-                    label-show="&viewBookmarksSidebar2.label;"
-                    label-hide="&hideBookmarksSidebar.label;"
-                    oncommand="SidebarUI.toggle('viewBookmarksSidebar');"/>
-          <!-- NB: temporary solution for bug 985024, this should go away soon. -->
-          <menuitem id="BMB_bookmarksShowAllTop"
-                    class="menuitem-iconic subviewbutton"
-                    label="&showAllBookmarks2.label;"
-                    command="Browser:ShowAllBookmarks"
-                    key="manBookmarkKb"/>
-          <menuseparator/>
-          <menu id="BMB_bookmarksToolbar"
-                class="menu-iconic bookmark-item subviewbutton"
-                label="&personalbarCmd.label;"
-                container="true">
-            <menupopup id="BMB_bookmarksToolbarPopup"
-                       placespopup="true"
-                       context="placesContext"
-                       onpopupshowing="if (!this.parentNode._placesView)
-                                         new PlacesMenu(event, `place:parent=${PlacesUtils.bookmarks.toolbarGuid}`,
-                                                        PlacesUIUtils.getViewForNode(this.parentNode.parentNode).options);">
-              <menuitem id="BMB_viewBookmarksToolbar"
-                        class="menuitem-iconic subviewbutton"
-                        label-show="&viewBookmarksToolbar.label;"
-                        label-hide="&hideBookmarksToolbar.label;"
-                        oncommand="BookmarkingUI.toggleBookmarksToolbar();"/>
-              <menuseparator/>
-              <!-- Bookmarks toolbar items -->
-            </menupopup>
-          </menu>
-          <menu id="BMB_unsortedBookmarks"
-                class="menu-iconic bookmark-item subviewbutton"
-                label="&bookmarksMenuButton.other.label;"
-                container="true">
-            <menupopup id="BMB_unsortedBookmarksPopup"
-                       placespopup="true"
-                       context="placesContext"
-                       onpopupshowing="if (!this.parentNode._placesView)
-                                         new PlacesMenu(event, `place:parent=${PlacesUtils.bookmarks.unfiledGuid}`,
-                                                        PlacesUIUtils.getViewForNode(this.parentNode.parentNode).options);"/>
-          </menu>
-          <menu id="BMB_mobileBookmarks"
-                class="menu-iconic bookmark-item subviewbutton"
-                label="&bookmarksMenuButton.mobile.label;"
-                hidden="true"
-                container="true">
-            <menupopup id="BMB_mobileBookmarksPopup"
-                       placespopup="true"
-                       context="placesContext"
-                       onpopupshowing="if (!this.parentNode._placesView)
-                                         new PlacesMenu(event, `place:parent=${PlacesUtils.bookmarks.mobileGuid}`,
-                                                        PlacesUIUtils.getViewForNode(this.parentNode.parentNode).options);"/>
-          </menu>
-
-          <menuseparator/>
-          <!-- Bookmarks menu items will go here -->
-          <menuitem id="BMB_bookmarksShowAll"
-                    class="subviewbutton panel-subview-footer"
-                    label="&showAllBookmarks2.label;"
-                    command="Browser:ShowAllBookmarks"
-                    key="manBookmarkKb"/>
-        </menupopup>
-      </toolbarbutton>
-
-      <toolbaritem id="search-container"
-                   class="chromeclass-toolbar-additional"
-                   title="&searchItem.title;"
-                   align="center"
-                   flex="100"
-                   persist="width">
-        <toolbartabstop/>
-        <searchbar id="searchbar" flex="1"/>
-        <toolbartabstop/>
-      </toolbaritem>
-    </toolbarpalette>
-  </toolbox>
-
-  <hbox id="fullscr-toggler" hidden="true"/>
-
-  <deck id="content-deck" flex="1" renderroot="content">
-    <hbox flex="1" id="browser">
-      <vbox id="browser-border-start" hidden="true" layer="true"/>
-      <vbox id="sidebar-box" hidden="true" class="chromeclass-extrachrome">
-        <sidebarheader id="sidebar-header" align="center">
-          <toolbarbutton id="sidebar-switcher-target" flex="1" class="tabbable">
-            <image id="sidebar-icon" consumeanchor="sidebar-switcher-target"/>
-            <label id="sidebar-title" crop="end" flex="1" control="sidebar"/>
-            <image id="sidebar-switcher-arrow"/>
-          </toolbarbutton>
-          <image id="sidebar-throbber"/>
-# To ensure the button label's intrinsic width doesn't expand the sidebar
-# if the label is long, the button needs flex=1.
-# To ensure the button doesn't expand unnecessarily for short labels, the
-# spacer should significantly out-flex the button.
-          <spacer flex="1000"/>
-          <toolbarbutton id="sidebar-close" class="close-icon tabbable" tooltiptext="&sidebarCloseButton.tooltip;" oncommand="SidebarUI.hide();"/>
-        </sidebarheader>
-        <browser id="sidebar" flex="1" autoscroll="false" disablehistory="true" disablefullscreen="true"
-                  style="min-width: 14em; width: 18em; max-width: 36em;" tooltip="aHTMLTooltip"/>
-      </vbox>
-
-      <splitter id="sidebar-splitter" class="chromeclass-extrachrome sidebar-splitter" hidden="true"/>
-      <vbox id="appcontent" flex="1">
-        <!-- gHighPriorityNotificationBox will be added here lazily. -->
-        <tabbox id="tabbrowser-tabbox"
-                flex="1" tabcontainer="tabbrowser-tabs">
-          <tabpanels id="tabbrowser-tabpanels"
-                     flex="1" class="plain" selectedIndex="0"/>
-        </tabbox>
-      </vbox>
-      <vbox id="browser-border-end" hidden="true" layer="true"/>
-    </hbox>
-    <box id="customization-container" flex="1" hidden="true"><![CDATA[
-#include ../../components/customizableui/content/customizeMode.inc.xul
-    ]]></box>
-  </deck>
-
-  <html:div id="fullscreen-warning" class="pointerlockfswarning" hidden="true" renderroot="content">
-    <html:div class="pointerlockfswarning-domain-text">
-      &fullscreenWarning.beforeDomain.label;
-      <html:span class="pointerlockfswarning-domain"/>
-      &fullscreenWarning.afterDomain.label;
-    </html:div>
-    <html:div class="pointerlockfswarning-generic-text">
-      &fullscreenWarning.generic.label;
-    </html:div>
-    <html:button id="fullscreen-exit-button"
-                 onclick="FullScreen.exitDomFullScreen();">
-#ifdef XP_MACOSX
-            &exitDOMFullscreenMac.button;
-#else
-            &exitDOMFullscreen.button;
-#endif
-    </html:button>
-  </html:div>
-
-  <html:div id="pointerlock-warning" class="pointerlockfswarning" hidden="true" renderroot="content">
-    <html:div class="pointerlockfswarning-domain-text">
-      &pointerlockWarning.beforeDomain.label;
-      <html:span class="pointerlockfswarning-domain"/>
-      &pointerlockWarning.afterDomain.label;
-    </html:div>
-    <html:div class="pointerlockfswarning-generic-text">
-      &pointerlockWarning.generic.label;
-    </html:div>
-  </html:div>
-
-  <vbox id="browser-bottombox" layer="true" renderroot="content">
-    <!-- gNotificationBox will be added here lazily. -->
-  </vbox>
-</window>
--- a/browser/base/content/global-scripts.inc
+++ b/browser/base/content/global-scripts.inc
@@ -1,26 +1,26 @@
 # -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 # 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/.
 
-# JS files which are needed by browser.xul but no other top level windows to
-# support MacOS specific features should be loaded directly from browser.xul
+# JS files which are needed by browser.xhtml but no other top level windows to
+# support MacOS specific features should be loaded directly from browser.xhtml
 # rather than this file.
 
 # If you update this list, you may need to add a mapping within the following
 # file so that ESLint works correctly:
 # tools/lint/eslint/eslint-plugin-mozilla/lib/environments/browser-window.js
 
 <script type="text/javascript">
 var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 Services.scriptloader.loadSubScript("chrome://browser/content/browser.js", this);
 Services.scriptloader.loadSubScript("chrome://browser/content/browser-places.js", this);
 Services.scriptloader.loadSubScript("chrome://global/content/globalOverlay.js", this);
 Services.scriptloader.loadSubScript("chrome://global/content/editMenuOverlay.js", this);
 Services.scriptloader.loadSubScript("chrome://browser/content/utilityOverlay.js", this);
-#ifdef XP_MACOSX
-Services.scriptloader.loadSubScript("chrome://global/content/macWindowMenu.js", this);
-#endif
+if (AppConstants.platform == "macosx") {
+  Services.scriptloader.loadSubScript("chrome://global/content/macWindowMenu.js", this);
+}
 
 </script>
--- a/browser/base/content/macWindow.inc.xul
+++ b/browser/base/content/macWindow.inc.xul
@@ -1,27 +1,27 @@
 # -*- Mode: HTML -*-
 #
 # 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/.
 
 # This include file should only contain things that are needed to support MacOS
 # specific features that are needed for all top level windows. If the feature is
-# also needed in browser.xul, it should go in one of the various include files
-# below that are shared with browser.xul. When including this file,
+# also needed in browser.xhtml, it should go in one of the various include files
+# below that are shared with browser.xhtml. When including this file,
 # browser-doctype.inc must also be included.
 
-# All JS files which are needed by browser.xul and other top level windows to
+# All JS files which are needed by browser.xhtml and other top level windows to
 # support MacOS specific features *must* go into the global-scripts.inc file so
-# that they can be shared with browser.xul.
+# that they can be shared with browser.xhtml.
 #include global-scripts.inc
 
 <script src="chrome://browser/content/nonbrowser-mac.js"></script>
 
 # All sets except for popupsets (commands, keys, and stringbundles)
 # *must* go into the browser-sets.inc file so that they can be shared with
-# browser.xul
+# browser.xhtml
 #include browser-sets.inc
 
 # The entire main menubar is placed into browser-menubar.inc, so that it can be
-# shared with browser.xul.
+# shared with browser.xhtml.
 #include browser-menubar.inc
--- a/browser/base/content/test/static/browser_all_files_referenced.js
+++ b/browser/base/content/test/static/browser_all_files_referenced.js
@@ -698,17 +698,17 @@ add_task(async function checkAllTheFiles
   for (let uri of uris) {
     uri = convertToCodeURI(uri.spec);
     if ((uri.startsWith("chrome://") || uri.startsWith("resource://")) &&
         isDevtools == hasDevtoolsPrefix(uri))
       chromeFiles.push(uri);
   }
 
   if (isDevtools) {
-    // chrome://devtools/skin/devtools-browser.css is included from browser.xul
+    // chrome://devtools/skin/devtools-browser.css is included from browser.xhtml
     gReferencesFromCode.set(AppConstants.BROWSER_CHROME_URL, null);
     // devtools' css is currently included from browser.css, see bug 1204810.
     gReferencesFromCode.set("chrome://browser/skin/browser.css", null);
   }
 
   let isUnreferenced = file => {
     if (gExceptionPaths.some(e => file.startsWith(e)))
       return false;
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -23,21 +23,17 @@ browser.jar:
         content/browser/aboutNetError.js               (content/aboutNetError.js)
         content/browser/aboutRobots-icon.png          (content/aboutRobots-icon.png)
         content/browser/aboutFrameCrashed.html        (content/aboutFrameCrashed.html)
         content/browser/aboutTabCrashed.css           (content/aboutTabCrashed.css)
         content/browser/aboutTabCrashed.js            (content/aboutTabCrashed.js)
         content/browser/aboutTabCrashed.xhtml         (content/aboutTabCrashed.xhtml)
 *       content/browser/browser.css                   (content/browser.css)
         content/browser/browser.js                    (content/browser.js)
-#ifdef MOZ_BROWSER_XUL
-*       content/browser/browser.xul                   (content/browser.xul)
-#else
 *       content/browser/browser.xhtml                 (content/browser.xhtml)
-#endif
         content/browser/browser-addons.js             (content/browser-addons.js)
         content/browser/browser-allTabsMenu.js        (content/browser-allTabsMenu.js)
         content/browser/browser-captivePortal.js      (content/browser-captivePortal.js)
         content/browser/browser-ctrlTab.js            (content/browser-ctrlTab.js)
         content/browser/browser-customization.js      (content/browser-customization.js)
         content/browser/browser-data-submission-info-bar.js (content/browser-data-submission-info-bar.js)
         content/browser/browser-contentblocking.js    (content/browser-contentblocking.js)
 #ifndef MOZILLA_OFFICIAL
--- a/browser/base/moz.build
+++ b/browser/base/moz.build
@@ -55,18 +55,16 @@ BROWSER_CHROME_MANIFESTS += [
     'content/test/touch/browser.ini',
     'content/test/trackingUI/browser.ini',
     'content/test/webextensions/browser.ini',
     'content/test/webrtc/browser.ini',
 ]
 
 DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION']
 DEFINES['MOZ_APP_VERSION_DISPLAY'] = CONFIG['MOZ_APP_VERSION_DISPLAY']
-if CONFIG['MOZ_BROWSER_XUL']:
-   DEFINES['MOZ_BROWSER_XUL'] = CONFIG['MOZ_BROWSER_XUL']
 
 DEFINES['APP_LICENSE_BLOCK'] = '%s/content/overrides/app-license.html' % SRCDIR
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk3', 'cocoa'):
     DEFINES['CONTEXT_COPY_IMAGE_CONTENTS'] = 1
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk3'):
     DEFINES['MENUBAR_CAN_AUTOHIDE'] = 1
--- a/browser/components/customizableui/CustomizeMode.jsm
+++ b/browser/components/customizableui/CustomizeMode.jsm
@@ -102,17 +102,17 @@ function CustomizeMode(aWindow) {
 
   let content = this.$("customization-content-container");
   if (!content) {
     this.window.MozXULElement.insertFTLIfNeeded("browser/customizeMode.ftl");
     let container = this.$("customization-container");
     container.replaceChild(this.window.MozXULElement.parseXULToFragment(container.firstChild.data), container.lastChild);
   }
   // There are two palettes - there's the palette that can be overlayed with
-  // toolbar items in browser.xul. This is invisible, and never seen by the
+  // toolbar items in browser.xhtml. This is invisible, and never seen by the
   // user. Then there's the visible palette, which gets populated and displayed
   // to the user when in customizing mode.
   this.visiblePalette = this.$(kPaletteId);
   this.pongArena = this.$("customization-pong-arena");
 
   if (this._canDrawInTitlebar()) {
     this._updateTitlebarCheckbox();
     this._updateDragSpaceCheckbox();
--- a/browser/components/extensions/test/browser/browser_ext_browserAction_pageAction_icon_permissions.js
+++ b/browser/components/extensions/test/browser/browser_ext_browserAction_pageAction_icon_permissions.js
@@ -133,17 +133,17 @@ add_task(async function testSecureURLsDe
       "browser_action": {},
       "page_action": {},
     },
 
     background: function() {
       browser.tabs.query({active: true, currentWindow: true}, tabs => {
         let tabId = tabs[0].id;
 
-        let urls = ["chrome://browser/content/browser.xul",
+        let urls = ["chrome://browser/content/browser.xhtml",
                     "javascript:true"];
 
         let promises = [];
         for (let url of urls) {
           for (let api of ["pageAction", "browserAction"]) {
             promises.push(
               browser.test.assertRejects(
                 browser[api].setIcon({tabId, path: url}),
@@ -164,17 +164,17 @@ add_task(async function testSecureURLsDe
   await extension.awaitFinish("setIcon security tests");
   await extension.unload();
 });
 
 
 add_task(async function testSecureManifestURLsDenied() {
   // Test URLs included in the manifest.
 
-  let urls = ["chrome://browser/content/browser.xul",
+  let urls = ["chrome://browser/content/browser.xhtml",
               "javascript:true"];
 
   let apis = ["browser_action", "page_action"];
 
   for (let url of urls) {
     for (let api of apis) {
       info(`TEST ${api} icon url: ${url}`);
 
--- a/browser/components/extensions/test/browser/browser_ext_pageAction_popup.js
+++ b/browser/components/extensions/test/browser/browser_ext_pageAction_popup.js
@@ -207,17 +207,17 @@ add_task(async function testPageActionPo
   let panel = document.getElementById(panelId);
   is(panel, null, "pageAction panel removed from document");
 
   BrowserTestUtils.removeTab(tab);
 });
 
 
 add_task(async function testPageActionSecurity() {
-  const URL = "chrome://browser/content/browser.xul";
+  const URL = "chrome://browser/content/browser.xhtml";
 
   let apis = ["browser_action", "page_action"];
 
   for (let api of apis) {
     info(`TEST ${api} icon url: ${URL}`);
 
     let messages = [/Access to restricted URI denied/];
 
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -175,17 +175,17 @@ var PlacesOrganizer = {
     if (AppConstants.platform === "macosx") {
       // 1. Map Edit->Find command to OrganizerCommand_find:all.  Need to map
       // both the menuitem and the Find key.
       let findMenuItem = document.getElementById("menu_find");
       findMenuItem.setAttribute("command", "OrganizerCommand_find:all");
       let findKey = document.getElementById("key_find");
       findKey.setAttribute("command", "OrganizerCommand_find:all");
 
-      // 2. Disable some keybindings from browser.xul
+      // 2. Disable some keybindings from browser.xhtml
       let elements = ["cmd_handleBackspace", "cmd_handleShiftBackspace"];
       for (let i = 0; i < elements.length; i++) {
         document.getElementById(elements[i]).setAttribute("disabled", "true");
       }
     }
 
     // remove the "Properties" context-menu item, we've our own details pane
     document.getElementById("placesContext")
--- a/browser/components/pocket/content/SaveToPocket.jsm
+++ b/browser/components/pocket/content/SaveToPocket.jsm
@@ -235,17 +235,17 @@ var SaveToPocket = {
   onPrefChange(pref, oldValue, newValue) {
     if (!newValue) {
       Services.mm.broadcastAsyncMessage("Reader:RemoveButton", { id: "pocket-button" });
       PocketOverlay.shutdown();
       Services.obs.addObserver(this, "browser-delayed-startup-finished");
     } else {
       Services.obs.removeObserver(this, "browser-delayed-startup-finished");
       PocketOverlay.startup();
-      // The title for the button is extracted from browser.xul where it comes from a DTD.
+      // The title for the button is extracted from browser.xhtml where it comes from a DTD.
       // If we don't have this, there's also no possibility of there being a reader
       // mode tab already loaded. We'll get an Reader:OnSetup message when that happens.
       if (this._readerButtonData.title) {
         Services.mm.broadcastAsyncMessage("Reader:AddButton", this._readerButtonData);
       }
     }
     this.updateElements(newValue);
   },
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -166,17 +166,17 @@
           // hamburger panel closes. Don't open in that spurious event.
           if (document.documentElement.getAttribute("customizing") == "true") {
             return;
           }
 
           let popup = this.popup;
           if (!popup.mPopupOpen) {
             // Initially the panel used for the searchbar (PopupSearchAutoComplete
-            // in browser.xul) is hidden to avoid impacting startup / new
+            // in browser.xhtml) is hidden to avoid impacting startup / new
             // window performance. The base binding's openPopup would normally
             // call the overriden openAutocompletePopup in
             // browser-search-autocomplete-result-popup binding to unhide the popup,
             // but since we're overriding openPopup we need to unhide the panel
             // ourselves.
             popup.hidden = false;
 
             // Don't roll up on mouse click in the anchor for the search UI.
--- a/browser/confvars.sh
+++ b/browser/confvars.sh
@@ -26,21 +26,17 @@ if test "$OS_ARCH" = "WINNT"; then
       fi
     fi
   fi
 fi
 
 # Enable building ./signmar and running libmar signature tests
 MOZ_ENABLE_SIGNMAR=1
 
-if [ "${MOZ_BROWSER_XUL}" = "1" ]; then
-  BROWSER_CHROME_URL=chrome://browser/content/browser.xul
-else
-  BROWSER_CHROME_URL=chrome://browser/content/browser.xhtml
-fi
+BROWSER_CHROME_URL=chrome://browser/content/browser.xhtml
 
 # MOZ_APP_DISPLAYNAME will be set by branding/configure.sh
 # MOZ_BRANDING_DIRECTORY is the default branding directory used when none is
 # specified. It should never point to the "official" branding directory.
 # For mozilla-beta, mozilla-release, or mozilla-central repositories, use
 # "unofficial" branding.
 # For the mozilla-aurora repository, use "aurora".
 MOZ_BRANDING_DIRECTORY=browser/branding/unofficial
--- a/browser/themes/shared/compacttheme.inc.css
+++ b/browser/themes/shared/compacttheme.inc.css
@@ -1,13 +1,13 @@
 % 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/.
 
-/* compacttheme.css is loaded in browser.xul after browser.css when it is
+/* compacttheme.css is loaded in browser.xhtml after browser.css when it is
    preffed on.  The bulk of the styling is here in the shared file, but
    there are overrides for each platform in their compacttheme.css files. */
 
 :root:-moz-lwtheme-brighttext {
   /* !important to override LightweightThemeConsumer.jsm */
   --autocomplete-popup-background: #2A2A2E !important;
   --autocomplete-popup-highlight-background: #0060DF;
 }
--- a/devtools/client/debugger/packages/devtools-reps/src/reps/stubs/document.js
+++ b/devtools/client/debugger/packages/devtools-reps/src/reps/stubs/document.js
@@ -42,13 +42,13 @@ stubs.set("XULDocument", {
   frozen: false,
   sealed: false,
   ownPropertyLength: 1,
   preview: {
     kind: "DOMNode",
     nodeType: 9,
     nodeName: "#document",
     isConnected: true,
-    location: "chrome://browser/content/browser.xul",
+    location: "chrome://browser/content/browser.xhtml",
   },
 });
 
 module.exports = stubs;
--- a/devtools/client/debugger/packages/devtools-reps/src/reps/tests/document.js
+++ b/devtools/client/debugger/packages/devtools-reps/src/reps/tests/document.js
@@ -49,13 +49,13 @@ describe("XULDocument", () => {
   it("renders with expected text content", () => {
     const renderedComponent = shallow(
       Document.rep({
         object: stub,
       })
     );
 
     expect(renderedComponent.text()).toEqual(
-      "XULDocument chrome://browser/content/browser.xul"
+      "XULDocument chrome://browser/content/browser.xhtml"
     );
     expectActorAttribute(renderedComponent, stub.actor);
   });
 });
--- a/devtools/client/framework/browser-menus.js
+++ b/devtools/client/framework/browser-menus.js
@@ -244,17 +244,17 @@ function addTopLevelItems(doc) {
   for (const node of menuItems.children) {
     nodes.push(node);
   }
   FragmentsCache.set(doc, nodes);
 
   const menu = doc.getElementById("menuWebDeveloperPopup");
   menu.appendChild(menuItems);
 
-  // There is still "Page Source" menuitem hardcoded into browser.xul. Instead
+  // There is still "Page Source" menuitem hardcoded into browser.xhtml. Instead
   // of manually inserting everything around it, move it to the expected
   // position.
   const pageSource = doc.getElementById("menu_pageSource");
   const endSeparator = doc.getElementById("devToolsEndSeparator");
   menu.insertBefore(pageSource, endSeparator);
 }
 
 /**
--- a/devtools/client/framework/test/browser_toolbox_custom_host.js
+++ b/devtools/client/framework/test/browser_toolbox_custom_host.js
@@ -29,17 +29,17 @@ add_task(async function() {
   let iframe = document.createXULElement("iframe");
   document.documentElement.appendChild(iframe);
 
   const tab = await addTab(TEST_URL);
   let target = await TargetFactory.forTab(tab);
   const options = { customIframe: iframe };
   let toolbox = await gDevTools.showToolbox(target, null, Toolbox.HostType.CUSTOM, options);
 
-  is(toolbox.win.top, window, "Toolbox is included in browser.xul");
+  is(toolbox.win.top, window, "Toolbox is included in browser.xhtml");
   is(toolbox.doc, iframe.contentDocument, "Toolbox is in the custom iframe");
 
   iframe.remove();
   await toolbox.destroy();
   await messageReceived;
 
   iframe = toolbox = target = null;
 });
--- a/devtools/client/framework/test/browser_toolbox_toggle.js
+++ b/devtools/client/framework/test/browser_toolbox_toggle.js
@@ -14,17 +14,17 @@ var {Toolbox} = require("devtools/client
 
 add_task(async function() {
   // Make sure this test starts with the selectedTool pref cleared. Previous
   // tests select various tools, and that sets this pref.
   Services.prefs.clearUserPref("devtools.toolbox.selectedTool");
 
   // Test with ACCEL+SHIFT+I / ACCEL+ALT+I (MacOSX) ; modifiers should match :
   // - toolbox-key-toggle in devtools/client/framework/toolbox-window.xul
-  // - key_devToolboxMenuItem in browser/base/content/browser.xul
+  // - key_devToolboxMenuItem in browser/base/content/browser.xhtml
   info("Test toggle using CTRL+SHIFT+I/CMD+ALT+I");
   await testToggle("I", {
     accelKey: true,
     shiftKey: !navigator.userAgent.match(/Mac/),
     altKey: navigator.userAgent.match(/Mac/),
   });
 
   // Test with F12 ; no modifiers
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/markup/components/TextNode.js
@@ -0,0 +1,77 @@
+/* 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";
+
+const {
+  createElement,
+  createRef,
+  Fragment,
+  PureComponent,
+} = require("devtools/client/shared/vendor/react");
+const dom = require("devtools/client/shared/vendor/react-dom-factories");
+const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
+const { editableItem } = require("devtools/client/shared/inplace-editor");
+
+const { getFormatStr } = require("../utils/l10n");
+
+class TextNode extends PureComponent {
+  static get propTypes() {
+    return {
+      showTextEditor: PropTypes.func.isRequired,
+      type: PropTypes.string.isRequired,
+      value: PropTypes.string.isRequired,
+    };
+  }
+
+  constructor(props) {
+    super(props);
+
+    this.state = {
+      value: this.props.value,
+    };
+
+    this.valuePreRef = createRef();
+  }
+
+  componentDidMount() {
+    editableItem({
+      element: this.valuePreRef.current,
+      trigger: "dblclick",
+    }, element => {
+      this.props.showTextEditor(element);
+    });
+  }
+
+  render() {
+    const { value } = this.state;
+    const isComment = this.props.type === "comment";
+    const isWhiteSpace = !/[^\s]/.exec(value);
+
+    return createElement(Fragment, null,
+      isComment ? dom.span({}, "<!--") : null,
+      dom.pre(
+        {
+          className: isWhiteSpace ? "whitespace" : "",
+          ref: this.valuePreRef,
+          style: {
+            display: "inline-block",
+            whiteSpace: "normal",
+          },
+          tabIndex: -1,
+          title: isWhiteSpace ?
+            getFormatStr("markupView.whitespaceOnly", value.replace(/\n/g, "⏎")
+                                                            .replace(/\t/g, "⇥")
+                                                            .replace(/ /g, "◦"))
+            :
+            "",
+        },
+        value
+      ),
+      isComment ? dom.span({}, "-->") : null
+    );
+  }
+}
+
+module.exports = TextNode;
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/markup/components/moz.build
@@ -0,0 +1,9 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+DevToolsModules(
+    'TextNode.js',
+)
--- a/devtools/client/inspector/markup/moz.build
+++ b/devtools/client/inspector/markup/moz.build
@@ -1,15 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DIRS += [
+    'components',
+    'utils',
     'views',
 ]
 
 DevToolsModules(
     'markup-context-menu.js',
     'markup.js',
     'utils.js',
 )
--- a/devtools/client/inspector/markup/test/browser_markup_keybindings_03.js
+++ b/devtools/client/inspector/markup/test/browser_markup_keybindings_03.js
@@ -19,17 +19,17 @@ add_task(async function() {
   await selectNode("div", inspector);
 
   const divFront = await walker.querySelector(walker.rootNode, "div");
   const textFront = await walker.nextSibling(divFront);
 
   info("Click on the MarkupContainer element for the text node");
   await clickContainer(textFront, inspector);
   is(inspector.markup.doc.activeElement,
-     getContainerForNodeFront(textFront, inspector).editor.value,
+     getContainerForNodeFront(textFront, inspector).editor.textNode.valuePreRef.current,
      "The currently focused element is the node's text content");
 
   info("Click on the MarkupContainer element for the <div> node");
   await clickContainer(divFront, inspector);
   is(inspector.markup.doc.activeElement,
      getContainerForNodeFront(divFront, inspector).editor.tag,
      "The currently focused element is the div's tagname");
 
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/markup/utils/l10n.js
@@ -0,0 +1,13 @@
+/* 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";
+
+const { LocalizationHelper } = require("devtools/shared/l10n");
+const L10N = new LocalizationHelper("devtools/client/locales/inspector.properties");
+
+module.exports = {
+  getStr: (...args) => L10N.getStr(...args),
+  getFormatStr: (...args) => L10N.getFormatStr(...args),
+};
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/markup/utils/moz.build
@@ -0,0 +1,9 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+DevToolsModules(
+    'l10n.js',
+)
--- a/devtools/client/inspector/markup/views/element-editor.js
+++ b/devtools/client/inspector/markup/views/element-editor.js
@@ -397,16 +397,17 @@ ElementEditor.prototype = {
   /**
    * Update the inline text editor in case of a single text child node.
    */
   updateTextEditor: function() {
     const node = this.node.inlineTextChild;
 
     if (this.textEditor && this.textEditor.node != node) {
       this.elt.removeChild(this.textEditor.elt);
+      this.textEditor.destroy();
       this.textEditor = null;
     }
 
     if (node && !this.textEditor) {
       // Create a text editor added to this editor.
       // This editor won't receive an update automatically, so we rely on
       // child text editors to let us know that we need updating.
       this.textEditor = new TextEditor(this.container, node, "text");
--- a/devtools/client/inspector/markup/views/text-editor.js
+++ b/devtools/client/inspector/markup/views/text-editor.js
@@ -1,22 +1,21 @@
 /* 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";
 
-const { editableField } = require("devtools/client/shared/inplace-editor");
-const { LocalizationHelper } = require("devtools/shared/l10n");
+const { createFactory } = require("devtools/client/shared/vendor/react");
+
+const TextNode = createFactory(require("devtools/client/inspector/markup/components/TextNode"));
 
 loader.lazyRequireGetter(this, "getAutocompleteMaxWidth", "devtools/client/inspector/markup/utils", true);
 loader.lazyRequireGetter(this, "getLongString", "devtools/client/inspector/shared/utils", true);
-
-const INSPECTOR_L10N =
-  new LocalizationHelper("devtools/client/locales/inspector.properties");
+loader.lazyRequireGetter(this, "InplaceEditor", "devtools/client/shared/inplace-editor", true);
 
 /**
  * Creates a simple text editor node, used for TEXT and COMMENT
  * nodes.
  *
  * @param  {MarkupContainer} container
  *         The container owning this editor.
  * @param  {DOMNode} node
@@ -25,97 +24,89 @@ const INSPECTOR_L10N =
  *         The type of editor to build. This can be either 'text' or 'comment'.
  */
 function TextEditor(container, node, type) {
   this.container = container;
   this.markup = this.container.markup;
   this.node = node;
   this._selected = false;
 
-  this.buildMarkup(type);
+  this.showTextEditor = this.showTextEditor.bind(this);
 
-  editableField({
-    element: this.value,
-    stopOnReturn: true,
-    trigger: "dblclick",
-    multiline: true,
-    maxWidth: () => getAutocompleteMaxWidth(this.value, this.container.elt),
-    trimOutput: false,
-    done: (val, commit) => {
-      if (!commit) {
-        return;
-      }
-      getLongString(this.node.getNodeValue()).then(oldValue => {
-        this.container.undo.do(() => {
-          this.node.setNodeValue(val);
-        }, () => {
-          this.node.setNodeValue(oldValue);
-        });
-      });
-    },
-    cssProperties: this.markup.inspector.cssProperties,
-  });
-
+  this.buildMarkup(type);
   this.update();
 }
 
 TextEditor.prototype = {
   buildMarkup: function(type) {
     const doc = this.markup.doc;
 
     this.elt = doc.createElement("span");
     this.elt.classList.add("editor", type);
 
-    if (type === "comment") {
-      const openComment = doc.createElement("span");
-      openComment.textContent = "<!--";
-      this.elt.appendChild(openComment);
-    }
+    this.textNode = this.ReactDOM.render(TextNode({
+      showTextEditor: this.showTextEditor,
+      type,
+      value: "",
+    }), this.elt);
+  },
 
-    this.value = doc.createElement("pre");
-    this.value.setAttribute("style", "display:inline-block;white-space: normal;");
-    this.value.setAttribute("tabindex", "-1");
-    this.elt.appendChild(this.value);
-
-    if (type === "comment") {
-      const closeComment = doc.createElement("span");
-      closeComment.textContent = "-->";
-      this.elt.appendChild(closeComment);
-    }
+  get ReactDOM() {
+    // Reuse the toolbox's ReactDOM to avoid loading react-dom.js again in the
+    // Inspector's BrowserLoader.
+    return this.container.markup.inspector.ReactDOM;
   },
 
   get selected() {
     return this._selected;
   },
 
   set selected(value) {
     if (value === this._selected) {
       return;
     }
     this._selected = value;
     this.update();
   },
 
-  update: function() {
-    getLongString(this.node.getNodeValue()).then(str => {
-      this.value.textContent = str;
-
-      const isWhitespace = !/[^\s]/.exec(str);
-      this.value.classList.toggle("whitespace", isWhitespace);
-
-      const chars = str.replace(/\n/g, "⏎")
-                     .replace(/\t/g, "⇥")
-                     .replace(/ /g, "◦");
-      this.value.setAttribute("title", isWhitespace
-        ? INSPECTOR_L10N.getFormatStr("markupView.whitespaceOnly", chars)
-        : "");
-    }).catch(console.error);
+  showTextEditor: function(element) {
+    new InplaceEditor({
+      cssProperties: this.markup.inspector.cssProperties,
+      done: (val, commit) => {
+        if (!commit) {
+          return;
+        }
+        getLongString(this.node.getNodeValue()).then(oldValue => {
+          this.container.undo.do(() => {
+            this.node.setNodeValue(val);
+          }, () => {
+            this.node.setNodeValue(oldValue);
+          });
+        });
+      },
+      element,
+      maxWidth: () => getAutocompleteMaxWidth(element, this.container.elt),
+      multiline: true,
+      stopOnReturn: true,
+      trimOutput: false,
+    });
   },
 
-  destroy: function() {},
+  update: async function() {
+    try {
+      const value = await getLongString(this.node.getNodeValue());
+      this.textNode.setState({ value });
+    } catch (e) {
+      console.error(e);
+    }
+  },
+
+  destroy: function() {
+    this.ReactDOM.unmountComponentAtNode(this.elt);
+  },
 
   /**
    * Stub method for consistency with ElementEditor.
    */
   getInfoAtNode: function() {
     return null;
   },
 };
--- a/devtools/client/shared/browser-loader.js
+++ b/devtools/client/shared/browser-loader.js
@@ -20,16 +20,17 @@ const BROWSER_BASED_DIRS = [
   "resource://devtools/client/inspector/boxmodel",
   "resource://devtools/client/inspector/changes",
   "resource://devtools/client/inspector/computed",
   "resource://devtools/client/inspector/events",
   "resource://devtools/client/inspector/flexbox",
   "resource://devtools/client/inspector/fonts",
   "resource://devtools/client/inspector/grids",
   "resource://devtools/client/inspector/layout",
+  "resource://devtools/client/inspector/markup",
   "resource://devtools/client/jsonview",
   "resource://devtools/client/netmonitor/src/utils",
   "resource://devtools/client/shared/source-map",
   "resource://devtools/client/shared/redux",
   "resource://devtools/client/shared/vendor",
 ];
 
 const COMMON_LIBRARY_DIRS = [
--- a/devtools/client/themes/splitters.css
+++ b/devtools/client/themes/splitters.css
@@ -1,13 +1,13 @@
 /* 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/. */
 
-/* This file is loaded by both browser.xul and toolbox.xul. Therefore, rules
+/* This file is loaded by both browser.xhtml and toolbox.xul. Therefore, rules
    defined here can not rely on toolbox.xul variables. */
 
 /* Splitters */
 
 :root {
   /* Draggable splitter element size */
   --devtools-splitter-element-size: 1px;
   --devtools-emphasized-splitter-element-size: 2px;
@@ -30,17 +30,17 @@
   --devtools-splitter-inline-end-width: 4px;
 
   --devtools-vertical-splitter-min-width: calc(var(--devtools-splitter-inline-start-width) +
                                                var(--devtools-splitter-inline-end-width) +
                                                var(--devtools-splitter-element-size));
 }
 
 #appcontent[devtoolstheme="light"] {
-  /* These variables are used in browser.xul but inside the toolbox they are overridden by --theme-splitter-color */
+  /* These variables are used in browser.xhtml but inside the toolbox they are overridden by --theme-splitter-color */
   --devtools-splitter-color: #dde1e4;
 }
 
 #appcontent[devtoolstheme="dark"] {
   --devtools-splitter-color: #42484f;
 }
 
 splitter.devtools-horizontal-splitter,
--- a/devtools/client/webconsole/test/mochitest/browser_console.js
+++ b/devtools/client/webconsole/test/mochitest/browser_console.js
@@ -98,17 +98,17 @@ async function testMessages(hud) {
   await fetch(TEST_IMAGE);
   console.log("fetch loaded");
 
   await checkMessageExists(hud, "message from chrome window");
   await checkMessageExists(hud,
     "error thrown from test-cu-reporterror.js via Cu.reportError()");
   await checkMessageExists(hud, "error from nuked globals");
   await checkMessageExists(hud, "message from content window");
-  await checkMessageExists(hud, "browser.xul");
+  await checkMessageExists(hud, "browser.xhtml");
   await checkMessageExists(hud, "framescript-eval");
   await checkMessageExists(hud, "framescript-message");
   await checkMessageExists(hud, "foobarException");
   await checkMessageExists(hud, "test-console.html");
   await checkMessageExists(hud, "404.html");
   await checkMessageExists(hud, "test-image.png");
 }
 
--- a/devtools/docs/contributing/css.md
+++ b/devtools/docs/contributing/css.md
@@ -78,17 +78,17 @@ Example:
 ## HDPI support
 
 It's recommended to use SVG since it keeps the CSS clean when supporting multiple resolutions. However, if only 1x and 2x PNG assets are available, you can use this `@media` query to target higher density displays (HDPI): `@media (min-resolution: 1.1dppx)`. <!--TODO an example would be good here-->
 
 ## Performance
 
 * Read [Writing Efficient CSS](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Writing_efficient_CSS).
 * Use an iframe where possible so your rules are scoped to the smallest possible set of nodes.<!--TODO: is this still true? and also refine exactly when it is appropriate to use an iframe. Examples might help-->
-* If your CSS is used in `browser.xul`, you need to take special care with performance:
+* If your CSS is used in `browser.xhtml`, you need to take special care with performance:
  * Descendent selectors should be avoided.
  * If possible, find ways to use **only** id selectors, class selectors and selector groups.
 
 ## Localization
 
 ### Text Direction
 * For margins, padding and borders, use `inline-start`/`inline-end` rather than `left`/`right`.
  * Example: Use `margin-inline-start: 3px;` not `margin-left: 3px`.
--- a/docshell/test/chrome/test_bug789773.xul
+++ b/docshell/test/chrome/test_bug789773.xul
@@ -54,16 +54,16 @@ https://bugzilla.mozilla.org/show_bug.cg
 
    // Open the window.
    var popup = window.open("about:mozilla", "_blank", "width=640,height=400");
 
    // Wait for the window to load.
    function finishTest() {
      webProgress.removeProgressListener(testProgressListener);
      ok(true, "Loaded the popup window without spinning forever in the event loop!");
-     ok(calledListenerForBrowserChromeURL, "Should have called the progress listener for browser.xul");
+     ok(calledListenerForBrowserChromeURL, "Should have called the progress listener for browser.xhtml");
      popup.close();
      SimpleTest.finish();
    }
 
   ]]>
   </script>
 </window>
--- a/dom/base/nsContentAreaDragDrop.cpp
+++ b/dom/base/nsContentAreaDragDrop.cpp
@@ -543,28 +543,19 @@ nsresult DragDataProducer::Produce(DataT
   nsCOMPtr<nsIContent> nodeToSerialize;
 
   nsCOMPtr<nsIDocShellTreeItem> dsti = mWindow->GetDocShell();
   const bool isChromeShell =
       dsti && dsti->ItemType() == nsIDocShellTreeItem::typeChrome;
 
   // In chrome shells, only allow dragging inside editable areas.
   if (isChromeShell && !editingElement) {
-    RefPtr<nsFrameLoaderOwner> flo = do_QueryObject(mTarget);
-    if (flo) {
-      RefPtr<nsFrameLoader> fl = flo->GetFrameLoader();
-      if (fl) {
-        BrowserParent* bp = fl->GetBrowserParent();
-        if (bp) {
-          // We have a BrowserParent, so it may have data for dnd in case the
-          // child process started a dnd session.
-          bp->AddInitialDnDDataTo(aDataTransfer, aPrincipal);
-        }
-      }
-    }
+    // This path should already be filtered out in
+    // EventStateManager::DetermineDragTargetAndDefaultData.
+    MOZ_ASSERT_UNREACHABLE("Shouldn't be generating drag data for chrome");
     return NS_OK;
   }
 
   if (isChromeShell && textControl) {
     // Only use the selection if the target node is in the selection.
     if (!selection->ContainsNode(*mSelectionTargetNode, false, IgnoreErrors()))
       return NS_OK;
 
--- a/dom/base/nsWindowMemoryReporter.h
+++ b/dom/base/nsWindowMemoryReporter.h
@@ -73,17 +73,17 @@
  * - <category> is "active", "cached", "detached", or "ghost", as described
  *   above.
  *
  * - <top-outer-id> is the window id of the top outer window (i.e. the tab, or
  *   the top level chrome window).  Exposing this ensures that each tab gets
  *   its own sub-tree, even if multiple tabs are showing the same URI.
  *
  * - <top-uri> is the URI of the top window.  Excepting special windows (such
- *   as browser.xul or hiddenWindow.html) it's what the address bar shows for
+ *   as browser.xhtml or hiddenWindow.html) it's what the address bar shows for
  *   the tab.
  *
  */
 class nsWindowMemoryReporter final : public nsIMemoryReporter,
                                      public nsIObserver,
                                      public nsSupportsWeakReference {
  public:
   NS_DECL_ISUPPORTS
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -29,16 +29,17 @@
 #include "mozilla/dom/UIEvent.h"
 #include "mozilla/dom/UIEventBinding.h"
 #include "mozilla/dom/WheelEventBinding.h"
 #include "mozilla/StaticPrefs.h"
 
 #include "ContentEventHandler.h"
 #include "IMEContentObserver.h"
 #include "WheelHandlingHelper.h"
+#include "RemoteDragStartData.h"
 
 #include "nsCommandParams.h"
 #include "nsCOMPtr.h"
 #include "nsCopySupport.h"
 #include "nsFocusManager.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIClipboard.h"
 #include "nsIContent.h"
@@ -1630,30 +1631,33 @@ void EventStateManager::SetGestureDownPo
 LayoutDeviceIntPoint EventStateManager::GetEventRefPoint(
     WidgetEvent* aEvent) const {
   auto touchEvent = aEvent->AsTouchEvent();
   return (touchEvent && !touchEvent->mTouches.IsEmpty())
              ? aEvent->AsTouchEvent()->mTouches[0]->mRefPoint
              : aEvent->mRefPoint;
 }
 
-void EventStateManager::BeginTrackingRemoteDragGesture(nsIContent* aContent) {
+void EventStateManager::BeginTrackingRemoteDragGesture(
+    nsIContent* aContent, RemoteDragStartData* aDragStartData) {
   mGestureDownContent = aContent;
   mGestureDownFrameOwner = aContent;
+  mGestureDownDragStartData = aDragStartData;
 }
 
 //
 // StopTrackingDragGesture
 //
 // Record that the mouse has gone back up so that we should leave the TRACKING
 // state of d&d gesture tracker and return to the START state.
 //
 void EventStateManager::StopTrackingDragGesture() {
   mGestureDownContent = nullptr;
   mGestureDownFrameOwner = nullptr;
+  mGestureDownDragStartData = nullptr;
 }
 
 void EventStateManager::FillInEventFromGestureDown(WidgetMouseEvent* aEvent) {
   NS_ASSERTION(aEvent->mWidget == mCurrentTarget->GetNearestWidget(),
                "Incorrect widget in event");
 
   // Set the coordinates in the new event to the coordinates of
   // the old event, adjusted for the fact that the widget might be
@@ -1779,23 +1783,25 @@ void EventStateManager::GenerateDragGest
           new DataTransfer(window, eDragStart, false, -1);
       auto protectDataTransfer = MakeScopeExit([&] {
         if (dataTransfer) {
           dataTransfer->Disconnect();
         }
       });
 
       RefPtr<Selection> selection;
+      RefPtr<RemoteDragStartData> remoteDragStartData;
       nsCOMPtr<nsIContent> eventContent, targetContent;
       nsCOMPtr<nsIPrincipal> principal;
       mCurrentTarget->GetContentForEvent(aEvent, getter_AddRefs(eventContent));
       if (eventContent)
         DetermineDragTargetAndDefaultData(
             window, eventContent, dataTransfer, getter_AddRefs(selection),
-            getter_AddRefs(targetContent), getter_AddRefs(principal));
+            getter_AddRefs(remoteDragStartData), getter_AddRefs(targetContent),
+            getter_AddRefs(principal));
 
       // Stop tracking the drag gesture now. This should stop us from
       // reentering GenerateDragGesture inside DOM event processing.
       StopTrackingDragGesture();
 
       if (!targetContent) return;
 
       // Use our targetContent, now that we've determined it, as the
@@ -1848,17 +1854,17 @@ void EventStateManager::GenerateDragGest
       if (observerService) {
         observerService->NotifyObservers(dataTransfer,
                                          "on-datatransfer-available", nullptr);
       }
 
       if (status != nsEventStatus_eConsumeNoDefault) {
         bool dragStarted =
             DoDefaultDragStart(aPresContext, event, dataTransfer, targetContent,
-                               selection, principal);
+                               selection, remoteDragStartData, principal);
         if (dragStarted) {
           sActiveESM = nullptr;
           MaybeFirePointerCancel(aEvent);
           aEvent->StopPropagation();
         }
       }
 
       // Reset mCurretTargetContent to what it was
@@ -1869,31 +1875,53 @@ void EventStateManager::GenerateDragGest
     // while dragging.
     FlushPendingEvents(aPresContext);
   }
 }  // GenerateDragGesture
 
 void EventStateManager::DetermineDragTargetAndDefaultData(
     nsPIDOMWindowOuter* aWindow, nsIContent* aSelectionTarget,
     DataTransfer* aDataTransfer, Selection** aSelection,
-    nsIContent** aTargetNode, nsIPrincipal** aPrincipal) {
+    RemoteDragStartData** aRemoteDragStartData, nsIContent** aTargetNode,
+    nsIPrincipal** aPrincipal) {
   *aTargetNode = nullptr;
 
-  // GetDragData determines if a selection, link or image in the content
-  // should be dragged, and places the data associated with the drag in the
-  // data transfer.
-  // mGestureDownContent is the node where the mousedown event for the drag
-  // occurred, and aSelectionTarget is the node to use when a selection is used
-  bool canDrag;
   nsCOMPtr<nsIContent> dragDataNode;
-  bool wasAlt = (mGestureModifiers & MODIFIER_ALT) != 0;
-  nsresult rv = nsContentAreaDragDrop::GetDragData(
-      aWindow, mGestureDownContent, aSelectionTarget, wasAlt, aDataTransfer,
-      &canDrag, aSelection, getter_AddRefs(dragDataNode), aPrincipal);
-  if (NS_FAILED(rv) || !canDrag) return;
+
+  nsIContent* editingElement = aSelectionTarget->IsEditable()
+                                   ? aSelectionTarget->GetEditingHost()
+                                   : nullptr;
+
+  // In chrome, only allow dragging inside editable areas.
+  bool isChromeContext = !aWindow->GetBrowsingContext()->IsContent();
+  if (isChromeContext && !editingElement) {
+    if (mGestureDownDragStartData) {
+      // A child process started a drag so use any data it assigned for the dnd
+      // session.
+      mGestureDownDragStartData->AddInitialDnDDataTo(aDataTransfer, aPrincipal);
+      mGestureDownDragStartData.forget(aRemoteDragStartData);
+    }
+  } else {
+    mGestureDownDragStartData = nullptr;
+
+    // GetDragData determines if a selection, link or image in the content
+    // should be dragged, and places the data associated with the drag in the
+    // data transfer.
+    // mGestureDownContent is the node where the mousedown event for the drag
+    // occurred, and aSelectionTarget is the node to use when a selection is
+    // used
+    bool canDrag;
+    bool wasAlt = (mGestureModifiers & MODIFIER_ALT) != 0;
+    nsresult rv = nsContentAreaDragDrop::GetDragData(
+        aWindow, mGestureDownContent, aSelectionTarget, wasAlt, aDataTransfer,
+        &canDrag, aSelection, getter_AddRefs(dragDataNode), aPrincipal);
+    if (NS_FAILED(rv) || !canDrag) {
+      return;
+    }
+  }
 
   // if GetDragData returned a node, use that as the node being dragged.
   // Otherwise, if a selection is being dragged, use the node within the
   // selection that was dragged. Otherwise, just use the mousedown target.
   nsIContent* dragContent = mGestureDownContent;
   if (dragDataNode)
     dragContent = dragDataNode;
   else if (*aSelection)
@@ -1938,22 +1966,20 @@ void EventStateManager::DetermineDragTar
     // XXXndeakin rework this a bit. Find a way to just not call GetDragData if
     // we don't need to.
     if (dragContent != originalDragContent) aDataTransfer->ClearAll();
     *aTargetNode = dragContent;
     NS_ADDREF(*aTargetNode);
   }
 }
 
-bool EventStateManager::DoDefaultDragStart(nsPresContext* aPresContext,
-                                           WidgetDragEvent* aDragEvent,
-                                           DataTransfer* aDataTransfer,
-                                           nsIContent* aDragTarget,
-                                           Selection* aSelection,
-                                           nsIPrincipal* aPrincipal) {
+bool EventStateManager::DoDefaultDragStart(
+    nsPresContext* aPresContext, WidgetDragEvent* aDragEvent,
+    DataTransfer* aDataTransfer, nsIContent* aDragTarget, Selection* aSelection,
+    RemoteDragStartData* aDragStartData, nsIPrincipal* aPrincipal) {
   nsCOMPtr<nsIDragService> dragService =
       do_GetService("@mozilla.org/widget/dragservice;1");
   if (!dragService) return false;
 
   // Default handling for the dragstart event.
   //
   // First, check if a drag session already exists. This means that the drag
   // service was called directly within a draggesture handler. In this case,
@@ -2017,16 +2043,21 @@ bool EventStateManager::DoDefaultDragSta
 
   // Use InvokeDragSessionWithSelection if a selection is being dragged,
   // such that the image can be generated from the selected text. However,
   // use InvokeDragSessionWithImage if a custom image was set or something
   // other than a selection is being dragged.
   if (!dragImage && aSelection) {
     dragService->InvokeDragSessionWithSelection(
         aSelection, aPrincipal, transArray, action, event, dataTransfer);
+  } else if (aDragStartData) {
+    MOZ_ASSERT(XRE_IsParentProcess());
+    dragService->InvokeDragSessionWithRemoteImage(
+        dragTarget, aPrincipal, transArray, action, aDragStartData, event,
+        dataTransfer);
   } else {
     dragService->InvokeDragSessionWithImage(dragTarget, aPrincipal, transArray,
                                             action, dragImage, imageX, imageY,
                                             event, dataTransfer);
   }
 
   return true;
 }
--- a/dom/events/EventStateManager.h
+++ b/dom/events/EventStateManager.h
@@ -41,16 +41,18 @@ class ScrollbarsForWheel;
 class WheelTransaction;
 
 namespace dom {
 class DataTransfer;
 class Document;
 class Element;
 class Selection;
 class BrowserParent;
+class RemoteDragStartData;
+
 }  // namespace dom
 
 class OverOutElementsWrapper final : public nsISupports {
   ~OverOutElementsWrapper();
 
  public:
   OverOutElementsWrapper();
 
@@ -1045,17 +1047,18 @@ class EventStateManager : public nsSuppo
                                 WidgetMouseEvent* aDownEvent,
                                 nsIFrame* aDownFrame);
 
   void SetGestureDownPoint(WidgetGUIEvent* aEvent);
 
   LayoutDeviceIntPoint GetEventRefPoint(WidgetEvent* aEvent) const;
 
   friend class mozilla::dom::BrowserParent;
-  void BeginTrackingRemoteDragGesture(nsIContent* aContent);
+  void BeginTrackingRemoteDragGesture(nsIContent* aContent,
+                                      dom::RemoteDragStartData* aDragStartData);
   void StopTrackingDragGesture();
   MOZ_CAN_RUN_SCRIPT
   void GenerateDragGesture(nsPresContext* aPresContext,
                            WidgetInputEvent* aEvent);
 
   /**
    * When starting a dnd session, UA must fire a pointercancel event and stop
    * firing the subsequent pointer events.
@@ -1070,40 +1073,41 @@ class EventStateManager : public nsSuppo
    *
    * aSelectionTarget - target to check for selection
    * aDataTransfer - data transfer object that will contain the data to drag
    * aSelection - [out] set to the selection to be dragged
    * aTargetNode - [out] the draggable node, or null if there isn't one
    * aPrincipal - [out] set to the triggering principal of the drag, or null
    *                    if it's from browser chrome or OS
    */
-  void DetermineDragTargetAndDefaultData(nsPIDOMWindowOuter* aWindow,
-                                         nsIContent* aSelectionTarget,
-                                         dom::DataTransfer* aDataTransfer,
-                                         dom::Selection** aSelection,
-                                         nsIContent** aTargetNode,
-                                         nsIPrincipal** aPrincipal);
+  void DetermineDragTargetAndDefaultData(
+      nsPIDOMWindowOuter* aWindow, nsIContent* aSelectionTarget,
+      dom::DataTransfer* aDataTransfer, dom::Selection** aSelection,
+      dom::RemoteDragStartData** aRemoteDragStartData, nsIContent** aTargetNode,
+      nsIPrincipal** aPrincipal);
 
   /*
    * Perform the default handling for the dragstart event and set up a
    * drag for aDataTransfer if it contains any data. Returns true if a drag has
    * started.
    *
    * aDragEvent - the dragstart event
    * aDataTransfer - the data transfer that holds the data to be dragged
    * aDragTarget - the target of the drag
    * aSelection - the selection to be dragged
+   * aData - information pertaining to a drag started in a child process
    * aPrincipal - the triggering principal of the drag, or null if it's from
    *              browser chrome or OS
    */
   MOZ_CAN_RUN_SCRIPT
   bool DoDefaultDragStart(nsPresContext* aPresContext,
                           WidgetDragEvent* aDragEvent,
                           dom::DataTransfer* aDataTransfer,
                           nsIContent* aDragTarget, dom::Selection* aSelection,
+                          dom::RemoteDragStartData* aDragStartData,
                           nsIPrincipal* aPrincipal);
 
   bool IsTrackingDragGesture() const { return mGestureDownContent != nullptr; }
   /**
    * Set the fields of aEvent to reflect the mouse position and modifier keys
    * that were set when the user first pressed the mouse button (stored by
    * BeginTrackingDragGesture). aEvent->mWidget must be
    * mCurrentTarget->GetNearestWidget().
@@ -1210,16 +1214,18 @@ class EventStateManager : public nsSuppo
   // member variables for the d&d gesture state machine
   LayoutDeviceIntPoint mGestureDownPoint;  // screen coordinates
   // The content to use as target if we start a d&d (what we drag).
   nsCOMPtr<nsIContent> mGestureDownContent;
   // The content of the frame where the mouse-down event occurred. It's the same
   // as the target in most cases but not always - for example when dragging
   // an <area> of an image map this is the image. (bug 289667)
   nsCOMPtr<nsIContent> mGestureDownFrameOwner;
+  // Data associated with a drag started in a content process.
+  RefPtr<dom::RemoteDragStartData> mGestureDownDragStartData;
   // State of keys when the original gesture-down happened
   Modifiers mGestureModifiers;
   uint16_t mGestureDownButtons;
 
   nsCOMPtr<nsIContent> mLastLeftMouseDownContent;
   nsCOMPtr<nsIContent> mLastMiddleMouseDownContent;
   nsCOMPtr<nsIContent> mLastRightMouseDownContent;
 
new file mode 100644
--- /dev/null
+++ b/dom/events/RemoteDragStartData.cpp
@@ -0,0 +1,82 @@
+/* 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/. */
+
+#include "nsContentAreaDragDrop.h"
+#include "RemoteDragStartData.h"
+#include "nsVariant.h"
+#include "mozilla/dom/BrowserParent.h"
+#include "mozilla/dom/IPCBlobUtils.h"
+#include "mozilla/dom/DOMTypes.h"
+#include "ProtocolUtils.h"
+
+using namespace mozilla::ipc;
+
+namespace mozilla {
+namespace dom {
+
+RemoteDragStartData::~RemoteDragStartData() { }
+
+RemoteDragStartData::RemoteDragStartData(
+    BrowserParent* aBrowserParent, nsTArray<IPCDataTransfer>&& aDataTransfer,
+    const LayoutDeviceIntRect& aRect, nsIPrincipal* aPrincipal)
+    : mBrowserParent(aBrowserParent),
+      mDataTransfer(aDataTransfer),
+      mRect(aRect),
+      mPrincipal(aPrincipal) {}
+
+void RemoteDragStartData::AddInitialDnDDataTo(DataTransfer* aDataTransfer,
+                                              nsIPrincipal** aPrincipal) {
+  NS_IF_ADDREF(*aPrincipal = mPrincipal);
+
+  for (uint32_t i = 0; i < mDataTransfer.Length(); ++i) {
+    nsTArray<IPCDataTransferItem>& itemArray = mDataTransfer[i].items();
+    for (auto& item : itemArray) {
+      RefPtr<nsVariantCC> variant = new nsVariantCC();
+      // Special case kFilePromiseMime so that we get the right
+      // nsIFlavorDataProvider for it.
+      if (item.flavor().EqualsLiteral(kFilePromiseMime)) {
+        RefPtr<nsISupports> flavorDataProvider =
+            new nsContentAreaDragDropDataProvider();
+        variant->SetAsISupports(flavorDataProvider);
+      } else if (item.data().type() == IPCDataTransferData::TnsString) {
+        variant->SetAsAString(item.data().get_nsString());
+      } else if (item.data().type() == IPCDataTransferData::TIPCBlob) {
+        RefPtr<BlobImpl> impl =
+            IPCBlobUtils::Deserialize(item.data().get_IPCBlob());
+        variant->SetAsISupports(impl);
+      } else if (item.data().type() == IPCDataTransferData::TShmem) {
+        if (nsContentUtils::IsFlavorImage(item.flavor())) {
+          // An image! Get the imgIContainer for it and set it in the variant.
+          nsCOMPtr<imgIContainer> imageContainer;
+          nsresult rv = nsContentUtils::DataTransferItemToImage(
+              item, getter_AddRefs(imageContainer));
+          if (NS_FAILED(rv)) {
+            continue;
+          }
+          variant->SetAsISupports(imageContainer);
+        } else {
+          Shmem data = item.data().get_Shmem();
+          variant->SetAsACString(
+              nsDependentCSubstring(data.get<char>(), data.Size<char>()));
+        }
+
+        mozilla::Unused << mBrowserParent->DeallocShmem(
+            item.data().get_Shmem());
+      }
+
+      // We set aHidden to false, as we don't need to worry about hiding data
+      // from content in the parent process where there is no content.
+      aDataTransfer->SetDataWithPrincipalFromOtherProcess(
+          NS_ConvertUTF8toUTF16(item.flavor()), variant, i, mPrincipal,
+          /* aHidden = */ false);
+    }
+  }
+
+  // Clear things that are no longer needed.
+  mDataTransfer.Clear();
+  mPrincipal = nullptr;
+}
+
+}  // namespace dom
+}  // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/events/RemoteDragStartData.h
@@ -0,0 +1,61 @@
+/* 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/. */
+
+#ifndef mozilla_dom_RemoteDragStartData_h
+#define mozilla_dom_RemoteDragStartData_h
+
+#include "nsCOMPtr.h"
+#include "nsRect.h"
+#include "mozilla/dom/DataTransfer.h"
+#include "mozilla/gfx/DataSurfaceHelpers.h"
+
+namespace mozilla {
+namespace dom {
+
+class IPCDataTransferItem;
+class BrowserParent;
+
+/**
+ * This class is used to hold information about a drag
+ * when a drag begins in a content process.
+ */
+class RemoteDragStartData {
+ public:
+  NS_INLINE_DECL_REFCOUNTING(RemoteDragStartData)
+
+  RemoteDragStartData(BrowserParent* aBrowserParent,
+                      nsTArray<IPCDataTransfer>&& aDataTransfer,
+                      const LayoutDeviceIntRect& aRect,
+                      nsIPrincipal* aPrincipal);
+
+  void SetVisualization(
+      already_AddRefed<gfx::DataSourceSurface> aVisualization) {
+    mVisualization = aVisualization;
+  }
+
+  // Get the drag image and rectangle, clearing it from this
+  // RemoteDragStartData in the process.
+  already_AddRefed<mozilla::gfx::SourceSurface> TakeVisualization(
+      LayoutDeviceIntRect* aRect) {
+    *aRect = mRect;
+    return mVisualization.forget();
+  }
+
+  void AddInitialDnDDataTo(DataTransfer* aDataTransfer,
+                           nsIPrincipal** aPrincipal);
+
+ private:
+  virtual ~RemoteDragStartData();
+
+  RefPtr<BrowserParent> mBrowserParent;
+  nsTArray<IPCDataTransfer> mDataTransfer;
+  const LayoutDeviceIntRect mRect;
+  nsCOMPtr<nsIPrincipal> mPrincipal;
+  RefPtr<mozilla::gfx::SourceSurface> mVisualization;
+};
+
+}  // namespace dom
+}  // namespace mozilla
+
+#endif  // mozilla_dom_RemoteDragStartData_h
--- a/dom/events/WheelHandlingHelper.cpp
+++ b/dom/events/WheelHandlingHelper.cpp
@@ -382,17 +382,17 @@ double WheelTransaction::ComputeAccelera
   return mozilla::ComputeAcceleratedWheelDelta(aDelta, sScrollSeriesCounter,
                                                aFactor);
 }
 
 /* static */
 DeltaValues WheelTransaction::OverrideSystemScrollSpeed(
     WidgetWheelEvent* aEvent) {
   MOZ_ASSERT(sTargetFrame, "We don't have mouse scrolling transaction");
-  MOZ_ASSERT(aEvent->mDeltaMode == WheelEvent_Binding::DOM_DELTA_LINE);
+  MOZ_ASSERT(aEvent->mDeltaMode == dom::WheelEvent_Binding::DOM_DELTA_LINE);
 
   // If the event doesn't scroll to both X and Y, we don't need to do anything
   // here.
   if (!aEvent->mDeltaX && !aEvent->mDeltaY) {
     return DeltaValues(aEvent);
   }
 
   return DeltaValues(aEvent->OverriddenDeltaX(), aEvent->OverriddenDeltaY());
@@ -672,17 +672,17 @@ ESMAutoDirWheelDeltaAdjuster::ESMAutoDir
   mScrollTargetFrame = aScrollFrame.GetScrollTargetFrame();
   MOZ_ASSERT(mScrollTargetFrame);
 
   nsIFrame* honouredFrame = nullptr;
   if (aHonoursRoot) {
     // If we are going to honour root, first try to get the frame for <body> as
     // the honoured root, because <body> is in preference to <html> if the
     // current document is an HTML document.
-    Document* document = aScrollFrame.PresShell()->GetDocument();
+    dom::Document* document = aScrollFrame.PresShell()->GetDocument();
     if (document) {
       Element* bodyElement = document->GetBodyElement();
       if (bodyElement) {
         honouredFrame = bodyElement->GetPrimaryFrame();
       }
     }
 
     if (!honouredFrame) {
--- a/dom/events/moz.build
+++ b/dom/events/moz.build
@@ -69,16 +69,17 @@ EXPORTS.mozilla.dom += [
     'MessageEvent.h',
     'MouseEvent.h',
     'MouseScrollEvent.h',
     'MutationEvent.h',
     'NotifyPaintEvent.h',
     'PaintRequest.h',
     'PointerEvent.h',
     'PointerEventHandler.h',
+    'RemoteDragStartData.h',
     'ScrollAreaEvent.h',
     'SimpleGestureEvent.h',
     'StorageEvent.h',
     'TextClause.h',
     'Touch.h',
     'TouchEvent.h',
     'TransitionEvent.h',
     'UIEvent.h',
@@ -121,16 +122,17 @@ UNIFIED_SOURCES += [
     'MessageEvent.cpp',
     'MouseEvent.cpp',
     'MouseScrollEvent.cpp',
     'MutationEvent.cpp',
     'NotifyPaintEvent.cpp',
     'PaintRequest.cpp',
     'PointerEvent.cpp',
     'PointerEventHandler.cpp',
+    'RemoteDragStartData.cpp',
     'ScrollAreaEvent.cpp',
     'SimpleGestureEvent.cpp',
     'StorageEvent.cpp',
     'TextClause.cpp',
     'TextComposition.cpp',
     'Touch.cpp',
     'TouchEvent.cpp',
     'TransitionEvent.cpp',
--- a/dom/ipc/BrowserParent.cpp
+++ b/dom/ipc/BrowserParent.cpp
@@ -15,19 +15,19 @@
 #include "mozilla/BrowserElementParent.h"
 #include "mozilla/dom/CancelContentJSOptionsBinding.h"
 #include "mozilla/dom/ChromeMessageSender.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/DataTransfer.h"
 #include "mozilla/dom/DataTransferItemList.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/indexedDB/ActorsParent.h"
-#include "mozilla/dom/IPCBlobUtils.h"
 #include "mozilla/dom/PaymentRequestParent.h"
 #include "mozilla/dom/BrowserBridgeParent.h"
+#include "mozilla/dom/RemoteDragStartData.h"
 #include "mozilla/dom/RemoteWebProgress.h"
 #include "mozilla/dom/RemoteWebProgressRequest.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/DataSurfaceHelpers.h"
 #include "mozilla/gfx/GPUProcessManager.h"
 #include "mozilla/Hal.h"
 #include "mozilla/IMEStateManager.h"
@@ -43,17 +43,16 @@
 #include "mozilla/PresShell.h"
 #include "mozilla/ProcessHangMonitor.h"
 #include "mozilla/StaticPrefs.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/TouchEvents.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Unused.h"
 #include "nsCOMPtr.h"
-#include "nsContentAreaDragDrop.h"
 #include "nsContentUtils.h"
 #include "nsDebug.h"
 #include "nsFocusManager.h"
 #include "nsFrameLoader.h"
 #include "nsFrameLoaderOwner.h"
 #include "nsFrameManager.h"
 #include "nsIBaseWindow.h"
 #include "nsIBrowser.h"
@@ -191,21 +190,16 @@ BrowserParent::BrowserParent(ContentPare
       mOrientation(0),
       mDPI(0),
       mRounding(0),
       mDefaultScale(0),
       mUpdatedDimensions(false),
       mSizeMode(nsSizeMode_Normal),
       mClientOffset{},
       mChromeOffset{},
-      mInitialDataTransferItems{},
-      mDnDVisualization{},
-      mDragValid(false),
-      mDragRect{},
-      mDragPrincipal{},
       mCreatingWindow(false),
       mDelayedURL{},
       mDelayedFrameScripts{},
       mCursor(eCursorInvalid),
       mCustomCursor{},
       mCustomCursorHotspotX(0),
       mCustomCursorHotspotY(0),
       mVerifyDropLinks{},
@@ -3482,122 +3476,53 @@ mozilla::ipc::IPCResult BrowserParent::R
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult BrowserParent::RecvInvokeDragSession(
     nsTArray<IPCDataTransfer>&& aTransfers, const uint32_t& aAction,
     Maybe<Shmem>&& aVisualDnDData, const uint32_t& aStride,
     const gfx::SurfaceFormat& aFormat, const LayoutDeviceIntRect& aDragRect,
     nsIPrincipal* aPrincipal) {
-  mInitialDataTransferItems.Clear();
   PresShell* presShell = mFrameElement->OwnerDoc()->GetPresShell();
   if (!presShell) {
     Unused << Manager()->SendEndDragSession(true, true, LayoutDeviceIntPoint(),
                                             0);
     // Continue sending input events with input priority when stopping the dnd
     // session.
     Manager()->SetInputPriorityEventEnabled(true);
     return IPC_OK();
   }
 
-  EventStateManager* esm = presShell->GetPresContext()->EventStateManager();
-  for (uint32_t i = 0; i < aTransfers.Length(); ++i) {
-    mInitialDataTransferItems.AppendElement(std::move(aTransfers[i].items()));
+  RefPtr<RemoteDragStartData> dragStartData = new RemoteDragStartData(
+      this, std::move(aTransfers), aDragRect, aPrincipal);
+
+  if (!aVisualDnDData.isNothing() && aVisualDnDData.ref().IsReadable() &&
+      aVisualDnDData.ref().Size<char>() >= aDragRect.height * aStride) {
+    dragStartData->SetVisualization(gfx::CreateDataSourceSurfaceFromData(
+        gfx::IntSize(aDragRect.width, aDragRect.height), aFormat,
+        aVisualDnDData.ref().get<uint8_t>(), aStride));
   }
 
   nsCOMPtr<nsIDragService> dragService =
       do_GetService("@mozilla.org/widget/dragservice;1");
   if (dragService) {
     dragService->MaybeAddChildProcess(Manager());
   }
 
-  if (aVisualDnDData.isNothing() || !aVisualDnDData.ref().IsReadable() ||
-      aVisualDnDData.ref().Size<char>() < aDragRect.height * aStride) {
-    mDnDVisualization = nullptr;
-  } else {
-    mDnDVisualization = gfx::CreateDataSourceSurfaceFromData(
-        gfx::IntSize(aDragRect.width, aDragRect.height), aFormat,
-        aVisualDnDData.ref().get<uint8_t>(), aStride);
-  }
-
-  mDragValid = true;
-  mDragRect = aDragRect;
-  mDragPrincipal = aPrincipal;
-
-  esm->BeginTrackingRemoteDragGesture(mFrameElement);
+  presShell->GetPresContext()
+      ->EventStateManager()
+      ->BeginTrackingRemoteDragGesture(mFrameElement, dragStartData);
 
   if (aVisualDnDData.isSome()) {
     Unused << DeallocShmem(aVisualDnDData.ref());
   }
 
   return IPC_OK();
 }
 
-void BrowserParent::AddInitialDnDDataTo(DataTransfer* aDataTransfer,
-                                        nsIPrincipal** aPrincipal) {
-  NS_IF_ADDREF(*aPrincipal = mDragPrincipal);
-
-  for (uint32_t i = 0; i < mInitialDataTransferItems.Length(); ++i) {
-    nsTArray<IPCDataTransferItem>& itemArray = mInitialDataTransferItems[i];
-    for (auto& item : itemArray) {
-      RefPtr<nsVariantCC> variant = new nsVariantCC();
-      // Special case kFilePromiseMime so that we get the right
-      // nsIFlavorDataProvider for it.
-      if (item.flavor().EqualsLiteral(kFilePromiseMime)) {
-        RefPtr<nsISupports> flavorDataProvider =
-            new nsContentAreaDragDropDataProvider();
-        variant->SetAsISupports(flavorDataProvider);
-      } else if (item.data().type() == IPCDataTransferData::TnsString) {
-        variant->SetAsAString(item.data().get_nsString());
-      } else if (item.data().type() == IPCDataTransferData::TIPCBlob) {
-        RefPtr<BlobImpl> impl =
-            IPCBlobUtils::Deserialize(item.data().get_IPCBlob());
-        variant->SetAsISupports(impl);
-      } else if (item.data().type() == IPCDataTransferData::TShmem) {
-        if (nsContentUtils::IsFlavorImage(item.flavor())) {
-          // An image! Get the imgIContainer for it and set it in the variant.
-          nsCOMPtr<imgIContainer> imageContainer;
-          nsresult rv = nsContentUtils::DataTransferItemToImage(
-              item, getter_AddRefs(imageContainer));
-          if (NS_FAILED(rv)) {
-            continue;
-          }
-          variant->SetAsISupports(imageContainer);
-        } else {
-          Shmem data = item.data().get_Shmem();
-          variant->SetAsACString(
-              nsDependentCSubstring(data.get<char>(), data.Size<char>()));
-        }
-
-        mozilla::Unused << DeallocShmem(item.data().get_Shmem());
-      }
-
-      // We set aHidden to false, as we don't need to worry about hiding data
-      // from content in the parent process where there is no content.
-      // XXX: Nested Content Processes may change this
-      aDataTransfer->SetDataWithPrincipalFromOtherProcess(
-          NS_ConvertUTF8toUTF16(item.flavor()), variant, i, mDragPrincipal,
-          /* aHidden = */ false);
-    }
-  }
-  mInitialDataTransferItems.Clear();
-  mDragPrincipal = nullptr;
-}
-
-bool BrowserParent::TakeDragVisualization(
-    RefPtr<mozilla::gfx::SourceSurface>& aSurface,
-    LayoutDeviceIntRect* aDragRect) {
-  if (!mDragValid) return false;
-
-  aSurface = mDnDVisualization.forget();
-  *aDragRect = mDragRect;
-  mDragValid = false;
-  return true;
-}
-
 bool BrowserParent::AsyncPanZoomEnabled() const {
   nsCOMPtr<nsIWidget> widget = GetWidget();
   return widget && widget->AsyncPanZoomEnabled();
 }
 
 void BrowserParent::StartPersistence(
     uint64_t aOuterWindowID, nsIWebBrowserPersistDocumentReceiver* aRecv,
     ErrorResult& aRv) {
--- a/dom/ipc/BrowserParent.h
+++ b/dom/ipc/BrowserParent.h
@@ -838,23 +838,16 @@ class BrowserParent final : public PBrow
   float mDPI;
   int32_t mRounding;
   CSSToLayoutDeviceScale mDefaultScale;
   bool mUpdatedDimensions;
   nsSizeMode mSizeMode;
   LayoutDeviceIntPoint mClientOffset;
   LayoutDeviceIntPoint mChromeOffset;
 
-  nsTArray<nsTArray<IPCDataTransferItem>> mInitialDataTransferItems;
-
-  RefPtr<gfx::DataSourceSurface> mDnDVisualization;
-  bool mDragValid;
-  LayoutDeviceIntRect mDragRect;
-  nsCOMPtr<nsIPrincipal> mDragPrincipal;
-
   // When loading a new tab or window via window.open, the child is
   // responsible for loading the URL it wants into the new BrowserChild. When
   // the parent receives the CreateWindow message, though, it sends a LoadURL
   // message, usually for about:blank. It's important for the about:blank load
   // to get processed because the Firefox frontend expects every new window to
   // immediately start loading something (see bug 1123090). However, we want
   // the child to process the LoadURL message before it returns from
   // ProvideWindow so that the URL sent from the parent doesn't override the
--- a/dom/localstorage/ActorsParent.cpp
+++ b/dom/localstorage/ActorsParent.cpp
@@ -1673,19 +1673,17 @@ class Datastore final
   DatastoreWriteOptimizer mWriteOptimizer;
   const nsCString mOrigin;
   const uint32_t mPrivateBrowsingId;
   int64_t mUsage;
   int64_t mUpdateBatchUsage;
   int64_t mSizeOfKeys;
   int64_t mSizeOfItems;
   bool mClosed;
-#ifdef DEBUG
   bool mInUpdateBatch;
-#endif
 
  public:
   // Created by PrepareDatastoreOp.
   Datastore(const nsACString& aOrigin, uint32_t aPrivateBrowsingId,
             int64_t aUsage, int64_t aSizeOfKeys, int64_t aSizeOfItems,
             already_AddRefed<DirectoryLock>&& aDirectoryLock,
             already_AddRefed<Connection>&& aConnection,
             already_AddRefed<QuotaObject>&& aQuotaObject,
@@ -1754,18 +1752,16 @@ class Datastore final
    */
   void SetItem(Database* aDatabase, const nsString& aKey,
                const LSValue& aValue);
 
   void RemoveItem(Database* aDatabase, const nsString& aKey);
 
   void Clear(Database* aDatabase);
 
-  void PrivateBrowsingClear();
-
   void BeginUpdateBatch(int64_t aSnapshotInitialUsage);
 
   int64_t EndUpdateBatch(int64_t aSnapshotPeakUsage);
 
   int64_t GetUsage() const { return mUsage; }
 
   int64_t RequestUpdateUsage(int64_t aRequestedSize, int64_t aMinSize);
 
@@ -1790,18 +1786,16 @@ class Datastore final
   void MaybeClose();
 
   void ConnectionClosedCallback();
 
   void CleanupMetadata();
 
   void NotifySnapshots(Database* aDatabase, const nsAString& aKey,
                        const LSValue& aOldValue, bool aAffectsOrder);
-
-  void MarkSnapshotsDirty();
 };
 
 class PreparedDatastore {
   RefPtr<Datastore> mDatastore;
   nsCOMPtr<nsITimer> mTimer;
   const Maybe<ContentParentId> mContentParentId;
   // Strings share buffers if possible, so it's not a problem to duplicate the
   // origin here.
@@ -3653,17 +3647,17 @@ bool RecvLSClearPrivateBrowsing() {
   AssertIsOnBackgroundThread();
 
   if (gDatastores) {
     for (auto iter = gDatastores->ConstIter(); !iter.Done(); iter.Next()) {
       Datastore* datastore = iter.Data();
       MOZ_ASSERT(datastore);
 
       if (datastore->PrivateBrowsingId()) {
-        datastore->PrivateBrowsingClear();
+        datastore->Clear(nullptr);
       }
     }
   }
 
   return true;
 }
 
 namespace localstorage {
@@ -4793,22 +4787,18 @@ Datastore::Datastore(const nsACString& a
       mConnection(std::move(aConnection)),
       mQuotaObject(std::move(aQuotaObject)),
       mOrigin(aOrigin),
       mPrivateBrowsingId(aPrivateBrowsingId),
       mUsage(aUsage),
       mUpdateBatchUsage(-1),
       mSizeOfKeys(aSizeOfKeys),
       mSizeOfItems(aSizeOfItems),
-      mClosed(false)
-#ifdef DEBUG
-      ,
-      mInUpdateBatch(false)
-#endif
-{
+      mClosed(false),
+      mInUpdateBatch(false) {
   AssertIsOnBackgroundThread();
 
   mValues.SwapElements(aValues);
   mOrderedItems.SwapElements(aOrderedItems);
 }
 
 Datastore::~Datastore() {
   AssertIsOnBackgroundThread();
@@ -5259,84 +5249,66 @@ void Datastore::RemoveItem(Database* aDa
     if (IsPersistent()) {
       mConnection->RemoveItem(aKey, delta);
     }
   }
 }
 
 void Datastore::Clear(Database* aDatabase) {
   AssertIsOnBackgroundThread();
-  MOZ_ASSERT(aDatabase);
   MOZ_ASSERT(!mClosed);
-  MOZ_ASSERT(mInUpdateBatch);
 
   if (mValues.Count()) {
     int64_t delta = 0;
     for (auto iter = mValues.ConstIter(); !iter.Done(); iter.Next()) {
       const nsAString& key = iter.Key();
       const LSValue& value = iter.Data();
 
       delta += -static_cast<int64_t>(key.Length()) -
                static_cast<int64_t>(value.UTF16Length());
 
       NotifySnapshots(aDatabase, key, value, /* aAffectsOrder */ true);
     }
 
     mValues.Clear();
 
-    mWriteOptimizer.Truncate();
-
-    mUpdateBatchUsage += delta;
+    if (mInUpdateBatch) {
+      mWriteOptimizer.Truncate();
+
+      mUpdateBatchUsage += delta;
+    } else {
+      mOrderedItems.Clear();
+
+      DebugOnly<bool> ok = UpdateUsage(delta);
+      MOZ_ASSERT(ok);
+    }
 
     mSizeOfKeys = 0;
     mSizeOfItems = 0;
 
     if (IsPersistent()) {
       mConnection->Clear(delta);
     }
   }
 }
 
-void Datastore::PrivateBrowsingClear() {
-  AssertIsOnBackgroundThread();
-  MOZ_ASSERT(mPrivateBrowsingId);
-  MOZ_ASSERT(!mClosed);
-  MOZ_ASSERT(!mInUpdateBatch);
-
-  if (mValues.Count()) {
-    MarkSnapshotsDirty();
-
-    mValues.Clear();
-
-    mOrderedItems.Clear();
-
-    DebugOnly<bool> ok = UpdateUsage(-mSizeOfItems);
-    MOZ_ASSERT(ok);
-
-    mSizeOfKeys = 0;
-    mSizeOfItems = 0;
-  }
-}
-
 void Datastore::BeginUpdateBatch(int64_t aSnapshotInitialUsage) {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aSnapshotInitialUsage >= 0);
   MOZ_ASSERT(!mClosed);
   MOZ_ASSERT(mUpdateBatchUsage == -1);
   MOZ_ASSERT(!mInUpdateBatch);
 
   mUpdateBatchUsage = aSnapshotInitialUsage;
 
   if (IsPersistent()) {
     mConnection->BeginUpdateBatch();
   }
 
-#ifdef DEBUG
   mInUpdateBatch = true;
-#endif
 }
 
 int64_t Datastore::EndUpdateBatch(int64_t aSnapshotPeakUsage) {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(!mClosed);
   MOZ_ASSERT(mInUpdateBatch);
 
   mWriteOptimizer.ApplyAndReset(mOrderedItems);
@@ -5364,19 +5336,17 @@ int64_t Datastore::EndUpdateBatch(int64_
 
   int64_t result = mUpdateBatchUsage;
   mUpdateBatchUsage = -1;
 
   if (IsPersistent()) {
     mConnection->EndUpdateBatch();
   }
 
-#ifdef DEBUG
   mInUpdateBatch = false;
-#endif
 
   return result;
 }
 
 int64_t Datastore::RequestUpdateUsage(int64_t aRequestedSize,
                                       int64_t aMinSize) {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aRequestedSize > 0);
@@ -5549,44 +5519,33 @@ void Datastore::CleanupMetadata() {
   if (!gDatastores->Count()) {
     gDatastores = nullptr;
   }
 }
 
 void Datastore::NotifySnapshots(Database* aDatabase, const nsAString& aKey,
                                 const LSValue& aOldValue, bool aAffectsOrder) {
   AssertIsOnBackgroundThread();
-  MOZ_ASSERT(aDatabase);
 
   for (auto iter = mDatabases.ConstIter(); !iter.Done(); iter.Next()) {
     Database* database = iter.Get()->GetKey();
+
+    MOZ_ASSERT(database);
+
     if (database == aDatabase) {
       continue;
     }
 
     Snapshot* snapshot = database->GetSnapshot();
     if (snapshot) {
       snapshot->SaveItem(aKey, aOldValue, aAffectsOrder);
     }
   }
 }
 
-void Datastore::MarkSnapshotsDirty() {
-  AssertIsOnBackgroundThread();
-
-  for (auto iter = mDatabases.ConstIter(); !iter.Done(); iter.Next()) {
-    Database* database = iter.Get()->GetKey();
-
-    Snapshot* snapshot = database->GetSnapshot();
-    if (snapshot) {
-      snapshot->MarkDirty();
-    }
-  }
-}
-
 /*******************************************************************************
  * PreparedDatastore
  ******************************************************************************/
 
 void PreparedDatastore::Destroy() {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(gPreparedDatastores);
   MOZ_ASSERT(gPreparedDatastores->Get(mDatastoreId));
--- a/dom/localstorage/moz.build
+++ b/dom/localstorage/moz.build
@@ -2,16 +2,18 @@
 # vim: set filetype=python:
 # 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/.
 
 with Files("**"):
     BUG_COMPONENT = ("Core", "DOM: Web Storage")
 
+BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
+
 XPCSHELL_TESTS_MANIFESTS += [
     'test/unit/xpcshell.ini'
 ]
 
 TEST_HARNESS_FILES.xpcshell.dom.localstorage.test.unit += [
     'test/unit/databaseShadowing-shared.js',
 ]
 
new file mode 100644
--- /dev/null
+++ b/dom/localstorage/test/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/browser-test",
+  ],
+};
new file mode 100644
--- /dev/null
+++ b/dom/localstorage/test/browser.ini
@@ -0,0 +1,6 @@
+[DEFAULT]
+skip-if = (buildapp != "browser")
+support-files =
+  page_private_ls.html
+
+[browser_private_ls.js]
new file mode 100644
--- /dev/null
+++ b/dom/localstorage/test/browser_private_ls.js
@@ -0,0 +1,39 @@
+/**
+ * This test is mainly to verify that datastores are cleared when the last
+ * private browsing context exited.
+ */
+
+async function lsCheckFunc() {
+  let storage = content.localStorage;
+
+  if (storage.length) {
+    return false;
+  }
+
+  // Store non-ASCII value to verify bug 1552428.
+  storage.setItem("foo", "úžasné");
+
+  return true;
+}
+
+function checkTabWindowLS(tab) {
+  return ContentTask.spawn(tab.linkedBrowser, null, lsCheckFunc);
+}
+
+add_task(async function() {
+  const pageUrl =
+    "http://example.com/browser/dom/localstorage/test/page_private_ls.html";
+
+  for (let i = 0; i < 2; i++) {
+    let privateWin =
+      await BrowserTestUtils.openNewBrowserWindow({private: true});
+
+    let privateTab =
+      await BrowserTestUtils.openNewForegroundTab(privateWin.gBrowser, pageUrl);
+
+    ok(await checkTabWindowLS(privateTab),
+       "LS works correctly in a private-browsing page.");
+
+    await BrowserTestUtils.closeWindow(privateWin);
+  }
+});
new file mode 100644
--- /dev/null
+++ b/dom/localstorage/test/page_private_ls.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<html>
+<head>
+  <meta charset="utf-8">
+</head>
+<body>
+  All the interesting stuff happens in ContentTask.spawn() calls.
+</body>
+</html>
--- a/dom/plugins/test/testplugin/nptest.cpp
+++ b/dom/plugins/test/testplugin/nptest.cpp
@@ -1053,17 +1053,17 @@ NPError NPP_New(NPMIMEType pluginType, N
     NPError err = NPN_GetURLNotify(instance, instanceData->testUrl.c_str(),
                                    nullptr, static_cast<void*>(&kNotifyData));
     if (err != NPERR_NO_ERROR) {
       instanceData->err << "NPN_GetURLNotify returned " << err;
     }
   }
 
   if ((instanceData->bugMode == 813906) && instanceData->frame.length()) {
-    bug813906(instance, "f", "browser.xul", instanceData->frame.c_str());
+    bug813906(instance, "f", "browser.xhtml", instanceData->frame.c_str());
   }
 
   return NPERR_NO_ERROR;
 }
 
 NPError NPP_Destroy(NPP instance, NPSavedData** save) {
   InstanceData* instanceData = (InstanceData*)(instance->pdata);
 
--- a/gfx/thebes/gfxFT2FontList.cpp
+++ b/gfx/thebes/gfxFT2FontList.cpp
@@ -702,21 +702,24 @@ class FontNameCache {
     mOps = (PLDHashTableOps){StringHash, HashMatchEntry, MoveEntry,
                              PLDHashTable::ClearEntryStub, nullptr};
 
     MOZ_ASSERT(XRE_IsParentProcess(),
                "FontNameCache should only be used in chrome process");
     mCache = mozilla::scache::StartupCache::GetSingleton();
   }
 
-  ~FontNameCache() {
+  ~FontNameCache() { WriteCache(); }
+
+  void WriteCache() {
     if (!mWriteNeeded || !mCache) {
       return;
     }
 
+    LOG(("Writing FontNameCache:"));
     nsAutoCString buf;
     for (auto iter = mMap.Iter(); !iter.Done(); iter.Next()) {
       auto entry = static_cast<FNCMapEntry*>(iter.Get());
       if (!entry->mFileExists) {
         // skip writing entries for files that are no longer present
         continue;
       }
       buf.Append(entry->mFilename);
@@ -724,33 +727,37 @@ class FontNameCache {
       buf.Append(entry->mFaces);
       buf.Append(';');
       buf.AppendInt(entry->mTimestamp);
       buf.Append(';');
       buf.AppendInt(entry->mFilesize);
       buf.Append(';');
     }
 
+    LOG(("putting FontNameCache to " CACHE_KEY ", length %u",
+         buf.Length() + 1));
     mCache->PutBuffer(CACHE_KEY, UniquePtr<char[]>(ToNewCString(buf)),
                       buf.Length() + 1);
+    mWriteNeeded = false;
   }
 
   // This may be called more than once (if we re-load the font list).
   void Init() {
     if (!mCache) {
       return;
     }
 
     uint32_t size;
     UniquePtr<char[]> buf;
     if (NS_FAILED(mCache->GetBuffer(CACHE_KEY, &buf, &size))) {
+      LOG(("no cache of " CACHE_KEY));
       return;
     }
 
-    LOG(("got: %s from the cache", nsDependentCString(buf.get(), size).get()));
+    LOG(("got: %u bytes from the cache " CACHE_KEY, size));
 
     mMap.Clear();
     mWriteNeeded = false;
 
     const char* beginning = buf.get();
     const char* end = strchr(beginning, ';');
     while (end) {
       nsCString filename(beginning, end - beginning);
@@ -1333,16 +1340,35 @@ void gfxFT2FontList::FindFonts() {
   // Finalize the families by sorting faces into standard order
   // and marking "simple" families.
   // Passing non-null userData here says that we want faces to be sorted.
   for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
     nsCStringHashKey::KeyType key = iter.Key();
     RefPtr<gfxFontFamily>& family = iter.Data();
     FinalizeFamilyMemberList(key, family, /* aSortFaces */ true);
   }
+  // Write out FontCache data if needed
+  WriteCache();
+}
+
+void gfxFT2FontList::WriteCache() {
+  if (mFontNameCache) {
+    mFontNameCache->WriteCache();
+  }
+  mozilla::scache::StartupCache* cache =
+      mozilla::scache::StartupCache::GetSingleton();
+  if (cache && mJarModifiedTime > 0) {
+    const size_t bufSize = sizeof(mJarModifiedTime);
+    auto buf = MakeUnique<char[]>(bufSize);
+    memcpy(buf.get(), &mJarModifiedTime, bufSize);
+
+    LOG(("WriteCache: putting Jar, length %zu", bufSize));
+    cache->PutBuffer(JAR_LAST_MODIFED_TIME, std::move(buf), bufSize);
+  }
+  LOG(("Done with writecache"));
 }
 
 void gfxFT2FontList::FindFontsInDir(const nsCString& aDir,
                                     FontNameCache* aFNC) {
   static const char* sStandardFonts[] = {"DroidSans.ttf",
                                          "DroidSans-Bold.ttf",
                                          "DroidSerif-Regular.ttf",
                                          "DroidSerif-Bold.ttf",
@@ -1543,19 +1569,12 @@ void gfxFT2FontList::GetFontFamilyList(
   }
 }
 
 gfxFontFamily* gfxFT2FontList::CreateFontFamily(const nsACString& aName) const {
   return new FT2FontFamily(aName);
 }
 
 void gfxFT2FontList::WillShutdown() {
-  mozilla::scache::StartupCache* cache =
-      mozilla::scache::StartupCache::GetSingleton();
-  if (cache && mJarModifiedTime > 0) {
-    const size_t bufSize = sizeof(mJarModifiedTime);
-    auto buf = MakeUnique<char[]>(bufSize);
-    memcpy(buf.get(), &mJarModifiedTime, bufSize);
-
-    cache->PutBuffer(JAR_LAST_MODIFED_TIME, std::move(buf), bufSize);
-  }
+  LOG(("WillShutdown"));
+  WriteCache();
   mFontNameCache = nullptr;
 }
--- a/gfx/thebes/gfxFT2FontList.h
+++ b/gfx/thebes/gfxFT2FontList.h
@@ -127,16 +127,18 @@ class gfxFT2FontList : public gfxPlatfor
 
   gfxFontEntry* MakePlatformFont(const nsACString& aFontName,
                                  WeightRange aWeightForEntry,
                                  StretchRange aStretchForEntry,
                                  SlantStyleRange aStyleForEntry,
                                  const uint8_t* aFontData,
                                  uint32_t aLength) override;
 
+  void WriteCache();
+
   void GetSystemFontList(InfallibleTArray<FontListEntry>* retValue);
 
   static gfxFT2FontList* PlatformFontList() {
     return static_cast<gfxFT2FontList*>(
         gfxPlatformFontList::PlatformFontList());
   }
 
   void GetFontFamilyList(
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -21,16 +21,18 @@
 #include "mozilla/webrender/webrender_ffi.h"
 #include "mozilla/webrender/WebRenderTypes.h"
 #include "GLTypes.h"
 #include "Units.h"
 
 class nsDisplayItem;
 class nsDisplayTransform;
 
+#undef None
+
 namespace mozilla {
 
 struct ActiveScrolledRoot;
 
 namespace widget {
 class CompositorWidget;
 }
 
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -9689,17 +9689,17 @@ bool nsTextFrame::IsEmpty() {
   }
 
   if (mState & TEXT_IS_ONLY_WHITESPACE) {
     return true;
   }
 
   bool isEmpty =
       IsAllWhitespace(TextFragment(), textStyle->mWhiteSpace !=
-                                           mozilla::StyleWhiteSpace::PreLine);
+                                          mozilla::StyleWhiteSpace::PreLine);
   AddStateBits(isEmpty ? TEXT_IS_ONLY_WHITESPACE : TEXT_ISNOT_ONLY_WHITESPACE);
   return isEmpty;
 }
 
 #ifdef DEBUG_FRAME_DUMP
 // Translate the mapped content into a string that's printable
 void nsTextFrame::ToCString(nsCString& aBuf,
                             int32_t* aTotalContentLength) const {
--- a/netwerk/protocol/about/nsAboutProtocolHandler.cpp
+++ b/netwerk/protocol/about/nsAboutProtocolHandler.cpp
@@ -160,40 +160,61 @@ nsresult nsAboutProtocolHandler::CreateN
              .Finalize(url);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   url.swap(*aResult);
   return NS_OK;
 }
 
+// The list of about: paths which are always allowed, regardless of enterprise
+// policies.
+//
+// Note: This is stored as a two-dimensional array, with each element the size
+// of the longest string in the list, for space efficiency. An array of
+// character pointers would consume more space than the extra padding in
+// shorter strings, and would require per-process relocations at load time.
+//
+// Important: This list MUST be kept sorted!
+static const char kAboutPageEnterpriseWhitelist[][10] = {
+    // clang-format off
+    "blank",
+    "certerror",
+    "home",
+    "neterror",
+    "newtab",
+    "welcome",
+    // clang-format on
+};
+
 NS_IMETHODIMP
 nsAboutProtocolHandler::NewChannel(nsIURI* uri, nsILoadInfo* aLoadInfo,
                                    nsIChannel** result) {
   NS_ENSURE_ARG_POINTER(uri);
 
   // about:what you ask?
   nsCOMPtr<nsIAboutModule> aboutMod;
   nsresult rv = NS_GetAboutModule(uri, getter_AddRefs(aboutMod));
 
   bool aboutPageAllowed = true;
   nsAutoCString path;
   nsresult rv2 = NS_GetAboutModuleName(uri, path);
   if (NS_SUCCEEDED(rv2)) {
+    size_t matchIdx;
     if (path.EqualsLiteral("srcdoc")) {
       // about:srcdoc is meant to be unresolvable, yet is included in the
       // about lookup tables so that it can pass security checks when used in
       // a srcdoc iframe.  To ensure that it stays unresolvable, we pretend
       // that it doesn't exist.
       rv = NS_ERROR_FACTORY_NOT_REGISTERED;
-    } else if (!path.EqualsLiteral("blank") &&
-               !path.EqualsLiteral("neterror") && !path.EqualsLiteral("home") &&
-               !path.EqualsLiteral("welcome") &&
-               !path.EqualsLiteral("newtab") &&
-               !path.EqualsLiteral("certerror")) {
+    } else if (!BinarySearchIf(
+                   kAboutPageEnterpriseWhitelist, 0,
+                   ArrayLength(kAboutPageEnterpriseWhitelist),
+                   [&path](const char* aOther) { return path.Compare(aOther); },
+                   &matchIdx)) {
       nsCOMPtr<nsIEnterprisePolicies> policyManager =
           do_GetService("@mozilla.org/enterprisepolicies;1", &rv2);
       if (NS_SUCCEEDED(rv2)) {
         nsAutoCString normalizedURL;
         normalizedURL.AssignLiteral("about:");
         normalizedURL.Append(path);
         rv2 = policyManager->IsAllowed(normalizedURL, &aboutPageAllowed);
         if (NS_FAILED(rv2)) {
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -851,20 +851,16 @@ MOZ_MUST_USE nsresult HttpAsyncAborter<T
   return AsyncCall(&T::HandleAsyncAbort);
 }
 
 // Each subclass needs to define its own version of this (which just calls this
 // base version), else we wind up casting base/derived member function ptrs
 template <class T>
 inline void HttpAsyncAborter<T>::HandleAsyncAbort() {
   MOZ_ASSERT(!mCallOnResume, "How did that happen?");
-  nsresult status = mThis->mStatus;
-  MOZ_LOG(gHttpLog, LogLevel::Debug,
-          ("HttpAsyncAborter::HandleAsyncAbort [this=%p status=%" PRIx32 "]\n",
-           mThis, static_cast<uint32_t>(status)));
 
   if (mThis->mSuspendCount) {
     MOZ_LOG(
         gHttpLog, LogLevel::Debug,
         ("Waiting until resume to do async notification [this=%p]\n", mThis));
     mCallOnResume = [](T* self) {
       self->HandleAsyncAbort();
       return NS_OK;
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -5239,54 +5239,16 @@ nsresult nsHttpChannel::ReadFromCache(bo
     //
     // TODO: This should be done asynchronously so we don't take the cache
     // service lock on the main thread.
     mCacheEntry->MaybeMarkValid();
   }
 
   nsresult rv;
 
-  // notify "http-on-may-change-process" observers
-  gHttpHandler->OnMayChangeProcess(this);
-
-  if (mRedirectContentProcessIdPromise) {
-    PushRedirectAsyncFunc(&nsHttpChannel::ContinueReadFromCache);
-    rv = StartCrossProcessRedirect();
-    if (NS_SUCCEEDED(rv)) {
-      return NS_OK;
-    }
-    PopRedirectAsyncFunc(&nsHttpChannel::ContinueReadFromCache);
-  }
-
-  return ContinueReadFromCache(NS_OK);
-}
-
-nsresult nsHttpChannel::ContinueReadFromCache(nsresult rv) {
-  LOG(("nsHttpChannel::ContinueReadFromCache [this=%p] spec: %s\n", this,
-       mSpec.get()));
-
-  // The channel may have been cancelled in the meantime, either by the
-  // consumer or the channel classifier. In that case, we need to AsyncAbort
-  // to ensure OnStart/StopRequest are called.
-  // This should only be an error code if the cross-process redirect failed,
-  // and OnRedirectVerifyCallback was called with an error code.
-  if (NS_FAILED(rv)) {
-    // rv can only be an error code if this was a failed cross-process redirect
-    // It shouldn't have happened during a revalidation.
-    MOZ_ASSERT(!mDidReval, "Should not be a 304 response");
-    // Also, this should not be possible.
-    MOZ_ASSERT(!mCachedContentIsPartial, "Unexpected partially cached page?");
-
-    MOZ_ASSERT(!mCachePump);
-
-    CloseCacheEntry(false);
-    DoAsyncAbort(NS_FAILED(mStatus) ? mStatus : rv);
-    return rv;
-  }
-
   // Keep the conditions below in sync with the conditions in
   // StartBufferingCachedEntity.
 
   if (WillRedirect(mResponseHead)) {
     // TODO: Bug 759040 - We should call HandleAsyncRedirect directly here,
     // to avoid event dispatching latency.
     MOZ_ASSERT(!mCacheInputStream);
     LOG(("Skipping skip read of cached redirect entity\n"));
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -404,17 +404,16 @@ class nsHttpChannel final : public HttpB
       nsICacheEntry* entry, bool aNew, nsIApplicationCache* aAppCache,
       nsresult status);
   MOZ_MUST_USE nsresult GenerateCacheKey(uint32_t postID, nsACString& key);
   MOZ_MUST_USE nsresult UpdateExpirationTime();
   MOZ_MUST_USE nsresult CheckPartial(nsICacheEntry* aEntry, int64_t* aSize,
                                      int64_t* aContentLength);
   bool ShouldUpdateOfflineCacheEntry();
   MOZ_MUST_USE nsresult ReadFromCache(bool alreadyMarkedValid);
-  MOZ_MUST_USE nsresult ContinueReadFromCache(nsresult rv);
   void CloseCacheEntry(bool doomOnFailure);
   void CloseOfflineCacheEntry();
   MOZ_MUST_USE nsresult InitCacheEntry();
   void UpdateInhibitPersistentCachingFlag();
   MOZ_MUST_USE nsresult InitOfflineCacheEntry();
   MOZ_MUST_USE nsresult AddCacheEntryHeaders(nsICacheEntry* entry);
   MOZ_MUST_USE nsresult FinalizeCacheEntry();
   MOZ_MUST_USE nsresult InstallCacheListener(int64_t offset = 0);
--- a/services/common/tests/unit/test_utils_makeURI.js
+++ b/services/common/tests/unit/test_utils_makeURI.js
@@ -32,17 +32,17 @@ function _test_makeURI() {
   let uris4 = "https://mozillalabs.com/multi/path";
   Assert.equal(CommonUtils.makeURI(uris4).spec, uris4);
   let uris5 = "https://mozillalabs.com/?query";
   Assert.equal(CommonUtils.makeURI(uris5).spec, uris5);
   let uris6 = "https://mozillalabs.com/#hash";
   Assert.equal(CommonUtils.makeURI(uris6).spec, uris6);
 
   _("Check chrome uris");
-  let uric1 = "chrome://browser/content/browser.xul";
+  let uric1 = "chrome://browser/content/browser.xhtml";
   Assert.equal(CommonUtils.makeURI(uric1).spec, uric1);
   let uric2 = "chrome://browser/skin/browser.css";
   Assert.equal(CommonUtils.makeURI(uric2).spec, uric2);
   let uric3 = "chrome://browser/locale/browser.dtd";
   Assert.equal(CommonUtils.makeURI(uric3).spec, uric3);
 
   _("Check about uris");
   let uria1 = "about:weave";
--- a/testing/talos/talos/tests/tart/addon/content/tab-min-width-1px.css
+++ b/testing/talos/talos/tests/tart/addon/content/tab-min-width-1px.css
@@ -1,11 +1,11 @@
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 
 /*
 Overlay this style rule at tart/chrome.manifest (but it seems to regress tab perf):
-style chrome://browser/content/browser.xul chrome://tart/content/tab-min-width-1px.css
+style chrome://browser/content/browser.xhtml chrome://tart/content/tab-min-width-1px.css
 */
 
 /* Prevent overflow while adding many tabs */
 .tabbrowser-tab[fadein]:not([pinned]) {
   min-width: 1px !important;
 }
--- a/testing/talos/talos/tests/tart/addon/content/tart.js
+++ b/testing/talos/talos/tests/tart/addon/content/tart.js
@@ -120,20 +120,20 @@ Tart.prototype = {
       win.gNavToolbox.removeEventListener("aftercustomization", handler);
     },
   },
 
   clickNewTab() {
     this._endDetection = this.tabDetector;
     this._win.BrowserOpenTab();
     // Modifying the style for each tab right after opening seems like it could regress performance,
-    // However, overlaying a global style over browser.xul actually ends up having greater ovrehead,
+    // However, overlaying a global style over browser.xhtml actually ends up having greater ovrehead,
     // especially while closing the last of many tabs (a noticeable ~250ms delay before expanding the rest).
     // To overlay the style globally, add at tart/chrome.manifest:
-    // style chrome://browser/content/browser.xul chrome://tart/content/tab-min-width-1px.css
+    // style chrome://browser/content/browser.xhtml chrome://tart/content/tab-min-width-1px.css
     // where the file tab-min-width-1px.css is:
     // .tabbrowser-tab[fadein]:not([pinned]) { min-width: 1px !important; }
     // Additionally, the global style overlay apparently messes with intervals recording when layout.frame_rate=10000:
     // Using the startFrameTimeRecording API, the first interval appears extra long (~1000ms) even with much widget tickling,
     // Per-tab min-width on open it is then.
 
     // --> many-tabs case which requires modified max-width will not go into v1. No need for now.
     // this._win.gBrowser.selectedTab.style.minWidth = "1px"; // Prevent overflow regrdless of DPI scale.
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b75a14aa8e510d95d350716353e2f121785a7d89
GIT binary patch
literal 294912
zc%1FkOKco>836DZ?|L0ObrglPZUshb6=+<HSnp%J7DCi<T^eef)Jf=5vUcsQ<l-ca
z*C8|kEf!#IZ~^rK6$dKd1eZ#jxI&Q-7ams*5eTUghaxqh5oPATaVKs;MO=#T@8_9s
zzWG1C`Ml%D=|>mWw>sr#E^MA_ZIx@$SE4wM9w?WiC>lu5;V4&1&*E+OarEv6qL2M)
zXtZ}TI&kIb=u3xszqtC!)$OaFy7I=Ar?33#KiCfd0000000000000000000000000
z0000000000@PB1vXlQJFJl_83R;#_yIoH{0J=of6?OqSeFE7lUSty^GJHEJ3-W@F;
zTVE@mT0ZgFx#cIyk1RY<KD%_{(X$KXlS}3KlS>aRo|r#VUS2r0I5)pARbJofoSW`n
zs*@i-P#T*bkE8YTYn?B4FK(oxE3Hdg7sCC@ZvB<%-E8=HsWdh=5kD0ctbV?=zIMLb
zJ+-<1h1OPQ=vH$lmL6Pqyc{O87V-t<W3A~*b@GA1P~)*sW24pXY~)KyduoKqchsm&
zK2$7?y?-KJ>9>8U{cLA-D_=6Wr^c=6f6>YG<b0ttcF*p2v)=7q>TKp~ihIiRXWvn!
zIX(G}Bpw=@n25hQ6JA+9oo54kUfb;j-u=bR9Y48zW~$t(q-XlxTGjNdWqBCLMy9i&
zW_H`mZkypYThgp&p^=3o3o}`0W??o9tt_<DFdIr$`Y}|jR731PrygP>#3aO-5St;+
zhS&<R9pY+etlwV0zmQk^d8k|sm8+q0HB_#K%GFT08Y<Vqu3Fet3%hDzS1s&H!fX;|
zlQ5fv*`z-kY9^uPOjz0M$M6Y;@3dO!=h@zB=(b)-RYS|S((qY_)wQs?7FO3Q{nh=2
z{gGOT^$;5&X3wsNr`E$$>*2jL!rn&M+o<$Mvc0RFMy+0JOy_AePj6dL&(lVpCV4uO
zr_Hz0B;S_g+md`+l5b0Pw<UQyN#0J9x0B@UBzZeY-cFLYljQBB>1>|1^0b|&t9iPX
zr=2`~=B+gRAoSCA-cCDfXRXnythK`@-mC=q=bOw<)&@#rpPu-4fBf>_(v|5vFQk8>
zi=%0Xdr{PTum4#900000000000000000000000000000000000008iw+WvBUxp?%@
zp(D}uvAr`#qp3qdlztsK^0s|PZ_WJo?(ScTar{#BWM#2(taR}HoriZ`AC2!Aj0=@}
zibuac`26wTe&)@m&VT*hAOGyvzx&os{E>eQ#Bs6wW)xq0;rAadeemaBJH7PBzufir
z=hp}B`q6i<jkNzf`tAE3e>p9C=k>i$i+80DOONdNah#5hWOKdiQSWW*0RR9100000
z00000000000000000000000000001BKNu<$hwo0WBk39UZbs<=000000000000000
z000000000000000000000002{QlStHkEGYQcQZ;40000000000000000000000000
z00000000000002kmkNbwcqF~Xy&F+_00000000000000000000000000000000000
z0002M{!=O(8Gb2xawJXT-m6i1000000000000000000000000000000000000002M
zzVN=n)bRDaL-A-9dOwWP0{{R300000000000000000000000000000000000{?|Pg
z4~|c5N6)po-OCp?*IxZWeE8X)Tzl~ozkKa`_kL$%ywa?EsC4lDoriZ`AC2!Aj0=@J
zi-(&RUpvs5{OcQ^{KLy<FIMmS>OdS956?AkJTm)A?KhwM>9vD5KJdcnk+gW+`&*PA
y0000000000000000000000000000000000000026uN*9l4?oxHb}wJpT>B^B%kLoo
--- a/toolkit/components/passwordmgr/test/unit/head.js
+++ b/toolkit/components/passwordmgr/test/unit/head.js
@@ -1,16 +1,17 @@
 /**
  * Provides infrastructure for automated login components tests.
  */
 
 "use strict";
 
 // Globals
 
+const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
 const {LoginRecipesContent, LoginRecipesParent} = ChromeUtils.import("resource://gre/modules/LoginRecipes.jsm");
 const {LoginHelper} = ChromeUtils.import("resource://gre/modules/LoginHelper.jsm");
 const {FileTestUtils} = ChromeUtils.import("resource://testing-common/FileTestUtils.jsm");
 const {LoginTestUtils} = ChromeUtils.import("resource://testing-common/LoginTestUtils.jsm");
 const {MockDocument} = ChromeUtils.import("resource://testing-common/MockDocument.jsm");
 
@@ -53,18 +54,20 @@ const RecipeHelpers = {
 };
 
 // Initialization functions common to all tests
 
 add_task(async function test_common_initialize() {
   // Before initializing the service for the first time, we should copy the key
   // file required to decrypt the logins contained in the SQLite databases used
   // by migration tests.  This file is not required for the other tests.
-  await OS.File.copy(do_get_file("data/key3.db").path,
-                     OS.Path.join(OS.Constants.Path.profileDir, "key3.db"));
+  const isAndroid = AppConstants.platform == "android";
+  const keyDBName = isAndroid ? "key4.db" : "key3.db";
+  await OS.File.copy(do_get_file(`data/${keyDBName}`).path,
+                     OS.Path.join(OS.Constants.Path.profileDir, keyDBName));
 
   // Ensure that the service and the storage module are initialized.
   await Services.logins.initializationPromise;
 
   // Ensure that every test file starts with an empty database.
   LoginTestUtils.clearData();
 
   // Clean up after every test.
--- a/toolkit/components/passwordmgr/test/unit/test_storage_mozStorage.js
+++ b/toolkit/components/passwordmgr/test/unit/test_storage_mozStorage.js
@@ -430,16 +430,23 @@ add_task(async function test_execute() {
     Assert.equal(CURRENT_SCHEMA, dbConnection.schemaVersion);
 
     // moz_disabledHosts should now be empty after migration.
     LoginTestUtils.assertDisabledHostsEqual([], getAllDisabledHostsFromMozStorage(dbConnection));
 
     // Get all the other hosts currently saved in the permission manager.
     let hostsInPermissionManager = getAllDisabledHostsFromPermissionManager();
 
+    // Converted to punycode
+    disabledHosts = [
+      "http://disabled1.example.com",
+      "http://xn--pss.net",
+      "http://xn--19g.com",
+    ];
+
     // All disabledHosts should have migrated to the permission manager
     LoginTestUtils.assertDisabledHostsEqual(disabledHosts, hostsInPermissionManager);
 
     // Remove all disabled hosts from the permission manager before test ends
     for (let host of disabledHosts) {
       setLoginSavingEnabled(host, true);
     }
 
--- a/toolkit/components/passwordmgr/test/unit/xpcshell.ini
+++ b/toolkit/components/passwordmgr/test/unit/xpcshell.ini
@@ -5,17 +5,17 @@ support-files = data/**
 # Test JSON file access and import from SQLite, not applicable to Android.
 [test_module_LoginImport.js]
 skip-if = os == "android"
 [test_module_LoginStore.js]
 skip-if = os == "android"
 
 # Test SQLite database backup and migration, applicable to Android only.
 [test_storage_mozStorage.js]
-skip-if = true || os != "android" # Bug 1171687: Needs fixing on Android
+skip-if = os != "android"
 
 # The following tests apply to any storage back-end.
 [test_context_menu.js]
 skip-if = os == "android" # The context menu isn't used on Android.
 # LoginManagerContextMenu is only included for MOZ_BUILD_APP == 'browser'.
 run-if = buildapp == "browser"
 [test_dedupeLogins.js]
 [test_disabled_hosts.js]
--- a/toolkit/components/places/tests/history/test_async_history_api.js
+++ b/toolkit/components/places/tests/history/test_async_history_api.js
@@ -338,17 +338,17 @@ add_task(async function test_non_addable
   // Array of protocols that nsINavHistoryService::canAddURI returns false for.
   const URLS = [
     "about:config",
     "imap://cyrus.andrew.cmu.edu/archive.imap",
     "news://new.mozilla.org/mozilla.dev.apps.firefox",
     "mailbox:Inbox",
     "moz-anno:favicon:http://mozilla.org/made-up-favicon",
     "view-source:http://mozilla.org",
-    "chrome://browser/content/browser.xul",
+    "chrome://browser/content/browser.xhtml",
     "resource://gre-resources/hiddenWindow.html",
     "data:,Hello%2C%20World!",
     "javascript:alert('hello wolrd!');",
     "blob:foo",
   ];
   let places = [];
   URLS.forEach(function(url) {
     try {
--- a/toolkit/components/places/tests/history/test_insertMany.js
+++ b/toolkit/components/places/tests/history/test_insertMany.js
@@ -26,17 +26,17 @@ add_task(async function test_error_cases
   Assert.throws(
     () => PlacesUtils.history.insertMany([validPageInfo, {}]),
     /Error: PageInfo: The following properties were expected/,
     "passing a second invalid PageInfo object to History.insertMany should throw an Error"
   );
 });
 
 add_task(async function test_insertMany() {
-  const BAD_URLS = ["about:config", "chrome://browser/content/browser.xul"];
+  const BAD_URLS = ["about:config", "chrome://browser/content/browser.xhtml"];
   const GOOD_URLS = [1, 2, 3].map(x => { return `http://mozilla.com/${x}`; });
 
   let makePageInfos = async function(urls, filter = x => x) {
     let pageInfos = [];
     for (let url of urls) {
       let uri = NetUtil.newURI(url);
 
       let pageInfo = {
--- a/toolkit/components/places/tests/unit/test_isURIVisited.js
+++ b/toolkit/components/places/tests/unit/test_isURIVisited.js
@@ -11,17 +11,17 @@ const SCHEMES = {
   "about:": false,
 // nsIIOService.newURI() can throw if e.g. the app knows about imap://
 // but the account is not set up and so the URL is invalid for it.
 //  "imap://": false,
   "news://": false,
   "mailbox:": false,
   "moz-anno:favicon:http://": false,
   "view-source:http://": false,
-  "chrome://browser/content/browser.xul?": false,
+  "chrome://browser/content/browser.xhtml?": false,
   "resource://": false,
   "data:,": false,
   "javascript:": false,
 };
 
 add_task(async function test_isURIVisited() {
   let history = Cc["@mozilla.org/browser/history;1"]
                   .getService(Ci.mozIAsyncHistory);
--- a/toolkit/components/places/tests/unit/test_isvisited.js
+++ b/toolkit/components/places/tests/unit/test_isvisited.js
@@ -34,17 +34,17 @@ add_task(async function test_execute() {
   // see CanAddURI() in nsNavHistory.cpp
   const URLS = [
     "about:config",
     "imap://cyrus.andrew.cmu.edu/archive.imap",
     "news://new.mozilla.org/mozilla.dev.apps.firefox",
     "mailbox:Inbox",
     "moz-anno:favicon:http://mozilla.org/made-up-favicon",
     "view-source:http://mozilla.org",
-    "chrome://browser/content/browser.xul",
+    "chrome://browser/content/browser.xhtml",
     "resource://gre-resources/hiddenWindow.html",
     "data:,Hello%2C%20World!",
     "javascript:alert('hello wolrd!');",
     "http://localhost/" + "a".repeat(1984),
   ];
   for (let currentURL of URLS) {
     try {
       var cantAddUri = uri(currentURL);
--- a/toolkit/components/xulstore/tests/xpcshell/test_XULStore.js
+++ b/toolkit/components/xulstore/tests/xpcshell/test_XULStore.js
@@ -2,17 +2,17 @@
    http://creativecommons.org/publicdomain/zero/1.0/◦
 */
 
 "use strict";
 
 const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 var XULStore = null;
-var browserURI = "chrome://browser/content/browser.xul";
+var browserURI = "chrome://browser/content/browser.xhtml";
 var aboutURI = "about:config";
 
 function run_test() {
   do_get_profile();
   run_next_test();
 }
 
 function checkValue(uri, id, attr, reference) {
--- a/toolkit/content/tests/chrome/window_browser_drop.xul
+++ b/toolkit/content/tests/chrome/window_browser_drop.xul
@@ -191,17 +191,17 @@ async function dropLinksOnBrowser(browse
                           data: "data:text/html,bad" } ] ],
                     "text/plain data url drop on browser " + type);
 
   // Dropping a chrome url should fail as we don't have a source node set,
   // defaulting to a source of file:///
   await expectLink(browser,
                     [],
                     [ [ { type: "text/x-moz-url",
-                          data: "chrome://browser/content/browser.xul" } ] ],
+                          data: "chrome://browser/content/browser.xhtml" } ] ],
                     "text/x-moz-url chrome url drop on browser " + type);
 
   if (browser.type == "content") {
     await ContentTask.spawn(browser, null, function() {
       content.window.stopMode = true;
     });
 
     // stopPropagation should not prevent the browser link handling from occuring
--- a/toolkit/content/tests/unit/test_contentAreaUtils.js
+++ b/toolkit/content/tests/unit/test_contentAreaUtils.js
@@ -9,17 +9,17 @@ function loadUtilsScript() {
   /* import-globals-from ../../contentAreaUtils.js */
   Services.scriptloader.loadSubScript("chrome://global/content/contentAreaUtils.js");
 }
 
 function test_urlSecurityCheck() {
   var nullPrincipal = Services.scriptSecurityManager.createNullPrincipal({});
 
   const HTTP_URI = "http://www.mozilla.org/";
-  const CHROME_URI = "chrome://browser/content/browser.xul";
+  const CHROME_URI = "chrome://browser/content/browser.xhtml";
   const DISALLOW_INHERIT_PRINCIPAL =
     Ci.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL;
 
   try {
     urlSecurityCheck(makeURI(HTTP_URI), nullPrincipal,
                      DISALLOW_INHERIT_PRINCIPAL);
   } catch (ex) {
     do_throw("urlSecurityCheck should not throw when linking to a http uri with a null principal");
--- a/toolkit/mozapps/extensions/test/mochitest/test_default_theme.html
+++ b/toolkit/mozapps/extensions/test/mochitest/test_default_theme.html
@@ -8,21 +8,26 @@
   <link rel="stylesheet" href="chrome://mochikit/contents/tests/SimpleTest/test.css">
 </head>
 <body>
 
 <script>
 "use strict";
 
 const {AddonManager} = ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
+const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 
 add_task(async function() {
   let addon = await AddonManager.getAddonByID("default-theme@mozilla.org");
 
+  // Dev edition uses a different default theme on desktop.
+  const expectActive = (!AppConstants.MOZ_DEV_EDITION ||
+                        AppConstants.MOZ_BUILD_APP !== "browser");
+
   ok(addon != null, "Default theme exists");
   is(addon.type, "theme", "Add-on type is correct");
-  is(addon.isActive, true, "Add-on is active");
+  is(addon.isActive, expectActive, "Add-on is active?");
   is(addon.hidden, false, "Add-on is not hidden");
 });
 
 </script>
 </body>
 </html>
--- a/toolkit/mozapps/extensions/test/xpcshell/test_json_updatecheck.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_json_updatecheck.js
@@ -252,17 +252,17 @@ add_task(async function test_update_url_
   // Checks that update links to privileged URLs are not accepted.
 
   let { messages, result: updates } = await promiseConsoleOutput(() => {
     return checkUpdates({
       id: "updatecheck-security@tests.mozilla.org",
       version: "0.1",
       updates: [
         { version: "0.2",
-          update_link: "chrome://browser/content/browser.xul",
+          update_link: "chrome://browser/content/browser.xhtml",
           update_hash: "sha256:08ac852190ecd81f40a514ea9299fe9143d9ab5e296b97e73fb2a314de49648a" },
         { version: "0.3",
           update_link: "http://example.com/update.xpi",
           update_hash: "sha256:18ac852190ecd81f40a514ea9299fe9143d9ab5e296b97e73fb2a314de49648a" },
       ],
     });
   });
 
--- a/tools/lint/docs/linters/eslint-plugin-mozilla.rst
+++ b/tools/lint/docs/linters/eslint-plugin-mozilla.rst
@@ -13,17 +13,17 @@ e.g.
    /* eslint-env mozilla/chrome-worker */
 
 There are also built-in ESLint environments available as well:
 http://eslint.org/docs/user-guide/configuring#specifying-environments
 
 browser-window
 --------------
 
-Defines the environment for scripts that are in the main browser.xul scope.
+Defines the environment for scripts that are in the main browser.xhtml scope.
 
 chrome-worker
 -------------
 
 Defines the environment for chrome workers. This differs from normal workers by
 the fact that `ctypes` can be accessed as well.
 
 frame-script
--- a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/browser-window.js
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/browser-window.js
@@ -1,10 +1,10 @@
 /**
- * @fileoverview Defines the environment when in the browser.xul window.
+ * @fileoverview Defines the environment when in the browser.xhtml window.
  *               Imports many globals from various files.
  *
  * 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";
@@ -18,17 +18,17 @@ var path = require("path");
 var helpers = require("../helpers");
 var globals = require("../globals");
 
 const rootDir = helpers.rootDir;
 
 // When updating EXTRA_SCRIPTS or MAPPINGS, be sure to also update the
 // 'support-files' config in `tools/lint/eslint.yml`.
 
-// These are scripts not loaded from browser.xul or global-scripts.inc
+// These are scripts not loaded from browser.xhtml or global-scripts.inc
 // but via other includes.
 const EXTRA_SCRIPTS = [
   "browser/base/content/nsContextMenu.js",
   "browser/components/places/content/editBookmark.js",
   "browser/components/downloads/content/downloads.js",
   "browser/components/downloads/content/indicator.js",
   "toolkit/content/customElements.js",
   "toolkit/content/editMenuOverlay.js",
--- a/tools/lint/eslint/eslint-plugin-mozilla/lib/helpers.js
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/helpers.js
@@ -730,17 +730,17 @@ module.exports = {
    * These characters need to be removed.
    */
   cleanUpPath(pathName) {
     return pathName.replace(/^"/, "").replace(/"$/, "");
   },
 
   get globalScriptPaths() {
     return [
-      path.join(this.rootDir, "browser", "base", "content", "browser.xul"),
+      path.join(this.rootDir, "browser", "base", "content", "browser.xhtml"),
       path.join(this.rootDir, "browser", "base", "content", "global-scripts.inc"),
     ];
   },
 
   isMozillaCentralBased() {
     return fs.existsSync(this.globalScriptPaths[0]);
   },
 
--- a/tools/lint/eslint/eslint-plugin-mozilla/lib/processors/xul.js
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/processors/xul.js
@@ -33,17 +33,16 @@ const kIfdefStateForLinting = {
   MOZ_SERVICES_SYNC: true,
   MOZ_DATA_REPORTING: true,
   MOZ_TELEMETRY_REPORTING: true,
   MOZ_CRASHREPORTER: true,
   MOZ_MAINTENANCE_SERVICE: true,
   HAVE_SHELL_SERVICE: true,
   MENUBAR_CAN_AUTOHIDE: true,
   MOZILLA_OFFICIAL: true,
-  BROWSER_XHTML: false, // other code can lint browser.xhtml, we hope.
 };
 
 // Anything not in the above list is assumed false.
 function dealWithIfdefs(text, filename) {
   function stripIfdefsFromLines(input, innerFile) {
     let outputLines = [];
     let inSkippingIfdef = [false];
     for (let i = 0; i < input.length; i++) {
--- a/widget/nsBaseDragService.cpp
+++ b/widget/nsBaseDragService.cpp
@@ -271,16 +271,17 @@ nsBaseDragService::InvokeDragSessionWith
   NS_ENSURE_TRUE(mSuppressLevel == 0, NS_ERROR_FAILURE);
 
   mDataTransfer = aDataTransfer;
   mSelection = nullptr;
   mHasImage = true;
   mDragPopup = nullptr;
   mImage = aImage;
   mImageOffset = CSSIntPoint(aImageX, aImageY);
+  mDragStartData = nullptr;
 
   mScreenPosition.x = aDragEvent->ScreenX(CallerType::System);
   mScreenPosition.y = aDragEvent->ScreenY(CallerType::System);
   mInputSource = aDragEvent->MozInputSource();
 
   // If dragging within a XUL tree and no custom drag image was
   // set, the region argument to InvokeDragSessionWithImage needs
   // to be set to the area encompassing the selected rows of the
@@ -303,32 +304,61 @@ nsBaseDragService::InvokeDragSessionWith
   nsresult rv =
       InvokeDragSession(aDOMNode, aPrincipal, aTransferableArray, aActionType,
                         nsIContentPolicy::TYPE_INTERNAL_IMAGE);
   mRegion = Nothing();
   return rv;
 }
 
 NS_IMETHODIMP
+nsBaseDragService::InvokeDragSessionWithRemoteImage(
+    nsINode* aDOMNode, nsIPrincipal* aPrincipal, nsIArray* aTransferableArray,
+    uint32_t aActionType, RemoteDragStartData* aDragStartData,
+    DragEvent* aDragEvent, DataTransfer* aDataTransfer) {
+  NS_ENSURE_TRUE(aDragEvent, NS_ERROR_NULL_POINTER);
+  NS_ENSURE_TRUE(aDataTransfer, NS_ERROR_NULL_POINTER);
+  NS_ENSURE_TRUE(mSuppressLevel == 0, NS_ERROR_FAILURE);
+
+  mDataTransfer = aDataTransfer;
+  mSelection = nullptr;
+  mHasImage = true;
+  mDragPopup = nullptr;
+  mImage = nullptr;
+  mDragStartData = aDragStartData;
+  mImageOffset = CSSIntPoint(0, 0);
+
+  mScreenPosition.x = aDragEvent->ScreenX(CallerType::System);
+  mScreenPosition.y = aDragEvent->ScreenY(CallerType::System);
+  mInputSource = aDragEvent->MozInputSource();
+
+  nsresult rv =
+      InvokeDragSession(aDOMNode, aPrincipal, aTransferableArray, aActionType,
+                        nsIContentPolicy::TYPE_INTERNAL_IMAGE);
+  mRegion = Nothing();
+  return rv;
+}
+
+NS_IMETHODIMP
 nsBaseDragService::InvokeDragSessionWithSelection(Selection* aSelection,
                                                   nsIPrincipal* aPrincipal,
                                                   nsIArray* aTransferableArray,
                                                   uint32_t aActionType,
                                                   DragEvent* aDragEvent,
                                                   DataTransfer* aDataTransfer) {
   NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
   NS_ENSURE_TRUE(aDragEvent, NS_ERROR_NULL_POINTER);
   NS_ENSURE_TRUE(mSuppressLevel == 0, NS_ERROR_FAILURE);
 
   mDataTransfer = aDataTransfer;
   mSelection = aSelection;
   mHasImage = true;
   mDragPopup = nullptr;
   mImage = nullptr;
   mImageOffset = CSSIntPoint();
+  mDragStartData = nullptr;
   mRegion = Nothing();
 
   mScreenPosition.x = aDragEvent->ScreenX(CallerType::System);
   mScreenPosition.y = aDragEvent->ScreenY(CallerType::System);
   mInputSource = aDragEvent->MozInputSource();
 
   // just get the focused node from the selection
   // XXXndeakin this should actually be the deepest node that contains both
@@ -432,16 +462,17 @@ nsBaseDragService::EndDragSession(bool a
   mSourceDocument = nullptr;
   mSourceNode = nullptr;
   mTriggeringPrincipal = nullptr;
   mSelection = nullptr;
   mDataTransfer = nullptr;
   mHasImage = false;
   mUserCancelled = false;
   mDragPopup = nullptr;
+  mDragStartData = nullptr;
   mImage = nullptr;
   mImageOffset = CSSIntPoint();
   mScreenPosition = CSSIntPoint();
   mEndDragPoint = LayoutDeviceIntPoint(0, 0);
   mInputSource = MouseEvent_Binding::MOZ_SOURCE_MOUSE;
   mRegion = Nothing();
 
   return NS_OK;
@@ -557,29 +588,22 @@ nsresult nsBaseDragService::DrawDrag(nsI
     presShell = GetPresShellForContent(aDOMNode);
   }
   if (!presShell) {
     return NS_ERROR_FAILURE;
   }
 
   *aPresContext = presShell->GetPresContext();
 
-  RefPtr<nsFrameLoaderOwner> flo = do_QueryObject(dragNode);
-  if (flo) {
-    RefPtr<nsFrameLoader> fl = flo->GetFrameLoader();
-    if (fl) {
-      auto* bp = fl->GetBrowserParent();
-      if (bp && bp->TakeDragVisualization(*aSurface, aScreenDragRect)) {
-        if (mImage) {
-          // Just clear the surface if chrome has overridden it with an image.
-          *aSurface = nullptr;
-        }
-
-        return NS_OK;
-      }
+  if (mDragStartData) {
+    if (mImage) {
+      // Just clear the surface if chrome has overridden it with an image.
+      *aSurface = nullptr;
+    } else {
+      *aSurface = mDragStartData->TakeVisualization(aScreenDragRect);
     }
   }
 
   // convert mouse position to dev pixels of the prescontext
   CSSIntPoint screenPosition(aScreenPosition);
   screenPosition.x -= mImageOffset.x;
   screenPosition.y -= mImageOffset.y;
   LayoutDeviceIntPoint screenPoint =
--- a/widget/nsBaseDragService.h
+++ b/widget/nsBaseDragService.h
@@ -11,16 +11,17 @@
 #include "nsITransferable.h"
 #include "nsCOMPtr.h"
 #include "nsRect.h"
 #include "nsPoint.h"
 #include "nsString.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/HTMLCanvasElement.h"
+#include "mozilla/dom/RemoteDragStartData.h"
 #include "nsTArray.h"
 #include "nsRegion.h"
 #include "Units.h"
 
 // translucency level for drag images
 #define DRAG_TRANSLUCENCY 0.65
 
 class nsIContent;
@@ -174,16 +175,19 @@ class nsBaseDragService : public nsIDrag
   // used to determine the image to appear on the cursor while dragging
   nsCOMPtr<nsINode> mImage;
   // offset of cursor within the image
   mozilla::CSSIntPoint mImageOffset;
 
   // set if a selection is being dragged
   RefPtr<mozilla::dom::Selection> mSelection;
 
+  // remote drag data
+  RefPtr<mozilla::dom::RemoteDragStartData> mDragStartData;
+
   // set if the image in mImage is a popup. If this case, the popup will be
   // opened and moved instead of using a drag image.
   nsCOMPtr<nsIContent> mDragPopup;
 
   // the screen position where drag gesture occurred, used for positioning the
   // drag image.
   mozilla::CSSIntPoint mScreenPosition;
 
--- a/widget/nsIDragService.idl
+++ b/widget/nsIDragService.idl
@@ -15,22 +15,24 @@ webidl Selection;
 
 %{C++
 #include "mozilla/EventForwards.h"
 
 namespace mozilla {
 namespace dom {
 class ContentParent;
 class DataTransfer;
+class RemoteDragStartData;
 } // namespace dom
 } // namespace mozilla
 %}
 
 [ptr] native ContentParentPtr(mozilla::dom::ContentParent);
 [ptr] native DataTransferPtr(mozilla::dom::DataTransfer);
+[ptr] native RemoteDragStartDataPtr(mozilla::dom::RemoteDragStartData);
 native EventMessage(mozilla::EventMessage);
 
 [scriptable, uuid(ebd6b3a2-af16-43af-a698-3091a087dd62), builtinclass]
 interface nsIDragService : nsISupports
 {
   const long DRAGDROP_ACTION_NONE = 0;
   const long DRAGDROP_ACTION_COPY = 1;
   const long DRAGDROP_ACTION_MOVE = 2;
@@ -90,16 +92,28 @@ interface nsIDragService : nsISupports
                                   in nsIArray aTransferableArray,
                                   in unsigned long aActionType,
                                   in Node aImage,
                                   in long aImageX,
                                   in long aImageY,
                                   in DragEvent aDragEvent,
                                   in DataTransferPtr aDataTransfer);
 
+  /** Start a drag session with the data in aDragStartData from a child process.
+   *  Other arguments are the same as invokeDragSessionWithImage.
+   */
+  [noscript, can_run_script]
+  void invokeDragSessionWithRemoteImage(in Node aDOMNode,
+                                        in nsIPrincipal aPrincipal,
+                                        in nsIArray aTransferableArray,
+                                        in unsigned long aActionType,
+                                        in RemoteDragStartDataPtr aDragStartData,
+                                        in DragEvent aDragEvent,
+                                        in DataTransferPtr aDataTransfer);
+
   /**
    * Start a modal drag session using the selection as the drag image.
    * The aDragEvent must be supplied as the current screen coordinates of the
    * event are needed to calculate the image location.
    *
    * Note: This method is deprecated for non-native code.
    */
   [can_run_script]