Commit 94482e33 authored by Yoshifumi Inoue's avatar Yoshifumi Inoue Committed by Commit Bot

Introduce CompositeEditCommand::RemoveAllChildrenIfPossible()

This patch Introduces |CompositeEditCommand::RemoveAllChildrenIfPossible()|
to avoid infinite root in |TypingCommand| and |DeleteSelectionCommand|.

This patch is a continuation of the CL[1].

Note: no regression test as there's no minimized test case in the original
report, and it's not worth the minimization because the bug is a rather
edge case that requires an editable <style> element that specifies editable
style on its parent using deprecated '-webkit-user-modify'.

[1] http://crrev.com/c/1567098 [Editing] Abort TypingCommand when RemoveNode()
fails to remove a node

Bug: 949501
Change-Id: I9bd19da22f54cd7cbda735103c599a5082f8d94f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1573434
Auto-Submit: Yoshifumi Inoue <yosin@chromium.org>
Reviewed-by: default avatarXiaocheng Hu <xiaochengh@chromium.org>
Commit-Queue: Yoshifumi Inoue <yosin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#652465}
parent a55917cb
......@@ -373,6 +373,25 @@ void CompositeEditCommand::AppendNode(Node* node,
editing_state);
}
void CompositeEditCommand::RemoveAllChildrenIfPossible(
ContainerNode* container,
EditingState* editing_state,
ShouldAssumeContentIsAlwaysEditable
should_assume_content_is_always_editable) {
Node* child = container->firstChild();
while (child) {
Node* const next = child->nextSibling();
RemoveNode(child, editing_state, should_assume_content_is_always_editable);
if (editing_state->IsAborted())
return;
if (next && next->parentNode() != container) {
// |RemoveNode()| moves |next| outside |node|.
return;
}
child = next;
}
}
void CompositeEditCommand::RemoveChildrenInRange(Node* node,
unsigned from,
unsigned to,
......
......@@ -130,6 +130,11 @@ class CORE_EXPORT CompositeEditCommand : public EditCommand {
bool CanRebalance(const Position&) const;
void RemoveCSSProperty(Element*, CSSPropertyID);
void RemoveElementAttribute(Element*, const QualifiedName& attribute);
// Remove all children if possible
void RemoveAllChildrenIfPossible(ContainerNode*,
EditingState*,
ShouldAssumeContentIsAlwaysEditable =
kDoNotAssumeContentIsAlwaysEditable);
void RemoveChildrenInRange(Node*, unsigned from, unsigned to, EditingState*);
virtual void RemoveNode(Node*,
EditingState*,
......
......@@ -479,21 +479,10 @@ void DeleteSelectionCommand::RemoveNode(
if (!node->hasChildren())
return;
// Search this non-editable region for editable regions to empty.
Node* child = node->firstChild();
while (child) {
Node* next_child = child->nextSibling();
RemoveNode(child, editing_state,
should_assume_content_is_always_editable);
if (editing_state->IsAborted())
return;
// Bail if nextChild is no longer node's child.
if (next_child && next_child->parentNode() != node)
return;
child = next_child;
}
// Don't remove editable regions that are inside non-editable ones, just
// clear them.
RemoveAllChildrenIfPossible(ToContainerNode(node), editing_state,
should_assume_content_is_always_editable);
return;
}
}
......@@ -501,15 +490,10 @@ void DeleteSelectionCommand::RemoveNode(
if (IsTableStructureNode(node) || IsRootEditableElement(*node)) {
// Do not remove an element of table structure; remove its contents.
// Likewise for the root editable element.
Node* child = node->firstChild();
while (child) {
Node* remove = child;
child = child->nextSibling();
RemoveNode(remove, editing_state,
should_assume_content_is_always_editable);
if (editing_state->IsAborted())
return;
}
RemoveAllChildrenIfPossible(ToContainerNode(node), editing_state,
should_assume_content_is_always_editable);
if (editing_state->IsAborted())
return;
// Make sure empty cell has some height, if a placeholder can be inserted.
GetDocument().UpdateStyleAndLayout();
......
......@@ -737,11 +737,9 @@ bool TypingCommand::MakeEditableRootEmpty(EditingState* editing_state) {
}
}
while (Node* child = root->firstChild()) {
RemoveNode(child, editing_state);
if (editing_state->IsAborted())
return false;
}
RemoveAllChildrenIfPossible(root, editing_state);
if (editing_state->IsAborted() || root->firstChild())
return false;
AddBlockPlaceholderIfNeeded(root, editing_state);
if (editing_state->IsAborted())
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment