# HG changeset patch
# User Timothy Nikkel <tnikkel@gmail.com>
# Date 1468252212 -32400
#      Tue Jul 12 00:50:12 2016 +0900
# Branch THUNDERBIRD3880_2016050308_RELBRANCH
# Node ID d5539dd692dfa795cbfb6b9a25e0d09a772b4914
# Parent  4b28c1ce2c89c89883474ee5f44c071860111d7f
Bug 1265577. r=mats, a=lizzard

diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -150,17 +150,17 @@
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameLoader)
   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)
+  , mDetachedSubdocFrame(nullptr)
   , mIsPrerendered(false)
   , mDepthTooGreat(false)
   , mIsTopLevelContent(false)
   , mDestroyCalled(false)
   , mNeedsAsyncDestroy(false)
   , mInSwap(false)
   , mInShow(false)
   , mHideCalled(false)
@@ -2502,28 +2502,28 @@
   MOZ_ASSERT(!mCurrentRemoteFrame);
   mRemoteFrame = true;
   mRemoteBrowser = TabParent::GetFrom(aTabParent);
   mChildID = mRemoteBrowser ? mRemoteBrowser->Manager()->ChildID() : 0;
   ShowRemoteFrame(nsIntSize(0, 0));
 }
 
 void
-nsFrameLoader::SetDetachedSubdocView(nsView* aDetachedViews,
-                                     nsIDocument* aContainerDoc)
+nsFrameLoader::SetDetachedSubdocFrame(nsIFrame* aDetachedFrame,
+                                      nsIDocument* aContainerDoc)
 {
-  mDetachedSubdocViews = aDetachedViews;
+  mDetachedSubdocFrame = aDetachedFrame;
   mContainerDocWhileDetached = aContainerDoc;
 }
 
-nsView*
-nsFrameLoader::GetDetachedSubdocView(nsIDocument** aContainerDoc) const
+nsIFrame*
+nsFrameLoader::GetDetachedSubdocFrame(nsIDocument** aContainerDoc) const
 {
   NS_IF_ADDREF(*aContainerDoc = mContainerDocWhileDetached);
-  return mDetachedSubdocViews;
+  return mDetachedSubdocFrame.GetFrame();
 }
 
 void
 nsFrameLoader::ApplySandboxFlags(uint32_t sandboxFlags)
 {
   if (mDocShell) {
     uint32_t parentSandboxFlags = mOwnerContent->OwnerDoc()->GetSandboxFlags();
 
diff --git a/dom/base/nsFrameLoader.h b/dom/base/nsFrameLoader.h
--- a/dom/base/nsFrameLoader.h
+++ b/dom/base/nsFrameLoader.h
@@ -18,16 +18,17 @@
 #include "nsSize.h"
 #include "nsIURI.h"
 #include "nsAutoPtr.h"
 #include "nsFrameMessageManager.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/Attributes.h"
 #include "FrameMetrics.h"
 #include "nsStubMutationObserver.h"
+#include "nsIFrame.h"
 
 class nsIURI;
 class nsSubDocumentFrame;
 class nsView;
 class nsIInProcessContentFrameMessageManager;
 class AutoResetInShow;
 class nsITabParent;
 class nsIDocShellTreeItem;
@@ -192,33 +193,33 @@
    * 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);
 
   /**
-   * Stashes a detached view on the frame loader. We do this when we're
+   * Stashes a detached nsIFrame on the frame loader. We do this when we're
    * destroying the nsSubDocumentFrame. If the nsSubdocumentFrame is
-   * being reframed we'll restore the detached view when it's recreated,
+   * being reframed we'll restore the detached nsIFrame when it's recreated,
    * otherwise we'll discard the old presentation and set the detached
-   * subdoc view to null. aContainerDoc is the document containing the
+   * subdoc nsIFrame to null. aContainerDoc is the document containing the
    * the subdoc frame. This enables us to detect when the containing
    * document has changed during reframe, so we can discard the presentation 
    * in that case.
    */
-  void SetDetachedSubdocView(nsView* aDetachedView,
-                             nsIDocument* aContainerDoc);
+  void SetDetachedSubdocFrame(nsIFrame* aDetachedFrame,
+                              nsIDocument* aContainerDoc);
 
   /**
-   * Retrieves the detached view and the document containing the view,
-   * as set by SetDetachedSubdocView().
+   * Retrieves the detached nsIFrame and the document containing the nsIFrame,
+   * as set by SetDetachedSubdocFrame().
    */
-  nsView* GetDetachedSubdocView(nsIDocument** aContainerDoc) const;
+  nsIFrame* GetDetachedSubdocFrame(nsIDocument** aContainerDoc) const;
 
   /**
    * Applies a new set of sandbox flags. These are merged with the sandbox
    * flags from our owning content's owning document with a logical OR, this
    * ensures that we can only add restrictions and never remove them.
    */
   void ApplySandboxFlags(uint32_t sandboxFlags);
 
@@ -323,20 +324,20 @@
 
 public:
   // public because a callback needs these.
   nsRefPtr<nsFrameMessageManager> mMessageManager;
   nsCOMPtr<nsIInProcessContentFrameMessageManager> mChildMessageManager;
 private:
   // Stores the root view of the subdocument while the subdocument is being
   // reframed. Used to restore the presentation after reframing.
-  nsView* mDetachedSubdocViews;
+  nsWeakFrame mDetachedSubdocFrame;
   // 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
+  // presentation is detached and stored in mDetachedSubdocFrame. 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;
diff --git a/layout/generic/nsSubDocumentFrame.cpp b/layout/generic/nsSubDocumentFrame.cpp
--- a/layout/generic/nsSubDocumentFrame.cpp
+++ b/layout/generic/nsSubDocumentFrame.cpp
@@ -125,23 +125,26 @@
 
   // If we have a detached subdoc's root view on our frame loader, re-insert
   // it into the view tree. This happens when we've been reframed, and
   // ensures the presentation persists across reframes. If the frame element
   // has changed documents however, we blow away the presentation.
   nsRefPtr<nsFrameLoader> frameloader = FrameLoader();
   if (frameloader) {
     nsCOMPtr<nsIDocument> oldContainerDoc;
-    nsView* detachedViews =
-      frameloader->GetDetachedSubdocView(getter_AddRefs(oldContainerDoc));
-    frameloader->SetDetachedSubdocView(nullptr, nullptr);
-    if (detachedViews) {
-      if (oldContainerDoc == aContent->OwnerDoc()) {
+    nsIFrame* detachedFrame =
+      frameloader->GetDetachedSubdocFrame(getter_AddRefs(oldContainerDoc));
+    frameloader->SetDetachedSubdocFrame(nullptr, nullptr);
+    MOZ_ASSERT(oldContainerDoc || !detachedFrame);
+    if (oldContainerDoc) {
+      nsView* detachedView =
+        detachedFrame ? detachedFrame->GetView() : nullptr;
+      if (detachedView && oldContainerDoc == aContent->OwnerDoc()) {
         // Restore stashed presentation.
-        ::InsertViewsInReverseOrder(detachedViews, mInnerView);
+        ::InsertViewsInReverseOrder(detachedView, mInnerView);
         ::EndSwapDocShellsForViews(mInnerView->GetFirstChild());
       } else {
         // Presentation is for a different document, don't restore it.
         frameloader->Hide();
       }
     }
   }
 
@@ -247,21 +250,22 @@
 
 nsIntSize
 nsSubDocumentFrame::GetSubdocumentSize()
 {
   if (GetStateBits() & NS_FRAME_FIRST_REFLOW) {
     nsRefPtr<nsFrameLoader> frameloader = FrameLoader();
     if (frameloader) {
       nsCOMPtr<nsIDocument> oldContainerDoc;
-      nsView* detachedViews =
-        frameloader->GetDetachedSubdocView(getter_AddRefs(oldContainerDoc));
-      if (detachedViews) {
-        nsSize size = detachedViews->GetBounds().Size();
-        nsPresContext* presContext = detachedViews->GetFrame()->PresContext();
+      nsIFrame* detachedFrame =
+        frameloader->GetDetachedSubdocFrame(getter_AddRefs(oldContainerDoc));
+      nsView* view = detachedFrame ? detachedFrame->GetView() : nullptr;
+      if (view) {
+        nsSize size = view->GetBounds().Size();
+        nsPresContext* presContext = detachedFrame->PresContext();
         return nsIntSize(presContext->AppUnitsToDevPixels(size.width),
                          presContext->AppUnitsToDevPixels(size.height));
       }
     }
     // Pick some default size for now.  Using 10x10 because that's what the
     // code used to do.
     return nsIntSize(10, 10);
   } else {
@@ -934,17 +938,17 @@
     // Note it can be unsafe to flush if we've destroyed the presentation
     // for some other reason, like if we're shutting down.
     if (!mPresShell->IsDestroying()) {
       mPresShell->FlushPendingNotifications(Flush_Frames);
     }
 
     // Either the frame has been constructed by now, or it never will be,
     // either way we want to clear the stashed views.
-    mFrameLoader->SetDetachedSubdocView(nullptr, nullptr);
+    mFrameLoader->SetDetachedSubdocFrame(nullptr, nullptr);
 
     nsSubDocumentFrame* frame = do_QueryFrame(mFrameElement->GetPrimaryFrame());
     if ((!frame && mHideViewerIfFrameless) ||
         mPresShell->IsDestroying()) {
       // Either the frame element has no nsIFrame or the presshell is being
       // destroyed. Hide the nsFrameLoader, which destroys the presentation.
       mFrameLoader->Hide();
     }
@@ -969,25 +973,34 @@
   }
 
   // Detach the subdocument's views and stash them in the frame loader.
   // We can then reattach them if we're being reframed (for example if
   // the frame has been made position:fixed).
   RefPtr<nsFrameLoader> frameloader = FrameLoader();
   if (frameloader) {
     nsView* detachedViews = ::BeginSwapDocShellsForViews(mInnerView->GetFirstChild());
-    frameloader->SetDetachedSubdocView(detachedViews, mContent->OwnerDoc());
+    if (detachedViews && detachedViews->GetFrame()) {
+      MOZ_ASSERT(mContent->OwnerDoc());
+      frameloader->SetDetachedSubdocFrame(
+        detachedViews->GetFrame(), mContent->OwnerDoc());
 
-    // We call nsFrameLoader::HideViewer() in a script runner so that we can
-    // safely determine whether the frame is being reframed or destroyed.
-    nsContentUtils::AddScriptRunner(
-      new nsHideViewer(mContent,
-                       frameloader,
-                       PresContext()->PresShell(),
-                       (mDidCreateDoc || mCallingShow)));
+      // We call nsFrameLoader::HideViewer() in a script runner so that we can
+      // safely determine whether the frame is being reframed or destroyed.
+      nsContentUtils::AddScriptRunner(
+        new nsHideViewer(mContent,
+                         frameloader,
+                         PresContext()->PresShell(),
+                         (mDidCreateDoc || mCallingShow)));
+    } else {
+      frameloader->SetDetachedSubdocFrame(nullptr, nullptr);
+      if (mDidCreateDoc || mCallingShow) {
+        frameloader->Hide();
+      }
+    }
   }
 
   nsLeafFrame::DestroyFrom(aDestructRoot);
 }
 
 nsIntSize
 nsSubDocumentFrame::GetMarginAttributes()
 {
