| Index: Source/core/editing/markup.cpp | 
| diff --git a/Source/core/editing/markup.cpp b/Source/core/editing/markup.cpp | 
| index c13fd5d73d8fce3a1379c2f03ffe9c0e57ce1295..de075c6286511c3c46a1e6987fa3dee1b5e5df46 100644 | 
| --- a/Source/core/editing/markup.cpp | 
| +++ b/Source/core/editing/markup.cpp | 
| @@ -38,6 +38,7 @@ | 
| #include "core/css/StylePropertySet.h" | 
| #include "core/dom/CDATASection.h" | 
| #include "core/dom/ChildListMutationScope.h" | 
| +#include "core/dom/Comment.h" | 
| #include "core/dom/ContextFeatures.h" | 
| #include "core/dom/DocumentFragment.h" | 
| #include "core/dom/ElementTraversal.h" | 
| @@ -51,12 +52,15 @@ | 
| #include "core/editing/VisibleUnits.h" | 
| #include "core/editing/htmlediting.h" | 
| #include "core/frame/LocalFrame.h" | 
| +#include "core/html/HTMLAnchorElement.h" | 
| #include "core/html/HTMLBRElement.h" | 
| #include "core/html/HTMLBodyElement.h" | 
| +#include "core/html/HTMLDivElement.h" | 
| #include "core/html/HTMLElement.h" | 
| #include "core/html/HTMLQuoteElement.h" | 
| #include "core/html/HTMLSpanElement.h" | 
| #include "core/html/HTMLTableCellElement.h" | 
| +#include "core/html/HTMLTableElement.h" | 
| #include "core/html/HTMLTextFormControlElement.h" | 
| #include "core/rendering/RenderObject.h" | 
| #include "platform/weborigin/KURL.h" | 
| @@ -133,7 +137,7 @@ public: | 
| StyledMarkupAccumulator(WillBeHeapVector<RawPtrWillBeMember<Node> >* nodes, EAbsoluteURLs, EAnnotateForInterchange, RawPtr<const Range>, Node* highestNodeToBeSerialized = 0); | 
| Node* serializeNodes(Node* startNode, Node* pastEnd); | 
| void appendString(const String& s) { return MarkupAccumulator::appendString(s); } | 
| -    void wrapWithNode(Node&, bool convertBlocksToInlines = false, RangeFullySelectsNode = DoesFullySelectNode); | 
| +    void wrapWithNode(ContainerNode&, bool convertBlocksToInlines = false, RangeFullySelectsNode = DoesFullySelectNode); | 
| void wrapWithStyleNode(StylePropertySet*, const Document&, bool isBlock = false); | 
| String takeResults(); | 
|  | 
| @@ -169,7 +173,7 @@ inline StyledMarkupAccumulator::StyledMarkupAccumulator(WillBeHeapVector<RawPtrW | 
| { | 
| } | 
|  | 
| -void StyledMarkupAccumulator::wrapWithNode(Node& node, bool convertBlocksToInlines, RangeFullySelectsNode rangeFullySelectsNode) | 
| +void StyledMarkupAccumulator::wrapWithNode(ContainerNode& node, bool convertBlocksToInlines, RangeFullySelectsNode rangeFullySelectsNode) | 
| { | 
| StringBuilder markup; | 
| if (node.isElementNode()) | 
| @@ -257,18 +261,18 @@ String StyledMarkupAccumulator::renderedText(Node& node, const Range* range) | 
| if (!node.isTextNode()) | 
| return String(); | 
|  | 
| -    const Text& textNode = toText(node); | 
| +    Text& textNode = toText(node); | 
| unsigned startOffset = 0; | 
| unsigned endOffset = textNode.length(); | 
|  | 
| -    if (range && node == range->startContainer()) | 
| +    if (range && textNode == range->startContainer()) | 
| startOffset = range->startOffset(); | 
| -    if (range && node == range->endContainer()) | 
| +    if (range && textNode == range->endContainer()) | 
| endOffset = range->endOffset(); | 
|  | 
| -    Position start = createLegacyEditingPosition(&node, startOffset); | 
| -    Position end = createLegacyEditingPosition(&node, endOffset); | 
| -    return plainText(Range::create(node.document(), start, end).get()); | 
| +    Position start = createLegacyEditingPosition(&textNode, startOffset); | 
| +    Position end = createLegacyEditingPosition(&textNode, endOffset); | 
| +    return plainText(Range::create(textNode.document(), start, end).get()); | 
| } | 
|  | 
| String StyledMarkupAccumulator::stringValueForRange(const Node& node, const Range* range) | 
| @@ -364,7 +368,7 @@ Node* StyledMarkupAccumulator::serializeNodes(Node* startNode, Node* pastEnd) | 
| Node* StyledMarkupAccumulator::traverseNodesForSerialization(Node* startNode, Node* pastEnd, NodeTraversalMode traversalMode) | 
| { | 
| const bool shouldEmit = traversalMode == EmitString; | 
| -    WillBeHeapVector<RawPtrWillBeMember<Node> > ancestorsToClose; | 
| +    WillBeHeapVector<RawPtrWillBeMember<ContainerNode> > ancestorsToClose; | 
| Node* next; | 
| Node* lastClosed = 0; | 
| for (Node* n = startNode; n != pastEnd; n = next) { | 
| @@ -394,13 +398,13 @@ Node* StyledMarkupAccumulator::traverseNodesForSerialization(Node* startNode, No | 
| appendStartTag(*n); | 
|  | 
| // If node has no children, close the tag now. | 
| -            if (!n->hasChildren()) { | 
| +            if (n->isContainerNode() && toContainerNode(n)->hasChildren()) { | 
| +                openedTag = true; | 
| +                ancestorsToClose.append(toContainerNode(n)); | 
| +            } else { | 
| if (shouldEmit) | 
| appendEndTag(*n); | 
| lastClosed = n; | 
| -            } else { | 
| -                openedTag = true; | 
| -                ancestorsToClose.append(n); | 
| } | 
| } | 
|  | 
| @@ -409,7 +413,7 @@ Node* StyledMarkupAccumulator::traverseNodesForSerialization(Node* startNode, No | 
| if (!openedTag && (!n->nextSibling() || next == pastEnd)) { | 
| // Close up the ancestors. | 
| while (!ancestorsToClose.isEmpty()) { | 
| -                Node* ancestor = ancestorsToClose.last(); | 
| +                ContainerNode* ancestor = ancestorsToClose.last(); | 
| ASSERT(ancestor); | 
| if (next != pastEnd && next->isDescendantOf(ancestor)) | 
| break; | 
| @@ -448,18 +452,13 @@ static bool isHTMLBlockElement(const Node* node) | 
| || isNonTableCellHTMLBlockElement(node); | 
| } | 
|  | 
| -static ContainerNode* ancestorToRetainStructureAndAppearanceForBlock(Node* commonAncestorBlock) | 
| +static HTMLElement* ancestorToRetainStructureAndAppearanceForBlock(Element* commonAncestorBlock) | 
| { | 
| if (!commonAncestorBlock) | 
| return 0; | 
|  | 
| -    if (commonAncestorBlock->hasTagName(tbodyTag) || isHTMLTableRowElement(*commonAncestorBlock)) { | 
| -        ContainerNode* table = commonAncestorBlock->parentNode(); | 
| -        while (table && !isHTMLTableElement(*table)) | 
| -            table = table->parentNode(); | 
| - | 
| -        return table; | 
| -    } | 
| +    if (commonAncestorBlock->hasTagName(tbodyTag) || isHTMLTableRowElement(*commonAncestorBlock)) | 
| +        return Traversal<HTMLTableElement>::firstAncestor(*commonAncestorBlock); | 
|  | 
| if (isNonTableCellHTMLBlockElement(commonAncestorBlock)) | 
| return toHTMLElement(commonAncestorBlock); | 
| @@ -467,14 +466,14 @@ static ContainerNode* ancestorToRetainStructureAndAppearanceForBlock(Node* commo | 
| return 0; | 
| } | 
|  | 
| -static inline ContainerNode* ancestorToRetainStructureAndAppearance(Node* commonAncestor) | 
| +static inline HTMLElement* ancestorToRetainStructureAndAppearance(Node* commonAncestor) | 
| { | 
| return ancestorToRetainStructureAndAppearanceForBlock(enclosingBlock(commonAncestor)); | 
| } | 
|  | 
| -static inline ContainerNode* ancestorToRetainStructureAndAppearanceWithNoRenderer(Node* commonAncestor) | 
| +static inline HTMLElement* ancestorToRetainStructureAndAppearanceWithNoRenderer(Node* commonAncestor) | 
| { | 
| -    Node* commonAncestorBlock = enclosingNodeOfType(firstPositionInOrBeforeNode(commonAncestor), isHTMLBlockElement); | 
| +    HTMLElement* commonAncestorBlock = toHTMLElement(enclosingNodeOfType(firstPositionInOrBeforeNode(commonAncestor), isHTMLBlockElement)); | 
| return ancestorToRetainStructureAndAppearanceForBlock(commonAncestorBlock); | 
| } | 
|  | 
| @@ -499,16 +498,12 @@ static bool needInterchangeNewlineAfter(const VisiblePosition& v) | 
| return isEndOfParagraph(v) && isStartOfParagraph(next) && !(isHTMLBRElement(*upstreamNode) && upstreamNode == downstreamNode); | 
| } | 
|  | 
| -static PassRefPtrWillBeRawPtr<EditingStyle> styleFromMatchedRulesAndInlineDecl(const Node* node) | 
| +static PassRefPtrWillBeRawPtr<EditingStyle> styleFromMatchedRulesAndInlineDecl(const HTMLElement* element) | 
| { | 
| -    if (!node->isHTMLElement()) | 
| -        return nullptr; | 
| - | 
| +    RefPtrWillBeRawPtr<EditingStyle> style = EditingStyle::create(element->inlineStyle()); | 
| // FIXME: Having to const_cast here is ugly, but it is quite a bit of work to untangle | 
| // the non-const-ness of styleFromMatchedRulesForElement. | 
| -    HTMLElement* element = const_cast<HTMLElement*>(toHTMLElement(node)); | 
| -    RefPtrWillBeRawPtr<EditingStyle> style = EditingStyle::create(element->inlineStyle()); | 
| -    style->mergeStyleFromRules(element); | 
| +    style->mergeStyleFromRules(const_cast<HTMLElement*>(element)); | 
| return style.release(); | 
| } | 
|  | 
| @@ -522,11 +517,11 @@ static bool isPresentationalHTMLElement(const Node* node) | 
| || element.hasTagName(iTag) || element.hasTagName(emTag) || element.hasTagName(bTag) || element.hasTagName(strongTag); | 
| } | 
|  | 
| -static ContainerNode* highestAncestorToWrapMarkup(const Range* range, EAnnotateForInterchange shouldAnnotate, Node* constrainingAncestor) | 
| +static HTMLElement* highestAncestorToWrapMarkup(const Range* range, EAnnotateForInterchange shouldAnnotate, Node* constrainingAncestor) | 
| { | 
| Node* commonAncestor = range->commonAncestorContainer(); | 
| ASSERT(commonAncestor); | 
| -    ContainerNode* specialCommonAncestor = 0; | 
| +    HTMLElement* specialCommonAncestor = 0; | 
| if (shouldAnnotate == AnnotateForInterchange) { | 
| // Include ancestors that aren't completely inside the range but are required to retain | 
| // the structure and appearance of the copied markup. | 
| @@ -534,9 +529,10 @@ static ContainerNode* highestAncestorToWrapMarkup(const Range* range, EAnnotateF | 
|  | 
| if (Node* parentListNode = enclosingNodeOfType(firstPositionInOrBeforeNode(range->firstNode()), isListItem)) { | 
| if (blink::areRangesEqual(VisibleSelection::selectionFromContentsOfNode(parentListNode).toNormalizedRange().get(), range)) { | 
| -                specialCommonAncestor = parentListNode->parentNode(); | 
| -                while (specialCommonAncestor && !isListElement(specialCommonAncestor)) | 
| -                    specialCommonAncestor = specialCommonAncestor->parentNode(); | 
| +                ContainerNode* ancestor = parentListNode->parentNode(); | 
| +                while (ancestor && !isHTMLListElement(ancestor)) | 
| +                    ancestor = ancestor->parentNode(); | 
| +                specialCommonAncestor = toHTMLElement(ancestor); | 
| } | 
| } | 
|  | 
| @@ -556,12 +552,12 @@ static ContainerNode* highestAncestorToWrapMarkup(const Range* range, EAnnotateF | 
| // If two or more tabs are selected, commonAncestor will be the tab span. | 
| // In either case, if there is a specialCommonAncestor already, it will necessarily be above | 
| // any tab span that needs to be included. | 
| -    if (!specialCommonAncestor && isTabSpanTextNode(commonAncestor)) | 
| -        specialCommonAncestor = commonAncestor->parentNode(); | 
| -    if (!specialCommonAncestor && isTabSpanElement(commonAncestor)) | 
| -        specialCommonAncestor = toElement(commonAncestor); | 
| +    if (!specialCommonAncestor && isTabHTMLSpanElementTextNode(commonAncestor)) | 
| +        specialCommonAncestor = toHTMLSpanElement(commonAncestor->parentNode()); | 
| +    if (!specialCommonAncestor && isTabHTMLSpanElement(commonAncestor)) | 
| +        specialCommonAncestor = toHTMLSpanElement(commonAncestor); | 
|  | 
| -    if (Element* enclosingAnchor = enclosingElementWithTag(firstPositionInNode(specialCommonAncestor ? specialCommonAncestor : commonAncestor), aTag)) | 
| +    if (HTMLAnchorElement* enclosingAnchor = toHTMLAnchorElement(enclosingElementWithTag(firstPositionInNode(specialCommonAncestor ? specialCommonAncestor : commonAncestor), aTag))) | 
| specialCommonAncestor = enclosingAnchor; | 
|  | 
| return specialCommonAncestor; | 
| @@ -585,12 +581,12 @@ static String createMarkupInternal(Document& document, const Range* range, const | 
|  | 
| document.updateLayoutIgnorePendingStylesheets(); | 
|  | 
| -    Element* body = enclosingElementWithTag(firstPositionInNode(commonAncestor), bodyTag); | 
| -    Node* fullySelectedRoot = 0; | 
| +    HTMLBodyElement* body = toHTMLBodyElement(enclosingElementWithTag(firstPositionInNode(commonAncestor), bodyTag)); | 
| +    HTMLBodyElement* fullySelectedRoot = 0; | 
| // FIXME: Do this for all fully selected blocks, not just the body. | 
| if (body && areRangesEqual(VisibleSelection::selectionFromContentsOfNode(body).toNormalizedRange().get(), range)) | 
| fullySelectedRoot = body; | 
| -    ContainerNode* specialCommonAncestor = highestAncestorToWrapMarkup(updatedRange, shouldAnnotate, constrainingAncestor); | 
| +    HTMLElement* specialCommonAncestor = highestAncestorToWrapMarkup(updatedRange, shouldAnnotate, constrainingAncestor); | 
| StyledMarkupAccumulator accumulator(nodes, shouldResolveURLs, shouldAnnotate, updatedRange, specialCommonAncestor); | 
| Node* pastEnd = updatedRange->pastLastNode(); | 
|  | 
| @@ -619,8 +615,8 @@ static String createMarkupInternal(Document& document, const Range* range, const | 
| // Bring the background attribute over, but not as an attribute because a background attribute on a div | 
| // appears to have no effect. | 
| if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style() || !fullySelectedRootStyle->style()->getPropertyCSSValue(CSSPropertyBackgroundImage)) | 
| -                    && toElement(fullySelectedRoot)->hasAttribute(backgroundAttr)) | 
| -                    fullySelectedRootStyle->style()->setProperty(CSSPropertyBackgroundImage, "url('" + toElement(fullySelectedRoot)->getAttribute(backgroundAttr) + "')"); | 
| +                    && fullySelectedRoot->hasAttribute(backgroundAttr)) | 
| +                    fullySelectedRootStyle->style()->setProperty(CSSPropertyBackgroundImage, "url('" + fullySelectedRoot->getAttribute(backgroundAttr) + "')"); | 
|  | 
| if (fullySelectedRootStyle->style()) { | 
| // Reset the CSS properties to avoid an assertion error in addStyleMarkup(). | 
| @@ -679,14 +675,14 @@ PassRefPtrWillBeRawPtr<DocumentFragment> createFragmentFromMarkup(Document& docu | 
|  | 
| static const char fragmentMarkerTag[] = "webkit-fragment-marker"; | 
|  | 
| -static bool findNodesSurroundingContext(Document* document, RefPtrWillBeRawPtr<Node>& nodeBeforeContext, RefPtrWillBeRawPtr<Node>& nodeAfterContext) | 
| +static bool findNodesSurroundingContext(Document* document, RefPtrWillBeRawPtr<Comment>& nodeBeforeContext, RefPtrWillBeRawPtr<Comment>& nodeAfterContext) | 
| { | 
| for (Node* node = document->firstChild(); node; node = NodeTraversal::next(*node)) { | 
| -        if (node->nodeType() == Node::COMMENT_NODE && toCharacterData(node)->data() == fragmentMarkerTag) { | 
| +        if (node->nodeType() == Node::COMMENT_NODE && toComment(node)->data() == fragmentMarkerTag) { | 
| if (!nodeBeforeContext) | 
| -                nodeBeforeContext = node; | 
| +                nodeBeforeContext = toComment(node); | 
| else { | 
| -                nodeAfterContext = node; | 
| +                nodeAfterContext = toComment(node); | 
| return true; | 
| } | 
| } | 
| @@ -694,7 +690,7 @@ static bool findNodesSurroundingContext(Document* document, RefPtrWillBeRawPtr<N | 
| return false; | 
| } | 
|  | 
| -static void trimFragment(DocumentFragment* fragment, Node* nodeBeforeContext, Node* nodeAfterContext) | 
| +static void trimFragment(DocumentFragment* fragment, Comment* nodeBeforeContext, Comment* nodeAfterContext) | 
| { | 
| RefPtrWillBeRawPtr<Node> next = nullptr; | 
| for (RefPtrWillBeRawPtr<Node> node = fragment->firstChild(); node; node = next) { | 
| @@ -736,8 +732,8 @@ PassRefPtrWillBeRawPtr<DocumentFragment> createFragmentFromMarkupWithContext(Doc | 
| // Document that are not normally allowed by using the parser machinery. | 
| taggedDocument->parserTakeAllChildrenFrom(*taggedFragment); | 
|  | 
| -    RefPtrWillBeRawPtr<Node> nodeBeforeContext = nullptr; | 
| -    RefPtrWillBeRawPtr<Node> nodeAfterContext = nullptr; | 
| +    RefPtrWillBeRawPtr<Comment> nodeBeforeContext = nullptr; | 
| +    RefPtrWillBeRawPtr<Comment> nodeAfterContext = nullptr; | 
| if (!findNodesSurroundingContext(taggedDocument.get(), nodeBeforeContext, nodeAfterContext)) | 
| return nullptr; | 
|  | 
| @@ -746,7 +742,7 @@ PassRefPtrWillBeRawPtr<DocumentFragment> createFragmentFromMarkupWithContext(Doc | 
| positionBeforeNode(nodeAfterContext.get()).parentAnchoredEquivalent()); | 
|  | 
| Node* commonAncestor = range->commonAncestorContainer(); | 
| -    Node* specialCommonAncestor = ancestorToRetainStructureAndAppearanceWithNoRenderer(commonAncestor); | 
| +    HTMLElement* specialCommonAncestor = ancestorToRetainStructureAndAppearanceWithNoRenderer(commonAncestor); | 
|  | 
| // When there's a special common ancestor outside of the fragment, we must include it as well to | 
| // preserve the structure and appearance of the fragment. For example, if the fragment contains | 
| @@ -796,7 +792,7 @@ static void fillContainerFromString(ContainerNode* paragraph, const String& stri | 
| paragraph->appendChild(createTabSpanElement(document, tabText.toString())); | 
| tabText.clear(); | 
| } | 
| -            RefPtrWillBeRawPtr<Node> textNode = document.createTextNode(stringWithRebalancedWhitespace(s, first, i + 1 == numEntries)); | 
| +            RefPtrWillBeRawPtr<Text> textNode = document.createTextNode(stringWithRebalancedWhitespace(s, first, i + 1 == numEntries)); | 
| paragraph->appendChild(textNode.release()); | 
| } | 
|  | 
| @@ -814,17 +810,17 @@ static void fillContainerFromString(ContainerNode* paragraph, const String& stri | 
| bool isPlainTextMarkup(Node* node) | 
| { | 
| ASSERT(node); | 
| -    if (!node->isElementNode()) | 
| +    if (!isHTMLDivElement(*node)) | 
| return false; | 
|  | 
| -    Element* element = toElement(node); | 
| -    if (!isHTMLDivElement(*element) || !element->hasAttributes()) | 
| +    HTMLDivElement& element = toHTMLDivElement(*node); | 
| +    if (!element.hasAttributes()) | 
| return false; | 
|  | 
| -    if (element->hasOneChild() && (element->firstChild()->isTextNode() || element->firstChild()->hasChildren())) | 
| -        return true; | 
| +    if (element.hasOneChild()) | 
| +        return element.firstChild()->isTextNode() || element.firstChild()->hasChildren(); | 
|  | 
| -    return element->hasChildCount(2) && isTabSpanTextNode(element->firstChild()->firstChild()) && element->lastChild()->isTextNode(); | 
| +    return element.hasChildCount(2) && isTabHTMLSpanElementTextNode(element.firstChild()->firstChild()) && element.lastChild()->isTextNode(); | 
| } | 
|  | 
| static bool shouldPreserveNewline(const Range& range) | 
| @@ -874,10 +870,8 @@ PassRefPtrWillBeRawPtr<DocumentFragment> createFragmentFromText(Range* context, | 
| } | 
|  | 
| // Break string into paragraphs. Extra line breaks turn into empty paragraphs. | 
| -    Node* blockNode = enclosingBlock(context->firstNode()); | 
| -    Element* block = toElement(blockNode); | 
| -    bool useClonesOfEnclosingBlock = blockNode | 
| -        && blockNode->isElementNode() | 
| +    Element* block = enclosingBlock(context->firstNode()); | 
| +    bool useClonesOfEnclosingBlock = block | 
| && !isHTMLBodyElement(*block) | 
| && !isHTMLHtmlElement(*block) | 
| && block != editableRootForPosition(context->startPosition()); | 
| @@ -920,8 +914,7 @@ String createFullMarkup(const Node* node) | 
|  | 
| // FIXME: This is never "for interchange". Is that right? | 
| String markupString = createMarkup(node, IncludeNode, 0); | 
| -    Node::NodeType nodeType = node->nodeType(); | 
| -    if (nodeType != Node::DOCUMENT_NODE && !node->isDocumentTypeNode()) | 
| +    if (!node->isDocumentNode() && !node->isDocumentTypeNode()) | 
| markupString = frame->documentTypeString() + markupString; | 
|  | 
| return markupString; | 
| @@ -1098,14 +1091,13 @@ void replaceChildrenWithText(ContainerNode* container, const String& text, Excep | 
| containerNode->appendChild(textNode.release(), exceptionState); | 
| } | 
|  | 
| -void mergeWithNextTextNode(PassRefPtrWillBeRawPtr<Node> node, ExceptionState& exceptionState) | 
| +void mergeWithNextTextNode(Text* textNode, ExceptionState& exceptionState) | 
| { | 
| -    ASSERT(node && node->isTextNode()); | 
| -    Node* next = node->nextSibling(); | 
| +    ASSERT(textNode); | 
| +    Node* next = textNode->nextSibling(); | 
| if (!next || !next->isTextNode()) | 
| return; | 
|  | 
| -    RefPtrWillBeRawPtr<Text> textNode = toText(node.get()); | 
| RefPtrWillBeRawPtr<Text> textNext = toText(next); | 
| textNode->appendData(textNext->data()); | 
| if (textNext->parentNode()) // Might have been removed by mutation event. | 
|  |