Fix for bug 430624 (Crash [@ nsDocShellEditorData::DetachFromWindow] with spellcheck attribute). Patch by cpearce, r=peterv, sr=jst.

This commit is contained in:
2008-05-02 04:36:29 -07:00
parent 0b309a5440
commit 05a85c8e3f
11 changed files with 124 additions and 72 deletions

View File

@@ -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<nsIDOMDocument> domDoc;
mContentViewer->GetDOMDocument(getter_AddRefs(domDoc));
@@ -6010,11 +6006,6 @@ nsDocShell::RestoreFromHistory()
}
}
if (HasDetachedEditor()) {
nsCOMPtr<nsIDOMWindow> 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<nsIChannel> 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<nsIDOMWindow> domWin;
CallGetInterface(this, static_cast<nsIDOMWindow**>(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);
}