From 12abbe164f19262ec74ee5749e24a10271ee8b47 Mon Sep 17 00:00:00 2001 From: "peterv%propagandism.org" Date: Fri, 2 May 2008 11:36:31 +0000 Subject: [PATCH] Fix for bug 430624 (Crash [@ nsDocShellEditorData::DetachFromWindow] with spellcheck attribute). Patch by cpearce, r=peterv, sr=jst. git-svn-id: svn://10.0.0.236/trunk@251098 18797224-902f-48f8-a5cc-f745e15eee43 --- .../html/document/src/nsHTMLDocument.cpp | 4 + mozilla/docshell/base/nsDocShell.cpp | 101 +++++++----------- mozilla/docshell/base/nsDocShell.h | 6 +- .../docshell/base/nsDocShellEditorData.cpp | 8 +- mozilla/docshell/base/nsDocShellEditorData.h | 2 +- mozilla/docshell/base/nsIDocShell.idl | 2 +- .../docshell/shistory/public/nsISHEntry.idl | 2 +- mozilla/docshell/test/navigation/Makefile.in | 1 + .../test/navigation/test_bug430624.html | 55 ++++++++++ .../libeditor/base/crashtests/430624-1.html | 14 +++ .../libeditor/base/crashtests/crashtests.list | 1 + 11 files changed, 124 insertions(+), 72 deletions(-) create mode 100644 mozilla/docshell/test/navigation/test_bug430624.html create mode 100644 mozilla/editor/libeditor/base/crashtests/430624-1.html diff --git a/mozilla/content/html/document/src/nsHTMLDocument.cpp b/mozilla/content/html/document/src/nsHTMLDocument.cpp index c42303e3fc1..4772b1006a0 100644 --- a/mozilla/content/html/document/src/nsHTMLDocument.cpp +++ b/mozilla/content/html/document/src/nsHTMLDocument.cpp @@ -3971,6 +3971,10 @@ nsHTMLDocument::SetEditingState(EditingState aState) nsresult nsHTMLDocument::EditingStateChanged() { + if (mRemovedFromDocShell) { + return NS_OK; + } + if (mEditingState == eSettingUp || mEditingState == eTearingDown) { // XXX We shouldn't recurse. return NS_OK; diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index 3064375a1cf..3da1422f09f 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -1011,12 +1011,9 @@ nsDocShell::FirePageHideNotification(PRBool aIsUnload) kids[i]->FirePageHideNotification(aIsUnload); } } - } - - // Now make sure our editor, if any, is detached before we go - // any farther. - if (mEditorData && aIsUnload) { - DetachEditorFromWindow(); + // Now make sure our editor, if any, is detached before we go + // any farther. + DetachEditorFromWindow(); } return NS_OK; @@ -3377,11 +3374,6 @@ nsDocShell::Reload(PRUint32 aReloadFlags) } - // Need to purge detached editor here, else when we reload a page, - // the detached editor state causes SetDesignMode() to fail. - if (mOSHE) - mOSHE->SetEditorData(nsnull); - return rv; } @@ -4885,8 +4877,13 @@ nsDocShell::Embed(nsIContentViewer * aContentViewer, SetBaseUrlForWyciwyg(aContentViewer); } // XXX What if SetupNewViewer fails? - if (mLSHE) + if (mLSHE) { + // Restore the editing state, if it's stored in session history. + if (mLSHE->HasDetachedEditor()) { + ReattachEditorToWindow(mLSHE); + } SetHistoryEntry(&mOSHE, mLSHE); + } PRBool updateHistory = PR_TRUE; @@ -5332,29 +5329,20 @@ nsDocShell::CanSavePresentation(PRUint32 aLoadType, return PR_TRUE; } -PRBool -nsDocShell::HasDetachedEditor() -{ - return (mOSHE && mOSHE->HasDetachedEditor()) || - (mLSHE && mLSHE->HasDetachedEditor()); -} - void -nsDocShell::ReattachEditorToWindow(nsIDOMWindow *aWindow, nsISHEntry *aSHEntry) +nsDocShell::ReattachEditorToWindow(nsISHEntry *aSHEntry) { NS_ASSERTION(!mEditorData, "Why reattach an editor when we already have one?"); - NS_ASSERTION(aWindow, - "Need a window to reattach to."); - NS_ASSERTION(HasDetachedEditor(), + NS_ASSERTION(aSHEntry && aSHEntry->HasDetachedEditor(), "Reattaching when there's not a detached editor."); - if (mEditorData || !aWindow || !aSHEntry) + if (mEditorData || !aSHEntry) return; mEditorData = aSHEntry->ForgetEditorData(); if (mEditorData) { - nsresult res = mEditorData->ReattachToWindow(aWindow); + nsresult res = mEditorData->ReattachToWindow(this); NS_ASSERTION(NS_SUCCEEDED(res), "Failed to reattach editing session"); } } @@ -5362,18 +5350,21 @@ nsDocShell::ReattachEditorToWindow(nsIDOMWindow *aWindow, nsISHEntry *aSHEntry) void nsDocShell::DetachEditorFromWindow(nsISHEntry *aSHEntry) { - if (!aSHEntry || !mEditorData) + if (!mEditorData) return; - NS_ASSERTION(!aSHEntry->HasDetachedEditor(), - "Why detach an editor twice?"); + NS_ASSERTION(!aSHEntry || !aSHEntry->HasDetachedEditor(), + "Detaching editor when it's already detached."); nsresult res = mEditorData->DetachFromWindow(); NS_ASSERTION(NS_SUCCEEDED(res), "Failed to detach editor"); if (NS_SUCCEEDED(res)) { - // Make aSHEntry hold the owning ref to the editor data. - aSHEntry->SetEditorData(mEditorData.forget()); + // Make aSHEntry hold the owning ref to the editor data. + if (aSHEntry) + aSHEntry->SetEditorData(mEditorData.forget()); + else + mEditorData = nsnull; } #ifdef DEBUG @@ -5390,7 +5381,8 @@ nsDocShell::DetachEditorFromWindow(nsISHEntry *aSHEntry) void nsDocShell::DetachEditorFromWindow() { - DetachEditorFromWindow(mOSHE); + if (mOSHE) + DetachEditorFromWindow(mOSHE); } nsresult @@ -5542,6 +5534,10 @@ nsDocShell::FinishRestore() } } + if (mOSHE && mOSHE->HasDetachedEditor()) { + ReattachEditorToWindow(mOSHE); + } + if (mContentViewer) { nsCOMPtr domDoc; mContentViewer->GetDOMDocument(getter_AddRefs(domDoc)); @@ -6010,11 +6006,6 @@ nsDocShell::RestoreFromHistory() } } - if (HasDetachedEditor()) { - nsCOMPtr domWin = do_QueryInterface(privWin); - ReattachEditorToWindow(domWin, mLSHE); - } - // Simulate the completion of the load. nsDocShell::FinishRestore(); @@ -7153,10 +7144,6 @@ nsDocShell::InternalLoad(nsIURI * aURI, mLoadType = aLoadType; - // Detach the current editor so that it can be restored from the - // bfcache later. - DetachEditorFromWindow(); - // mLSHE should be assigned to aSHEntry, only after Stop() has // been called. But when loading an error page, do not clear the // mLSHE for the real page. @@ -7220,22 +7207,6 @@ nsDocShell::InternalLoad(nsIURI * aURI, nsCOMPtr chan(do_QueryInterface(req)); DisplayLoadError(rv, aURI, nsnull, chan); } - - if (aSHEntry) { - if (aLoadType & LOAD_CMD_HISTORY) { - // We've just loaded a page from session history. Reattach - // its editing session if it has one. - nsCOMPtr domWin; - CallGetInterface(this, static_cast(getter_AddRefs(domWin))); - ReattachEditorToWindow(domWin, aSHEntry); - } else { - // This is a non-history load from a session history entry. Purge any - // previous editing sessions, so that the the editing session will - // be recreated. This can happen when we reload something that's - // in the bfcache. - aSHEntry->SetEditorData(nsnull); - } - } return rv; } @@ -8735,9 +8706,12 @@ nsDocShell::ShouldDiscardLayoutState(nsIHttpChannel * aChannel) NS_IMETHODIMP nsDocShell::GetEditor(nsIEditor * *aEditor) { NS_ENSURE_ARG_POINTER(aEditor); - nsresult rv = EnsureEditorData(); - if (NS_FAILED(rv)) return rv; - + + if (!mEditorData) { + *aEditor = nsnull; + return NS_OK; + } + return mEditorData->GetEditor(aEditor); } @@ -9043,9 +9017,12 @@ nsDocShell::EnsureScriptEnvironment() NS_IMETHODIMP nsDocShell::EnsureEditorData() { - NS_ASSERTION(!HasDetachedEditor(), "EnsureEditorData() called when detached.\n"); - - if (!mEditorData && !mIsBeingDestroyed && !HasDetachedEditor()) { + PRBool openDocHasDetachedEditor = mOSHE && mOSHE->HasDetachedEditor(); + if (!mEditorData && !mIsBeingDestroyed && !openDocHasDetachedEditor) { + // We shouldn't recreate the editor data if it already exists, or + // we're shutting down, or we already have a detached editor data + // stored in the session history. We should only have one editordata + // per docshell. mEditorData = new nsDocShellEditorData(this); } diff --git a/mozilla/docshell/base/nsDocShell.h b/mozilla/docshell/base/nsDocShell.h index fc23d3d7284..af26a537473 100644 --- a/mozilla/docshell/base/nsDocShell.h +++ b/mozilla/docshell/base/nsDocShell.h @@ -525,7 +525,7 @@ protected: // we are it's still OK to load this URI. PRBool IsOKToLoadURI(nsIURI* aURI); - void ReattachEditorToWindow(nsIDOMWindow *aWindow, nsISHEntry *aSHEntry); + void ReattachEditorToWindow(nsISHEntry *aSHEntry); void DetachEditorFromWindow(nsISHEntry *aSHEntry); protected: @@ -677,10 +677,6 @@ protected: static nsIURIFixup *sURIFixup; - // Returns true when the currently open document has a detached editor - // waiting to be reattached. - PRBool HasDetachedEditor(); - public: class InterfaceRequestorProxy : public nsIInterfaceRequestor { public: diff --git a/mozilla/docshell/base/nsDocShellEditorData.cpp b/mozilla/docshell/base/nsDocShellEditorData.cpp index f0e0832bc8a..2c356f7fd37 100644 --- a/mozilla/docshell/base/nsDocShellEditorData.cpp +++ b/mozilla/docshell/base/nsDocShellEditorData.cpp @@ -73,12 +73,12 @@ nsDocShellEditorData::~nsDocShellEditorData() void nsDocShellEditorData::TearDownEditor() { - NS_ASSERTION(mIsDetached, "We should be detached before tearing down"); if (mEditor) { mEditor->PreDestroy(); mEditor = nsnull; } mEditingSession = nsnull; + mIsDetached = PR_FALSE; } @@ -244,12 +244,16 @@ nsDocShellEditorData::DetachFromWindow() if (htmlDoc) mDetachedEditingState = htmlDoc->GetEditingState(); + mDocShell = nsnull; + return NS_OK; } nsresult -nsDocShellEditorData::ReattachToWindow(nsIDOMWindow *aWindow) +nsDocShellEditorData::ReattachToWindow(nsIDocShell* aDocShell) { + mDocShell = aDocShell; + nsCOMPtr domWindow = do_GetInterface(mDocShell); nsresult rv = mEditingSession->ReattachToWindow(domWindow); NS_ENSURE_SUCCESS(rv, rv); diff --git a/mozilla/docshell/base/nsDocShellEditorData.h b/mozilla/docshell/base/nsDocShellEditorData.h index df34ff0e89b..c3d5f7c40dc 100644 --- a/mozilla/docshell/base/nsDocShellEditorData.h +++ b/mozilla/docshell/base/nsDocShellEditorData.h @@ -72,7 +72,7 @@ public: nsresult SetEditor(nsIEditor *inEditor); void TearDownEditor(); nsresult DetachFromWindow(); - nsresult ReattachToWindow(nsIDOMWindow *aWindow); + nsresult ReattachToWindow(nsIDocShell *aDocShell); protected: diff --git a/mozilla/docshell/base/nsIDocShell.idl b/mozilla/docshell/base/nsIDocShell.idl index dfae54e4c6d..7d1b733e1f1 100644 --- a/mozilla/docshell/base/nsIDocShell.idl +++ b/mozilla/docshell/base/nsIDocShell.idl @@ -68,7 +68,7 @@ interface nsILayoutHistoryState; interface nsISecureBrowserUI; interface nsIDOMStorage; -[scriptable, uuid(4b00222a-8d0a-46d7-a1fe-43bd89d19324)] +[scriptable, uuid(7d1cf6b9-daa3-476d-8f9f-9eb2a971a95c)] interface nsIDocShell : nsISupports { /** diff --git a/mozilla/docshell/shistory/public/nsISHEntry.idl b/mozilla/docshell/shistory/public/nsISHEntry.idl index b729de82c0c..11bb8c6311a 100644 --- a/mozilla/docshell/shistory/public/nsISHEntry.idl +++ b/mozilla/docshell/shistory/public/nsISHEntry.idl @@ -58,7 +58,7 @@ class nsDocShellEditorData; [ptr] native nsDocShellEditorDataPtr(nsDocShellEditorData); -[scriptable, uuid(abe54136-49e5-44ca-a749-290038c6b85d)] +[scriptable, uuid(c16fde76-3108-450e-8c8c-ae8286f286ed)] interface nsISHEntry : nsIHistoryEntry { /** URI for the document */ diff --git a/mozilla/docshell/test/navigation/Makefile.in b/mozilla/docshell/test/navigation/Makefile.in index 4a4b3bb3e30..7e52865039f 100644 --- a/mozilla/docshell/test/navigation/Makefile.in +++ b/mozilla/docshell/test/navigation/Makefile.in @@ -50,6 +50,7 @@ _TEST_FILES = \ test_bug278916.html \ test_bug279495.html \ test_bug386782.html \ + test_bug430624.html \ test_bug430723.html \ test_child.html \ test_grandchild.html \ diff --git a/mozilla/docshell/test/navigation/test_bug430624.html b/mozilla/docshell/test/navigation/test_bug430624.html new file mode 100644 index 00000000000..d75fe89022a --- /dev/null +++ b/mozilla/docshell/test/navigation/test_bug430624.html @@ -0,0 +1,55 @@ + + + + + Test for Bug 430624 + + + + + + +Mozilla Bug 430624 +

+ + + + +
+
+
+ + + + + + diff --git a/mozilla/editor/libeditor/base/crashtests/430624-1.html b/mozilla/editor/libeditor/base/crashtests/430624-1.html new file mode 100644 index 00000000000..bfa95c6623c --- /dev/null +++ b/mozilla/editor/libeditor/base/crashtests/430624-1.html @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/mozilla/editor/libeditor/base/crashtests/crashtests.list b/mozilla/editor/libeditor/base/crashtests/crashtests.list index e0631556523..050442c1b90 100644 --- a/mozilla/editor/libeditor/base/crashtests/crashtests.list +++ b/mozilla/editor/libeditor/base/crashtests/crashtests.list @@ -1,3 +1,4 @@ load 382527-1.html load 402172-1.html load 407256-1.html +load 430624-1.html