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
--- 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;
}