Bug 1465702 - part 7: Make protected/private methods of EditorBase/TextEditor/HTMLEditor use SelectionRefPtr() instead of GetSelection() r=m_kato

Now, any protected/private methods of editor classes can refer
SelectionRefPtr() safely.  So, we can cut the cost of calling GetSelection()
only once per edit action handling.

Differential Revision: https://phabricator.services.mozilla.com/D10011

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Masayuki Nakano 2018-10-30 10:04:08 +00:00
Родитель 53578eb0db
Коммит d97102c926
7 изменённых файлов: 235 добавлений и 219 удалений

Просмотреть файл

@ -939,25 +939,24 @@ EditorBase::EndTransactionInternal()
void
EditorBase::BeginPlaceholderTransaction(nsAtom* aTransactionName)
{
MOZ_ASSERT(IsEditActionDataAvailable());
MOZ_ASSERT(mPlaceholderBatch >= 0, "negative placeholder batch count!");
if (!mPlaceholderBatch) {
NotifyEditorObservers(eNotifyEditorObserversOfBefore);
// time to turn on the batch
BeginUpdateViewBatch();
mPlaceholderTransaction = nullptr;
mPlaceholderName = aTransactionName;
RefPtr<Selection> selection = GetSelection();
if (selection) {
mSelState.emplace();
mSelState->SaveSelection(selection);
// Composition transaction can modify multiple nodes and it merges text
// node for ime into single text node.
// So if current selection is into IME text node, it might be failed
// to restore selection by UndoTransaction.
// So we need update selection by range updater.
if (mPlaceholderName == nsGkAtoms::IMETxnName) {
mRangeUpdater.RegisterSelectionState(*mSelState);
}
mSelState.emplace();
mSelState->SaveSelection(SelectionRefPtr());
// Composition transaction can modify multiple nodes and it merges text
// node for ime into single text node.
// So if current selection is into IME text node, it might be failed
// to restore selection by UndoTransaction.
// So we need update selection by range updater.
if (mPlaceholderName == nsGkAtoms::IMETxnName) {
mRangeUpdater.RegisterSelectionState(*mSelState);
}
}
mPlaceholderBatch++;
@ -966,20 +965,18 @@ EditorBase::BeginPlaceholderTransaction(nsAtom* aTransactionName)
void
EditorBase::EndPlaceholderTransaction()
{
MOZ_ASSERT(IsEditActionDataAvailable());
MOZ_ASSERT(mPlaceholderBatch > 0,
"zero or negative placeholder batch count when ending batch!");
if (mPlaceholderBatch == 1) {
RefPtr<Selection> selection = GetSelection();
if (mPlaceholderBatch == 1) {
// By making the assumption that no reflow happens during the calls
// to EndUpdateViewBatch and ScrollSelectionIntoView, we are able to
// allow the selection to cache a frame offset which is used by the
// caret drawing code. We only enable this cache here; at other times,
// we have no way to know whether reflow invalidates it
// See bugs 35296 and 199412.
if (selection) {
selection->SetCanCacheFrameOffset(true);
}
SelectionRefPtr()->SetCanCacheFrameOffset(true);
// time to turn off the batch
EndUpdateViewBatch();
@ -990,9 +987,7 @@ EditorBase::EndPlaceholderTransaction()
ScrollSelectionIntoView(false);
// cached for frame offset are Not available now
if (selection) {
selection->SetCanCacheFrameOffset(false);
}
SelectionRefPtr()->SetCanCacheFrameOffset(false);
if (mSelState) {
// we saved the selection state, but never got to hand it to placeholder
@ -3256,6 +3251,8 @@ EditorBase::DoJoinNodes(nsINode* aNodeToKeep,
nsINode* aNodeToJoin,
nsINode* aParent)
{
MOZ_ASSERT(IsEditActionDataAvailable());
MOZ_ASSERT(aNodeToKeep);
MOZ_ASSERT(aNodeToJoin);
MOZ_ASSERT(aParent);
@ -3399,11 +3396,11 @@ EditorBase::DoJoinNodes(nsINode* aNodeToKeep,
if (allowedTransactionsToChangeSelection) {
// Editor wants us to set selection at join point.
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_FAILURE;
}
selection->Collapse(aNodeToKeep, AssertedCast<int32_t>(firstNodeLength));
DebugOnly<nsresult> rv =
SelectionRefPtr()->Collapse(aNodeToKeep,
AssertedCast<int32_t>(firstNodeLength));
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"Failed to collapse Selection at end of the node");
}
return err.StealNSResult();
@ -4163,14 +4160,12 @@ EditorBase::JoinNodesDeepWithTransaction(nsIContent& aLeftNode,
void
EditorBase::BeginUpdateViewBatch()
{
MOZ_ASSERT(IsEditActionDataAvailable());
MOZ_ASSERT(mUpdateCount >= 0, "bad state");
if (!mUpdateCount) {
// Turn off selection updates and notifications.
RefPtr<Selection> selection = GetSelection();
if (selection) {
selection->StartBatchChanges();
}
SelectionRefPtr()->StartBatchChanges();
}
mUpdateCount++;
@ -4179,6 +4174,7 @@ EditorBase::BeginUpdateViewBatch()
void
EditorBase::EndUpdateViewBatch()
{
MOZ_ASSERT(IsEditActionDataAvailable());
MOZ_ASSERT(mUpdateCount > 0, "bad state");
if (mUpdateCount <= 0) {
@ -4191,10 +4187,7 @@ EditorBase::EndUpdateViewBatch()
}
// Turn selection updating and notifications back on.
RefPtr<Selection> selection = GetSelection();
if (selection) {
selection->EndBatchChanges();
}
SelectionRefPtr()->EndBatchChanges();
HTMLEditor* htmlEditor = AsHTMLEditor();
if (!htmlEditor) {
@ -4207,10 +4200,6 @@ EditorBase::EndUpdateViewBatch()
// to a document may result in multiple events, some of them quite hard
// to listen too (in particular when an ancestor of the selection is
// changed but the selection itself is not changed).
if (NS_WARN_IF(!selection)) {
return;
}
DebugOnly<nsresult> rv = htmlEditor->RefereshEditingUI();
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "RefereshEditingUI() failed");
}
@ -4278,13 +4267,10 @@ EditorBase::CreateTxnForDeleteSelection(EDirection aAction,
int32_t* aOffset,
int32_t* aLength)
{
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return nullptr;
}
MOZ_ASSERT(IsEditActionDataAvailable());
// Check whether the selection is collapsed and we should do nothing:
if (NS_WARN_IF(selection->IsCollapsed() && aAction == eNone)) {
if (NS_WARN_IF(SelectionRefPtr()->IsCollapsed() && aAction == eNone)) {
return nullptr;
}
@ -4292,8 +4278,10 @@ EditorBase::CreateTxnForDeleteSelection(EDirection aAction,
RefPtr<EditAggregateTransaction> aggregateTransaction =
EditAggregateTransaction::Create();
for (uint32_t rangeIdx = 0; rangeIdx < selection->RangeCount(); ++rangeIdx) {
RefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
for (uint32_t rangeIdx = 0;
rangeIdx < SelectionRefPtr()->RangeCount();
++rangeIdx) {
RefPtr<nsRange> range = SelectionRefPtr()->GetRangeAt(rangeIdx);
if (NS_WARN_IF(!range)) {
return nullptr;
}
@ -4530,33 +4518,44 @@ EditorBase::CreateRange(nsINode* aStartContainer,
nsresult
EditorBase::AppendNodeToSelectionAsRange(nsINode* aNode)
{
NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
MOZ_ASSERT(IsEditActionDataAvailable());
if (NS_WARN_IF(!aNode)) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsINode> parentNode = aNode->GetParentNode();
NS_ENSURE_TRUE(parentNode, NS_ERROR_NULL_POINTER);
if (NS_WARN_IF(!parentNode)) {
return NS_ERROR_FAILURE;
}
int32_t offset = GetChildOffset(aNode, parentNode);
RefPtr<nsRange> range;
nsresult rv = CreateRange(parentNode, offset, parentNode, offset + 1,
getter_AddRefs(range));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(range, NS_ERROR_NULL_POINTER);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (NS_WARN_IF(!range)) {
return NS_ERROR_FAILURE;
}
ErrorResult err;
selection->AddRange(*range, err);
SelectionRefPtr()->AddRange(*range, err);
NS_WARNING_ASSERTION(!err.Failed(), "Failed to add range to Selection");
return err.StealNSResult();
}
nsresult
EditorBase::ClearSelection()
{
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
MOZ_ASSERT(IsEditActionDataAvailable());
ErrorResult rv;
selection->RemoveAllRanges(rv);
SelectionRefPtr()->RemoveAllRanges(rv);
NS_WARNING_ASSERTION(!rv.Failed(),
"Failed to remove all ranges from Selection");
return rv.StealNSResult();
}
@ -4708,18 +4707,21 @@ EditorBase::InitializeSelectionAncestorLimit(nsIContent& aAncestorLimit)
nsresult
EditorBase::InitializeSelection(EventTarget* aFocusEventTarget)
{
MOZ_ASSERT(IsEditActionDataAvailable());
nsCOMPtr<nsINode> targetNode = do_QueryInterface(aFocusEventTarget);
NS_ENSURE_TRUE(targetNode, NS_ERROR_INVALID_ARG);
if (NS_WARN_IF(!targetNode)) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIContent> selectionRootContent = FindSelectionRoot(targetNode);
if (!selectionRootContent) {
return NS_OK;
}
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_STATE(selection);
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_INITIALIZED);
if (NS_WARN_IF(!presShell)) {
return NS_ERROR_NOT_INITIALIZED;
}
nsCOMPtr<nsISelectionController> selectionController =
GetSelectionController();
@ -4729,9 +4731,11 @@ EditorBase::InitializeSelection(EventTarget* aFocusEventTarget)
// Init the caret
RefPtr<nsCaret> caret = presShell->GetCaret();
NS_ENSURE_TRUE(caret, NS_ERROR_UNEXPECTED);
if (NS_WARN_IF(!caret)) {
return NS_ERROR_FAILURE;
}
caret->SetIgnoreUserModify(false);
caret->SetSelection(selection);
caret->SetSelection(SelectionRefPtr());
selectionController->SetCaretReadOnly(IsReadonly());
selectionController->SetCaretEnabled(true);
@ -4751,7 +4755,7 @@ EditorBase::InitializeSelection(EventTarget* aFocusEventTarget)
if (selectionRootContent->GetParent()) {
InitializeSelectionAncestorLimit(*selectionRootContent);
} else {
selection->SetAncestorLimiter(nullptr);
SelectionRefPtr()->SetAncestorLimiter(nullptr);
}
// If there is composition when this is called, we may need to restore IME
@ -4760,7 +4764,7 @@ EditorBase::InitializeSelection(EventTarget* aFocusEventTarget)
if (mComposition && mComposition->IsMovingToNewTextNode()) {
// We need to look for the new text node from current selection.
// XXX If selection is changed during reframe, this doesn't work well!
nsRange* firstRange = selection->GetRangeAt(0);
nsRange* firstRange = SelectionRefPtr()->GetRangeAt(0);
if (NS_WARN_IF(!firstRange)) {
return NS_ERROR_FAILURE;
}

Просмотреть файл

@ -564,6 +564,8 @@ HTMLEditor::SetPositionToAbsoluteOrStatic(Element& aElement,
nsresult
HTMLEditor::SetPositionToAbsolute(Element& aElement)
{
MOZ_ASSERT(IsEditActionDataAvailable());
AutoPlaceholderBatch treatAsOneTransaction(*this);
int32_t x, y;
@ -580,10 +582,6 @@ HTMLEditor::SetPositionToAbsolute(Element& aElement)
// container
nsINode* parentNode = aElement.GetParentNode();
if (parentNode->GetChildCount() == 1) {
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_FAILURE;
}
RefPtr<Element> newBrElement =
InsertBrElementWithTransaction(EditorRawDOMPoint(parentNode, 0));
if (NS_WARN_IF(!newBrElement)) {

Просмотреть файл

@ -661,15 +661,7 @@ nsresult
HTMLEditor::MaybeCollapseSelectionAtFirstEditableNode(
bool aIgnoreIfSelectionInEditingHost)
{
// XXX Why doesn't this check if the document is alive?
if (!IsInitialized()) {
return NS_ERROR_NOT_INITIALIZED;
}
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_NOT_INITIALIZED;
}
MOZ_ASSERT(IsEditActionDataAvailable());
// Use editing host. If you use root element here, selection may be
// moved to <head> element, e.g., if there is a text node in <script>
@ -682,8 +674,8 @@ HTMLEditor::MaybeCollapseSelectionAtFirstEditableNode(
// If selection range is already in the editing host and the range is not
// start of the editing host, we shouldn't reset selection. E.g., window
// is activated when the editor had focus before inactivated.
if (aIgnoreIfSelectionInEditingHost && selection->RangeCount() == 1) {
nsRange* range = selection->GetRangeAt(0);
if (aIgnoreIfSelectionInEditingHost && SelectionRefPtr()->RangeCount() == 1) {
nsRange* range = SelectionRefPtr()->GetRangeAt(0);
if (!range->Collapsed() ||
range->GetStartContainer() != editingHost.get() ||
range->StartOffset()) {
@ -775,7 +767,11 @@ HTMLEditor::MaybeCollapseSelectionAtFirstEditableNode(
pointToPutCaret.Set(visNode, 0);
}
}
return selection->Collapse(pointToPutCaret);
nsresult rv = SelectionRefPtr()->Collapse(pointToPutCaret);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
nsresult
@ -826,7 +822,10 @@ HTMLEditor::HandleKeyPressEvent(WidgetKeyboardEvent* aKeyboardEvent)
}
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection && selection->RangeCount(), NS_ERROR_FAILURE);
if (NS_WARN_IF(!selection) ||
NS_WARN_IF(!selection->RangeCount())) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsINode> node = selection->GetRangeAt(0)->GetStartContainer();
MOZ_ASSERT(node);
@ -1241,6 +1240,8 @@ HTMLEditor::TabInTable(bool inIsShift,
nsresult
HTMLEditor::InsertBrElementAtSelectionWithTransaction()
{
MOZ_ASSERT(IsEditActionDataAvailable());
// calling it text insertion to trigger moz br treatment by rules
// XXX Why do we use EditSubAction::eInsertText here? Looks like
// EditSubAction::eInsertParagraphSeparator or EditSubAction::eInsertNode
@ -1249,17 +1250,15 @@ HTMLEditor::InsertBrElementAtSelectionWithTransaction()
*this, EditSubAction::eInsertText,
nsIEditor::eNext);
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_STATE(selection);
if (!selection->IsCollapsed()) {
if (!SelectionRefPtr()->IsCollapsed()) {
nsresult rv = DeleteSelectionAsSubAction(eNone, eStrip);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
EditorRawDOMPoint atStartOfSelection(EditorBase::GetStartPoint(*selection));
EditorRawDOMPoint atStartOfSelection(
EditorBase::GetStartPoint(*SelectionRefPtr()));
if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
return NS_ERROR_FAILURE;
}
@ -1300,13 +1299,13 @@ nsresult
HTMLEditor::ReplaceHeadContentsWithSourceWithTransaction(
const nsAString& aSourceToInsert)
{
MOZ_ASSERT(IsEditActionDataAvailable());
// don't do any post processing, rules get confused
AutoTopLevelEditSubActionNotifier
maybeTopLevelEditSubAction(*this,
EditSubAction::eReplaceHeadWithHTMLSource,
nsIEditor::eNone);
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
CommitComposition();
@ -1346,7 +1345,7 @@ HTMLEditor::ReplaceHeadContentsWithSourceWithTransaction(
AutoPlaceholderBatch treatAsOneTransaction(*this);
// Get the first range in the selection, for context:
RefPtr<nsRange> range = selection->GetRangeAt(0);
RefPtr<nsRange> range = SelectionRefPtr()->GetRangeAt(0);
if (NS_WARN_IF(!range)) {
return NS_ERROR_FAILURE;
}
@ -2007,38 +2006,49 @@ HTMLEditor::GetCSSBackgroundColorState(bool* aMixed,
nsAString& aOutColor,
bool aBlockLevel)
{
NS_ENSURE_TRUE(aMixed, NS_ERROR_NULL_POINTER);
MOZ_ASSERT(IsEditActionDataAvailable());
if (NS_WARN_IF(!aMixed)) {
return NS_ERROR_INVALID_ARG;
}
*aMixed = false;
// the default background color is transparent
aOutColor.AssignLiteral("transparent");
// get selection
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_STATE(selection && selection->GetRangeAt(0));
RefPtr<nsRange> firstRange = SelectionRefPtr()->GetRangeAt(0);
if (NS_WARN_IF(!firstRange)) {
return NS_ERROR_FAILURE;
}
// get selection location
nsCOMPtr<nsINode> parent = selection->GetRangeAt(0)->GetStartContainer();
NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsINode> parent = firstRange->GetStartContainer();
if (NS_WARN_IF(!parent)) {
return NS_ERROR_FAILURE;
}
// is the selection collapsed?
nsCOMPtr<nsINode> nodeToExamine;
if (selection->IsCollapsed() || IsTextNode(parent)) {
if (SelectionRefPtr()->IsCollapsed() || IsTextNode(parent)) {
// we want to look at the parent and ancestors
nodeToExamine = parent;
} else {
// otherwise we want to look at the first editable node after
// {parent,offset} and its ancestors for divs with alignment on them
nodeToExamine = selection->GetRangeAt(0)->GetChildAtStartOffset();
nodeToExamine = firstRange->GetChildAtStartOffset();
//GetNextNode(parent, offset, true, address_of(nodeToExamine));
}
NS_ENSURE_TRUE(nodeToExamine, NS_ERROR_NULL_POINTER);
if (NS_WARN_IF(!nodeToExamine)) {
return NS_ERROR_FAILURE;
}
if (aBlockLevel) {
// we are querying the block background (and not the text background), let's
// climb to the block container
nsCOMPtr<Element> blockParent = GetBlock(*nodeToExamine);
NS_ENSURE_TRUE(blockParent, NS_OK);
if (NS_WARN_IF(!blockParent)) {
return NS_OK;
}
// Make sure to not walk off onto the Document node
do {
@ -2093,16 +2103,16 @@ nsresult
HTMLEditor::GetHTMLBackgroundColorState(bool* aMixed,
nsAString& aOutColor)
{
//TODO: We don't handle "mixed" correctly!
NS_ENSURE_TRUE(aMixed, NS_ERROR_NULL_POINTER);
MOZ_ASSERT(IsEditActionDataAvailable());
// TODO: We don't handle "mixed" correctly!
if (NS_WARN_IF(!aMixed)) {
return NS_ERROR_INVALID_ARG;
}
*aMixed = false;
aOutColor.Truncate();
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_FAILURE;
}
ErrorResult error;
RefPtr<Element> cellOrRowOrTableElement =
GetSelectedOrParentTableElement(error);
@ -2132,8 +2142,10 @@ HTMLEditor::GetHTMLBackgroundColorState(bool* aMixed,
}
// If no table or cell found, get page body
dom::Element* bodyElement = GetRoot();
NS_ENSURE_TRUE(bodyElement, NS_ERROR_NULL_POINTER);
Element* bodyElement = GetRoot();
if (NS_WARN_IF(!bodyElement)) {
return NS_ERROR_FAILURE;
}
bodyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::bgcolor, aOutColor);
return NS_OK;
@ -3126,12 +3138,7 @@ HTMLEditor::InsertLinkAroundSelection(Element* aAnchorElement)
nsresult
HTMLEditor::SetHTMLBackgroundColorWithTransaction(const nsAString& aColor)
{
MOZ_ASSERT(IsInitialized(), "The HTMLEditor hasn't been initialized yet");
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(IsEditActionDataAvailable());
// Find a selected or enclosing table element to set background on
ErrorResult error;
@ -3481,26 +3488,31 @@ nsresult
HTMLEditor::DeleteSelectionWithTransaction(EDirection aAction,
EStripWrappers aStripWrappers)
{
MOZ_ASSERT(IsEditActionDataAvailable());
MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
nsresult rv =
TextEditor::DeleteSelectionWithTransaction(aAction, aStripWrappers);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// If we weren't asked to strip any wrappers, we're done.
if (aStripWrappers == eNoStrip) {
return NS_OK;
}
RefPtr<Selection> selection = GetSelection();
// Just checking that the selection itself is collapsed doesn't seem to work
// right in the multi-range case
NS_ENSURE_STATE(selection);
NS_ENSURE_STATE(selection->GetAnchorFocusRange());
NS_ENSURE_STATE(selection->GetAnchorFocusRange()->Collapsed());
if (NS_WARN_IF(!SelectionRefPtr()->GetAnchorFocusRange()) ||
NS_WARN_IF(!SelectionRefPtr()->GetAnchorFocusRange()->Collapsed()) ||
NS_WARN_IF(!SelectionRefPtr()->GetAnchorNode()->IsContent())) {
return NS_ERROR_FAILURE;
}
NS_ENSURE_STATE(selection->GetAnchorNode()->IsContent());
nsCOMPtr<nsIContent> content = selection->GetAnchorNode()->AsContent();
nsCOMPtr<nsIContent> content =
SelectionRefPtr()->GetAnchorNode()->AsContent();
// Don't strip wrappers if this is the only wrapper in the block. Then we'll
// add a <br> later, so it won't be an empty wrapper in the end.
@ -3513,7 +3525,9 @@ HTMLEditor::DeleteSelectionWithTransaction(EDirection aAction,
}
bool emptyBlockParent;
rv = IsEmptyNode(blockParent, &emptyBlockParent);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (emptyBlockParent) {
return NS_OK;
}
@ -3527,7 +3541,9 @@ HTMLEditor::DeleteSelectionWithTransaction(EDirection aAction,
content = content->GetParent();
}
rv = DeleteNodeWithTransaction(*content);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
return NS_OK;
@ -3846,6 +3862,8 @@ HTMLEditor::SelectEntireDocument()
nsresult
HTMLEditor::SelectAllInternal()
{
MOZ_ASSERT(IsEditActionDataAvailable());
CommitComposition();
if (NS_WARN_IF(Destroyed())) {
return NS_ERROR_EDITOR_DESTROYED;
@ -3857,12 +3875,7 @@ HTMLEditor::SelectAllInternal()
// before committing composition and check if selection is still in
// same editing host.
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_FAILURE;
}
nsINode* anchorNode = selection->GetAnchorNode();
nsINode* anchorNode = SelectionRefPtr()->GetAnchorNode();
if (NS_WARN_IF(!anchorNode) || NS_WARN_IF(!anchorNode->IsContent())) {
return NS_ERROR_FAILURE;
}
@ -3870,7 +3883,7 @@ HTMLEditor::SelectAllInternal()
nsIContent* anchorContent = anchorNode->AsContent();
nsIContent* rootContent;
if (anchorContent->HasIndependentSelection()) {
selection->SetAncestorLimiter(nullptr);
SelectionRefPtr()->SetAncestorLimiter(nullptr);
rootContent = mRootElement;
} else {
nsCOMPtr<nsIPresShell> ps = GetPresShell();
@ -3881,12 +3894,12 @@ HTMLEditor::SelectAllInternal()
return NS_ERROR_UNEXPECTED;
}
Maybe<mozilla::dom::Selection::AutoUserInitiated> userSelection;
Maybe<Selection::AutoUserInitiated> userSelection;
if (!rootContent->IsEditable()) {
userSelection.emplace(selection);
userSelection.emplace(SelectionRefPtr());
}
ErrorResult errorResult;
selection->SelectAllChildren(*rootContent, errorResult);
SelectionRefPtr()->SelectAllChildren(*rootContent, errorResult);
NS_WARNING_ASSERTION(!errorResult.Failed(), "SelectAllChildren() failed");
return errorResult.StealNSResult();
}
@ -3935,6 +3948,8 @@ HTMLEditor::IsTextPropertySetByContent(nsINode* aNode,
bool
HTMLEditor::SetCaretInTableCell(Element* aElement)
{
MOZ_ASSERT(IsEditActionDataAvailable());
if (!aElement || !aElement->IsHTMLElement() ||
!HTMLEditUtils::IsTableElement(aElement) ||
!IsDescendantOfEditorRoot(aElement)) {
@ -3947,10 +3962,10 @@ HTMLEditor::SetCaretInTableCell(Element* aElement)
}
// Set selection at beginning of the found node
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, false);
return NS_SUCCEEDED(selection->Collapse(node, 0));
nsresult rv = SelectionRefPtr()->Collapse(node, 0);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"Failed to collapse Selection in aElement");
return NS_SUCCEEDED(rv);
}
/**
@ -4049,10 +4064,7 @@ HTMLEditor::SetSelectionAtDocumentStart()
nsresult
HTMLEditor::RemoveBlockContainerWithTransaction(Element& aElement)
{
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(IsEditActionDataAvailable());
// Two possibilities: the container could be empty of editable content. If
// that is the case, we need to compare what is before and after aNode to
@ -4819,6 +4831,8 @@ HTMLEditor::CopyLastEditableChildStylesWithTransaction(
Element& aNewBlock,
RefPtr<Element>* aNewBrElement)
{
MOZ_ASSERT(IsEditActionDataAvailable());
if (NS_WARN_IF(!aNewBrElement)) {
return NS_ERROR_INVALID_ARG;
}
@ -4906,10 +4920,6 @@ HTMLEditor::CopyLastEditableChildStylesWithTransaction(
return NS_OK;
}
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_FAILURE;
}
RefPtr<Element> brElement =
InsertBrElementWithTransaction(EditorRawDOMPoint(firstClonsedElement, 0));
if (NS_WARN_IF(!brElement)) {

Просмотреть файл

@ -1039,16 +1039,15 @@ HTMLEditor::GetInlinePropertyBase(nsAtom& aProperty,
bool* aAll,
nsAString* outValue)
{
MOZ_ASSERT(IsEditActionDataAvailable());
*aAny = false;
*aAll = true;
*aFirst = false;
bool first = true;
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
bool isCollapsed = selection->IsCollapsed();
RefPtr<nsRange> range = selection->GetRangeAt(0);
bool isCollapsed = SelectionRefPtr()->IsCollapsed();
RefPtr<nsRange> range = SelectionRefPtr()->GetRangeAt(0);
// XXX: Should be a while loop, to get each separate range
// XXX: ERROR_HANDLING can currentItem be null?
if (range) {
@ -1057,7 +1056,9 @@ HTMLEditor::GetInlinePropertyBase(nsAtom& aProperty,
if (isCollapsed) {
nsCOMPtr<nsINode> collapsedNode = range->GetStartContainer();
NS_ENSURE_TRUE(collapsedNode, NS_ERROR_FAILURE);
if (NS_WARN_IF(!collapsedNode)) {
return NS_ERROR_FAILURE;
}
bool isSet, theSetting;
nsString tOutString;
if (aAttribute) {
@ -1506,23 +1507,29 @@ HTMLEditor::DecreaseFontSize()
nsresult
HTMLEditor::RelativeFontChange(FontSize aDir)
{
MOZ_ASSERT(IsEditActionDataAvailable());
CommitComposition();
// Get the selection
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
// If selection is collapsed, set typing state
if (selection->IsCollapsed()) {
if (SelectionRefPtr()->IsCollapsed()) {
nsAtom& atom = aDir == FontSize::incr ? *nsGkAtoms::big :
*nsGkAtoms::small;
*nsGkAtoms::small;
// Let's see in what kind of element the selection is
NS_ENSURE_TRUE(selection->RangeCount() &&
selection->GetRangeAt(0)->GetStartContainer(), NS_OK);
OwningNonNull<nsINode> selectedNode =
*selection->GetRangeAt(0)->GetStartContainer();
if (NS_WARN_IF(!SelectionRefPtr()->RangeCount())) {
return NS_OK;
}
RefPtr<nsRange> firstRange = SelectionRefPtr()->GetRangeAt(0);
if (NS_WARN_IF(!firstRange) ||
NS_WARN_IF(!firstRange->GetStartContainer())) {
return NS_OK;
}
OwningNonNull<nsINode> selectedNode = *firstRange->GetStartContainer();
if (IsTextNode(selectedNode)) {
NS_ENSURE_TRUE(selectedNode->GetParentNode(), NS_OK);
if (NS_WARN_IF(!selectedNode->GetParentNode())) {
return NS_OK;
}
selectedNode = *selectedNode->GetParentNode();
}
if (!CanContainTag(selectedNode, atom)) {
@ -1544,11 +1551,13 @@ HTMLEditor::RelativeFontChange(FontSize aDir)
AutoTransactionsConserveSelection dontChangeMySelection(*this);
// Loop through the ranges in the selection
AutoRangeArray arrayOfRanges(selection);
AutoRangeArray arrayOfRanges(SelectionRefPtr());
for (auto& range : arrayOfRanges.mRanges) {
// Adjust range to include any ancestors with entirely selected children
nsresult rv = PromoteInlineRange(*range);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Check for easy case: both range endpoints in same text node
nsCOMPtr<nsINode> startNode = range->GetStartContainer();
@ -1557,7 +1566,9 @@ HTMLEditor::RelativeFontChange(FontSize aDir)
rv = RelativeFontChangeOnTextNode(aDir, *startNode->GetAsText(),
range->StartOffset(),
range->EndOffset());
NS_ENSURE_SUCCESS(rv, rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else {
// Not the easy case. Range not contained in single text node. There
// are up to three phases here. There are all the nodes reported by the
@ -1577,7 +1588,9 @@ HTMLEditor::RelativeFontChange(FontSize aDir)
if (NS_SUCCEEDED(rv)) {
nsTArray<OwningNonNull<nsIContent>> arrayOfNodes;
for (; !iter->IsDone(); iter->Next()) {
NS_ENSURE_TRUE(iter->GetCurrentNode()->IsContent(), NS_ERROR_FAILURE);
if (NS_WARN_IF(!iter->GetCurrentNode()->IsContent())) {
return NS_ERROR_FAILURE;
}
OwningNonNull<nsIContent> node = *iter->GetCurrentNode()->AsContent();
if (IsEditable(node)) {
@ -1588,7 +1601,9 @@ HTMLEditor::RelativeFontChange(FontSize aDir)
// Now that we have the list, do the font size change on each node
for (auto& node : arrayOfNodes) {
rv = RelativeFontChangeOnNode(aDir == FontSize::incr ? +1 : -1, node);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
}
// Now check the start and end parents of the range to see if they need
@ -1598,12 +1613,16 @@ HTMLEditor::RelativeFontChange(FontSize aDir)
rv = RelativeFontChangeOnTextNode(aDir, *startNode->GetAsText(),
range->StartOffset(),
startNode->Length());
NS_ENSURE_SUCCESS(rv, rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
if (IsTextNode(endNode) && IsEditable(endNode)) {
rv = RelativeFontChangeOnTextNode(aDir, *endNode->GetAsText(), 0,
range->EndOffset());
NS_ENSURE_SUCCESS(rv, rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
}
}

Просмотреть файл

@ -1401,6 +1401,8 @@ nsresult
HTMLEditor::DeleteTableColumnWithTransaction(Element& aTableElement,
int32_t aColumnIndex)
{
MOZ_ASSERT(IsEditActionDataAvailable());
// XXX Why don't this method remove proper <col> (and <colgroup>)?
ErrorResult error;
IgnoredErrorResult ignoredError;
@ -1473,10 +1475,6 @@ HTMLEditor::DeleteTableColumnWithTransaction(Element& aTableElement,
if (tableSize.mRowCount == 1) {
// We're deleting the last row. So, let's remove the <table> now.
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_FAILURE;
}
nsresult rv = DeleteTableElementAndChildrenWithTransaction(aTableElement);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@ -3958,12 +3956,9 @@ HTMLEditor::SetSelectionAfterTableEdit(Element* aTable,
int32_t aDirection,
bool aSelected)
{
if (NS_WARN_IF(!aTable) || Destroyed()) {
return;
}
MOZ_ASSERT(IsEditActionDataAvailable());
RefPtr<Selection> selection = GetSelection();
if (!selection) {
if (NS_WARN_IF(!aTable) || Destroyed()) {
return;
}
@ -4026,7 +4021,9 @@ HTMLEditor::SetSelectionAfterTableEdit(Element* aTable,
if (NS_WARN_IF(!atTable.IsSetAndValid())) {
return;
}
selection->Collapse(atTable);
DebugOnly<nsresult> rv = SelectionRefPtr()->Collapse(atTable);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"Failed to collapse Selection at the table");
return;
}
// Last resort: Set selection to start of doc

Просмотреть файл

@ -881,17 +881,14 @@ TextEditor::DeleteSelectionWithTransaction(EDirection aDirection,
already_AddRefed<Element>
TextEditor::DeleteSelectionAndCreateElement(nsAtom& aTag)
{
MOZ_ASSERT(IsEditActionDataAvailable());
nsresult rv = DeleteSelectionAndPrepareToCreateNode();
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return nullptr;
}
EditorRawDOMPoint pointToInsert(selection->AnchorRef());
EditorRawDOMPoint pointToInsert(SelectionRefPtr()->AnchorRef());
if (!pointToInsert.IsSet()) {
return nullptr;
}
@ -904,7 +901,7 @@ TextEditor::DeleteSelectionAndCreateElement(nsAtom& aTag)
NS_WARNING_ASSERTION(advanced,
"Failed to move offset next to the new element");
ErrorResult error;
selection->Collapse(afterNewElement, error);
SelectionRefPtr()->Collapse(afterNewElement, error);
if (NS_WARN_IF(error.Failed())) {
// XXX Even if it succeeded to create new element, this returns error
// when Selection.Collapse() fails something. This could occur with
@ -918,28 +915,25 @@ TextEditor::DeleteSelectionAndCreateElement(nsAtom& aTag)
nsresult
TextEditor::DeleteSelectionAndPrepareToCreateNode()
{
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_NOT_INITIALIZED;
}
MOZ_ASSERT(IsEditActionDataAvailable());
if (NS_WARN_IF(!selection->GetAnchorFocusRange())) {
if (NS_WARN_IF(!SelectionRefPtr()->GetAnchorFocusRange())) {
return NS_OK;
}
if (!selection->GetAnchorFocusRange()->Collapsed()) {
if (!SelectionRefPtr()->GetAnchorFocusRange()->Collapsed()) {
nsresult rv = DeleteSelectionAsSubAction(eNone, eStrip);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(selection->GetAnchorFocusRange() &&
selection->GetAnchorFocusRange()->Collapsed(),
MOZ_ASSERT(SelectionRefPtr()->GetAnchorFocusRange() &&
SelectionRefPtr()->GetAnchorFocusRange()->Collapsed(),
"Selection not collapsed after delete");
}
// If the selection is a chardata node, split it if necessary and compute
// where to put the new node
EditorDOMPoint atAnchor(selection->AnchorRef());
EditorDOMPoint atAnchor(SelectionRefPtr()->AnchorRef());
if (NS_WARN_IF(!atAnchor.IsSet()) || !atAnchor.IsInDataNode()) {
return NS_OK;
}
@ -954,7 +948,7 @@ TextEditor::DeleteSelectionAndPrepareToCreateNode()
return NS_ERROR_FAILURE;
}
ErrorResult error;
selection->Collapse(atAnchorContainer, error);
SelectionRefPtr()->Collapse(atAnchorContainer, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
@ -967,7 +961,7 @@ TextEditor::DeleteSelectionAndPrepareToCreateNode()
return NS_ERROR_FAILURE;
}
ErrorResult error;
selection->Collapse(afterAnchorContainer, error);
SelectionRefPtr()->Collapse(afterAnchorContainer, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
@ -985,7 +979,7 @@ TextEditor::DeleteSelectionAndPrepareToCreateNode()
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(atRightNode.IsSetAndValid());
selection->Collapse(atRightNode, error);
SelectionRefPtr()->Collapse(atRightNode, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
@ -1803,17 +1797,14 @@ TextEditor::Redo(uint32_t aCount)
bool
TextEditor::CanCutOrCopy(PasswordFieldAllowed aPasswordFieldAllowed)
{
RefPtr<Selection> selection = GetSelection();
if (!selection) {
return false;
}
MOZ_ASSERT(IsEditActionDataAvailable());
if (aPasswordFieldAllowed == ePasswordFieldNotAllowed &&
IsPasswordEditor()) {
return false;
}
return !selection->IsCollapsed();
return !SelectionRefPtr()->IsCollapsed();
}
bool
@ -1821,20 +1812,20 @@ TextEditor::FireClipboardEvent(EventMessage aEventMessage,
int32_t aSelectionType,
bool* aActionTaken)
{
MOZ_ASSERT(IsEditActionDataAvailable());
if (aEventMessage == ePaste) {
CommitComposition();
}
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
NS_ENSURE_TRUE(presShell, false);
RefPtr<Selection> selection = GetSelection();
if (!selection) {
if (NS_WARN_IF(!presShell)) {
return false;
}
if (!nsCopySupport::FireClipboardEvent(aEventMessage, aSelectionType,
presShell, selection, aActionTaken)) {
presShell, SelectionRefPtr(),
aActionTaken)) {
return false;
}
@ -1935,6 +1926,8 @@ TextEditor::GetAndInitDocEncoder(const nsAString& aFormatType,
uint32_t aDocumentEncoderFlags,
const nsACString& aCharset) const
{
MOZ_ASSERT(IsEditActionDataAvailable());
nsCOMPtr<nsIDocumentEncoder> docEncoder;
if (!mCachedDocumentEncoder ||
!mCachedDocumentEncoderType.Equals(aFormatType)) {
@ -1975,11 +1968,7 @@ TextEditor::GetAndInitDocEncoder(const nsAString& aFormatType,
// We do this either if the OutputSelectionOnly flag is set,
// in which case we use our existing selection ...
if (aDocumentEncoderFlags & nsIDocumentEncoder::OutputSelectionOnly) {
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return nullptr;
}
rv = docEncoder->SetSelection(selection);
rv = docEncoder->SetSelection(SelectionRefPtr());
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
@ -2179,10 +2168,9 @@ TextEditor::SharedOutputString(uint32_t aFlags,
bool* aIsCollapsed,
nsAString& aResult)
{
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
MOZ_ASSERT(IsEditActionDataAvailable());
*aIsCollapsed = selection->IsCollapsed();
*aIsCollapsed = SelectionRefPtr()->IsCollapsed();
if (!*aIsCollapsed) {
aFlags |= nsIDocumentEncoder::OutputSelectionOnly;

Просмотреть файл

@ -70,10 +70,9 @@ TextEditor::InsertTextAt(const nsAString& aStringToInsert,
int32_t aDestOffset,
bool aDoDeleteSelection)
{
if (aDestinationNode) {
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_STATE(selection);
MOZ_ASSERT(IsEditActionDataAvailable());
if (aDestinationNode) {
nsCOMPtr<nsINode> targetNode = aDestinationNode;
int32_t targetOffset = aDestOffset;
@ -88,7 +87,8 @@ TextEditor::InsertTextAt(const nsAString& aStringToInsert,
}
ErrorResult error;
selection->Collapse(RawRangeBoundary(targetNode, targetOffset), error);
SelectionRefPtr()->Collapse(RawRangeBoundary(targetNode, targetOffset),
error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}