Bug 1061864 - Part 2: Add a prerendered flag to nsIFrameLoader and nsIFrameLoaderOwner; r=smaug
authorEhsan Akhgari <ehsan@mozilla.com>
Mon, 05 Jan 2015 14:16:09 -0500
changeset 248000 75a20fb5f86430a9dc8ef49a6cdd0aa7bea9d50c
parent 247999 9ea0c21e8e33a434642d8c03a6b939e29200bccc
child 248001 d07e602fd38520da2cdbce963ff4d5b7ccce63e6
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1061864
milestone37.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1061864 - Part 2: Add a prerendered flag to nsIFrameLoader and nsIFrameLoaderOwner; r=smaug
dom/base/nsElementFrameLoaderOwner.cpp
dom/base/nsElementFrameLoaderOwner.h
dom/base/nsFrameLoader.cpp
dom/base/nsFrameLoader.h
dom/base/nsGkAtomList.h
dom/base/nsIFrameLoader.idl
dom/base/nsObjectLoadingContent.cpp
dom/webidl/XULElement.webidl
dom/xul/nsXULElement.cpp
dom/xul/nsXULElement.h
--- a/dom/base/nsElementFrameLoaderOwner.cpp
+++ b/dom/base/nsElementFrameLoaderOwner.cpp
@@ -107,16 +107,19 @@ nsElementFrameLoaderOwner::EnsureFrameLo
       mFrameLoaderCreationDisallowed) {
     // If frame loader is there, we just keep it around, cached
     return;
   }
 
   // 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
 nsElementFrameLoaderOwner::GetFrameLoader(nsIFrameLoader **aFrameLoader)
 {
   NS_IF_ADDREF(*aFrameLoader = mFrameLoader);
   return NS_OK;
 }
@@ -130,16 +133,24 @@ nsElementFrameLoaderOwner::GetFrameLoade
 
 NS_IMETHODIMP
 nsElementFrameLoaderOwner::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner)
 {
   // We don't support this yet
   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()
 {
   EnsureFrameLoader();
 
   if (!mFrameLoader) {
     return NS_OK;
   }
--- a/dom/base/nsElementFrameLoaderOwner.h
+++ b/dom/base/nsElementFrameLoaderOwner.h
@@ -28,16 +28,17 @@ class nsXULElement;
 /**
  * A helper class for frame elements
  */
 class nsElementFrameLoaderOwner : public nsIFrameLoaderOwner
 {
 public:
   explicit nsElementFrameLoaderOwner(mozilla::dom::FromParser aFromParser)
     : mNetworkCreated(aFromParser == mozilla::dom::FROM_PARSER_NETWORK)
+    , mIsPrerendered(false)
     , mBrowserFrameListenersRegistered(false)
     , mFrameLoaderCreationDisallowed(false)
   {
   }
 
   virtual ~nsElementFrameLoaderOwner();
 
   NS_DECL_NSIFRAMELOADEROWNER
@@ -65,13 +66,14 @@ protected:
 
   /**
    * True when the element is created by the parser using the
    * NS_FROM_PARSER_NETWORK flag.
    * If the element is modified, it may lose the flag.
    */
   bool mNetworkCreated;
 
+  bool mIsPrerendered;
   bool mBrowserFrameListenersRegistered;
   bool mFrameLoaderCreationDisallowed;
 };
 
 #endif // nsElementFrameLoaderOwner_h
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -149,16 +149,17 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsIFrameLoader)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIFrameLoader)
 NS_INTERFACE_MAP_END
 
 nsFrameLoader::nsFrameLoader(Element* aOwner, bool aNetworkCreated)
   : mOwnerContent(aOwner)
   , mAppIdSentToPermissionManager(nsIScriptSecurityManager::NO_APP_ID)
   , mDetachedSubdocViews(nullptr)
+  , mIsPrerendered(false)
   , mDepthTooGreat(false)
   , mIsTopLevelContent(false)
   , mDestroyCalled(false)
   , mNeedsAsyncDestroy(false)
   , mInSwap(false)
   , mInShow(false)
   , mHideCalled(false)
   , mNetworkCreated(aNetworkCreated)
@@ -290,16 +291,25 @@ nsFrameLoader::LoadURI(nsIURI* aURI)
   mURIToLoad = aURI;
   rv = doc->InitializeFrameLoader(this);
   if (NS_FAILED(rv)) {
     mURIToLoad = nullptr;
   }
   return rv;
 }
 
+NS_IMETHODIMP
+nsFrameLoader::SetIsPrerendered()
+{
+  MOZ_ASSERT(!mDocShell, "Please call SetIsPrerendered before docShell is created");
+  mIsPrerendered = true;
+
+  return NS_OK;
+}
+
 nsresult
 nsFrameLoader::ReallyStartLoading()
 {
   nsresult rv = ReallyStartLoadingInternal();
   if (NS_FAILED(rv)) {
     FireErrorEvent();
   }
   
@@ -1608,16 +1618,21 @@ nsFrameLoader::MaybeCreateDocShell()
   nsCOMPtr<nsIDocShell> docShell = doc->GetDocShell();
   nsCOMPtr<nsIWebNavigation> parentAsWebNav = do_QueryInterface(docShell);
   NS_ENSURE_STATE(parentAsWebNav);
 
   // Create the docshell...
   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;
   if (!mOwnerContent->IsSVG(nsGkAtoms::iframe)) {
     HTMLIFrameElement* iframe = HTMLIFrameElement::FromContent(mOwnerContent);
     if (iframe) {
       sandboxFlags = iframe->GetSandboxFlags();
     }
--- a/dom/base/nsFrameLoader.h
+++ b/dom/base/nsFrameLoader.h
@@ -326,16 +326,17 @@ private:
   nsView* mDetachedSubdocViews;
   // Stores the containing document of the frame corresponding to this
   // frame loader. This is reference is kept valid while the subframe's
   // presentation is detached and stored in mDetachedSubdocViews. This
   // enables us to detect whether the frame has moved documents during
   // a reframe, so that we know not to restore the presentation.
   nsCOMPtr<nsIDocument> mContainerDocWhileDetached;
 
+  bool mIsPrerendered : 1;
   bool mDepthTooGreat : 1;
   bool mIsTopLevelContent : 1;
   bool mDestroyCalled : 1;
   bool mNeedsAsyncDestroy : 1;
   bool mInSwap : 1;
   bool mInShow : 1;
   bool mHideCalled : 1;
   // True when the object is created for an element which the parser has
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -946,16 +946,17 @@ GK_ATOM(popupsinherittooltip, "popupsinh
 GK_ATOM(position, "position")
 GK_ATOM(poster, "poster")
 GK_ATOM(pre, "pre")
 GK_ATOM(preceding, "preceding")
 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")
 GK_ATOM(primary, "primary")
 GK_ATOM(print, "print")
 GK_ATOM(priority, "priority")
 GK_ATOM(processingInstruction, "processing-instruction")
 GK_ATOM(profile, "profile")
--- a/dom/base/nsIFrameLoader.idl
+++ b/dom/base/nsIFrameLoader.idl
@@ -11,17 +11,17 @@ interface nsIURI;
 interface nsIFrame;
 interface nsSubDocumentFrame;
 interface nsIMessageSender;
 interface nsIVariant;
 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
 {
   /**
    * Get the docshell from the frame loader.
    */
   readonly attribute nsIDocShell docShell;
 
   /**
@@ -45,16 +45,21 @@ interface nsIFrameLoader : nsISupports
 
   /**
    * Loads the specified URI in this frame. Behaves identically to loadFrame,
    * except that this method allows specifying the URI to load.
    */
   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.
    */
   void destroy();
 
   /**
    * Find out whether the loader's frame is at too great a depth in
    * the frame tree.  This can be used to decide what operations may
@@ -187,26 +192,31 @@ interface nsIFrameLoader : nsISupports
 };
 
 %{C++
 class nsFrameLoader;
 %}
 
 native alreadyAddRefed_nsFrameLoader(already_AddRefed<nsFrameLoader>);
 
-[scriptable, uuid(5879040e-83e9-40e3-b2bb-5ddf43b76e47)]
+[scriptable, uuid(c4abebcf-55f3-47d4-af15-151311971255)]
 interface nsIFrameLoaderOwner : nsISupports
 {
   /**
    * The frame loader owned by this nsIFrameLoaderOwner
    */
   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
    * never, depending on the object implementing this interface.
    *
    * @throws NS_ERROR_NOT_IMPLEMENTED if the swapping logic is not
    *   implemented for the two given frame loader owners.
    * @throws NS_ERROR_DOM_SECURITY_ERR if the swap is not allowed on
    *   security grounds.
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -1195,16 +1195,22 @@ nsObjectLoadingContent::GetFrameLoader(n
 NS_IMETHODIMP_(already_AddRefed<nsFrameLoader>)
 nsObjectLoadingContent::GetFrameLoader()
 {
   nsRefPtr<nsFrameLoader> loader = mFrameLoader;
   return loader.forget();
 }
 
 NS_IMETHODIMP
+nsObjectLoadingContent::SetIsPrerendered()
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
 nsObjectLoadingContent::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherLoader)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 nsObjectLoadingContent::GetActualType(nsACString& aType)
 {
--- a/dom/webidl/XULElement.webidl
+++ b/dom/webidl/XULElement.webidl
@@ -117,16 +117,19 @@ interface XULElement : Element {
 };
 
 // And the things from nsIFrameLoaderOwner
 [NoInterfaceObject]
 interface MozFrameLoaderOwner {
   [ChromeOnly]
   readonly attribute MozFrameLoader? frameLoader;
 
+  [ChromeOnly]
+  void setIsPrerendered();
+
   [ChromeOnly, Throws]
   void swapFrameLoaders(XULElement aOtherOwner);
 };
 
 XULElement implements GlobalEventHandlers;
 XULElement implements TouchEventHandlers;
 XULElement implements MozFrameLoaderOwner;
 XULElement implements OnErrorEventHandlerForNodes;
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -1598,16 +1598,22 @@ nsXULElement::LoadSrc()
     }
     nsXULSlots* slots = static_cast<nsXULSlots*>(Slots());
     if (!slots->mFrameLoader) {
         // false as the last parameter so that xul:iframe/browser/editor
         // session history handling works like dynamic html:iframes.
         // 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);
     }
 
     return slots->mFrameLoader->LoadFrame();
 }
 
 nsresult
 nsXULElement::GetFrameLoader(nsIFrameLoader **aFrameLoader)
@@ -1623,16 +1629,23 @@ nsXULElement::GetFrameLoader()
     if (!slots)
         return nullptr;
 
     nsRefPtr<nsFrameLoader> loader = slots->mFrameLoader;
     return loader.forget();
 }
 
 nsresult
+nsXULElement::SetIsPrerendered()
+{
+  return SetAttr(kNameSpaceID_None, nsGkAtoms::prerendered, nullptr,
+                 NS_LITERAL_STRING("true"), true);
+}
+
+nsresult
 nsXULElement::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner)
 {
     nsCOMPtr<nsIContent> otherContent(do_QueryInterface(aOtherOwner));
     NS_ENSURE_TRUE(otherContent, NS_ERROR_NOT_IMPLEMENTED);
 
     nsXULElement* otherEl = FromContent(otherContent);
     NS_ENSURE_TRUE(otherEl, NS_ERROR_NOT_IMPLEMENTED);
 
--- a/dom/xul/nsXULElement.h
+++ b/dom/xul/nsXULElement.h
@@ -435,16 +435,17 @@ public:
 
     // nsIDOMXULElement
     NS_DECL_NSIDOMXULELEMENT
 
     virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
     virtual mozilla::EventStates IntrinsicState() const MOZ_OVERRIDE;
 
     nsresult GetFrameLoader(nsIFrameLoader** aFrameLoader);
+    nsresult SetIsPrerendered();
     nsresult SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner);
 
     virtual void RecompileScriptEventListeners() MOZ_OVERRIDE;
 
     // This function should ONLY be used by BindToTree implementations.
     // The function exists solely because XUL elements store the binding
     // parent as a member instead of in the slots, as Element does.
     void SetXULBindingParent(nsIContent* aBindingParent)