Bug 1467692 - Create EditorBase::SelectAllInternal() for internal use r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Thu, 07 Jun 2018 22:30:14 +0900
changeset 805647 8c525e856612c0f4e5577b308eeef098cd71086f
parent 805646 7dacf00f85e00833a470bafc29669fd53c285b2e
child 805653 bed68e8d4a72c935f652725dd241234c29507753
push id112727
push usermasayuki@d-toybox.com
push dateFri, 08 Jun 2018 07:35:45 +0000
reviewersm_kato
bugs1467692, 1465702
milestone62.0a1
Bug 1467692 - Create EditorBase::SelectAllInternal() for internal use r?m_kato For preparing to fix bug 1465702, we need to split public methods of editor which are used by both outside and itself or friends. SelectAll() is used by both outside and TextEditor. So, we need to create SelectAllInternal() and make TextEditor use it instead. MozReview-Commit-ID: JtIlrfBYBSD
editor/libeditor/EditorBase.cpp
editor/libeditor/EditorBase.h
editor/libeditor/HTMLEditor.cpp
editor/libeditor/HTMLEditor.h
editor/libeditor/TextEditor.cpp
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -1014,21 +1014,47 @@ EditorBase::GetDocumentIsEmpty(bool* aDo
 //      root, or the body)
 NS_IMETHODIMP
 EditorBase::SelectAll()
 {
   // XXX Why doesn't this check if the document is alive?
   if (!IsInitialized()) {
     return NS_ERROR_NOT_INITIALIZED;
   }
-  ForceCompositionEnd();
+
+  nsresult rv = SelectAllInternal();
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
+}
+
+nsresult
+EditorBase::SelectAllInternal()
+{
+  MOZ_ASSERT(IsInitialized());
+
+  CommitComposition();
+  if (NS_WARN_IF(Destroyed())) {
+    return NS_ERROR_EDITOR_DESTROYED;
+  }
+
+  // XXX Do we need to keep handling after committing composition causes moving
+  //     focus to different element?  Although TextEditor has independent
+  //     selection, so, we may not see any odd behavior even in such case.
 
   RefPtr<Selection> selection = GetSelection();
-  NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
-  return SelectEntireDocument(selection);
+  if (NS_WARN_IF(!selection)) {
+    return NS_ERROR_FAILURE;
+  }
+  nsresult rv = SelectEntireDocument(selection);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 EditorBase::BeginningOfDocument()
 {
   // XXX Why doesn't this check if the document is alive?
   if (!IsInitialized()) {
     return NS_ERROR_NOT_INITIALIZED;
--- a/editor/libeditor/EditorBase.h
+++ b/editor/libeditor/EditorBase.h
@@ -1618,16 +1618,23 @@ protected: // Called by helper classes.
 
 protected: // Shouldn't be used by friend classes
   /**
    * The default destructor. This should suffice. Should this be pure virtual
    * for someone to derive from the EditorBase later? I don't believe so.
    */
   virtual ~EditorBase();
 
+  /**
+   * SelectAllInternal() should be used instead of SelectAll() in editor
+   * because SelectAll() creates AutoEditActionSetter but we should avoid
+   * to create it as far as possible.
+   */
+  virtual nsresult SelectAllInternal();
+
   nsresult DetermineCurrentDirection();
   void FireInputEvent();
 
   /**
    * Called after a transaction is done successfully.
    */
   void DoAfterDoTransaction(nsITransaction *aTxn);
 
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -3583,47 +3583,61 @@ HTMLEditor::SelectEntireDocument(Selecti
 
     // if its empty dont select entire doc - that would select the bogus node
     return aSelection->Collapse(rootElement, 0);
   }
 
   return EditorBase::SelectEntireDocument(aSelection);
 }
 
-NS_IMETHODIMP
-HTMLEditor::SelectAll()
+nsresult
+HTMLEditor::SelectAllInternal()
 {
   CommitComposition();
+  if (NS_WARN_IF(Destroyed())) {
+    return NS_ERROR_EDITOR_DESTROYED;
+  }
+
+  // XXX Perhaps, we should check whether we still have focus since composition
+  //     event listener may have already moved focus to different editing
+  //     host or other element.  So, perhaps, we need to retrieve anchor node
+  //     before committing composition and check if selection is still in
+  //     same editing host.
 
   RefPtr<Selection> selection = GetSelection();
-  NS_ENSURE_STATE(selection);
+  if (NS_WARN_IF(!selection)) {
+    return NS_ERROR_FAILURE;
+  }
 
   nsINode* anchorNode = selection->GetAnchorNode();
   if (NS_WARN_IF(!anchorNode) || NS_WARN_IF(!anchorNode->IsContent())) {
     return NS_ERROR_FAILURE;
   }
 
   nsIContent* anchorContent = anchorNode->AsContent();
   nsIContent* rootContent;
   if (anchorContent->HasIndependentSelection()) {
     selection->SetAncestorLimiter(nullptr);
     rootContent = mRootElement;
   } else {
     nsCOMPtr<nsIPresShell> ps = GetPresShell();
     rootContent = anchorContent->GetSelectionRootContent(ps);
   }
 
-  NS_ENSURE_TRUE(rootContent, NS_ERROR_UNEXPECTED);
+  if (NS_WARN_IF(!rootContent)) {
+    return NS_ERROR_UNEXPECTED;
+  }
 
   Maybe<mozilla::dom::Selection::AutoUserInitiated> userSelection;
   if (!rootContent->IsEditable()) {
     userSelection.emplace(selection);
   }
   ErrorResult errorResult;
   selection->SelectAllChildren(*rootContent, errorResult);
+  NS_WARNING_ASSERTION(!errorResult.Failed(), "SelectAllChildren() failed");
   return errorResult.StealNSResult();
 }
 
 // this will NOT find aAttribute unless aAttribute has a non-null value
 // so singleton attributes like <Table border> will not be matched!
 bool
 HTMLEditor::IsTextPropertySetByContent(nsINode* aNode,
                                        nsAtom* aProperty,
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -138,18 +138,16 @@ public:
 
   NS_IMETHOD Paste(int32_t aSelectionType) override;
   NS_IMETHOD CanPaste(int32_t aSelectionType, bool* aCanPaste) override;
 
   NS_IMETHOD PasteTransferable(nsITransferable* aTransferable) override;
 
   NS_IMETHOD DeleteNode(nsINode* aNode) override;
 
-  NS_IMETHOD SelectAll() override;
-
   NS_IMETHOD DebugUnitTests(int32_t* outNumTests,
                             int32_t* outNumTestsFailed) override;
 
   virtual nsresult HandleKeyPressEvent(
                      WidgetKeyboardEvent* aKeyboardEvent) override;
   virtual nsIContent* GetFocusedContent() override;
   virtual already_AddRefed<nsIContent> GetFocusedContentForIME() override;
   virtual bool IsActiveInDOMWindow() override;
@@ -746,16 +744,18 @@ protected: // Called by helper classes.
     EditSubAction aEditSubAction, nsIEditor::EDirection aDirection) override;
   virtual void OnEndHandlingTopLevelEditSubAction() override;
 
   virtual nsresult EndUpdateViewBatch() override;
 
 protected: // Shouldn't be used by friend classes
   virtual ~HTMLEditor();
 
+  virtual nsresult SelectAllInternal() override;
+
   /**
    * InsertNodeIntoProperAncestorWithTransaction() attempts to insert aNode
    * into the document, at aPointToInsert.  Checks with strict dtd to see if
    * containment is allowed.  If not allowed, will attempt to find a parent
    * in the parent hierarchy of aPointToInsert.GetContainer() that will accept
    * aNode as a child.  If such a parent is found, will split the document
    * tree from aPointToInsert up to parent, and then insert aNode.
    * aPointToInsert is then adjusted to point to the actual location that
--- a/editor/libeditor/TextEditor.cpp
+++ b/editor/libeditor/TextEditor.cpp
@@ -1951,17 +1951,18 @@ TextEditor::Rewrap(bool aRespectNewlines
 
   nsString wrapped;
   uint32_t firstLineOffset = 0;   // XXX need to reset this if there is a selection
   rv = InternetCiter::Rewrap(current, wrapCol, firstLineOffset,
                              aRespectNewlines, wrapped);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (isCollapsed) {
-    SelectAll();
+    DebugOnly<nsresult> rv = SelectAllInternal();
+    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),  "Failed to select all text");
   }
 
   return InsertTextWithQuotations(wrapped);
 }
 
 NS_IMETHODIMP
 TextEditor::StripCites()
 {
@@ -1971,18 +1972,20 @@ TextEditor::StripCites()
                                    &isCollapsed, current);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsString stripped;
   rv = InternetCiter::StripCites(current, stripped);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (isCollapsed) {
-    rv = SelectAll();
-    NS_ENSURE_SUCCESS(rv, rv);
+    rv = SelectAllInternal();
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
   }
 
   rv = InsertTextAsAction(stripped);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }