Bug 1377580 - [1.2] Extend nsIBrowserDOMWindow to support content window creation without URI loading. r=smaug
authorEugen Sawin <esawin@mozilla.com>
Thu, 03 Aug 2017 17:21:11 +0200
changeset 374533 216dc8344ce047d521c5431e212d942230337f13
parent 374532 53118a4b39b1b09ac796aa406ea8f4b02ce55a0e
child 374534 315ef1c38167b490798d8a377e2ae8389ae11fb5
push id93692
push useresawin@mozilla.com
push dateMon, 14 Aug 2017 12:57:56 +0000
treeherdermozilla-inbound@2ef6679f5c0e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1377580
milestone57.0a1
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
Bug 1377580 - [1.2] Extend nsIBrowserDOMWindow to support content window creation without URI loading. r=smaug
browser/base/content/browser.js
dom/interfaces/base/nsIBrowserDOMWindow.idl
mobile/android/chrome/content/browser.js
xpfe/appshell/nsContentTreeOwner.cpp
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -5230,17 +5230,30 @@ nsBrowserAccess.prototype = {
     let browser = win.gBrowser.getBrowserForTab(tab);
 
     if (needToFocusWin || (!loadInBackground && aIsExternal))
       win.focus();
 
     return browser;
   },
 
+  createContentWindow(aURI, aOpener, aWhere, aFlags) {
+    return this.getContentWindowOrOpenURI(null, aOpener, aWhere, aFlags);
+  },
+
   openURI(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal) {
+    if (!aURI) {
+      Cu.reportError("openURI should only be called with a valid URI");
+      throw Cr.NS_ERROR_FAILURE;
+    }
+    return this.getContentWindowOrOpenURI(aURI, aOpener, aWhere, aFlags,
+                                          aTriggeringPrincipal);
+  },
+
+  getContentWindowOrOpenURI(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal) {
     // This function should only ever be called if we're opening a URI
     // from a non-remote browser window (via nsContentTreeOwner).
     if (aOpener && Cu.isCrossProcessWrapper(aOpener)) {
       Cu.reportError("nsBrowserAccess.openURI was passed a CPOW for aOpener. " +
                      "openURI should only ever be called from non-remote browsers.");
       throw Cr.NS_ERROR_FAILURE;
     }
 
--- a/dom/interfaces/base/nsIBrowserDOMWindow.idl
+++ b/dom/interfaces/base/nsIBrowserDOMWindow.idl
@@ -17,29 +17,29 @@ interface nsIOpenURIInFrameParams : nsIS
   attribute DOMString referrer;
   readonly attribute boolean isPrivate;
   attribute nsIPrincipal triggeringPrincipal;
 
   [implicit_jscontext]
   readonly attribute jsval openerOriginAttributes;
 };
 
-[scriptable, uuid(9d17f3dd-672b-451e-afd2-b1115df780d5)]
+[scriptable, uuid(2a9bb880-5d73-40f3-8152-c60c8d137a14)]
 
 /**
  * The C++ source has access to the browser script source through
  * nsIBrowserDOMWindow. It is intended to be attached to the chrome DOMWindow
  * of a toplevel browser window (a XUL window). A DOMWindow that does not
  * happen to be a browser chrome window will simply have no access to any such
  * interface.
  */
 interface nsIBrowserDOMWindow : nsISupports
 {
   /**
-   * Values for openURI's aWhere parameter.
+   * Values for createContentWindow's and openURI's aWhere parameter.
    */
   /**
    * Do whatever the default is based on application state, user preferences,
    * and the value of the aContext parameter to openURI.
    */
   const short OPEN_DEFAULTWINDOW = 0;
   /**
    * Open in the "current window".  If aOpener is provided, this should be the
@@ -59,52 +59,70 @@ interface nsIBrowserDOMWindow : nsISuppo
   const short OPEN_NEWTAB        = 3;
   /**
    * Open in an existing content tab based on the URI. If a match can't be
    * found, revert to OPEN_NEWTAB behavior.
    */
   const short OPEN_SWITCHTAB     = 4;
 
   /**
-   * Values for openURI's aFlags parameter. This is a bitflags field.
+   * Values for createContentWindow's and openURI's aFlags parameter.
+   * This is a bitflags field.
    *
    * The 0x1 bit decides the behavior of OPEN_DEFAULTWINDOW, and the 0x4 bit
    * controls whether or not to set the window.opener property on the newly
    * opened window.
    *
    * NOTE: The 0x2 bit is ignored for backwards compatibility with addons, as
    * OPEN_NEW used to have the value 2. The values 0 and 2 are treated
    * the same way internally.
    */
   /**
-   * internal open new window
+   * Internal open new window.
    */
   const long OPEN_NEW           = 0x0;
   /**
-   * external link (load request from another application, xremote, etc).
+   * External link (load request from another application, xremote, etc).
    */
   const long OPEN_EXTERNAL      = 0x1;
 
   /**
-   * Don't set the window.opener property on the window which is being opened
+   * Don't set the window.opener property on the window which is being opened.
    */
   const long OPEN_NO_OPENER     = 0x4;
 
   /**
-   * Load a URI
+   * Create the content window for the given URI.
 
-   * @param aURI the URI to open. null is allowed.  If null is passed in, no
-   *             load will be done, though the window the load would have
-   *             happened in will be returned.
+   * @param aURI the URI to be opened in the window (can be null).
+   * @param aWhere see possible values described above.
+   * @param aOpener window requesting the creation (can be null).
+   * @param aFlags flags which control the behavior of the load. The
+   *               OPEN_EXTERNAL/OPEN_NEW flag is only used when
+   *               aWhere == OPEN_DEFAULTWINDOW.
+   * @param aTriggeringPrincipal the principal that would trigger the potential
+   *        load of aURI.
+   * @return the window into which the URI would have been opened.
+  */
+  mozIDOMWindowProxy
+  createContentWindow(in nsIURI aURI, in mozIDOMWindowProxy aOpener,
+                      in short aWhere, in long aFlags,
+                      in nsIPrincipal aTriggeringPrincipal);
+
+  /**
+   * Load a URI.
+
+   * @param aURI the URI to open. null is not allowed. To create the window
+   *        without loading the URI, use createContentWindow instead.
    * @param aWhere see possible values described above.
    * @param aOpener window requesting the open (can be null).
    * @param aFlags flags which control the behavior of the load. The
    *               OPEN_EXTERNAL/OPEN_NEW flag is only used when
    *               aWhere == OPEN_DEFAULTWINDOW.
-   * @param aTriggeringPrincipal the principal that triggered the load of aURI
+   * @param aTriggeringPrincipal the principal that triggered the load of aURI.
    * @return the window into which the URI was opened.
   */
   mozIDOMWindowProxy
   openURI(in nsIURI aURI, in mozIDOMWindowProxy aOpener,
           in short aWhere, in long aFlags, in nsIPrincipal aTriggeringPrincipal);
 
   /**
    * As above, but return the nsIFrameLoaderOwner for the new window.
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -3419,19 +3419,32 @@ nsBrowserAccess.prototype = {
         referrerURI: referrer,
         triggeringPrincipal: aTriggeringPrincipal,
       });
     }
 
     return browser;
   },
 
-  openURI: function browser_openURI(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal) {
-    let browser = this._getBrowser(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal);
-    return browser ? browser.contentWindow : null;
+  openURI: function browser_openURI(aURI, aOpener, aWhere, aFlags,
+                                    aTriggeringPrincipal) {
+    if (!aURI) {
+      throw "Can't open an empty uri";
+    }
+    let browser = this._getBrowser(aURI, aOpener, aWhere, aFlags,
+                                   aTriggeringPrincipal);
+    return browser && browser.contentWindow;
+  },
+
+  createContentWindow: function browser_createContentWindow(
+                                aURI, aOpener, aWhere, aFlags,
+                                aTriggeringPrincipal) {
+    let browser = this._getBrowser(null, aOpener, aWhere, aFlags,
+                                   aTriggeringPrincipal);
+    return browser && browser.contentWindow;
   },
 
   openURIInFrame: function browser_openURIInFrame(aURI, aParams, aWhere, aFlags,
                                                   aNextTabParentId, aName) {
     // We currently ignore aNextTabParentId on mobile.  This needs to change
     // when Fennec starts to support e10s.  Assertions will fire if this code
     // isn't fixed by then.
     //
--- a/xpfe/appshell/nsContentTreeOwner.cpp
+++ b/xpfe/appshell/nsContentTreeOwner.cpp
@@ -918,26 +918,25 @@ nsContentTreeOwner::ProvideWindow(mozIDO
   {
     dom::AutoNoJSAPI nojsapi;
 
     uint32_t flags = nsIBrowserDOMWindow::OPEN_NEW;
     if (aForceNoOpener) {
       flags |= nsIBrowserDOMWindow::OPEN_NO_OPENER;
     }
 
-    // Get a new rendering area from the browserDOMWin.  We don't want
-    // to be starting any loads here, so get it with a null URI. Since/
-    // we are not loading any URI, we follow the principle of least privlege
-    // and use a nullPrincipal as the triggeringPrincipal.
+    // Get a new rendering area from the browserDOMWin.
+    // Since we are not loading any URI, we follow the principle of least
+    // privilege and use a nullPrincipal as the triggeringPrincipal.
     //
     // This method handles setting the opener for us, so we don't need to set it
     // ourselves.
     RefPtr<NullPrincipal> nullPrincipal = NullPrincipal::Create();
-    return browserDOMWin->OpenURI(nullptr, aParent, openLocation,
-                                  flags, nullPrincipal, aReturn);
+    return browserDOMWin->CreateContentWindow(aURI, aParent, openLocation,
+                                              flags, nullPrincipal, aReturn);
   }
 }
 
 //*****************************************************************************
 // nsContentTreeOwner: Accessors
 //*****************************************************************************
 
 #if defined(XP_MACOSX)