Invalidate cached presentation if the DOM is mutated (bug 292962). Patch by sicking, r+sr=me, a=chofmann.
This commit is contained in:
Родитель
881de3ae1b
Коммит
6a7d2b7baf
|
@ -56,6 +56,8 @@ REQUIRES = xpcom \
|
|||
docshell \
|
||||
pref \
|
||||
gfx \
|
||||
content \
|
||||
widget \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = nsSHEntry.cpp \
|
||||
|
|
|
@ -47,6 +47,13 @@
|
|||
#include "nsReadableUtils.h"
|
||||
#include "nsIDocShellLoadInfo.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "PLEvent.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIEventQueue.h"
|
||||
#include "nsEventQueueUtils.h"
|
||||
|
||||
|
||||
static PRUint32 gEntryID = 0;
|
||||
|
||||
|
@ -95,6 +102,7 @@ nsSHEntry::nsSHEntry(const nsSHEntry &other)
|
|||
nsSHEntry::~nsSHEntry()
|
||||
{
|
||||
mChildren.Clear();
|
||||
RemoveDocumentObserver();
|
||||
if (mContentViewer)
|
||||
mContentViewer->Destroy();
|
||||
}
|
||||
|
@ -103,7 +111,8 @@ nsSHEntry::~nsSHEntry()
|
|||
// nsSHEntry: nsISupports
|
||||
//*****************************************************************************
|
||||
|
||||
NS_IMPL_ISUPPORTS3(nsSHEntry, nsISHContainer, nsISHEntry, nsIHistoryEntry)
|
||||
NS_IMPL_ISUPPORTS4(nsSHEntry, nsISHContainer, nsISHEntry, nsIHistoryEntry,
|
||||
nsIDocumentObserver)
|
||||
|
||||
//*****************************************************************************
|
||||
// nsSHEntry: nsISHEntry
|
||||
|
@ -152,7 +161,21 @@ NS_IMETHODIMP nsSHEntry::SetReferrerURI(nsIURI *aReferrerURI)
|
|||
NS_IMETHODIMP
|
||||
nsSHEntry::SetContentViewer(nsIContentViewer *aViewer)
|
||||
{
|
||||
RemoveDocumentObserver();
|
||||
mContentViewer = aViewer;
|
||||
|
||||
mDocument = nsnull;
|
||||
if (mContentViewer) {
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
mContentViewer->GetDOMDocument(getter_AddRefs(domDoc));
|
||||
// Store observed document in strong pointer in case it is removed from
|
||||
// the contentviewer
|
||||
mDocument = do_QueryInterface(domDoc);
|
||||
if (mDocument) {
|
||||
mDocument->AddObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -522,15 +545,149 @@ nsSHEntry::SyncPresentationState()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// If not, then nuke all of the presentation-related members.
|
||||
DropPresentationState();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsSHEntry::DropPresentationState()
|
||||
{
|
||||
RemoveDocumentObserver();
|
||||
if (mContentViewer)
|
||||
mContentViewer->ClearHistoryEntry();
|
||||
|
||||
mContentViewer = nsnull;
|
||||
mDocument = nsnull;
|
||||
mSticky = PR_TRUE;
|
||||
mWindowState = nsnull;
|
||||
mViewerBounds.SetRect(0, 0, 0, 0);
|
||||
mChildShells.Clear();
|
||||
mRefreshURIList = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsSHEntry::RemoveDocumentObserver()
|
||||
{
|
||||
if (mDocument) {
|
||||
mDocument->RemoveObserver(this);
|
||||
mDocument = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// nsSHEntry: nsIDocumentObserver
|
||||
//*****************************************************************************
|
||||
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_CORE_STUB(nsSHEntry)
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(nsSHEntry)
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_REFLOW_STUB(nsSHEntry)
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(nsSHEntry)
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(nsSHEntry)
|
||||
|
||||
void
|
||||
nsSHEntry::CharacterDataChanged(nsIDocument* aDocument,
|
||||
nsIContent* aContent,
|
||||
PRBool aAppend)
|
||||
{
|
||||
DocumentMutated();
|
||||
}
|
||||
|
||||
void
|
||||
nsSHEntry::AttributeChanged(nsIDocument* aDocument,
|
||||
nsIContent* aContent,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aModType)
|
||||
{
|
||||
DocumentMutated();
|
||||
}
|
||||
|
||||
void
|
||||
nsSHEntry::ContentAppended(nsIDocument* aDocument,
|
||||
nsIContent* aContainer,
|
||||
PRInt32 aNewIndexInContainer)
|
||||
{
|
||||
DocumentMutated();
|
||||
}
|
||||
|
||||
void
|
||||
nsSHEntry::ContentInserted(nsIDocument* aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer)
|
||||
{
|
||||
DocumentMutated();
|
||||
}
|
||||
|
||||
void
|
||||
nsSHEntry::ContentRemoved(nsIDocument* aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer)
|
||||
{
|
||||
DocumentMutated();
|
||||
}
|
||||
|
||||
class DropPresentationEvent : public PLEvent
|
||||
{
|
||||
public:
|
||||
DropPresentationEvent(nsSHEntry* aSHEntry);
|
||||
|
||||
nsRefPtr<nsSHEntry> mSHEntry;
|
||||
};
|
||||
|
||||
PR_STATIC_CALLBACK(void*)
|
||||
HandleDropPresentationEvent(PLEvent *aEvent)
|
||||
{
|
||||
nsSHEntry* entry = NS_STATIC_CAST(DropPresentationEvent*, aEvent)->mSHEntry;
|
||||
nsCOMPtr<nsIContentViewer> viewer;
|
||||
entry->GetContentViewer(getter_AddRefs(viewer));
|
||||
if (viewer) {
|
||||
viewer->Destroy();
|
||||
}
|
||||
entry->DropPresentationState();
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(void)
|
||||
DestroyDropPresentationEvent(PLEvent *aEvent)
|
||||
{
|
||||
delete NS_STATIC_CAST(DropPresentationEvent*, aEvent);
|
||||
}
|
||||
|
||||
DropPresentationEvent::DropPresentationEvent(nsSHEntry* aSHEntry)
|
||||
: mSHEntry(aSHEntry)
|
||||
{
|
||||
PL_InitEvent(this, mSHEntry, ::HandleDropPresentationEvent,
|
||||
::DestroyDropPresentationEvent);
|
||||
}
|
||||
|
||||
void
|
||||
nsSHEntry::DocumentMutated()
|
||||
{
|
||||
NS_ASSERTION(mContentViewer && mDocument,
|
||||
"we shouldn't still be observing the doc");
|
||||
|
||||
// Release the reference to the contentviewer asynconously so that the
|
||||
// document doesn't get nuked mid-mutation.
|
||||
nsCOMPtr<nsIEventQueue> uiThreadQueue;
|
||||
NS_GetMainEventQ(getter_AddRefs(uiThreadQueue));
|
||||
if (!uiThreadQueue) {
|
||||
return;
|
||||
}
|
||||
|
||||
PLEvent *evt = new DropPresentationEvent(this);
|
||||
if (!evt) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv = uiThreadQueue->PostEvent(evt);
|
||||
if (NS_FAILED(rv)) {
|
||||
PL_DestroyEvent(evt);
|
||||
}
|
||||
|
||||
// Ensure that we don't post more then one PLEvent
|
||||
RemoveDocumentObserver();
|
||||
}
|
||||
|
|
|
@ -57,9 +57,11 @@
|
|||
#include "nsIHistoryEntry.h"
|
||||
#include "nsRect.h"
|
||||
#include "nsSupportsArray.h"
|
||||
#include "nsIDocumentObserver.h"
|
||||
|
||||
class nsSHEntry : public nsISHEntry,
|
||||
public nsISHContainer
|
||||
public nsISHContainer,
|
||||
public nsIDocumentObserver
|
||||
{
|
||||
public:
|
||||
nsSHEntry();
|
||||
|
@ -69,13 +71,19 @@ public:
|
|||
NS_DECL_NSIHISTORYENTRY
|
||||
NS_DECL_NSISHENTRY
|
||||
NS_DECL_NSISHCONTAINER
|
||||
NS_DECL_NSIDOCUMENTOBSERVER
|
||||
|
||||
void DropPresentationState();
|
||||
|
||||
private:
|
||||
~nsSHEntry();
|
||||
void RemoveDocumentObserver();
|
||||
void DocumentMutated();
|
||||
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCOMPtr<nsIURI> mReferrerURI;
|
||||
nsCOMPtr<nsIContentViewer> mContentViewer;
|
||||
nsCOMPtr<nsIDocument> mDocument; // document currently being observed
|
||||
nsString mTitle;
|
||||
nsCOMPtr<nsIInputStream> mPostData;
|
||||
nsCOMPtr<nsILayoutHistoryState> mLayoutHistoryState;
|
||||
|
|
Загрузка…
Ссылка в новой задаче