diff --git a/dom/base/nsElementFrameLoaderOwner.cpp b/dom/base/nsElementFrameLoaderOwner.cpp index e61fcfaf1f5..8d49e2d46bb 100644 --- a/dom/base/nsElementFrameLoaderOwner.cpp +++ b/dom/base/nsElementFrameLoaderOwner.cpp @@ -112,6 +112,9 @@ nsElementFrameLoaderOwner::EnsureFrameLoader() // Strangely enough, this method doesn't actually ensure that the // frameloader exists. It's more of a best-effort kind of thing. mFrameLoader = nsFrameLoader::Create(thisElement, mNetworkCreated); + if (mIsPrerendered) { + mFrameLoader->SetIsPrerendered(); + } } NS_IMETHODIMP @@ -135,6 +138,14 @@ nsElementFrameLoaderOwner::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner) return NS_ERROR_NOT_IMPLEMENTED; } +NS_IMETHODIMP +nsElementFrameLoaderOwner::SetIsPrerendered() +{ + MOZ_ASSERT(!mFrameLoader, "Please call SetIsPrerendered before frameLoader is created"); + mIsPrerendered = true; + return NS_OK; +} + nsresult nsElementFrameLoaderOwner::LoadSrc() { diff --git a/dom/base/nsElementFrameLoaderOwner.h b/dom/base/nsElementFrameLoaderOwner.h index f00125a5d58..fbdd796d9ed 100644 --- a/dom/base/nsElementFrameLoaderOwner.h +++ b/dom/base/nsElementFrameLoaderOwner.h @@ -33,6 +33,7 @@ class nsElementFrameLoaderOwner : public nsIFrameLoaderOwner public: explicit nsElementFrameLoaderOwner(mozilla::dom::FromParser aFromParser) : mNetworkCreated(aFromParser == mozilla::dom::FROM_PARSER_NETWORK) + , mIsPrerendered(false) , mBrowserFrameListenersRegistered(false) , mFrameLoaderCreationDisallowed(false) { @@ -70,6 +71,7 @@ protected: */ bool mNetworkCreated; + bool mIsPrerendered; bool mBrowserFrameListenersRegistered; bool mFrameLoaderCreationDisallowed; }; diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp index ef7204a76af..6fea812ac9b 100644 --- a/dom/base/nsFrameLoader.cpp +++ b/dom/base/nsFrameLoader.cpp @@ -154,6 +154,7 @@ nsFrameLoader::nsFrameLoader(Element* aOwner, bool aNetworkCreated) : mOwnerContent(aOwner) , mAppIdSentToPermissionManager(nsIScriptSecurityManager::NO_APP_ID) , mDetachedSubdocViews(nullptr) + , mIsPrerendered(false) , mDepthTooGreat(false) , mIsTopLevelContent(false) , mDestroyCalled(false) @@ -295,6 +296,15 @@ nsFrameLoader::LoadURI(nsIURI* aURI) return rv; } +NS_IMETHODIMP +nsFrameLoader::SetIsPrerendered() +{ + MOZ_ASSERT(!mDocShell, "Please call SetIsPrerendered before docShell is created"); + mIsPrerendered = true; + + return NS_OK; +} + nsresult nsFrameLoader::ReallyStartLoading() { @@ -1613,6 +1623,11 @@ nsFrameLoader::MaybeCreateDocShell() mDocShell = do_CreateInstance("@mozilla.org/docshell;1"); NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE); + if (mIsPrerendered) { + nsresult rv = mDocShell->SetIsPrerendered(true); + NS_ENSURE_SUCCESS(rv,rv); + } + // Apply sandbox flags even if our owner is not an iframe, as this copies // flags from our owning content's owning document. uint32_t sandboxFlags = 0; diff --git a/dom/base/nsFrameLoader.h b/dom/base/nsFrameLoader.h index 530b9af76d3..a8a0a7baebe 100644 --- a/dom/base/nsFrameLoader.h +++ b/dom/base/nsFrameLoader.h @@ -331,6 +331,7 @@ private: // a reframe, so that we know not to restore the presentation. nsCOMPtr mContainerDocWhileDetached; + bool mIsPrerendered : 1; bool mDepthTooGreat : 1; bool mIsTopLevelContent : 1; bool mDestroyCalled : 1; diff --git a/dom/base/nsGkAtomList.h b/dom/base/nsGkAtomList.h index 4fc582b520b..c8ef7123a5b 100644 --- a/dom/base/nsGkAtomList.h +++ b/dom/base/nsGkAtomList.h @@ -951,6 +951,7 @@ GK_ATOM(precedingSibling, "preceding-sibling") GK_ATOM(predicate, "predicate") GK_ATOM(prefix, "prefix") GK_ATOM(preload, "preload") +GK_ATOM(prerendered, "prerendered") GK_ATOM(preserve, "preserve") GK_ATOM(preserveSpace, "preserve-space") GK_ATOM(preventdefault, "preventdefault") diff --git a/dom/base/nsIFrameLoader.idl b/dom/base/nsIFrameLoader.idl index beff6e1e66c..b60a8ff20f4 100644 --- a/dom/base/nsIFrameLoader.idl +++ b/dom/base/nsIFrameLoader.idl @@ -16,7 +16,7 @@ interface nsIDOMElement; interface nsITabParent; interface nsILoadContext; -[scriptable, builtinclass, uuid(7600aa92-88dc-491c-896d-0564159b6a66)] +[scriptable, builtinclass, uuid(28b6b043-46ec-412f-9be9-db22938b0d6d)] interface nsIFrameLoader : nsISupports { /** @@ -49,6 +49,11 @@ interface nsIFrameLoader : nsISupports */ void loadURI(in nsIURI aURI); + /** + * Puts the frameloader in prerendering mode. + */ + void setIsPrerendered(); + /** * Destroy the frame loader and everything inside it. This will * clear the weak owner content reference. @@ -192,7 +197,7 @@ class nsFrameLoader; native alreadyAddRefed_nsFrameLoader(already_AddRefed); -[scriptable, uuid(5879040e-83e9-40e3-b2bb-5ddf43b76e47)] +[scriptable, uuid(c4abebcf-55f3-47d4-af15-151311971255)] interface nsIFrameLoaderOwner : nsISupports { /** @@ -201,6 +206,11 @@ interface nsIFrameLoaderOwner : nsISupports readonly attribute nsIFrameLoader frameLoader; [noscript, notxpcom] alreadyAddRefed_nsFrameLoader GetFrameLoader(); + /** + * Puts the FrameLoaderOwner in prerendering mode. + */ + void setIsPrerendered(); + /** * Swap frame loaders with the given nsIFrameLoaderOwner. This may * only be posible in a very limited range of circumstances, or diff --git a/dom/base/nsObjectLoadingContent.cpp b/dom/base/nsObjectLoadingContent.cpp index 911af4d72b9..f5f50379717 100644 --- a/dom/base/nsObjectLoadingContent.cpp +++ b/dom/base/nsObjectLoadingContent.cpp @@ -1199,6 +1199,12 @@ nsObjectLoadingContent::GetFrameLoader() return loader.forget(); } +NS_IMETHODIMP +nsObjectLoadingContent::SetIsPrerendered() +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + NS_IMETHODIMP nsObjectLoadingContent::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherLoader) { diff --git a/dom/webidl/XULElement.webidl b/dom/webidl/XULElement.webidl index 7d9772ebb1f..ff2af0e7484 100644 --- a/dom/webidl/XULElement.webidl +++ b/dom/webidl/XULElement.webidl @@ -122,6 +122,9 @@ interface MozFrameLoaderOwner { [ChromeOnly] readonly attribute MozFrameLoader? frameLoader; + [ChromeOnly] + void setIsPrerendered(); + [ChromeOnly, Throws] void swapFrameLoaders(XULElement aOtherOwner); }; diff --git a/dom/xul/nsXULElement.cpp b/dom/xul/nsXULElement.cpp index 6e73570451c..07c9d74869d 100644 --- a/dom/xul/nsXULElement.cpp +++ b/dom/xul/nsXULElement.cpp @@ -1603,6 +1603,12 @@ nsXULElement::LoadSrc() // Usually xul elements are used in chrome, which doesn't have // session history at all. slots->mFrameLoader = nsFrameLoader::Create(this, false); + if (AttrValueIs(kNameSpaceID_None, nsGkAtoms::prerendered, + NS_LITERAL_STRING("true"), eIgnoreCase)) { + nsresult rv = slots->mFrameLoader->SetIsPrerendered(); + NS_ENSURE_SUCCESS(rv,rv); + } + NS_ENSURE_TRUE(slots->mFrameLoader, NS_OK); } @@ -1627,6 +1633,13 @@ nsXULElement::GetFrameLoader() return loader.forget(); } +nsresult +nsXULElement::SetIsPrerendered() +{ + return SetAttr(kNameSpaceID_None, nsGkAtoms::prerendered, nullptr, + NS_LITERAL_STRING("true"), true); +} + nsresult nsXULElement::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner) { diff --git a/dom/xul/nsXULElement.h b/dom/xul/nsXULElement.h index fe2e6179c4b..4346f6f2371 100644 --- a/dom/xul/nsXULElement.h +++ b/dom/xul/nsXULElement.h @@ -440,6 +440,7 @@ public: virtual mozilla::EventStates IntrinsicState() const MOZ_OVERRIDE; nsresult GetFrameLoader(nsIFrameLoader** aFrameLoader); + nsresult SetIsPrerendered(); nsresult SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner); virtual void RecompileScriptEventListeners() MOZ_OVERRIDE;