Bug 1460509 - part 13: Make TextEditRules::WillInsert() return NS_ERROR_EDITOR_DESTROYED if it causes destroying the editor r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 11 May 2018 19:06:07 +0900
changeset 798731 b7fcbfde487a85e09afc57aa786988de6d7b264b
parent 798730 b86c8a4d3ec013edef48ebc5519070ff38a83bd2
child 798732 7276770b8cf7ecdf9c322e5153aa6bbadb9bf228
push id110840
push usermasayuki@d-toybox.com
push dateWed, 23 May 2018 13:41:58 +0000
reviewersm_kato
bugs1460509
milestone62.0a1
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.