author | Justin Lebar <justin.lebar@gmail.com> |
Tue, 12 Jun 2012 18:01:25 -0400 | |
changeset 101817 | 65a425a98e860afa7132473dbf6a2f6868374b92 |
parent 101816 | c2630a86e9a2ad3859a71e94ae63e939b7636e56 |
child 101818 | bc7286e373c9ddea9fe819473e25e5b05e91cfd3 |
push id | 191 |
push user | lsblakk@mozilla.com |
push date | Fri, 05 Oct 2012 17:12:53 +0000 |
treeherder | mozilla-release@ddb22ac6c03b [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bz, cjones |
bugs | 742944 |
milestone | 16.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
|
--- 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 &&