--- a/editor/composer/nsEditingSession.cpp
+++ b/editor/composer/nsEditingSession.cpp
@@ -3,16 +3,17 @@
/* 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 <string.h> // for nullptr, strcmp
#include "imgIContainer.h" // for imgIContainer, etc
#include "mozilla/FlushType.h" // for FlushType::Frames
+#include "mozilla/HTMLEditor.h" // for HTMLEditor
#include "mozilla/mozalloc.h" // for operator new
#include "nsAString.h"
#include "nsComponentManagerUtils.h" // for do_CreateInstance
#include "nsComposerCommandsUpdater.h" // for nsComposerCommandsUpdater
#include "nsContentUtils.h"
#include "nsDebug.h" // for NS_ENSURE_SUCCESS, etc
#include "nsEditingSession.h"
#include "nsError.h" // for NS_ERROR_FAILURE, NS_OK, etc
@@ -44,22 +45,25 @@
#include "nsIWebNavigation.h" // for nsIWebNavigation
#include "nsIWebProgress.h" // for nsIWebProgress, etc
#include "nsLiteralString.h" // for NS_LITERAL_STRING
#include "nsPICommandUpdater.h" // for nsPICommandUpdater
#include "nsPIDOMWindow.h" // for nsPIDOMWindow
#include "nsPresContext.h" // for nsPresContext
#include "nsReadableUtils.h" // for AppendUTF16toUTF8
#include "nsStringFwd.h" // for nsString
-#include "mozilla/dom/Selection.h" // for AutoHideSelectionChanges
+#include "mozilla/dom/Selection.h" // for AutoHideSelectionChanges, etc
#include "nsFrameSelection.h" // for nsFrameSelection
class nsISupports;
class nsIURI;
+using namespace mozilla;
+using namespace mozilla::dom;
+
/*---------------------------------------------------------------------------
nsEditingSession
----------------------------------------------------------------------------*/
nsEditingSession::nsEditingSession()
: mDoneSetup(false)
, mCanCreateEditor(false)
@@ -343,17 +347,16 @@ nsEditingSession::SetupEditorOnWindow(mo
// Enable usage of the execCommand API
htmlDocument->SetEditingState(nsIHTMLDocument::eDesignMode);
}
}
}
}
bool needHTMLController = false;
- const char *classString = "@mozilla.org/editor/htmleditor;1";
if (mEditorType.EqualsLiteral("textmail")) {
mEditorFlags = nsIPlaintextEditor::eEditorPlaintextMask |
nsIPlaintextEditor::eEditorEnableWrapHackMask |
nsIPlaintextEditor::eEditorMailMask;
} else if (mEditorType.EqualsLiteral("text")) {
mEditorFlags = nsIPlaintextEditor::eEditorPlaintextMask |
nsIPlaintextEditor::eEditorEnableWrapHackMask;
} else if (mEditorType.EqualsLiteral("htmlmail")) {
@@ -403,110 +406,112 @@ nsEditingSession::SetupEditorOnWindow(mo
mImageAnimationMode = presContext->ImageAnimationMode();
presContext->SetImageAnimationMode(imgIContainer::kDontAnimMode);
}
// Hide selection changes during initialization, in order to hide this
// from web pages.
RefPtr<nsFrameSelection> fs = presShell->FrameSelection();
NS_ENSURE_TRUE(fs, NS_ERROR_FAILURE);
- mozilla::dom::AutoHideSelectionChanges hideSelectionChanges(fs);
+ AutoHideSelectionChanges hideSelectionChanges(fs);
// create and set editor
// Try to reuse an existing editor
nsCOMPtr<nsIEditor> editor = do_QueryReferent(mExistingEditor);
- if (editor) {
- editor->PreDestroy(false);
+ RefPtr<HTMLEditor> htmlEditor = editor ? editor->AsHTMLEditor() : nullptr;
+ MOZ_ASSERT(!editor || htmlEditor);
+ if (htmlEditor) {
+ htmlEditor->PreDestroy(false);
} else {
- editor = do_CreateInstance(classString, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- mExistingEditor = do_GetWeakReference(editor);
+ htmlEditor = new HTMLEditor();
+ mExistingEditor =
+ do_GetWeakReference(static_cast<nsIEditor*>(htmlEditor.get()));
}
// set the editor on the docShell. The docShell now owns it.
- rv = docShell->SetEditor(editor);
+ rv = docShell->SetHTMLEditor(htmlEditor);
NS_ENSURE_SUCCESS(rv, rv);
// setup the HTML editor command controller
if (needHTMLController) {
// The third controller takes an nsIEditor as the context
rv = SetupEditorCommandController("@mozilla.org/editor/htmleditorcontroller;1",
- aWindow, editor,
+ aWindow,
+ static_cast<nsIEditor*>(htmlEditor),
&mHTMLCommandControllerId);
NS_ENSURE_SUCCESS(rv, rv);
}
// Set mimetype on editor
- rv = editor->SetContentsMIMEType(mimeCType.get());
+ rv = htmlEditor->SetContentsMIMEType(mimeCType.get());
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContentViewer> contentViewer;
rv = docShell->GetContentViewer(getter_AddRefs(contentViewer));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(contentViewer, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMDocument> domDoc;
rv = contentViewer->GetDOMDocument(getter_AddRefs(domDoc));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);
// Set up as a doc state listener
// Important! We must have this to broadcast the "obs_documentCreated" message
- rv = editor->AddDocumentStateListener(mStateMaintainer);
+ rv = htmlEditor->AddDocumentStateListener(mStateMaintainer);
NS_ENSURE_SUCCESS(rv, rv);
- rv = editor->Init(domDoc, nullptr /* root content */,
- nullptr, mEditorFlags, EmptyString());
+ rv = htmlEditor->Init(domDoc, nullptr /* root content */,
+ nullptr, mEditorFlags, EmptyString());
NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<nsISelection> selection;
- editor->GetSelection(getter_AddRefs(selection));
- nsCOMPtr<nsISelectionPrivate> selPriv = do_QueryInterface(selection);
- NS_ENSURE_TRUE(selPriv, NS_ERROR_FAILURE);
+ RefPtr<Selection> selection = htmlEditor->GetSelection();
+ if (NS_WARN_IF(!selection)) {
+ return NS_ERROR_FAILURE;
+ }
- rv = selPriv->AddSelectionListener(mStateMaintainer);
+ rv = selection->AddSelectionListener(mStateMaintainer);
NS_ENSURE_SUCCESS(rv, rv);
// and as a transaction listener
nsCOMPtr<nsITransactionManager> txnMgr;
- editor->GetTransactionManager(getter_AddRefs(txnMgr));
+ htmlEditor->GetTransactionManager(getter_AddRefs(txnMgr));
if (txnMgr) {
txnMgr->AddListener(mStateMaintainer);
}
// Set context on all controllers to be the editor
- rv = SetEditorOnControllers(aWindow, editor);
+ rv = SetEditorOnControllers(aWindow, htmlEditor);
NS_ENSURE_SUCCESS(rv, rv);
// Everything went fine!
mEditorStatus = eEditorOK;
// This will trigger documentCreation notification
- return editor->PostCreate();
+ return htmlEditor->PostCreate();
}
// Removes all listeners and controllers from aWindow and aEditor.
void
nsEditingSession::RemoveListenersAndControllers(nsPIDOMWindowOuter* aWindow,
- nsIEditor *aEditor)
+ HTMLEditor* aHTMLEditor)
{
- if (!mStateMaintainer || !aEditor) {
+ if (!mStateMaintainer || !aHTMLEditor) {
return;
}
// Remove all the listeners
- nsCOMPtr<nsISelection> selection;
- aEditor->GetSelection(getter_AddRefs(selection));
- nsCOMPtr<nsISelectionPrivate> selPriv = do_QueryInterface(selection);
- if (selPriv)
- selPriv->RemoveSelectionListener(mStateMaintainer);
+ RefPtr<Selection> selection = aHTMLEditor->GetSelection();
+ if (selection) {
+ selection->RemoveSelectionListener(mStateMaintainer);
+ }
- aEditor->RemoveDocumentStateListener(mStateMaintainer);
+ aHTMLEditor->RemoveDocumentStateListener(mStateMaintainer);
nsCOMPtr<nsITransactionManager> txnMgr;
- aEditor->GetTransactionManager(getter_AddRefs(txnMgr));
+ aHTMLEditor->GetTransactionManager(getter_AddRefs(txnMgr));
if (txnMgr) {
txnMgr->RemoveListener(mStateMaintainer);
}
// Remove editor controllers from the window now that we're not
// editing in that window any more.
RemoveEditorControllers(aWindow);
}
@@ -521,18 +526,16 @@ NS_IMETHODIMP
nsEditingSession::TearDownEditorOnWindow(mozIDOMWindowProxy *aWindow)
{
if (!mDoneSetup) {
return NS_OK;
}
NS_ENSURE_TRUE(aWindow, NS_ERROR_NULL_POINTER);
- nsresult rv;
-
// Kill any existing reload timer
if (mLoadBlankDocTimer) {
mLoadBlankDocTimer->Cancel();
mLoadBlankDocTimer = nullptr;
}
mDoneSetup = false;
@@ -544,51 +547,48 @@ nsEditingSession::TearDownEditorOnWindow
bool stopEditing = htmlDoc && htmlDoc->IsEditingOn();
if (stopEditing) {
RemoveWebProgressListener(window);
}
nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
NS_ENSURE_STATE(docShell);
- nsCOMPtr<nsIEditor> editor;
- rv = docShell->GetEditor(getter_AddRefs(editor));
- NS_ENSURE_SUCCESS(rv, rv);
-
+ RefPtr<HTMLEditor> htmlEditor = docShell->GetHTMLEditor();
if (stopEditing) {
- htmlDoc->TearingDownEditor(editor);
+ htmlDoc->TearingDownEditor(htmlEditor);
}
- if (mStateMaintainer && editor) {
+ if (mStateMaintainer && htmlEditor) {
// Null out the editor on the controllers first to prevent their weak
// references from pointing to a destroyed editor.
SetEditorOnControllers(aWindow, nullptr);
}
// Null out the editor on the docShell to trigger PreDestroy which
// needs to happen before document state listeners are removed below.
docShell->SetEditor(nullptr);
- RemoveListenersAndControllers(window, editor);
+ RemoveListenersAndControllers(window, htmlEditor);
if (stopEditing) {
// Make things the way they were before we started editing.
RestoreJSAndPlugins(aWindow);
RestoreAnimationMode(window);
if (mMakeWholeDocumentEditable) {
doc->SetEditableFlag(false);
nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(doc);
if (htmlDocument) {
htmlDocument->SetEditingState(nsIHTMLDocument::eOff);
}
}
}
- return rv;
+ return NS_OK;
}
/*---------------------------------------------------------------------------
GetEditorForFrame
nsIEditor getEditorForFrame (in nsIDOMWindow aWindow);
----------------------------------------------------------------------------*/
@@ -948,21 +948,17 @@ nsEditingSession::EndDocumentLoad(nsIWeb
if (makeEditable) {
// To keep pre Gecko 1.9 behavior, setup editor always when
// mMakeWholeDocumentEditable.
bool needsSetup = false;
if (mMakeWholeDocumentEditable) {
needsSetup = true;
} else {
// do we already have an editor here?
- nsCOMPtr<nsIEditor> editor;
- rv = docShell->GetEditor(getter_AddRefs(editor));
- NS_ENSURE_SUCCESS(rv, rv);
-
- needsSetup = !editor;
+ needsSetup = !docShell->GetHTMLEditor();
}
if (needsSetup) {
mCanCreateEditor = false;
rv = SetupEditorOnWindow(domWindow);
if (NS_FAILED(rv)) {
// If we had an error, setup timer to load a blank page later
if (mLoadBlankDocTimer) {
@@ -1165,17 +1161,17 @@ nsEditingSession::SetEditorOnControllers
NS_ENSURE_TRUE(aWindow, NS_ERROR_NULL_POINTER);
auto* piWindow = nsPIDOMWindowOuter::From(aWindow);
nsCOMPtr<nsIControllers> controllers;
nsresult rv = piWindow->GetControllers(getter_AddRefs(controllers));
NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<nsISupports> editorAsISupports = do_QueryInterface(aEditor);
+ nsCOMPtr<nsISupports> editorAsISupports = static_cast<nsISupports*>(aEditor);
if (mBaseCommandControllerId) {
rv = SetContextOnControllerById(controllers, editorAsISupports,
mBaseCommandControllerId);
NS_ENSURE_SUCCESS(rv, rv);
}
if (mDocStateControllerId) {
rv = SetContextOnControllerById(controllers, editorAsISupports,
@@ -1354,39 +1350,41 @@ nsEditingSession::ReattachToWindow(mozID
&mDocStateControllerId);
NS_ENSURE_SUCCESS(rv, rv);
if (mStateMaintainer) {
mStateMaintainer->Init(window);
}
// Get editor
- nsCOMPtr<nsIEditor> editor;
- rv = GetEditorForWindow(aWindow, getter_AddRefs(editor));
- NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE);
+ RefPtr<HTMLEditor> htmlEditor = GetHTMLEditorForWindow(aWindow);
+ if (NS_WARN_IF(!htmlEditor)) {
+ return NS_ERROR_FAILURE;
+ }
if (!mInteractive) {
// Disable animation of images in this document:
nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
nsPresContext* presContext = presShell->GetPresContext();
NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
mImageAnimationMode = presContext->ImageAnimationMode();
presContext->SetImageAnimationMode(imgIContainer::kDontAnimMode);
}
// The third controller takes an nsIEditor as the context
rv = SetupEditorCommandController("@mozilla.org/editor/htmleditorcontroller;1",
- aWindow, editor,
+ aWindow,
+ static_cast<nsIEditor*>(htmlEditor.get()),
&mHTMLCommandControllerId);
NS_ENSURE_SUCCESS(rv, rv);
// Set context on all controllers to be the editor
- rv = SetEditorOnControllers(aWindow, editor);
+ rv = SetEditorOnControllers(aWindow, htmlEditor);
NS_ENSURE_SUCCESS(rv, rv);
#ifdef DEBUG
{
bool isEditable;
rv = WindowIsEditable(aWindow, &isEditable);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(isEditable, "Window is not editable after reattaching editor.");
--- a/editor/composer/nsEditingSession.h
+++ b/editor/composer/nsEditingSession.h
@@ -38,16 +38,20 @@ class nsITimer;
class nsComposerCommandsUpdater;
class nsIChannel;
class nsIControllers;
class nsIDocShell;
class nsIEditor;
class nsIWebProgress;
+namespace mozilla {
+class HTMLEditor;
+} // namespace mozilla
+
class nsEditingSession final : public nsIEditingSession,
public nsIWebProgressListener,
public nsSupportsWeakReference
{
public:
nsEditingSession();
@@ -87,18 +91,19 @@ protected:
nsresult EndPageLoad(nsIWebProgress *aWebProgress,
nsIChannel* aChannel, nsresult aStatus);
bool IsProgressForTargetDocument(nsIWebProgress *aWebProgress);
void RemoveEditorControllers(nsPIDOMWindowOuter* aWindow);
void RemoveWebProgressListener(nsPIDOMWindowOuter* aWindow);
void RestoreAnimationMode(nsPIDOMWindowOuter* aWindow);
- void RemoveListenersAndControllers(nsPIDOMWindowOuter* aWindow,
- nsIEditor *aEditor);
+ void RemoveListenersAndControllers(
+ nsPIDOMWindowOuter* aWindow,
+ mozilla::HTMLEditor* aHTMLEditor);
protected:
bool mDoneSetup; // have we prepared for editing yet?
// Used to prevent double creation of editor because nsIWebProgressListener
// receives a STATE_STOP notification before the STATE_START
// for our document, so we wait for the STATE_START, then STATE_STOP