summaryrefslogtreecommitdiff
path: root/chromium/third_party/WebKit/Source/core/editing/CompositeEditCommand.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/editing/CompositeEditCommand.cpp')
-rw-r--r--chromium/third_party/WebKit/Source/core/editing/CompositeEditCommand.cpp67
1 files changed, 51 insertions, 16 deletions
diff --git a/chromium/third_party/WebKit/Source/core/editing/CompositeEditCommand.cpp b/chromium/third_party/WebKit/Source/core/editing/CompositeEditCommand.cpp
index 5afcf1d48f9..24acf2d5182 100644
--- a/chromium/third_party/WebKit/Source/core/editing/CompositeEditCommand.cpp
+++ b/chromium/third_party/WebKit/Source/core/editing/CompositeEditCommand.cpp
@@ -33,7 +33,7 @@
#include "core/dom/DocumentMarkerController.h"
#include "core/dom/NodeTraversal.h"
#include "core/dom/Range.h"
-#include "core/dom/ScopedEventQueue.h"
+#include "core/events/ScopedEventQueue.h"
#include "core/dom/Text.h"
#include "core/editing/AppendNodeCommand.h"
#include "core/editing/ApplyStyleCommand.h"
@@ -45,12 +45,14 @@
#include "core/editing/InsertNodeBeforeCommand.h"
#include "core/editing/InsertParagraphSeparatorCommand.h"
#include "core/editing/MergeIdenticalElementsCommand.h"
+#include "core/editing/PlainTextRange.h"
#include "core/editing/RemoveCSSPropertyCommand.h"
#include "core/editing/RemoveNodeCommand.h"
#include "core/editing/RemoveNodePreservingChildrenCommand.h"
#include "core/editing/ReplaceNodeWithSpanCommand.h"
#include "core/editing/ReplaceSelectionCommand.h"
#include "core/editing/SetNodeAttributeCommand.h"
+#include "core/editing/SpellChecker.h"
#include "core/editing/SplitElementCommand.h"
#include "core/editing/SplitTextNodeCommand.h"
#include "core/editing/SplitTextNodeContainingElementCommand.h"
@@ -60,7 +62,7 @@
#include "core/editing/htmlediting.h"
#include "core/editing/markup.h"
#include "core/html/HTMLElement.h"
-#include "core/page/Frame.h"
+#include "core/frame/Frame.h"
#include "core/rendering/InlineTextBox.h"
#include "core/rendering/RenderBlock.h"
#include "core/rendering/RenderText.h"
@@ -71,6 +73,24 @@ namespace WebCore {
using namespace HTMLNames;
+namespace {
+class ReentrancyGuard {
+public:
+ static bool isRecursiveCall() { return s_nestingCounter; }
+
+ class Scope {
+ public:
+ Scope() { ++s_nestingCounter; }
+ ~Scope() { --s_nestingCounter; }
+ };
+ friend class Scope;
+
+private:
+ static int s_nestingCounter;
+};
+int ReentrancyGuard::s_nestingCounter;
+}
+
PassRefPtr<EditCommandComposition> EditCommandComposition::create(Document* document,
const VisibleSelection& startingSelection, const VisibleSelection& endingSelection, EditAction editAction)
{
@@ -87,6 +107,12 @@ EditCommandComposition::EditCommandComposition(Document* document, const Visible
{
}
+bool EditCommandComposition::belongsTo(const Frame& frame) const
+{
+ ASSERT(m_document);
+ return m_document->frame() == &frame;
+}
+
void EditCommandComposition::unapply()
{
ASSERT(m_document);
@@ -156,6 +182,14 @@ CompositeEditCommand::~CompositeEditCommand()
void CompositeEditCommand::apply()
{
+ // We don't allow recusrive |apply()| to protect against attack code.
+ // Recursive call of |apply()| could be happened by moving iframe
+ // with script triggered by insertion, e.g. <iframe src="javascript:...">
+ // <iframe onload="...">. This usage is valid as of the specification
+ // although, it isn't common use case, rather it is used as attack code.
+ if (ReentrancyGuard::isRecursiveCall())
+ return;
+
if (!endingSelection().isContentRichlyEditable()) {
switch (editingAction()) {
case EditActionTyping:
@@ -180,7 +214,8 @@ void CompositeEditCommand::apply()
Frame* frame = document().frame();
ASSERT(frame);
{
- EventQueueScope scope;
+ EventQueueScope eventQueueScope;
+ ReentrancyGuard::Scope reentrancyGuardScope;
doApply();
}
@@ -675,7 +710,7 @@ void CompositeEditCommand::prepareWhitespaceAtPositionForSplit(Position& positio
// Delete collapsed whitespace so that inserting nbsps doesn't uncollapse it.
Position upstreamPos = position.upstream();
- deleteInsignificantText(position.upstream(), position.downstream());
+ deleteInsignificantText(upstreamPos, position.downstream());
position = upstreamPos.downstream();
VisiblePosition visiblePos(position);
@@ -795,7 +830,7 @@ void CompositeEditCommand::deleteInsignificantText(const Position& start, const
return;
Vector<RefPtr<Text> > nodes;
- for (Node* node = start.deprecatedNode(); node; node = NodeTraversal::next(node)) {
+ for (Node* node = start.deprecatedNode(); node; node = NodeTraversal::next(*node)) {
if (node->isTextNode())
nodes.append(toText(node));
if (node == end.deprecatedNode())
@@ -979,7 +1014,7 @@ void CompositeEditCommand::cloneParagraphUnderNewElement(Position& start, Positi
appendNode(lastNode, blockElement);
}
- if (start.deprecatedNode() != outerNode && lastNode->isElementNode()) {
+ if (start.anchorNode() != outerNode && lastNode->isElementNode() && start.anchorNode()->isDescendantOf(outerNode.get())) {
Vector<RefPtr<Node> > ancestors;
// Insert each node from innerNode to outerNode (excluded) in a list.
@@ -991,7 +1026,7 @@ void CompositeEditCommand::cloneParagraphUnderNewElement(Position& start, Positi
for (size_t i = ancestors.size(); i != 0; --i) {
Node* item = ancestors[i - 1].get();
RefPtr<Node> child = item->cloneNode(isTableElement(item));
- appendNode(child, toElement(lastNode.get()));
+ appendNode(child, toElement(lastNode));
lastNode = child.release();
}
}
@@ -1013,7 +1048,7 @@ void CompositeEditCommand::cloneParagraphUnderNewElement(Position& start, Positi
}
RefPtr<Node> startNode = start.deprecatedNode();
- for (RefPtr<Node> node = NodeTraversal::nextSkippingChildren(startNode.get(), outerNode.get()); node; node = NodeTraversal::nextSkippingChildren(node.get(), outerNode.get())) {
+ for (RefPtr<Node> node = NodeTraversal::nextSkippingChildren(*startNode, outerNode.get()); node; node = NodeTraversal::nextSkippingChildren(*node, outerNode.get())) {
// Move lastNode up in the tree as much as node was moved up in the
// tree by NodeTraversal::nextSkippingChildren, so that the relative depth between
// node and the original start node is maintained in the clone.
@@ -1120,7 +1155,7 @@ void CompositeEditCommand::moveParagraphWithClones(const VisiblePosition& startO
beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent());
afterParagraph = VisiblePosition(afterParagraph.deepEquivalent());
- if (beforeParagraph.isNotNull() && !isTableElement(beforeParagraph.deepEquivalent().deprecatedNode())
+ if (beforeParagraph.isNotNull() && !isRenderedTable(beforeParagraph.deepEquivalent().deprecatedNode())
&& ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforeParagraph)) || beforeParagraph == afterParagraph)) {
// FIXME: Trim text between beforeParagraph and afterParagraph if they aren't equal.
insertNodeAt(createBreakElement(document()), beforeParagraph.deepEquivalent());
@@ -1200,7 +1235,7 @@ void CompositeEditCommand::moveParagraphs(const VisiblePosition& startOfParagrap
// FIXME (5098931): We should add a new insert action "WebViewInsertActionMoved" and call shouldInsertFragment here.
setEndingSelection(VisibleSelection(start, end, DOWNSTREAM));
- document().frame()->editor().clearMisspellingsAndBadGrammar(endingSelection());
+ document().frame()->spellChecker().clearMisspellingsAndBadGrammar(endingSelection());
deleteSelection(false, false, false, false);
ASSERT(destination.deepEquivalent().inDocument());
@@ -1233,7 +1268,7 @@ void CompositeEditCommand::moveParagraphs(const VisiblePosition& startOfParagrap
options |= ReplaceSelectionCommand::MatchStyle;
applyCommandToComposite(ReplaceSelectionCommand::create(document(), fragment, options));
- document().frame()->editor().markMisspellingsAndBadGrammar(endingSelection());
+ document().frame()->spellChecker().markMisspellingsAndBadGrammar(endingSelection());
// If the selection is in an empty paragraph, restore styles from the old empty paragraph to the new empty paragraph.
bool selectionIsEmptyParagraph = endingSelection().isCaret() && isStartOfParagraph(endingSelection().visibleStart()) && isEndOfParagraph(endingSelection().visibleStart());
@@ -1246,8 +1281,8 @@ void CompositeEditCommand::moveParagraphs(const VisiblePosition& startOfParagrap
// causes spaces to be collapsed during the move operation. This results
// in a call to rangeFromLocationAndLength with a location past the end
// of the document (which will return null).
- RefPtr<Range> start = TextIterator::rangeFromLocationAndLength(document().documentElement(), destinationIndex + startIndex, 0, true);
- RefPtr<Range> end = TextIterator::rangeFromLocationAndLength(document().documentElement(), destinationIndex + endIndex, 0, true);
+ RefPtr<Range> start = PlainTextRange(destinationIndex + startIndex).createRangeForSelection(*document().documentElement());
+ RefPtr<Range> end = PlainTextRange(destinationIndex + endIndex).createRangeForSelection(*document().documentElement());
if (start && end)
setEndingSelection(VisibleSelection(start->startPosition(), end->startPosition(), DOWNSTREAM, originalIsDirectional));
}
@@ -1291,12 +1326,12 @@ bool CompositeEditCommand::breakOutOfEmptyListItem()
if (!newBlock)
newBlock = createDefaultParagraphElement(document());
- RefPtr<Node> previousListNode = emptyListItem->isElementNode() ? toElement(emptyListItem.get())->previousElementSibling(): emptyListItem->previousSibling();
- RefPtr<Node> nextListNode = emptyListItem->isElementNode() ? toElement(emptyListItem.get())->nextElementSibling(): emptyListItem->nextSibling();
+ RefPtr<Node> previousListNode = emptyListItem->isElementNode() ? toElement(emptyListItem)->previousElementSibling(): emptyListItem->previousSibling();
+ RefPtr<Node> nextListNode = emptyListItem->isElementNode() ? toElement(emptyListItem)->nextElementSibling(): emptyListItem->nextSibling();
if (isListItem(nextListNode.get()) || isListElement(nextListNode.get())) {
// If emptyListItem follows another list item or nested list, split the list node.
if (isListItem(previousListNode.get()) || isListElement(previousListNode.get()))
- splitElement(toElement(listNode.get()), emptyListItem);
+ splitElement(toElement(listNode), emptyListItem);
// If emptyListItem is followed by other list item or nested list, then insert newBlock before the list node.
// Because we have splitted the element, emptyListItem is the first element in the list node.