From e4f1520c9edc18be52df352ff9eb0ad2390bb1e0 Mon Sep 17 00:00:00 2001 From: "bryner%brianryner.com" Date: Sun, 6 Nov 2005 19:23:03 +0000 Subject: [PATCH] Unhook subframe containers / link handlers when putting a document into bfcache, and restore them when restoring the document (bug 314549). r+sr=bzbarsky. git-svn-id: svn://10.0.0.236/trunk@184218 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/docshell/base/nsDocShell.cpp | 2 +- mozilla/docshell/base/nsIContentViewer.idl | 5 +- mozilla/layout/base/nsDocumentViewer.cpp | 99 +++++++++++++++++++++- mozilla/layout/base/nsIDocumentViewer.h | 2 +- 4 files changed, 103 insertions(+), 5 deletions(-) diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index d16b5a6b3b1..c29c0fab610 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -5426,7 +5426,7 @@ nsDocShell::RestoreFromHistory() mLSHE->SetWindowState(nsnull); // Reattach to the window object. - rv = mContentViewer->Open(windowState); + rv = mContentViewer->Open(windowState, mLSHE); // Now remove it from the cached presentation. mLSHE->SetContentViewer(nsnull); diff --git a/mozilla/docshell/base/nsIContentViewer.idl b/mozilla/docshell/base/nsIContentViewer.idl index f5e92c72721..f30a4f965e6 100644 --- a/mozilla/docshell/base/nsIContentViewer.idl +++ b/mozilla/docshell/base/nsIContentViewer.idl @@ -14,7 +14,7 @@ struct nsRect; [ptr] native nsIDeviceContextPtr(nsIDeviceContext); [ref] native nsRectRef(nsRect); -[scriptable, uuid(6a7ddb40-8a9e-4576-8ad1-71c5641d8780)] +[scriptable, uuid(13a1028c-7720-4ea1-9c49-688ef1574528)] interface nsIContentViewer : nsISupports { @@ -87,8 +87,9 @@ interface nsIContentViewer : nsISupports * Attach the content viewer to its DOM window and docshell. * @param aState A state object that might be useful in attaching the DOM * window. + * @param aSHEntry The history entry that the content viewer was stored in */ - void open(in nsISupports aState); + void open(in nsISupports aState, in nsISHEntry aSHEntry); /** * Clears the current history entry. This is used if we need to clear out diff --git a/mozilla/layout/base/nsDocumentViewer.cpp b/mozilla/layout/base/nsDocumentViewer.cpp index e57eebd1c44..27f4796ebe2 100644 --- a/mozilla/layout/base/nsDocumentViewer.cpp +++ b/mozilla/layout/base/nsDocumentViewer.cpp @@ -1215,8 +1215,46 @@ DocumentViewerImpl::PageHide(PRBool aIsUnload) NS_EVENT_FLAG_INIT, &status); } +static void +AttachContainerRecurse(nsIDocShell* aShell) +{ + nsCOMPtr viewer; + aShell->GetContentViewer(getter_AddRefs(viewer)); + nsCOMPtr docViewer = do_QueryInterface(viewer); + if (docViewer) { + nsCOMPtr doc; + docViewer->GetDocument(getter_AddRefs(doc)); + if (doc) { + doc->SetContainer(aShell); + } + nsCOMPtr pc; + docViewer->GetPresContext(getter_AddRefs(pc)); + if (pc) { + pc->SetContainer(aShell); + pc->SetLinkHandler(nsCOMPtr(do_QueryInterface(aShell))); + } + nsCOMPtr presShell; + docViewer->GetPresShell(getter_AddRefs(presShell)); + if (presShell) { + presShell->SetForwardingContainer(nsnull); + } + } + + // Now recurse through the children + nsCOMPtr node = do_QueryInterface(aShell); + NS_ASSERTION(node, "docshells must implement nsIDocShellTreeNode"); + + PRInt32 childCount; + node->GetChildCount(&childCount); + for (PRInt32 i = 0; i < childCount; ++i) { + nsCOMPtr childItem; + node->GetChildAt(i, getter_AddRefs(childItem)); + AttachContainerRecurse(nsCOMPtr(do_QueryInterface(childItem))); + } +} + NS_IMETHODIMP -DocumentViewerImpl::Open(nsISupports *aState) +DocumentViewerImpl::Open(nsISupports *aState, nsISHEntry *aSHEntry) { NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED); @@ -1239,6 +1277,16 @@ DocumentViewerImpl::Open(nsISupports *aState) if (mPresShell) mPresShell->SetForwardingContainer(nsnull); + // Rehook the child presentations. The child shells are still in + // session history, so get them from there. + + nsCOMPtr item; + PRInt32 itemIndex = 0; + while (NS_SUCCEEDED(aSHEntry->ChildShellAt(itemIndex++, + getter_AddRefs(item))) && item) { + AttachContainerRecurse(nsCOMPtr(do_QueryInterface(item))); + } + SyncParentSubDocMap(); if (mFocusListener) { @@ -1317,6 +1365,45 @@ DocumentViewerImpl::Close(nsISHEntry *aSHEntry) return NS_OK; } +static void +DetachContainerRecurse(nsIDocShell *aShell) +{ + // Unhook this docshell's presentation + nsCOMPtr viewer; + aShell->GetContentViewer(getter_AddRefs(viewer)); + nsCOMPtr docViewer = do_QueryInterface(viewer); + if (docViewer) { + nsCOMPtr doc; + docViewer->GetDocument(getter_AddRefs(doc)); + if (doc) { + doc->SetContainer(nsnull); + } + nsCOMPtr pc; + docViewer->GetPresContext(getter_AddRefs(pc)); + if (pc) { + pc->SetContainer(nsnull); + pc->SetLinkHandler(nsnull); + } + nsCOMPtr presShell; + docViewer->GetPresShell(getter_AddRefs(presShell)); + if (presShell) { + presShell->SetForwardingContainer(nsWeakPtr(do_GetWeakReference(aShell))); + } + } + + // Now recurse through the children + nsCOMPtr node = do_QueryInterface(aShell); + NS_ASSERTION(node, "docshells must implement nsIDocShellTreeNode"); + + PRInt32 childCount; + node->GetChildCount(&childCount); + for (PRInt32 i = 0; i < childCount; ++i) { + nsCOMPtr childItem; + node->GetChildAt(i, getter_AddRefs(childItem)); + DetachContainerRecurse(nsCOMPtr(do_QueryInterface(childItem))); + } +} + NS_IMETHODIMP DocumentViewerImpl::Destroy() { @@ -1396,6 +1483,7 @@ DocumentViewerImpl::Destroy() else { mSHEntry->SyncPresentationState(); } + nsCOMPtr shEntry = mSHEntry; // we'll need this below mSHEntry = nsnull; // Break the link from the document/presentation to the docshell, so that @@ -1412,6 +1500,15 @@ DocumentViewerImpl::Destroy() if (mPresShell) mPresShell->SetForwardingContainer(mContainer); + // Do the same for our children. Note that we need to get the child + // docshells from the SHEntry now; the docshell will have cleared them. + nsCOMPtr item; + PRInt32 itemIndex = 0; + while (NS_SUCCEEDED(shEntry->ChildShellAt(itemIndex++, + getter_AddRefs(item))) && item) { + DetachContainerRecurse(nsCOMPtr(do_QueryInterface(item))); + } + return NS_OK; } diff --git a/mozilla/layout/base/nsIDocumentViewer.h b/mozilla/layout/base/nsIDocumentViewer.h index 7fde76a533d..40b5ad5ab9a 100644 --- a/mozilla/layout/base/nsIDocumentViewer.h +++ b/mozilla/layout/base/nsIDocumentViewer.h @@ -45,7 +45,7 @@ class nsIPresShell; class nsIStyleSheet; #define NS_IDOCUMENT_VIEWER_IID \ - { 0x42ecec88, 0x80d5, 0x48ac,{0x9a, 0xcd, 0x12, 0x51, 0xdc, 0x42, 0x60, 0x4a}} + { 0x41796e63, 0xbd1f, 0x401d,{0xb6, 0x63, 0x5b, 0x86, 0xa9, 0x70, 0x72, 0x31}} /** * A document viewer is a kind of content viewer that uses NGLayout