michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: michael@0: #include "nsDocShellEditorData.h" michael@0: #include "nsIInterfaceRequestorUtils.h" michael@0: #include "nsComponentManagerUtils.h" michael@0: #include "nsIDOMWindow.h" michael@0: #include "nsIDOMDocument.h" michael@0: #include "nsIEditor.h" michael@0: #include "nsIEditingSession.h" michael@0: #include "nsIDocShell.h" michael@0: michael@0: /*--------------------------------------------------------------------------- michael@0: michael@0: nsDocShellEditorData michael@0: michael@0: ----------------------------------------------------------------------------*/ michael@0: michael@0: nsDocShellEditorData::nsDocShellEditorData(nsIDocShell* inOwningDocShell) michael@0: : mDocShell(inOwningDocShell) michael@0: , mMakeEditable(false) michael@0: , mIsDetached(false) michael@0: , mDetachedMakeEditable(false) michael@0: , mDetachedEditingState(nsIHTMLDocument::eOff) michael@0: { michael@0: NS_ASSERTION(mDocShell, "Where is my docShell?"); michael@0: } michael@0: michael@0: michael@0: /*--------------------------------------------------------------------------- michael@0: michael@0: ~nsDocShellEditorData michael@0: michael@0: ----------------------------------------------------------------------------*/ michael@0: nsDocShellEditorData::~nsDocShellEditorData() michael@0: { michael@0: TearDownEditor(); michael@0: } michael@0: michael@0: void michael@0: nsDocShellEditorData::TearDownEditor() michael@0: { michael@0: if (mEditor) { michael@0: mEditor->PreDestroy(false); michael@0: mEditor = nullptr; michael@0: } michael@0: mEditingSession = nullptr; michael@0: mIsDetached = false; michael@0: } michael@0: michael@0: michael@0: /*--------------------------------------------------------------------------- michael@0: michael@0: MakeEditable michael@0: michael@0: ----------------------------------------------------------------------------*/ michael@0: nsresult michael@0: nsDocShellEditorData::MakeEditable(bool inWaitForUriLoad) michael@0: { michael@0: if (mMakeEditable) michael@0: return NS_OK; michael@0: michael@0: // if we are already editable, and are getting turned off, michael@0: // nuke the editor. michael@0: if (mEditor) michael@0: { michael@0: NS_WARNING("Destroying existing editor on frame"); michael@0: michael@0: mEditor->PreDestroy(false); michael@0: mEditor = nullptr; michael@0: } michael@0: michael@0: if (inWaitForUriLoad) michael@0: mMakeEditable = true; michael@0: return NS_OK; michael@0: } michael@0: michael@0: michael@0: /*--------------------------------------------------------------------------- michael@0: michael@0: GetEditable michael@0: michael@0: ----------------------------------------------------------------------------*/ michael@0: bool michael@0: nsDocShellEditorData::GetEditable() michael@0: { michael@0: return mMakeEditable || (mEditor != nullptr); michael@0: } michael@0: michael@0: /*--------------------------------------------------------------------------- michael@0: michael@0: CreateEditor michael@0: michael@0: ----------------------------------------------------------------------------*/ michael@0: nsresult michael@0: nsDocShellEditorData::CreateEditor() michael@0: { michael@0: nsCOMPtr editingSession; michael@0: nsresult rv = GetEditingSession(getter_AddRefs(editingSession)); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: nsCOMPtr domWindow = do_GetInterface(mDocShell); michael@0: rv = editingSession->SetupEditorOnWindow(domWindow); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: michael@0: /*--------------------------------------------------------------------------- michael@0: michael@0: GetEditingSession michael@0: michael@0: ----------------------------------------------------------------------------*/ michael@0: nsresult michael@0: nsDocShellEditorData::GetEditingSession(nsIEditingSession **outEditingSession) michael@0: { michael@0: nsresult rv = EnsureEditingSession(); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: NS_ADDREF(*outEditingSession = mEditingSession); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: michael@0: /*--------------------------------------------------------------------------- michael@0: michael@0: GetEditor michael@0: michael@0: ----------------------------------------------------------------------------*/ michael@0: nsresult michael@0: nsDocShellEditorData::GetEditor(nsIEditor **outEditor) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(outEditor); michael@0: NS_IF_ADDREF(*outEditor = mEditor); michael@0: return NS_OK; michael@0: } michael@0: michael@0: michael@0: /*--------------------------------------------------------------------------- michael@0: michael@0: SetEditor michael@0: michael@0: ----------------------------------------------------------------------------*/ michael@0: nsresult michael@0: nsDocShellEditorData::SetEditor(nsIEditor *inEditor) michael@0: { michael@0: // destroy any editor that we have. Checks for equality are michael@0: // necessary to ensure that assigment into the nsCOMPtr does michael@0: // not temporarily reduce the refCount of the editor to zero michael@0: if (mEditor.get() != inEditor) michael@0: { michael@0: if (mEditor) michael@0: { michael@0: mEditor->PreDestroy(false); michael@0: mEditor = nullptr; michael@0: } michael@0: michael@0: mEditor = inEditor; // owning addref michael@0: if (!mEditor) michael@0: mMakeEditable = false; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: michael@0: /*--------------------------------------------------------------------------- michael@0: michael@0: EnsureEditingSession michael@0: michael@0: This creates the editing session on the content docShell that owns michael@0: 'this'. michael@0: michael@0: ----------------------------------------------------------------------------*/ michael@0: nsresult michael@0: nsDocShellEditorData::EnsureEditingSession() michael@0: { michael@0: NS_ASSERTION(mDocShell, "Should have docShell here"); michael@0: NS_ASSERTION(!mIsDetached, "This will stomp editing session!"); michael@0: michael@0: nsresult rv = NS_OK; michael@0: michael@0: if (!mEditingSession) michael@0: { michael@0: mEditingSession = michael@0: do_CreateInstance("@mozilla.org/editor/editingsession;1", &rv); michael@0: } michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: nsresult michael@0: nsDocShellEditorData::DetachFromWindow() michael@0: { michael@0: NS_ASSERTION(mEditingSession, michael@0: "Can't detach when we don't have a session to detach!"); michael@0: michael@0: nsCOMPtr domWindow = do_GetInterface(mDocShell); michael@0: nsresult rv = mEditingSession->DetachFromWindow(domWindow); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: mIsDetached = true; michael@0: mDetachedMakeEditable = mMakeEditable; michael@0: mMakeEditable = false; michael@0: michael@0: nsCOMPtr domDoc; michael@0: domWindow->GetDocument(getter_AddRefs(domDoc)); michael@0: nsCOMPtr htmlDoc = do_QueryInterface(domDoc); michael@0: if (htmlDoc) michael@0: mDetachedEditingState = htmlDoc->GetEditingState(); michael@0: michael@0: mDocShell = nullptr; michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: nsDocShellEditorData::ReattachToWindow(nsIDocShell* aDocShell) michael@0: { michael@0: mDocShell = aDocShell; michael@0: michael@0: nsCOMPtr domWindow = do_GetInterface(mDocShell); michael@0: nsresult rv = mEditingSession->ReattachToWindow(domWindow); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: mIsDetached = false; michael@0: mMakeEditable = mDetachedMakeEditable; michael@0: michael@0: nsCOMPtr domDoc; michael@0: domWindow->GetDocument(getter_AddRefs(domDoc)); michael@0: nsCOMPtr htmlDoc = do_QueryInterface(domDoc); michael@0: if (htmlDoc) michael@0: htmlDoc->SetEditingState(mDetachedEditingState); michael@0: michael@0: return NS_OK; michael@0: }