Bug 1362774 - insert initial browser dynamically to be able to set nodefaultsrc on it, r?dao draft
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Wed, 11 Jul 2018 21:04:58 +0100
changeset 821973 29bdcc8f7ed3e301094dd0ec51491255fbb17664
parent 821972 eb42d0318a35ed63442c7b18c74033a486f0b71b
child 821974 f9b49f77e60f6f8b3ed97448d4d31a3b13a3a7d3
push id117240
push userbmo:gijskruitbosch+bugs@gmail.com
push dateTue, 24 Jul 2018 13:13:26 +0000
reviewersdao
bugs1362774
milestone63.0a1
Bug 1362774 - insert initial browser dynamically to be able to set nodefaultsrc on it, r?dao MozReview-Commit-ID: HGZXQWmc2LT
browser/base/content/browser.js
browser/base/content/browser.xul
browser/base/content/tabbrowser.js
browser/base/content/test/general/browser_newWindowDrop.js
browser/components/resistfingerprinting/test/browser/browser_roundedWindow_newWindow.js
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1273,17 +1273,18 @@ var gBrowserInit = {
         remoteType = linkedBrowser.remoteType;
         isRemote = remoteType != E10SUtils.NOT_REMOTE;
         sameProcessAsFrameLoader = linkedBrowser.frameLoader;
       }
       initBrowser.removeAttribute("blank");
     }
 
     gBrowser.updateBrowserRemoteness(initBrowser, isRemote, {
-      remoteType, sameProcessAsFrameLoader
+      remoteType, sameProcessAsFrameLoader,
+      keepNoDefaultSrcInInitialBrowser: true,
     });
 
     BrowserSearch.initPlaceHolder();
 
     // Hack to ensure that the about:home favicon is loaded
     // instantaneously, to avoid flickering and improve perceived performance.
     this._callWithURIToLoad(uriToLoad => {
       if (uriToLoad == "about:home" || uriToLoad == "about:newtab" || uriToLoad == "about:welcome") {
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -615,16 +615,26 @@
       <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" layer="true">
+      <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"/>
 
 <vbox id="titlebar">
   <hbox id="titlebar-content">
     <spacer id="titlebar-spacer" flex="1"/>
     <hbox id="titlebar-buttonbox-container">
       <hbox id="titlebar-buttonbox" class="titlebar-color">
@@ -1240,45 +1250,16 @@
       <splitter id="sidebar-splitter" class="chromeclass-extrachrome sidebar-splitter" hidden="true"/>
       <vbox id="appcontent" flex="1">
         <notificationbox id="high-priority-global-notificationbox" notificationside="top"/>
         <tabbox id="tabbrowser-tabbox"
                 flex="1" eventnode="document" tabcontainer="tabbrowser-tabs">
           <tabpanels id="tabbrowser-tabpanels"
                      flex="1" class="plain" selectedIndex="0"
                      onselect="if (event.target == this) gBrowser.updateCurrentBrowser();">
-            <notificationbox flex="1" notificationside="top">
-              <!-- Set large flex to allow the devtools toolbox to set a flex attribute.
-                   We don't want the toolbox to actually take up free space, but we do want it to collapse when the window shrinks, and with flex=0 it can't.
-                   When the toolbox is on the bottom it's a sibling of browserSidebarContainer,
-                   and when it's on the side it's a sibling of browserContainer.  -->
-              <hbox flex="10000" class="browserSidebarContainer">
-                <vbox flex="10000" class="browserContainer">
-                  <stack flex="1" class="browserStack">
-                    <browser id="tabbrowser-initialBrowser" type="content"
-                             message="true" messagemanagergroup="browsers"
-                             primary="true" blank="true"
-                             tooltip="aHTMLTooltip"
-                             contextmenu="contentAreaContextMenu"
-                             autocompletepopup="PopupAutoComplete"
-                             selectmenulist="ContentSelectDropdown"
-                             datetimepicker="DateTimePickerPanel"/>
-                  </stack>
-                  <hbox id="statuspanel" inactive="true" layer="true">
-                    <hbox id="statuspanel-inner">
-                      <label id="statuspanel-label"
-                             role="status"
-                             aria-live="off"
-                             flex="1"
-                             crop="end"/>
-                    </hbox>
-                  </hbox>
-                </vbox>
-              </hbox>
-            </notificationbox>
           </tabpanels>
         </tabbox>
       </vbox>
       <vbox id="browser-border-end" hidden="true" layer="true"/>
     </hbox>
 #include ../../components/customizableui/content/customizeMode.inc.xul
   </deck>
 
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -269,59 +269,72 @@ window._gBrowser = {
   get selectedTab() {
     return this._selectedTab;
   },
 
   get selectedBrowser() {
     return this._selectedBrowser;
   },
 
-  get initialBrowser() {
-    delete this.initialBrowser;
-    return this.initialBrowser = document.getElementById("tabbrowser-initialBrowser");
-  },
-
   _setupInitialBrowserAndTab() {
-    let browser = this.initialBrowser;
+    // Determine the first URL we load. We can't use gBrowserInit's
+    // _uriToLoadPromise because it's null even if we know session restore is
+    // active, in which case we shouldn't bother loading about:blank.
+    const firstURL = window.arguments && window.arguments[0];
+    // accessibility tests send firstURL with value null, several mochitests
+    // submit "" firstURL, so just check for false-y or explicit about:blank.
+    let uriIsAboutBlank = !firstURL || firstURL == "about:blank";
+
+    // Note that this URL could be the homepage and non-about:blank,
+    // and yet we could then load about:blank in it through session
+    // restore. That is OK - we'll just load it slightly later.
+    // Alternatively, it could be that the homepage is set to about:blank,
+    // that's what we get here, and session restore is enabled, in which
+    // case we may later load something other than the initial about:blank
+    // anyway. Try to avoid loading about:blank then:
+    if (uriIsAboutBlank) {
+      const {willOverrideHomepage} = SessionStartup;
+      // If this is a bool and true, we know we'll override about:blank,
+      // so set uriIsAboutBlank to false so we set nodefaultsrc=true.
+      // Note that willOverrideHomepage could be a promise, in which case
+      // we will load about:blank to be safe.
+      uriIsAboutBlank =
+        !(typeof willOverrideHomepage == "boolean" && willOverrideHomepage);
+    }
+
+    let browser = this._createBrowser({uriIsAboutBlank});
+    browser.id = "tabbrowser-initialBrowser";
+    browser.setAttribute("primary", "true");
+    browser.setAttribute("blank", "true");
+    browser.droppedLinkHandler = handleDroppedLink;
+
+    let notificationbox = this.getNotificationBox(browser);
+    this.tabpanels.appendChild(notificationbox);
+    this.initialBrowser = browser;
     this._selectedBrowser = browser;
 
-    browser.permanentKey = {};
-    browser.droppedLinkHandler = handleDroppedLink;
-
     let autoScrollPopup = browser._createAutoScrollPopup();
     autoScrollPopup.id = "autoscroller";
     document.getElementById("mainPopupSet").appendChild(autoScrollPopup);
     browser.setAttribute("autoscrollpopup", autoScrollPopup.id);
 
-    this._defaultBrowserAttributes = {
-      autoscrollpopup: "",
-      contextmenu: "",
-      datetimepicker: "",
-      message: "",
-      messagemanagergroup: "",
-      selectmenulist: "",
-      tooltip: "",
-      type: "",
-    };
-    for (let attribute in this._defaultBrowserAttributes) {
-      this._defaultBrowserAttributes[attribute] = browser.getAttribute(attribute);
-    }
-
     let tab = this.tabs[0];
     this._selectedTab = tab;
 
     let uniqueId = this._generateUniquePanelID();
-    this.tabpanels.childNodes[0].id = uniqueId;
+    notificationbox.id = uniqueId;
     tab.linkedPanel = uniqueId;
     tab.permanentKey = browser.permanentKey;
     tab._tPos = 0;
     tab._fullyOpen = true;
     tab.linkedBrowser = browser;
     this._tabForBrowser.set(browser, tab);
 
+    this._appendStatusPanel();
+
     // Hook the browser up with a progress listener.
     let tabListener = new TabProgressListener(tab, browser, true, false);
     let filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
                   .createInstance(Ci.nsIWebProgress);
     filter.addProgressListener(tabListener, Ci.nsIWebProgress.NOTIFY_ALL);
     this._tabListeners.set(tab, tabListener);
     this._tabFilters.set(tab, filter);
     browser.webProgress.addProgressListener(filter, Ci.nsIWebProgress.NOTIFY_ALL);
@@ -1538,16 +1551,24 @@ window._gBrowser = {
       if (aShouldBeRemote) {
         throw new Error("Cannot set an opener on a browser which should be remote!");
       }
       if (!isRemote && aBrowser.contentWindow.opener != aOptions.opener) {
         throw new Error("Cannot change opener on an already non-remote browser!");
       }
     }
 
+    // We're removing the nodefaultsrc because extensions
+    // which are started in a different process expect the
+    // nodefaultsrc to not be set. See bug 1397365 for details.
+    if (!aOptions.keepNoDefaultSrcInInitialBrowser &&
+        aBrowser.id == "tabbrowser-initialBrowser") {
+      aBrowser.removeAttribute("nodefaultsrc");
+    }
+
     // Abort if we're not going to change anything
     let currentRemoteType = aBrowser.getAttribute("remoteType");
     if (isRemote == aShouldBeRemote && !aOptions.newFrameloader &&
         (!isRemote || currentRemoteType == aOptions.remoteType)) {
       return false;
     }
 
     let tab = this.getTabForBrowser(aBrowser);
@@ -1783,18 +1804,27 @@ window._gBrowser = {
   _createBrowser(aParams) {
     // Supported parameters:
     // userContextId, remote, remoteType, isPreloadBrowser,
     // uriIsAboutBlank, sameProcessAsFrameLoader
 
     let b = document.createElementNS(this._XUL_NS, "browser");
     b.permanentKey = {};
 
-    for (let attribute in this._defaultBrowserAttributes) {
-      b.setAttribute(attribute, this._defaultBrowserAttributes[attribute]);
+    const defaultBrowserAttributes = {
+      contextmenu: "contentAreaContextMenu",
+      datetimepicker: "DateTimePickerPanel",
+      message: "true",
+      messagemanagergroup: "browsers",
+      selectmenulist: "ContentSelectDropdown",
+      tooltip: "aHTMLTooltip",
+      type: "content",
+    };
+    for (let attribute in defaultBrowserAttributes) {
+      b.setAttribute(attribute, defaultBrowserAttributes[attribute]);
     }
 
     if (aParams.userContextId) {
       b.setAttribute("usercontextid", aParams.userContextId);
     }
 
     // remote parameter used by some addons, use default in this case.
     if (aParams.remote && !aParams.remoteType) {
@@ -1811,16 +1841,20 @@ window._gBrowser = {
         throw new Error("Cannot set opener window on a remote browser!");
       }
       b.presetOpenerWindow(aParams.openerWindow);
     }
 
     if (!aParams.isPreloadBrowser) {
       b.setAttribute("autocompletepopup", "PopupAutoComplete");
     }
+    if (this._autoscrollPopup) {
+      b.setAttribute("autoscrollpopup", this._autoScrollPopup.id);
+    }
+
 
     /*
      * This attribute is meant to describe if the browser is the
      * preloaded browser. There are 2 defined states: "preloaded" or
      * "consumed". The order of events goes as follows:
      *   1. The preloaded browser is created and the 'preloadedState'
      *      attribute for that browser is set to "preloaded".
      *   2. When a new tab is opened and it is time to show that
@@ -1857,23 +1891,27 @@ window._gBrowser = {
     }
 
     // Create the browserStack container
     let stack = document.createElementNS(this._XUL_NS, "stack");
     stack.className = "browserStack";
     stack.appendChild(b);
     stack.setAttribute("flex", "1");
 
-    // Create the browserContainer
+    // We set large flex on both containers to allow the devtools toolbox to
+    // set a flex attribute. We don't want the toolbox to actually take up free
+    // space, but we do want it to collapse when the window shrinks, and with
+    // flex=0 it can't. When the toolbox is on the bottom it's a sibling of
+    // browserSidebarContainer, and when it's on the side it's a sibling of
+    // browserContainer.
     let browserContainer = document.createElementNS(this._XUL_NS, "vbox");
     browserContainer.className = "browserContainer";
     browserContainer.appendChild(stack);
     browserContainer.setAttribute("flex", "10000");
 
-    // Create the sidebar container
     let browserSidebarContainer = document.createElementNS(this._XUL_NS, "hbox");
     browserSidebarContainer.className = "browserSidebarContainer";
     browserSidebarContainer.appendChild(browserContainer);
     browserSidebarContainer.setAttribute("flex", "10000");
 
     // Add the Message and the Browser to the box
     let notificationbox = document.createElementNS(this._XUL_NS, "notificationbox");
     notificationbox.setAttribute("flex", "1");
--- a/browser/base/content/test/general/browser_newWindowDrop.js
+++ b/browser/base/content/test/general/browser_newWindowDrop.js
@@ -32,21 +32,21 @@ add_task(async function test_setup() {
 
 // New Window Button opens any link.
 add_task(async function single_url() {
   await dropText("mochi.test/first",
                  ["http://www.mochi.test/first"]);
 });
 add_task(async function single_javascript() {
   await dropText("javascript:'bad'",
-                 ["about:blank"]);
+                 ["javascript:'bad'"]);
 });
 add_task(async function single_javascript_capital() {
   await dropText("jAvascript:'bad'",
-                 ["about:blank"]);
+                 ["javascript:'bad'"]);
 });
 add_task(async function single_url2() {
   await dropText("mochi.test/second",
                  ["http://www.mochi.test/second"]);
 });
 add_task(async function single_data_url() {
   await dropText("data:text/html,bad",
                  ["data:text/html,bad"]);
--- a/browser/components/resistfingerprinting/test/browser/browser_roundedWindow_newWindow.js
+++ b/browser/components/resistfingerprinting/test/browser/browser_roundedWindow_newWindow.js
@@ -20,30 +20,27 @@ add_task(async function setup() {
   let maxAvailSize = await calcMaximumAvailSize();
 
   gMaxAvailWidth = maxAvailSize.maxAvailWidth;
   gMaxAvailHeight = maxAvailSize.maxAvailHeight;
 });
 
 add_task(async function test_new_window() {
   // Open a new window.
-  let win = await BrowserTestUtils.openNewBrowserWindow();
+  let winPromise = BrowserTestUtils.waitForNewWindow();
+  OpenBrowserWindow();
+  let win = await winPromise;
 
-  // Load a page and verify its window size.
-  let tab = await BrowserTestUtils.openNewForegroundTab(
-    win.gBrowser, TEST_PATH + "file_dummy.html");
-
-  await ContentTask.spawn(tab.linkedBrowser, {gMaxAvailWidth, gMaxAvailHeight},
+  await ContentTask.spawn(win.gBrowser.selectedBrowser, {gMaxAvailWidth, gMaxAvailHeight},
     async function(input) {
       is(content.screen.width, input.gMaxAvailWidth,
         "The screen.width has a correct rounded value");
       is(content.screen.height, input.gMaxAvailHeight,
         "The screen.height has a correct rounded value");
       is(content.innerWidth, input.gMaxAvailWidth,
         "The window.innerWidth has a correct rounded value");
       is(content.innerHeight, input.gMaxAvailHeight,
         "The window.innerHeight has a correct rounded value");
     }
   );
 
-  BrowserTestUtils.removeTab(tab);
   await BrowserTestUtils.closeWindow(win);
 });