OLD | NEW |
---|---|
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 30 matching lines...) Expand all Loading... | |
41 #include "core/editing/FrameSelection.h" | 41 #include "core/editing/FrameSelection.h" |
42 #include "core/editing/HTMLInterchange.h" | 42 #include "core/editing/HTMLInterchange.h" |
43 #include "core/editing/SimplifyMarkupCommand.h" | 43 #include "core/editing/SimplifyMarkupCommand.h" |
44 #include "core/editing/SmartReplace.h" | 44 #include "core/editing/SmartReplace.h" |
45 #include "core/editing/TextIterator.h" | 45 #include "core/editing/TextIterator.h" |
46 #include "core/editing/VisibleUnits.h" | 46 #include "core/editing/VisibleUnits.h" |
47 #include "core/editing/htmlediting.h" | 47 #include "core/editing/htmlediting.h" |
48 #include "core/editing/markup.h" | 48 #include "core/editing/markup.h" |
49 #include "core/events/BeforeTextInsertedEvent.h" | 49 #include "core/events/BeforeTextInsertedEvent.h" |
50 #include "core/frame/LocalFrame.h" | 50 #include "core/frame/LocalFrame.h" |
51 #include "core/frame/UseCounter.h" | |
51 #include "core/html/HTMLElement.h" | 52 #include "core/html/HTMLElement.h" |
52 #include "core/html/HTMLInputElement.h" | 53 #include "core/html/HTMLInputElement.h" |
53 #include "core/rendering/RenderObject.h" | 54 #include "core/rendering/RenderObject.h" |
54 #include "core/rendering/RenderText.h" | 55 #include "core/rendering/RenderText.h" |
55 #include "wtf/StdLibExtras.h" | 56 #include "wtf/StdLibExtras.h" |
56 #include "wtf/Vector.h" | 57 #include "wtf/Vector.h" |
57 | 58 |
58 namespace WebCore { | 59 namespace WebCore { |
59 | 60 |
60 using namespace HTMLNames; | 61 using namespace HTMLNames; |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
282 void ReplacementFragment::removeInterchangeNodes(Node* container) | 283 void ReplacementFragment::removeInterchangeNodes(Node* container) |
283 { | 284 { |
284 m_hasInterchangeNewlineAtStart = false; | 285 m_hasInterchangeNewlineAtStart = false; |
285 m_hasInterchangeNewlineAtEnd = false; | 286 m_hasInterchangeNewlineAtEnd = false; |
286 | 287 |
287 // Interchange newlines at the "start" of the incoming fragment must be | 288 // Interchange newlines at the "start" of the incoming fragment must be |
288 // either the first node in the fragment or the first leaf in the fragment. | 289 // either the first node in the fragment or the first leaf in the fragment. |
289 Node* node = container->firstChild(); | 290 Node* node = container->firstChild(); |
290 while (node) { | 291 while (node) { |
291 if (isInterchangeNewlineNode(node)) { | 292 if (isInterchangeNewlineNode(node)) { |
293 UseCounter::count(node->document(), UseCounter::EditingAppleIntercha ngeNewline); | |
Yuta Kitamura
2014/06/12 07:55:23
You add some count() calls in predicate functions
yosin_UTC9
2014/06/12 08:46:06
You're right. I move count() call to predicate.
| |
292 m_hasInterchangeNewlineAtStart = true; | 294 m_hasInterchangeNewlineAtStart = true; |
293 removeNode(node); | 295 removeNode(node); |
294 break; | 296 break; |
295 } | 297 } |
296 node = node->firstChild(); | 298 node = node->firstChild(); |
297 } | 299 } |
298 if (!container->hasChildren()) | 300 if (!container->hasChildren()) |
299 return; | 301 return; |
300 // Interchange newlines at the "end" of the incoming fragment must be | 302 // Interchange newlines at the "end" of the incoming fragment must be |
301 // either the last node in the fragment or the last leaf in the fragment. | 303 // either the last node in the fragment or the last leaf in the fragment. |
302 node = container->lastChild(); | 304 node = container->lastChild(); |
303 while (node) { | 305 while (node) { |
304 if (isInterchangeNewlineNode(node)) { | 306 if (isInterchangeNewlineNode(node)) { |
307 UseCounter::count(node->document(), UseCounter::EditingAppleIntercha ngeNewline); | |
305 m_hasInterchangeNewlineAtEnd = true; | 308 m_hasInterchangeNewlineAtEnd = true; |
306 removeNode(node); | 309 removeNode(node); |
307 break; | 310 break; |
308 } | 311 } |
309 node = node->lastChild(); | 312 node = node->lastChild(); |
310 } | 313 } |
311 | 314 |
312 node = container->firstChild(); | 315 node = container->firstChild(); |
313 while (node) { | 316 while (node) { |
314 RefPtrWillBeRawPtr<Node> next = NodeTraversal::next(*node); | 317 RefPtrWillBeRawPtr<Node> next = NodeTraversal::next(*node); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
411 return false; | 414 return false; |
412 | 415 |
413 return !selectionEndWasEndOfParagraph | 416 return !selectionEndWasEndOfParagraph |
414 && isEndOfParagraph(endOfInsertedContent) | 417 && isEndOfParagraph(endOfInsertedContent) |
415 && !isHTMLBRElement(*endOfInsertedContent.deepEquivalent().deprecatedNod e()) | 418 && !isHTMLBRElement(*endOfInsertedContent.deepEquivalent().deprecatedNod e()) |
416 && shouldMerge(endOfInsertedContent, next); | 419 && shouldMerge(endOfInsertedContent, next); |
417 } | 420 } |
418 | 421 |
419 static bool isMailPasteAsQuotationNode(const Node* node) | 422 static bool isMailPasteAsQuotationNode(const Node* node) |
420 { | 423 { |
421 return node && node->hasTagName(blockquoteTag) && toElement(node)->getAttrib ute(classAttr) == ApplePasteAsQuotation; | 424 if (!node || !node->hasTagName(blockquoteTag) || toElement(node)->getAttribu te(classAttr) != ApplePasteAsQuotation) |
425 return false; | |
426 UseCounter::count(node->document(), UseCounter::EditingApplePasteAsQuotation ); | |
427 return true; | |
422 } | 428 } |
423 | 429 |
424 static bool isHeaderElement(const Node* a) | 430 static bool isHeaderElement(const Node* a) |
425 { | 431 { |
426 if (!a) | 432 if (!a) |
427 return false; | 433 return false; |
428 | 434 |
429 return a->hasTagName(h1Tag) | 435 return a->hasTagName(h1Tag) |
430 || a->hasTagName(h2Tag) | 436 || a->hasTagName(h2Tag) |
431 || a->hasTagName(h3Tag) | 437 || a->hasTagName(h3Tag) |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
525 removeNodePreservingChildren(element); | 531 removeNodePreservingChildren(element); |
526 continue; | 532 continue; |
527 } | 533 } |
528 | 534 |
529 if (element->parentNode() && element->parentNode()->rendererIsRichlyEdit able()) | 535 if (element->parentNode() && element->parentNode()->rendererIsRichlyEdit able()) |
530 removeNodeAttribute(element, contenteditableAttr); | 536 removeNodeAttribute(element, contenteditableAttr); |
531 | 537 |
532 // WebKit used to not add display: inline and float: none on copy. | 538 // WebKit used to not add display: inline and float: none on copy. |
533 // Keep this code around for backward compatibility | 539 // Keep this code around for backward compatibility |
534 if (isLegacyAppleStyleSpan(element)) { | 540 if (isLegacyAppleStyleSpan(element)) { |
541 UseCounter::count(document(), UseCounter::EditingAppleStyleSpanClass ); | |
535 if (!element->firstChild()) { | 542 if (!element->firstChild()) { |
536 insertedNodes.willRemoveNodePreservingChildren(*element); | 543 insertedNodes.willRemoveNodePreservingChildren(*element); |
537 removeNodePreservingChildren(element); | 544 removeNodePreservingChildren(element); |
538 continue; | 545 continue; |
539 } | 546 } |
540 // There are other styles that style rules can give to style spans, | 547 // There are other styles that style rules can give to style spans, |
541 // but these are the two important ones because they'll prevent | 548 // but these are the two important ones because they'll prevent |
542 // inserted content from appearing in the right paragraph. | 549 // inserted content from appearing in the right paragraph. |
543 // FIXME: Hyatt is concerned that selectively using display:inline w ill give inconsistent | 550 // FIXME: Hyatt is concerned that selectively using display:inline w ill give inconsistent |
544 // results. We already know one issue because td elements ignore the ir display property | 551 // results. We already know one issue because td elements ignore the ir display property |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
721 // Handling the case where we are doing Paste as Quotation or pasting into q uoted content is more complicated (see handleStyleSpans) | 728 // Handling the case where we are doing Paste as Quotation or pasting into q uoted content is more complicated (see handleStyleSpans) |
722 // and doesn't receive the optimization. | 729 // and doesn't receive the optimization. |
723 if (isMailPasteAsQuotationNode(topNode) || enclosingNodeOfType(firstPosition InOrBeforeNode(topNode), isMailBlockquote, CanCrossEditingBoundary)) | 730 if (isMailPasteAsQuotationNode(topNode) || enclosingNodeOfType(firstPosition InOrBeforeNode(topNode), isMailBlockquote, CanCrossEditingBoundary)) |
724 return false; | 731 return false; |
725 | 732 |
726 // Either there are no style spans in the fragment or a WebKit client has ad ded content to the fragment | 733 // Either there are no style spans in the fragment or a WebKit client has ad ded content to the fragment |
727 // before inserting it. Look for and handle style spans after insertion. | 734 // before inserting it. Look for and handle style spans after insertion. |
728 if (!isLegacyAppleStyleSpan(topNode)) | 735 if (!isLegacyAppleStyleSpan(topNode)) |
729 return false; | 736 return false; |
730 | 737 |
738 UseCounter::count(topNode->document(), UseCounter::EditingAppleStyleSpanClas s); | |
731 Node* wrappingStyleSpan = topNode; | 739 Node* wrappingStyleSpan = topNode; |
732 RefPtrWillBeRawPtr<EditingStyle> styleAtInsertionPos = EditingStyle::create( insertionPos.parentAnchoredEquivalent()); | 740 RefPtrWillBeRawPtr<EditingStyle> styleAtInsertionPos = EditingStyle::create( insertionPos.parentAnchoredEquivalent()); |
733 String styleText = styleAtInsertionPos->style()->asText(); | 741 String styleText = styleAtInsertionPos->style()->asText(); |
734 | 742 |
735 // FIXME: This string comparison is a naive way of comparing two styles. | 743 // FIXME: This string comparison is a naive way of comparing two styles. |
736 // We should be taking the diff and check that the diff is empty. | 744 // We should be taking the diff and check that the diff is empty. |
737 if (styleText != toElement(wrappingStyleSpan)->getAttribute(styleAttr)) | 745 if (styleText != toElement(wrappingStyleSpan)->getAttribute(styleAttr)) |
738 return false; | 746 return false; |
739 | 747 |
740 fragment.removeNodePreservingChildren(wrappingStyleSpan); | 748 fragment.removeNodePreservingChildren(wrappingStyleSpan); |
741 return true; | 749 return true; |
742 } | 750 } |
743 | 751 |
744 // At copy time, WebKit wraps copied content in a span that contains the source document's | 752 // At copy time, WebKit wraps copied content in a span that contains the source document's |
745 // default styles. If the copied Range inherits any other styles from its ances tors, we put | 753 // default styles. If the copied Range inherits any other styles from its ances tors, we put |
746 // those styles on a second span. | 754 // those styles on a second span. |
747 // This function removes redundant styles from those spans, and removes the span s if all their | 755 // This function removes redundant styles from those spans, and removes the span s if all their |
748 // styles are redundant. | 756 // styles are redundant. |
749 // We should remove the Apple-style-span class when we're done, see <rdar://prob lem/5685600>. | 757 // We should remove the Apple-style-span class when we're done, see <rdar://prob lem/5685600>. |
750 // We should remove styles from spans that are overridden by all of their childr en, either here | 758 // We should remove styles from spans that are overridden by all of their childr en, either here |
751 // or at copy time. | 759 // or at copy time. |
752 void ReplaceSelectionCommand::handleStyleSpans(InsertedNodes& insertedNodes) | 760 void ReplaceSelectionCommand::handleStyleSpans(InsertedNodes& insertedNodes) |
753 { | 761 { |
754 HTMLElement* wrappingStyleSpan = 0; | 762 HTMLElement* wrappingStyleSpan = 0; |
755 // The style span that contains the source document's default style should b e at | 763 // The style span that contains the source document's default style should b e at |
756 // the top of the fragment, but Mail sometimes adds a wrapper (for Paste As Quotation), | 764 // the top of the fragment, but Mail sometimes adds a wrapper (for Paste As Quotation), |
757 // so search for the top level style span instead of assuming it's at the to p. | 765 // so search for the top level style span instead of assuming it's at the to p. |
758 for (Node* node = insertedNodes.firstNodeInserted(); node; node = NodeTraver sal::next(*node)) { | 766 for (Node* node = insertedNodes.firstNodeInserted(); node; node = NodeTraver sal::next(*node)) { |
759 if (isLegacyAppleStyleSpan(node)) { | 767 if (isLegacyAppleStyleSpan(node)) { |
768 UseCounter::count(document(), UseCounter::EditingAppleStyleSpanClass ); | |
760 wrappingStyleSpan = toHTMLElement(node); | 769 wrappingStyleSpan = toHTMLElement(node); |
761 break; | 770 break; |
762 } | 771 } |
763 } | 772 } |
764 | 773 |
765 // There might not be any style spans if we're pasting from another applicat ion or if | 774 // There might not be any style spans if we're pasting from another applicat ion or if |
766 // we are here because of a document.execCommand("InsertHTML", ...) call. | 775 // we are here because of a document.execCommand("InsertHTML", ...) call. |
767 if (!wrappingStyleSpan) | 776 if (!wrappingStyleSpan) |
768 return; | 777 return; |
769 | 778 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
859 if (isBlock(node)) | 868 if (isBlock(node)) |
860 return false; | 869 return false; |
861 | 870 |
862 if (!node->isHTMLElement()) | 871 if (!node->isHTMLElement()) |
863 return false; | 872 return false; |
864 | 873 |
865 // We can skip over elements whose class attribute is | 874 // We can skip over elements whose class attribute is |
866 // one of our internal classes. | 875 // one of our internal classes. |
867 const HTMLElement* element = toHTMLElement(node); | 876 const HTMLElement* element = toHTMLElement(node); |
868 const AtomicString& classAttributeValue = element->getAttribute(classAttr); | 877 const AtomicString& classAttributeValue = element->getAttribute(classAttr); |
869 if (classAttributeValue == AppleTabSpanClass | 878 if (classAttributeValue == AppleTabSpanClass) { |
870 || classAttributeValue == AppleConvertedSpace | 879 UseCounter::count(node->document(), UseCounter::EditingAppleTabSpanClass ); |
871 || classAttributeValue == ApplePasteAsQuotation) | |
872 return true; | 880 return true; |
881 } | |
882 if (classAttributeValue == AppleConvertedSpace) { | |
883 UseCounter::count(node->document(), UseCounter::EditingAppleConvertedSpa ce); | |
884 return true; | |
885 } | |
886 if (classAttributeValue == ApplePasteAsQuotation) { | |
887 UseCounter::count(node->document(), UseCounter::EditingApplePasteAsQuota tion); | |
888 return true; | |
889 } | |
873 | 890 |
874 return EditingStyle::elementIsStyledSpanOrHTMLEquivalent(element); | 891 return EditingStyle::elementIsStyledSpanOrHTMLEquivalent(element); |
875 } | 892 } |
876 | 893 |
877 inline Node* nodeToSplitToAvoidPastingIntoInlineNodesWithStyle(const Position& i nsertionPos) | 894 inline Node* nodeToSplitToAvoidPastingIntoInlineNodesWithStyle(const Position& i nsertionPos) |
878 { | 895 { |
879 Node* containgBlock = enclosingBlock(insertionPos.containerNode()); | 896 Node* containgBlock = enclosingBlock(insertionPos.containerNode()); |
880 return highestEnclosingNodeOfType(insertionPos, isInlineNodeWithStyle, Canno tCrossEditingBoundary, containgBlock); | 897 return highestEnclosingNodeOfType(insertionPos, isInlineNodeWithStyle, Canno tCrossEditingBoundary, containgBlock); |
881 } | 898 } |
882 | 899 |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1068 | 1085 |
1069 InsertedNodes insertedNodes; | 1086 InsertedNodes insertedNodes; |
1070 RefPtrWillBeRawPtr<Node> refNode = fragment.firstChild(); | 1087 RefPtrWillBeRawPtr<Node> refNode = fragment.firstChild(); |
1071 ASSERT(refNode); | 1088 ASSERT(refNode); |
1072 RefPtrWillBeRawPtr<Node> node = refNode->nextSibling(); | 1089 RefPtrWillBeRawPtr<Node> node = refNode->nextSibling(); |
1073 | 1090 |
1074 fragment.removeNode(refNode); | 1091 fragment.removeNode(refNode); |
1075 | 1092 |
1076 Node* blockStart = enclosingBlock(insertionPos.deprecatedNode()); | 1093 Node* blockStart = enclosingBlock(insertionPos.deprecatedNode()); |
1077 if ((isListElement(refNode.get()) || (isLegacyAppleStyleSpan(refNode.get()) && isListElement(refNode->firstChild()))) | 1094 if ((isListElement(refNode.get()) || (isLegacyAppleStyleSpan(refNode.get()) && isListElement(refNode->firstChild()))) |
1078 && blockStart && blockStart->renderer()->isListItem()) | 1095 && blockStart && blockStart->renderer()->isListItem()) { |
1096 if (isLegacyAppleStyleSpan(refNode.get())) | |
1097 UseCounter::count(document(), UseCounter::EditingAppleStyleSpanClass ); | |
1079 refNode = insertAsListItems(toHTMLElement(refNode), blockStart, insertio nPos, insertedNodes); | 1098 refNode = insertAsListItems(toHTMLElement(refNode), blockStart, insertio nPos, insertedNodes); |
1080 else { | 1099 } else { |
1081 insertNodeAt(refNode, insertionPos); | 1100 insertNodeAt(refNode, insertionPos); |
1082 insertedNodes.respondToNodeInsertion(*refNode); | 1101 insertedNodes.respondToNodeInsertion(*refNode); |
1083 } | 1102 } |
1084 | 1103 |
1085 // Mutation events (bug 22634) may have already removed the inserted content | 1104 // Mutation events (bug 22634) may have already removed the inserted content |
1086 if (!refNode->inDocument()) | 1105 if (!refNode->inDocument()) |
1087 return; | 1106 return; |
1088 | 1107 |
1089 bool plainTextFragment = isPlainTextMarkup(refNode.get()); | 1108 bool plainTextFragment = isPlainTextMarkup(refNode.get()); |
1090 | 1109 |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1506 void ReplaceSelectionCommand::trace(Visitor* visitor) | 1525 void ReplaceSelectionCommand::trace(Visitor* visitor) |
1507 { | 1526 { |
1508 visitor->trace(m_startOfInsertedContent); | 1527 visitor->trace(m_startOfInsertedContent); |
1509 visitor->trace(m_endOfInsertedContent); | 1528 visitor->trace(m_endOfInsertedContent); |
1510 visitor->trace(m_insertionStyle); | 1529 visitor->trace(m_insertionStyle); |
1511 visitor->trace(m_documentFragment); | 1530 visitor->trace(m_documentFragment); |
1512 CompositeEditCommand::trace(visitor); | 1531 CompositeEditCommand::trace(visitor); |
1513 } | 1532 } |
1514 | 1533 |
1515 } // namespace WebCore | 1534 } // namespace WebCore |
OLD | NEW |