• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Peter Kelly (pmk@post.com)
5  *           (C) 2001 Dirk Mueller (mueller@kde.org)
6  *           (C) 2007 David Smith (catfish.man@gmail.com)
7  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
8  *           (C) 2007 Eric Seidel (eric@webkit.org)
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25 
26 #include "config.h"
27 #include "Element.h"
28 
29 #include "AXObjectCache.h"
30 #include "Attr.h"
31 #include "CSSParser.h"
32 #include "CSSSelectorList.h"
33 #include "CSSStyleSelector.h"
34 #include "ClassList.h"
35 #include "ClientRect.h"
36 #include "ClientRectList.h"
37 #include "DOMTokenList.h"
38 #include "DatasetDOMStringMap.h"
39 #include "Document.h"
40 #include "DocumentFragment.h"
41 #include "ElementRareData.h"
42 #include "ExceptionCode.h"
43 #include "FocusController.h"
44 #include "Frame.h"
45 #include "FrameView.h"
46 #include "HTMLElement.h"
47 #include "HTMLNames.h"
48 #include "HTMLParserIdioms.h"
49 #include "InspectorInstrumentation.h"
50 #include "NodeList.h"
51 #include "NodeRenderStyle.h"
52 #include "Page.h"
53 #include "RenderLayer.h"
54 #include "RenderView.h"
55 #include "RenderWidget.h"
56 #include "Settings.h"
57 #include "ShadowRoot.h"
58 #include "TextIterator.h"
59 #include "WebKitAnimationList.h"
60 #include "XMLNames.h"
61 #include "htmlediting.h"
62 #include <wtf/text/CString.h>
63 
64 #if ENABLE(SVG)
65 #include "SVGElement.h"
66 #include "SVGNames.h"
67 #endif
68 
69 namespace WebCore {
70 
71 using namespace HTMLNames;
72 using namespace XMLNames;
73 
74 class StyleSelectorParentPusher {
75 public:
StyleSelectorParentPusher(Element * parent)76     StyleSelectorParentPusher(Element* parent)
77         : m_parent(parent)
78         , m_pushedStyleSelector(0)
79     {
80     }
push()81     void push()
82     {
83         if (m_pushedStyleSelector)
84             return;
85         m_pushedStyleSelector = m_parent->document()->styleSelector();
86         m_pushedStyleSelector->pushParent(m_parent);
87     }
~StyleSelectorParentPusher()88     ~StyleSelectorParentPusher()
89     {
90 
91         if (!m_pushedStyleSelector)
92             return;
93 
94         // This tells us that our pushed style selector is in a bad state,
95         // so we should just bail out in that scenario.
96         ASSERT(m_pushedStyleSelector == m_parent->document()->styleSelector());
97         if (m_pushedStyleSelector != m_parent->document()->styleSelector())
98             return;
99 
100         m_pushedStyleSelector->popParent(m_parent);
101     }
102 
103 private:
104     Element* m_parent;
105     CSSStyleSelector* m_pushedStyleSelector;
106 };
107 
create(const QualifiedName & tagName,Document * document)108 PassRefPtr<Element> Element::create(const QualifiedName& tagName, Document* document)
109 {
110     return adoptRef(new Element(tagName, document, CreateElement));
111 }
112 
~Element()113 Element::~Element()
114 {
115     removeShadowRoot();
116     if (m_attributeMap)
117         m_attributeMap->detachFromElement();
118 }
119 
rareData() const120 inline ElementRareData* Element::rareData() const
121 {
122     ASSERT(hasRareData());
123     return static_cast<ElementRareData*>(NodeRareData::rareDataFromMap(this));
124 }
125 
ensureRareData()126 inline ElementRareData* Element::ensureRareData()
127 {
128     return static_cast<ElementRareData*>(Node::ensureRareData());
129 }
130 
createRareData()131 NodeRareData* Element::createRareData()
132 {
133     return new ElementRareData;
134 }
135 
136 DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, blur);
137 DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, error);
138 DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, focus);
139 DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, load);
140 
deprecatedCreateContextualFragment(const String & markup,FragmentScriptingPermission scriptingPermission)141 PassRefPtr<DocumentFragment> Element::deprecatedCreateContextualFragment(const String& markup, FragmentScriptingPermission scriptingPermission)
142 {
143     RefPtr<DocumentFragment> fragment = document()->createDocumentFragment();
144 
145     if (document()->isHTMLDocument())
146         fragment->parseHTML(markup, this, scriptingPermission);
147     else {
148         if (!fragment->parseXML(markup, this, scriptingPermission))
149             // FIXME: We should propagate a syntax error exception out here.
150             return 0;
151     }
152 
153     // Exceptions are ignored because none ought to happen here.
154     ExceptionCode ignoredExceptionCode;
155 
156     // We need to pop <html> and <body> elements and remove <head> to
157     // accommodate folks passing complete HTML documents to make the
158     // child of an element.
159 
160     RefPtr<Node> nextNode;
161     for (RefPtr<Node> node = fragment->firstChild(); node; node = nextNode) {
162         nextNode = node->nextSibling();
163         if (node->hasTagName(htmlTag) || node->hasTagName(bodyTag)) {
164             HTMLElement* element = toHTMLElement(node.get());
165             Node* firstChild = element->firstChild();
166             if (firstChild)
167                 nextNode = firstChild;
168             RefPtr<Node> nextChild;
169             for (RefPtr<Node> child = firstChild; child; child = nextChild) {
170                 nextChild = child->nextSibling();
171                 element->removeChild(child.get(), ignoredExceptionCode);
172                 ASSERT(!ignoredExceptionCode);
173                 fragment->insertBefore(child, element, ignoredExceptionCode);
174                 ASSERT(!ignoredExceptionCode);
175             }
176             fragment->removeChild(element, ignoredExceptionCode);
177             ASSERT(!ignoredExceptionCode);
178         } else if (node->hasTagName(headTag)) {
179             fragment->removeChild(node.get(), ignoredExceptionCode);
180             ASSERT(!ignoredExceptionCode);
181         }
182     }
183     return fragment.release();
184 }
185 
cloneNode(bool deep)186 PassRefPtr<Node> Element::cloneNode(bool deep)
187 {
188     return deep ? cloneElementWithChildren() : cloneElementWithoutChildren();
189 }
190 
cloneElementWithChildren()191 PassRefPtr<Element> Element::cloneElementWithChildren()
192 {
193     RefPtr<Element> clone = cloneElementWithoutChildren();
194     cloneChildNodes(clone.get());
195     return clone.release();
196 }
197 
cloneElementWithoutChildren()198 PassRefPtr<Element> Element::cloneElementWithoutChildren()
199 {
200     RefPtr<Element> clone = cloneElementWithoutAttributesAndChildren();
201     // This will catch HTML elements in the wrong namespace that are not correctly copied.
202     // This is a sanity check as HTML overloads some of the DOM methods.
203     ASSERT(isHTMLElement() == clone->isHTMLElement());
204 
205     // Call attributes(true) to force attribute synchronization to occur for SVG and style attributes.
206     if (NamedNodeMap* attributeMap = attributes(true))
207         clone->attributes()->setAttributes(*attributeMap);
208 
209     clone->copyNonAttributeProperties(this);
210 
211     return clone.release();
212 }
213 
cloneElementWithoutAttributesAndChildren() const214 PassRefPtr<Element> Element::cloneElementWithoutAttributesAndChildren() const
215 {
216     return document()->createElement(tagQName(), false);
217 }
218 
removeAttribute(const QualifiedName & name,ExceptionCode & ec)219 void Element::removeAttribute(const QualifiedName& name, ExceptionCode& ec)
220 {
221     if (m_attributeMap) {
222         ec = 0;
223         m_attributeMap->removeNamedItem(name, ec);
224         if (ec == NOT_FOUND_ERR)
225             ec = 0;
226     }
227 }
228 
setAttribute(const QualifiedName & name,const AtomicString & value)229 void Element::setAttribute(const QualifiedName& name, const AtomicString& value)
230 {
231     ExceptionCode ec;
232     setAttribute(name, value, ec);
233 }
234 
setCStringAttribute(const QualifiedName & name,const char * cStringValue)235 void Element::setCStringAttribute(const QualifiedName& name, const char* cStringValue)
236 {
237     ExceptionCode ec;
238     setAttribute(name, AtomicString(cStringValue), ec);
239 }
240 
setBooleanAttribute(const QualifiedName & name,bool b)241 void Element::setBooleanAttribute(const QualifiedName& name, bool b)
242 {
243     if (b)
244         setAttribute(name, emptyAtom);
245     else {
246         ExceptionCode ex;
247         removeAttribute(name, ex);
248     }
249 }
250 
nodeType() const251 Node::NodeType Element::nodeType() const
252 {
253     return ELEMENT_NODE;
254 }
255 
hasAttribute(const QualifiedName & name) const256 bool Element::hasAttribute(const QualifiedName& name) const
257 {
258     return hasAttributeNS(name.namespaceURI(), name.localName());
259 }
260 
getAttribute(const QualifiedName & name) const261 const AtomicString& Element::getAttribute(const QualifiedName& name) const
262 {
263     if (UNLIKELY(name == styleAttr) && !isStyleAttributeValid())
264         updateStyleAttribute();
265 
266 #if ENABLE(SVG)
267     if (UNLIKELY(!areSVGAttributesValid()))
268         updateAnimatedSVGAttribute(name);
269 #endif
270 
271     return fastGetAttribute(name);
272 }
273 
scrollIntoView(bool alignToTop)274 void Element::scrollIntoView(bool alignToTop)
275 {
276     document()->updateLayoutIgnorePendingStylesheets();
277     IntRect bounds = getRect();
278     if (renderer()) {
279         // Align to the top / bottom and to the closest edge.
280         if (alignToTop)
281             renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
282         else
283             renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignBottomAlways);
284     }
285 }
286 
scrollIntoViewIfNeeded(bool centerIfNeeded)287 void Element::scrollIntoViewIfNeeded(bool centerIfNeeded)
288 {
289     document()->updateLayoutIgnorePendingStylesheets();
290     IntRect bounds = getRect();
291     if (renderer()) {
292         if (centerIfNeeded)
293             renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
294         else
295             renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
296     }
297 }
298 
scrollByUnits(int units,ScrollGranularity granularity)299 void Element::scrollByUnits(int units, ScrollGranularity granularity)
300 {
301     document()->updateLayoutIgnorePendingStylesheets();
302     if (RenderObject *rend = renderer()) {
303         if (rend->hasOverflowClip()) {
304             ScrollDirection direction = ScrollDown;
305             if (units < 0) {
306                 direction = ScrollUp;
307                 units = -units;
308             }
309             toRenderBox(rend)->layer()->scroll(direction, granularity, units);
310         }
311     }
312 }
313 
scrollByLines(int lines)314 void Element::scrollByLines(int lines)
315 {
316     scrollByUnits(lines, ScrollByLine);
317 }
318 
scrollByPages(int pages)319 void Element::scrollByPages(int pages)
320 {
321     scrollByUnits(pages, ScrollByPage);
322 }
323 
localZoomForRenderer(RenderObject * renderer)324 static float localZoomForRenderer(RenderObject* renderer)
325 {
326     // FIXME: This does the wrong thing if two opposing zooms are in effect and canceled each
327     // other out, but the alternative is that we'd have to crawl up the whole render tree every
328     // time (or store an additional bit in the RenderStyle to indicate that a zoom was specified).
329     float zoomFactor = 1;
330     if (renderer->style()->effectiveZoom() != 1) {
331         // Need to find the nearest enclosing RenderObject that set up
332         // a differing zoom, and then we divide our result by it to eliminate the zoom.
333         RenderObject* prev = renderer;
334         for (RenderObject* curr = prev->parent(); curr; curr = curr->parent()) {
335             if (curr->style()->effectiveZoom() != prev->style()->effectiveZoom()) {
336                 zoomFactor = prev->style()->zoom();
337                 break;
338             }
339             prev = curr;
340         }
341         if (prev->isRenderView())
342             zoomFactor = prev->style()->zoom();
343     }
344     return zoomFactor;
345 }
346 
adjustForLocalZoom(int value,RenderObject * renderer)347 static int adjustForLocalZoom(int value, RenderObject* renderer)
348 {
349     float zoomFactor = localZoomForRenderer(renderer);
350     if (zoomFactor == 1)
351         return value;
352     // Needed because computeLengthInt truncates (rather than rounds) when scaling up.
353     if (zoomFactor > 1)
354         value++;
355     return static_cast<int>(value / zoomFactor);
356 }
357 
offsetLeft()358 int Element::offsetLeft()
359 {
360     document()->updateLayoutIgnorePendingStylesheets();
361     if (RenderBoxModelObject* rend = renderBoxModelObject())
362         return adjustForLocalZoom(rend->offsetLeft(), rend);
363     return 0;
364 }
365 
offsetTop()366 int Element::offsetTop()
367 {
368     document()->updateLayoutIgnorePendingStylesheets();
369     if (RenderBoxModelObject* rend = renderBoxModelObject())
370         return adjustForLocalZoom(rend->offsetTop(), rend);
371     return 0;
372 }
373 
offsetWidth()374 int Element::offsetWidth()
375 {
376     document()->updateLayoutIgnorePendingStylesheets();
377     if (RenderBoxModelObject* rend = renderBoxModelObject())
378         return adjustForAbsoluteZoom(rend->offsetWidth(), rend);
379     return 0;
380 }
381 
offsetHeight()382 int Element::offsetHeight()
383 {
384     document()->updateLayoutIgnorePendingStylesheets();
385     if (RenderBoxModelObject* rend = renderBoxModelObject())
386         return adjustForAbsoluteZoom(rend->offsetHeight(), rend);
387     return 0;
388 }
389 
offsetParent()390 Element* Element::offsetParent()
391 {
392     document()->updateLayoutIgnorePendingStylesheets();
393     if (RenderObject* rend = renderer())
394         if (RenderObject* offsetParent = rend->offsetParent())
395             return static_cast<Element*>(offsetParent->node());
396     return 0;
397 }
398 
clientLeft()399 int Element::clientLeft()
400 {
401     document()->updateLayoutIgnorePendingStylesheets();
402 
403     if (RenderBox* rend = renderBox())
404         return adjustForAbsoluteZoom(rend->clientLeft(), rend);
405     return 0;
406 }
407 
clientTop()408 int Element::clientTop()
409 {
410     document()->updateLayoutIgnorePendingStylesheets();
411 
412     if (RenderBox* rend = renderBox())
413         return adjustForAbsoluteZoom(rend->clientTop(), rend);
414     return 0;
415 }
416 
clientWidth()417 int Element::clientWidth()
418 {
419     document()->updateLayoutIgnorePendingStylesheets();
420 
421     // When in strict mode, clientWidth for the document element should return the width of the containing frame.
422     // When in quirks mode, clientWidth for the body element should return the width of the containing frame.
423     bool inQuirksMode = document()->inQuirksMode();
424     if ((!inQuirksMode && document()->documentElement() == this) ||
425         (inQuirksMode && isHTMLElement() && document()->body() == this)) {
426         if (FrameView* view = document()->view()) {
427             if (RenderView* renderView = document()->renderView())
428                 return adjustForAbsoluteZoom(view->layoutWidth(), renderView);
429         }
430     }
431 
432     if (RenderBox* rend = renderBox())
433         return adjustForAbsoluteZoom(rend->clientWidth(), rend);
434     return 0;
435 }
436 
clientHeight()437 int Element::clientHeight()
438 {
439     document()->updateLayoutIgnorePendingStylesheets();
440 
441     // When in strict mode, clientHeight for the document element should return the height of the containing frame.
442     // When in quirks mode, clientHeight for the body element should return the height of the containing frame.
443     bool inQuirksMode = document()->inQuirksMode();
444 
445     if ((!inQuirksMode && document()->documentElement() == this) ||
446         (inQuirksMode && isHTMLElement() && document()->body() == this)) {
447         if (FrameView* view = document()->view()) {
448             if (RenderView* renderView = document()->renderView())
449                 return adjustForAbsoluteZoom(view->layoutHeight(), renderView);
450         }
451     }
452 
453     if (RenderBox* rend = renderBox())
454         return adjustForAbsoluteZoom(rend->clientHeight(), rend);
455     return 0;
456 }
457 
scrollLeft() const458 int Element::scrollLeft() const
459 {
460     document()->updateLayoutIgnorePendingStylesheets();
461     if (RenderBox* rend = renderBox())
462         return adjustForAbsoluteZoom(rend->scrollLeft(), rend);
463     return 0;
464 }
465 
scrollTop() const466 int Element::scrollTop() const
467 {
468     document()->updateLayoutIgnorePendingStylesheets();
469     if (RenderBox* rend = renderBox())
470         return adjustForAbsoluteZoom(rend->scrollTop(), rend);
471     return 0;
472 }
473 
setScrollLeft(int newLeft)474 void Element::setScrollLeft(int newLeft)
475 {
476     document()->updateLayoutIgnorePendingStylesheets();
477     if (RenderBox* rend = renderBox())
478         rend->setScrollLeft(static_cast<int>(newLeft * rend->style()->effectiveZoom()));
479 }
480 
setScrollTop(int newTop)481 void Element::setScrollTop(int newTop)
482 {
483     document()->updateLayoutIgnorePendingStylesheets();
484     if (RenderBox* rend = renderBox())
485         rend->setScrollTop(static_cast<int>(newTop * rend->style()->effectiveZoom()));
486 }
487 
scrollWidth() const488 int Element::scrollWidth() const
489 {
490     document()->updateLayoutIgnorePendingStylesheets();
491     if (RenderBox* rend = renderBox())
492         return adjustForAbsoluteZoom(rend->scrollWidth(), rend);
493     return 0;
494 }
495 
scrollHeight() const496 int Element::scrollHeight() const
497 {
498     document()->updateLayoutIgnorePendingStylesheets();
499     if (RenderBox* rend = renderBox())
500         return adjustForAbsoluteZoom(rend->scrollHeight(), rend);
501     return 0;
502 }
503 
boundsInWindowSpace() const504 IntRect Element::boundsInWindowSpace() const
505 {
506     document()->updateLayoutIgnorePendingStylesheets();
507 
508     FrameView* view = document()->view();
509     if (!view)
510         return IntRect();
511 
512     Vector<FloatQuad> quads;
513 #if ENABLE(SVG)
514     if (isSVGElement() && renderer()) {
515         // Get the bounding rectangle from the SVG model.
516         const SVGElement* svgElement = static_cast<const SVGElement*>(this);
517         FloatRect localRect;
518         if (svgElement->boundingBox(localRect))
519             quads.append(renderer()->localToAbsoluteQuad(localRect));
520     } else
521 #endif
522     {
523         // Get the bounding rectangle from the box model.
524         if (renderBoxModelObject())
525             renderBoxModelObject()->absoluteQuads(quads);
526     }
527 
528     if (quads.isEmpty())
529         return IntRect();
530 
531     IntRect result = quads[0].enclosingBoundingBox();
532     for (size_t i = 1; i < quads.size(); ++i)
533         result.unite(quads[i].enclosingBoundingBox());
534 
535     result = view->contentsToWindow(result);
536     return result;
537 }
538 
getClientRects() const539 PassRefPtr<ClientRectList> Element::getClientRects() const
540 {
541     document()->updateLayoutIgnorePendingStylesheets();
542 
543     RenderBoxModelObject* renderBoxModelObject = this->renderBoxModelObject();
544     if (!renderBoxModelObject)
545         return ClientRectList::create();
546 
547     // FIXME: Handle SVG elements.
548     // FIXME: Handle table/inline-table with a caption.
549 
550     Vector<FloatQuad> quads;
551     renderBoxModelObject->absoluteQuads(quads);
552 
553     float pageScale = 1;
554     if (Page* page = document()->page()) {
555         if (Frame* frame = page->mainFrame())
556             pageScale = frame->pageScaleFactor();
557     }
558 
559     if (FrameView* view = document()->view()) {
560         IntRect visibleContentRect = view->visibleContentRect();
561         for (size_t i = 0; i < quads.size(); ++i) {
562             quads[i].move(-visibleContentRect.x(), -visibleContentRect.y());
563             adjustFloatQuadForAbsoluteZoom(quads[i], renderBoxModelObject);
564             if (pageScale != 1)
565                 adjustFloatQuadForPageScale(quads[i], pageScale);
566         }
567     }
568 
569     return ClientRectList::create(quads);
570 }
571 
getBoundingClientRect() const572 PassRefPtr<ClientRect> Element::getBoundingClientRect() const
573 {
574     document()->updateLayoutIgnorePendingStylesheets();
575 
576     Vector<FloatQuad> quads;
577 #if ENABLE(SVG)
578     if (isSVGElement() && renderer()) {
579         // Get the bounding rectangle from the SVG model.
580         const SVGElement* svgElement = static_cast<const SVGElement*>(this);
581         FloatRect localRect;
582         if (svgElement->boundingBox(localRect))
583             quads.append(renderer()->localToAbsoluteQuad(localRect));
584     } else
585 #endif
586     {
587         // Get the bounding rectangle from the box model.
588         if (renderBoxModelObject())
589             renderBoxModelObject()->absoluteQuads(quads);
590     }
591 
592     if (quads.isEmpty())
593         return ClientRect::create();
594 
595     FloatRect result = quads[0].boundingBox();
596     for (size_t i = 1; i < quads.size(); ++i)
597         result.unite(quads[i].boundingBox());
598 
599     if (FrameView* view = document()->view()) {
600         IntRect visibleContentRect = view->visibleContentRect();
601         result.move(-visibleContentRect.x(), -visibleContentRect.y());
602     }
603 
604     adjustFloatRectForAbsoluteZoom(result, renderer());
605     if (Page* page = document()->page()) {
606         if (Frame* frame = page->mainFrame())
607             adjustFloatRectForPageScale(result, frame->pageScaleFactor());
608     }
609 
610     return ClientRect::create(result);
611 }
612 
screenRect() const613 IntRect Element::screenRect() const
614 {
615     if (!renderer())
616         return IntRect();
617     return renderer()->view()->frameView()->contentsToScreen(renderer()->absoluteBoundingBoxRect());
618 }
619 
shouldIgnoreAttributeCase(const Element * e)620 static inline bool shouldIgnoreAttributeCase(const Element* e)
621 {
622     return e && e->document()->isHTMLDocument() && e->isHTMLElement();
623 }
624 
getAttribute(const String & name) const625 const AtomicString& Element::getAttribute(const String& name) const
626 {
627     bool ignoreCase = shouldIgnoreAttributeCase(this);
628 
629     // Update the 'style' attribute if it's invalid and being requested:
630     if (!isStyleAttributeValid() && equalPossiblyIgnoringCase(name, styleAttr.localName(), ignoreCase))
631         updateStyleAttribute();
632 
633 #if ENABLE(SVG)
634     if (!areSVGAttributesValid()) {
635         // We're not passing a namespace argument on purpose. SVGNames::*Attr are defined w/o namespaces as well.
636         updateAnimatedSVGAttribute(QualifiedName(nullAtom, name, nullAtom));
637     }
638 #endif
639 
640     if (m_attributeMap) {
641         if (Attribute* attribute = m_attributeMap->getAttributeItem(name, ignoreCase))
642             return attribute->value();
643     }
644 
645     return nullAtom;
646 }
647 
getAttributeNS(const String & namespaceURI,const String & localName) const648 const AtomicString& Element::getAttributeNS(const String& namespaceURI, const String& localName) const
649 {
650     return getAttribute(QualifiedName(nullAtom, localName, namespaceURI));
651 }
652 
setAttribute(const AtomicString & name,const AtomicString & value,ExceptionCode & ec)653 void Element::setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode& ec)
654 {
655     if (!Document::isValidName(name)) {
656         ec = INVALID_CHARACTER_ERR;
657         return;
658     }
659 
660 #if ENABLE(INSPECTOR)
661     if (!isSynchronizingStyleAttribute())
662         InspectorInstrumentation::willModifyDOMAttr(document(), this);
663 #endif
664 
665     const AtomicString& localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
666     QualifiedName attributeName(nullAtom, localName, nullAtom);
667 
668     // Allocate attribute map if necessary.
669     Attribute* old = attributes(false)->getAttributeItem(localName, false);
670 
671     document()->incDOMTreeVersion();
672 
673     if (isIdAttributeName(old ? old->name() : attributeName))
674         updateId(old ? old->value() : nullAtom, value);
675 
676     if (old && value.isNull())
677         m_attributeMap->removeAttribute(old->name());
678     else if (!old && !value.isNull())
679         m_attributeMap->addAttribute(createAttribute(attributeName, value));
680     else if (old && !value.isNull()) {
681         if (Attr* attrNode = old->attr())
682             attrNode->setValue(value);
683         else
684             old->setValue(value);
685         attributeChanged(old);
686     }
687 
688 #if ENABLE(INSPECTOR)
689     if (!isSynchronizingStyleAttribute())
690         InspectorInstrumentation::didModifyDOMAttr(document(), this);
691 #endif
692 }
693 
setAttribute(const QualifiedName & name,const AtomicString & value,ExceptionCode &)694 void Element::setAttribute(const QualifiedName& name, const AtomicString& value, ExceptionCode&)
695 {
696 #if ENABLE(INSPECTOR)
697     if (!isSynchronizingStyleAttribute())
698         InspectorInstrumentation::willModifyDOMAttr(document(), this);
699 #endif
700 
701     document()->incDOMTreeVersion();
702 
703     // Allocate attribute map if necessary.
704     Attribute* old = attributes(false)->getAttributeItem(name);
705 
706     if (isIdAttributeName(name))
707         updateId(old ? old->value() : nullAtom, value);
708 
709     if (old && value.isNull())
710         m_attributeMap->removeAttribute(name);
711     else if (!old && !value.isNull())
712         m_attributeMap->addAttribute(createAttribute(name, value));
713     else if (old) {
714         if (Attr* attrNode = old->attr())
715             attrNode->setValue(value);
716         else
717             old->setValue(value);
718         attributeChanged(old);
719     }
720 
721 #if ENABLE(INSPECTOR)
722     if (!isSynchronizingStyleAttribute())
723         InspectorInstrumentation::didModifyDOMAttr(document(), this);
724 #endif
725 }
726 
createAttribute(const QualifiedName & name,const AtomicString & value)727 PassRefPtr<Attribute> Element::createAttribute(const QualifiedName& name, const AtomicString& value)
728 {
729     return Attribute::create(name, value);
730 }
731 
attributeChanged(Attribute * attr,bool)732 void Element::attributeChanged(Attribute* attr, bool)
733 {
734     if (isIdAttributeName(attr->name()))
735         idAttributeChanged(attr);
736     recalcStyleIfNeededAfterAttributeChanged(attr);
737     updateAfterAttributeChanged(attr);
738 }
739 
updateAfterAttributeChanged(Attribute * attr)740 void Element::updateAfterAttributeChanged(Attribute* attr)
741 {
742     if (!AXObjectCache::accessibilityEnabled())
743         return;
744 
745     const QualifiedName& attrName = attr->name();
746     if (attrName == aria_activedescendantAttr) {
747         // any change to aria-activedescendant attribute triggers accessibility focus change, but document focus remains intact
748         document()->axObjectCache()->handleActiveDescendantChanged(renderer());
749     } else if (attrName == roleAttr) {
750         // the role attribute can change at any time, and the AccessibilityObject must pick up these changes
751         document()->axObjectCache()->handleAriaRoleChanged(renderer());
752     } else if (attrName == aria_valuenowAttr) {
753         // If the valuenow attribute changes, AX clients need to be notified.
754         document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXValueChanged, true);
755     } else if (attrName == aria_labelAttr || attrName == aria_labeledbyAttr || attrName == altAttr || attrName == titleAttr) {
756         // If the content of an element changes due to an attribute change, notify accessibility.
757         document()->axObjectCache()->contentChanged(renderer());
758     } else if (attrName == aria_selectedAttr)
759         document()->axObjectCache()->selectedChildrenChanged(renderer());
760     else if (attrName == aria_expandedAttr)
761         document()->axObjectCache()->handleAriaExpandedChange(renderer());
762     else if (attrName == aria_hiddenAttr)
763         document()->axObjectCache()->childrenChanged(renderer());
764     else if (attrName == aria_invalidAttr)
765         document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXInvalidStatusChanged, true);
766 }
767 
recalcStyleIfNeededAfterAttributeChanged(Attribute * attr)768 void Element::recalcStyleIfNeededAfterAttributeChanged(Attribute* attr)
769 {
770     if (document()->attached() && document()->styleSelector()->hasSelectorForAttribute(attr->name().localName()))
771         setNeedsStyleRecalc();
772 }
773 
idAttributeChanged(Attribute * attr)774 void Element::idAttributeChanged(Attribute* attr)
775 {
776     setHasID(!attr->isNull());
777     if (attributeMap()) {
778         if (attr->isNull())
779             attributeMap()->setIdForStyleResolution(nullAtom);
780         else if (document()->inQuirksMode())
781             attributeMap()->setIdForStyleResolution(attr->value().lower());
782         else
783             attributeMap()->setIdForStyleResolution(attr->value());
784     }
785     setNeedsStyleRecalc();
786 }
787 
788 // Returns true is the given attribute is an event handler.
789 // We consider an event handler any attribute that begins with "on".
790 // It is a simple solution that has the advantage of not requiring any
791 // code or configuration change if a new event handler is defined.
792 
isEventHandlerAttribute(const QualifiedName & name)793 static bool isEventHandlerAttribute(const QualifiedName& name)
794 {
795     return name.namespaceURI().isNull() && name.localName().startsWith("on");
796 }
797 
isAttributeToRemove(const QualifiedName & name,const AtomicString & value)798 static bool isAttributeToRemove(const QualifiedName& name, const AtomicString& value)
799 {
800     return (name.localName().endsWith(hrefAttr.localName()) || name == srcAttr || name == actionAttr) && protocolIsJavaScript(stripLeadingAndTrailingHTMLSpaces(value));
801 }
802 
setAttributeMap(PassRefPtr<NamedNodeMap> list,FragmentScriptingPermission scriptingPermission)803 void Element::setAttributeMap(PassRefPtr<NamedNodeMap> list, FragmentScriptingPermission scriptingPermission)
804 {
805     document()->incDOMTreeVersion();
806 
807     // If setting the whole map changes the id attribute, we need to call updateId.
808 
809     const QualifiedName& idName = document()->idAttributeName();
810     Attribute* oldId = m_attributeMap ? m_attributeMap->getAttributeItem(idName) : 0;
811     Attribute* newId = list ? list->getAttributeItem(idName) : 0;
812 
813     if (oldId || newId)
814         updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom);
815 
816     if (m_attributeMap)
817         m_attributeMap->m_element = 0;
818 
819     m_attributeMap = list;
820 
821     if (m_attributeMap) {
822         m_attributeMap->m_element = this;
823         // If the element is created as result of a paste or drag-n-drop operation
824         // we want to remove all the script and event handlers.
825         if (scriptingPermission == FragmentScriptingNotAllowed) {
826             unsigned i = 0;
827             while (i < m_attributeMap->length()) {
828                 const QualifiedName& attributeName = m_attributeMap->m_attributes[i]->name();
829                 if (isEventHandlerAttribute(attributeName)) {
830                     m_attributeMap->m_attributes.remove(i);
831                     continue;
832                 }
833 
834                 if (isAttributeToRemove(attributeName, m_attributeMap->m_attributes[i]->value()))
835                     m_attributeMap->m_attributes[i]->setValue(nullAtom);
836                 i++;
837             }
838         }
839         // Store the set of attributes that changed on the stack in case
840         // attributeChanged mutates m_attributeMap.
841         Vector<RefPtr<Attribute> > attributes;
842         m_attributeMap->copyAttributesToVector(attributes);
843         for (Vector<RefPtr<Attribute> >::iterator iter = attributes.begin(); iter != attributes.end(); ++iter)
844             attributeChanged(iter->get());
845         // FIXME: What about attributes that were in the old map that are not in the new map?
846     }
847 }
848 
hasAttributes() const849 bool Element::hasAttributes() const
850 {
851     if (!isStyleAttributeValid())
852         updateStyleAttribute();
853 
854 #if ENABLE(SVG)
855     if (!areSVGAttributesValid())
856         updateAnimatedSVGAttribute(anyQName());
857 #endif
858 
859     return m_attributeMap && m_attributeMap->length();
860 }
861 
nodeName() const862 String Element::nodeName() const
863 {
864     return m_tagName.toString();
865 }
866 
nodeNamePreservingCase() const867 String Element::nodeNamePreservingCase() const
868 {
869     return m_tagName.toString();
870 }
871 
setPrefix(const AtomicString & prefix,ExceptionCode & ec)872 void Element::setPrefix(const AtomicString& prefix, ExceptionCode& ec)
873 {
874     ec = 0;
875     checkSetPrefix(prefix, ec);
876     if (ec)
877         return;
878 
879     m_tagName.setPrefix(prefix.isEmpty() ? AtomicString() : prefix);
880 }
881 
baseURI() const882 KURL Element::baseURI() const
883 {
884     const AtomicString& baseAttribute = getAttribute(baseAttr);
885     KURL base(KURL(), baseAttribute);
886     if (!base.protocol().isEmpty())
887         return base;
888 
889     ContainerNode* parent = parentNode();
890     if (!parent)
891         return base;
892 
893     const KURL& parentBase = parent->baseURI();
894     if (parentBase.isNull())
895         return base;
896 
897     return KURL(parentBase, baseAttribute);
898 }
899 
createAttributeMap() const900 void Element::createAttributeMap() const
901 {
902     m_attributeMap = NamedNodeMap::create(const_cast<Element*>(this));
903 }
904 
isURLAttribute(Attribute *) const905 bool Element::isURLAttribute(Attribute*) const
906 {
907     return false;
908 }
909 
imageSourceAttributeName() const910 const QualifiedName& Element::imageSourceAttributeName() const
911 {
912     return srcAttr;
913 }
914 
createRenderer(RenderArena * arena,RenderStyle * style)915 RenderObject* Element::createRenderer(RenderArena* arena, RenderStyle* style)
916 {
917     if (document()->documentElement() == this && style->display() == NONE) {
918         // Ignore display: none on root elements.  Force a display of block in that case.
919         RenderBlock* result = new (arena) RenderBlock(this);
920         if (result)
921             result->setAnimatableStyle(style);
922         return result;
923     }
924     return RenderObject::createObject(this, style);
925 }
926 
wasChangedSinceLastFormControlChangeEvent() const927 bool Element::wasChangedSinceLastFormControlChangeEvent() const
928 {
929     return false;
930 }
931 
setChangedSinceLastFormControlChangeEvent(bool)932 void Element::setChangedSinceLastFormControlChangeEvent(bool)
933 {
934 }
935 
insertedIntoDocument()936 void Element::insertedIntoDocument()
937 {
938     // need to do superclass processing first so inDocument() is true
939     // by the time we reach updateId
940     ContainerNode::insertedIntoDocument();
941     if (Node* shadow = shadowRoot())
942         shadow->insertedIntoDocument();
943 
944     if (hasID()) {
945         if (m_attributeMap) {
946             Attribute* idItem = m_attributeMap->getAttributeItem(document()->idAttributeName());
947             if (idItem && !idItem->isNull())
948                 updateId(nullAtom, idItem->value());
949         }
950     }
951 }
952 
removedFromDocument()953 void Element::removedFromDocument()
954 {
955     if (hasID()) {
956         if (m_attributeMap) {
957             Attribute* idItem = m_attributeMap->getAttributeItem(document()->idAttributeName());
958             if (idItem && !idItem->isNull())
959                 updateId(idItem->value(), nullAtom);
960         }
961     }
962 
963     ContainerNode::removedFromDocument();
964     if (Node* shadow = shadowRoot())
965         shadow->removedFromDocument();
966 }
967 
insertedIntoTree(bool deep)968 void Element::insertedIntoTree(bool deep)
969 {
970     ContainerNode::insertedIntoTree(deep);
971     if (!deep)
972         return;
973     if (Node* shadow = shadowRoot())
974         shadow->insertedIntoTree(true);
975 }
976 
removedFromTree(bool deep)977 void Element::removedFromTree(bool deep)
978 {
979     ContainerNode::removedFromTree(deep);
980     if (!deep)
981         return;
982     if (Node* shadow = shadowRoot())
983         shadow->removedFromTree(true);
984 }
985 
attach()986 void Element::attach()
987 {
988     suspendPostAttachCallbacks();
989     RenderWidget::suspendWidgetHierarchyUpdates();
990 
991     createRendererIfNeeded();
992 
993     StyleSelectorParentPusher parentPusher(this);
994 
995     if (Node* shadow = shadowRoot()) {
996         parentPusher.push();
997         shadow->attach();
998     }
999 
1000     if (firstChild())
1001         parentPusher.push();
1002     ContainerNode::attach();
1003 
1004     if (hasRareData()) {
1005         ElementRareData* data = rareData();
1006         if (data->needsFocusAppearanceUpdateSoonAfterAttach()) {
1007             if (isFocusable() && document()->focusedNode() == this)
1008                 document()->updateFocusAppearanceSoon(false /* don't restore selection */);
1009             data->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
1010         }
1011     }
1012 
1013     RenderWidget::resumeWidgetHierarchyUpdates();
1014     resumePostAttachCallbacks();
1015 }
1016 
detach()1017 void Element::detach()
1018 {
1019     RenderWidget::suspendWidgetHierarchyUpdates();
1020 
1021     cancelFocusAppearanceUpdate();
1022     if (hasRareData())
1023         rareData()->resetComputedStyle();
1024     ContainerNode::detach();
1025     if (Node* shadow = shadowRoot())
1026         shadow->detach();
1027 
1028     RenderWidget::resumeWidgetHierarchyUpdates();
1029 }
1030 
pseudoStyleCacheIsInvalid(const RenderStyle * currentStyle,RenderStyle * newStyle)1031 bool Element::pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle)
1032 {
1033     ASSERT(currentStyle == renderStyle());
1034 
1035     if (!renderer() || !currentStyle)
1036         return false;
1037 
1038     const PseudoStyleCache* pseudoStyleCache = currentStyle->cachedPseudoStyles();
1039     if (!pseudoStyleCache)
1040         return false;
1041 
1042     size_t cacheSize = pseudoStyleCache->size();
1043     for (size_t i = 0; i < cacheSize; ++i) {
1044         RefPtr<RenderStyle> newPseudoStyle;
1045         PseudoId pseudoId = pseudoStyleCache->at(i)->styleType();
1046         if (pseudoId == VISITED_LINK) {
1047             newPseudoStyle =  newStyle->getCachedPseudoStyle(VISITED_LINK); // This pseudo-style was aggressively computed already when we first called styleForElement on the new style.
1048             if (!newPseudoStyle || *newPseudoStyle != *pseudoStyleCache->at(i))
1049                 return true;
1050         } else if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED)
1051             newPseudoStyle = renderer()->uncachedFirstLineStyle(newStyle);
1052         else
1053             newPseudoStyle = renderer()->getUncachedPseudoStyle(pseudoId, newStyle, newStyle);
1054         if (!newPseudoStyle)
1055             return true;
1056         if (*newPseudoStyle != *pseudoStyleCache->at(i)) {
1057             if (pseudoId < FIRST_INTERNAL_PSEUDOID)
1058                 newStyle->setHasPseudoStyle(pseudoId);
1059             newStyle->addCachedPseudoStyle(newPseudoStyle);
1060             if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED) {
1061                 // FIXME: We should do an actual diff to determine whether a repaint vs. layout
1062                 // is needed, but for now just assume a layout will be required.  The diff code
1063                 // in RenderObject::setStyle would need to be factored out so that it could be reused.
1064                 renderer()->setNeedsLayoutAndPrefWidthsRecalc();
1065             }
1066             return true;
1067         }
1068     }
1069     return false;
1070 }
1071 
1072 #ifdef ANDROID_STYLE_VERSION
displayDiff(const RenderStyle * s1,const RenderStyle * s2)1073 static bool displayDiff(const RenderStyle* s1, const RenderStyle* s2)
1074 {
1075     if (!s1 && !s2)
1076         return false;
1077     else if ((!s1 && s2) || (s1 && !s2))
1078         return true;
1079 
1080     return s1->display() != s2->display()
1081         || s1->left() != s2->left() || s1->top() != s2->top()
1082         || s1->right() != s2->right() || s1->bottom() != s2->bottom()
1083         || s1->width() != s2->width() || s1->height() != s2->height();
1084 }
1085 #endif
1086 
recalcStyle(StyleChange change)1087 void Element::recalcStyle(StyleChange change)
1088 {
1089     // Ref currentStyle in case it would otherwise be deleted when setRenderStyle() is called.
1090     RefPtr<RenderStyle> currentStyle(renderStyle());
1091     bool hasParentStyle = parentNodeForRenderingAndStyle() ? parentNodeForRenderingAndStyle()->renderStyle() : false;
1092     bool hasDirectAdjacentRules = currentStyle && currentStyle->childrenAffectedByDirectAdjacentRules();
1093 
1094     if ((change > NoChange || needsStyleRecalc())) {
1095 #ifdef ANDROID_STYLE_VERSION
1096         RefPtr<RenderStyle> newStyle = document()->styleForElementIgnoringPendingStylesheets(this);
1097         if (displayDiff(currentStyle.get(), newStyle.get()))
1098             document()->incStyleVersion();
1099 #endif
1100         if (hasRareData())
1101             rareData()->resetComputedStyle();
1102     }
1103     if (hasParentStyle && (change >= Inherit || needsStyleRecalc())) {
1104         RefPtr<RenderStyle> newStyle = document()->styleSelector()->styleForElement(this);
1105         StyleChange ch = diff(currentStyle.get(), newStyle.get());
1106         if (ch == Detach || !currentStyle) {
1107             if (attached())
1108                 detach();
1109             attach(); // FIXME: The style gets computed twice by calling attach. We could do better if we passed the style along.
1110             // attach recalulates the style for all children. No need to do it twice.
1111             clearNeedsStyleRecalc();
1112             clearChildNeedsStyleRecalc();
1113             return;
1114         }
1115 
1116         if (currentStyle) {
1117             // Preserve "affected by" bits that were propagated to us from descendants in the case where we didn't do a full
1118             // style change (e.g., only inline style changed).
1119             if (currentStyle->affectedByHoverRules())
1120                 newStyle->setAffectedByHoverRules(true);
1121             if (currentStyle->affectedByActiveRules())
1122                 newStyle->setAffectedByActiveRules(true);
1123             if (currentStyle->affectedByDragRules())
1124                 newStyle->setAffectedByDragRules(true);
1125             if (currentStyle->childrenAffectedByForwardPositionalRules())
1126                 newStyle->setChildrenAffectedByForwardPositionalRules();
1127             if (currentStyle->childrenAffectedByBackwardPositionalRules())
1128                 newStyle->setChildrenAffectedByBackwardPositionalRules();
1129             if (currentStyle->childrenAffectedByFirstChildRules())
1130                 newStyle->setChildrenAffectedByFirstChildRules();
1131             if (currentStyle->childrenAffectedByLastChildRules())
1132                 newStyle->setChildrenAffectedByLastChildRules();
1133             if (currentStyle->childrenAffectedByDirectAdjacentRules())
1134                 newStyle->setChildrenAffectedByDirectAdjacentRules();
1135         }
1136 
1137         if (ch != NoChange || pseudoStyleCacheIsInvalid(currentStyle.get(), newStyle.get()) || (change == Force && renderer() && renderer()->requiresForcedStyleRecalcPropagation())) {
1138             setRenderStyle(newStyle);
1139         } else if (needsStyleRecalc() && styleChangeType() != SyntheticStyleChange) {
1140             // Although no change occurred, we use the new style so that the cousin style sharing code won't get
1141             // fooled into believing this style is the same.
1142             if (renderer())
1143                 renderer()->setStyleInternal(newStyle.get());
1144             else
1145                 setRenderStyle(newStyle);
1146         } else if (styleChangeType() == SyntheticStyleChange)
1147              setRenderStyle(newStyle);
1148 
1149         if (change != Force) {
1150             // If "rem" units are used anywhere in the document, and if the document element's font size changes, then go ahead and force font updating
1151             // all the way down the tree.  This is simpler than having to maintain a cache of objects (and such font size changes should be rare anyway).
1152             if (document()->usesRemUnits() && ch != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize() && document()->documentElement() == this)
1153                 change = Force;
1154             else if (styleChangeType() >= FullStyleChange)
1155                 change = Force;
1156             else
1157                 change = ch;
1158         }
1159     }
1160     StyleSelectorParentPusher parentPusher(this);
1161     // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
1162     // For now we will just worry about the common case, since it's a lot trickier to get the second case right
1163     // without doing way too much re-resolution.
1164     bool forceCheckOfNextElementSibling = false;
1165     for (Node *n = firstChild(); n; n = n->nextSibling()) {
1166         bool childRulesChanged = n->needsStyleRecalc() && n->styleChangeType() == FullStyleChange;
1167         if (forceCheckOfNextElementSibling && n->isElementNode())
1168             n->setNeedsStyleRecalc();
1169         if (change >= Inherit || n->isTextNode() || n->childNeedsStyleRecalc() || n->needsStyleRecalc()) {
1170             parentPusher.push();
1171             n->recalcStyle(change);
1172         }
1173         if (n->isElementNode())
1174             forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
1175     }
1176     // FIXME: This does not care about sibling combinators. Will be necessary in XBL2 world.
1177     if (Node* shadow = shadowRoot()) {
1178         if (change >= Inherit || shadow->childNeedsStyleRecalc() || shadow->needsStyleRecalc()) {
1179             parentPusher.push();
1180             shadow->recalcStyle(change);
1181         }
1182     }
1183 
1184     clearNeedsStyleRecalc();
1185     clearChildNeedsStyleRecalc();
1186 }
1187 
shadowRoot() const1188 ContainerNode* Element::shadowRoot() const
1189 {
1190     return hasRareData() ? rareData()->m_shadowRoot : 0;
1191 }
1192 
ensureShadowRoot()1193 ContainerNode* Element::ensureShadowRoot()
1194 {
1195     if (ContainerNode* existingRoot = shadowRoot())
1196         return existingRoot;
1197 
1198     RefPtr<ShadowRoot> newRoot = ShadowRoot::create(document());
1199     ensureRareData()->m_shadowRoot = newRoot.get();
1200     newRoot->setShadowHost(this);
1201     if (inDocument())
1202         newRoot->insertedIntoDocument();
1203     if (attached())
1204         newRoot->lazyAttach();
1205     return newRoot.get();
1206 }
1207 
removeShadowRoot()1208 void Element::removeShadowRoot()
1209 {
1210     if (!hasRareData())
1211         return;
1212 
1213     ElementRareData* data = rareData();
1214     if (RefPtr<Node> oldRoot = data->m_shadowRoot) {
1215         data->m_shadowRoot = 0;
1216         document()->removeFocusedNodeOfSubtree(oldRoot.get());
1217         oldRoot->setShadowHost(0);
1218         if (oldRoot->inDocument())
1219             oldRoot->removedFromDocument();
1220         else
1221             oldRoot->removedFromTree(true);
1222     }
1223 }
1224 
childTypeAllowed(NodeType type) const1225 bool Element::childTypeAllowed(NodeType type) const
1226 {
1227     switch (type) {
1228     case ELEMENT_NODE:
1229     case TEXT_NODE:
1230     case COMMENT_NODE:
1231     case PROCESSING_INSTRUCTION_NODE:
1232     case CDATA_SECTION_NODE:
1233     case ENTITY_REFERENCE_NODE:
1234         return true;
1235     default:
1236         break;
1237     }
1238     return false;
1239 }
1240 
checkForEmptyStyleChange(Element * element,RenderStyle * style)1241 static void checkForEmptyStyleChange(Element* element, RenderStyle* style)
1242 {
1243     if (!style)
1244         return;
1245 
1246     if (style->affectedByEmpty() && (!style->emptyState() || element->hasChildNodes()))
1247         element->setNeedsStyleRecalc();
1248 }
1249 
checkForSiblingStyleChanges(Element * e,RenderStyle * style,bool finishedParsingCallback,Node * beforeChange,Node * afterChange,int childCountDelta)1250 static void checkForSiblingStyleChanges(Element* e, RenderStyle* style, bool finishedParsingCallback,
1251                                         Node* beforeChange, Node* afterChange, int childCountDelta)
1252 {
1253     if (!style || (e->needsStyleRecalc() && style->childrenAffectedByPositionalRules()))
1254         return;
1255 
1256     // :first-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
1257     // In the DOM case, we only need to do something if |afterChange| is not 0.
1258     // |afterChange| is 0 in the parser case, so it works out that we'll skip this block.
1259     if (style->childrenAffectedByFirstChildRules() && afterChange) {
1260         // Find our new first child.
1261         Node* newFirstChild = 0;
1262         for (newFirstChild = e->firstChild(); newFirstChild && !newFirstChild->isElementNode(); newFirstChild = newFirstChild->nextSibling()) {};
1263 
1264         // Find the first element node following |afterChange|
1265         Node* firstElementAfterInsertion = 0;
1266         for (firstElementAfterInsertion = afterChange;
1267              firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
1268              firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
1269 
1270         // This is the insert/append case.
1271         if (newFirstChild != firstElementAfterInsertion && firstElementAfterInsertion && firstElementAfterInsertion->attached() &&
1272             firstElementAfterInsertion->renderStyle() && firstElementAfterInsertion->renderStyle()->firstChildState())
1273             firstElementAfterInsertion->setNeedsStyleRecalc();
1274 
1275         // We also have to handle node removal.
1276         if (childCountDelta < 0 && newFirstChild == firstElementAfterInsertion && newFirstChild && newFirstChild->renderStyle() && !newFirstChild->renderStyle()->firstChildState())
1277             newFirstChild->setNeedsStyleRecalc();
1278     }
1279 
1280     // :last-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
1281     // In the DOM case, we only need to do something if |afterChange| is not 0.
1282     if (style->childrenAffectedByLastChildRules() && beforeChange) {
1283         // Find our new last child.
1284         Node* newLastChild = 0;
1285         for (newLastChild = e->lastChild(); newLastChild && !newLastChild->isElementNode(); newLastChild = newLastChild->previousSibling()) {};
1286 
1287         // Find the last element node going backwards from |beforeChange|
1288         Node* lastElementBeforeInsertion = 0;
1289         for (lastElementBeforeInsertion = beforeChange;
1290              lastElementBeforeInsertion && !lastElementBeforeInsertion->isElementNode();
1291              lastElementBeforeInsertion = lastElementBeforeInsertion->previousSibling()) {};
1292 
1293         if (newLastChild != lastElementBeforeInsertion && lastElementBeforeInsertion && lastElementBeforeInsertion->attached() &&
1294             lastElementBeforeInsertion->renderStyle() && lastElementBeforeInsertion->renderStyle()->lastChildState())
1295             lastElementBeforeInsertion->setNeedsStyleRecalc();
1296 
1297         // We also have to handle node removal.  The parser callback case is similar to node removal as well in that we need to change the last child
1298         // to match now.
1299         if ((childCountDelta < 0 || finishedParsingCallback) && newLastChild == lastElementBeforeInsertion && newLastChild && newLastChild->renderStyle() && !newLastChild->renderStyle()->lastChildState())
1300             newLastChild->setNeedsStyleRecalc();
1301     }
1302 
1303     // The + selector.  We need to invalidate the first element following the insertion point.  It is the only possible element
1304     // that could be affected by this DOM change.
1305     if (style->childrenAffectedByDirectAdjacentRules() && afterChange) {
1306         Node* firstElementAfterInsertion = 0;
1307         for (firstElementAfterInsertion = afterChange;
1308              firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
1309              firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
1310         if (firstElementAfterInsertion && firstElementAfterInsertion->attached())
1311             firstElementAfterInsertion->setNeedsStyleRecalc();
1312     }
1313 
1314     // Forward positional selectors include the ~ selector, nth-child, nth-of-type, first-of-type and only-of-type.
1315     // Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type.
1316     // We have to invalidate everything following the insertion point in the forward case, and everything before the insertion point in the
1317     // backward case.
1318     // |afterChange| is 0 in the parser callback case, so we won't do any work for the forward case if we don't have to.
1319     // For performance reasons we just mark the parent node as changed, since we don't want to make childrenChanged O(n^2) by crawling all our kids
1320     // here.  recalcStyle will then force a walk of the children when it sees that this has happened.
1321     if ((style->childrenAffectedByForwardPositionalRules() && afterChange) ||
1322         (style->childrenAffectedByBackwardPositionalRules() && beforeChange))
1323         e->setNeedsStyleRecalc();
1324 
1325     // :empty selector.
1326     checkForEmptyStyleChange(e, style);
1327 }
1328 
childrenChanged(bool changedByParser,Node * beforeChange,Node * afterChange,int childCountDelta)1329 void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
1330 {
1331     ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
1332     if (changedByParser)
1333         checkForEmptyStyleChange(this, renderStyle());
1334     else
1335         checkForSiblingStyleChanges(this, renderStyle(), false, beforeChange, afterChange, childCountDelta);
1336 }
1337 
beginParsingChildren()1338 void Element::beginParsingChildren()
1339 {
1340     clearIsParsingChildrenFinished();
1341     CSSStyleSelector* styleSelector = document()->styleSelectorIfExists();
1342     if (styleSelector && attached())
1343         styleSelector->pushParent(this);
1344 }
1345 
finishParsingChildren()1346 void Element::finishParsingChildren()
1347 {
1348     ContainerNode::finishParsingChildren();
1349     setIsParsingChildrenFinished();
1350     checkForSiblingStyleChanges(this, renderStyle(), true, lastChild(), 0, 0);
1351     if (CSSStyleSelector* styleSelector = document()->styleSelectorIfExists())
1352         styleSelector->popParent(this);
1353 }
1354 
dispatchAttrRemovalEvent(Attribute *)1355 void Element::dispatchAttrRemovalEvent(Attribute*)
1356 {
1357     ASSERT(!eventDispatchForbidden());
1358 
1359 #if 0
1360     if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
1361         return;
1362     ExceptionCode ec = 0;
1363     dispatchScopedEvent(MutationEvent::create(DOMAttrModifiedEvent, true, attr, attr->value(),
1364         attr->value(), document()->attrName(attr->id()), MutationEvent::REMOVAL), ec);
1365 #endif
1366 }
1367 
dispatchAttrAdditionEvent(Attribute *)1368 void Element::dispatchAttrAdditionEvent(Attribute*)
1369 {
1370     ASSERT(!eventDispatchForbidden());
1371 
1372 #if 0
1373     if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
1374         return;
1375     ExceptionCode ec = 0;
1376     dispatchScopedEvent(MutationEvent::create(DOMAttrModifiedEvent, true, attr, attr->value(),
1377         attr->value(), document()->attrName(attr->id()), MutationEvent::ADDITION), ec);
1378 #endif
1379 }
1380 
openTagStartToString() const1381 String Element::openTagStartToString() const
1382 {
1383     String result = "<" + nodeName();
1384 
1385     NamedNodeMap* attrMap = attributes(true);
1386 
1387     if (attrMap) {
1388         unsigned numAttrs = attrMap->length();
1389         for (unsigned i = 0; i < numAttrs; i++) {
1390             result += " ";
1391 
1392             Attribute *attribute = attrMap->attributeItem(i);
1393             result += attribute->name().toString();
1394             if (!attribute->value().isNull()) {
1395                 result += "=\"";
1396                 // FIXME: substitute entities for any instances of " or '
1397                 result += attribute->value();
1398                 result += "\"";
1399             }
1400         }
1401     }
1402 
1403     return result;
1404 }
1405 
1406 #ifndef NDEBUG
formatForDebugger(char * buffer,unsigned length) const1407 void Element::formatForDebugger(char* buffer, unsigned length) const
1408 {
1409     String result;
1410     String s;
1411 
1412     s = nodeName();
1413     if (s.length() > 0) {
1414         result += s;
1415     }
1416 
1417     s = getIdAttribute();
1418     if (s.length() > 0) {
1419         if (result.length() > 0)
1420             result += "; ";
1421         result += "id=";
1422         result += s;
1423     }
1424 
1425     s = getAttribute(classAttr);
1426     if (s.length() > 0) {
1427         if (result.length() > 0)
1428             result += "; ";
1429         result += "class=";
1430         result += s;
1431     }
1432 
1433     strncpy(buffer, result.utf8().data(), length - 1);
1434 }
1435 #endif
1436 
setAttributeNode(Attr * attr,ExceptionCode & ec)1437 PassRefPtr<Attr> Element::setAttributeNode(Attr* attr, ExceptionCode& ec)
1438 {
1439     if (!attr) {
1440         ec = TYPE_MISMATCH_ERR;
1441         return 0;
1442     }
1443     return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));
1444 }
1445 
setAttributeNodeNS(Attr * attr,ExceptionCode & ec)1446 PassRefPtr<Attr> Element::setAttributeNodeNS(Attr* attr, ExceptionCode& ec)
1447 {
1448     if (!attr) {
1449         ec = TYPE_MISMATCH_ERR;
1450         return 0;
1451     }
1452     return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));
1453 }
1454 
removeAttributeNode(Attr * attr,ExceptionCode & ec)1455 PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionCode& ec)
1456 {
1457     if (!attr) {
1458         ec = TYPE_MISMATCH_ERR;
1459         return 0;
1460     }
1461     if (attr->ownerElement() != this) {
1462         ec = NOT_FOUND_ERR;
1463         return 0;
1464     }
1465 
1466     ASSERT(document() == attr->document());
1467 
1468     NamedNodeMap* attrs = attributes(true);
1469     if (!attrs)
1470         return 0;
1471 
1472     return static_pointer_cast<Attr>(attrs->removeNamedItem(attr->qualifiedName(), ec));
1473 }
1474 
setAttributeNS(const AtomicString & namespaceURI,const AtomicString & qualifiedName,const AtomicString & value,ExceptionCode & ec,FragmentScriptingPermission scriptingPermission)1475 void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode& ec, FragmentScriptingPermission scriptingPermission)
1476 {
1477     String prefix, localName;
1478     if (!Document::parseQualifiedName(qualifiedName, prefix, localName, ec))
1479         return;
1480 
1481     if (namespaceURI.isNull() && !prefix.isNull()) {
1482         ec = NAMESPACE_ERR;
1483         return;
1484     }
1485 
1486     QualifiedName qName(prefix, localName, namespaceURI);
1487 
1488     if (scriptingPermission == FragmentScriptingNotAllowed && (isEventHandlerAttribute(qName) || isAttributeToRemove(qName, value)))
1489         return;
1490 
1491     setAttribute(qName, value, ec);
1492 }
1493 
removeAttribute(const String & name,ExceptionCode & ec)1494 void Element::removeAttribute(const String& name, ExceptionCode& ec)
1495 {
1496     InspectorInstrumentation::willModifyDOMAttr(document(), this);
1497 
1498     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
1499 
1500     if (m_attributeMap) {
1501         m_attributeMap->removeNamedItem(localName, ec);
1502         if (ec == NOT_FOUND_ERR)
1503             ec = 0;
1504     }
1505 
1506     InspectorInstrumentation::didModifyDOMAttr(document(), this);
1507 }
1508 
removeAttributeNS(const String & namespaceURI,const String & localName,ExceptionCode & ec)1509 void Element::removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode& ec)
1510 {
1511     removeAttribute(QualifiedName(nullAtom, localName, namespaceURI), ec);
1512 }
1513 
getAttributeNode(const String & name)1514 PassRefPtr<Attr> Element::getAttributeNode(const String& name)
1515 {
1516     NamedNodeMap* attrs = attributes(true);
1517     if (!attrs)
1518         return 0;
1519     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
1520     return static_pointer_cast<Attr>(attrs->getNamedItem(localName));
1521 }
1522 
getAttributeNodeNS(const String & namespaceURI,const String & localName)1523 PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const String& localName)
1524 {
1525     NamedNodeMap* attrs = attributes(true);
1526     if (!attrs)
1527         return 0;
1528     return static_pointer_cast<Attr>(attrs->getNamedItem(QualifiedName(nullAtom, localName, namespaceURI)));
1529 }
1530 
hasAttribute(const String & name) const1531 bool Element::hasAttribute(const String& name) const
1532 {
1533     NamedNodeMap* attrs = attributes(true);
1534     if (!attrs)
1535         return false;
1536 
1537     // This call to String::lower() seems to be required but
1538     // there may be a way to remove it.
1539     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
1540     return attrs->getAttributeItem(localName, false);
1541 }
1542 
hasAttributeNS(const String & namespaceURI,const String & localName) const1543 bool Element::hasAttributeNS(const String& namespaceURI, const String& localName) const
1544 {
1545     NamedNodeMap* attrs = attributes(true);
1546     if (!attrs)
1547         return false;
1548     return attrs->getAttributeItem(QualifiedName(nullAtom, localName, namespaceURI));
1549 }
1550 
style()1551 CSSStyleDeclaration *Element::style()
1552 {
1553     return 0;
1554 }
1555 
focus(bool restorePreviousSelection)1556 void Element::focus(bool restorePreviousSelection)
1557 {
1558     if (!inDocument())
1559         return;
1560 
1561     Document* doc = document();
1562     if (doc->focusedNode() == this)
1563         return;
1564 
1565     // If the stylesheets have already been loaded we can reliably check isFocusable.
1566     // If not, we continue and set the focused node on the focus controller below so
1567     // that it can be updated soon after attach.
1568     if (doc->haveStylesheetsLoaded()) {
1569         doc->updateLayoutIgnorePendingStylesheets();
1570         if (!isFocusable())
1571             return;
1572     }
1573 
1574     if (!supportsFocus())
1575         return;
1576 
1577     RefPtr<Node> protect;
1578     if (Page* page = doc->page()) {
1579         // Focus and change event handlers can cause us to lose our last ref.
1580         // If a focus event handler changes the focus to a different node it
1581         // does not make sense to continue and update appearence.
1582         protect = this;
1583         if (!page->focusController()->setFocusedNode(this, doc->frame()))
1584             return;
1585     }
1586 
1587     // Setting the focused node above might have invalidated the layout due to scripts.
1588     doc->updateLayoutIgnorePendingStylesheets();
1589 
1590     if (!isFocusable()) {
1591         ensureRareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(true);
1592         return;
1593     }
1594 
1595     cancelFocusAppearanceUpdate();
1596     updateFocusAppearance(restorePreviousSelection);
1597 }
1598 
updateFocusAppearance(bool)1599 void Element::updateFocusAppearance(bool /*restorePreviousSelection*/)
1600 {
1601     if (this == rootEditableElement()) {
1602         Frame* frame = document()->frame();
1603         if (!frame)
1604             return;
1605 
1606         // When focusing an editable element in an iframe, don't reset the selection if it already contains a selection.
1607         if (this == frame->selection()->rootEditableElement())
1608             return;
1609 
1610         // FIXME: We should restore the previous selection if there is one.
1611         VisibleSelection newSelection = VisibleSelection(firstPositionInOrBeforeNode(this), DOWNSTREAM);
1612 
1613         if (frame->selection()->shouldChangeSelection(newSelection)) {
1614             frame->selection()->setSelection(newSelection);
1615             frame->selection()->revealSelection();
1616         }
1617     } else if (renderer() && !renderer()->isWidget())
1618         renderer()->enclosingLayer()->scrollRectToVisible(getRect());
1619 }
1620 
blur()1621 void Element::blur()
1622 {
1623     cancelFocusAppearanceUpdate();
1624     Document* doc = document();
1625     if (doc->focusedNode() == this) {
1626         if (doc->frame())
1627             doc->frame()->page()->focusController()->setFocusedNode(0, doc->frame());
1628         else
1629             doc->setFocusedNode(0);
1630     }
1631 }
1632 
innerText() const1633 String Element::innerText() const
1634 {
1635     // We need to update layout, since plainText uses line boxes in the render tree.
1636     document()->updateLayoutIgnorePendingStylesheets();
1637 
1638     if (!renderer())
1639         return textContent(true);
1640 
1641     return plainText(rangeOfContents(const_cast<Element*>(this)).get());
1642 }
1643 
outerText() const1644 String Element::outerText() const
1645 {
1646     // Getting outerText is the same as getting innerText, only
1647     // setting is different. You would think this should get the plain
1648     // text for the outer range, but this is wrong, <br> for instance
1649     // would return different values for inner and outer text by such
1650     // a rule, but it doesn't in WinIE, and we want to match that.
1651     return innerText();
1652 }
1653 
title() const1654 String Element::title() const
1655 {
1656     return String();
1657 }
1658 
minimumSizeForResizing() const1659 IntSize Element::minimumSizeForResizing() const
1660 {
1661     return hasRareData() ? rareData()->m_minimumSizeForResizing : defaultMinimumSizeForResizing();
1662 }
1663 
setMinimumSizeForResizing(const IntSize & size)1664 void Element::setMinimumSizeForResizing(const IntSize& size)
1665 {
1666     if (size == defaultMinimumSizeForResizing() && !hasRareData())
1667         return;
1668     ensureRareData()->m_minimumSizeForResizing = size;
1669 }
1670 
computedStyle(PseudoId pseudoElementSpecifier)1671 RenderStyle* Element::computedStyle(PseudoId pseudoElementSpecifier)
1672 {
1673     // FIXME: Find and use the renderer from the pseudo element instead of the actual element so that the 'length'
1674     // properties, which are only known by the renderer because it did the layout, will be correct and so that the
1675     // values returned for the ":selection" pseudo-element will be correct.
1676     if (RenderStyle* usedStyle = renderStyle())
1677         return pseudoElementSpecifier ? usedStyle->getCachedPseudoStyle(pseudoElementSpecifier) : usedStyle;
1678 
1679     if (!attached())
1680         // FIXME: Try to do better than this. Ensure that styleForElement() works for elements that are not in the
1681         // document tree and figure out when to destroy the computed style for such elements.
1682         return 0;
1683 
1684     ElementRareData* data = ensureRareData();
1685     if (!data->m_computedStyle)
1686         data->m_computedStyle = document()->styleForElementIgnoringPendingStylesheets(this);
1687     return pseudoElementSpecifier ? data->m_computedStyle->getCachedPseudoStyle(pseudoElementSpecifier) : data->m_computedStyle.get();
1688 }
1689 
computeInheritedLanguage() const1690 AtomicString Element::computeInheritedLanguage() const
1691 {
1692     const Node* n = this;
1693     AtomicString value;
1694     // The language property is inherited, so we iterate over the parents to find the first language.
1695     while (n && value.isNull()) {
1696         if (n->isElementNode()) {
1697             // Spec: xml:lang takes precedence -- http://www.w3.org/TR/xhtml1/#C_7
1698             value = static_cast<const Element*>(n)->fastGetAttribute(XMLNames::langAttr);
1699             if (value.isNull())
1700                 value = static_cast<const Element*>(n)->fastGetAttribute(HTMLNames::langAttr);
1701         } else if (n->isDocumentNode()) {
1702             // checking the MIME content-language
1703             value = static_cast<const Document*>(n)->contentLanguage();
1704         }
1705 
1706         n = n->parentNode();
1707     }
1708 
1709     return value;
1710 }
1711 
cancelFocusAppearanceUpdate()1712 void Element::cancelFocusAppearanceUpdate()
1713 {
1714     if (hasRareData())
1715         rareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
1716     if (document()->focusedNode() == this)
1717         document()->cancelFocusAppearanceUpdate();
1718 }
1719 
normalizeAttributes()1720 void Element::normalizeAttributes()
1721 {
1722     // Normalize attributes.
1723     NamedNodeMap* attrs = attributes(true);
1724     if (!attrs)
1725         return;
1726 
1727     if (attrs->isEmpty())
1728         return;
1729 
1730     Vector<RefPtr<Attribute> > attributeVector;
1731     attrs->copyAttributesToVector(attributeVector);
1732     size_t numAttrs = attributeVector.size();
1733     for (size_t i = 0; i < numAttrs; ++i) {
1734         if (Attr* attr = attributeVector[i]->attr())
1735             attr->normalize();
1736     }
1737 }
1738 
1739 // ElementTraversal API
firstElementChild() const1740 Element* Element::firstElementChild() const
1741 {
1742     return WebCore::firstElementChild(this);
1743 }
1744 
lastElementChild() const1745 Element* Element::lastElementChild() const
1746 {
1747     Node* n = lastChild();
1748     while (n && !n->isElementNode())
1749         n = n->previousSibling();
1750     return static_cast<Element*>(n);
1751 }
1752 
previousElementSibling() const1753 Element* Element::previousElementSibling() const
1754 {
1755     Node* n = previousSibling();
1756     while (n && !n->isElementNode())
1757         n = n->previousSibling();
1758     return static_cast<Element*>(n);
1759 }
1760 
nextElementSibling() const1761 Element* Element::nextElementSibling() const
1762 {
1763     Node* n = nextSibling();
1764     while (n && !n->isElementNode())
1765         n = n->nextSibling();
1766     return static_cast<Element*>(n);
1767 }
1768 
childElementCount() const1769 unsigned Element::childElementCount() const
1770 {
1771     unsigned count = 0;
1772     Node* n = firstChild();
1773     while (n) {
1774         count += n->isElementNode();
1775         n = n->nextSibling();
1776     }
1777     return count;
1778 }
1779 
webkitMatchesSelector(const String & selector,ExceptionCode & ec)1780 bool Element::webkitMatchesSelector(const String& selector, ExceptionCode& ec)
1781 {
1782     if (selector.isEmpty()) {
1783         ec = SYNTAX_ERR;
1784         return false;
1785     }
1786 
1787     bool strictParsing = !document()->inQuirksMode();
1788     CSSParser p(strictParsing);
1789 
1790     CSSSelectorList selectorList;
1791     p.parseSelector(selector, document(), selectorList);
1792 
1793     if (!selectorList.first()) {
1794         ec = SYNTAX_ERR;
1795         return false;
1796     }
1797 
1798     // Throw a NAMESPACE_ERR if the selector includes any namespace prefixes.
1799     if (selectorList.selectorsNeedNamespaceResolution()) {
1800         ec = NAMESPACE_ERR;
1801         return false;
1802     }
1803 
1804     CSSStyleSelector::SelectorChecker selectorChecker(document(), strictParsing);
1805     for (CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
1806         if (selectorChecker.checkSelector(selector, this))
1807             return true;
1808     }
1809 
1810     return false;
1811 }
1812 
classList()1813 DOMTokenList* Element::classList()
1814 {
1815     ElementRareData* data = ensureRareData();
1816     if (!data->m_classList)
1817         data->m_classList = ClassList::create(this);
1818     return data->m_classList.get();
1819 }
1820 
optionalClassList() const1821 DOMTokenList* Element::optionalClassList() const
1822 {
1823     if (!hasRareData())
1824         return 0;
1825     return rareData()->m_classList.get();
1826 }
1827 
dataset()1828 DOMStringMap* Element::dataset()
1829 {
1830     ElementRareData* data = ensureRareData();
1831     if (!data->m_datasetDOMStringMap)
1832         data->m_datasetDOMStringMap = DatasetDOMStringMap::create(this);
1833     return data->m_datasetDOMStringMap.get();
1834 }
1835 
optionalDataset() const1836 DOMStringMap* Element::optionalDataset() const
1837 {
1838     if (!hasRareData())
1839         return 0;
1840     return rareData()->m_datasetDOMStringMap.get();
1841 }
1842 
getURLAttribute(const QualifiedName & name) const1843 KURL Element::getURLAttribute(const QualifiedName& name) const
1844 {
1845 #if !ASSERT_DISABLED
1846     if (m_attributeMap) {
1847         if (Attribute* attribute = m_attributeMap->getAttributeItem(name))
1848             ASSERT(isURLAttribute(attribute));
1849     }
1850 #endif
1851     return document()->completeURL(stripLeadingAndTrailingHTMLSpaces(getAttribute(name)));
1852 }
1853 
getNonEmptyURLAttribute(const QualifiedName & name) const1854 KURL Element::getNonEmptyURLAttribute(const QualifiedName& name) const
1855 {
1856 #if !ASSERT_DISABLED
1857     if (m_attributeMap) {
1858         if (Attribute* attribute = m_attributeMap->getAttributeItem(name))
1859             ASSERT(isURLAttribute(attribute));
1860     }
1861 #endif
1862     String value = stripLeadingAndTrailingHTMLSpaces(getAttribute(name));
1863     if (value.isEmpty())
1864         return KURL();
1865     return document()->completeURL(value);
1866 }
1867 
getIntegralAttribute(const QualifiedName & attributeName) const1868 int Element::getIntegralAttribute(const QualifiedName& attributeName) const
1869 {
1870     return getAttribute(attributeName).string().toInt();
1871 }
1872 
setIntegralAttribute(const QualifiedName & attributeName,int value)1873 void Element::setIntegralAttribute(const QualifiedName& attributeName, int value)
1874 {
1875     // FIXME: Need an AtomicString version of String::number.
1876     ExceptionCode ec;
1877     setAttribute(attributeName, String::number(value), ec);
1878 }
1879 
getUnsignedIntegralAttribute(const QualifiedName & attributeName) const1880 unsigned Element::getUnsignedIntegralAttribute(const QualifiedName& attributeName) const
1881 {
1882     return getAttribute(attributeName).string().toUInt();
1883 }
1884 
setUnsignedIntegralAttribute(const QualifiedName & attributeName,unsigned value)1885 void Element::setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value)
1886 {
1887     // FIXME: Need an AtomicString version of String::number.
1888     ExceptionCode ec;
1889     setAttribute(attributeName, String::number(value), ec);
1890 }
1891 
1892 #if ENABLE(SVG)
childShouldCreateRenderer(Node * child) const1893 bool Element::childShouldCreateRenderer(Node* child) const
1894 {
1895     // Only create renderers for SVG elements whose parents are SVG elements, or for proper <svg xmlns="svgNS"> subdocuments.
1896     if (child->isSVGElement())
1897         return child->hasTagName(SVGNames::svgTag) || isSVGElement();
1898 
1899     return Node::childShouldCreateRenderer(child);
1900 }
1901 #endif
1902 
1903 #if ENABLE(FULLSCREEN_API)
webkitRequestFullScreen(unsigned short flags)1904 void Element::webkitRequestFullScreen(unsigned short flags)
1905 {
1906     document()->webkitRequestFullScreenForElement(this, flags);
1907 }
1908 #endif
1909 
spellcheckAttributeState() const1910 SpellcheckAttributeState Element::spellcheckAttributeState() const
1911 {
1912     if (!hasAttribute(HTMLNames::spellcheckAttr))
1913         return SpellcheckAttributeDefault;
1914 
1915     const AtomicString& value = getAttribute(HTMLNames::spellcheckAttr);
1916     if (equalIgnoringCase(value, "true") || equalIgnoringCase(value, ""))
1917         return SpellcheckAttributeTrue;
1918     if (equalIgnoringCase(value, "false"))
1919         return SpellcheckAttributeFalse;
1920 
1921     return SpellcheckAttributeDefault;
1922 }
1923 
isSpellCheckingEnabled() const1924 bool Element::isSpellCheckingEnabled() const
1925 {
1926     const Element* element = this;
1927     while (element) {
1928         switch (element->spellcheckAttributeState()) {
1929         case SpellcheckAttributeTrue:
1930             return true;
1931         case SpellcheckAttributeFalse:
1932             return false;
1933         case SpellcheckAttributeDefault:
1934             break;
1935         }
1936 
1937         ContainerNode* parent = const_cast<Element*>(element)->parentOrHostNode();
1938         element = (parent && parent->isElementNode()) ? toElement(parent) : 0;
1939     }
1940 
1941     return true;
1942 }
1943 
webkitGetAnimations() const1944 PassRefPtr<WebKitAnimationList> Element::webkitGetAnimations() const
1945 {
1946     if (!renderer())
1947         return 0;
1948 
1949     AnimationController* animController = renderer()->animation();
1950 
1951     if (!animController)
1952         return 0;
1953 
1954     return animController->animationsForRenderer(renderer());
1955 }
1956 
1957 } // namespace WebCore
1958