--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -172,16 +172,17 @@
@BINPATH@/components/dom_notification.xpt
@BINPATH@/components/dom_html.xpt
@BINPATH@/components/dom_indexeddb.xpt
@BINPATH@/components/dom_offline.xpt
@BINPATH@/components/dom_json.xpt
#ifdef MOZ_B2G_RIL
@BINPATH@/components/dom_mms.xpt
#endif
+@BINPATH@/components/dom_browserelement.xpt
@BINPATH@/components/dom_power.xpt
@BINPATH@/components/dom_range.xpt
@BINPATH@/components/dom_settings.xpt
@BINPATH@/components/dom_sidebar.xpt
@BINPATH@/components/dom_sms.xpt
@BINPATH@/components/dom_storage.xpt
@BINPATH@/components/dom_stylesheets.xpt
@BINPATH@/components/dom_threads.xpt
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -183,16 +183,17 @@
@BINPATH@/components/dom_notification.xpt
@BINPATH@/components/dom_html.xpt
@BINPATH@/components/dom_indexeddb.xpt
@BINPATH@/components/dom_offline.xpt
@BINPATH@/components/dom_json.xpt
#ifdef MOZ_B2G_RIL
@BINPATH@/components/dom_mms.xpt
#endif
+@BINPATH@/components/dom_browserelement.xpt
@BINPATH@/components/dom_power.xpt
@BINPATH@/components/dom_range.xpt
@BINPATH@/components/dom_settings.xpt
@BINPATH@/components/dom_sidebar.xpt
@BINPATH@/components/dom_sms.xpt
@BINPATH@/components/dom_storage.xpt
@BINPATH@/components/dom_stylesheets.xpt
@BINPATH@/components/dom_traversal.xpt
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -2206,8 +2206,16 @@ nsFrameLoader::GetTabChildGlobalAsEventT
NS_IMETHODIMP
nsFrameLoader::GetOwnerElement(nsIDOMElement **aElement)
{
nsCOMPtr<nsIDOMElement> ownerElement = do_QueryInterface(mOwnerContent);
ownerElement.forget(aElement);
return NS_OK;
}
+
+void
+nsFrameLoader::SetRemoteBrowser(nsITabParent* aTabParent)
+{
+ MOZ_ASSERT(!mRemoteBrowser);
+ MOZ_ASSERT(!mCurrentRemoteFrame);
+ mRemoteBrowser = static_cast<TabParent*>(aTabParent);
+}
--- a/content/base/src/nsFrameLoader.h
+++ b/content/base/src/nsFrameLoader.h
@@ -22,16 +22,17 @@
#include "Layers.h"
#include "mozilla/dom/Element.h"
class nsIURI;
class nsSubDocumentFrame;
class nsIView;
class nsIInProcessContentFrameMessageManager;
class AutoResetInShow;
+class nsITabParent;
namespace mozilla {
namespace dom {
class PBrowserParent;
class TabParent;
}
namespace layout {
@@ -251,16 +252,26 @@ public:
}
nsFrameMessageManager* GetFrameMessageManager() { return mMessageManager; }
mozilla::dom::Element* GetOwnerContent() { return mOwnerContent; }
bool ShouldClipSubdocument() { return mClipSubdocument; }
bool ShouldClampScrollPosition() { return mClampScrollPosition; }
+ /**
+ * Tell this FrameLoader to use a particular remote browser.
+ *
+ * This will assert if mRemoteBrowser or mCurrentRemoteFrame is non-null. In
+ * practice, this means you can't have successfully run TryRemoteBrowser() on
+ * this object, which means you can't have called ShowRemoteFrame() or
+ * ReallyStartLoading().
+ */
+ void SetRemoteBrowser(nsITabParent* aTabParent);
+
private:
void SetOwnerContent(mozilla::dom::Element* aContent);
bool ShouldUseRemoteProcess();
/**
* Is this a frameloader for a bona fide <iframe mozbrowser>? (I.e., does
--- a/content/html/content/src/nsGenericHTMLFrameElement.cpp
+++ b/content/html/content/src/nsGenericHTMLFrameElement.cpp
@@ -93,31 +93,41 @@ nsGenericHTMLFrameElement::GetContentWin
"Uh, this window should always be an outer window!");
return CallQueryInterface(win, aContentWindow);
}
nsresult
nsGenericHTMLFrameElement::EnsureFrameLoader()
{
- if (!GetParent() || !IsInDoc() || mFrameLoader) {
+ if (!GetParent() || !IsInDoc() || mFrameLoader || mFrameLoaderCreationDisallowed) {
// If frame loader is there, we just keep it around, cached
return NS_OK;
}
mFrameLoader = nsFrameLoader::Create(this, mNetworkCreated);
if (!mFrameLoader) {
// Strangely enough, this method doesn't actually ensure that the
// frameloader exists. It's more of a best-effort kind of thing.
return NS_OK;
}
return NS_OK;
}
+nsresult
+nsGenericHTMLFrameElement::CreateRemoteFrameLoader(nsITabParent* aTabParent)
+{
+ MOZ_ASSERT(!mFrameLoader);
+ EnsureFrameLoader();
+ NS_ENSURE_STATE(mFrameLoader);
+ mFrameLoader->SetRemoteBrowser(aTabParent);
+ return NS_OK;
+}
+
NS_IMETHODIMP
nsGenericHTMLFrameElement::GetFrameLoader(nsIFrameLoader **aFrameLoader)
{
NS_IF_ADDREF(*aFrameLoader = mFrameLoader);
return NS_OK;
}
NS_IMETHODIMP_(already_AddRefed<nsFrameLoader>)
@@ -291,8 +301,26 @@ nsGenericHTMLFrameElement::GetReallyIsBr
"dom.mozBrowserFramesWhitelist")) {
return NS_OK;
}
// Otherwise, succeed.
*aOut = true;
return NS_OK;
}
+
+NS_IMETHODIMP
+nsGenericHTMLFrameElement::DisallowCreateFrameLoader()
+{
+ MOZ_ASSERT(!mFrameLoader);
+ MOZ_ASSERT(!mFrameLoaderCreationDisallowed);
+ mFrameLoaderCreationDisallowed = true;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGenericHTMLFrameElement::AllowCreateFrameLoader()
+{
+ MOZ_ASSERT(!mFrameLoader);
+ MOZ_ASSERT(mFrameLoaderCreationDisallowed);
+ mFrameLoaderCreationDisallowed = false;
+ return NS_OK;
+}
--- a/content/html/content/src/nsGenericHTMLFrameElement.h
+++ b/content/html/content/src/nsGenericHTMLFrameElement.h
@@ -20,16 +20,17 @@ class nsGenericHTMLFrameElement : public
public nsIMozBrowserFrame
{
public:
nsGenericHTMLFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
mozilla::dom::FromParser aFromParser)
: nsGenericHTMLElement(aNodeInfo)
, mNetworkCreated(aFromParser == mozilla::dom::FROM_PARSER_NETWORK)
, mBrowserFrameListenersRegistered(false)
+ , mFrameLoaderCreationDisallowed(false)
{
}
virtual ~nsGenericHTMLFrameElement();
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
NS_DECL_NSIFRAMELOADEROWNER
NS_DECL_NSIDOMMOZBROWSERFRAME
@@ -94,9 +95,10 @@ protected:
nsRefPtr<nsFrameLoader> mFrameLoader;
// True when the element is created by the parser
// using NS_FROM_PARSER_NETWORK flag.
// If the element is modified, it may lose the flag.
bool mNetworkCreated;
bool mBrowserFrameListenersRegistered;
+ bool mFrameLoaderCreationDisallowed;
};
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -516,28 +516,28 @@ using mozilla::dom::indexedDB::IDBWrappe
#ifdef MOZ_B2G_BT
#include "BluetoothManager.h"
#include "BluetoothAdapter.h"
#endif
#include "DOMError.h"
#include "DOMRequest.h"
+#include "nsIOpenWindowEventDetail.h"
+#include "nsIDOMGlobalObjectConstructor.h"
#include "DOMFileHandle.h"
#include "FileRequest.h"
#include "LockedFile.h"
#include "mozilla/Likely.h"
#undef None // something included above defines this preprocessor symbol, maybe Xlib headers
#include "WebGLContext.h"
-#include "nsIDOMGlobalObjectConstructor.h"
-
using namespace mozilla;
using namespace mozilla::dom;
static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
static const char kDOMStringBundleURL[] =
"chrome://global/locale/dom/dom.properties";
@@ -1658,16 +1658,18 @@ static nsDOMClassInfoData sClassInfoData
EVENTTARGET_SCRIPTABLE_FLAGS)
#endif
NS_DEFINE_CLASSINFO_DATA(DOMError, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(DOMRequest, nsEventTargetSH,
EVENTTARGET_SCRIPTABLE_FLAGS)
+ NS_DEFINE_CLASSINFO_DATA(OpenWindowEventDetail, nsDOMGenericSH,
+ DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA_WITH_NAME(DOMFileHandle, FileHandle, nsEventTargetSH,
EVENTTARGET_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(FileRequest, nsEventTargetSH,
EVENTTARGET_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(LockedFile, nsEventTargetSH,
EVENTTARGET_SCRIPTABLE_FLAGS)
};
@@ -4521,16 +4523,20 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMError)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(DOMRequest, nsIDOMDOMRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
DOM_CLASSINFO_MAP_END
+ DOM_CLASSINFO_MAP_BEGIN(OpenWindowEventDetail, nsIOpenWindowEventDetail)
+ DOM_CLASSINFO_MAP_ENTRY(nsIOpenWindowEventDetail)
+ DOM_CLASSINFO_MAP_END
+
DOM_CLASSINFO_MAP_BEGIN(DOMFileHandle, nsIDOMFileHandle)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMFileHandle)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(FileRequest, nsIDOMFileRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMFileRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -527,12 +527,13 @@ DOMCI_CLASS(CallEvent)
#ifdef MOZ_B2G_BT
DOMCI_CLASS(BluetoothManager)
DOMCI_CLASS(BluetoothAdapter)
#endif
DOMCI_CLASS(DOMError)
DOMCI_CLASS(DOMRequest)
+DOMCI_CLASS(OpenWindowEventDetail)
DOMCI_CLASS(DOMFileHandle)
DOMCI_CLASS(FileRequest)
DOMCI_CLASS(LockedFile)
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -8291,20 +8291,18 @@ nsGlobalWindow::GetInterface(const nsIID
*aSink = webNav;
NS_ADDREF(((nsISupports *) *aSink));
}
}
}
else if (aIID.Equals(NS_GET_IID(nsIDocShell))) {
FORWARD_TO_OUTER(GetInterface, (aIID, aSink), NS_ERROR_NOT_INITIALIZED);
- nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(mDocShell);
- if (docShell) {
- docShell.forget(aSink);
- }
+ nsCOMPtr<nsIDocShell> docShell = mDocShell;
+ docShell.forget(aSink);
}
#ifdef NS_PRINTING
else if (aIID.Equals(NS_GET_IID(nsIWebBrowserPrint))) {
FORWARD_TO_OUTER(GetInterface, (aIID, aSink), NS_ERROR_NOT_INITIALIZED);
if (mDocShell) {
nsCOMPtr<nsIContentViewer> viewer;
mDocShell->GetContentViewer(getter_AddRefs(viewer));
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/BrowserElementParent.cpp
@@ -0,0 +1,209 @@
+/* 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 "TabParent.h"
+
+// TabParent.h transitively includes <windows.h>, which does
+// #define CreateEvent CreateEventW
+// That messes up our call to nsEventDispatcher::CreateEvent below.
+
+#ifdef CreateEvent
+#undef CreateEvent
+#endif
+
+#include "BrowserElementParent.h"
+#include "nsHTMLIFrameElement.h"
+#include "nsOpenWindowEventDetail.h"
+#include "nsEventDispatcher.h"
+#include "nsIDOMCustomEvent.h"
+#include "nsVariant.h"
+
+using mozilla::dom::Element;
+using mozilla::dom::TabParent;
+
+namespace {
+
+/**
+ * Create an <iframe mozbrowser> owned by the same document as
+ * aOpenerFrameElement.
+ */
+already_AddRefed<nsHTMLIFrameElement>
+CreateIframe(Element* aOpenerFrameElement)
+{
+ nsNodeInfoManager *nodeInfoManager =
+ aOpenerFrameElement->OwnerDoc()->NodeInfoManager();
+
+ nsCOMPtr<nsINodeInfo> nodeInfo =
+ nodeInfoManager->GetNodeInfo(nsGkAtoms::iframe,
+ /* aPrefix = */ nsnull,
+ kNameSpaceID_XHTML,
+ nsIDOMNode::ELEMENT_NODE);
+
+ nsRefPtr<nsHTMLIFrameElement> popupFrameElement =
+ static_cast<nsHTMLIFrameElement*>(
+ NS_NewHTMLIFrameElement(nodeInfo.forget(), mozilla::dom::NOT_FROM_PARSER));
+
+ popupFrameElement->SetMozbrowser(true);
+
+ // Copy the opener frame's mozapp attribute to the popup frame.
+ if (aOpenerFrameElement->HasAttr(kNameSpaceID_None, nsGkAtoms::mozapp)) {
+ nsAutoString mozapp;
+ aOpenerFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::mozapp, mozapp);
+ popupFrameElement->SetAttr(kNameSpaceID_None, nsGkAtoms::mozapp,
+ mozapp, /* aNotify = */ false);
+ }
+
+ return popupFrameElement.forget();
+}
+
+/**
+ * Dispatch a mozbrowseropenwindow event to the given opener frame element.
+ * The "popup iframe" (event.detail.frameElement) will be |aPopupFrameElement|.
+ *
+ * Returns true iff there were no unexpected failures and the window.open call
+ * was accepted by the embedder.
+ */
+bool
+DispatchOpenWindowEvent(Element* aOpenerFrameElement,
+ Element* aPopupFrameElement,
+ const nsAString& aURL,
+ const nsAString& aName,
+ const nsAString& aFeatures)
+{
+ // Dispatch a CustomEvent at aOpenerFrameElement with a detail object
+ // (nsIOpenWindowEventDetail) containing aPopupFrameElement, aURL, aName, and
+ // aFeatures.
+
+ // Create the event's detail object.
+ nsRefPtr<nsOpenWindowEventDetail> detail =
+ new nsOpenWindowEventDetail(aURL, aName, aFeatures,
+ aPopupFrameElement->AsDOMNode());
+ nsCOMPtr<nsIWritableVariant> detailVariant = new nsVariant();
+ nsresult rv = detailVariant->SetAsISupports(detail);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ // Create the CustomEvent.
+ nsIPresShell *shell = aOpenerFrameElement->OwnerDoc()->GetShell();
+ nsRefPtr<nsPresContext> presContext;
+ if (shell) {
+ presContext = shell->GetPresContext();
+ }
+
+ nsCOMPtr<nsIDOMEvent> domEvent;
+ nsEventDispatcher::CreateEvent(presContext, nsnull,
+ NS_LITERAL_STRING("customevent"),
+ getter_AddRefs(domEvent));
+ NS_ENSURE_TRUE(domEvent, false);
+
+ nsCOMPtr<nsIDOMCustomEvent> customEvent = do_QueryInterface(domEvent);
+ NS_ENSURE_TRUE(customEvent, false);
+ customEvent->InitCustomEvent(NS_LITERAL_STRING("mozbrowseropenwindow"),
+ /* bubbles = */ true,
+ /* cancelable = */ false,
+ detailVariant);
+ customEvent->SetTrusted(true);
+
+ // Dispatch the event.
+ nsEventStatus status = nsEventStatus_eIgnore;
+ rv = nsEventDispatcher::DispatchDOMEvent(aOpenerFrameElement, nsnull,
+ domEvent, presContext, &status);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ // If the iframe is not in some document's DOM at this point, the embedder
+ // has "blocked" the popup.
+ return aPopupFrameElement->IsInDoc();
+}
+
+} // anonymous namespace
+
+namespace mozilla {
+
+/*static*/ bool
+BrowserElementParent::OpenWindowOOP(mozilla::dom::TabParent* aOpenerTabParent,
+ mozilla::dom::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 =
+ do_QueryInterface(aOpenerTabParent->GetOwnerElement());
+ NS_ENSURE_TRUE(openerFrameElement, false);
+ nsRefPtr<nsHTMLIFrameElement> popupFrameElement =
+ CreateIframe(openerFrameElement);
+
+ // 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();
+
+ bool dispatchSucceeded =
+ DispatchOpenWindowEvent(openerFrameElement, popupFrameElement,
+ aURL, aName, aFeatures);
+ if (!dispatchSucceeded) {
+ return false;
+ }
+
+ // 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 true;
+}
+
+/* static */ bool
+BrowserElementParent::OpenWindowInProcess(nsIDOMWindow* aOpenerWindow,
+ nsIURI* aURI,
+ const nsAString& aName,
+ const nsACString& aFeatures,
+ nsIDOMWindow** aReturnWindow)
+{
+ *aReturnWindow = NULL;
+
+ nsCOMPtr<nsIDOMElement> openerFrameDOMElement;
+ aOpenerWindow->GetFrameElement(getter_AddRefs(openerFrameDOMElement));
+ NS_ENSURE_TRUE(openerFrameDOMElement, false);
+
+ nsCOMPtr<nsINode> openerFrameNode = do_QueryInterface(openerFrameDOMElement);
+ nsRefPtr<Element> openerFrameElement = openerFrameNode->AsElement();
+
+ nsRefPtr<nsHTMLIFrameElement> popupFrameElement =
+ CreateIframe(openerFrameElement);
+ NS_ENSURE_TRUE(popupFrameElement, false);
+
+ nsCAutoString spec;
+ aURI->GetSpec(spec);
+ bool dispatchSucceeded =
+ DispatchOpenWindowEvent(openerFrameElement, popupFrameElement,
+ NS_ConvertUTF8toUTF16(spec),
+ aName,
+ NS_ConvertUTF8toUTF16(aFeatures));
+ if (!dispatchSucceeded) {
+ return false;
+ }
+
+ // Return popupFrameElement's window.
+ nsCOMPtr<nsIFrameLoader> frameLoader;
+ popupFrameElement->GetFrameLoader(getter_AddRefs(frameLoader));
+ NS_ENSURE_TRUE(frameLoader, false);
+
+ nsCOMPtr<nsIDocShell> docshell;
+ frameLoader->GetDocShell(getter_AddRefs(docshell));
+ NS_ENSURE_TRUE(docshell, false);
+
+ nsCOMPtr<nsIDOMWindow> window = do_GetInterface(docshell);
+ window.forget(aReturnWindow);
+ return !!*aReturnWindow;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/BrowserElementParent.h
@@ -0,0 +1,89 @@
+/* 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_BrowserElementHelpers_h
+#define mozilla_BrowserElementHelpers_h
+
+#include "nsAString.h"
+
+class nsIDOMWindow;
+class nsIURI;
+
+namespace mozilla {
+
+namespace dom {
+class TabParent;
+}
+
+/**
+ * BrowserElementParent implements a portion of the parent-process side of
+ * <iframe mozbrowser>.
+ *
+ * Most of the parent-process side of <iframe mozbrowser> is implemented in
+ * BrowserElementParent.js. This file implements the few parts of this
+ * functionality which must be written in C++.
+ *
+ * We don't communicate with the JS code that lives in BrowserElementParent.js;
+ * the JS and C++ parts are completely separate.
+ */
+class BrowserElementParent
+{
+public:
+ /**
+ * Handle a window.open call from an out-of-process <iframe mozbrowser>.
+ *
+ * window.open inside <iframe mozbrowser> doesn't actually open a new
+ * top-level window. Instead, the "embedder" (the document which contains
+ * the <iframe mozbrowser> whose content called window.open) gets the
+ * opportunity to place a new <iframe mozbrowser> in the DOM somewhere. This
+ * new "popup" iframe acts as the opened window.
+ *
+ * This method proceeds in three steps.
+ *
+ * 1) We fire a mozbrowseropenwindow CustomEvent on the opener
+ * iframe element. This event's detail is an instance of
+ * nsIOpenWindowEventDetail.
+ *
+ * 2) The embedder (the document which contains the opener iframe) can accept
+ * the window.open request by inserting event.detail.frameElement (an iframe
+ * element) into the DOM somewhere.
+ *
+ * 3) If the embedder accepted the window.open request, we return true and
+ * set aPopupTabParent's frame element to event.detail.frameElement.
+ * Otherwise, we return false.
+ *
+ * @param aOpenerTabParent the TabParent whose TabChild called window.open.
+ * @param aPopupTabParent the TabParent inside which the opened window will
+ * live.
+ * @return true on success, false otherwise. Failure is not (necessarily)
+ * an error; it may indicate that the embedder simply rejected the
+ * window.open request.
+ */
+ static bool
+ OpenWindowOOP(mozilla::dom::TabParent* aOpenerTabParent,
+ mozilla::dom::TabParent* aPopupTabParent,
+ const nsAString& aURL,
+ const nsAString& aName,
+ const nsAString& aFeatures);
+
+ /**
+ * Handle a window.open call from an in-process <iframe mozbrowser>.
+ *
+ * As with OpenWindowOOP, we return true if the window.open request
+ * succeeded, and return false if the embedder denied the request.
+ *
+ * (These parameter types are silly, but they match what our caller has in
+ * hand. Feel free to add an override, if they are inconvenient to you.)
+ */
+ static bool
+ OpenWindowInProcess(nsIDOMWindow* aOpenerWindow,
+ nsIURI* aURI,
+ const nsAString& aName,
+ const nsACString& aFeatures,
+ nsIDOMWindow** aReturnWindow);
+};
+
+} // namespace mozilla
+
+#endif
--- a/dom/browser-element/Makefile.in
+++ b/dom/browser-element/Makefile.in
@@ -2,24 +2,56 @@
# 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/.
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
-relativesrcdir = dom/browser-element
-
include $(DEPTH)/config/autoconf.mk
+MODULE = dom
+LIBRARY_NAME = dom_browserelement_s
+XPIDL_MODULE = dom_browserelement
+LIBXUL_LIBRARY = 1
+FORCE_STATIC_LIB = 1
+
+include $(topsrcdir)/dom/dom-config.mk
+
TEST_DIRS += mochitest
+XPIDLSRCS = \
+ nsIOpenWindowEventDetail.idl \
+ $(NULL)
+
+EXPORTS = \
+ nsOpenWindowEventDetail.h \
+ $(NULL)
+
+EXPORTS_NAMESPACES = mozilla
+EXPORTS_mozilla = \
+ BrowserElementParent.h \
+ $(NULL)
+
+CPPSRCS = \
+ nsOpenWindowEventDetail.cpp \
+ BrowserElementParent.cpp \
+ $(NULL)
+
EXTRA_COMPONENTS = \
BrowserElementParent.js \
BrowserElementParent.manifest \
$(NULL)
EXTRA_JS_MODULES = \
BrowserElementPromptService.jsm \
$(NULL)
+include $(topsrcdir)/config/config.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
include $(topsrcdir)/config/rules.mk
+
+INCLUDES += \
+ -I$(topsrcdir)/dom/base \
+ -I$(topsrcdir)/dom/ipc \
+ -I$(topsrcdir)/content/base/src \
+ $(NULL)
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/nsIOpenWindowEventDetail.idl
@@ -0,0 +1,20 @@
+/* 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 "nsISupports.idl"
+
+interface nsIDOMNode;
+
+/**
+ * When we send a mozbrowseropenwindow event (an instance of CustomEvent), we
+ * use an instance of this interface as the event's detail.
+ */
+[scriptable, uuid(94377af6-956a-4adf-908b-363f7023ae1a)]
+interface nsIOpenWindowEventDetail : nsISupports
+{
+ readonly attribute AString url;
+ readonly attribute AString name;
+ readonly attribute AString features;
+ readonly attribute nsIDOMNode frameElement;
+};
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/nsOpenWindowEventDetail.cpp
@@ -0,0 +1,49 @@
+/* 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 "nsOpenWindowEventDetail.h"
+#include "nsDOMClassInfoID.h"
+#include "nsIDOMClassInfo.h"
+#include "nsIClassInfo.h"
+#include "nsDOMClassInfo.h"
+
+NS_IMPL_CYCLE_COLLECTION_1(nsOpenWindowEventDetail, mFrameElement)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsOpenWindowEventDetail)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsOpenWindowEventDetail)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsOpenWindowEventDetail)
+ NS_INTERFACE_MAP_ENTRY(nsISupports)
+ NS_INTERFACE_MAP_ENTRY(nsIOpenWindowEventDetail)
+ NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(OpenWindowEventDetail)
+NS_INTERFACE_MAP_END
+
+DOMCI_DATA(OpenWindowEventDetail, nsOpenWindowEventDetail)
+
+NS_IMETHODIMP
+nsOpenWindowEventDetail::GetUrl(nsAString& aOut)
+{
+ aOut.Assign(mURL);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsOpenWindowEventDetail::GetName(nsAString& aOut)
+{
+ aOut.Assign(mName);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsOpenWindowEventDetail::GetFeatures(nsAString& aOut)
+{
+ aOut.Assign(mFeatures);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsOpenWindowEventDetail::GetFrameElement(nsIDOMNode** aOut)
+{
+ nsCOMPtr<nsIDOMNode> out = mFrameElement;
+ out.forget(aOut);
+ return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/nsOpenWindowEventDetail.h
@@ -0,0 +1,39 @@
+/* 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 "nsIOpenWindowEventDetail.h"
+#include "nsIDOMNode.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+/**
+ * When we send a mozbrowseropenwindow event (an instance of CustomEvent), we
+ * use an instance of this class as the event's detail.
+ */
+class nsOpenWindowEventDetail : public nsIOpenWindowEventDetail
+{
+public:
+ nsOpenWindowEventDetail(const nsAString& aURL,
+ const nsAString& aName,
+ const nsAString& aFeatures,
+ nsIDOMNode* aFrameElement)
+ : mURL(aURL)
+ , mName(aName)
+ , mFeatures(aFeatures)
+ , mFrameElement(aFrameElement)
+ {}
+
+ virtual ~nsOpenWindowEventDetail() {}
+
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_CLASS(nsOpenWindowEventDetail)
+ NS_DECL_NSIOPENWINDOWEVENTDETAIL
+
+private:
+ const nsString mURL;
+ const nsString mName;
+ const nsString mFeatures;
+ nsCOMPtr<nsIDOMNode> mFrameElement;
+};
--- a/dom/interfaces/html/nsIMozBrowserFrame.idl
+++ b/dom/interfaces/html/nsIMozBrowserFrame.idl
@@ -2,20 +2,46 @@
/* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=2: */
/* 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 "nsIDOMMozBrowserFrame.idl"
-[scriptable, uuid(076AD76C-2DF6-4760-B914-21D554F0A2B6)]
+interface nsITabParent;
+
+[scriptable, uuid(0acd92dd-2902-48ee-adcf-082d3bb3ec45)]
interface nsIMozBrowserFrame : nsIDOMMozBrowserFrame
{
/**
* Gets whether this frame really is a browser frame.
*
* In order to really be a browser frame, this frame's
* nsIDOMMozBrowserFrame::mozbrowser attribute must be true, and the frame
* may have to pass various security checks.
*/
readonly attribute boolean reallyIsBrowser;
+
+ /**
+ * Normally, a frame tries to create its frame loader when its src is
+ * modified, or its contentWindow is accessed.
+ *
+ * disallowCreateFrameLoader prevents the frame element from creating its
+ * frame loader (in the same way that not being inside a document prevents the
+ * creation of a frame loader). allowCreateFrameLoader lifts this restriction.
+ *
+ * These methods are not re-entrant -- it is an error to call
+ * disallowCreateFrameLoader twice without first calling allowFrameLoader.
+ *
+ * It's also an error to call either method if we already have a frame loader.
+ */
+ void disallowCreateFrameLoader();
+ void allowCreateFrameLoader();
+
+ /**
+ * Create a remote (i.e., out-of-process) frame loader attached to the given
+ * tab parent.
+ *
+ * It is an error to call this method if we already have a frame loader.
+ */
+ void createRemoteFrameLoader(in nsITabParent aTabParent);
};
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -200,16 +200,31 @@ parent:
* has already been cached (stickDocument=false).
*/
POfflineCacheUpdate(URI manifestURI, URI documentURI, nsCString clientID,
bool stickDocument);
sync PIndexedDB(nsCString asciiOrigin)
returns (bool allowed);
+ /**
+ * window.open from inside <iframe mozbrowser> is special. When the child
+ * process calls window.open, it creates a new PBrowser (in its own
+ * process), then calls BrowserFrameOpenWindow on it.
+ *
+ * The parent process gets a chance to accept or reject the window.open
+ * call, and windowOpened is set to true if we ended up going through with
+ * the window.open.
+ *
+ * @param opener the PBrowser whose content called window.open.
+ */
+ sync BrowserFrameOpenWindow(PBrowser opener, nsString aURL,
+ nsString aName, nsString aFeatures)
+ returns (bool windowOpened);
+
__delete__();
child:
/**
* Notify the remote browser that it has been Show()n on this
* side, with the given |visibleRect|. This message is expected
* to trigger creation of the remote browser's "widget".
*
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -72,19 +72,26 @@ rpc protocol PContent
manages PExternalHelperApp;
manages PHal;
manages PMemoryReportRequest;
manages PNecko;
manages PSms;
manages PStorage;
manages PTestShell;
+both:
+ // Depending on exactly how the new browser is being created, it might be
+ // created from either the child or parent process!
+ //
+ // The child creates the PBrowser as part of
+ // TabChild::BrowserFrameProvideWindow, and the parent creates the PBrowser
+ // as part of ContentParent::CreateTab.
+ async PBrowser(PRUint32 chromeFlags);
+
child:
- PBrowser(PRUint32 chromeFlags);
-
PMemoryReportRequest();
PTestShell();
RegisterChrome(ChromePackage[] packages, ResourceMapping[] resources,
OverrideMapping[] overrides, nsCString locale);
async SetOffline(bool offline);
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -1,10 +1,10 @@
/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*- */
-/* vim: set sw=4 ts=8 et tw=80 : */
+/* vim: set sw=2 sts=2 ts=8 et tw=80 : */
/* 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 "TabChild.h"
#include "mozilla/IntentionalCrash.h"
#include "mozilla/dom/PContentChild.h"
#include "mozilla/dom/PContentDialogChild.h"
@@ -88,16 +88,17 @@ public:
TabChild::TabChild(PRUint32 aChromeFlags)
: mRemoteFrame(nsnull)
, mTabChildGlobal(nsnull)
, mChromeFlags(aChromeFlags)
, mOuterRect(0, 0, 0, 0)
, mLastBackgroundColor(NS_RGB(255, 255, 255))
+ , mDidFakeShow(false)
{
printf("creating %d!\n", NS_IsMainThread());
}
nsresult
TabChild::Init()
{
nsCOMPtr<nsIWebBrowser> webBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID);
@@ -326,28 +327,85 @@ TabChild::ProvideWindow(nsIDOMWindow* aP
bool aCalledFromJS,
bool aPositionSpecified, bool aSizeSpecified,
nsIURI* aURI, const nsAString& aName,
const nsACString& aFeatures, bool* aWindowIsNew,
nsIDOMWindow** aReturn)
{
*aReturn = nsnull;
+ // If aParent is inside an <iframe mozbrowser> and this isn't a request to
+ // open a modal-type window, we're going to create a new <iframe mozbrowser>
+ // and return its window here.
+ nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent);
+ bool inBrowserFrame = false;
+ if (docshell) {
+ docshell->GetContainedInBrowserFrame(&inBrowserFrame);
+ }
+
+ if (inBrowserFrame &&
+ !(aChromeFlags & (nsIWebBrowserChrome::CHROME_MODAL |
+ nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
+ nsIWebBrowserChrome::CHROME_OPENAS_CHROME))) {
+
+ // Note that BrowserFrameProvideWindow may return NS_ERROR_ABORT if the
+ // open window call was canceled. It's important that we pass this error
+ // code back to our caller.
+ return BrowserFrameProvideWindow(aParent, aURI, aName, aFeatures,
+ aWindowIsNew, aReturn);
+ }
+
+ // Otherwise, create a new top-level window.
PBrowserChild* newChild;
if (!CallCreateWindow(&newChild)) {
return NS_ERROR_NOT_AVAILABLE;
}
*aWindowIsNew = true;
nsCOMPtr<nsIDOMWindow> win =
do_GetInterface(static_cast<TabChild*>(newChild)->mWebNav);
win.forget(aReturn);
return NS_OK;
}
+nsresult
+TabChild::BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
+ nsIURI* aURI,
+ const nsAString& aName,
+ const nsACString& aFeatures,
+ bool* aWindowIsNew,
+ nsIDOMWindow** aReturn)
+{
+ *aReturn = nsnull;
+
+ nsRefPtr<TabChild> newChild =
+ static_cast<TabChild*>(Manager()->SendPBrowserConstructor(0));
+
+ nsCAutoString spec;
+ aURI->GetSpec(spec);
+
+ NS_ConvertUTF8toUTF16 url(spec);
+ nsString name(aName);
+ NS_ConvertUTF8toUTF16 features(aFeatures);
+ newChild->SendBrowserFrameOpenWindow(this, url, name,
+ features, aWindowIsNew);
+ if (!*aWindowIsNew) {
+ PBrowserChild::Send__delete__(newChild);
+ return NS_ERROR_ABORT;
+ }
+
+ // Unfortunately we don't get a window unless we've shown the frame. That's
+ // pretty bogus; see bug 763602.
+ newChild->DoFakeShow();
+
+ nsCOMPtr<nsIDOMWindow> win = do_GetInterface(newChild->mWebNav);
+ win.forget(aReturn);
+ return NS_OK;
+}
+
static nsInterfaceHashtable<nsPtrHashKey<PContentDialogChild>, nsIDialogParamBlock> gActiveDialogs;
NS_IMETHODIMP
TabChild::OpenDialog(PRUint32 aType, const nsACString& aName,
const nsACString& aFeatures,
nsIDialogParamBlock* aArguments,
nsIDOMElement* aFrameElement)
{
@@ -478,19 +536,30 @@ TabChild::RecvLoadURL(const nsCString& u
NULL, NULL, NULL);
if (NS_FAILED(rv)) {
NS_WARNING("mWebNav->LoadURI failed. Eating exception, what else can I do?");
}
return true;
}
+void
+TabChild::DoFakeShow()
+{
+ RecvShow(nsIntSize(0, 0));
+ mDidFakeShow = true;
+}
+
bool
TabChild::RecvShow(const nsIntSize& size)
{
+ if (mDidFakeShow) {
+ return true;
+ }
+
printf("[TabChild] SHOW (w,h)= (%d, %d)\n", size.width, size.height);
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(mWebNav);
if (!baseWindow) {
NS_ERROR("mWebNav doesn't QI to nsIBaseWindow");
return false;
}
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -241,23 +241,35 @@ protected:
private:
void ActorDestroy(ActorDestroyReason why);
bool InitTabChildGlobal();
bool InitWidget(const nsIntSize& size);
void DestroyWindow();
+ // Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow().
+ void DoFakeShow();
+
+ nsresult
+ BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
+ nsIURI* aURI,
+ const nsAString& aName,
+ const nsACString& aFeatures,
+ bool* aWindowIsNew,
+ nsIDOMWindow** aReturn);
+
nsCOMPtr<nsIWebNavigation> mWebNav;
nsCOMPtr<nsIWidget> mWidget;
RenderFrameChild* mRemoteFrame;
nsRefPtr<TabChildGlobal> mTabChildGlobal;
PRUint32 mChromeFlags;
nsIntRect mOuterRect;
nscolor mLastBackgroundColor;
+ bool mDidFakeShow;
DISALLOW_EVIL_CONSTRUCTORS(TabChild);
};
inline TabChild*
GetTabChildFrom(nsIDocShell* aDocShell)
{
nsCOMPtr<nsITabChild> tc = do_GetInterface(aDocShell);
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -33,16 +33,17 @@
#include "nsSerializationHelper.h"
#include "nsIPromptFactory.h"
#include "nsIContent.h"
#include "nsIWidget.h"
#include "nsIViewManager.h"
#include "mozilla/unused.h"
#include "nsDebug.h"
#include "nsPrintfCString.h"
+#include "mozilla/BrowserElementParent.h"
#include "IndexedDBParent.h"
#include "IDBFactory.h"
using namespace mozilla::dom;
using namespace mozilla::ipc;
using namespace mozilla::layout;
using namespace mozilla::widget;
using namespace mozilla::dom::indexedDB;
@@ -917,10 +918,23 @@ TabParent::GetWidget() const
nsIFrame *frame = content->GetPrimaryFrame();
if (!frame)
return nsnull;
nsCOMPtr<nsIWidget> widget = frame->GetNearestWidget();
return widget.forget();
}
+bool
+TabParent::RecvBrowserFrameOpenWindow(PBrowserParent* aOpener,
+ const nsString& aURL,
+ const nsString& aName,
+ const nsString& aFeatures,
+ bool* aOutWindowOpened)
+{
+ *aOutWindowOpened =
+ BrowserElementParent::OpenWindowOOP(static_cast<TabParent*>(aOpener),
+ this, aURL, aName, aFeatures);
+ return true;
+}
+
} // namespace tabs
} // namespace mozilla
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -47,17 +47,21 @@ public:
void SetBrowserDOMWindow(nsIBrowserDOMWindow* aBrowserDOMWindow) {
mBrowserDOMWindow = aBrowserDOMWindow;
}
void Destroy();
virtual bool RecvMoveFocus(const bool& aForward);
virtual bool RecvEvent(const RemoteDOMEvent& aEvent);
-
+ virtual bool RecvBrowserFrameOpenWindow(PBrowserParent* aOpener,
+ const nsString& aURL,
+ const nsString& aName,
+ const nsString& aFeatures,
+ bool* aOutWindowOpened);
virtual bool AnswerCreateWindow(PBrowserParent** retval);
virtual bool RecvSyncMessage(const nsString& aMessage,
const nsString& aJSON,
InfallibleTArray<nsString>* aJSONRetVal);
virtual bool RecvAsyncMessage(const nsString& aMessage,
const nsString& aJSON);
virtual bool RecvNotifyIMEFocus(const bool& aFocus,
nsIMEUpdatePreference* aPreference,
--- a/embedding/base/nsIWindowProvider.idl
+++ b/embedding/base/nsIWindowProvider.idl
@@ -72,16 +72,19 @@ interface nsIWindowProvider : nsISupport
* before the provideWindow() call. The value of this
* out parameter is meaningless if provideWindow()
* returns null.
* @return A window the caller should use or null if the caller should just
* create a new window. The returned window may be newly opened by
* the nsIWindowProvider implementation or may be a window that
* already existed.
*
+ * @throw NS_ERROR_ABORT if the caller should cease its attempt to open a new
+ * window.
+ *
* @see nsIWindowWatcher for more information on aFeatures.
* @see nsIWebBrowserChrome for more information on aChromeFlags.
*/
nsIDOMWindow provideWindow(in nsIDOMWindow aParent,
in unsigned long aChromeFlags,
in boolean aCalledFromJS,
in boolean aPositionSpecified,
in boolean aSizeSpecified,
--- a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
+++ b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
@@ -588,28 +588,37 @@ nsWindowWatcher::OpenWindowJSInternal(ns
NS_ASSERTION(aParent, "We've _got_ to have a parent here!");
nsCOMPtr<nsIDOMWindow> newWindow;
rv = provider->ProvideWindow(aParent, chromeFlags, aCalledFromJS,
sizeSpec.PositionSpecified(),
sizeSpec.SizeSpecified(),
uriToLoad, name, features, &windowIsNew,
getter_AddRefs(newWindow));
+
if (NS_SUCCEEDED(rv)) {
GetWindowTreeItem(newWindow, getter_AddRefs(newDocShellItem));
if (windowIsNew && newDocShellItem) {
// Make sure to stop any loads happening in this window that the
// window provider might have started. Otherwise if our caller
// manipulates the window it just opened and then the load
// completes their stuff will get blown away.
nsCOMPtr<nsIWebNavigation> webNav =
do_QueryInterface(newDocShellItem);
webNav->Stop(nsIWebNavigation::STOP_NETWORK);
}
}
+ else if (rv == NS_ERROR_ABORT) {
+ // NS_ERROR_ABORT means the window provider has flat-out rejected
+ // the open-window call and we should bail. Don't return an error
+ // here, because our caller may propagate that error, which might
+ // cause e.g. window.open to throw! Just return null for our out
+ // param.
+ return NS_OK;
+ }
}
}
}
bool newWindowShouldBeModal = false;
bool parentIsModal = false;
if (!newDocShellItem) {
windowIsNew = true;
--- a/layout/build/Makefile.in
+++ b/layout/build/Makefile.in
@@ -75,16 +75,17 @@ SHARED_LIBRARY_LIBS = \
$(DEPTH)/dom/src/storage/$(LIB_PREFIX)jsdomstorage_s.$(LIB_SUFFIX) \
$(DEPTH)/dom/src/offline/$(LIB_PREFIX)jsdomoffline_s.$(LIB_SUFFIX) \
$(DEPTH)/dom/src/geolocation/$(LIB_PREFIX)jsdomgeolocation_s.$(LIB_SUFFIX) \
$(DEPTH)/dom/src/notification/$(LIB_PREFIX)jsdomnotification_s.$(LIB_SUFFIX) \
$(DEPTH)/dom/system/$(LIB_PREFIX)domsystem_s.$(LIB_SUFFIX) \
$(DEPTH)/dom/workers/$(LIB_PREFIX)domworkers_s.$(LIB_SUFFIX) \
$(DEPTH)/dom/indexedDB/$(LIB_PREFIX)dom_indexeddb_s.$(LIB_SUFFIX) \
$(DEPTH)/dom/indexedDB/ipc/$(LIB_PREFIX)dom_indexeddb_ipc_s.$(LIB_SUFFIX) \
+ $(DEPTH)/dom/browser-element/$(LIB_PREFIX)dom_browserelement_s.$(LIB_SUFFIX) \
$(DEPTH)/editor/libeditor/text/$(LIB_PREFIX)texteditor_s.$(LIB_SUFFIX) \
$(DEPTH)/editor/libeditor/base/$(LIB_PREFIX)editorbase_s.$(LIB_SUFFIX) \
$(DEPTH)/parser/html/$(LIB_PREFIX)html5p_s.$(LIB_SUFFIX) \
$(DEPTH)/caps/src/$(LIB_PREFIX)caps_s.$(LIB_SUFFIX) \
$(DEPTH)/editor/libeditor/html/$(LIB_PREFIX)htmleditor_s.$(LIB_SUFFIX) \
$(DEPTH)/editor/txtsvc/src/$(LIB_PREFIX)txtsvc_s.$(LIB_SUFFIX) \
$(DEPTH)/content/mathml/content/src/$(LIB_PREFIX)gkcontentmathml_s.$(LIB_SUFFIX) \
$(NULL)
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -165,16 +165,17 @@
@BINPATH@/components/dom_geolocation.xpt
@BINPATH@/components/dom_media.xpt
@BINPATH@/components/dom_network.xpt
@BINPATH@/components/dom_notification.xpt
@BINPATH@/components/dom_html.xpt
@BINPATH@/components/dom_indexeddb.xpt
@BINPATH@/components/dom_offline.xpt
@BINPATH@/components/dom_json.xpt
+@BINPATH@/components/dom_browserelement.xpt
@BINPATH@/components/dom_power.xpt
@BINPATH@/components/dom_range.xpt
@BINPATH@/components/dom_sidebar.xpt
@BINPATH@/components/dom_sms.xpt
@BINPATH@/components/dom_storage.xpt
@BINPATH@/components/dom_stylesheets.xpt
@BINPATH@/components/dom_threads.xpt
@BINPATH@/components/dom_traversal.xpt
--- a/mobile/xul/installer/package-manifest.in
+++ b/mobile/xul/installer/package-manifest.in
@@ -171,16 +171,17 @@
@BINPATH@/components/dom_events.xpt
@BINPATH@/components/dom_file.xpt
@BINPATH@/components/dom_geolocation.xpt
@BINPATH@/components/dom_network.xpt
@BINPATH@/components/dom_notification.xpt
@BINPATH@/components/dom_html.xpt
@BINPATH@/components/dom_indexeddb.xpt
@BINPATH@/components/dom_offline.xpt
+@BINPATH@/components/dom_browserelement.xpt
@BINPATH@/components/dom_json.xpt
@BINPATH@/components/dom_range.xpt
@BINPATH@/components/dom_sidebar.xpt
@BINPATH@/components/dom_storage.xpt
@BINPATH@/components/dom_sms.xpt
@BINPATH@/components/dom_stylesheets.xpt
@BINPATH@/components/dom_threads.xpt
@BINPATH@/components/dom_traversal.xpt
--- a/xpfe/appshell/src/nsContentTreeOwner.cpp
+++ b/xpfe/appshell/src/nsContentTreeOwner.cpp
@@ -26,16 +26,17 @@
#include "nsIAuthPrompt.h"
#include "nsIWindowMediator.h"
#include "nsIXULBrowserWindow.h"
#include "nsIPrincipal.h"
#include "nsIURIFixup.h"
#include "nsCDefaultURIFixup.h"
#include "nsIWebNavigation.h"
#include "nsIJSContextStack.h"
+#include "mozilla/BrowserElementParent.h"
#include "nsIDOMDocument.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsIURI.h"
#if defined(XP_MACOSX)
#include "nsThreadUtils.h"
#endif
@@ -832,16 +833,39 @@ nsContentTreeOwner::ProvideWindow(nsIDOM
#ifdef DEBUG
nsCOMPtr<nsIWebNavigation> parentNav = do_GetInterface(aParent);
nsCOMPtr<nsIDocShellTreeOwner> parentOwner = do_GetInterface(parentNav);
NS_ASSERTION(SameCOMIdentity(parentOwner,
static_cast<nsIDocShellTreeOwner*>(this)),
"Parent from wrong docshell tree?");
#endif
+ // If aParent is inside an <iframe mozbrowser> and this isn't a request to
+ // open a modal-type window, we're going to create a new <iframe mozbrowser>
+ // and return its window here.
+ nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent);
+ bool inBrowserFrame = false;
+ if (docshell) {
+ docshell->GetContainedInBrowserFrame(&inBrowserFrame);
+ }
+
+ if (inBrowserFrame &&
+ !(aChromeFlags & (nsIWebBrowserChrome::CHROME_MODAL |
+ nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
+ nsIWebBrowserChrome::CHROME_OPENAS_CHROME))) {
+ bool openSucceeded =
+ BrowserElementParent::OpenWindowInProcess(aParent, aURI, aName,
+ aFeatures, aReturn);
+
+ // If OpenWindowInProcess failed (perhaps because the embedder blocked the
+ // popup), tell our caller not to proceed trying to create a new window
+ // through other means.
+ return openSucceeded ? NS_OK : NS_ERROR_ABORT;
+ }
+
// Where should we open this?
PRInt32 containerPref;
if (NS_FAILED(Preferences::GetInt("browser.link.open_newwindow",
&containerPref))) {
return NS_OK;
}
if (containerPref != nsIBrowserDOMWindow::OPEN_NEWTAB &&