Bug 1456879 - Clean up spellchecker not to use nsIDOM* if possible. r?masayuki draft
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Wed, 25 Apr 2018 17:39:50 +0900
changeset 787865 4f8b3b5e98083d9ef6d28d1eb8aec9610c333dfc
parent 787860 7f6a582f00bfb5d0acb8d8bf7f8c79ca37c99b65
push id107821
push userbmo:m_kato@ga2.so-net.ne.jp
push dateWed, 25 Apr 2018 15:33:20 +0000
reviewersmasayuki
bugs1456879
milestone61.0a1
Bug 1456879 - Clean up spellchecker not to use nsIDOM* if possible. r?masayuki Without XPCOM and related method, I want to remove dependencies of nsIDOM* from spellchecker. Also, it is unnecessary to use nsISelectionPrivate since we can use mozilla::dom::Selection instead. MozReview-Commit-ID: 1Zheq3Hsepj
extensions/spellcheck/src/mozInlineSpellChecker.cpp
extensions/spellcheck/src/mozInlineSpellChecker.h
extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
extensions/spellcheck/src/mozInlineSpellWordUtil.h
--- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp
@@ -45,28 +45,23 @@
 #include "mozilla/dom/MouseEvent.h"
 #include "mozilla/dom/Selection.h"
 #include "mozInlineSpellWordUtil.h"
 #include "mozISpellI18NManager.h"
 #include "mozISpellI18NUtil.h"
 #include "nsCOMPtr.h"
 #include "nsCRT.h"
 #include "nsIDOMNode.h"
-#include "nsIDOMDocument.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMNode.h"
-#include "nsIDOMNodeList.h"
 #include "nsGenericHTMLElement.h"
 #include "nsRange.h"
 #include "nsIPlaintextEditor.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
 #include "nsIRunnable.h"
 #include "nsISelection.h"
-#include "nsISelectionPrivate.h"
 #include "nsISelectionController.h"
 #include "nsIServiceManager.h"
 #include "nsITextServicesFilter.h"
 #include "nsString.h"
 #include "nsThreadUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsIContent.h"
 #include "nsIContentInlines.h"
@@ -362,17 +357,17 @@ mozInlineSpellStatus::FinishNavigationEv
   if (NS_WARN_IF(err.Failed())) {
     return err.StealNSResult();
   }
   uint32_t oldAnchorOffset = mOldNavigationAnchorRange->StartOffset();
 
   // find the word on the old caret position, this is the one that we MAY need
   // to check
   RefPtr<nsRange> oldWord;
-  nsresult rv = aWordUtil.GetRangeForWord(oldAnchorNode->AsDOMNode(),
+  nsresult rv = aWordUtil.GetRangeForWord(oldAnchorNode,
                                           static_cast<int32_t>(oldAnchorOffset),
                                           getter_AddRefs(oldWord));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // aWordUtil.GetRangeForWord flushes pending notifications, check editor again.
   if (!mSpellChecker->mTextEditor) {
     return NS_ERROR_FAILURE; // editor is gone
   }
@@ -423,24 +418,24 @@ mozInlineSpellStatus::FillNoCheckRangeFr
 {
   ErrorResult err;
   nsCOMPtr<nsINode> anchorNode = mAnchorRange->GetStartContainer(err);
   if (NS_WARN_IF(err.Failed())) {
     return err.StealNSResult();
   }
 
   uint32_t anchorOffset = mAnchorRange->StartOffset();
-  return aWordUtil.GetRangeForWord(anchorNode->AsDOMNode(),
+  return aWordUtil.GetRangeForWord(anchorNode,
                                    static_cast<int32_t>(anchorOffset),
                                    getter_AddRefs(mNoCheckRange));
 }
 
 // mozInlineSpellStatus::GetDocument
 //
-//    Returns the nsIDOMDocument object for the document for the
+//    Returns the nsIDocument object for the document for the
 //    current spellchecker.
 
 nsIDocument*
 mozInlineSpellStatus::GetDocument() const
 {
   if (!mSpellChecker->mTextEditor) {
     return nullptr;
   }
@@ -932,17 +927,17 @@ mozInlineSpellChecker::GetMisspelledWord
 {
   if (NS_WARN_IF(!aNode)) {
     return NS_ERROR_INVALID_ARG;
   }
   RefPtr<Selection> spellCheckSelection = GetSpellCheckSelection();
   if (NS_WARN_IF(!spellCheckSelection)) {
     return NS_ERROR_FAILURE;
   }
-  return IsPointInSelection(spellCheckSelection, aNode, aOffset, newword);
+  return IsPointInSelection(*spellCheckSelection, aNode, aOffset, newword);
 }
 
 // mozInlineSpellChecker::ReplaceWord
 
 NS_IMETHODIMP
 mozInlineSpellChecker::ReplaceWord(nsIDOMNode *aNode, int32_t aOffset,
                                    const nsAString &newword)
 {
@@ -1045,45 +1040,43 @@ mozInlineSpellChecker::IgnoreWords(const
 
 void
 mozInlineSpellChecker::DidSplitNode(nsINode* aExistingRightNode,
                                     nsINode* aNewLeftNode)
 {
   if (!mIsListeningToEditActions) {
     return;
   }
-  nsIDOMNode* newLeftDOMNode =
-    aNewLeftNode ? aNewLeftNode->AsDOMNode() : nullptr;
-  SpellCheckBetweenNodes(newLeftDOMNode, 0, newLeftDOMNode, 0);
+  SpellCheckBetweenNodes(aNewLeftNode, 0, aNewLeftNode, 0);
 }
 
 void
 mozInlineSpellChecker::DidJoinNodes(nsINode& aLeftNode,
                                     nsINode& aRightNode)
 {
   if (!mIsListeningToEditActions) {
     return;
   }
-  SpellCheckBetweenNodes(aRightNode.AsDOMNode(), 0, aRightNode.AsDOMNode(), 0);
+  SpellCheckBetweenNodes(&aRightNode, 0, &aRightNode, 0);
 }
 
 // mozInlineSpellChecker::MakeSpellCheckRange
 //
 //    Given begin and end positions, this function constructs a range as
 //    required for ScheduleSpellCheck. If the start and end nodes are nullptr,
 //    then the entire range will be selected, and you can supply -1 as the
 //    offset to the end range to select all of that node.
 //
 //    If the resulting range would be empty, nullptr is put into *aRange and the
 //    function succeeds.
 
 nsresult
 mozInlineSpellChecker::MakeSpellCheckRange(
-    nsIDOMNode* aStartNode, int32_t aStartOffset,
-    nsIDOMNode* aEndNode, int32_t aEndOffset,
+    nsINode* aStartNode, int32_t aStartOffset,
+    nsINode* aEndNode, int32_t aEndOffset,
     nsRange** aRange)
 {
   nsresult rv;
   *aRange = nullptr;
 
   if (NS_WARN_IF(!mTextEditor)) {
     return NS_ERROR_FAILURE;
   }
@@ -1092,66 +1085,62 @@ mozInlineSpellChecker::MakeSpellCheckRan
   if (NS_WARN_IF(!doc)) {
     return NS_ERROR_FAILURE;
   }
 
   RefPtr<nsRange> range = new nsRange(doc);
 
   // possibly use full range of the editor
   if (! aStartNode || ! aEndNode) {
-    nsCOMPtr<nsIDOMElement> domRootElement =
-      do_QueryInterface(mTextEditor->GetRoot());
+    Element* domRootElement = mTextEditor->GetRoot();
     if (NS_WARN_IF(!domRootElement)) {
       return NS_ERROR_FAILURE;
     }
     aStartNode = aEndNode = domRootElement;
     aStartOffset = 0;
     aEndOffset = -1;
   }
 
   if (aEndOffset == -1) {
     // It's hard to say whether it's better to just do nsINode::GetChildCount or
     // get the ChildNodes() and then its length.  The latter is faster if we
     // keep going through this code for the same nodes (because it caches the
     // length).  The former is faster if we keep getting different nodes here...
     //
     // Let's do the thing which can't end up with bad O(N^2) behavior.
-    nsCOMPtr<nsINode> endNode = do_QueryInterface(aEndNode);
-    aEndOffset = endNode->ChildNodes()->Length();
+    aEndOffset = aEndNode->ChildNodes()->Length();
   }
 
   // sometimes we are are requested to check an empty range (possibly an empty
   // document). This will result in assertions later.
   if (aStartNode == aEndNode && aStartOffset == aEndOffset)
     return NS_OK;
 
-  nsCOMPtr<nsINode> startNode = do_QueryInterface(aStartNode);
-  nsCOMPtr<nsINode> endNode = do_QueryInterface(aEndNode);
   if (aEndOffset) {
-    rv = range->SetStartAndEnd(startNode, aStartOffset, endNode, aEndOffset);
+    rv = range->SetStartAndEnd(aStartNode, aStartOffset, aEndNode, aEndOffset);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   } else {
     uint32_t endOffset;
-    endNode = nsRange::GetContainerAndOffsetAfter(endNode, &endOffset);
-    rv = range->SetStartAndEnd(startNode, aStartOffset, endNode, endOffset);
+    aEndNode = nsRange::GetContainerAndOffsetAfter(aEndNode, &endOffset);
+    rv = range->SetStartAndEnd(aStartNode, aStartOffset, aEndNode, endOffset);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   range.swap(*aRange);
   return NS_OK;
 }
 
 nsresult
-mozInlineSpellChecker::SpellCheckBetweenNodes(nsIDOMNode *aStartNode,
+mozInlineSpellChecker::SpellCheckBetweenNodes(nsINode *aStartNode,
                                               int32_t aStartOffset,
-                                              nsIDOMNode *aEndNode,
+                                              nsINode *aEndNode,
                                               int32_t aEndOffset)
 {
   RefPtr<nsRange> range;
   nsresult rv = MakeSpellCheckRange(aStartNode, aStartOffset,
                                     aEndNode, aEndOffset,
                                     getter_AddRefs(range));
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -1626,29 +1615,28 @@ mozInlineSpellChecker::ResumeCheck(Uniqu
 //    Determines if a given (node,offset) point is inside the given
 //    selection. If so, the specific range of the selection that
 //    intersects is places in *aRange. (There may be multiple disjoint
 //    ranges in a selection.)
 //
 //    If there is no intersection, *aRange will be nullptr.
 
 nsresult
-mozInlineSpellChecker::IsPointInSelection(nsISelection *aSelection,
+mozInlineSpellChecker::IsPointInSelection(Selection& aSelection,
                                           nsIDOMNode *aNode,
                                           int32_t aOffset,
                                           nsIDOMRange **aRange)
 {
   *aRange = nullptr;
 
-  nsCOMPtr<nsISelectionPrivate> privSel(do_QueryInterface(aSelection));
-
   nsTArray<nsRange*> ranges;
   nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
-  nsresult rv = privSel->GetRangesForIntervalArray(node, aOffset, node, aOffset,
-                                                   true, &ranges);
+  nsresult rv = aSelection.GetRangesForIntervalArray(node, aOffset,
+                                                     node, aOffset,
+                                                     true, &ranges);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (ranges.Length() == 0)
     return NS_OK; // no matches
 
   // there may be more than one range returned, and we don't know what do
   // do with that, so just get the first one
   NS_ADDREF(*aRange = ranges[0]);
--- a/extensions/spellcheck/src/mozInlineSpellChecker.h
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.h
@@ -57,18 +57,20 @@ public:
   RefPtr<mozInlineSpellChecker> mSpellChecker;
 
   // The total number of words checked in this sequence, using this tally tells
   // us when to stop. This count is preserved as we continue checking in new
   // messages.
   int32_t mWordCount;
 
   // what happened?
-  enum Operation { eOpChange,       // for SpellCheckAfterChange except deleteSelection
-                   eOpChangeDelete, // for SpellCheckAfterChange deleteSelection
+  enum Operation { eOpChange,       // for SpellCheckAfterEditorChange except
+                                    // deleteSelection
+                   eOpChangeDelete, // for SpellCheckAfterEditorChange with
+                                    // deleteSelection
                    eOpNavigation,   // for HandleNavigationEvent
                    eOpSelection,    // re-check all misspelled words
                    eOpResume };     // for resuming a previously started check
   Operation mOp;
 
   // Used for events where we have already computed the range to use. It can
   // also be nullptr in these cases where we need to check the entire range.
   RefPtr<nsRange> mRange;
@@ -196,57 +198,53 @@ public:
 
   nsresult OnBlur(mozilla::dom::Event* aEvent);
   nsresult OnMouseClick(mozilla::dom::Event* aMouseEvent);
   nsresult OnKeyPress(mozilla::dom::Event* aKeyEvent);
 
   mozInlineSpellChecker();
 
   // spell checks all of the words between two nodes
-  nsresult SpellCheckBetweenNodes(nsIDOMNode *aStartNode,
+  nsresult SpellCheckBetweenNodes(nsINode* aStartNode,
                                   int32_t aStartOffset,
-                                  nsIDOMNode *aEndNode,
+                                  nsINode* aEndNode,
                                   int32_t aEndOffset);
 
   // examines the dom node in question and returns true if the inline spell
   // checker should skip the node (i.e. the text is inside of a block quote
   // or an e-mail signature...)
   bool ShouldSpellCheckNode(mozilla::TextEditor* aTextEditor, nsINode *aNode);
 
-  nsresult SpellCheckAfterChange(nsIDOMNode* aCursorNode, int32_t aCursorOffset,
-                                 nsIDOMNode* aPreviousNode, int32_t aPreviousOffset,
-                                 nsISelection* aSpellCheckSelection);
-
   // spell check the text contained within aRange, potentially scheduling
   // another check in the future if the time threshold is reached
   nsresult ScheduleSpellCheck(mozilla::UniquePtr<mozInlineSpellStatus>&& aStatus);
 
   nsresult DoSpellCheckSelection(mozInlineSpellWordUtil& aWordUtil,
                                  mozilla::dom::Selection* aSpellCheckSelection);
   nsresult DoSpellCheck(mozInlineSpellWordUtil& aWordUtil,
                         mozilla::dom::Selection *aSpellCheckSelection,
                         const mozilla::UniquePtr<mozInlineSpellStatus>& aStatus,
                         bool* aDoneChecking);
 
   // helper routine to determine if a point is inside of the passed in selection.
-  nsresult IsPointInSelection(nsISelection *aSelection,
+  nsresult IsPointInSelection(mozilla::dom::Selection& aSelection,
                               nsIDOMNode *aNode,
                               int32_t aOffset,
                               nsIDOMRange **aRange);
 
   nsresult CleanupRangesInSelection(mozilla::dom::Selection *aSelection);
 
   nsresult RemoveRange(mozilla::dom::Selection *aSpellCheckSelection,
                        nsRange *aRange);
   nsresult AddRange(mozilla::dom::Selection *aSpellCheckSelection,
                     nsRange* aRange);
   bool     SpellCheckSelectionIsFull() { return mNumWordsInSpellSelection >= mMaxNumWordsInSpellSelection; }
 
-  nsresult MakeSpellCheckRange(nsIDOMNode* aStartNode, int32_t aStartOffset,
-                               nsIDOMNode* aEndNode, int32_t aEndOffset,
+  nsresult MakeSpellCheckRange(nsINode* aStartNode, int32_t aStartOffset,
+                               nsINode* aEndNode, int32_t aEndOffset,
                                nsRange** aRange);
 
   // DOM and editor event registration helper routines
   nsresult RegisterEventListeners();
   nsresult UnregisterEventListeners();
   nsresult HandleNavigationEvent(bool aForceWordSpellCheck, int32_t aNewPositionOffset = 0);
 
   already_AddRefed<mozilla::dom::Selection> GetSpellCheckSelection();
--- a/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
@@ -7,20 +7,17 @@
 
 #include "mozilla/BinarySearch.h"
 #include "mozilla/TextEditor.h"
 #include "mozilla/dom/Element.h"
 
 #include "nsDebug.h"
 #include "nsAtom.h"
 #include "nsComponentManagerUtils.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMRange.h"
 #include "nsIEditor.h"
-#include "nsIDOMNode.h"
 #include "nsUnicodeProperties.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIContent.h"
 #include "nsTextFragment.h"
 #include "nsRange.h"
 #include "nsContentUtils.h"
 #include "nsIFrame.h"
 #include <algorithm>
@@ -57,17 +54,16 @@ mozInlineSpellWordUtil::Init(TextEditor*
   if (NS_WARN_IF(!aTextEditor)) {
     return NS_ERROR_FAILURE;
   }
 
   mDocument = aTextEditor->GetDocument();
   if (NS_WARN_IF(!mDocument)) {
     return NS_ERROR_FAILURE;
   }
-  mDOMDocument = do_QueryInterface(mDocument);
 
   // Find the root node for the editor. For contenteditable we'll need something
   // cleverer here.
   mRootNode = aTextEditor->GetRoot();
   if (NS_WARN_IF(!mRootNode)) {
     return NS_ERROR_FAILURE;
   }
   return NS_OK;
@@ -237,23 +233,22 @@ mozInlineSpellWordUtil::MakeNodeOffsetRa
   NodeOffset begin = MapSoftTextOffsetToDOMPosition(aWord.mSoftTextOffset, HINT_BEGIN);
   NodeOffset end = MapSoftTextOffsetToDOMPosition(aWord.EndOffset(), HINT_END);
   *aNodeOffsetRange = NodeOffsetRange(begin, end);
 }
 
 // mozInlineSpellWordUtil::GetRangeForWord
 
 nsresult
-mozInlineSpellWordUtil::GetRangeForWord(nsIDOMNode* aWordNode,
+mozInlineSpellWordUtil::GetRangeForWord(nsINode* aWordNode,
                                         int32_t aWordOffset,
                                         nsRange** aRange)
 {
   // Set our soft end and start
-  nsCOMPtr<nsINode> wordNode = do_QueryInterface(aWordNode);
-  NodeOffset pt = NodeOffset(wordNode, aWordOffset);
+  NodeOffset pt = NodeOffset(aWordNode, aWordOffset);
 
   if (!mSoftTextValid || pt != mSoftBegin || pt != mSoftEnd) {
     InvalidateWords();
     mSoftBegin = mSoftEnd = pt;
     nsresult rv = EnsureWords();
     if (NS_FAILED(rv)) {
       return rv;
     }
@@ -330,18 +325,19 @@ mozInlineSpellWordUtil::GetNextWord(nsAS
 //
 //    Convenience function for creating a range over the current document.
 
 nsresult
 mozInlineSpellWordUtil::MakeRange(NodeOffset aBegin, NodeOffset aEnd,
                                   nsRange** aRange)
 {
   NS_ENSURE_ARG_POINTER(aBegin.mNode);
-  if (!mDOMDocument)
+  if (!mDocument) {
     return NS_ERROR_NOT_INITIALIZED;
+  }
 
   RefPtr<nsRange> range = new nsRange(aBegin.mNode);
   nsresult rv = range->SetStartAndEnd(aBegin.mNode, aBegin.mOffset,
                                       aEnd.mNode, aEnd.mOffset);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   range.forget(aRange);
--- a/extensions/spellcheck/src/mozInlineSpellWordUtil.h
+++ b/extensions/spellcheck/src/mozInlineSpellWordUtil.h
@@ -1,18 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #ifndef mozInlineSpellWordUtil_h
 #define mozInlineSpellWordUtil_h
 
+#include "mozilla/Attributes.h"
 #include "nsCOMPtr.h"
-#include "nsIDOMDocument.h"
 #include "nsIDocument.h"
 #include "nsString.h"
 #include "nsTArray.h"
 
 //#define DEBUG_SPELLCHECK
 
 class nsRange;
 class nsINode;
@@ -83,17 +83,17 @@ public:
  *    2. Call SetEnd to set where you want to stop spellchecking. We'll stop
  *       at the word boundary after that. If SetEnd is not called, we'll stop
  *       at the end of the document's root element.
  *    3. Call SetPosition to initialize the current position inside the
  *       previously given range.
  *    4. Call GetNextWord over and over until it returns false.
  */
 
-class mozInlineSpellWordUtil
+class MOZ_STACK_CLASS mozInlineSpellWordUtil
 {
 public:
   mozInlineSpellWordUtil()
     : mRootNode(nullptr),
       mSoftBegin(nullptr, 0), mSoftEnd(nullptr, 0),
       mNextWordIndex(-1), mSoftTextValid(false) {}
 
   nsresult Init(mozilla::TextEditor* aTextEditor);
@@ -108,17 +108,17 @@ public:
   // DOM range that exactly encloses that word's characters. The current
   // position will be at the end of the word. This will find the previous
   // word if the current position is space, so if you care that the point is
   // inside the word, you should check the range.
   //
   // THIS CHANGES THE CURRENT POSITION AND RANGE. It is designed to be called
   // before you actually generate the range you are interested in and iterate
   // the words in it.
-  nsresult GetRangeForWord(nsIDOMNode* aWordNode, int32_t aWordOffset,
+  nsresult GetRangeForWord(nsINode* aWordNode, int32_t aWordOffset,
                            nsRange** aRange);
 
   // Convenience functions, object must be initialized
   nsresult MakeRange(NodeOffset aBegin, NodeOffset aEnd, nsRange** aRange);
 
   // Moves to the the next word in the range, and retrieves it's text and range.
   // An empty word and a nullptr range are returned when we are done checking.
   // aSkipChecking will be set if the word is "special" and shouldn't be
@@ -126,24 +126,22 @@ public:
   nsresult GetNextWord(nsAString& aText,
                        NodeOffsetRange* aNodeOffsetRange,
                        bool* aSkipChecking);
 
   // Call to normalize some punctuation. This function takes an autostring
   // so we can access characters directly.
   static void NormalizeWord(nsAString& aWord);
 
-  nsIDOMDocument* GetDOMDocument() const { return mDOMDocument; }
   nsIDocument* GetDocument() const { return mDocument; }
   nsINode* GetRootNode() { return mRootNode; }
 
 private:
 
   // cached stuff for the editor, set by Init
-  nsCOMPtr<nsIDOMDocument> mDOMDocument;
   nsCOMPtr<nsIDocument>         mDocument;
 
   // range to check, see SetPosition and SetEnd
   nsINode*    mRootNode;
   NodeOffset  mSoftBegin;
   NodeOffset  mSoftEnd;
 
   // DOM text covering the soft range, with newlines added at block boundaries