Backed out 5 changesets (bug 1444760) for talos failures regarding undefined params on a CLOSED TREE
authorAndreea Pavel <apavel@mozilla.com>
Sat, 17 Mar 2018 19:45:06 +0200
changeset 408691 384c57a10906f919aa27af99575186e9f14aaa20
parent 408690 5c72707149c3885a42a573c558dda1224594633c
child 408692 a6528c5018d22c41a03fe1353e188ea0f8526d93
push id101008
push userapavel@mozilla.com
push dateSat, 17 Mar 2018 17:45:22 +0000
treeherdermozilla-inbound@384c57a10906 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1444760
milestone61.0a1
backs out00da6f45a098a51748cce5759fb3ed6241d6afa9
79b40369822f20507569bacefd6a4ee6b8f29871
08e77f90bdb43726cf6069f3d0e69b2e7d43140a
c1e0ecafa70331503f3d4d18de5fb7862c81c985
4c52361ab381233976673dd2c519e43d9543c2fc
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 5 changesets (bug 1444760) for talos failures regarding undefined params on a CLOSED TREE Backed out changeset 00da6f45a098 (bug 1444760) Backed out changeset 79b40369822f (bug 1444760) Backed out changeset 08e77f90bdb4 (bug 1444760) Backed out changeset c1e0ecafa703 (bug 1444760) Backed out changeset 4c52361ab381 (bug 1444760)
browser/base/content/browser.js
browser/base/content/tabbrowser.js
browser/base/content/tabbrowser.xml
browser/base/content/test/general/browser_e10s_switchbrowser.js
browser/base/content/utilityOverlay.js
browser/base/content/webext-panels.js
browser/components/extensions/ExtensionPopups.jsm
browser/components/extensions/ext-devtools-panels.js
browser/components/extensions/ext-devtools.js
browser/components/extensions/ext-tabs.js
browser/components/extensions/ext-url-overrides.js
browser/components/search/test/browser_aboutSearchReset.js
browser/components/sessionstore/SessionStore.jsm
browser/components/sessionstore/test/browser_491168.js
browser/components/sessionstore/test/browser_closed_objects_changed_notifications_tabs.js
browser/components/sessionstore/test/browser_closed_objects_changed_notifications_windows.js
browser/components/sessionstore/test/browser_dying_cache.js
browser/components/sessionstore/test/browser_undoCloseById.js
browser/modules/ContentSearch.jsm
devtools/client/netmonitor/test/browser_net_frame.js
devtools/client/responsive.html/browser/swap.js
devtools/client/responsive.html/test/browser/head.js
docshell/test/browser/browser_dataURI_unique_opaque_origin.js
docshell/test/browser/browser_loadDisallowInherit.js
docshell/test/browser/browser_loadURI.js
mobile/android/chrome/content/browser.js
testing/talos/talos/pageloader/chrome/pageloader.js
toolkit/components/extensions/ext-backgroundPage.js
toolkit/content/widgets/browser.xml
toolkit/mozapps/extensions/content/extensions.js
widget/tests/test_bug428405.xul
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1016,34 +1016,32 @@ function handleUriInChrome(aBrowser, aUr
     }
   }
 
   return false;
 }
 
 // A shared function used by both remote and non-remote browser XBL bindings to
 // load a URI or redirect it to the correct process.
-function _loadURI(browser, uri, params = {}) {
+function _loadURIWithFlags(browser, uri, params) {
   let tab = gBrowser.getTabForBrowser(browser);
   // Preloaded browsers don't have tabs, so we ignore those.
   if (tab) {
     maybeRecordAbandonmentTelemetry(tab, "newURI");
   }
 
   if (!uri) {
     uri = "about:blank";
   }
-
-  let {
-    flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE,
-    referrerURI,
-    referrerPolicy = Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
-    triggeringPrincipal,
-    postData,
-  } = params || {};
+  let triggeringPrincipal = params.triggeringPrincipal || null;
+  let flags = params.flags || 0;
+  let referrer = params.referrerURI;
+  let referrerPolicy = ("referrerPolicy" in params ? params.referrerPolicy :
+                        Ci.nsIHttpChannel.REFERRER_POLICY_UNSET);
+  let postData = params.postData;
 
   let currentRemoteType = browser.remoteType;
   let requiredRemoteType;
   try {
     let fixupFlags = Ci.nsIURIFixup.FIXUP_FLAG_NONE;
     if (flags & Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
       fixupFlags |= Ci.nsIURIFixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP;
     }
@@ -1084,17 +1082,17 @@ function _loadURI(browser, uri, params =
   }
   try {
     if (!mustChangeProcess) {
       if (params.userContextId) {
         browser.webNavigation.setOriginAttributesBeforeLoading({ userContextId: params.userContextId });
       }
 
       browser.webNavigation.loadURIWithOptions(uri, flags,
-                                               referrerURI, referrerPolicy,
+                                               referrer, referrerPolicy,
                                                postData, null, null, triggeringPrincipal);
     } else {
       // Check if the current browser is allowed to unload.
       let {permitUnload, timedOut} = browser.permitUnload();
       if (!timedOut && !permitUnload) {
         return;
       }
 
@@ -1103,17 +1101,17 @@ function _loadURI(browser, uri, params =
       }
 
       let loadParams = {
         uri,
         triggeringPrincipal: triggeringPrincipal
           ? gSerializationHelper.serializeToString(triggeringPrincipal)
           : null,
         flags,
-        referrer: referrerURI ? referrerURI.spec : null,
+        referrer: referrer ? referrer.spec : null,
         referrerPolicy,
         remoteType: requiredRemoteType,
         postData,
         newFrameloader,
       };
 
       if (params.userContextId) {
         loadParams.userContextId = params.userContextId;
@@ -1130,17 +1128,17 @@ function _loadURI(browser, uri, params =
     if (mustChangeProcess) {
       Cu.reportError(e);
       gBrowser.updateBrowserRemotenessByURL(browser, uri);
 
       if (params.userContextId) {
         browser.webNavigation.setOriginAttributesBeforeLoading({ userContextId: params.userContextId });
       }
 
-      browser.webNavigation.loadURIWithOptions(uri, flags, referrerURI, referrerPolicy,
+      browser.webNavigation.loadURIWithOptions(uri, flags, referrer, referrerPolicy,
                                                postData, null, null, triggeringPrincipal);
     } else {
       throw e;
     }
   } finally {
     if (!requiredRemoteType) {
       browser.inLoadURI = false;
     }
@@ -3177,19 +3175,19 @@ var BrowserOnClick = {
         break;
     }
   },
 
   ignoreWarningLink(reason, blockedInfo) {
     // Allow users to override and continue through to the site,
     // but add a notify bar as a reminder, so that they don't lose
     // track after, e.g., tab switching.
-    gBrowser.loadURI(gBrowser.currentURI.spec, {
-      flags: Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CLASSIFIER,
-    });
+    gBrowser.loadURIWithFlags(gBrowser.currentURI.spec,
+                              Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CLASSIFIER,
+                              null, null, null);
 
     Services.perms.add(gBrowser.currentURI, "safe-browsing",
                        Ci.nsIPermissionManager.ALLOW_ACTION,
                        Ci.nsIPermissionManager.EXPIRE_SESSION);
 
     let buttons = [{
       label: gNavigatorBundle.getString("safebrowsing.getMeOutOfHereButton.label"),
       accessKey: gNavigatorBundle.getString("safebrowsing.getMeOutOfHereButton.accessKey"),
@@ -3302,23 +3300,23 @@ function getWebNavigation() {
 }
 
 function BrowserReloadWithFlags(reloadFlags) {
   let url = gBrowser.currentURI.spec;
   if (gBrowser.updateBrowserRemotenessByURL(gBrowser.selectedBrowser, url)) {
     // If the remoteness has changed, the new browser doesn't have any
     // information of what was loaded before, so we need to load the previous
     // URL again.
-    gBrowser.loadURI(url, { flags: reloadFlags });
+    gBrowser.loadURIWithFlags(url, reloadFlags);
     return;
   }
 
   // Do this after the above case where we might flip remoteness.
   // Unfortunately, we'll count the remoteness flip case as a
-  // "newURL" load, since we're using loadURI, but hopefully
+  // "newURL" load, since we're using loadURIWithFlags, but hopefully
   // that's rare enough to not matter.
   maybeRecordAbandonmentTelemetry(gBrowser.selectedTab, "reload");
 
   // Reset temporary permissions on the current tab. This is done here
   // because we only want to reset permissions on user reload.
   SitePermissions.clearTemporaryPermissions(gBrowser.selectedBrowser);
 
   let windowUtils = window.QueryInterface(Ci.nsIInterfaceRequestor)
@@ -5346,18 +5344,18 @@ nsBrowserAccess.prototype = {
           newWindow = browser.contentWindow;
         break;
       default : // OPEN_CURRENTWINDOW or an illegal value
         newWindow = window.content;
         if (aURI) {
           let loadflags = isExternal ?
                             Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL :
                             Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
-          gBrowser.loadURI(aURI.spec, {
-            triggeringPrincipal: aTriggeringPrincipal,
+          gBrowser.loadURIWithFlags(aURI.spec, {
+            aTriggeringPrincipal,
             flags: loadflags,
             referrerURI: referrer,
             referrerPolicy,
           });
         }
         if (!Services.prefs.getBoolPref("browser.tabs.loadDivertedInBackground"))
           window.focus();
     }
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -121,17 +121,17 @@ window._gBrowser = {
    * the browser when it is inserted into the document.  If any of these
    * properties are accessed by consumers, `_insertBrowser` is called and
    * the browser is inserted to ensure that things don't break.  This list
    * provides the names of properties that may be called while the browser
    * is in its unbound (lazy) state.
    */
   _browserBindingProperties: [
     "canGoBack", "canGoForward", "goBack", "goForward", "permitUnload",
-    "reload", "reloadWithFlags", "stop", "loadURI",
+    "reload", "reloadWithFlags", "stop", "loadURI", "loadURIWithFlags",
     "gotoIndex", "currentURI", "documentURI",
     "preferences", "imageDocument", "isRemoteBrowser", "messageManager",
     "getTabBrowser", "finder", "fastFind", "sessionHistory", "contentTitle",
     "characterSet", "fullZoom", "textZoom", "webProgress",
     "addProgressListener", "removeProgressListener", "audioPlaybackStarted",
     "audioPlaybackStopped", "pauseMedia", "stopMedia",
     "resumeMedia", "mute", "unmute", "blockedPopups", "lastURI",
     "purgeSessionHistory", "stopScroll", "startScroll",
@@ -347,18 +347,30 @@ window._gBrowser = {
 
   stop() {
     return this.selectedBrowser.stop();
   },
 
   /**
    * throws exception for unknown schemes
    */
-  loadURI(aURI, aParams) {
-    return this.selectedBrowser.loadURI(aURI, aParams);
+  loadURI(aURI, aReferrerURI, aCharset) {
+    return this.selectedBrowser.loadURI(aURI, aReferrerURI, aCharset);
+  },
+
+  /**
+   * throws exception for unknown schemes
+   */
+  loadURIWithFlags(aURI, aFlags, aReferrerURI, aCharset, aPostData) {
+    // Note - the callee understands both:
+    // (a) loadURIWithFlags(aURI, aFlags, ...)
+    // (b) loadURIWithFlags(aURI, { flags: aFlags, ... })
+    // Forwarding it as (a) here actually supports both (a) and (b),
+    // so you can call us either way too.
+    return this.selectedBrowser.loadURIWithFlags(aURI, aFlags, aReferrerURI, aCharset, aPostData);
   },
 
   gotoIndex(aIndex) {
     return this.selectedBrowser.gotoIndex(aIndex);
   },
 
   get currentURI() {
     return this.selectedBrowser.currentURI;
@@ -1487,17 +1499,17 @@ window._gBrowser = {
         targetTabIndex = this.tabContainer.selectedIndex;
       }
       let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
       if (aAllowThirdPartyFixup) {
         flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
           Ci.nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
       }
       try {
-        browser.loadURI(aURIs[0], {
+        browser.loadURIWithFlags(aURIs[0], {
           flags,
           postData: aPostDatas[0],
           triggeringPrincipal: aTriggeringPrincipal,
         });
       } catch (e) {
         // Ignore failure in case a URI is wrong, so we can continue
         // opening the next ones.
       }
@@ -2420,17 +2432,17 @@ window._gBrowser = {
       }
       if (aFromExternal)
         flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL;
       if (aAllowMixedContent)
         flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_MIXED_CONTENT;
       if (aDisallowInheritPrincipal)
         flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL;
       try {
-        b.loadURI(aURI, {
+        b.loadURIWithFlags(aURI, {
           flags,
           triggeringPrincipal: aTriggeringPrincipal,
           referrerURI: aNoReferrer ? null : aReferrerURI,
           referrerPolicy: aReferrerPolicy,
           charset: aCharset,
           postData: aPostData,
         });
       } catch (ex) {
@@ -4705,8 +4717,9 @@ var StatusPanel = {
     }
 
     if (!this.panel.hasAttribute("sizelimit")) {
       this.panel.setAttribute("sizelimit", "true");
       this._mouseTargetRect = null;
     }
   }
 };
+
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -2296,39 +2296,63 @@
   </binding>
 
   <binding id="tabbrowser-browser"
            extends="chrome://global/content/bindings/browser.xml#browser">
     <implementation>
       <field name="tabModalPromptBox">null</field>
 
       <!-- throws exception for unknown schemes -->
-      <method name="loadURI">
+      <method name="loadURIWithFlags">
         <parameter name="aURI"/>
-        <parameter name="aParams"/>
+        <parameter name="aFlags"/>
+        <parameter name="aReferrerURI"/>
+        <parameter name="aCharset"/>
+        <parameter name="aPostData"/>
         <body>
           <![CDATA[
-            _loadURI(this, aURI, aParams);
+            var params = arguments[1];
+            if (typeof(params) == "number") {
+              params = {
+                flags: aFlags,
+                referrerURI: aReferrerURI,
+                charset: aCharset,
+                postData: aPostData,
+              };
+            }
+            _loadURIWithFlags(this, aURI, params);
           ]]>
         </body>
       </method>
     </implementation>
   </binding>
 
   <binding id="tabbrowser-remote-browser"
            extends="chrome://global/content/bindings/remote-browser.xml#remote-browser">
     <implementation>
       <field name="tabModalPromptBox">null</field>
 
       <!-- throws exception for unknown schemes -->
-      <method name="loadURI">
+      <method name="loadURIWithFlags">
         <parameter name="aURI"/>
-        <parameter name="aParams"/>
+        <parameter name="aFlags"/>
+        <parameter name="aReferrerURI"/>
+        <parameter name="aCharset"/>
+        <parameter name="aPostData"/>
         <body>
           <![CDATA[
-            _loadURI(this, aURI, aParams);
+            var params = arguments[1];
+            if (typeof(params) == "number") {
+              params = {
+                flags: aFlags,
+                referrerURI: aReferrerURI,
+                charset: aCharset,
+                postData: aPostData,
+              };
+            }
+            _loadURIWithFlags(this, aURI, params);
           ]]>
         </body>
       </method>
     </implementation>
   </binding>
 
 </bindings>
--- a/browser/base/content/test/general/browser_e10s_switchbrowser.js
+++ b/browser/base/content/test/general/browser_e10s_switchbrowser.js
@@ -72,17 +72,17 @@ var waitForLoad = async function(uri) {
     uri: gBrowser.currentURI.spec,
     title: gBrowser.contentTitle
   });
 };
 
 // Waits for a load and updates the known history
 var waitForLoadWithFlags = async function(uri, flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE) {
   info("Loading " + uri + " flags = " + flags);
-  gBrowser.selectedBrowser.loadURI(uri, { flags });
+  gBrowser.selectedBrowser.loadURIWithFlags(uri, flags, null, null, null);
 
   await BrowserTestUtils.browserStopped(gBrowser);
   if (!(flags & Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY)) {
 
     if (flags & Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY) {
       gExpectedHistory.entries.pop();
     } else {
       gExpectedHistory.index++;
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -443,17 +443,17 @@ function openLinkIn(url, where, params) 
     if (aForceAboutBlankViewerInCurrent &&
         (!uriObj ||
          (doGetProtocolFlags(uriObj) & URI_INHERITS_SECURITY_CONTEXT))) {
       // Unless we know for sure we're not inheriting principals,
       // force the about:blank viewer to have the right principal:
       targetBrowser.createAboutBlankContentViewer(aPrincipal);
     }
 
-    targetBrowser.loadURI(url, {
+    targetBrowser.loadURIWithFlags(url, {
       triggeringPrincipal: aTriggeringPrincipal,
       flags,
       referrerURI: aNoReferrer ? null : aReferrerURI,
       referrerPolicy: aReferrerPolicy,
       postData: aPostData,
       userContextId: aUserContextId
     });
 
--- a/browser/base/content/webext-panels.js
+++ b/browser/base/content/webext-panels.js
@@ -103,11 +103,11 @@ function loadPanel(extensionId, extensio
   let sidebar = {
     uri: extensionUrl,
     remote: policy.extension.remote,
     browserStyle,
   };
   getBrowser(sidebar).then(browser => {
     let uri = Services.io.newURI(policy.getURL());
     let triggeringPrincipal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
-    browser.loadURI(extensionUrl, {triggeringPrincipal});
+    browser.loadURIWithFlags(extensionUrl, {triggeringPrincipal});
   });
 }
--- a/browser/components/extensions/ExtensionPopups.jsm
+++ b/browser/components/extensions/ExtensionPopups.jsm
@@ -311,17 +311,17 @@ class BasePopup {
         allowScriptsToClose: true,
         blockParser: this.blockParser,
         fixedWidth: this.fixedWidth,
         maxWidth: 800,
         maxHeight: 600,
         stylesheets: this.STYLESHEETS,
       });
 
-      browser.loadURI(popupURL, {triggeringPrincipal: this.extension.principal});
+      browser.loadURIWithFlags(popupURL, {triggeringPrincipal: this.extension.principal});
     });
   }
 
   unblockParser() {
     this.browserReady.then(browser => {
       this.browser.messageManager.sendAsyncMessage("Extension:UnblockParser");
     });
   }
--- a/browser/components/extensions/ext-devtools-panels.js
+++ b/browser/components/extensions/ext-devtools-panels.js
@@ -273,17 +273,17 @@ class ParentDevToolsPanel {
 
     extensions.emit("extension-browser-inserted", browser, {
       devtoolsToolboxInfo: {
         toolboxPanelId: this.id,
         inspectedWindowTabId: getTargetTabIdForToolbox(toolbox),
       },
     });
 
-    browser.loadURI(url, {
+    browser.loadURIWithFlags(url, {
       triggeringPrincipal: extension.principal,
     });
   }
 
   destroyBrowserElement() {
     const {browser, unwatchExtensionProxyContextLoad} = this;
     if (unwatchExtensionProxyContextLoad) {
       this.unwatchExtensionProxyContextLoad = null;
--- a/browser/components/extensions/ext-devtools.js
+++ b/browser/components/extensions/ext-devtools.js
@@ -171,17 +171,17 @@ class DevToolsPage extends HiddenExtensi
 
     extensions.emit("extension-browser-inserted", this.browser, {
       devtoolsToolboxInfo: {
         inspectedWindowTabId: getTargetTabIdForToolbox(this.toolbox),
         themeName: DevToolsShim.getTheme(),
       },
     });
 
-    this.browser.loadURI(this.url, {
+    this.browser.loadURIWithFlags(this.url, {
       triggeringPrincipal: this.extension.principal,
     });
 
     await this.waitForTopLevelContext;
   }
 
   close() {
     if (this.closed) {
--- a/browser/components/extensions/ext-tabs.js
+++ b/browser/components/extensions/ext-tabs.js
@@ -609,17 +609,17 @@ this.tabs = class extends ExtensionAPI {
             }
 
             let options = {
               flags: updateProperties.loadReplace
                       ? Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY
                       : Ci.nsIWebNavigation.LOAD_FLAGS_NONE,
               triggeringPrincipal: context.principal,
             };
-            nativeTab.linkedBrowser.loadURI(url, options);
+            nativeTab.linkedBrowser.loadURIWithFlags(url, options);
           }
 
           if (updateProperties.active !== null) {
             if (updateProperties.active) {
               tabbrowser.selectedTab = nativeTab;
             } else {
               // Not sure what to do here? Which tab should we select?
             }
--- a/browser/components/extensions/ext-url-overrides.js
+++ b/browser/components/extensions/ext-url-overrides.js
@@ -53,19 +53,18 @@ function replaceUrlInTab(gBrowser, tab, 
             && browser.ownerGlobal.gBrowser.getTabForBrowser(browser) == tab
             && locationURI.spec == url) {
           windowTracker.removeListener(this);
           resolve();
         }
       },
     });
   });
-  gBrowser.loadURI(url, {
-    flags: Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY,
-  });
+  gBrowser.loadURIWithFlags(
+    url, {flags: Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY});
   return loaded;
 }
 
 async function handleNewTabOpened() {
   // We don't need to open the doorhanger again until the controlling add-on changes.
   // eslint-disable-next-line no-use-before-define
   removeNewTabObserver();
 
--- a/browser/components/search/test/browser_aboutSearchReset.js
+++ b/browser/components/search/test/browser_aboutSearchReset.js
@@ -28,20 +28,20 @@ function checkTelemetryRecords(expectedV
   Assert.deepEqual(snapshot.counts, expectedCounts,
                    "histogram has expected content");
   histogram.clear();
 }
 
 function promiseStoppedLoad(expectedURL) {
   return new Promise(resolve => {
     let browser = gBrowser.selectedBrowser;
-    let original = browser.loadURI;
-    browser.loadURI = function(URI) {
+    let original = browser.loadURIWithFlags;
+    browser.loadURIWithFlags = function(URI) {
       if (URI == expectedURL) {
-        browser.loadURI = original;
+        browser.loadURIWithFlags = original;
         ok(true, "loaded expected url: " + URI);
         resolve();
         return;
       }
 
       original.apply(browser, arguments);
     };
   });
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -2896,17 +2896,17 @@ var SessionStoreInternal = {
                       "Somehow a crashed browser is still remote.");
     }
 
     // We put the browser at about:blank in case the user is
     // restoring tabs on demand. This way, the user won't see
     // a flash of the about:tabcrashed page after selecting
     // the revived tab.
     aTab.removeAttribute("crashed");
-    browser.loadURI("about:blank");
+    browser.loadURI("about:blank", null, null);
 
     let data = TabState.collect(aTab);
     this.restoreTab(aTab, data, {
       forceOnDemand: true,
     });
   },
 
   /**
--- a/browser/components/sessionstore/test/browser_491168.js
+++ b/browser/components/sessionstore/test/browser_491168.js
@@ -12,17 +12,17 @@ add_task(async function() {
 
   // Add a new tab.
   let tab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, "about:blank");
   let browser = tab.linkedBrowser;
   await promiseBrowserLoaded(browser);
 
   // Load a new URI with a specific referrer.
   let referrerURI = Services.io.newURI(REFERRER1);
-  browser.loadURI("http://example.org", { referrerURI });
+  browser.loadURI("http://example.org", referrerURI, null);
   await promiseBrowserLoaded(browser);
 
   await TabStateFlusher.flush(browser);
   let tabState = JSON.parse(ss.getTabState(tab));
   is(tabState.entries[0].referrer, REFERRER1,
      "Referrer retrieved via getTabState matches referrer set via loadURI.");
 
   tabState.entries[0].referrer = REFERRER2;
--- a/browser/components/sessionstore/test/browser_closed_objects_changed_notifications_tabs.js
+++ b/browser/components/sessionstore/test/browser_closed_objects_changed_notifications_tabs.js
@@ -7,17 +7,17 @@
 const MAX_TABS_UNDO_PREF = "browser.sessionstore.max_tabs_undo";
 const TOPIC = "sessionstore-closed-objects-changed";
 
 let notificationsCount = 0;
 
 async function openWindow(url) {
   let win = await promiseNewWindowLoaded();
   let flags = Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY;
-  win.gBrowser.selectedBrowser.loadURI(url, { flags });
+  win.gBrowser.selectedBrowser.loadURIWithFlags(url, flags);
   await promiseBrowserLoaded(win.gBrowser.selectedBrowser, true, url);
   return win;
 }
 
 async function closeWindow(win) {
   await awaitNotification(() => BrowserTestUtils.closeWindow(win));
 }
 
--- a/browser/components/sessionstore/test/browser_closed_objects_changed_notifications_windows.js
+++ b/browser/components/sessionstore/test/browser_closed_objects_changed_notifications_windows.js
@@ -9,17 +9,17 @@ requestLongerTimeout(2);
 const MAX_WINDOWS_UNDO_PREF = "browser.sessionstore.max_windows_undo";
 const TOPIC = "sessionstore-closed-objects-changed";
 
 let notificationsCount = 0;
 
 async function openWindow(url) {
   let win = await promiseNewWindowLoaded();
   let flags = Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY;
-  win.gBrowser.selectedBrowser.loadURI(url, { flags });
+  win.gBrowser.selectedBrowser.loadURIWithFlags(url, flags);
   await promiseBrowserLoaded(win.gBrowser.selectedBrowser, true, url);
   return win;
 }
 
 async function closeWindow(win) {
   await awaitNotification(() => BrowserTestUtils.closeWindow(win));
 }
 
--- a/browser/components/sessionstore/test/browser_dying_cache.js
+++ b/browser/components/sessionstore/test/browser_dying_cache.js
@@ -7,17 +7,17 @@
  */
 
 add_task(async function test() {
   // Open a new window.
   let win = await promiseNewWindowLoaded();
 
   // Load some URL in the current tab.
   let flags = Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY;
-  win.gBrowser.selectedBrowser.loadURI("about:robots", { flags });
+  win.gBrowser.selectedBrowser.loadURIWithFlags("about:robots", flags);
   await promiseBrowserLoaded(win.gBrowser.selectedBrowser);
 
   // Open a second tab and close the first one.
   let tab = win.gBrowser.addTab("about:mozilla");
   await promiseBrowserLoaded(tab.linkedBrowser);
   await TabStateFlusher.flush(tab.linkedBrowser);
   await promiseRemoveTab(win.gBrowser.tabs[0]);
 
--- a/browser/components/sessionstore/test/browser_undoCloseById.js
+++ b/browser/components/sessionstore/test/browser_undoCloseById.js
@@ -12,17 +12,17 @@ async function openAndCloseTab(window, u
   await promiseBrowserLoaded(tab.linkedBrowser, true, url);
   await TabStateFlusher.flush(tab.linkedBrowser);
   await promiseRemoveTab(tab);
 }
 
 async function openWindow(url) {
   let win = await promiseNewWindowLoaded();
   let flags = Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY;
-  win.gBrowser.selectedBrowser.loadURI(url, { flags });
+  win.gBrowser.selectedBrowser.loadURIWithFlags(url, flags);
   await promiseBrowserLoaded(win.gBrowser.selectedBrowser, true, url);
   return win;
 }
 
 async function closeWindow(win) {
   await BrowserTestUtils.closeWindow(win);
   // Wait 20 ms to allow SessionStorage a chance to register the closed window.
   await new Promise(resolve => setTimeout(resolve, 20));
--- a/browser/modules/ContentSearch.jsm
+++ b/browser/modules/ContentSearch.jsm
@@ -234,19 +234,19 @@ var ContentSearch = {
     // has switched away from the tab that triggered the search. If, based on the
     // event, we need to load the search in the same tab that triggered it (i.e.
     // where === "current"), openUILinkIn will not work because that tab is no
     // longer the current one. For this case we manually load the URI.
     if (where === "current") {
       // Since we're going to load the search in the same browser, blur the search
       // UI to prevent further interaction before we start loading.
       this._reply(msg, "Blur");
-      browser.loadURI(submission.uri.spec, {
-        postData: submission.postData
-      });
+      browser.loadURIWithFlags(submission.uri.spec,
+                               Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null,
+                               submission.postData);
     } else {
       let params = {
         postData: submission.postData,
         inBackground: Services.prefs.getBoolPref("browser.tabs.loadInBackground"),
       };
       win.openUILinkIn(submission.uri.spec, where, params);
     }
     win.BrowserSearch.recordSearchInTelemetry(engine, data.healthReportKey,
--- a/devtools/client/netmonitor/test/browser_net_frame.js
+++ b/devtools/client/netmonitor/test/browser_net_frame.js
@@ -162,17 +162,17 @@ add_task(async function() {
   let Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
   let {
     getDisplayedRequests,
     getSortedRequests,
   } = windowRequire("devtools/client/netmonitor/src/selectors/index");
 
   store.dispatch(Actions.batchEnable(false));
 
-  tab.linkedBrowser.loadURI(TOP_URL);
+  tab.linkedBrowser.loadURI(TOP_URL, null, null);
 
   await waitForNetworkEvents(monitor, REQUEST_COUNT);
 
   is(store.getState().requests.requests.size, REQUEST_COUNT,
     "All the page events should be recorded.");
 
   // Fetch stack-trace data from the backend and wait till
   // all packets are received.
--- a/devtools/client/responsive.html/browser/swap.js
+++ b/devtools/client/responsive.html/browser/swap.js
@@ -119,17 +119,17 @@ function swapToInnerBrowser({ tab, conta
       // to just not load the `content-sessionStore.js` frame script at all in the
       // container tab, but it's loaded for all tab browsers, so this seems a bit harder
       // to achieve in a nice way.
       containerBrowser.messageManager.sendAsyncMessage("SessionStore:flush", {
         epoch: -1,
       });
       // Prevent the `containerURL` from ending up in the tab's history.
       debug("Load container URL");
-      containerBrowser.loadURI(containerURL, {
+      containerBrowser.loadURIWithFlags(containerURL, {
         flags: Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY,
       });
 
       // Copy tab listener state flags to container tab.  Each tab gets its own tab
       // listener and state flags which cache document loading progress.  The state flags
       // are checked when switching tabs to update the browser UI.  The later step of
       // `swapBrowsersAndCloseOther` will fold the state back into the main tab.
       let stateFlags = gBrowser._tabListeners.get(tab).mStateFlags;
--- a/devtools/client/responsive.html/test/browser/head.js
+++ b/devtools/client/responsive.html/test/browser/head.js
@@ -310,17 +310,17 @@ function waitForPageShow(browser) {
 }
 
 function waitForViewportLoad(ui) {
   return BrowserTestUtils.waitForContentEvent(ui.getViewportBrowser(), "load", true);
 }
 
 function load(browser, url) {
   let loaded = BrowserTestUtils.browserLoaded(browser, false, url);
-  browser.loadURI(url);
+  browser.loadURI(url, null, null);
   return loaded;
 }
 
 function back(browser) {
   let shown = waitForPageShow(browser);
   browser.goBack();
   return shown;
 }
--- a/docshell/test/browser/browser_dataURI_unique_opaque_origin.js
+++ b/docshell/test/browser/browser_dataURI_unique_opaque_origin.js
@@ -9,17 +9,17 @@ add_task(async function setup() {
 add_task(async function test_dataURI_unique_opaque_origin() {
   let tab = BrowserTestUtils.addTab(gBrowser, "http://example.com");
   let browser = tab.linkedBrowser;
   await BrowserTestUtils.browserLoaded(browser);
 
   let pagePrincipal = browser.contentPrincipal;
   info("pagePrincial " + pagePrincipal.origin);
 
-  browser.loadURI("data:text/html,hi");
+  browser.loadURIWithFlags("data:text/html,hi", 0, null, null, null);
   await BrowserTestUtils.browserLoaded(browser);
 
   await ContentTask.spawn(browser, { principal: pagePrincipal }, async function(args) {
     info("data URI principal: " + content.document.nodePrincipal.origin);
     Assert.ok(content.document.nodePrincipal.isNullPrincipal,
               "data: URI should have NullPrincipal.");
     Assert.ok(!content.document.nodePrincipal.equals(args.principal),
               "data: URI should have unique opaque origin.");
--- a/docshell/test/browser/browser_loadDisallowInherit.js
+++ b/docshell/test/browser/browser_loadDisallowInherit.js
@@ -17,17 +17,17 @@ function startTest() {
   let tab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
 
   let browser = gBrowser.getBrowserForTab(tab);
 
   function loadURL(url, flags, func) {
     BrowserTestUtils.browserLoaded(browser, false, url).then(() => {
       func();
     });
-    browser.loadURI(url, { flags });
+    browser.loadURIWithFlags(url, flags, null, null, null);
   }
 
   // Load a normal http URL
   function testURL(url, func) {
     loadURL("http://example.com/", 0, function () {
       let pagePrincipal = browser.contentPrincipal;
       ok(pagePrincipal, "got principal for http:// page");
 
@@ -63,8 +63,9 @@ function startTest() {
     } else {
       gBrowser.removeTab(tab);
       finish();
     }
   }
 
   nextTest();
 }
+
--- a/docshell/test/browser/browser_loadURI.js
+++ b/docshell/test/browser/browser_loadURI.js
@@ -15,18 +15,16 @@ function test() {
                    createInstance(Ci.nsIStringInputStream);
   dataStream.data = gPostData;
 
   var postStream = Cc["@mozilla.org/network/mime-input-stream;1"].
                    createInstance(Ci.nsIMIMEInputStream);
   postStream.addHeader("Content-Type", "application/x-www-form-urlencoded");
   postStream.setData(dataStream);
 
-  tab.linkedBrowser.loadURI("http://mochi.test:8888/browser/docshell/test/browser/print_postdata.sjs", {
-    postData: postStream,
-  });
+  tab.linkedBrowser.loadURIWithFlags("http://mochi.test:8888/browser/docshell/test/browser/print_postdata.sjs", 0, null, null, postStream);
   BrowserTestUtils.browserLoaded(tab.linkedBrowser).then(() => {
     ContentTask.spawn(tab.linkedBrowser, gPostData, function(postData) {
       var bodyText = content.document.body.textContent;
       is(bodyText, postData, "post data was submitted correctly");
     }).then(() => { finish(); });
   });
 }
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -1167,22 +1167,17 @@ var BrowserApp = {
 
     let tab = this.getTabForBrowser(aBrowser);
     if (tab) {
       if ("userRequested" in aParams) tab.userRequested = aParams.userRequested;
       tab.isSearch = ("isSearch" in aParams) ? aParams.isSearch : false;
     }
 
     try {
-      aBrowser.loadURI(aURI, {
-        flags,
-        referrerURI,
-        charset,
-        postData,
-      });
+      aBrowser.loadURIWithFlags(aURI, flags, referrerURI, charset, postData);
     } catch(e) {
       if (tab) {
         let message = {
           type: "Content:LoadError",
           tabID: tab.id
         };
         GlobalEventDispatcher.sendRequest(message);
         dump("Handled load error: " + e)
@@ -3492,34 +3487,34 @@ nsBrowserAccess.prototype = {
         let parent = BrowserApp.getTabForWindow(aOpener.top);
         if (parent) {
           parentId = parent.id;
           isPrivate = PrivateBrowsingUtils.isBrowserPrivate(parent.browser);
         }
       }
 
       let openerWindow = (aFlags & Ci.nsIBrowserDOMWindow.OPEN_NO_OPENER) ? null : aOpener;
-      // BrowserApp.addTab calls loadURI with the appropriate params
+      // BrowserApp.addTab calls loadURIWithFlags with the appropriate params
       let tab = BrowserApp.addTab(aURI ? aURI.spec : "about:blank", { flags: loadflags,
                                                                       referrerURI: referrer,
                                                                       external: isExternal,
                                                                       parentId: parentId,
                                                                       opener: openerWindow,
                                                                       selected: true,
                                                                       isPrivate: isPrivate,
                                                                       pinned: pinned,
                                                                       triggeringPrincipal: aTriggeringPrincipal});
 
       return tab.browser;
     }
 
     // OPEN_CURRENTWINDOW and illegal values
     let browser = BrowserApp.selectedBrowser;
     if (aURI && browser) {
-      browser.loadURI(aURI.spec, {
+      browser.loadURIWithFlags(aURI.spec, {
         flags: loadflags,
         referrerURI: referrer,
         triggeringPrincipal: aTriggeringPrincipal,
       });
     }
 
     return browser;
   },
@@ -3775,22 +3770,17 @@ Tab.prototype = {
       let referrerURI = "referrerURI" in aParams ? aParams.referrerURI : null;
       let charset = "charset" in aParams ? aParams.charset : null;
 
       // The search term the user entered to load the current URL
       this.userRequested = "userRequested" in aParams ? aParams.userRequested : "";
       this.isSearch = "isSearch" in aParams ? aParams.isSearch : false;
 
       try {
-        this.browser.loadURI(aURL, {
-          flags,
-          referrerURI,
-          charset,
-          postData,
-        });
+        this.browser.loadURIWithFlags(aURL, flags, referrerURI, charset, postData);
       } catch(e) {
         let message = {
           type: "Content:LoadError",
           tabID: this.id
         };
         GlobalEventDispatcher.sendRequest(message);
         dump("Handled load error: " + e);
       }
--- a/testing/talos/talos/pageloader/chrome/pageloader.js
+++ b/testing/talos/talos/pageloader/chrome/pageloader.js
@@ -316,19 +316,17 @@ function startAndLoadURI(pageName) {
     // Resume the profiler because we're really measuring page load time.
     // If the test is doing its own timing, it'll also need to do its own
     // profiler pausing / resuming.
     TalosParentProfiler.resume("Starting to load URI " + pageName);
   }
 
   start_time = Date.now();
   if (loadNoCache) {
-    content.loadURI(pageName, {
-      flags: Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE
-    });
+    content.loadURIWithFlags(pageName, Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE);
   } else {
     content.loadURI(pageName);
   }
 }
 
 function getTestName() { // returns tp5n
   var pageName = pages[pageIndex].url.spec;
   let parts = pageName.split("/");
--- a/toolkit/components/extensions/ext-backgroundPage.js
+++ b/toolkit/components/extensions/ext-backgroundPage.js
@@ -26,17 +26,17 @@ class BackgroundPage extends HiddenExten
 
   async build() {
     TelemetryStopwatch.start("WEBEXT_BACKGROUND_PAGE_LOAD_MS", this);
     await this.createBrowserElement();
     this.extension._backgroundPageFrameLoader = this.browser.frameLoader;
 
     extensions.emit("extension-browser-inserted", this.browser);
 
-    this.browser.loadURI(this.url, {triggeringPrincipal: this.extension.principal});
+    this.browser.loadURIWithFlags(this.url, {triggeringPrincipal: this.extension.principal});
 
     let context = await promiseExtensionViewLoaded(this.browser);
     TelemetryStopwatch.finish("WEBEXT_BACKGROUND_PAGE_LOAD_MS", this);
 
     if (context) {
       // Wait until all event listeners registered by the script so far
       // to be handled.
       await Promise.all(context.listenerPromises);
--- a/toolkit/content/widgets/browser.xml
+++ b/toolkit/content/widgets/browser.xml
@@ -98,35 +98,62 @@
             this.webNavigation.stop(flags);
           ]]>
         </body>
       </method>
 
       <!-- throws exception for unknown schemes -->
       <method name="loadURI">
         <parameter name="aURI"/>
-        <parameter name="aParams"/>
+        <parameter name="aReferrerURI"/>
+        <parameter name="aCharset"/>
+        <body>
+          <![CDATA[
+            const nsIWebNavigation = Ci.nsIWebNavigation;
+            const flags = nsIWebNavigation.LOAD_FLAGS_NONE;
+            this._wrapURIChangeCall(() =>
+              this.loadURIWithFlags(aURI, flags, aReferrerURI, aCharset));
+          ]]>
+        </body>
+      </method>
+
+      <!-- throws exception for unknown schemes -->
+      <method name="loadURIWithFlags">
+        <parameter name="aURI"/>
+        <parameter name="aFlags"/>
+        <parameter name="aReferrerURI"/>
+        <parameter name="aCharset"/>
+        <parameter name="aPostData"/>
         <body>
           <![CDATA[
-            if (!aURI) {
+            if (!aURI)
               aURI = "about:blank";
-            }
+
+            var aReferrerPolicy = Ci.nsIHttpChannel.REFERRER_POLICY_UNSET;
+            var aTriggeringPrincipal;
 
-            let {
-              flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE,
-              referrerURI,
-              referrerPolicy = Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
-              triggeringPrincipal,
-              postData,
-            } = aParams || {};
+            // Check for loadURIWithFlags(uri, { ... });
+            var params = arguments[1];
+            if (params && typeof(params) == "object") {
+              aFlags = params.flags;
+              aReferrerURI = params.referrerURI;
+              if ("referrerPolicy" in params) {
+                aReferrerPolicy = params.referrerPolicy;
+              }
+              if ("triggeringPrincipal" in params) {
+                aTriggeringPrincipal = params.triggeringPrincipal;
+              }
+              aCharset = params.charset;
+              aPostData = params.postData;
+            }
 
             this._wrapURIChangeCall(() =>
               this.webNavigation.loadURIWithOptions(
-                  aURI, flags, referrerURI, referrerPolicy,
-                  postData, null, null, triggeringPrincipal));
+                  aURI, aFlags, aReferrerURI, aReferrerPolicy,
+                  aPostData, null, null, aTriggeringPrincipal));
           ]]>
         </body>
       </method>
 
       <method name="gotoIndex">
         <parameter name="aIndex"/>
         <body>
           <![CDATA[
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -2212,17 +2212,17 @@ var gDiscoverView = {
 
     if (aCallback)
       this._loadListeners.push(aCallback);
 
     var flags = 0;
     if (!aKeepHistory)
       flags |= Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY;
 
-    this._browser.loadURI(aURL, { flags });
+    this._browser.loadURIWithFlags(aURL, flags);
   },
 
   onLocationChange(aWebProgress, aRequest, aLocation, aFlags) {
     // Ignore the about:blank load
     if (aLocation.spec == "about:blank")
       return;
 
     // When using the real session history the inner-frame will update the
--- a/widget/tests/test_bug428405.xul
+++ b/widget/tests/test_bug428405.xul
@@ -51,17 +51,17 @@
       // it's a cmd-opt-y event.
       gChromeWindow.addEventListener("keypress", onKeyPress, false);
     }
 
     // 1) Start loading first tab.
     // 6) Start reloading first tab.
     function loadFirstTab() {
       var browser = document.getElementById("tab1browser");
-      browser.loadURI("data:text/html;charset=utf-8,<body><h2>First Tab</h2><p><input type='submit' value='Button' id='button1'/></body>");
+      browser.loadURI("data:text/html;charset=utf-8,<body><h2>First Tab</h2><p><input type='submit' value='Button' id='button1'/></body>", null, null);
     }
 
     function configureFirstTab() {
       try {
         var button = document.getElementById("tab1browser").contentDocument.getElementById("button1");
         button.addEventListener("click", onFirstTabButtonClicked, false);
         button.focus();
         if (document.getElementById("tabbox").selectedIndex == 0) {
@@ -76,17 +76,17 @@
         }
       } catch(e) {
       }
     }
 
     // 8) Start loading second tab.
     function loadSecondTab() {
       var browser = document.getElementById("tab2browser");
-      browser.loadURI("data:text/html;charset=utf-8,<body><h2>Second Tab</h2><p><input type='submit' value='Button' id='button1'/></body>");
+      browser.loadURI("data:text/html;charset=utf-8,<body><h2>Second Tab</h2><p><input type='submit' value='Button' id='button1'/></body>", null, null);
     }
 
     function configureSecondTab() {
       try {
         var button = document.getElementById("tab2browser").contentDocument.getElementById("button1");
         button.addEventListener("click", onSecondTabButtonClicked, false);
         button.focus();
         if (document.getElementById("tabbox").selectedIndex == 1) {