Bug 1460509 - part 13: Make TextEditRules::WillInsert() return NS_ERROR_EDITOR_DESTROYED if it causes destroying the editor r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 11 May 2018 19:06:07 +0900
changeset 476197 67892070f7ccd6329825f005cfc84957424a7769
parent 476196 54e551b4a5cddd89cea388c5a506c8268bdb7b68
child 476198 e9a4f9a25edc11e5d394706d1db2764a7cee0640
push id1757
push userffxbld-merge
push dateFri, 24 Aug 2018 17:02:43 +0000
treeherdermozilla-release@736023aebdb1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1460509
milestone62.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 1460509 - part 13: Make TextEditRules::WillInsert() return NS_ERROR_EDITOR_DESTROYED if it causes destroying the editor r=m_kato This patch also makes aCancel of TextEditRules::WillInsert() optional since a lot of callers need to ignore the result. MozReview-Commit-ID: JrvycxMQ9Mm
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/TextEditRules.cpp
editor/libeditor/TextEditRules.h
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -1330,17 +1330,20 @@ HTMLEditRules::GetFormatString(nsINode* 
 }
 
 void
 HTMLEditRules::WillInsert(bool* aCancel)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(aCancel);
 
-  TextEditRules::WillInsert(aCancel);
+  nsresult rv = TextEditRules::WillInsert(aCancel);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return;
+  }
 
   // Adjust selection to prevent insertion after a moz-BR.  This next only
   // works for collapsed selections right now, because selection is a pain to
   // work with when not collapsed.  (no good way to extend start or end of
   // selection), so we ignore those types of selections.
   if (!SelectionRef().IsCollapsed()) {
     return;
   }
--- a/editor/libeditor/TextEditRules.cpp
+++ b/editor/libeditor/TextEditRules.cpp
@@ -351,18 +351,17 @@ TextEditRules::WillDoAction(Selection* a
     case EditAction::removeTextProperty:
       return WillRemoveTextProperty(aCancel, aHandled);
     case EditAction::outputText:
       return WillOutputText(aInfo->outputFormat, aInfo->outString, aInfo->flags,
                             aCancel, aHandled);
     case EditAction::insertElement:
       // i had thought this would be html rules only.  but we put pre elements
       // into plaintext mail when doing quoting for reply!  doh!
-      WillInsert(aCancel);
-      return NS_OK;
+      return WillInsert(aCancel);
     default:
       return NS_ERROR_FAILURE;
   }
 }
 
 nsresult
 TextEditRules::DidDoAction(Selection* aSelection,
                            RulesInfo* aInfo,
@@ -405,38 +404,47 @@ TextEditRules::DocumentIsEmpty()
   bool retVal = false;
   if (!mTextEditor || NS_FAILED(mTextEditor->DocumentIsEmpty(&retVal))) {
     retVal = true;
   }
 
   return retVal;
 }
 
-void
+nsresult
 TextEditRules::WillInsert(bool* aCancel)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
-  MOZ_ASSERT(aCancel);
 
   if (IsReadonly() || IsDisabled()) {
-    *aCancel = true;
-    return;
+    if (aCancel) {
+      *aCancel = true;
+    }
+    return NS_OK;
   }
 
   // initialize out param
-  *aCancel = false;
+  if (aCancel) {
+    *aCancel = false;
+  }
 
   // check for the magic content node and delete it if it exists
-  if (mBogusNode) {
-    DebugOnly<nsresult> rv =
-      TextEditorRef().DeleteNodeWithTransaction(*mBogusNode);
-    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
-      "Failed to remove the bogus node");
-    mBogusNode = nullptr;
+  if (!mBogusNode) {
+    return NS_OK;
   }
+
+  DebugOnly<nsresult> rv =
+    TextEditorRef().DeleteNodeWithTransaction(*mBogusNode);
+  if (NS_WARN_IF(!CanHandleEditAction())) {
+    return NS_ERROR_EDITOR_DESTROYED;
+  }
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+    "Failed to remove the bogus node");
+  mBogusNode = nullptr;
+  return NS_OK;
 }
 
 nsresult
 TextEditRules::WillInsertBreak(bool* aCancel,
                                bool* aHandled,
                                int32_t aMaxLength)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
@@ -473,20 +481,20 @@ TextEditRules::WillInsertBreak(bool* aCa
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
 
-    WillInsert(aCancel);
-    // initialize out param
-    // we want to ignore result of WillInsert()
-    *aCancel = false;
+    rv = WillInsert();
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
   }
   return NS_OK;
 }
 
 nsresult
 TextEditRules::CollapseSelectionToTrailingBRIfNeeded()
 {
   MOZ_ASSERT(IsEditorDataAvailable());
@@ -721,20 +729,20 @@ TextEditRules::WillInsertText(EditAction
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
-  WillInsert(aCancel);
-  // initialize out param
-  // we want to ignore result of WillInsert()
-  *aCancel = false;
+  rv = WillInsert(aCancel);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 
   // handle password field data
   // this has the side effect of changing all the characters in aOutString
   // to the replacement character
   if (IsPasswordEditor() &&
       aAction == EditAction::insertIMEText) {
     RemoveIMETextFromPWBuf(start, outString);
   }
@@ -889,19 +897,20 @@ TextEditRules::WillSetText(bool* aCancel
   }
 
   if (IsPasswordEditor() && LookAndFeel::GetEchoPassword() &&
       !DontEchoPassword()) {
     // Echo password timer will implement on InsertText.
     return NS_OK;
   }
 
-  WillInsert(aCancel);
-  // we want to ignore result of WillInsert()
-  *aCancel = false;
+  nsresult rv = WillInsert(aCancel);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 
   RefPtr<Element> rootElement = TextEditorRef().GetRoot();
   uint32_t count = rootElement->GetChildCount();
 
   // handles only when there is only one node and it's a text node, or empty.
 
   if (count > 1) {
     return NS_OK;
@@ -947,18 +956,18 @@ TextEditRules::WillSetText(bool* aCancel
 
   nsINode* curNode = rootElement->GetFirstChild();
   if (NS_WARN_IF(!EditorBase::IsTextNode(curNode))) {
     return NS_OK;
   }
 
   // Even if empty text, we don't remove text node and set empty text
   // for performance
-  nsresult rv = TextEditorRef().SetTextImpl(SelectionRef(), tString,
-                                            *curNode->GetAsText());
+  rv = TextEditorRef().SetTextImpl(SelectionRef(), tString,
+                                   *curNode->GetAsText());
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   *aHandled = true;
--- a/editor/libeditor/TextEditRules.h
+++ b/editor/libeditor/TextEditRules.h
@@ -173,17 +173,25 @@ protected:
    * @param inString            String to be set.
    * @param aMaxLength          The maximum string length which the text editor
    *                            allows to set.
    */
   MOZ_MUST_USE nsresult
   WillSetText(bool* aCancel, bool* aHandled,
               const nsAString* inString, int32_t aMaxLength);
 
-  void WillInsert(bool* aCancel);
+  /**
+   * Called before inserting something into the editor.
+   * This method may removes mBougsNode if there is.  Therefore, this method
+   * might cause destroying the editor.
+   *
+   * @param aCancel             Returns true if the operation is canceled.
+   *                            This can be nullptr.
+   */
+  MOZ_MUST_USE nsresult WillInsert(bool* aCancel = nullptr);
 
   /**
    * Called before deleting selected content.
    * This method may actually remove the selected content with
    * DeleteSelectionWithTransaction().  So, this might cause destroying the
    * editor.
    *
    * @param aCaollapsedAction   Direction to extend the selection.