| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv
      ed. | 2  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv
      ed. | 
| 3  * Copyright (C) 2008, 2009, 2010, 2011 Google Inc. All rights reserved. | 3  * Copyright (C) 2008, 2009, 2010, 2011 Google Inc. All rights reserved. | 
| 4  * Copyright (C) 2011 Igalia S.L. | 4  * Copyright (C) 2011 Igalia S.L. | 
| 5  * Copyright (C) 2011 Motorola Mobility. All rights reserved. | 5  * Copyright (C) 2011 Motorola Mobility. All rights reserved. | 
| 6  * | 6  * | 
| 7  * Redistribution and use in source and binary forms, with or without | 7  * Redistribution and use in source and binary forms, with or without | 
| 8  * modification, are permitted provided that the following conditions | 8  * modification, are permitted provided that the following conditions | 
| 9  * are met: | 9  * are met: | 
| 10  * 1. Redistributions of source code must retain the above copyright | 10  * 1. Redistributions of source code must retain the above copyright | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 31 | 31 | 
| 32 #include "bindings/core/v8/ExceptionState.h" | 32 #include "bindings/core/v8/ExceptionState.h" | 
| 33 #include "core/CSSPropertyNames.h" | 33 #include "core/CSSPropertyNames.h" | 
| 34 #include "core/CSSValueKeywords.h" | 34 #include "core/CSSValueKeywords.h" | 
| 35 #include "core/HTMLNames.h" | 35 #include "core/HTMLNames.h" | 
| 36 #include "core/css/CSSPrimitiveValue.h" | 36 #include "core/css/CSSPrimitiveValue.h" | 
| 37 #include "core/css/CSSValue.h" | 37 #include "core/css/CSSValue.h" | 
| 38 #include "core/css/StylePropertySet.h" | 38 #include "core/css/StylePropertySet.h" | 
| 39 #include "core/dom/CDATASection.h" | 39 #include "core/dom/CDATASection.h" | 
| 40 #include "core/dom/ChildListMutationScope.h" | 40 #include "core/dom/ChildListMutationScope.h" | 
|  | 41 #include "core/dom/Comment.h" | 
| 41 #include "core/dom/ContextFeatures.h" | 42 #include "core/dom/ContextFeatures.h" | 
| 42 #include "core/dom/DocumentFragment.h" | 43 #include "core/dom/DocumentFragment.h" | 
| 43 #include "core/dom/ElementTraversal.h" | 44 #include "core/dom/ElementTraversal.h" | 
| 44 #include "core/dom/ExceptionCode.h" | 45 #include "core/dom/ExceptionCode.h" | 
| 45 #include "core/dom/NodeTraversal.h" | 46 #include "core/dom/NodeTraversal.h" | 
| 46 #include "core/dom/Range.h" | 47 #include "core/dom/Range.h" | 
| 47 #include "core/editing/Editor.h" | 48 #include "core/editing/Editor.h" | 
| 48 #include "core/editing/MarkupAccumulator.h" | 49 #include "core/editing/MarkupAccumulator.h" | 
| 49 #include "core/editing/TextIterator.h" | 50 #include "core/editing/TextIterator.h" | 
| 50 #include "core/editing/VisibleSelection.h" | 51 #include "core/editing/VisibleSelection.h" | 
| 51 #include "core/editing/VisibleUnits.h" | 52 #include "core/editing/VisibleUnits.h" | 
| 52 #include "core/editing/htmlediting.h" | 53 #include "core/editing/htmlediting.h" | 
| 53 #include "core/frame/LocalFrame.h" | 54 #include "core/frame/LocalFrame.h" | 
|  | 55 #include "core/html/HTMLAnchorElement.h" | 
| 54 #include "core/html/HTMLBRElement.h" | 56 #include "core/html/HTMLBRElement.h" | 
| 55 #include "core/html/HTMLBodyElement.h" | 57 #include "core/html/HTMLBodyElement.h" | 
|  | 58 #include "core/html/HTMLDivElement.h" | 
| 56 #include "core/html/HTMLElement.h" | 59 #include "core/html/HTMLElement.h" | 
| 57 #include "core/html/HTMLQuoteElement.h" | 60 #include "core/html/HTMLQuoteElement.h" | 
| 58 #include "core/html/HTMLSpanElement.h" | 61 #include "core/html/HTMLSpanElement.h" | 
| 59 #include "core/html/HTMLTableCellElement.h" | 62 #include "core/html/HTMLTableCellElement.h" | 
|  | 63 #include "core/html/HTMLTableElement.h" | 
| 60 #include "core/html/HTMLTextFormControlElement.h" | 64 #include "core/html/HTMLTextFormControlElement.h" | 
| 61 #include "core/rendering/RenderObject.h" | 65 #include "core/rendering/RenderObject.h" | 
| 62 #include "platform/weborigin/KURL.h" | 66 #include "platform/weborigin/KURL.h" | 
| 63 #include "wtf/StdLibExtras.h" | 67 #include "wtf/StdLibExtras.h" | 
| 64 #include "wtf/text/StringBuilder.h" | 68 #include "wtf/text/StringBuilder.h" | 
| 65 | 69 | 
| 66 namespace blink { | 70 namespace blink { | 
| 67 | 71 | 
| 68 using namespace HTMLNames; | 72 using namespace HTMLNames; | 
| 69 | 73 | 
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 126         changes[i].apply(); | 130         changes[i].apply(); | 
| 127 } | 131 } | 
| 128 | 132 | 
| 129 class StyledMarkupAccumulator FINAL : public MarkupAccumulator { | 133 class StyledMarkupAccumulator FINAL : public MarkupAccumulator { | 
| 130 public: | 134 public: | 
| 131     enum RangeFullySelectsNode { DoesFullySelectNode, DoesNotFullySelectNode }; | 135     enum RangeFullySelectsNode { DoesFullySelectNode, DoesNotFullySelectNode }; | 
| 132 | 136 | 
| 133     StyledMarkupAccumulator(WillBeHeapVector<RawPtrWillBeMember<Node> >* nodes, 
      EAbsoluteURLs, EAnnotateForInterchange, RawPtr<const Range>, Node* highestNodeTo
      BeSerialized = 0); | 137     StyledMarkupAccumulator(WillBeHeapVector<RawPtrWillBeMember<Node> >* nodes, 
      EAbsoluteURLs, EAnnotateForInterchange, RawPtr<const Range>, Node* highestNodeTo
      BeSerialized = 0); | 
| 134     Node* serializeNodes(Node* startNode, Node* pastEnd); | 138     Node* serializeNodes(Node* startNode, Node* pastEnd); | 
| 135     void appendString(const String& s) { return MarkupAccumulator::appendString(
      s); } | 139     void appendString(const String& s) { return MarkupAccumulator::appendString(
      s); } | 
| 136     void wrapWithNode(Node&, bool convertBlocksToInlines = false, RangeFullySele
      ctsNode = DoesFullySelectNode); | 140     void wrapWithNode(ContainerNode&, bool convertBlocksToInlines = false, Range
      FullySelectsNode = DoesFullySelectNode); | 
| 137     void wrapWithStyleNode(StylePropertySet*, const Document&, bool isBlock = fa
      lse); | 141     void wrapWithStyleNode(StylePropertySet*, const Document&, bool isBlock = fa
      lse); | 
| 138     String takeResults(); | 142     String takeResults(); | 
| 139 | 143 | 
| 140 private: | 144 private: | 
| 141     void appendStyleNodeOpenTag(StringBuilder&, StylePropertySet*, const Documen
      t&, bool isBlock = false); | 145     void appendStyleNodeOpenTag(StringBuilder&, StylePropertySet*, const Documen
      t&, bool isBlock = false); | 
| 142     const String& styleNodeCloseTag(bool isBlock = false); | 146     const String& styleNodeCloseTag(bool isBlock = false); | 
| 143     virtual void appendText(StringBuilder& out, Text&) OVERRIDE; | 147     virtual void appendText(StringBuilder& out, Text&) OVERRIDE; | 
| 144     String renderedText(Node&, const Range*); | 148     String renderedText(Node&, const Range*); | 
| 145     String stringValueForRange(const Node&, const Range*); | 149     String stringValueForRange(const Node&, const Range*); | 
| 146     void appendElement(StringBuilder& out, Element&, bool addDisplayInline, Rang
      eFullySelectsNode); | 150     void appendElement(StringBuilder& out, Element&, bool addDisplayInline, Rang
      eFullySelectsNode); | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
| 162     RefPtrWillBeMember<EditingStyle> m_wrappingStyle; | 166     RefPtrWillBeMember<EditingStyle> m_wrappingStyle; | 
| 163 }; | 167 }; | 
| 164 | 168 | 
| 165 inline StyledMarkupAccumulator::StyledMarkupAccumulator(WillBeHeapVector<RawPtrW
      illBeMember<Node> >* nodes, EAbsoluteURLs shouldResolveURLs, EAnnotateForInterch
      ange shouldAnnotate, RawPtr<const Range> range, Node* highestNodeToBeSerialized) | 169 inline StyledMarkupAccumulator::StyledMarkupAccumulator(WillBeHeapVector<RawPtrW
      illBeMember<Node> >* nodes, EAbsoluteURLs shouldResolveURLs, EAnnotateForInterch
      ange shouldAnnotate, RawPtr<const Range> range, Node* highestNodeToBeSerialized) | 
| 166     : MarkupAccumulator(nodes, shouldResolveURLs, range) | 170     : MarkupAccumulator(nodes, shouldResolveURLs, range) | 
| 167     , m_shouldAnnotate(shouldAnnotate) | 171     , m_shouldAnnotate(shouldAnnotate) | 
| 168     , m_highestNodeToBeSerialized(highestNodeToBeSerialized) | 172     , m_highestNodeToBeSerialized(highestNodeToBeSerialized) | 
| 169 { | 173 { | 
| 170 } | 174 } | 
| 171 | 175 | 
| 172 void StyledMarkupAccumulator::wrapWithNode(Node& node, bool convertBlocksToInlin
      es, RangeFullySelectsNode rangeFullySelectsNode) | 176 void StyledMarkupAccumulator::wrapWithNode(ContainerNode& node, bool convertBloc
      ksToInlines, RangeFullySelectsNode rangeFullySelectsNode) | 
| 173 { | 177 { | 
| 174     StringBuilder markup; | 178     StringBuilder markup; | 
| 175     if (node.isElementNode()) | 179     if (node.isElementNode()) | 
| 176         appendElement(markup, toElement(node), convertBlocksToInlines && isBlock
      (&node), rangeFullySelectsNode); | 180         appendElement(markup, toElement(node), convertBlocksToInlines && isBlock
      (&node), rangeFullySelectsNode); | 
| 177     else | 181     else | 
| 178         appendStartMarkup(markup, node, 0); | 182         appendStartMarkup(markup, node, 0); | 
| 179     m_reversedPrecedingMarkup.append(markup.toString()); | 183     m_reversedPrecedingMarkup.append(markup.toString()); | 
| 180     appendEndTag(node); | 184     appendEndTag(node); | 
| 181     if (m_nodes) | 185     if (m_nodes) | 
| 182         m_nodes->append(&node); | 186         m_nodes->append(&node); | 
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 250 | 254 | 
| 251     if (wrappingSpan) | 255     if (wrappingSpan) | 
| 252         out.append(styleNodeCloseTag()); | 256         out.append(styleNodeCloseTag()); | 
| 253 } | 257 } | 
| 254 | 258 | 
| 255 String StyledMarkupAccumulator::renderedText(Node& node, const Range* range) | 259 String StyledMarkupAccumulator::renderedText(Node& node, const Range* range) | 
| 256 { | 260 { | 
| 257     if (!node.isTextNode()) | 261     if (!node.isTextNode()) | 
| 258         return String(); | 262         return String(); | 
| 259 | 263 | 
| 260     const Text& textNode = toText(node); | 264     Text& textNode = toText(node); | 
| 261     unsigned startOffset = 0; | 265     unsigned startOffset = 0; | 
| 262     unsigned endOffset = textNode.length(); | 266     unsigned endOffset = textNode.length(); | 
| 263 | 267 | 
| 264     if (range && node == range->startContainer()) | 268     if (range && textNode == range->startContainer()) | 
| 265         startOffset = range->startOffset(); | 269         startOffset = range->startOffset(); | 
| 266     if (range && node == range->endContainer()) | 270     if (range && textNode == range->endContainer()) | 
| 267         endOffset = range->endOffset(); | 271         endOffset = range->endOffset(); | 
| 268 | 272 | 
| 269     Position start = createLegacyEditingPosition(&node, startOffset); | 273     Position start = createLegacyEditingPosition(&textNode, startOffset); | 
| 270     Position end = createLegacyEditingPosition(&node, endOffset); | 274     Position end = createLegacyEditingPosition(&textNode, endOffset); | 
| 271     return plainText(Range::create(node.document(), start, end).get()); | 275     return plainText(Range::create(textNode.document(), start, end).get()); | 
| 272 } | 276 } | 
| 273 | 277 | 
| 274 String StyledMarkupAccumulator::stringValueForRange(const Node& node, const Rang
      e* range) | 278 String StyledMarkupAccumulator::stringValueForRange(const Node& node, const Rang
      e* range) | 
| 275 { | 279 { | 
| 276     if (!range) | 280     if (!range) | 
| 277         return node.nodeValue(); | 281         return node.nodeValue(); | 
| 278 | 282 | 
| 279     String str = node.nodeValue(); | 283     String str = node.nodeValue(); | 
| 280     if (node == range->endContainer()) | 284     if (node == range->endContainer()) | 
| 281         str.truncate(range->endOffset()); | 285         str.truncate(range->endOffset()); | 
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 357         } | 361         } | 
| 358     } | 362     } | 
| 359 | 363 | 
| 360 | 364 | 
| 361     return traverseNodesForSerialization(startNode, pastEnd, EmitString); | 365     return traverseNodesForSerialization(startNode, pastEnd, EmitString); | 
| 362 } | 366 } | 
| 363 | 367 | 
| 364 Node* StyledMarkupAccumulator::traverseNodesForSerialization(Node* startNode, No
      de* pastEnd, NodeTraversalMode traversalMode) | 368 Node* StyledMarkupAccumulator::traverseNodesForSerialization(Node* startNode, No
      de* pastEnd, NodeTraversalMode traversalMode) | 
| 365 { | 369 { | 
| 366     const bool shouldEmit = traversalMode == EmitString; | 370     const bool shouldEmit = traversalMode == EmitString; | 
| 367     WillBeHeapVector<RawPtrWillBeMember<Node> > ancestorsToClose; | 371     WillBeHeapVector<RawPtrWillBeMember<ContainerNode> > ancestorsToClose; | 
| 368     Node* next; | 372     Node* next; | 
| 369     Node* lastClosed = 0; | 373     Node* lastClosed = 0; | 
| 370     for (Node* n = startNode; n != pastEnd; n = next) { | 374     for (Node* n = startNode; n != pastEnd; n = next) { | 
| 371         // According to <rdar://problem/5730668>, it is possible for n to blow | 375         // According to <rdar://problem/5730668>, it is possible for n to blow | 
| 372         // past pastEnd and become null here. This shouldn't be possible. | 376         // past pastEnd and become null here. This shouldn't be possible. | 
| 373         // This null check will prevent crashes (but create too much markup) | 377         // This null check will prevent crashes (but create too much markup) | 
| 374         // and the ASSERT will hopefully lead us to understanding the problem. | 378         // and the ASSERT will hopefully lead us to understanding the problem. | 
| 375         ASSERT(n); | 379         ASSERT(n); | 
| 376         if (!n) | 380         if (!n) | 
| 377             break; | 381             break; | 
| 378 | 382 | 
| 379         next = NodeTraversal::next(*n); | 383         next = NodeTraversal::next(*n); | 
| 380         bool openedTag = false; | 384         bool openedTag = false; | 
| 381 | 385 | 
| 382         if (isBlock(n) && canHaveChildrenForEditing(n) && next == pastEnd) | 386         if (isBlock(n) && canHaveChildrenForEditing(n) && next == pastEnd) | 
| 383             // Don't write out empty block containers that aren't fully selected
      . | 387             // Don't write out empty block containers that aren't fully selected
      . | 
| 384             continue; | 388             continue; | 
| 385 | 389 | 
| 386         if (!n->renderer() && !enclosingElementWithTag(firstPositionInOrBeforeNo
      de(n), selectTag) && m_shouldAnnotate != AnnotateForNavigationTransition) { | 390         if (!n->renderer() && !enclosingElementWithTag(firstPositionInOrBeforeNo
      de(n), selectTag) && m_shouldAnnotate != AnnotateForNavigationTransition) { | 
| 387             next = NodeTraversal::nextSkippingChildren(*n); | 391             next = NodeTraversal::nextSkippingChildren(*n); | 
| 388             // Don't skip over pastEnd. | 392             // Don't skip over pastEnd. | 
| 389             if (pastEnd && pastEnd->isDescendantOf(n)) | 393             if (pastEnd && pastEnd->isDescendantOf(n)) | 
| 390                 next = pastEnd; | 394                 next = pastEnd; | 
| 391         } else { | 395         } else { | 
| 392             // Add the node to the markup if we're not skipping the descendants | 396             // Add the node to the markup if we're not skipping the descendants | 
| 393             if (shouldEmit) | 397             if (shouldEmit) | 
| 394                 appendStartTag(*n); | 398                 appendStartTag(*n); | 
| 395 | 399 | 
| 396             // If node has no children, close the tag now. | 400             // If node has no children, close the tag now. | 
| 397             if (!n->hasChildren()) { | 401             if (n->isContainerNode() && toContainerNode(n)->hasChildren()) { | 
|  | 402                 openedTag = true; | 
|  | 403                 ancestorsToClose.append(toContainerNode(n)); | 
|  | 404             } else { | 
| 398                 if (shouldEmit) | 405                 if (shouldEmit) | 
| 399                     appendEndTag(*n); | 406                     appendEndTag(*n); | 
| 400                 lastClosed = n; | 407                 lastClosed = n; | 
| 401             } else { |  | 
| 402                 openedTag = true; |  | 
| 403                 ancestorsToClose.append(n); |  | 
| 404             } | 408             } | 
| 405         } | 409         } | 
| 406 | 410 | 
| 407         // If we didn't insert open tag and there's no more siblings or we're at
       the end of the traversal, take care of ancestors. | 411         // If we didn't insert open tag and there's no more siblings or we're at
       the end of the traversal, take care of ancestors. | 
| 408         // FIXME: What happens if we just inserted open tag and reached the end? | 412         // FIXME: What happens if we just inserted open tag and reached the end? | 
| 409         if (!openedTag && (!n->nextSibling() || next == pastEnd)) { | 413         if (!openedTag && (!n->nextSibling() || next == pastEnd)) { | 
| 410             // Close up the ancestors. | 414             // Close up the ancestors. | 
| 411             while (!ancestorsToClose.isEmpty()) { | 415             while (!ancestorsToClose.isEmpty()) { | 
| 412                 Node* ancestor = ancestorsToClose.last(); | 416                 ContainerNode* ancestor = ancestorsToClose.last(); | 
| 413                 ASSERT(ancestor); | 417                 ASSERT(ancestor); | 
| 414                 if (next != pastEnd && next->isDescendantOf(ancestor)) | 418                 if (next != pastEnd && next->isDescendantOf(ancestor)) | 
| 415                     break; | 419                     break; | 
| 416                 // Not at the end of the range, close ancestors up to sibling of
       next node. | 420                 // Not at the end of the range, close ancestors up to sibling of
       next node. | 
| 417                 if (shouldEmit) | 421                 if (shouldEmit) | 
| 418                     appendEndTag(*ancestor); | 422                     appendEndTag(*ancestor); | 
| 419                 lastClosed = ancestor; | 423                 lastClosed = ancestor; | 
| 420                 ancestorsToClose.removeLast(); | 424                 ancestorsToClose.removeLast(); | 
| 421             } | 425             } | 
| 422 | 426 | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
| 441     return lastClosed; | 445     return lastClosed; | 
| 442 } | 446 } | 
| 443 | 447 | 
| 444 static bool isHTMLBlockElement(const Node* node) | 448 static bool isHTMLBlockElement(const Node* node) | 
| 445 { | 449 { | 
| 446     ASSERT(node); | 450     ASSERT(node); | 
| 447     return isHTMLTableCellElement(*node) | 451     return isHTMLTableCellElement(*node) | 
| 448         || isNonTableCellHTMLBlockElement(node); | 452         || isNonTableCellHTMLBlockElement(node); | 
| 449 } | 453 } | 
| 450 | 454 | 
| 451 static ContainerNode* ancestorToRetainStructureAndAppearanceForBlock(Node* commo
      nAncestorBlock) | 455 static HTMLElement* ancestorToRetainStructureAndAppearanceForBlock(Element* comm
      onAncestorBlock) | 
| 452 { | 456 { | 
| 453     if (!commonAncestorBlock) | 457     if (!commonAncestorBlock) | 
| 454         return 0; | 458         return 0; | 
| 455 | 459 | 
| 456     if (commonAncestorBlock->hasTagName(tbodyTag) || isHTMLTableRowElement(*comm
      onAncestorBlock)) { | 460     if (commonAncestorBlock->hasTagName(tbodyTag) || isHTMLTableRowElement(*comm
      onAncestorBlock)) | 
| 457         ContainerNode* table = commonAncestorBlock->parentNode(); | 461         return Traversal<HTMLTableElement>::firstAncestor(*commonAncestorBlock); | 
| 458         while (table && !isHTMLTableElement(*table)) |  | 
| 459             table = table->parentNode(); |  | 
| 460 |  | 
| 461         return table; |  | 
| 462     } |  | 
| 463 | 462 | 
| 464     if (isNonTableCellHTMLBlockElement(commonAncestorBlock)) | 463     if (isNonTableCellHTMLBlockElement(commonAncestorBlock)) | 
| 465         return toHTMLElement(commonAncestorBlock); | 464         return toHTMLElement(commonAncestorBlock); | 
| 466 | 465 | 
| 467     return 0; | 466     return 0; | 
| 468 } | 467 } | 
| 469 | 468 | 
| 470 static inline ContainerNode* ancestorToRetainStructureAndAppearance(Node* common
      Ancestor) | 469 static inline HTMLElement* ancestorToRetainStructureAndAppearance(Node* commonAn
      cestor) | 
| 471 { | 470 { | 
| 472     return ancestorToRetainStructureAndAppearanceForBlock(enclosingBlock(commonA
      ncestor)); | 471     return ancestorToRetainStructureAndAppearanceForBlock(enclosingBlock(commonA
      ncestor)); | 
| 473 } | 472 } | 
| 474 | 473 | 
| 475 static inline ContainerNode* ancestorToRetainStructureAndAppearanceWithNoRendere
      r(Node* commonAncestor) | 474 static inline HTMLElement* ancestorToRetainStructureAndAppearanceWithNoRenderer(
      Node* commonAncestor) | 
| 476 { | 475 { | 
| 477     Node* commonAncestorBlock = enclosingNodeOfType(firstPositionInOrBeforeNode(
      commonAncestor), isHTMLBlockElement); | 476     HTMLElement* commonAncestorBlock = toHTMLElement(enclosingNodeOfType(firstPo
      sitionInOrBeforeNode(commonAncestor), isHTMLBlockElement)); | 
| 478     return ancestorToRetainStructureAndAppearanceForBlock(commonAncestorBlock); | 477     return ancestorToRetainStructureAndAppearanceForBlock(commonAncestorBlock); | 
| 479 } | 478 } | 
| 480 | 479 | 
| 481 static bool propertyMissingOrEqualToNone(StylePropertySet* style, CSSPropertyID 
      propertyID) | 480 static bool propertyMissingOrEqualToNone(StylePropertySet* style, CSSPropertyID 
      propertyID) | 
| 482 { | 481 { | 
| 483     if (!style) | 482     if (!style) | 
| 484         return false; | 483         return false; | 
| 485     RefPtrWillBeRawPtr<CSSValue> value = style->getPropertyCSSValue(propertyID); | 484     RefPtrWillBeRawPtr<CSSValue> value = style->getPropertyCSSValue(propertyID); | 
| 486     if (!value) | 485     if (!value) | 
| 487         return true; | 486         return true; | 
| 488     if (!value->isPrimitiveValue()) | 487     if (!value->isPrimitiveValue()) | 
| 489         return false; | 488         return false; | 
| 490     return toCSSPrimitiveValue(value.get())->getValueID() == CSSValueNone; | 489     return toCSSPrimitiveValue(value.get())->getValueID() == CSSValueNone; | 
| 491 } | 490 } | 
| 492 | 491 | 
| 493 static bool needInterchangeNewlineAfter(const VisiblePosition& v) | 492 static bool needInterchangeNewlineAfter(const VisiblePosition& v) | 
| 494 { | 493 { | 
| 495     VisiblePosition next = v.next(); | 494     VisiblePosition next = v.next(); | 
| 496     Node* upstreamNode = next.deepEquivalent().upstream().deprecatedNode(); | 495     Node* upstreamNode = next.deepEquivalent().upstream().deprecatedNode(); | 
| 497     Node* downstreamNode = v.deepEquivalent().downstream().deprecatedNode(); | 496     Node* downstreamNode = v.deepEquivalent().downstream().deprecatedNode(); | 
| 498     // Add an interchange newline if a paragraph break is selected and a br won'
      t already be added to the markup to represent it. | 497     // Add an interchange newline if a paragraph break is selected and a br won'
      t already be added to the markup to represent it. | 
| 499     return isEndOfParagraph(v) && isStartOfParagraph(next) && !(isHTMLBRElement(
      *upstreamNode) && upstreamNode == downstreamNode); | 498     return isEndOfParagraph(v) && isStartOfParagraph(next) && !(isHTMLBRElement(
      *upstreamNode) && upstreamNode == downstreamNode); | 
| 500 } | 499 } | 
| 501 | 500 | 
| 502 static PassRefPtrWillBeRawPtr<EditingStyle> styleFromMatchedRulesAndInlineDecl(c
      onst Node* node) | 501 static PassRefPtrWillBeRawPtr<EditingStyle> styleFromMatchedRulesAndInlineDecl(c
      onst HTMLElement* element) | 
| 503 { | 502 { | 
| 504     if (!node->isHTMLElement()) | 503     RefPtrWillBeRawPtr<EditingStyle> style = EditingStyle::create(element->inlin
      eStyle()); | 
| 505         return nullptr; |  | 
| 506 |  | 
| 507     // FIXME: Having to const_cast here is ugly, but it is quite a bit of work t
      o untangle | 504     // FIXME: Having to const_cast here is ugly, but it is quite a bit of work t
      o untangle | 
| 508     // the non-const-ness of styleFromMatchedRulesForElement. | 505     // the non-const-ness of styleFromMatchedRulesForElement. | 
| 509     HTMLElement* element = const_cast<HTMLElement*>(toHTMLElement(node)); | 506     style->mergeStyleFromRules(const_cast<HTMLElement*>(element)); | 
| 510     RefPtrWillBeRawPtr<EditingStyle> style = EditingStyle::create(element->inlin
      eStyle()); |  | 
| 511     style->mergeStyleFromRules(element); |  | 
| 512     return style.release(); | 507     return style.release(); | 
| 513 } | 508 } | 
| 514 | 509 | 
| 515 static bool isPresentationalHTMLElement(const Node* node) | 510 static bool isPresentationalHTMLElement(const Node* node) | 
| 516 { | 511 { | 
| 517     if (!node->isHTMLElement()) | 512     if (!node->isHTMLElement()) | 
| 518         return false; | 513         return false; | 
| 519 | 514 | 
| 520     const HTMLElement& element = toHTMLElement(*node); | 515     const HTMLElement& element = toHTMLElement(*node); | 
| 521     return element.hasTagName(uTag) || element.hasTagName(sTag) || element.hasTa
      gName(strikeTag) | 516     return element.hasTagName(uTag) || element.hasTagName(sTag) || element.hasTa
      gName(strikeTag) | 
| 522         || element.hasTagName(iTag) || element.hasTagName(emTag) || element.hasT
      agName(bTag) || element.hasTagName(strongTag); | 517         || element.hasTagName(iTag) || element.hasTagName(emTag) || element.hasT
      agName(bTag) || element.hasTagName(strongTag); | 
| 523 } | 518 } | 
| 524 | 519 | 
| 525 static ContainerNode* highestAncestorToWrapMarkup(const Range* range, EAnnotateF
      orInterchange shouldAnnotate, Node* constrainingAncestor) | 520 static HTMLElement* highestAncestorToWrapMarkup(const Range* range, EAnnotateFor
      Interchange shouldAnnotate, Node* constrainingAncestor) | 
| 526 { | 521 { | 
| 527     Node* commonAncestor = range->commonAncestorContainer(); | 522     Node* commonAncestor = range->commonAncestorContainer(); | 
| 528     ASSERT(commonAncestor); | 523     ASSERT(commonAncestor); | 
| 529     ContainerNode* specialCommonAncestor = 0; | 524     HTMLElement* specialCommonAncestor = 0; | 
| 530     if (shouldAnnotate == AnnotateForInterchange) { | 525     if (shouldAnnotate == AnnotateForInterchange) { | 
| 531         // Include ancestors that aren't completely inside the range but are req
      uired to retain | 526         // Include ancestors that aren't completely inside the range but are req
      uired to retain | 
| 532         // the structure and appearance of the copied markup. | 527         // the structure and appearance of the copied markup. | 
| 533         specialCommonAncestor = ancestorToRetainStructureAndAppearance(commonAnc
      estor); | 528         specialCommonAncestor = ancestorToRetainStructureAndAppearance(commonAnc
      estor); | 
| 534 | 529 | 
| 535         if (Node* parentListNode = enclosingNodeOfType(firstPositionInOrBeforeNo
      de(range->firstNode()), isListItem)) { | 530         if (Node* parentListNode = enclosingNodeOfType(firstPositionInOrBeforeNo
      de(range->firstNode()), isListItem)) { | 
| 536             if (blink::areRangesEqual(VisibleSelection::selectionFromContentsOfN
      ode(parentListNode).toNormalizedRange().get(), range)) { | 531             if (blink::areRangesEqual(VisibleSelection::selectionFromContentsOfN
      ode(parentListNode).toNormalizedRange().get(), range)) { | 
| 537                 specialCommonAncestor = parentListNode->parentNode(); | 532                 ContainerNode* ancestor = parentListNode->parentNode(); | 
| 538                 while (specialCommonAncestor && !isListElement(specialCommonAnce
      stor)) | 533                 while (ancestor && !isHTMLListElement(ancestor)) | 
| 539                     specialCommonAncestor = specialCommonAncestor->parentNode(); | 534                     ancestor = ancestor->parentNode(); | 
|  | 535                 specialCommonAncestor = toHTMLElement(ancestor); | 
| 540             } | 536             } | 
| 541         } | 537         } | 
| 542 | 538 | 
| 543         // Retain the Mail quote level by including all ancestor mail block quot
      es. | 539         // Retain the Mail quote level by including all ancestor mail block quot
      es. | 
| 544         if (HTMLQuoteElement* highestMailBlockquote = toHTMLQuoteElement(highest
      EnclosingNodeOfType(firstPositionInOrBeforeNode(range->firstNode()), isMailHTMLB
      lockquoteElement, CanCrossEditingBoundary))) | 540         if (HTMLQuoteElement* highestMailBlockquote = toHTMLQuoteElement(highest
      EnclosingNodeOfType(firstPositionInOrBeforeNode(range->firstNode()), isMailHTMLB
      lockquoteElement, CanCrossEditingBoundary))) | 
| 545             specialCommonAncestor = highestMailBlockquote; | 541             specialCommonAncestor = highestMailBlockquote; | 
| 546     } | 542     } | 
| 547 | 543 | 
| 548     Node* checkAncestor = specialCommonAncestor ? specialCommonAncestor : common
      Ancestor; | 544     Node* checkAncestor = specialCommonAncestor ? specialCommonAncestor : common
      Ancestor; | 
| 549     if (checkAncestor->renderer()) { | 545     if (checkAncestor->renderer()) { | 
| 550         HTMLElement* newSpecialCommonAncestor = toHTMLElement(highestEnclosingNo
      deOfType(firstPositionInNode(checkAncestor), &isPresentationalHTMLElement, CanCr
      ossEditingBoundary, constrainingAncestor)); | 546         HTMLElement* newSpecialCommonAncestor = toHTMLElement(highestEnclosingNo
      deOfType(firstPositionInNode(checkAncestor), &isPresentationalHTMLElement, CanCr
      ossEditingBoundary, constrainingAncestor)); | 
| 551         if (newSpecialCommonAncestor) | 547         if (newSpecialCommonAncestor) | 
| 552             specialCommonAncestor = newSpecialCommonAncestor; | 548             specialCommonAncestor = newSpecialCommonAncestor; | 
| 553     } | 549     } | 
| 554 | 550 | 
| 555     // If a single tab is selected, commonAncestor will be a text node inside a 
      tab span. | 551     // If a single tab is selected, commonAncestor will be a text node inside a 
      tab span. | 
| 556     // If two or more tabs are selected, commonAncestor will be the tab span. | 552     // If two or more tabs are selected, commonAncestor will be the tab span. | 
| 557     // In either case, if there is a specialCommonAncestor already, it will nece
      ssarily be above | 553     // In either case, if there is a specialCommonAncestor already, it will nece
      ssarily be above | 
| 558     // any tab span that needs to be included. | 554     // any tab span that needs to be included. | 
| 559     if (!specialCommonAncestor && isTabSpanTextNode(commonAncestor)) | 555     if (!specialCommonAncestor && isTabHTMLSpanElementTextNode(commonAncestor)) | 
| 560         specialCommonAncestor = commonAncestor->parentNode(); | 556         specialCommonAncestor = toHTMLSpanElement(commonAncestor->parentNode()); | 
| 561     if (!specialCommonAncestor && isTabSpanElement(commonAncestor)) | 557     if (!specialCommonAncestor && isTabHTMLSpanElement(commonAncestor)) | 
| 562         specialCommonAncestor = toElement(commonAncestor); | 558         specialCommonAncestor = toHTMLSpanElement(commonAncestor); | 
| 563 | 559 | 
| 564     if (Element* enclosingAnchor = enclosingElementWithTag(firstPositionInNode(s
      pecialCommonAncestor ? specialCommonAncestor : commonAncestor), aTag)) | 560     if (HTMLAnchorElement* enclosingAnchor = toHTMLAnchorElement(enclosingElemen
      tWithTag(firstPositionInNode(specialCommonAncestor ? specialCommonAncestor : com
      monAncestor), aTag))) | 
| 565         specialCommonAncestor = enclosingAnchor; | 561         specialCommonAncestor = enclosingAnchor; | 
| 566 | 562 | 
| 567     return specialCommonAncestor; | 563     return specialCommonAncestor; | 
| 568 } | 564 } | 
| 569 | 565 | 
| 570 // FIXME: Shouldn't we omit style info when annotate == DoNotAnnotateForIntercha
      nge? | 566 // FIXME: Shouldn't we omit style info when annotate == DoNotAnnotateForIntercha
      nge? | 
| 571 // FIXME: At least, annotation and style info should probably not be included in
       range.markupString() | 567 // FIXME: At least, annotation and style info should probably not be included in
       range.markupString() | 
| 572 static String createMarkupInternal(Document& document, const Range* range, const
       Range* updatedRange, WillBeHeapVector<RawPtrWillBeMember<Node> >* nodes, | 568 static String createMarkupInternal(Document& document, const Range* range, const
       Range* updatedRange, WillBeHeapVector<RawPtrWillBeMember<Node> >* nodes, | 
| 573     EAnnotateForInterchange shouldAnnotate, bool convertBlocksToInlines, EAbsolu
      teURLs shouldResolveURLs, Node* constrainingAncestor) | 569     EAnnotateForInterchange shouldAnnotate, bool convertBlocksToInlines, EAbsolu
      teURLs shouldResolveURLs, Node* constrainingAncestor) | 
| 574 { | 570 { | 
| 575     ASSERT(range); | 571     ASSERT(range); | 
| 576     ASSERT(updatedRange); | 572     ASSERT(updatedRange); | 
| 577     DEFINE_STATIC_LOCAL(const String, interchangeNewlineString, ("<br class=\"" 
      AppleInterchangeNewline "\">")); | 573     DEFINE_STATIC_LOCAL(const String, interchangeNewlineString, ("<br class=\"" 
      AppleInterchangeNewline "\">")); | 
| 578 | 574 | 
| 579     bool collapsed = updatedRange->collapsed(); | 575     bool collapsed = updatedRange->collapsed(); | 
| 580     if (collapsed) | 576     if (collapsed) | 
| 581         return emptyString(); | 577         return emptyString(); | 
| 582     Node* commonAncestor = updatedRange->commonAncestorContainer(); | 578     Node* commonAncestor = updatedRange->commonAncestorContainer(); | 
| 583     if (!commonAncestor) | 579     if (!commonAncestor) | 
| 584         return emptyString(); | 580         return emptyString(); | 
| 585 | 581 | 
| 586     document.updateLayoutIgnorePendingStylesheets(); | 582     document.updateLayoutIgnorePendingStylesheets(); | 
| 587 | 583 | 
| 588     Element* body = enclosingElementWithTag(firstPositionInNode(commonAncestor),
       bodyTag); | 584     HTMLBodyElement* body = toHTMLBodyElement(enclosingElementWithTag(firstPosit
      ionInNode(commonAncestor), bodyTag)); | 
| 589     Node* fullySelectedRoot = 0; | 585     HTMLBodyElement* fullySelectedRoot = 0; | 
| 590     // FIXME: Do this for all fully selected blocks, not just the body. | 586     // FIXME: Do this for all fully selected blocks, not just the body. | 
| 591     if (body && areRangesEqual(VisibleSelection::selectionFromContentsOfNode(bod
      y).toNormalizedRange().get(), range)) | 587     if (body && areRangesEqual(VisibleSelection::selectionFromContentsOfNode(bod
      y).toNormalizedRange().get(), range)) | 
| 592         fullySelectedRoot = body; | 588         fullySelectedRoot = body; | 
| 593     ContainerNode* specialCommonAncestor = highestAncestorToWrapMarkup(updatedRa
      nge, shouldAnnotate, constrainingAncestor); | 589     HTMLElement* specialCommonAncestor = highestAncestorToWrapMarkup(updatedRang
      e, shouldAnnotate, constrainingAncestor); | 
| 594     StyledMarkupAccumulator accumulator(nodes, shouldResolveURLs, shouldAnnotate
      , updatedRange, specialCommonAncestor); | 590     StyledMarkupAccumulator accumulator(nodes, shouldResolveURLs, shouldAnnotate
      , updatedRange, specialCommonAncestor); | 
| 595     Node* pastEnd = updatedRange->pastLastNode(); | 591     Node* pastEnd = updatedRange->pastLastNode(); | 
| 596 | 592 | 
| 597     Node* startNode = updatedRange->firstNode(); | 593     Node* startNode = updatedRange->firstNode(); | 
| 598     VisiblePosition visibleStart(updatedRange->startPosition(), VP_DEFAULT_AFFIN
      ITY); | 594     VisiblePosition visibleStart(updatedRange->startPosition(), VP_DEFAULT_AFFIN
      ITY); | 
| 599     VisiblePosition visibleEnd(updatedRange->endPosition(), VP_DEFAULT_AFFINITY)
      ; | 595     VisiblePosition visibleEnd(updatedRange->endPosition(), VP_DEFAULT_AFFINITY)
      ; | 
| 600     if (shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfter(
      visibleStart)) { | 596     if (shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfter(
      visibleStart)) { | 
| 601         if (visibleStart == visibleEnd.previous()) | 597         if (visibleStart == visibleEnd.previous()) | 
| 602             return interchangeNewlineString; | 598             return interchangeNewlineString; | 
| 603 | 599 | 
| 604         accumulator.appendString(interchangeNewlineString); | 600         accumulator.appendString(interchangeNewlineString); | 
| 605         startNode = visibleStart.next().deepEquivalent().deprecatedNode(); | 601         startNode = visibleStart.next().deepEquivalent().deprecatedNode(); | 
| 606 | 602 | 
| 607         if (pastEnd && Range::compareBoundaryPoints(startNode, 0, pastEnd, 0, AS
      SERT_NO_EXCEPTION) >= 0) | 603         if (pastEnd && Range::compareBoundaryPoints(startNode, 0, pastEnd, 0, AS
      SERT_NO_EXCEPTION) >= 0) | 
| 608             return interchangeNewlineString; | 604             return interchangeNewlineString; | 
| 609     } | 605     } | 
| 610 | 606 | 
| 611     Node* lastClosed = accumulator.serializeNodes(startNode, pastEnd); | 607     Node* lastClosed = accumulator.serializeNodes(startNode, pastEnd); | 
| 612 | 608 | 
| 613     if (specialCommonAncestor && lastClosed) { | 609     if (specialCommonAncestor && lastClosed) { | 
| 614         // Also include all of the ancestors of lastClosed up to this special an
      cestor. | 610         // Also include all of the ancestors of lastClosed up to this special an
      cestor. | 
| 615         for (ContainerNode* ancestor = lastClosed->parentNode(); ancestor; ances
      tor = ancestor->parentNode()) { | 611         for (ContainerNode* ancestor = lastClosed->parentNode(); ancestor; ances
      tor = ancestor->parentNode()) { | 
| 616             if (ancestor == fullySelectedRoot && !convertBlocksToInlines) { | 612             if (ancestor == fullySelectedRoot && !convertBlocksToInlines) { | 
| 617                 RefPtrWillBeRawPtr<EditingStyle> fullySelectedRootStyle = styleF
      romMatchedRulesAndInlineDecl(fullySelectedRoot); | 613                 RefPtrWillBeRawPtr<EditingStyle> fullySelectedRootStyle = styleF
      romMatchedRulesAndInlineDecl(fullySelectedRoot); | 
| 618 | 614 | 
| 619                 // Bring the background attribute over, but not as an attribute 
      because a background attribute on a div | 615                 // Bring the background attribute over, but not as an attribute 
      because a background attribute on a div | 
| 620                 // appears to have no effect. | 616                 // appears to have no effect. | 
| 621                 if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style()
       || !fullySelectedRootStyle->style()->getPropertyCSSValue(CSSPropertyBackgroundI
      mage)) | 617                 if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style()
       || !fullySelectedRootStyle->style()->getPropertyCSSValue(CSSPropertyBackgroundI
      mage)) | 
| 622                     && toElement(fullySelectedRoot)->hasAttribute(backgroundAttr
      )) | 618                     && fullySelectedRoot->hasAttribute(backgroundAttr)) | 
| 623                     fullySelectedRootStyle->style()->setProperty(CSSPropertyBack
      groundImage, "url('" + toElement(fullySelectedRoot)->getAttribute(backgroundAttr
      ) + "')"); | 619                     fullySelectedRootStyle->style()->setProperty(CSSPropertyBack
      groundImage, "url('" + fullySelectedRoot->getAttribute(backgroundAttr) + "')"); | 
| 624 | 620 | 
| 625                 if (fullySelectedRootStyle->style()) { | 621                 if (fullySelectedRootStyle->style()) { | 
| 626                     // Reset the CSS properties to avoid an assertion error in a
      ddStyleMarkup(). | 622                     // Reset the CSS properties to avoid an assertion error in a
      ddStyleMarkup(). | 
| 627                     // This assertion is caused at least when we select all text
       of a <body> element whose | 623                     // This assertion is caused at least when we select all text
       of a <body> element whose | 
| 628                     // 'text-decoration' property is "inherit", and copy it. | 624                     // 'text-decoration' property is "inherit", and copy it. | 
| 629                     if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st
      yle(), CSSPropertyTextDecoration)) | 625                     if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st
      yle(), CSSPropertyTextDecoration)) | 
| 630                         fullySelectedRootStyle->style()->setProperty(CSSProperty
      TextDecoration, CSSValueNone); | 626                         fullySelectedRootStyle->style()->setProperty(CSSProperty
      TextDecoration, CSSValueNone); | 
| 631                     if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st
      yle(), CSSPropertyWebkitTextDecorationsInEffect)) | 627                     if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st
      yle(), CSSPropertyWebkitTextDecorationsInEffect)) | 
| 632                         fullySelectedRootStyle->style()->setProperty(CSSProperty
      WebkitTextDecorationsInEffect, CSSValueNone); | 628                         fullySelectedRootStyle->style()->setProperty(CSSProperty
      WebkitTextDecorationsInEffect, CSSValueNone); | 
| 633                     accumulator.wrapWithStyleNode(fullySelectedRootStyle->style(
      ), document, true); | 629                     accumulator.wrapWithStyleNode(fullySelectedRootStyle->style(
      ), document, true); | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 672     fragment->parseHTML(markup, fakeBody.get(), parserContentPolicy); | 668     fragment->parseHTML(markup, fakeBody.get(), parserContentPolicy); | 
| 673 | 669 | 
| 674     if (!baseURL.isEmpty() && baseURL != blankURL() && baseURL != document.baseU
      RL()) | 670     if (!baseURL.isEmpty() && baseURL != blankURL() && baseURL != document.baseU
      RL()) | 
| 675         completeURLs(*fragment, baseURL); | 671         completeURLs(*fragment, baseURL); | 
| 676 | 672 | 
| 677     return fragment.release(); | 673     return fragment.release(); | 
| 678 } | 674 } | 
| 679 | 675 | 
| 680 static const char fragmentMarkerTag[] = "webkit-fragment-marker"; | 676 static const char fragmentMarkerTag[] = "webkit-fragment-marker"; | 
| 681 | 677 | 
| 682 static bool findNodesSurroundingContext(Document* document, RefPtrWillBeRawPtr<N
      ode>& nodeBeforeContext, RefPtrWillBeRawPtr<Node>& nodeAfterContext) | 678 static bool findNodesSurroundingContext(Document* document, RefPtrWillBeRawPtr<C
      omment>& nodeBeforeContext, RefPtrWillBeRawPtr<Comment>& nodeAfterContext) | 
| 683 { | 679 { | 
| 684     for (Node* node = document->firstChild(); node; node = NodeTraversal::next(*
      node)) { | 680     for (Node* node = document->firstChild(); node; node = NodeTraversal::next(*
      node)) { | 
| 685         if (node->nodeType() == Node::COMMENT_NODE && toCharacterData(node)->dat
      a() == fragmentMarkerTag) { | 681         if (node->nodeType() == Node::COMMENT_NODE && toComment(node)->data() ==
       fragmentMarkerTag) { | 
| 686             if (!nodeBeforeContext) | 682             if (!nodeBeforeContext) | 
| 687                 nodeBeforeContext = node; | 683                 nodeBeforeContext = toComment(node); | 
| 688             else { | 684             else { | 
| 689                 nodeAfterContext = node; | 685                 nodeAfterContext = toComment(node); | 
| 690                 return true; | 686                 return true; | 
| 691             } | 687             } | 
| 692         } | 688         } | 
| 693     } | 689     } | 
| 694     return false; | 690     return false; | 
| 695 } | 691 } | 
| 696 | 692 | 
| 697 static void trimFragment(DocumentFragment* fragment, Node* nodeBeforeContext, No
      de* nodeAfterContext) | 693 static void trimFragment(DocumentFragment* fragment, Comment* nodeBeforeContext,
       Comment* nodeAfterContext) | 
| 698 { | 694 { | 
| 699     RefPtrWillBeRawPtr<Node> next = nullptr; | 695     RefPtrWillBeRawPtr<Node> next = nullptr; | 
| 700     for (RefPtrWillBeRawPtr<Node> node = fragment->firstChild(); node; node = ne
      xt) { | 696     for (RefPtrWillBeRawPtr<Node> node = fragment->firstChild(); node; node = ne
      xt) { | 
| 701         if (nodeBeforeContext->isDescendantOf(node.get())) { | 697         if (nodeBeforeContext->isDescendantOf(node.get())) { | 
| 702             next = NodeTraversal::next(*node); | 698             next = NodeTraversal::next(*node); | 
| 703             continue; | 699             continue; | 
| 704         } | 700         } | 
| 705         next = NodeTraversal::nextSkippingChildren(*node); | 701         next = NodeTraversal::nextSkippingChildren(*node); | 
| 706         ASSERT(!node->contains(nodeAfterContext)); | 702         ASSERT(!node->contains(nodeAfterContext)); | 
| 707         node->parentNode()->removeChild(node.get(), ASSERT_NO_EXCEPTION); | 703         node->parentNode()->removeChild(node.get(), ASSERT_NO_EXCEPTION); | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
| 729     taggedMarkup.append(markup.substring(fragmentEnd)); | 725     taggedMarkup.append(markup.substring(fragmentEnd)); | 
| 730 | 726 | 
| 731     RefPtrWillBeRawPtr<DocumentFragment> taggedFragment = createFragmentFromMark
      up(document, taggedMarkup.toString(), baseURL, parserContentPolicy); | 727     RefPtrWillBeRawPtr<DocumentFragment> taggedFragment = createFragmentFromMark
      up(document, taggedMarkup.toString(), baseURL, parserContentPolicy); | 
| 732     RefPtrWillBeRawPtr<Document> taggedDocument = Document::create(); | 728     RefPtrWillBeRawPtr<Document> taggedDocument = Document::create(); | 
| 733     taggedDocument->setContextFeatures(document.contextFeatures()); | 729     taggedDocument->setContextFeatures(document.contextFeatures()); | 
| 734 | 730 | 
| 735     // FIXME: It's not clear what this code is trying to do. It puts nodes as di
      rect children of a | 731     // FIXME: It's not clear what this code is trying to do. It puts nodes as di
      rect children of a | 
| 736     // Document that are not normally allowed by using the parser machinery. | 732     // Document that are not normally allowed by using the parser machinery. | 
| 737     taggedDocument->parserTakeAllChildrenFrom(*taggedFragment); | 733     taggedDocument->parserTakeAllChildrenFrom(*taggedFragment); | 
| 738 | 734 | 
| 739     RefPtrWillBeRawPtr<Node> nodeBeforeContext = nullptr; | 735     RefPtrWillBeRawPtr<Comment> nodeBeforeContext = nullptr; | 
| 740     RefPtrWillBeRawPtr<Node> nodeAfterContext = nullptr; | 736     RefPtrWillBeRawPtr<Comment> nodeAfterContext = nullptr; | 
| 741     if (!findNodesSurroundingContext(taggedDocument.get(), nodeBeforeContext, no
      deAfterContext)) | 737     if (!findNodesSurroundingContext(taggedDocument.get(), nodeBeforeContext, no
      deAfterContext)) | 
| 742         return nullptr; | 738         return nullptr; | 
| 743 | 739 | 
| 744     RefPtrWillBeRawPtr<Range> range = Range::create(*taggedDocument.get(), | 740     RefPtrWillBeRawPtr<Range> range = Range::create(*taggedDocument.get(), | 
| 745         positionAfterNode(nodeBeforeContext.get()).parentAnchoredEquivalent(), | 741         positionAfterNode(nodeBeforeContext.get()).parentAnchoredEquivalent(), | 
| 746         positionBeforeNode(nodeAfterContext.get()).parentAnchoredEquivalent()); | 742         positionBeforeNode(nodeAfterContext.get()).parentAnchoredEquivalent()); | 
| 747 | 743 | 
| 748     Node* commonAncestor = range->commonAncestorContainer(); | 744     Node* commonAncestor = range->commonAncestorContainer(); | 
| 749     Node* specialCommonAncestor = ancestorToRetainStructureAndAppearanceWithNoRe
      nderer(commonAncestor); | 745     HTMLElement* specialCommonAncestor = ancestorToRetainStructureAndAppearanceW
      ithNoRenderer(commonAncestor); | 
| 750 | 746 | 
| 751     // When there's a special common ancestor outside of the fragment, we must i
      nclude it as well to | 747     // When there's a special common ancestor outside of the fragment, we must i
      nclude it as well to | 
| 752     // preserve the structure and appearance of the fragment. For example, if th
      e fragment contains | 748     // preserve the structure and appearance of the fragment. For example, if th
      e fragment contains | 
| 753     // TD, we need to include the enclosing TABLE tag as well. | 749     // TD, we need to include the enclosing TABLE tag as well. | 
| 754     RefPtrWillBeRawPtr<DocumentFragment> fragment = DocumentFragment::create(doc
      ument); | 750     RefPtrWillBeRawPtr<DocumentFragment> fragment = DocumentFragment::create(doc
      ument); | 
| 755     if (specialCommonAncestor) | 751     if (specialCommonAncestor) | 
| 756         fragment->appendChild(specialCommonAncestor); | 752         fragment->appendChild(specialCommonAncestor); | 
| 757     else | 753     else | 
| 758         fragment->parserTakeAllChildrenFrom(toContainerNode(*commonAncestor)); | 754         fragment->parserTakeAllChildrenFrom(toContainerNode(*commonAncestor)); | 
| 759 | 755 | 
| (...skipping 29 matching lines...) Expand all  Loading... | 
| 789     size_t numEntries = tabList.size(); | 785     size_t numEntries = tabList.size(); | 
| 790     for (size_t i = 0; i < numEntries; ++i) { | 786     for (size_t i = 0; i < numEntries; ++i) { | 
| 791         const String& s = tabList[i]; | 787         const String& s = tabList[i]; | 
| 792 | 788 | 
| 793         // append the non-tab textual part | 789         // append the non-tab textual part | 
| 794         if (!s.isEmpty()) { | 790         if (!s.isEmpty()) { | 
| 795             if (!tabText.isEmpty()) { | 791             if (!tabText.isEmpty()) { | 
| 796                 paragraph->appendChild(createTabSpanElement(document, tabText.to
      String())); | 792                 paragraph->appendChild(createTabSpanElement(document, tabText.to
      String())); | 
| 797                 tabText.clear(); | 793                 tabText.clear(); | 
| 798             } | 794             } | 
| 799             RefPtrWillBeRawPtr<Node> textNode = document.createTextNode(stringWi
      thRebalancedWhitespace(s, first, i + 1 == numEntries)); | 795             RefPtrWillBeRawPtr<Text> textNode = document.createTextNode(stringWi
      thRebalancedWhitespace(s, first, i + 1 == numEntries)); | 
| 800             paragraph->appendChild(textNode.release()); | 796             paragraph->appendChild(textNode.release()); | 
| 801         } | 797         } | 
| 802 | 798 | 
| 803         // there is a tab after every entry, except the last entry | 799         // there is a tab after every entry, except the last entry | 
| 804         // (if the last character is a tab, the list gets an extra empty entry) | 800         // (if the last character is a tab, the list gets an extra empty entry) | 
| 805         if (i + 1 != numEntries) | 801         if (i + 1 != numEntries) | 
| 806             tabText.append('\t'); | 802             tabText.append('\t'); | 
| 807         else if (!tabText.isEmpty()) | 803         else if (!tabText.isEmpty()) | 
| 808             paragraph->appendChild(createTabSpanElement(document, tabText.toStri
      ng())); | 804             paragraph->appendChild(createTabSpanElement(document, tabText.toStri
      ng())); | 
| 809 | 805 | 
| 810         first = false; | 806         first = false; | 
| 811     } | 807     } | 
| 812 } | 808 } | 
| 813 | 809 | 
| 814 bool isPlainTextMarkup(Node* node) | 810 bool isPlainTextMarkup(Node* node) | 
| 815 { | 811 { | 
| 816     ASSERT(node); | 812     ASSERT(node); | 
| 817     if (!node->isElementNode()) | 813     if (!isHTMLDivElement(*node)) | 
| 818         return false; | 814         return false; | 
| 819 | 815 | 
| 820     Element* element = toElement(node); | 816     HTMLDivElement& element = toHTMLDivElement(*node); | 
| 821     if (!isHTMLDivElement(*element) || !element->hasAttributes()) | 817     if (!element.hasAttributes()) | 
| 822         return false; | 818         return false; | 
| 823 | 819 | 
| 824     if (element->hasOneChild() && (element->firstChild()->isTextNode() || elemen
      t->firstChild()->hasChildren())) | 820     if (element.hasOneChild()) | 
| 825         return true; | 821         return element.firstChild()->isTextNode() || element.firstChild()->hasCh
      ildren(); | 
| 826 | 822 | 
| 827     return element->hasChildCount(2) && isTabSpanTextNode(element->firstChild()-
      >firstChild()) && element->lastChild()->isTextNode(); | 823     return element.hasChildCount(2) && isTabHTMLSpanElementTextNode(element.firs
      tChild()->firstChild()) && element.lastChild()->isTextNode(); | 
| 828 } | 824 } | 
| 829 | 825 | 
| 830 static bool shouldPreserveNewline(const Range& range) | 826 static bool shouldPreserveNewline(const Range& range) | 
| 831 { | 827 { | 
| 832     if (Node* node = range.firstNode()) { | 828     if (Node* node = range.firstNode()) { | 
| 833         if (RenderObject* renderer = node->renderer()) | 829         if (RenderObject* renderer = node->renderer()) | 
| 834             return renderer->style()->preserveNewline(); | 830             return renderer->style()->preserveNewline(); | 
| 835     } | 831     } | 
| 836 | 832 | 
| 837     if (Node* node = range.startPosition().anchorNode()) { | 833     if (Node* node = range.startPosition().anchorNode()) { | 
| (...skipping 29 matching lines...) Expand all  Loading... | 
| 867         return fragment.release(); | 863         return fragment.release(); | 
| 868     } | 864     } | 
| 869 | 865 | 
| 870     // A string with no newlines gets added inline, rather than being put into a
       paragraph. | 866     // A string with no newlines gets added inline, rather than being put into a
       paragraph. | 
| 871     if (string.find('\n') == kNotFound) { | 867     if (string.find('\n') == kNotFound) { | 
| 872         fillContainerFromString(fragment.get(), string); | 868         fillContainerFromString(fragment.get(), string); | 
| 873         return fragment.release(); | 869         return fragment.release(); | 
| 874     } | 870     } | 
| 875 | 871 | 
| 876     // Break string into paragraphs. Extra line breaks turn into empty paragraph
      s. | 872     // Break string into paragraphs. Extra line breaks turn into empty paragraph
      s. | 
| 877     Node* blockNode = enclosingBlock(context->firstNode()); | 873     Element* block = enclosingBlock(context->firstNode()); | 
| 878     Element* block = toElement(blockNode); | 874     bool useClonesOfEnclosingBlock = block | 
| 879     bool useClonesOfEnclosingBlock = blockNode |  | 
| 880         && blockNode->isElementNode() |  | 
| 881         && !isHTMLBodyElement(*block) | 875         && !isHTMLBodyElement(*block) | 
| 882         && !isHTMLHtmlElement(*block) | 876         && !isHTMLHtmlElement(*block) | 
| 883         && block != editableRootForPosition(context->startPosition()); | 877         && block != editableRootForPosition(context->startPosition()); | 
| 884     bool useLineBreak = enclosingTextFormControl(context->startPosition()); | 878     bool useLineBreak = enclosingTextFormControl(context->startPosition()); | 
| 885 | 879 | 
| 886     Vector<String> list; | 880     Vector<String> list; | 
| 887     string.split('\n', true, list); // true gets us empty strings in the list | 881     string.split('\n', true, list); // true gets us empty strings in the list | 
| 888     size_t numLines = list.size(); | 882     size_t numLines = list.size(); | 
| 889     for (size_t i = 0; i < numLines; ++i) { | 883     for (size_t i = 0; i < numLines; ++i) { | 
| 890         const String& s = list[i]; | 884         const String& s = list[i]; | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
| 913 { | 907 { | 
| 914     if (!node) | 908     if (!node) | 
| 915         return String(); | 909         return String(); | 
| 916 | 910 | 
| 917     LocalFrame* frame = node->document().frame(); | 911     LocalFrame* frame = node->document().frame(); | 
| 918     if (!frame) | 912     if (!frame) | 
| 919         return String(); | 913         return String(); | 
| 920 | 914 | 
| 921     // FIXME: This is never "for interchange". Is that right? | 915     // FIXME: This is never "for interchange". Is that right? | 
| 922     String markupString = createMarkup(node, IncludeNode, 0); | 916     String markupString = createMarkup(node, IncludeNode, 0); | 
| 923     Node::NodeType nodeType = node->nodeType(); | 917     if (!node->isDocumentNode() && !node->isDocumentTypeNode()) | 
| 924     if (nodeType != Node::DOCUMENT_NODE && !node->isDocumentTypeNode()) |  | 
| 925         markupString = frame->documentTypeString() + markupString; | 918         markupString = frame->documentTypeString() + markupString; | 
| 926 | 919 | 
| 927     return markupString; | 920     return markupString; | 
| 928 } | 921 } | 
| 929 | 922 | 
| 930 String urlToMarkup(const KURL& url, const String& title) | 923 String urlToMarkup(const KURL& url, const String& title) | 
| 931 { | 924 { | 
| 932     StringBuilder markup; | 925     StringBuilder markup; | 
| 933     markup.appendLiteral("<a href=\""); | 926     markup.appendLiteral("<a href=\""); | 
| 934     markup.append(url.string()); | 927     markup.append(url.string()); | 
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1091     // FIXME: No need to replace the child it is a text node and its contents ar
      e already == text. | 1084     // FIXME: No need to replace the child it is a text node and its contents ar
      e already == text. | 
| 1092     if (containerNode->hasOneChild()) { | 1085     if (containerNode->hasOneChild()) { | 
| 1093         containerNode->replaceChild(textNode.release(), containerNode->firstChil
      d(), exceptionState); | 1086         containerNode->replaceChild(textNode.release(), containerNode->firstChil
      d(), exceptionState); | 
| 1094         return; | 1087         return; | 
| 1095     } | 1088     } | 
| 1096 | 1089 | 
| 1097     containerNode->removeChildren(); | 1090     containerNode->removeChildren(); | 
| 1098     containerNode->appendChild(textNode.release(), exceptionState); | 1091     containerNode->appendChild(textNode.release(), exceptionState); | 
| 1099 } | 1092 } | 
| 1100 | 1093 | 
| 1101 void mergeWithNextTextNode(PassRefPtrWillBeRawPtr<Node> node, ExceptionState& ex
      ceptionState) | 1094 void mergeWithNextTextNode(Text* textNode, ExceptionState& exceptionState) | 
| 1102 { | 1095 { | 
| 1103     ASSERT(node && node->isTextNode()); | 1096     ASSERT(textNode); | 
| 1104     Node* next = node->nextSibling(); | 1097     Node* next = textNode->nextSibling(); | 
| 1105     if (!next || !next->isTextNode()) | 1098     if (!next || !next->isTextNode()) | 
| 1106         return; | 1099         return; | 
| 1107 | 1100 | 
| 1108     RefPtrWillBeRawPtr<Text> textNode = toText(node.get()); |  | 
| 1109     RefPtrWillBeRawPtr<Text> textNext = toText(next); | 1101     RefPtrWillBeRawPtr<Text> textNext = toText(next); | 
| 1110     textNode->appendData(textNext->data()); | 1102     textNode->appendData(textNext->data()); | 
| 1111     if (textNext->parentNode()) // Might have been removed by mutation event. | 1103     if (textNext->parentNode()) // Might have been removed by mutation event. | 
| 1112         textNext->remove(exceptionState); | 1104         textNext->remove(exceptionState); | 
| 1113 } | 1105 } | 
| 1114 | 1106 | 
| 1115 String createStyledMarkupForNavigationTransition(Node* node) | 1107 String createStyledMarkupForNavigationTransition(Node* node) | 
| 1116 { | 1108 { | 
| 1117     node->document().updateLayoutIgnorePendingStylesheets(); | 1109     node->document().updateLayoutIgnorePendingStylesheets(); | 
| 1118 | 1110 | 
| 1119     StyledMarkupAccumulator accumulator(0, ResolveAllURLs, AnnotateForNavigation
      Transition, nullptr, 0); | 1111     StyledMarkupAccumulator accumulator(0, ResolveAllURLs, AnnotateForNavigation
      Transition, nullptr, 0); | 
| 1120     accumulator.serializeNodes(node, NodeTraversal::nextSkippingChildren(*node))
      ; | 1112     accumulator.serializeNodes(node, NodeTraversal::nextSkippingChildren(*node))
      ; | 
| 1121 | 1113 | 
| 1122     static const char* documentMarkup = "<!DOCTYPE html><meta name=\"viewport\" 
      content=\"width=device-width, user-scalable=0\">"; | 1114     static const char* documentMarkup = "<!DOCTYPE html><meta name=\"viewport\" 
      content=\"width=device-width, user-scalable=0\">"; | 
| 1123     return documentMarkup + accumulator.takeResults(); | 1115     return documentMarkup + accumulator.takeResults(); | 
| 1124 } | 1116 } | 
| 1125 | 1117 | 
| 1126 } | 1118 } | 
| OLD | NEW | 
|---|