Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / HTMLElement.cpp
index 9c9a776..79c7fa1 100644 (file)
@@ -30,9 +30,8 @@
 #include "HTMLNames.h"
 #include "XMLNames.h"
 #include "bindings/v8/ExceptionState.h"
-#include "bindings/v8/ScriptController.h"
 #include "bindings/v8/ScriptEventListener.h"
-#include "core/css/CSSParser.h"
+#include "core/css/CSSMarkup.h"
 #include "core/css/CSSValuePool.h"
 #include "core/css/StylePropertySet.h"
 #include "core/dom/DocumentFragment.h"
 #include "core/events/EventListener.h"
 #include "core/events/KeyboardEvent.h"
 #include "core/events/ThreadLocalEventNames.h"
+#include "core/frame/Settings.h"
 #include "core/html/HTMLBRElement.h"
 #include "core/html/HTMLFormElement.h"
 #include "core/html/HTMLInputElement.h"
 #include "core/html/HTMLTemplateElement.h"
 #include "core/html/HTMLTextFormControlElement.h"
 #include "core/html/parser/HTMLParserIdioms.h"
-#include "core/loader/FrameLoader.h"
-#include "core/frame/Frame.h"
-#include "core/page/Settings.h"
-#include "core/rendering/RenderWordBreak.h"
-#include "platform/graphics/TextRunIterator.h"
+#include "core/rendering/RenderObject.h"
 #include "platform/text/BidiResolver.h"
+#include "platform/text/BidiTextRun.h"
+#include "platform/text/TextRunIterator.h"
 #include "wtf/StdLibExtras.h"
 #include "wtf/text/CString.h"
 
@@ -204,10 +202,10 @@ void HTMLElement::collectStyleForPresentationAttribute(const QualifiedName& name
         Element::collectStyleForPresentationAttribute(name, value, style);
 }
 
-AtomicString HTMLElement::eventNameForAttributeName(const QualifiedName& attrName) const
+const AtomicString& HTMLElement::eventNameForAttributeName(const QualifiedName& attrName)
 {
     if (!attrName.namespaceURI().isNull())
-        return AtomicString();
+        return nullAtom;
 
     typedef HashMap<AtomicString, AtomicString> StringToStringMap;
     DEFINE_STATIC_LOCAL(StringToStringMap, attributeNameToEventNameMap, ());
@@ -283,6 +281,7 @@ AtomicString HTMLElement::eventNameForAttributeName(const QualifiedName& attrNam
         attributeNameToEventNameMap.set(onprogressAttr.localName(), EventTypeNames::progress);
         attributeNameToEventNameMap.set(onratechangeAttr.localName(), EventTypeNames::ratechange);
         attributeNameToEventNameMap.set(onresetAttr.localName(), EventTypeNames::reset);
+        attributeNameToEventNameMap.set(onresizeAttr.localName(), EventTypeNames::resize);
         attributeNameToEventNameMap.set(onseekedAttr.localName(), EventTypeNames::seeked);
         attributeNameToEventNameMap.set(onseekingAttr.localName(), EventTypeNames::seeking);
         attributeNameToEventNameMap.set(onselectAttr.localName(), EventTypeNames::select);
@@ -319,13 +318,13 @@ void HTMLElement::parseAttribute(const QualifiedName& name, const AtomicString&
             setTabIndexExplicitly(max(static_cast<int>(std::numeric_limits<short>::min()), min(tabindex, static_cast<int>(std::numeric_limits<short>::max()))));
         }
     } else {
-        AtomicString eventName = eventNameForAttributeName(name);
+        const AtomicString& eventName = eventNameForAttributeName(name);
         if (!eventName.isNull())
             setAttributeEventListener(eventName, createAttributeEventListener(this, name, value));
     }
 }
 
-PassRefPtr<DocumentFragment> HTMLElement::textToFragment(const String& text, ExceptionState& es)
+PassRefPtr<DocumentFragment> HTMLElement::textToFragment(const String& text, ExceptionState& exceptionState)
 {
     RefPtr<DocumentFragment> fragment = DocumentFragment::create(document());
     unsigned int i, length = text.length();
@@ -339,13 +338,13 @@ PassRefPtr<DocumentFragment> HTMLElement::textToFragment(const String& text, Exc
               break;
         }
 
-        fragment->appendChild(Text::create(document(), text.substring(start, i - start)), es);
-        if (es.hadException())
+        fragment->appendChild(Text::create(document(), text.substring(start, i - start)), exceptionState);
+        if (exceptionState.hadException())
             return 0;
 
         if (c == '\r' || c == '\n') {
-            fragment->appendChild(HTMLBRElement::create(document()), es);
-            if (es.hadException())
+            fragment->appendChild(HTMLBRElement::create(document()), exceptionState);
+            if (exceptionState.hadException())
                 return 0;
             // Make sure \r\n doesn't result in two line breaks.
             if (c == '\r' && i + 1 < length && text[i + 1] == '\n')
@@ -358,17 +357,17 @@ PassRefPtr<DocumentFragment> HTMLElement::textToFragment(const String& text, Exc
     return fragment;
 }
 
-void HTMLElement::setInnerText(const String& text, ExceptionState& es)
+void HTMLElement::setInnerText(const String& text, ExceptionState& exceptionState)
 {
     if (ieForbidsInsertHTML()) {
-        es.throwUninformativeAndGenericDOMException(NoModificationAllowedError);
+        exceptionState.throwDOMException(NoModificationAllowedError, "The '" + localName() + "' element does not support text insertion.");
         return;
     }
     if (hasLocalName(colTag) || hasLocalName(colgroupTag) || hasLocalName(framesetTag) ||
         hasLocalName(headTag) || hasLocalName(htmlTag) || hasLocalName(tableTag) ||
         hasLocalName(tbodyTag) || hasLocalName(tfootTag) || hasLocalName(theadTag) ||
         hasLocalName(trTag)) {
-        es.throwUninformativeAndGenericDOMException(NoModificationAllowedError);
+        exceptionState.throwDOMException(NoModificationAllowedError, "The '" + localName() + "' element does not support text insertion.");
         return;
     }
 
@@ -379,7 +378,7 @@ void HTMLElement::setInnerText(const String& text, ExceptionState& es)
             removeChildren();
             return;
         }
-        replaceChildrenWithText(this, text, es);
+        replaceChildrenWithText(this, text, exceptionState);
         return;
     }
 
@@ -389,39 +388,39 @@ void HTMLElement::setInnerText(const String& text, ExceptionState& es)
     RenderObject* r = renderer();
     if (r && r->style()->preserveNewline()) {
         if (!text.contains('\r')) {
-            replaceChildrenWithText(this, text, es);
+            replaceChildrenWithText(this, text, exceptionState);
             return;
         }
         String textWithConsistentLineBreaks = text;
         textWithConsistentLineBreaks.replace("\r\n", "\n");
         textWithConsistentLineBreaks.replace('\r', '\n');
-        replaceChildrenWithText(this, textWithConsistentLineBreaks, es);
+        replaceChildrenWithText(this, textWithConsistentLineBreaks, exceptionState);
         return;
     }
 
     // Add text nodes and <br> elements.
-    RefPtr<DocumentFragment> fragment = textToFragment(text, es);
-    if (!es.hadException())
-        replaceChildrenWithFragment(this, fragment.release(), es);
+    RefPtr<DocumentFragment> fragment = textToFragment(text, exceptionState);
+    if (!exceptionState.hadException())
+        replaceChildrenWithFragment(this, fragment.release(), exceptionState);
 }
 
-void HTMLElement::setOuterText(const String &text, ExceptionState& es)
+void HTMLElement::setOuterText(const String &text, ExceptionState& exceptionState)
 {
     if (ieForbidsInsertHTML()) {
-        es.throwUninformativeAndGenericDOMException(NoModificationAllowedError);
+        exceptionState.throwDOMException(NoModificationAllowedError, "The '" + localName() + "' element does not support text insertion.");
         return;
     }
     if (hasLocalName(colTag) || hasLocalName(colgroupTag) || hasLocalName(framesetTag) ||
         hasLocalName(headTag) || hasLocalName(htmlTag) || hasLocalName(tableTag) ||
         hasLocalName(tbodyTag) || hasLocalName(tfootTag) || hasLocalName(theadTag) ||
         hasLocalName(trTag)) {
-        es.throwUninformativeAndGenericDOMException(NoModificationAllowedError);
+        exceptionState.throwDOMException(NoModificationAllowedError, "The '" + localName() + "' element does not support text insertion.");
         return;
     }
 
     ContainerNode* parent = parentNode();
     if (!parent) {
-        es.throwUninformativeAndGenericDOMException(NoModificationAllowedError);
+        exceptionState.throwDOMException(NoModificationAllowedError, "The element has no parent.");
         return;
     }
 
@@ -431,111 +430,25 @@ void HTMLElement::setOuterText(const String &text, ExceptionState& es)
 
     // Convert text to fragment with <br> tags instead of linebreaks if needed.
     if (text.contains('\r') || text.contains('\n'))
-        newChild = textToFragment(text, es);
+        newChild = textToFragment(text, exceptionState);
     else
         newChild = Text::create(document(), text);
 
+    // textToFragment might cause mutation events.
     if (!this || !parentNode())
-        es.throwUninformativeAndGenericDOMException(HierarchyRequestError);
-    if (es.hadException())
-        return;
-    parent->replaceChild(newChild.release(), this, es);
-
-    RefPtr<Node> node = next ? next->previousSibling() : 0;
-    if (!es.hadException() && node && node->isTextNode())
-        mergeWithNextTextNode(node.release(), es);
-
-    if (!es.hadException() && prev && prev->isTextNode())
-        mergeWithNextTextNode(prev.release(), es);
-}
-
-Node* HTMLElement::insertAdjacent(const String& where, Node* newChild, ExceptionState& es)
-{
-    // In Internet Explorer if the element has no parent and where is "beforeBegin" or "afterEnd",
-    // a document fragment is created and the elements appended in the correct order. This document
-    // fragment isn't returned anywhere.
-    //
-    // This is impossible for us to implement as the DOM tree does not allow for such structures,
-    // Opera also appears to disallow such usage.
-
-    if (equalIgnoringCase(where, "beforeBegin")) {
-        if (ContainerNode* parent = this->parentNode()) {
-            parent->insertBefore(newChild, this, es);
-            if (!es.hadException())
-                return newChild;
-        }
-        return 0;
-    }
-
-    if (equalIgnoringCase(where, "afterBegin")) {
-        insertBefore(newChild, firstChild(), es);
-        return es.hadException() ? 0 : newChild;
-    }
-
-    if (equalIgnoringCase(where, "beforeEnd")) {
-        appendChild(newChild, es);
-        return es.hadException() ? 0 : newChild;
-    }
-
-    if (equalIgnoringCase(where, "afterEnd")) {
-        if (ContainerNode* parent = this->parentNode()) {
-            parent->insertBefore(newChild, nextSibling(), es);
-            if (!es.hadException())
-                return newChild;
-        }
-        return 0;
-    }
-
-    // IE throws COM Exception E_INVALIDARG; this is the best DOM exception alternative.
-    es.throwUninformativeAndGenericDOMException(NotSupportedError);
-    return 0;
-}
-
-Element* HTMLElement::insertAdjacentElement(const String& where, Element* newChild, ExceptionState& es)
-{
-    if (!newChild) {
-        // IE throws COM Exception E_INVALIDARG; this is the best DOM exception alternative.
-        es.throwUninformativeAndGenericDOMException(TypeMismatchError);
-        return 0;
-    }
-
-    Node* returnValue = insertAdjacent(where, newChild, es);
-    return toElement(returnValue);
-}
-
-// Step 3 of http://www.whatwg.org/specs/web-apps/current-work/multipage/apis-in-html-documents.html#insertadjacenthtml()
-static Element* contextElementForInsertion(const String& where, Element* element, ExceptionState& es)
-{
-    if (equalIgnoringCase(where, "beforeBegin") || equalIgnoringCase(where, "afterEnd")) {
-        ContainerNode* parent = element->parentNode();
-        if (parent && !parent->isElementNode()) {
-            es.throwUninformativeAndGenericDOMException(NoModificationAllowedError);
-            return 0;
-        }
-        return toElement(parent);
-    }
-    if (equalIgnoringCase(where, "afterBegin") || equalIgnoringCase(where, "beforeEnd"))
-        return element;
-    es.throwUninformativeAndGenericDOMException(SyntaxError);
-    return 0;
-}
+        exceptionState.throwDOMException(HierarchyRequestError, "The element has no parent.");
 
-void HTMLElement::insertAdjacentHTML(const String& where, const String& markup, ExceptionState& es)
-{
-    RefPtr<Element> contextElement = contextElementForInsertion(where, this, es);
-    if (!contextElement)
+    if (exceptionState.hadException())
         return;
 
-    RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(markup, contextElement.get(), AllowScriptingContent, "insertAdjacentHTML", es);
-    if (!fragment)
-        return;
-    insertAdjacent(where, fragment.get(), es);
-}
+    parent->replaceChild(newChild.release(), this, exceptionState);
 
-void HTMLElement::insertAdjacentText(const String& where, const String& text, ExceptionState& es)
-{
-    RefPtr<Text> textNode = document().createTextNode(text);
-    insertAdjacent(where, textNode.get(), es);
+    RefPtr<Node> node = next ? next->previousSibling() : 0;
+    if (!exceptionState.hadException() && node && node->isTextNode())
+        mergeWithNextTextNode(node.release(), exceptionState);
+
+    if (!exceptionState.hadException() && prev && prev->isTextNode())
+        mergeWithNextTextNode(prev.release(), exceptionState);
 }
 
 void HTMLElement::applyAlignmentAttributeToStyle(const AtomicString& alignment, MutableStylePropertySet* style)
@@ -621,7 +534,7 @@ String HTMLElement::contentEditable() const
     return "inherit";
 }
 
-void HTMLElement::setContentEditable(const String& enabled, ExceptionState& es)
+void HTMLElement::setContentEditable(const String& enabled, ExceptionState& exceptionState)
 {
     if (equalIgnoringCase(enabled, "true"))
         setAttribute(contenteditableAttr, "true");
@@ -632,7 +545,7 @@ void HTMLElement::setContentEditable(const String& enabled, ExceptionState& es)
     else if (equalIgnoringCase(enabled, "inherit"))
         removeAttribute(contenteditableAttr);
     else
-        es.throwUninformativeAndGenericDOMException(SyntaxError);
+        exceptionState.throwDOMException(SyntaxError, "The value provided ('" + enabled + "') is not one of 'true', 'false', 'plaintext-only', or 'inherit'.");
 }
 
 bool HTMLElement::draggable() const
@@ -658,7 +571,7 @@ void HTMLElement::setSpellcheck(bool enable)
 
 void HTMLElement::click()
 {
-    dispatchSimulatedClick(0, SendNoEvents, DoNotShowPressedLook);
+    dispatchSimulatedClick(0, SendNoEvents);
 }
 
 void HTMLElement::accessKeyAction(bool sendMouseEvents)
@@ -668,7 +581,7 @@ void HTMLElement::accessKeyAction(bool sendMouseEvents)
 
 String HTMLElement::title() const
 {
-    return getAttribute(titleAttr);
+    return fastGetAttribute(titleAttr);
 }
 
 short HTMLElement::tabIndex() const
@@ -680,7 +593,7 @@ short HTMLElement::tabIndex() const
 
 void HTMLElement::setTabIndex(int value)
 {
-    setAttribute(tabindexAttr, String::number(value));
+    setIntegralAttribute(tabindexAttr, value);
 }
 
 TranslateAttributeMode HTMLElement::translateAttributeMode() const
@@ -718,27 +631,6 @@ void HTMLElement::setTranslate(bool enable)
     setAttribute(translateAttr, enable ? "yes" : "no");
 }
 
-bool HTMLElement::rendererIsNeeded(const RenderStyle& style)
-{
-    if (hasLocalName(noscriptTag)) {
-        Frame* frame = document().frame();
-        if (frame && frame->script().canExecuteScripts(NotAboutToExecuteScript))
-            return false;
-    } else if (hasLocalName(noembedTag)) {
-        Frame* frame = document().frame();
-        if (frame && frame->loader().allowPlugins(NotAboutToInstantiatePlugin))
-            return false;
-    }
-    return Element::rendererIsNeeded(style);
-}
-
-RenderObject* HTMLElement::createRenderer(RenderStyle* style)
-{
-    if (hasLocalName(wbrTag))
-        return new RenderWordBreak(this);
-    return RenderObject::createObject(this, style);
-}
-
 HTMLFormElement* HTMLElement::findFormAncestor() const
 {
     for (ContainerNode* ancestor = parentNode(); ancestor; ancestor = ancestor->parentNode()) {
@@ -748,11 +640,6 @@ HTMLFormElement* HTMLElement::findFormAncestor() const
     return 0;
 }
 
-HTMLFormElement* HTMLElement::virtualForm() const
-{
-    return findFormAncestor();
-}
-
 static inline bool elementAffectsDirectionality(const Node* node)
 {
     return node->isHTMLElement() && (node->hasTagName(bdiTag) || toHTMLElement(node)->hasAttribute(dirAttr));
@@ -771,13 +658,13 @@ static void setHasDirAutoFlagRecursively(Node* firstNode, bool flag, Node* lastN
         if (elementAffectsDirectionality(node)) {
             if (node == lastNode)
                 return;
-            node = NodeTraversal::nextSkippingChildren(node, firstNode);
+            node = NodeTraversal::nextSkippingChildren(*node, firstNode);
             continue;
         }
         node->setSelfOrAncestorHasDirAutoAttribute(flag);
         if (node == lastNode)
             return;
-        node = NodeTraversal::next(node, firstNode);
+        node = NodeTraversal::next(*node, firstNode);
     }
 }
 
@@ -804,15 +691,6 @@ TextDirection HTMLElement::directionalityIfhasDirAutoAttribute(bool& isAuto) con
     return directionality();
 }
 
-static TextDirection determineDirectionality(const String& value, bool& hasStrongDirectionality)
-{
-    TextRun run(value);
-    BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver;
-    bidiResolver.setStatus(BidiStatus(run.direction(), run.directionalOverride()));
-    bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&run, 0));
-    return bidiResolver.determineParagraphDirectionality(&hasStrongDirectionality);
-}
-
 TextDirection HTMLElement::directionality(Node** strongDirectionalityTextNode) const
 {
     if (hasTagName(inputTag)) {
@@ -829,7 +707,7 @@ TextDirection HTMLElement::directionality(Node** strongDirectionalityTextNode) c
         // Skip bdi, script, style and text form controls.
         if (equalIgnoringCase(node->nodeName(), "bdi") || node->hasTagName(scriptTag) || node->hasTagName(styleTag)
             || (node->isElementNode() && toElement(node)->isTextFormControl())) {
-            node = NodeTraversal::nextSkippingChildren(node, this);
+            node = NodeTraversal::nextSkippingChildren(*node, this);
             continue;
         }
 
@@ -837,7 +715,7 @@ TextDirection HTMLElement::directionality(Node** strongDirectionalityTextNode) c
         if (node->isElementNode()) {
             AtomicString dirAttributeValue = toElement(node)->fastGetAttribute(dirAttr);
             if (isValidDirAttribute(dirAttributeValue)) {
-                node = NodeTraversal::nextSkippingChildren(node, this);
+                node = NodeTraversal::nextSkippingChildren(*node, this);
                 continue;
             }
         }
@@ -851,7 +729,7 @@ TextDirection HTMLElement::directionality(Node** strongDirectionalityTextNode) c
                 return textDirection;
             }
         }
-        node = NodeTraversal::next(node, this);
+        node = NodeTraversal::next(*node, this);
     }
     if (strongDirectionalityTextNode)
         *strongDirectionalityTextNode = 0;
@@ -879,7 +757,7 @@ void HTMLElement::adjustDirectionalityIfNeededAfterChildAttributeChanged(Element
         Element* elementToAdjust = this;
         for (; elementToAdjust; elementToAdjust = elementToAdjust->parentElement()) {
             if (elementAffectsDirectionality(elementToAdjust)) {
-                elementToAdjust->setNeedsStyleRecalc();
+                elementToAdjust->setNeedsStyleRecalc(SubtreeStyleChange);
                 return;
             }
         }
@@ -892,14 +770,14 @@ void HTMLElement::calculateAndAdjustDirectionality()
     TextDirection textDirection = directionality(&strongDirectionalityTextNode);
     setHasDirAutoFlagRecursively(this, true, strongDirectionalityTextNode);
     if (renderer() && renderer()->style() && renderer()->style()->direction() != textDirection)
-        setNeedsStyleRecalc();
+        setNeedsStyleRecalc(SubtreeStyleChange);
 }
 
 void HTMLElement::adjustDirectionalityIfNeededAfterChildrenChanged(Node* beforeChange, int childCountDelta)
 {
     if (document().renderer() && childCountDelta < 0) {
-        Node* node = beforeChange ? NodeTraversal::nextSkippingChildren(beforeChange) : 0;
-        for (int counter = 0; node && counter < childCountDelta; counter++, node = NodeTraversal::nextSkippingChildren(node)) {
+        Node* node = beforeChange ? NodeTraversal::nextSkippingChildren(*beforeChange) : 0;
+        for (int counter = 0; node && counter < childCountDelta; counter++, node = NodeTraversal::nextSkippingChildren(*node)) {
             if (elementAffectsDirectionality(node))
                 continue;
 
@@ -910,9 +788,9 @@ void HTMLElement::adjustDirectionalityIfNeededAfterChildrenChanged(Node* beforeC
     if (!selfOrAncestorHasDirAutoAttribute())
         return;
 
-    Node* oldMarkedNode = beforeChange ? NodeTraversal::nextSkippingChildren(beforeChange) : 0;
+    Node* oldMarkedNode = beforeChange ? NodeTraversal::nextSkippingChildren(*beforeChange) : 0;
     while (oldMarkedNode && elementAffectsDirectionality(oldMarkedNode))
-        oldMarkedNode = NodeTraversal::nextSkippingChildren(oldMarkedNode, this);
+        oldMarkedNode = NodeTraversal::nextSkippingChildren(*oldMarkedNode, this);
     if (oldMarkedNode)
         setHasDirAutoFlagRecursively(oldMarkedNode, false);
 
@@ -1028,8 +906,8 @@ void HTMLElement::addHTMLColorToStyle(MutableStylePropertySet* style, CSSPropert
         return;
 
     // If the string is a named CSS color or a 3/6-digit hex color, use that.
-    Color parsedColor(colorString);
-    if (!parsedColor.isValid())
+    Color parsedColor;
+    if (!parsedColor.setFromString(colorString))
         parsedColor.setRGB(parseColorStringWithCrazyLegacyRules(colorString));
 
     style->setProperty(propertyID, cssValuePool().createColorValue(parsedColor.rgb()));