diff options
8 files changed, 45 insertions, 23 deletions
diff --git a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp index 875db7a..9d9f8b5 100644 --- a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp @@ -398,11 +398,12 @@ void CompositeEditCommand::removeChildrenInRange(PassRefPtrWillBeRawPtr<Node> no removeNode(children[i].release()); } -void CompositeEditCommand::removeNode(PassRefPtrWillBeRawPtr<Node> node, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) +void CompositeEditCommand::removeNode(PassRefPtrWillBeRawPtr<Node> node, EditingState* editingState, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) { if (!node || !node->nonShadowBoundaryParentNode()) return; - applyCommandToComposite(RemoveNodeCommand::create(node, shouldAssumeContentIsAlwaysEditable)); + ASSERT_IN_EDITING_COMMAND(node->document().frame()); + applyCommandToComposite(RemoveNodeCommand::create(node, shouldAssumeContentIsAlwaysEditable), editingState); } void CompositeEditCommand::removeNodePreservingChildren(PassRefPtrWillBeRawPtr<Node> node, EditingState* editingState, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) diff --git a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.h b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.h index 3d97058..1a2a929 100644 --- a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.h +++ b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.h @@ -125,7 +125,7 @@ protected: void removeCSSProperty(PassRefPtrWillBeRawPtr<Element>, CSSPropertyID); void removeElementAttribute(PassRefPtrWillBeRawPtr<Element>, const QualifiedName& attribute); void removeChildrenInRange(PassRefPtrWillBeRawPtr<Node>, unsigned from, unsigned to); - virtual void removeNode(PassRefPtrWillBeRawPtr<Node>, ShouldAssumeContentIsAlwaysEditable = DoNotAssumeContentIsAlwaysEditable); + virtual void removeNode(PassRefPtrWillBeRawPtr<Node>, EditingState* = ASSERT_NO_EDITING_ABORT, ShouldAssumeContentIsAlwaysEditable = DoNotAssumeContentIsAlwaysEditable); HTMLSpanElement* replaceElementWithSpanPreservingChildrenAndAttributes(PassRefPtrWillBeRawPtr<HTMLElement>); void removeNodePreservingChildren(PassRefPtrWillBeRawPtr<Node>, EditingState* = ASSERT_NO_EDITING_ABORT, ShouldAssumeContentIsAlwaysEditable = DoNotAssumeContentIsAlwaysEditable); void removeNodeAndPruneAncestors(PassRefPtrWillBeRawPtr<Node>, Node* excludeNode = nullptr); diff --git a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp index a62632f..cd8700f 100644 --- a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp @@ -338,7 +338,7 @@ static Position firstEditablePositionInNode(Node* node) return next ? firstPositionInOrBeforeNode(next) : Position(); } -void DeleteSelectionCommand::removeNode(PassRefPtrWillBeRawPtr<Node> node, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) +void DeleteSelectionCommand::removeNode(PassRefPtrWillBeRawPtr<Node> node, EditingState* editingState, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) { if (!node) return; @@ -353,7 +353,9 @@ void DeleteSelectionCommand::removeNode(PassRefPtrWillBeRawPtr<Node> node, Shoul RefPtrWillBeRawPtr<Node> child = node->firstChild(); while (child) { RefPtrWillBeRawPtr<Node> nextChild = child->nextSibling(); - removeNode(child.get(), shouldAssumeContentIsAlwaysEditable); + removeNode(child.get(), editingState, shouldAssumeContentIsAlwaysEditable); + if (editingState->isAborted()) + return; // Bail if nextChild is no longer node's child. if (nextChild && nextChild->parentNode() != node) return; @@ -372,7 +374,9 @@ void DeleteSelectionCommand::removeNode(PassRefPtrWillBeRawPtr<Node> node, Shoul while (child) { Node* remove = child; child = child->nextSibling(); - removeNode(remove, shouldAssumeContentIsAlwaysEditable); + removeNode(remove, editingState, shouldAssumeContentIsAlwaysEditable); + if (editingState->isAborted()) + return; } // Make sure empty cell has some height, if a placeholder can be inserted. @@ -402,7 +406,7 @@ void DeleteSelectionCommand::removeNode(PassRefPtrWillBeRawPtr<Node> node, Shoul updatePositionForNodeRemoval(m_leadingWhitespace, *node); updatePositionForNodeRemoval(m_trailingWhitespace, *node); - CompositeEditCommand::removeNode(node, shouldAssumeContentIsAlwaysEditable); + CompositeEditCommand::removeNode(node, editingState, shouldAssumeContentIsAlwaysEditable); } static void updatePositionForTextRemoval(Text* node, int offset, int count, Position& position) @@ -445,7 +449,7 @@ void DeleteSelectionCommand::makeStylingElementsDirectChildrenOfEditableRootToPr } } -void DeleteSelectionCommand::handleGeneralDelete() +void DeleteSelectionCommand::handleGeneralDelete(EditingState* editingState) { if (m_upstreamStart.isNull()) return; @@ -492,8 +496,11 @@ void DeleteSelectionCommand::handleGeneralDelete() } // The selection to delete is all in one node. - if (!startNode->layoutObject() || (!startOffset && m_downstreamEnd.atLastEditingPositionForNode())) - removeNode(startNode); + if (!startNode->layoutObject() || (!startOffset && m_downstreamEnd.atLastEditingPositionForNode())) { + removeNode(startNode, editingState); + if (editingState->isAborted()) + return; + } } else { bool startNodeWasDescendantOfEndNode = m_upstreamStart.anchorNode()->isDescendantOf(m_downstreamEnd.anchorNode()); // The selection to delete spans more than one node. @@ -523,12 +530,16 @@ void DeleteSelectionCommand::handleGeneralDelete() // if we just removed a node from the end container, update end position so the // check above will work updatePositionForNodeRemoval(m_downstreamEnd, *node); - removeNode(node.get()); + removeNode(node.get(), editingState); + if (editingState->isAborted()) + return; node = nextNode.get(); } else { Node& n = NodeTraversal::lastWithinOrSelf(*node); if (m_downstreamEnd.anchorNode() == n && m_downstreamEnd.computeEditingOffset() >= caretMaxOffset(&n)) { - removeNode(node.get()); + removeNode(node.get(), editingState); + if (editingState->isAborted()) + return; node = nullptr; } else { node = NodeTraversal::next(*node); @@ -539,7 +550,7 @@ void DeleteSelectionCommand::handleGeneralDelete() if (m_downstreamEnd.anchorNode() != startNode && !m_upstreamStart.anchorNode()->isDescendantOf(m_downstreamEnd.anchorNode()) && m_downstreamEnd.inDocument() && m_downstreamEnd.computeEditingOffset() >= caretMinOffset(m_downstreamEnd.anchorNode())) { if (m_downstreamEnd.atLastEditingPositionForNode() && !canHaveChildrenForEditing(m_downstreamEnd.anchorNode())) { // The node itself is fully selected, not just its contents. Delete it. - removeNode(m_downstreamEnd.anchorNode()); + removeNode(m_downstreamEnd.anchorNode(), editingState); } else { if (m_downstreamEnd.anchorNode()->isTextNode()) { // in a text node that needs to be trimmed @@ -839,7 +850,9 @@ void DeleteSelectionCommand::doApply(EditingState* editingState) return; } - handleGeneralDelete(); + handleGeneralDelete(editingState); + if (editingState->isAborted()) + return; fixupWhitespace(); diff --git a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.h b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.h index 8bd90bb..6e8ea714 100644 --- a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.h +++ b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.h @@ -60,14 +60,14 @@ private: void initializePositionData(); void saveTypingStyleState(); bool handleSpecialCaseBRDelete(); - void handleGeneralDelete(); + void handleGeneralDelete(EditingState*); void fixupWhitespace(); void mergeParagraphs(); void removePreviouslySelectedEmptyTableRows(); void calculateTypingStyleAfterDelete(); void clearTransientState(); void makeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss(); - void removeNode(PassRefPtrWillBeRawPtr<Node>, ShouldAssumeContentIsAlwaysEditable = DoNotAssumeContentIsAlwaysEditable) override; + void removeNode(PassRefPtrWillBeRawPtr<Node>, EditingState* = ASSERT_NO_EDITING_ABORT, ShouldAssumeContentIsAlwaysEditable = DoNotAssumeContentIsAlwaysEditable) override; void deleteTextFromNode(PassRefPtrWillBeRawPtr<Text>, unsigned, unsigned) override; void removeRedundantBlocks(EditingState*); diff --git a/third_party/WebKit/Source/core/editing/commands/RemoveNodeCommand.cpp b/third_party/WebKit/Source/core/editing/commands/RemoveNodeCommand.cpp index a9b8ead..ddc352d 100644 --- a/third_party/WebKit/Source/core/editing/commands/RemoveNodeCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/RemoveNodeCommand.cpp @@ -27,6 +27,7 @@ #include "bindings/core/v8/ExceptionStatePlaceholder.h" #include "core/dom/Node.h" +#include "core/editing/commands/EditingState.h" #include "wtf/Assertions.h" namespace blink { @@ -40,7 +41,7 @@ RemoveNodeCommand::RemoveNodeCommand(PassRefPtrWillBeRawPtr<Node> node, ShouldAs ASSERT(m_node->parentNode()); } -void RemoveNodeCommand::doApply(EditingState*) +void RemoveNodeCommand::doApply(EditingState* editingState) { ContainerNode* parent = m_node->parentNode(); if (!parent || (m_shouldAssumeContentIsAlwaysEditable == DoNotAssumeContentIsAlwaysEditable @@ -52,6 +53,11 @@ void RemoveNodeCommand::doApply(EditingState*) m_refChild = m_node->nextSibling(); m_node->remove(IGNORE_EXCEPTION); + // Node::remove dispatch synchronous events such as IFRAME unload events, + // and event handlers may break the document. We check the document state + // here in order to prevent further processing in bad situation. + ASSERT_IN_EDITING_COMMAND(m_node->document().frame()); + ASSERT_IN_EDITING_COMMAND(m_node->document().documentElement()); } void RemoveNodeCommand::doUnapply() diff --git a/third_party/WebKit/Source/core/editing/commands/RemoveNodePreservingChildrenCommand.cpp b/third_party/WebKit/Source/core/editing/commands/RemoveNodePreservingChildrenCommand.cpp index 55fb5d7..4283ee6 100644 --- a/third_party/WebKit/Source/core/editing/commands/RemoveNodePreservingChildrenCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/RemoveNodePreservingChildrenCommand.cpp @@ -46,11 +46,11 @@ void RemoveNodePreservingChildrenCommand::doApply(EditingState*) for (auto& currentChild : children) { RefPtrWillBeRawPtr<Node> child = currentChild.release(); - removeNode(child, m_shouldAssumeContentIsAlwaysEditable); + removeNode(child, ASSERT_NO_EDITING_ABORT, m_shouldAssumeContentIsAlwaysEditable); insertNodeBefore(child.release(), m_node, m_shouldAssumeContentIsAlwaysEditable); } } - removeNode(m_node, m_shouldAssumeContentIsAlwaysEditable); + removeNode(m_node, ASSERT_NO_EDITING_ABORT, m_shouldAssumeContentIsAlwaysEditable); } DEFINE_TRACE(RemoveNodePreservingChildrenCommand) diff --git a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp index aa6415c..9cadc76 100644 --- a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp @@ -920,7 +920,7 @@ static inline HTMLElement* elementToSplitToAvoidPastingIntoInlineElementsWithSty return toHTMLElement(highestEnclosingNodeOfType(insertionPos, isInlineHTMLElementWithStyle, CannotCrossEditingBoundary, containingBlock)); } -void ReplaceSelectionCommand::doApply(EditingState*) +void ReplaceSelectionCommand::doApply(EditingState* editingState) { const VisibleSelection selection = endingSelection(); ASSERT(selection.isCaretOrRange()); @@ -974,7 +974,9 @@ void ReplaceSelectionCommand::doApply(EditingState*) bool mergeBlocksAfterDelete = startIsInsideMailBlockquote || isEndOfParagraph(visibleEnd) || isStartOfBlock(visibleStart); // FIXME: We should only expand to include fully selected special elements if we are copying a // selection and pasting it on top of itself. - deleteSelection(ASSERT_NO_EDITING_ABORT, false, mergeBlocksAfterDelete, false); + deleteSelection(editingState, false, mergeBlocksAfterDelete, false); + if (editingState->isAborted()) + return; if (fragment.hasInterchangeNewlineAtStart()) { VisiblePosition startAfterDelete = endingSelection().visibleStart(); if (isEndOfParagraph(startAfterDelete) && !isStartOfParagraph(startAfterDelete) && !isEndOfEditableOrNonEditableContent(startAfterDelete)) diff --git a/third_party/WebKit/Source/core/editing/commands/SimplifyMarkupCommand.cpp b/third_party/WebKit/Source/core/editing/commands/SimplifyMarkupCommand.cpp index e7edd8f..538e7e3 100644 --- a/third_party/WebKit/Source/core/editing/commands/SimplifyMarkupCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/SimplifyMarkupCommand.cpp @@ -113,9 +113,9 @@ int SimplifyMarkupCommand::pruneSubsequentAncestorsToRemove(WillBeHeapVector<Ref if (pastLastNodeToRemove == startNodeIndex + 1) return 0; - removeNode(nodesToRemove[startNodeIndex], AssumeContentIsAlwaysEditable); + removeNode(nodesToRemove[startNodeIndex], ASSERT_NO_EDITING_ABORT, AssumeContentIsAlwaysEditable); insertNodeBefore(nodesToRemove[startNodeIndex], highestAncestorToRemove, AssumeContentIsAlwaysEditable); - removeNode(highestAncestorToRemove, AssumeContentIsAlwaysEditable); + removeNode(highestAncestorToRemove, ASSERT_NO_EDITING_ABORT, AssumeContentIsAlwaysEditable); return pastLastNodeToRemove - startNodeIndex - 1; } |