Bug 1460509 - part 3: Make TextEditRules::HideLastPWInput() return NS_ERROR_EDITOR_DESTROYED when it causes destroying the editor r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 11 May 2018 16:08:47 +0900
changeset 798721 7b2ba37b4f038296072318633aa749a9435962a1
parent 798720 6aec242133f1f4385c0832b5bcb486b221145588
child 798722 5ccf7ab97dc41b8a5df61c8af929d318aaf94046
push id110840
push usermasayuki@d-toybox.com
push dateWed, 23 May 2018 13:41:58 +0000
reviewersm_kato
bugs1460509
milestone62.0a1
Bug 1460509 - part 3: Make TextEditRules::HideLastPWInput() return NS_ERROR_EDITOR_DESTROYED when it causes destroying the editor r?m_kato And also this patch marks it as MOZ_MUST_USE. All callers have to check if the result is NS_ERROR_EDITOR_DESTROYED at least. MozReview-Commit-ID: H4DfU1asPpe
editor/libeditor/TextEditRules.cpp
editor/libeditor/TextEditRules.h
--- a/editor/libeditor/TextEditRules.cpp
+++ b/editor/libeditor/TextEditRules.cpp
@@ -738,24 +738,27 @@ TextEditRules::WillInsertText(EditAction
     outString->Assign(tString);
   }
 
   if (IsPasswordEditor()) {
     // manage the password buffer
     mPasswordText.Insert(*outString, start);
 
     if (LookAndFeel::GetEchoPassword() && !DontEchoPassword()) {
-      HideLastPWInput();
+      nsresult rv = HideLastPWInput();
       mLastStart = start;
       mLastLength = outString->Length();
       if (mTimer) {
         mTimer->Cancel();
-      } else {
+      }
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+      if (!mTimer) {
         mTimer = NS_NewTimer();
-        NS_ENSURE_TRUE(mTimer, NS_ERROR_OUT_OF_MEMORY);
       }
       mTimer->InitWithCallback(this, LookAndFeel::GetPasswordMaskDelay(),
                                nsITimer::TYPE_ONE_SHOT);
     } else {
       FillBufWithPWChars(outString, outString->Length());
     }
   }
 
@@ -1005,22 +1008,25 @@ TextEditRules::WillDeleteSelection(nsIEd
 
     // manage the password buffer
     uint32_t start, end;
     nsContentUtils::GetSelectionInTextControl(&SelectionRef(),
                                               TextEditorRef().GetRoot(),
                                               start, end);
 
     if (LookAndFeel::GetEchoPassword()) {
-      HideLastPWInput();
+      rv = HideLastPWInput();
       mLastStart = start;
       mLastLength = 0;
       if (mTimer) {
         mTimer->Cancel();
       }
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
     }
 
     // Collapsed selection.
     if (end == start) {
       // Deleting back.
       if (nsIEditor::ePrevious == aCollapsedAction && start > 0) {
         mPasswordText.Cut(start-1, 1);
       }
@@ -1601,16 +1607,17 @@ TextEditRules::Notify(nsITimer* aTimer)
     return NS_ERROR_FAILURE;
   }
 
   AutoSafeEditorData setData(*this, *mTextEditor, *selection);
 
   // Check whether our text editor's password flag was changed before this
   // "hide password character" timer actually fires.
   nsresult rv = IsPasswordEditor() ? HideLastPWInput() : NS_OK;
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to hide last password input");
   ASSERT_PASSWORD_LENGTHS_EQUAL();
   mLastLength = 0;
   return rv;
 }
 
 NS_IMETHODIMP
 TextEditRules::GetName(nsACString& aName)
 {
@@ -1638,22 +1645,31 @@ TextEditRules::HideLastPWInput()
 
   nsCOMPtr<nsINode> selNode = GetTextNode(&SelectionRef());
   if (NS_WARN_IF(!selNode)) {
     return NS_OK;
   }
 
   selNode->GetAsText()->ReplaceData(mLastStart, mLastLength, hiddenText,
                                     IgnoreErrors());
+  if (NS_WARN_IF(!CanHandleEditAction())) {
+    return NS_ERROR_EDITOR_DESTROYED;
+  }
   // XXXbz Selection::Collapse/Extend take int32_t, but there are tons of
   // callsites... Converting all that is a battle for another day.
   DebugOnly<nsresult> rv = SelectionRef().Collapse(selNode, start);
+  if (NS_WARN_IF(!CanHandleEditAction())) {
+    return NS_ERROR_EDITOR_DESTROYED;
+  }
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to collapse selection");
   if (start != end) {
     rv = SelectionRef().Extend(selNode, end);
+    if (NS_WARN_IF(!CanHandleEditAction())) {
+      return NS_ERROR_EDITOR_DESTROYED;
+    }
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to extend selection");
   }
   return NS_OK;
 }
 
 // static
 void
 TextEditRules::FillBufWithPWChars(nsAString* aOutString,
--- a/editor/libeditor/TextEditRules.h
+++ b/editor/libeditor/TextEditRules.h
@@ -250,17 +250,22 @@ protected:
   }
 
   void UndefineCaretBidiLevel();
 
   nsresult CheckBidiLevelForDeletion(const EditorRawDOMPoint& aSelectionPoint,
                                      nsIEditor::EDirection aAction,
                                      bool* aCancel);
 
-  nsresult HideLastPWInput();
+  /**
+   * HideLastPWInput() replaces last password characters which have not
+   * been replaced with mask character like '*' with with the mask character.
+   * This method may cause destroying the editor.
+   */
+  MOZ_MUST_USE nsresult HideLastPWInput();
 
   nsresult CollapseSelectionToTrailingBRIfNeeded();
 
   bool IsPasswordEditor() const;
   bool IsSingleLineEditor() const;
   bool IsPlaintextEditor() const;
   bool IsReadonly() const;
   bool IsDisabled() const;