diff options
Diffstat (limited to 'docshell/base/nsDocShellEditorData.cpp')
-rw-r--r-- | docshell/base/nsDocShellEditorData.cpp | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/docshell/base/nsDocShellEditorData.cpp b/docshell/base/nsDocShellEditorData.cpp new file mode 100644 index 000000000..7e4068eb9 --- /dev/null +++ b/docshell/base/nsDocShellEditorData.cpp @@ -0,0 +1,192 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsDocShellEditorData.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsComponentManagerUtils.h" +#include "nsPIDOMWindow.h" +#include "nsIDOMDocument.h" +#include "nsIEditor.h" +#include "nsIEditingSession.h" +#include "nsIDocShell.h" + +nsDocShellEditorData::nsDocShellEditorData(nsIDocShell* aOwningDocShell) + : mDocShell(aOwningDocShell) + , mMakeEditable(false) + , mIsDetached(false) + , mDetachedMakeEditable(false) + , mDetachedEditingState(nsIHTMLDocument::eOff) +{ + NS_ASSERTION(mDocShell, "Where is my docShell?"); +} + +nsDocShellEditorData::~nsDocShellEditorData() +{ + TearDownEditor(); +} + +void +nsDocShellEditorData::TearDownEditor() +{ + if (mEditor) { + mEditor->PreDestroy(false); + mEditor = nullptr; + } + mEditingSession = nullptr; + mIsDetached = false; +} + +nsresult +nsDocShellEditorData::MakeEditable(bool aInWaitForUriLoad) +{ + if (mMakeEditable) { + return NS_OK; + } + + // if we are already editable, and are getting turned off, + // nuke the editor. + if (mEditor) { + NS_WARNING("Destroying existing editor on frame"); + + mEditor->PreDestroy(false); + mEditor = nullptr; + } + + if (aInWaitForUriLoad) { + mMakeEditable = true; + } + return NS_OK; +} + +bool +nsDocShellEditorData::GetEditable() +{ + return mMakeEditable || (mEditor != nullptr); +} + +nsresult +nsDocShellEditorData::CreateEditor() +{ + nsCOMPtr<nsIEditingSession> editingSession; + nsresult rv = GetEditingSession(getter_AddRefs(editingSession)); + if (NS_FAILED(rv)) { + return rv; + } + + nsCOMPtr<nsPIDOMWindowOuter> domWindow = + mDocShell ? mDocShell->GetWindow() : nullptr; + rv = editingSession->SetupEditorOnWindow(domWindow); + if (NS_FAILED(rv)) { + return rv; + } + + return NS_OK; +} + +nsresult +nsDocShellEditorData::GetEditingSession(nsIEditingSession** aResult) +{ + nsresult rv = EnsureEditingSession(); + NS_ENSURE_SUCCESS(rv, rv); + + NS_ADDREF(*aResult = mEditingSession); + + return NS_OK; +} + +nsresult +nsDocShellEditorData::GetEditor(nsIEditor** aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + NS_IF_ADDREF(*aResult = mEditor); + return NS_OK; +} + +nsresult +nsDocShellEditorData::SetEditor(nsIEditor* aEditor) +{ + // destroy any editor that we have. Checks for equality are + // necessary to ensure that assigment into the nsCOMPtr does + // not temporarily reduce the refCount of the editor to zero + if (mEditor.get() != aEditor) { + if (mEditor) { + mEditor->PreDestroy(false); + mEditor = nullptr; + } + + mEditor = aEditor; // owning addref + if (!mEditor) { + mMakeEditable = false; + } + } + + return NS_OK; +} + +// This creates the editing session on the content docShell that owns 'this'. +nsresult +nsDocShellEditorData::EnsureEditingSession() +{ + NS_ASSERTION(mDocShell, "Should have docShell here"); + NS_ASSERTION(!mIsDetached, "This will stomp editing session!"); + + nsresult rv = NS_OK; + + if (!mEditingSession) { + mEditingSession = + do_CreateInstance("@mozilla.org/editor/editingsession;1", &rv); + } + + return rv; +} + +nsresult +nsDocShellEditorData::DetachFromWindow() +{ + NS_ASSERTION(mEditingSession, + "Can't detach when we don't have a session to detach!"); + + nsCOMPtr<nsPIDOMWindowOuter> domWindow = + mDocShell ? mDocShell->GetWindow() : nullptr; + nsresult rv = mEditingSession->DetachFromWindow(domWindow); + NS_ENSURE_SUCCESS(rv, rv); + + mIsDetached = true; + mDetachedMakeEditable = mMakeEditable; + mMakeEditable = false; + + nsCOMPtr<nsIDocument> doc = domWindow->GetDoc(); + nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(doc); + if (htmlDoc) { + mDetachedEditingState = htmlDoc->GetEditingState(); + } + + mDocShell = nullptr; + + return NS_OK; +} + +nsresult +nsDocShellEditorData::ReattachToWindow(nsIDocShell* aDocShell) +{ + mDocShell = aDocShell; + + nsCOMPtr<nsPIDOMWindowOuter> domWindow = + mDocShell ? mDocShell->GetWindow() : nullptr; + nsresult rv = mEditingSession->ReattachToWindow(domWindow); + NS_ENSURE_SUCCESS(rv, rv); + + mIsDetached = false; + mMakeEditable = mDetachedMakeEditable; + + nsCOMPtr<nsIDocument> doc = domWindow->GetDoc(); + nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(doc); + if (htmlDoc) { + htmlDoc->SetEditingState(mDetachedEditingState); + } + + return NS_OK; +} |