Bug 386782. save and restore editor state so that it isn't lost when a page goes into the bfcache and then comes back. patch by Chris Pearce, r+sr=peterv,a=beltzner

This commit is contained in:
2008-04-23 14:36:17 -07:00
parent 3ba669d01f
commit c8c3e7e610
17 changed files with 660 additions and 186 deletions

View File

@@ -120,6 +120,7 @@
#include "nsCDefaultURIFixup.h"
#include "nsDocShellEnumerator.h"
#include "nsSHistory.h"
#include "nsDocShellEditorData.h"
// Helper Classes
#include "nsDOMError.h"
@@ -306,7 +307,6 @@ nsDocShell::nsDocShell():
mDefaultScrollbarPref(Scrollbar_Auto, Scrollbar_Auto),
mPreviousTransIndex(-1),
mLoadedTransIndex(-1),
mEditorData(nsnull),
mTreeOwner(nsnull),
mChromeEventHandler(nsnull)
#ifdef DEBUG
@@ -1013,10 +1013,10 @@ nsDocShell::FirePageHideNotification(PRBool aIsUnload)
}
}
// Now make sure our editor, if any, is torn down before we go
// Now make sure our editor, if any, is detached before we go
// any farther.
if (mEditorData && aIsUnload) {
mEditorData->TearDownEditor();
DetachEditorFromWindow();
}
return NS_OK;
@@ -3352,6 +3352,12 @@ nsDocShell::Reload(PRUint32 aReloadFlags)
nsnull); // No nsIRequest
}
// 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;
}
@@ -3663,8 +3669,7 @@ nsDocShell::Destroy()
// Stop any URLs that are currently being loaded...
Stop(nsIWebNavigation::STOP_ALL);
delete mEditorData;
mEditorData = 0;
mEditorData = nsnull;
mTransferableHookData = nsnull;
@@ -5303,6 +5308,67 @@ nsDocShell::CanSavePresentation(PRUint32 aLoadType,
return PR_TRUE;
}
PRBool
nsDocShell::HasDetachedEditor()
{
return (mOSHE && mOSHE->HasDetachedEditor()) ||
(mLSHE && mLSHE->HasDetachedEditor());
}
void
nsDocShell::ReattachEditorToWindow(nsIDOMWindow *aWindow, 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(),
"Reattaching when there's not a detached editor.");
if (mEditorData || !aWindow || !aSHEntry)
return;
mEditorData = aSHEntry->ForgetEditorData();
if (mEditorData) {
nsresult res = mEditorData->ReattachToWindow(aWindow);
NS_ASSERTION(NS_SUCCEEDED(res), "Failed to reattach editing session");
}
}
void
nsDocShell::DetachEditorFromWindow(nsISHEntry *aSHEntry)
{
if (!aSHEntry || !mEditorData)
return;
NS_ASSERTION(!aSHEntry->HasDetachedEditor(),
"Why detach an editor twice?");
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());
}
#ifdef DEBUG
{
PRBool isEditable;
GetEditable(&isEditable);
NS_ASSERTION(!isEditable,
"Window is still editable after detaching editor.");
}
#endif // DEBUG
}
void
nsDocShell::DetachEditorFromWindow()
{
DetachEditorFromWindow(mOSHE);
}
nsresult
nsDocShell::CaptureState()
{
@@ -5920,6 +5986,11 @@ nsDocShell::RestoreFromHistory()
}
}
if (HasDetachedEditor()) {
nsCOMPtr<nsIDOMWindow> domWin = do_QueryInterface(privWin);
ReattachEditorToWindow(domWin, mLSHE);
}
// Simulate the completion of the load.
nsDocShell::FinishRestore();
@@ -7045,7 +7116,11 @@ 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.
@@ -7110,6 +7185,22 @@ nsDocShell::InternalLoad(nsIURI * aURI,
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;
}
@@ -8916,10 +9007,10 @@ nsDocShell::EnsureScriptEnvironment()
NS_IMETHODIMP
nsDocShell::EnsureEditorData()
{
if (!mEditorData && !mIsBeingDestroyed)
{
NS_ASSERTION(!HasDetachedEditor(), "EnsureEditorData() called when detached.\n");
if (!mEditorData && !mIsBeingDestroyed && !HasDetachedEditor()) {
mEditorData = new nsDocShellEditorData(this);
if (!mEditorData) return NS_ERROR_OUT_OF_MEMORY;
}
return mEditorData ? NS_OK : NS_ERROR_NOT_AVAILABLE;