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

Side by Side Diff: Source/core/editing/ReplaceSelectionCommand.cpp

Issue 327323005: Introduce use counters for Blink specific CSS classes for editing (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 6 years, 6 months 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
« no previous file with comments | « no previous file | Source/core/editing/htmlediting.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 30 matching lines...) Expand all
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | Source/core/editing/htmlediting.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698