Bug 1031440 - Start moving mozInlineSpellChecker off of nsIDOM* APIs. r=ehsan
authorBlake Kaplan <mrbkap@gmail.com>
Mon, 30 Jun 2014 16:30:51 -0700
changeset 191633 d774d2c87e78660c41dba7dc0710ffabec49a549
parent 191632 f00ebb996486218b60f198d6fd6f1b419bc009c9
child 191634 05f283d784e0805107cff2b93db8b04dc9b69825
push id27055
push usercbook@mozilla.com
push dateTue, 01 Jul 2014 12:01:46 +0000
treeherdermozilla-central@4a9353b5762d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs1031440
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1031440 - Start moving mozInlineSpellChecker off of nsIDOM* APIs. r=ehsan
extensions/spellcheck/src/mozInlineSpellChecker.cpp
extensions/spellcheck/src/mozInlineSpellChecker.h
--- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp
@@ -1,9 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=2 sts=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/. */
 
 /**
  * This class is called by the editor to handle spellchecking after various
  * events. The main entrypoint is SpellCheckAfterEditorChange, which is called
  * when the text is changed.
@@ -39,17 +40,19 @@
 #include "nsIDOMNode.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIDOMMouseEvent.h"
 #include "nsIDOMKeyEvent.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeList.h"
+#include "nsGenericHTMLElement.h"
 #include "nsRange.h"
+#include "mozilla/dom/Selection.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"
@@ -59,18 +62,19 @@
 #include "nsUnicharUtils.h"
 #include "nsIContent.h"
 #include "nsRange.h"
 #include "nsContentUtils.h"
 #include "nsEditor.h"
 #include "mozilla/Services.h"
 #include "nsIObserverService.h"
 #include "nsITextControlElement.h"
-#include "prtime.h" 
+#include "prtime.h"
 
+using namespace mozilla;
 using namespace mozilla::dom;
 
 // Set to spew messages to the console about what is happening.
 //#define DEBUG_INLINESPELL
 
 // the number of milliseconds that we will take at once to do spellchecking
 #define INLINESPELL_CHECK_TIMEOUT 50
 
@@ -1203,134 +1207,111 @@ mozInlineSpellChecker::SpellCheckBetween
     return NS_OK; // range is empty: nothing to do
 
   mozInlineSpellStatus status(this);
   rv = status.InitForRange(range);
   NS_ENSURE_SUCCESS(rv, rv);
   return ScheduleSpellCheck(status);
 }
 
-// mozInlineSpellChecker::SkipSpellCheckForNode
+// mozInlineSpellChecker::ShouldSpellCheckNode
 //
 //    There are certain conditions when we don't want to spell check a node. In
 //    particular quotations, moz signatures, etc. This routine returns false
 //    for these cases.
 
-nsresult
-mozInlineSpellChecker::SkipSpellCheckForNode(nsIEditor* aEditor,
-                                             nsIDOMNode *aNode,
-                                             bool *checkSpelling)
+bool
+mozInlineSpellChecker::ShouldSpellCheckNode(nsIEditor* aEditor,
+                                            nsINode *aNode)
 {
-  *checkSpelling = true;
-  NS_ENSURE_ARG_POINTER(aNode);
+  MOZ_ASSERT(aNode);
+  if (!aNode->IsContent())
+    return true;
+
+  nsIContent *content = aNode->AsContent();
 
   uint32_t flags;
   aEditor->GetFlags(&flags);
-  if (flags & nsIPlaintextEditor::eEditorMailMask)
-  {
-    nsCOMPtr<nsIDOMNode> parent;
-    aNode->GetParentNode(getter_AddRefs(parent));
-
-    while (parent)
-    {
-      nsCOMPtr<nsIDOMElement> parentElement = do_QueryInterface(parent);
-      if (!parentElement)
-        break;
-
-      nsAutoString parentTagName;
-      parentElement->GetTagName(parentTagName);
-
-      if (parentTagName.Equals(NS_LITERAL_STRING("blockquote"), nsCaseInsensitiveStringComparator()))
-      {
-        nsAutoString quotetype;
-        parentElement->GetAttribute(NS_LITERAL_STRING("type"), quotetype);
-        if (quotetype.Equals(NS_LITERAL_STRING("cite"), nsCaseInsensitiveStringComparator()))
-        {
-          *checkSpelling = false;
-          break;
-        }
+  if (flags & nsIPlaintextEditor::eEditorMailMask) {
+    nsIContent *parent = content->GetParent();
+    while (parent) {
+      if (parent->IsHTML(nsGkAtoms::blockquote) &&
+          parent->AttrValueIs(kNameSpaceID_None,
+                              nsGkAtoms::type,
+                              nsGkAtoms::cite,
+                              eIgnoreCase)) {
+        return false;
       }
-      else if (parentTagName.Equals(NS_LITERAL_STRING("pre"), nsCaseInsensitiveStringComparator()))
-      {
-        nsAutoString classname;
-        parentElement->GetAttribute(NS_LITERAL_STRING("class"),classname);
-        if (classname.EqualsLiteral("moz-signature"))
-          *checkSpelling = false;
+      if (parent->IsHTML(nsGkAtoms::pre) &&
+          parent->AttrValueIs(kNameSpaceID_None,
+                              nsGkAtoms::_class,
+                              nsGkAtoms::mozsignature,
+                              eIgnoreCase)) {
+        return false;
       }
 
-      nsCOMPtr<nsIDOMNode> nextParent;
-      parent->GetParentNode(getter_AddRefs(nextParent));
-      parent = nextParent;
+      parent = parent->GetParent();
     }
-  }
-  else {
+  } else {
     // Check spelling only if the node is editable, and GetSpellcheck() is true
     // on the nearest HTMLElement ancestor.
-    nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
     if (!content->IsEditable()) {
-      *checkSpelling = false;
-      return NS_OK;
+      return false;
     }
 
     // Make sure that we can always turn on spell checking for inputs/textareas.
     // Note that because of the previous check, at this point we know that the
     // node is editable.
     if (content->IsInAnonymousSubtree()) {
-      nsCOMPtr<nsIContent> node = content->GetParent();
+      nsIContent *node = content->GetParent();
       while (node && node->IsInNativeAnonymousSubtree()) {
         node = node->GetParent();
       }
       nsCOMPtr<nsITextControlElement> textControl = do_QueryInterface(node);
       if (textControl) {
-        *checkSpelling = true;
-        return NS_OK;
+        return true;
       }
     }
 
     // Get HTML element ancestor (might be aNode itself, although probably that
     // has to be a text node in real life here)
-    nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(content);
-    while (content && !htmlElement) {
-      content = content->GetParent();
-      htmlElement = do_QueryInterface(content);
-    }
-    NS_ASSERTION(htmlElement, "Why do we have no htmlElement?");
-    if (!htmlElement) {
-      return NS_OK;
+    nsIContent *parent = content;
+    while (!parent->IsHTML()) {
+      parent = parent->GetParent();
+      if (!parent) {
+        return true;
+      }
     }
 
     // See if it's spellcheckable
-    htmlElement->GetSpellcheck(checkSpelling);
-    return NS_OK;
+    return static_cast<nsGenericHTMLElement *>(parent)->Spellcheck();
   }
 
-  return NS_OK;
+  return true;
 }
 
 // mozInlineSpellChecker::ScheduleSpellCheck
 //
 //    This is called by code to do the actual spellchecking. We will set up
 //    the proper structures for calls to DoSpellCheck.
 
 nsresult
 mozInlineSpellChecker::ScheduleSpellCheck(const mozInlineSpellStatus& aStatus)
 {
   if (mFullSpellCheckScheduled) {
     // Just ignore this; we're going to spell-check everything anyway
     return NS_OK;
   }
 
-  mozInlineSpellResume* resume =
+  nsRefPtr<mozInlineSpellResume> resume =
     new mozInlineSpellResume(aStatus, mDisabledAsyncToken);
   NS_ENSURE_TRUE(resume, NS_ERROR_OUT_OF_MEMORY);
 
   nsresult rv = resume->Post();
-  if (NS_FAILED(rv)) {
-    delete resume;
-  } else {
+  if (NS_SUCCEEDED(rv)) {
     if (aStatus.IsFullSpellCheck()) {
       // We're going to check everything.  Suppress further spell-check attempts
       // until that happens.
       mFullSpellCheckScheduled = true;
     }
     ChangeNumPendingSpellChecks(1);
   }
   return rv;
@@ -1344,39 +1325,36 @@ mozInlineSpellChecker::ScheduleSpellChec
 //    be removed from the selection.
 //
 //    FIXME-PERFORMANCE: This takes as long as it takes and is not resumable.
 //    Typically, checking this small amount of text is relatively fast, but
 //    for large numbers of words, a lag may be noticeable.
 
 nsresult
 mozInlineSpellChecker::DoSpellCheckSelection(mozInlineSpellWordUtil& aWordUtil,
-                                             nsISelection* aSpellCheckSelection,
+                                             Selection* aSpellCheckSelection,
                                              mozInlineSpellStatus* aStatus)
 {
   nsresult rv;
 
   // clear out mNumWordsInSpellSelection since we'll be rebuilding the ranges.
   mNumWordsInSpellSelection = 0;
 
   // Since we could be modifying the ranges for the spellCheckSelection while
   // looping on the spell check selection, keep a separate array of range
   // elements inside the selection
-  nsCOMArray<nsIDOMRange> ranges;
+  nsTArray<nsRefPtr<nsRange>> ranges;
 
-  int32_t count;
-  aSpellCheckSelection->GetRangeCount(&count);
+  int32_t count = aSpellCheckSelection->GetRangeCount();
 
-  int32_t idx;
   nsCOMPtr<nsIDOMRange> checkRange;
-  for (idx = 0; idx < count; idx ++) {
-    aSpellCheckSelection->GetRangeAt(idx, getter_AddRefs(checkRange));
-    if (checkRange) {
-      if (! ranges.AppendObject(checkRange))
-        return NS_ERROR_OUT_OF_MEMORY;
+  for (int32_t idx = 0; idx < count; idx++) {
+    nsRange *range = aSpellCheckSelection->GetRangeAt(idx);
+    if (range) {
+      ranges.AppendElement(range);
     }
   }
 
   // We have saved the ranges above. Clearing the spellcheck selection here
   // isn't necessary (rechecking each word will modify it as necessary) but
   // provides better performance. By ensuring that no ranges need to be
   // removed in DoSpellCheck, we can save checking range inclusion which is
   // slow.
@@ -1385,31 +1363,31 @@ mozInlineSpellChecker::DoSpellCheckSelec
   // We use this state object for all calls, and just update its range. Note
   // that we don't need to call FinishInit since we will be filling in the
   // necessary information.
   mozInlineSpellStatus status(this);
   rv = status.InitForRange(nullptr);
   NS_ENSURE_SUCCESS(rv, rv);
 
   bool doneChecking;
-  for (idx = 0; idx < count; idx ++) {
-    checkRange = ranges[idx];
-    if (checkRange) {
-      // We can consider this word as "added" since we know it has no spell
-      // check range over it that needs to be deleted. All the old ranges
-      // were cleared above. We also need to clear the word count so that we
-      // check all words instead of stopping early.
-      status.mRange = static_cast<nsRange*>(checkRange.get());
-      rv = DoSpellCheck(aWordUtil, aSpellCheckSelection, &status,
-                        &doneChecking);
-      NS_ENSURE_SUCCESS(rv, rv);
-      NS_ASSERTION(doneChecking, "We gave the spellchecker one word, but it didn't finish checking?!?!");
+  for (int32_t idx = 0; idx < count; idx++) {
+    auto& checkRange = ranges[idx];
 
-      status.mWordCount = 0;
-    }
+    // We can consider this word as "added" since we know it has no spell
+    // check range over it that needs to be deleted. All the old ranges
+    // were cleared above. We also need to clear the word count so that we
+    // check all words instead of stopping early.
+    status.mRange = checkRange;
+    rv = DoSpellCheck(aWordUtil, aSpellCheckSelection, &status,
+                      &doneChecking);
+    NS_ENSURE_SUCCESS(rv, rv);
+    MOZ_ASSERT(doneChecking,
+               "We gave the spellchecker one word, but it didn't finish checking?!?!");
+
+    status.mWordCount = 0;
   }
 
   return NS_OK;
 }
 
 // mozInlineSpellChecker::DoSpellCheck
 //
 //    This function checks words intersecting the given range, excluding those
@@ -1437,44 +1415,37 @@ mozInlineSpellChecker::DoSpellCheckSelec
 //                                               [---] aNoCheckRange
 //      -> recheck all words in range except those in aNoCheckRange
 //
 //    If checking is complete, *aDoneChecking will be set. If there is more
 //    but we ran out of time, this will be false and the range will be
 //    updated with the stuff that still needs checking.
 
 nsresult mozInlineSpellChecker::DoSpellCheck(mozInlineSpellWordUtil& aWordUtil,
-                                             nsISelection *aSpellCheckSelection,
+                                             Selection *aSpellCheckSelection,
                                              mozInlineSpellStatus* aStatus,
                                              bool* aDoneChecking)
 {
   *aDoneChecking = true;
 
   NS_ENSURE_TRUE(mSpellCheck, NS_ERROR_NOT_INITIALIZED);
 
-  // get the editor for SkipSpellCheckForNode, this may fail in reasonable
+  // get the editor for ShouldSpellCheckNode, this may fail in reasonable
   // circumstances since the editor could have gone away
   nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
   if (! editor)
     return NS_ERROR_FAILURE;
 
-  bool iscollapsed;
-  nsresult rv = aStatus->mRange->GetCollapsed(&iscollapsed);
-  NS_ENSURE_SUCCESS(rv, rv);
-  if (iscollapsed)
+  if (aStatus->mRange->Collapsed())
     return NS_OK;
 
-  nsCOMPtr<nsISelectionPrivate> privSel = do_QueryInterface(aSpellCheckSelection);
-
   // see if the selection has any ranges, if not, then we can optimize checking
   // range inclusion later (we have no ranges when we are initially checking or
   // when there are no misspelled words yet).
-  int32_t originalRangeCount;
-  rv = aSpellCheckSelection->GetRangeCount(&originalRangeCount);
-  NS_ENSURE_SUCCESS(rv, rv);
+  int32_t originalRangeCount = aSpellCheckSelection->GetRangeCount();
 
   // set the starting DOM position to be the beginning of our range
   {
     // Scope for the node/offset pairs here so they don't get
     // accidentally used later
     nsINode* beginNode = aStatus->mRange->GetStartParent();
     int32_t beginOffset = aStatus->mRange->StartOffset();
     nsINode* endNode = aStatus->mRange->GetEndParent();
@@ -1483,106 +1454,98 @@ nsresult mozInlineSpellChecker::DoSpellC
     // Now check that we're still looking at a range that's under
     // aWordUtil.GetRootNode()
     nsINode* rootNode = aWordUtil.GetRootNode();
     if (!nsContentUtils::ContentIsDescendantOf(beginNode, rootNode) ||
         !nsContentUtils::ContentIsDescendantOf(endNode, rootNode)) {
       // Just bail out and don't try to spell-check this
       return NS_OK;
     }
-  
+
     aWordUtil.SetEnd(endNode, endOffset);
     aWordUtil.SetPosition(beginNode, beginOffset);
   }
 
   // aWordUtil.SetPosition flushes pending notifications, check editor again.
+  // XXX Uhhh, *we're* holding a strong ref to the editor.
   editor = do_QueryReferent(mEditor);
   if (! editor)
     return NS_ERROR_FAILURE;
 
   int32_t wordsSinceTimeCheck = 0;
   PRTime beginTime = PR_Now();
 
   nsAutoString wordText;
   nsRefPtr<nsRange> wordRange;
   bool dontCheckWord;
   while (NS_SUCCEEDED(aWordUtil.GetNextWord(wordText,
                                             getter_AddRefs(wordRange),
                                             &dontCheckWord)) &&
          wordRange) {
-    wordsSinceTimeCheck ++;
+    wordsSinceTimeCheck++;
 
     // get the range for the current word.
-    // Not using nsINode here for now because we have to call into
-    // selection APIs that use nsIDOMNode. :(
-    nsCOMPtr<nsIDOMNode> beginNode, endNode;
+    nsINode *beginNode;
+    nsINode *endNode;
     int32_t beginOffset, endOffset;
-    wordRange->GetStartContainer(getter_AddRefs(beginNode));
-    wordRange->GetEndContainer(getter_AddRefs(endNode));
-    wordRange->GetStartOffset(&beginOffset);
-    wordRange->GetEndOffset(&endOffset);
+
+    ErrorResult erv;
+    beginNode = wordRange->GetStartContainer(erv);
+    endNode = wordRange->GetEndContainer(erv);
+    beginOffset = wordRange->GetStartOffset(erv);
+    endOffset = wordRange->GetEndOffset(erv);
 
 #ifdef DEBUG_INLINESPELL
     printf("->Got word \"%s\"", NS_ConvertUTF16toUTF8(wordText).get());
     if (dontCheckWord)
       printf(" (not checking)");
     printf("\n");
 #endif
 
     // see if there is a spellcheck range that already intersects the word
     // and remove it. We only need to remove old ranges, so don't bother if
     // there were no ranges when we started out.
     if (originalRangeCount > 0) {
       // likewise, if this word is inside new text, we won't bother testing
-      bool inCreatedRange = false;
-      if (aStatus->mCreatedRange)
-        aStatus->mCreatedRange->IsPointInRange(beginNode, beginOffset, &inCreatedRange);
-      if (! inCreatedRange) {
-        nsTArray<nsRange*> ranges;
-        nsCOMPtr<nsINode> firstNode = do_QueryInterface(beginNode);
-        nsCOMPtr<nsINode> lastNode = do_QueryInterface(endNode);
-        rv = privSel->GetRangesForIntervalArray(firstNode, beginOffset,
-                                                lastNode, endOffset,
-                                                true, &ranges);
-        NS_ENSURE_SUCCESS(rv, rv);
+      if (!aStatus->mCreatedRange ||
+          !aStatus->mCreatedRange->IsPointInRange(*beginNode, beginOffset, erv)) {
+        nsTArray<nsRefPtr<nsRange>> ranges;
+        aSpellCheckSelection->GetRangesForInterval(*beginNode, beginOffset,
+                                                   *endNode, endOffset,
+                                                   true, ranges, erv);
+        ENSURE_SUCCESS(erv, erv.ErrorCode());
         for (uint32_t i = 0; i < ranges.Length(); i++)
           RemoveRange(aSpellCheckSelection, ranges[i]);
       }
     }
 
     // some words are special and don't need checking
     if (dontCheckWord)
       continue;
 
     // some nodes we don't spellcheck
-    bool checkSpelling;
-    rv = SkipSpellCheckForNode(editor, beginNode, &checkSpelling);
-    NS_ENSURE_SUCCESS(rv, rv);
-    if (!checkSpelling)
+    if (!ShouldSpellCheckNode(editor, beginNode))
       continue;
 
     // Don't check spelling if we're inside the noCheckRange. This needs to
     // be done after we clear any old selection because the excluded word
     // might have been previously marked.
     //
     // We do a simple check to see if the beginning of our word is in the
     // exclusion range. Because the exclusion range is a multiple of a word,
     // this is sufficient.
-    if (aStatus->mNoCheckRange) {
-      bool inExclusion = false;
-      aStatus->mNoCheckRange->IsPointInRange(beginNode, beginOffset,
-                                             &inExclusion);
-      if (inExclusion)
-        continue;
+    if (aStatus->mNoCheckRange &&
+        aStatus->mNoCheckRange->IsPointInRange(*beginNode, beginOffset, erv)) {
+      continue;
     }
 
     // check spelling and add to selection if misspelled
     bool isMisspelled;
     aWordUtil.NormalizeWord(wordText);
-    rv = mSpellCheck->CheckCurrentWordNoSuggest(wordText.get(), &isMisspelled);
+    nsresult rv = mSpellCheck->CheckCurrentWordNoSuggest(wordText.get(), &isMisspelled);
     if (NS_FAILED(rv))
       continue;
 
     if (isMisspelled) {
       // misspelled words count extra toward the max
       wordsSinceTimeCheck += MISSPELLED_WORD_COUNT_PENALTY;
       AddRange(aSpellCheckSelection, wordRange);
 
@@ -1663,36 +1626,37 @@ mozInlineSpellChecker::ResumeCheck(mozIn
   if (! editor)
     return NS_OK; // editor is gone
 
   mozInlineSpellWordUtil wordUtil;
   nsresult rv = wordUtil.Init(mEditor);
   if (NS_FAILED(rv))
     return NS_OK; // editor doesn't like us, don't assert
 
-  nsCOMPtr<nsISelection> spellCheckSelection;
-  rv = GetSpellCheckSelection(getter_AddRefs(spellCheckSelection));
+  nsCOMPtr<nsISelection> spellCheckSelectionRef;
+  rv = GetSpellCheckSelection(getter_AddRefs(spellCheckSelectionRef));
   NS_ENSURE_SUCCESS(rv, rv);
 
+  auto spellCheckSelection =
+    static_cast<Selection *>(spellCheckSelectionRef.get());
+
   nsAutoString currentDictionary;
   rv = mSpellCheck->GetCurrentDictionary(currentDictionary);
   if (NS_FAILED(rv)) {
     // no active dictionary
-    int32_t count;
-    spellCheckSelection->GetRangeCount(&count);
+    int32_t count = spellCheckSelection->GetRangeCount();
     for (int32_t index = count - 1; index >= 0; index--) {
-      nsCOMPtr<nsIDOMRange> checkRange;
-      spellCheckSelection->GetRangeAt(index, getter_AddRefs(checkRange));
+      nsRange *checkRange = spellCheckSelection->GetRangeAt(index);
       if (checkRange) {
         RemoveRange(spellCheckSelection, checkRange);
       }
     }
-    return NS_OK; 
+    return NS_OK;
   }
- 
+
   CleanupRangesInSelection(spellCheckSelection);
 
   rv = aStatus->FinishInitOnEvent(wordUtil);
   NS_ENSURE_SUCCESS(rv, rv);
   if (! aStatus->mRange)
     return NS_OK; // empty range, nothing to do
 
   bool doneChecking = true;
@@ -1737,35 +1701,31 @@ mozInlineSpellChecker::IsPointInSelectio
 
   // 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]);
   return NS_OK;
 }
 
 nsresult
-mozInlineSpellChecker::CleanupRangesInSelection(nsISelection *aSelection)
+mozInlineSpellChecker::CleanupRangesInSelection(Selection *aSelection)
 {
   // integrity check - remove ranges that have collapsed to nothing. This
   // can happen if the node containing a highlighted word was removed.
-  NS_ENSURE_ARG_POINTER(aSelection);
+  if (!aSelection)
+    return NS_ERROR_FAILURE;
 
-  int32_t count;
-  aSelection->GetRangeCount(&count);
+  int32_t count = aSelection->GetRangeCount();
 
   for (int32_t index = 0; index < count; index++)
   {
-    nsCOMPtr<nsIDOMRange> checkRange;
-    aSelection->GetRangeAt(index, getter_AddRefs(checkRange));
-
+    nsRange *checkRange = aSelection->GetRangeAt(index);
     if (checkRange)
     {
-      bool collapsed;
-      checkRange->GetCollapsed(&collapsed);
-      if (collapsed)
+      if (checkRange->Collapsed())
       {
         RemoveRange(aSelection, checkRange);
         index--;
         count--;
       }
     }
   }
 
@@ -1775,27 +1735,28 @@ mozInlineSpellChecker::CleanupRangesInSe
 
 // mozInlineSpellChecker::RemoveRange
 //
 //    For performance reasons, we have an upper bound on the number of word
 //    ranges  in the spell check selection. When removing a range from the
 //    selection, we need to decrement mNumWordsInSpellSelection
 
 nsresult
-mozInlineSpellChecker::RemoveRange(nsISelection* aSpellCheckSelection,
-                                   nsIDOMRange* aRange)
+mozInlineSpellChecker::RemoveRange(Selection *aSpellCheckSelection,
+                                   nsRange *aRange)
 {
   NS_ENSURE_ARG_POINTER(aSpellCheckSelection);
   NS_ENSURE_ARG_POINTER(aRange);
 
-  nsresult rv = aSpellCheckSelection->RemoveRange(aRange);
-  if (NS_SUCCEEDED(rv) && mNumWordsInSpellSelection)
+  ErrorResult rv;
+  aSpellCheckSelection->RemoveRange(*aRange, rv);
+  if (!rv.Failed() && mNumWordsInSpellSelection)
     mNumWordsInSpellSelection--;
 
-  return rv;
+  return rv.ErrorCode();
 }
 
 
 // mozInlineSpellChecker::AddRange
 //
 //    For performance reasons, we have an upper bound on the number of word
 //    ranges we'll add to the spell check selection. Once we reach that upper
 //    bound, stop adding the ranges
--- a/extensions/spellcheck/src/mozInlineSpellChecker.h
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.h
@@ -72,17 +72,17 @@ public:
   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.
   nsRefPtr<nsRange> mRange;
 
   // If we happen to know something was inserted, this is that range.
   // Can be nullptr (this only allows an optimization, so not setting doesn't hurt)
-  nsCOMPtr<nsIDOMRange> mCreatedRange;
+  nsRefPtr<nsRange> mCreatedRange;
 
   // Contains the range computed for the current word. Can be nullptr.
   nsRefPtr<nsRange> mNoCheckRange;
 
   // Indicates the position of the cursor for the event (so we can compute
   // mNoCheckRange). It can be nullptr if we don't care about the cursor position
   // (such as for the intial check of everything).
   //
@@ -207,44 +207,44 @@ public:
   nsresult SpellCheckBetweenNodes(nsIDOMNode *aStartNode,
                                   int32_t aStartOffset,
                                   nsIDOMNode *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...)
-  nsresult SkipSpellCheckForNode(nsIEditor* aEditor,
-                                 nsIDOMNode *aNode, bool * aCheckSpelling);
+  bool ShouldSpellCheckNode(nsIEditor* aEditor, 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(const mozInlineSpellStatus& aStatus);
 
   nsresult DoSpellCheckSelection(mozInlineSpellWordUtil& aWordUtil,
-                                 nsISelection* aSpellCheckSelection,
+                                 mozilla::dom::Selection* aSpellCheckSelection,
                                  mozInlineSpellStatus* aStatus);
   nsresult DoSpellCheck(mozInlineSpellWordUtil& aWordUtil,
-                        nsISelection *aSpellCheckSelection,
+                        mozilla::dom::Selection *aSpellCheckSelection,
                         mozInlineSpellStatus* aStatus,
                         bool* aDoneChecking);
 
   // helper routine to determine if a point is inside of the passed in selection.
   nsresult IsPointInSelection(nsISelection *aSelection,
                               nsIDOMNode *aNode,
                               int32_t aOffset,
                               nsIDOMRange **aRange);
 
-  nsresult CleanupRangesInSelection(nsISelection *aSelection);
+  nsresult CleanupRangesInSelection(mozilla::dom::Selection *aSelection);
 
-  nsresult RemoveRange(nsISelection *aSpellCheckSelection, nsIDOMRange * aRange);
+  nsresult RemoveRange(mozilla::dom::Selection *aSpellCheckSelection,
+                       nsRange *aRange);
   nsresult AddRange(nsISelection *aSpellCheckSelection, nsIDOMRange * aRange);
   bool     SpellCheckSelectionIsFull() { return mNumWordsInSpellSelection >= mMaxNumWordsInSpellSelection; }
 
   nsresult MakeSpellCheckRange(nsIDOMNode* aStartNode, int32_t aStartOffset,
                                nsIDOMNode* aEndNode, int32_t aEndOffset,
                                nsRange** aRange);
 
   // DOM and editor event registration helper routines