/*static*/
BrowserElementParent::OpenWindowResult
BrowserElementParent::OpenWindowOOP(TabParent* aOpenerTabParent,
                                    TabParent* aPopupTabParent,
                                    const nsAString& aURL,
                                    const nsAString& aName,
                                    const nsAString& aFeatures)
{
    // Create an iframe owned by the same document which owns openerFrameElement.
    nsCOMPtr<Element> openerFrameElement = aOpenerTabParent->GetOwnerElement();
    NS_ENSURE_TRUE(openerFrameElement,
                   BrowserElementParent::OPEN_WINDOW_IGNORED);
    nsRefPtr<HTMLIFrameElement> popupFrameElement =
        CreateIframe(openerFrameElement, aName, /* aRemote = */ true);

    // Normally an <iframe> element will try to create a frameLoader when the
    // page touches iframe.contentWindow or sets iframe.src.
    //
    // But in our case, we want to delay the creation of the frameLoader until
    // we've verified that the popup has gone through successfully.  If the popup
    // is "blocked" by the embedder, we don't want to load the popup's url.
    //
    // Therefore we call DisallowCreateFrameLoader() on the element and call
    // AllowCreateFrameLoader() only after we've verified that the popup was
    // allowed.
    popupFrameElement->DisallowCreateFrameLoader();

    OpenWindowResult opened =
        DispatchOpenWindowEvent(openerFrameElement, popupFrameElement,
                                aURL, aName, aFeatures);

    if (opened != BrowserElementParent::OPEN_WINDOW_ADDED) {
        return opened;
    }

    // The popup was not blocked, so hook up the frame element and the popup tab
    // parent, and return success.
    aPopupTabParent->SetOwnerElement(popupFrameElement);
    popupFrameElement->AllowCreateFrameLoader();
    popupFrameElement->CreateRemoteFrameLoader(aPopupTabParent);
    return opened;
}
/* static */
BrowserElementParent::OpenWindowResult
BrowserElementParent::OpenWindowInProcess(nsPIDOMWindowOuter* aOpenerWindow,
                                          nsIURI* aURI,
                                          const nsAString& aName,
                                          const nsACString& aFeatures,
                                          bool aForceNoOpener,
                                          mozIDOMWindowProxy** aReturnWindow)
{
  *aReturnWindow = nullptr;

  // If we call window.open from an <iframe> inside an <iframe mozbrowser>,
  // it's as though the top-level document inside the <iframe mozbrowser>
  // called window.open.  (Indeed, in the OOP case, the inner <iframe> lives
  // out-of-process, so we couldn't touch it if we tried.)
  //
  // GetScriptableTop gets us the <iframe mozbrowser>'s window; we'll use its
  // frame element, rather than aOpenerWindow's frame element, as our "opener
  // frame element" below.
  nsCOMPtr<nsPIDOMWindowOuter> win = aOpenerWindow->GetScriptableTop();

  nsCOMPtr<Element> openerFrameElement = win->GetFrameElementInternal();
  NS_ENSURE_TRUE(openerFrameElement, BrowserElementParent::OPEN_WINDOW_IGNORED);


  RefPtr<HTMLIFrameElement> popupFrameElement =
    CreateIframe(openerFrameElement, aName, /* aRemote = */ false);
  NS_ENSURE_TRUE(popupFrameElement, BrowserElementParent::OPEN_WINDOW_IGNORED);

  nsAutoCString spec;
  if (aURI) {
    aURI->GetSpec(spec);
  }

  if (!aForceNoOpener) {
    ErrorResult res;
    popupFrameElement->PresetOpenerWindow(aOpenerWindow, res);
    MOZ_ASSERT(!res.Failed());
  }

  OpenWindowResult opened =
    DispatchOpenWindowEvent(openerFrameElement, popupFrameElement,
                            NS_ConvertUTF8toUTF16(spec),
                            aName,
                            NS_ConvertUTF8toUTF16(aFeatures));

  if (opened != BrowserElementParent::OPEN_WINDOW_ADDED) {
    return opened;
  }

  // Return popupFrameElement's window.
  RefPtr<nsFrameLoader> frameLoader = popupFrameElement->GetFrameLoader();
  NS_ENSURE_TRUE(frameLoader, BrowserElementParent::OPEN_WINDOW_IGNORED);

  nsCOMPtr<nsIDocShell> docshell;
  frameLoader->GetDocShell(getter_AddRefs(docshell));
  NS_ENSURE_TRUE(docshell, BrowserElementParent::OPEN_WINDOW_IGNORED);

  nsCOMPtr<nsPIDOMWindowOuter> window = docshell->GetWindow();
  window.forget(aReturnWindow);

  return !!*aReturnWindow ? opened : BrowserElementParent::OPEN_WINDOW_CANCELLED;
}