Bug 1388001 - part2: nsEditingSession should treat editor as HTMLEditor r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 04 Aug 2017 22:53:28 +0900
changeset 645251 be80a709f4c92a94e7cc1287e676e8b6150b7fbb
parent 645250 6d11d375f6897e23b0f16de47f9a2f1d40a1e7b8
child 645252 66f01a988d5849b226f373a80ef127ebe65036cc
push id73718
push usermasayuki@d-toybox.com
push dateSat, 12 Aug 2017 02:58:16 +0000
reviewersm_kato
bugs1388001
milestone57.0a1
Bug 1388001 - part2: nsEditingSession should treat editor as HTMLEditor r?m_kato nsEditingSession should treat editor as HTMLEditor in its internal handling. MozReview-Commit-ID: 51SfY4oeq3p
editor/composer/nsEditingSession.cpp
editor/composer/nsEditingSession.h
--- 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