Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Side by Side Diff: third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp

Issue 2533703002: Don't refer to removed spans when reformulating pasted content. (Closed)
Patch Set: Address nit. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2009, 2010, 2011 Google Inc. All rights reserved. 3 * Copyright (C) 2009, 2010, 2011 Google Inc. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 399
400 inline void 400 inline void
401 ReplaceSelectionCommand::InsertedNodes::willRemoveNodePreservingChildren( 401 ReplaceSelectionCommand::InsertedNodes::willRemoveNodePreservingChildren(
402 Node& node) { 402 Node& node) {
403 if (m_firstNodeInserted.get() == node) 403 if (m_firstNodeInserted.get() == node)
404 m_firstNodeInserted = NodeTraversal::next(node); 404 m_firstNodeInserted = NodeTraversal::next(node);
405 if (m_lastNodeInserted.get() == node) 405 if (m_lastNodeInserted.get() == node)
406 m_lastNodeInserted = node.lastChild() 406 m_lastNodeInserted = node.lastChild()
407 ? node.lastChild() 407 ? node.lastChild()
408 : NodeTraversal::nextSkippingChildren(node); 408 : NodeTraversal::nextSkippingChildren(node);
409 if (m_refNode.get() == node)
410 m_refNode = NodeTraversal::next(node);
409 } 411 }
410 412
411 inline void ReplaceSelectionCommand::InsertedNodes::willRemoveNode(Node& node) { 413 inline void ReplaceSelectionCommand::InsertedNodes::willRemoveNode(Node& node) {
412 if (m_firstNodeInserted.get() == node && m_lastNodeInserted.get() == node) { 414 if (m_firstNodeInserted.get() == node && m_lastNodeInserted.get() == node) {
413 m_firstNodeInserted = nullptr; 415 m_firstNodeInserted = nullptr;
414 m_lastNodeInserted = nullptr; 416 m_lastNodeInserted = nullptr;
415 } else if (m_firstNodeInserted.get() == node) { 417 } else if (m_firstNodeInserted.get() == node) {
416 m_firstNodeInserted = 418 m_firstNodeInserted =
417 NodeTraversal::nextSkippingChildren(*m_firstNodeInserted); 419 NodeTraversal::nextSkippingChildren(*m_firstNodeInserted);
418 } else if (m_lastNodeInserted.get() == node) { 420 } else if (m_lastNodeInserted.get() == node) {
419 m_lastNodeInserted = 421 m_lastNodeInserted =
420 NodeTraversal::previousSkippingChildren(*m_lastNodeInserted); 422 NodeTraversal::previousSkippingChildren(*m_lastNodeInserted);
421 } 423 }
424 if (node.contains(m_refNode))
425 m_refNode = NodeTraversal::nextSkippingChildren(node);
422 } 426 }
423 427
424 inline void ReplaceSelectionCommand::InsertedNodes::didReplaceNode( 428 inline void ReplaceSelectionCommand::InsertedNodes::didReplaceNode(
425 Node& node, 429 Node& node,
426 Node& newNode) { 430 Node& newNode) {
427 if (m_firstNodeInserted.get() == node) 431 if (m_firstNodeInserted.get() == node)
428 m_firstNodeInserted = &newNode; 432 m_firstNodeInserted = &newNode;
429 if (m_lastNodeInserted.get() == node) 433 if (m_lastNodeInserted.get() == node)
430 m_lastNodeInserted = &newNode; 434 m_lastNodeInserted = &newNode;
435 if (m_refNode.get() == node)
436 m_refNode = &newNode;
431 } 437 }
432 438
433 ReplaceSelectionCommand::ReplaceSelectionCommand( 439 ReplaceSelectionCommand::ReplaceSelectionCommand(
434 Document& document, 440 Document& document,
435 DocumentFragment* fragment, 441 DocumentFragment* fragment,
436 CommandOptions options, 442 CommandOptions options,
437 InputEvent::InputType inputType) 443 InputEvent::InputType inputType)
438 : CompositeEditCommand(document), 444 : CompositeEditCommand(document),
439 m_selectReplacement(options & SelectReplacement), 445 m_selectReplacement(options & SelectReplacement),
440 m_smartReplace(options & SmartReplace), 446 m_smartReplace(options & SmartReplace),
(...skipping 964 matching lines...) Expand 10 before | Expand all | Expand 10 after
1405 // position being pasted into. 1411 // position being pasted into.
1406 // 4) Do one of the following: 1412 // 4) Do one of the following:
1407 // a) expand the last br if the fragment ends with one and it collapsed, 1413 // a) expand the last br if the fragment ends with one and it collapsed,
1408 // b) merge the last paragraph of the incoming fragment with the paragraph 1414 // b) merge the last paragraph of the incoming fragment with the paragraph
1409 // that contained the end of the selection that was pasted into, or 1415 // that contained the end of the selection that was pasted into, or
1410 // c) handle an interchange newline at the end of the incoming fragment. 1416 // c) handle an interchange newline at the end of the incoming fragment.
1411 // 5) Add spaces for smart replace. 1417 // 5) Add spaces for smart replace.
1412 // 6) Select the replacement if requested, and match style if requested. 1418 // 6) Select the replacement if requested, and match style if requested.
1413 1419
1414 InsertedNodes insertedNodes; 1420 InsertedNodes insertedNodes;
1415 Node* refNode = fragment.firstChild(); 1421 insertedNodes.setRefNode(fragment.firstChild());
1416 DCHECK(refNode); 1422 DCHECK(insertedNodes.refNode());
1417 Node* node = refNode->nextSibling(); 1423 Node* node = insertedNodes.refNode()->nextSibling();
1418 1424
1419 fragment.removeNode(refNode); 1425 fragment.removeNode(insertedNodes.refNode());
1420 1426
1421 Element* blockStart = enclosingBlock(insertionPos.anchorNode()); 1427 Element* blockStart = enclosingBlock(insertionPos.anchorNode());
1422 if ((isHTMLListElement(refNode) || 1428 if ((isHTMLListElement(insertedNodes.refNode()) ||
1423 (isLegacyAppleHTMLSpanElement(refNode) && 1429 (isLegacyAppleHTMLSpanElement(insertedNodes.refNode()) &&
1424 isHTMLListElement(refNode->firstChild()))) && 1430 isHTMLListElement(insertedNodes.refNode()->firstChild()))) &&
1425 blockStart && blockStart->layoutObject()->isListItem() && 1431 blockStart && blockStart->layoutObject()->isListItem() &&
1426 hasEditableStyle(*blockStart->parentNode())) { 1432 hasEditableStyle(*blockStart->parentNode())) {
1427 refNode = insertAsListItems(toHTMLElement(refNode), blockStart, 1433 insertedNodes.setRefNode(
1428 insertionPos, insertedNodes, editingState); 1434 insertAsListItems(toHTMLElement(insertedNodes.refNode()), blockStart,
1435 insertionPos, insertedNodes, editingState));
1429 if (editingState->isAborted()) 1436 if (editingState->isAborted())
1430 return; 1437 return;
1431 } else { 1438 } else {
1432 insertNodeAt(refNode, insertionPos, editingState); 1439 insertNodeAt(insertedNodes.refNode(), insertionPos, editingState);
1433 if (editingState->isAborted()) 1440 if (editingState->isAborted())
1434 return; 1441 return;
1435 insertedNodes.respondToNodeInsertion(*refNode); 1442 insertedNodes.respondToNodeInsertion(*insertedNodes.refNode());
1436 } 1443 }
1437 1444
1438 // Mutation events (bug 22634) may have already removed the inserted content 1445 // Mutation events (bug 22634) may have already removed the inserted content
1439 if (!refNode->isConnected()) 1446 if (!insertedNodes.refNode()->isConnected())
1440 return; 1447 return;
1441 1448
1442 bool plainTextFragment = isPlainTextMarkup(refNode); 1449 bool plainTextFragment = isPlainTextMarkup(insertedNodes.refNode());
1443 1450
1444 while (node) { 1451 while (node) {
1445 Node* next = node->nextSibling(); 1452 Node* next = node->nextSibling();
1446 fragment.removeNode(node); 1453 fragment.removeNode(node);
1447 insertNodeAfter(node, refNode, editingState); 1454 insertNodeAfter(node, insertedNodes.refNode(), editingState);
1448 if (editingState->isAborted()) 1455 if (editingState->isAborted())
1449 return; 1456 return;
1450 insertedNodes.respondToNodeInsertion(*node); 1457 insertedNodes.respondToNodeInsertion(*node);
1451 1458
1452 // Mutation events (bug 22634) may have already removed the inserted content 1459 // Mutation events (bug 22634) may have already removed the inserted content
1453 if (!node->isConnected()) 1460 if (!node->isConnected())
1454 return; 1461 return;
1455 1462
1456 refNode = node; 1463 insertedNodes.setRefNode(node);
1457 if (node && plainTextFragment) 1464 if (node && plainTextFragment)
1458 plainTextFragment = isPlainTextMarkup(node); 1465 plainTextFragment = isPlainTextMarkup(node);
1459 node = next; 1466 node = next;
1460 } 1467 }
1461 1468
1462 if (isRichlyEditablePosition(insertionPos)) 1469 if (isRichlyEditablePosition(insertionPos))
1463 removeUnrenderedTextNodesAtEnds(insertedNodes); 1470 removeUnrenderedTextNodesAtEnds(insertedNodes);
1464 1471
1465 if (!handledStyleSpans) { 1472 if (!handledStyleSpans) {
1466 handleStyleSpans(insertedNodes, editingState); 1473 handleStyleSpans(insertedNodes, editingState);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1516 if (editingState->isAborted()) 1523 if (editingState->isAborted())
1517 return; 1524 return;
1518 } 1525 }
1519 } 1526 }
1520 1527
1521 makeInsertedContentRoundTrippableWithHTMLTreeBuilder(insertedNodes, 1528 makeInsertedContentRoundTrippableWithHTMLTreeBuilder(insertedNodes,
1522 editingState); 1529 editingState);
1523 if (editingState->isAborted()) 1530 if (editingState->isAborted())
1524 return; 1531 return;
1525 1532
1526 removeRedundantStylesAndKeepStyleSpanInline(insertedNodes, editingState); 1533 {
1527 if (editingState->isAborted()) 1534 // TODO(dominicc): refNode may not be connected, for example in
1528 return; 1535 // LayoutTests/editing/inserting/insert-table-in-paragraph-crash.html .
1536 // Refactor this so there's a relationship between the conditions
1537 // where refNode is dereferenced and refNode is connected.
1538 bool refNodeWasConnected = insertedNodes.refNode()->isConnected();
1539 removeRedundantStylesAndKeepStyleSpanInline(insertedNodes, editingState);
1540 if (editingState->isAborted())
1541 return;
1542 DCHECK_EQ(insertedNodes.refNode()->isConnected(), refNodeWasConnected)
1543 << insertedNodes.refNode();
1544 }
1529 1545
1530 if (m_sanitizeFragment && insertedNodes.firstNodeInserted()) { 1546 if (m_sanitizeFragment && insertedNodes.firstNodeInserted()) {
1531 applyCommandToComposite(SimplifyMarkupCommand::create( 1547 applyCommandToComposite(SimplifyMarkupCommand::create(
1532 document(), insertedNodes.firstNodeInserted(), 1548 document(), insertedNodes.firstNodeInserted(),
1533 insertedNodes.pastLastLeaf()), 1549 insertedNodes.pastLastLeaf()),
1534 editingState); 1550 editingState);
1535 if (editingState->isAborted()) 1551 if (editingState->isAborted())
1536 return; 1552 return;
1537 } 1553 }
1538 1554
(...skipping 23 matching lines...) Expand all
1562 1578
1563 // We need to handle the case where we need to merge the end 1579 // We need to handle the case where we need to merge the end
1564 // but our destination node is inside an inline that is the last in the 1580 // but our destination node is inside an inline that is the last in the
1565 // block. 1581 // block.
1566 // We insert a placeholder before the newly inserted content to avoid being 1582 // We insert a placeholder before the newly inserted content to avoid being
1567 // merged into the inline. 1583 // merged into the inline.
1568 Node* destinationNode = destination.deepEquivalent().anchorNode(); 1584 Node* destinationNode = destination.deepEquivalent().anchorNode();
1569 if (m_shouldMergeEnd && 1585 if (m_shouldMergeEnd &&
1570 destinationNode != enclosingInline(destinationNode) && 1586 destinationNode != enclosingInline(destinationNode) &&
1571 enclosingInline(destinationNode)->nextSibling()) { 1587 enclosingInline(destinationNode)->nextSibling()) {
1572 insertNodeBefore(HTMLBRElement::create(document()), refNode, 1588 insertNodeBefore(HTMLBRElement::create(document()),
1573 editingState); 1589 insertedNodes.refNode(), editingState);
1574 if (editingState->isAborted()) 1590 if (editingState->isAborted())
1575 return; 1591 return;
1576 } 1592 }
1577 1593
1578 // Merging the the first paragraph of inserted content with the content that 1594 // Merging the the first paragraph of inserted content with the content that
1579 // came before the selection that was pasted into would also move content 1595 // came before the selection that was pasted into would also move content
1580 // after the selection that was pasted into if: only one paragraph was being 1596 // after the selection that was pasted into if: only one paragraph was being
1581 // pasted, and it was not wrapped in a block, the selection that was pasted 1597 // pasted, and it was not wrapped in a block, the selection that was pasted
1582 // into ended at the end of a block and the next paragraph didn't start at 1598 // into ended at the end of a block and the next paragraph didn't start at
1583 // the start of a block. 1599 // the start of a block.
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after
2114 visitor->trace(m_startOfInsertedContent); 2130 visitor->trace(m_startOfInsertedContent);
2115 visitor->trace(m_endOfInsertedContent); 2131 visitor->trace(m_endOfInsertedContent);
2116 visitor->trace(m_insertionStyle); 2132 visitor->trace(m_insertionStyle);
2117 visitor->trace(m_documentFragment); 2133 visitor->trace(m_documentFragment);
2118 visitor->trace(m_startOfInsertedRange); 2134 visitor->trace(m_startOfInsertedRange);
2119 visitor->trace(m_endOfInsertedRange); 2135 visitor->trace(m_endOfInsertedRange);
2120 CompositeEditCommand::trace(visitor); 2136 CompositeEditCommand::trace(visitor);
2121 } 2137 }
2122 2138
2123 } // namespace blink 2139 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698