adbb720110e44431059d29568a7fa97316b5d909
[WebKit-https.git] / WebCore / dom / Element.cpp
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 "ClientRect.h"
35 #include "ClientRectList.h"
36 #include "Document.h"
37 #include "DocumentFragment.h"
38 #include "ElementRareData.h"
39 #include "ExceptionCode.h"
40 #include "FocusController.h"
41 #include "Frame.h"
42 #include "FrameView.h"
43 #include "HTMLElement.h"
44 #include "HTMLNames.h"
45 #include "InspectorController.h"
46 #include "NodeList.h"
47 #include "NodeRenderStyle.h"
48 #include "Page.h"
49 #include "RenderLayer.h"
50 #include "RenderView.h"
51 #include "RenderWidget.h"
52 #include "TextIterator.h"
53 #include "XMLNames.h"
54 #include <wtf/text/CString.h>
55
56 #if ENABLE(SVG)
57 #include "SVGNames.h"
58 #endif
59
60 namespace WebCore {
61
62 using namespace HTMLNames;
63 using namespace XMLNames;
64     
65 PassRefPtr<Element> Element::create(const QualifiedName& tagName, Document* document)
66 {
67     return adoptRef(new Element(tagName, document, CreateElement));
68 }
69
70 Element::~Element()
71 {
72     if (namedAttrMap)
73         namedAttrMap->detachFromElement();
74 }
75
76 inline ElementRareData* Element::rareData() const
77 {
78     ASSERT(hasRareData());
79     return static_cast<ElementRareData*>(NodeRareData::rareDataFromMap(this));
80 }
81     
82 inline ElementRareData* Element::ensureRareData()
83 {
84     return static_cast<ElementRareData*>(Node::ensureRareData());
85 }
86     
87 NodeRareData* Element::createRareData()
88 {
89     return new ElementRareData;
90 }
91
92 PassRefPtr<DocumentFragment> Element::createContextualFragment(const String& markup, FragmentScriptingPermission scriptingPermission)
93 {
94     RefPtr<DocumentFragment> fragment = document()->createDocumentFragment();
95
96     if (document()->isHTMLDocument())
97         fragment->parseHTML(markup, scriptingPermission);
98     else {
99         if (!fragment->parseXML(markup, this, scriptingPermission))
100             // FIXME: We should propagate a syntax error exception out here.
101             return 0;
102     }
103     
104     // Exceptions are ignored because none ought to happen here.
105     ExceptionCode ignoredExceptionCode;
106     
107     // We need to pop <html> and <body> elements and remove <head> to
108     // accommodate folks passing complete HTML documents to make the
109     // child of an element.
110     
111     RefPtr<Node> nextNode;
112     for (RefPtr<Node> node = fragment->firstChild(); node; node = nextNode) {
113         nextNode = node->nextSibling();
114         if (node->hasTagName(htmlTag) || node->hasTagName(bodyTag)) {
115             Node* firstChild = node->firstChild();
116             if (firstChild)
117                 nextNode = firstChild;
118             RefPtr<Node> nextChild;
119             for (RefPtr<Node> child = firstChild; child; child = nextChild) {
120                 nextChild = child->nextSibling();
121                 node->removeChild(child.get(), ignoredExceptionCode);
122                 ASSERT(!ignoredExceptionCode);
123                 fragment->insertBefore(child, node.get(), ignoredExceptionCode);
124                 ASSERT(!ignoredExceptionCode);
125             }
126             fragment->removeChild(node.get(), ignoredExceptionCode);
127             ASSERT(!ignoredExceptionCode);
128         } else if (node->hasTagName(headTag)) {
129             fragment->removeChild(node.get(), ignoredExceptionCode);
130             ASSERT(!ignoredExceptionCode);
131         }
132     }
133     
134     return fragment.release();
135 }
136     
137 PassRefPtr<Node> Element::cloneNode(bool deep)
138 {
139     return deep ? cloneElementWithChildren() : cloneElementWithoutChildren();
140 }
141
142 PassRefPtr<Element> Element::cloneElementWithChildren()
143 {
144     RefPtr<Element> clone = cloneElementWithoutChildren();
145     cloneChildNodes(clone.get());
146     return clone.release();
147 }
148
149 PassRefPtr<Element> Element::cloneElementWithoutChildren()
150 {
151     RefPtr<Element> clone = document()->createElement(tagQName(), false);
152     // This will catch HTML elements in the wrong namespace that are not correctly copied.
153     // This is a sanity check as HTML overloads some of the DOM methods.
154     ASSERT(isHTMLElement() == clone->isHTMLElement());
155
156     // Clone attributes.
157     if (namedAttrMap)
158         clone->attributes()->setAttributes(*attributes(true)); // Call attributes(true) to force attribute synchronization to occur (for svg and style) before cloning happens.
159     
160     clone->copyNonAttributeProperties(this);
161
162     return clone.release();
163 }
164
165 void Element::removeAttribute(const QualifiedName& name, ExceptionCode& ec)
166 {
167     if (namedAttrMap) {
168         ec = 0;
169         namedAttrMap->removeNamedItem(name, ec);
170         if (ec == NOT_FOUND_ERR)
171             ec = 0;
172     }
173 }
174
175 void Element::setAttribute(const QualifiedName& name, const AtomicString& value)
176 {
177     ExceptionCode ec;
178     setAttribute(name, value, ec);
179 }
180     
181 void Element::setCStringAttribute(const QualifiedName& name, const char* cStringValue)
182 {
183     ExceptionCode ec;
184     setAttribute(name, AtomicString(cStringValue), ec);
185 }
186
187 void Element::setBooleanAttribute(const QualifiedName& name, bool b)
188 {
189     if (b)
190         setAttribute(name, emptyAtom);
191     else {
192         ExceptionCode ex;
193         removeAttribute(name, ex);
194     }
195 }
196
197 // Virtual function, defined in base class.
198 NamedNodeMap* Element::attributes() const
199 {
200     return attributes(false);
201 }
202
203 Node::NodeType Element::nodeType() const
204 {
205     return ELEMENT_NODE;
206 }
207
208 bool Element::hasAttribute(const QualifiedName& name) const
209 {
210     return hasAttributeNS(name.namespaceURI(), name.localName());
211 }
212
213 const AtomicString& Element::getAttribute(const QualifiedName& name) const
214 {
215     if (UNLIKELY(name == styleAttr) && !isStyleAttributeValid())
216         updateStyleAttribute();
217
218 #if ENABLE(SVG)
219     if (UNLIKELY(!areSVGAttributesValid()))
220         updateAnimatedSVGAttribute(name);
221 #endif
222
223     return fastGetAttribute(name);
224 }
225
226 void Element::scrollIntoView(bool alignToTop) 
227 {
228     document()->updateLayoutIgnorePendingStylesheets();
229     IntRect bounds = getRect();    
230     if (renderer()) {
231         // Align to the top / bottom and to the closest edge.
232         if (alignToTop)
233             renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
234         else
235             renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignBottomAlways);
236     }
237 }
238
239 void Element::scrollIntoViewIfNeeded(bool centerIfNeeded)
240 {
241     document()->updateLayoutIgnorePendingStylesheets();
242     IntRect bounds = getRect();    
243     if (renderer()) {
244         if (centerIfNeeded)
245             renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
246         else
247             renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
248     }
249 }
250
251 void Element::scrollByUnits(int units, ScrollGranularity granularity)
252 {
253     document()->updateLayoutIgnorePendingStylesheets();
254     if (RenderObject *rend = renderer()) {
255         if (rend->hasOverflowClip()) {
256             ScrollDirection direction = ScrollDown;
257             if (units < 0) {
258                 direction = ScrollUp;
259                 units = -units;
260             }
261             toRenderBox(rend)->layer()->scroll(direction, granularity, units);
262         }
263     }
264 }
265
266 void Element::scrollByLines(int lines)
267 {
268     scrollByUnits(lines, ScrollByLine);
269 }
270
271 void Element::scrollByPages(int pages)
272 {
273     scrollByUnits(pages, ScrollByPage);
274 }
275
276 static float localZoomForRenderer(RenderObject* renderer)
277 {
278     // FIXME: This does the wrong thing if two opposing zooms are in effect and canceled each
279     // other out, but the alternative is that we'd have to crawl up the whole render tree every
280     // time (or store an additional bit in the RenderStyle to indicate that a zoom was specified).
281     float zoomFactor = 1.0f;
282     if (renderer->style()->effectiveZoom() != 1.0f) {
283         // Need to find the nearest enclosing RenderObject that set up
284         // a differing zoom, and then we divide our result by it to eliminate the zoom.
285         RenderObject* prev = renderer;
286         for (RenderObject* curr = prev->parent(); curr; curr = curr->parent()) {
287             if (curr->style()->effectiveZoom() != prev->style()->effectiveZoom()) {
288                 zoomFactor = prev->style()->zoom();
289                 break;
290             }
291             prev = curr;
292         }
293         if (prev->isRenderView())
294             zoomFactor = prev->style()->zoom();
295     }
296     return zoomFactor;
297 }
298
299 static int adjustForLocalZoom(int value, RenderObject* renderer)
300 {
301     float zoomFactor = localZoomForRenderer(renderer);
302     if (zoomFactor == 1)
303         return value;
304     // Needed because computeLengthInt truncates (rather than rounds) when scaling up.
305     if (zoomFactor > 1)
306         value++;
307     return static_cast<int>(value / zoomFactor);
308 }
309
310 int Element::offsetLeft()
311 {
312     document()->updateLayoutIgnorePendingStylesheets();
313     if (RenderBoxModelObject* rend = renderBoxModelObject())
314         return adjustForLocalZoom(rend->offsetLeft(), rend);
315     return 0;
316 }
317
318 int Element::offsetTop()
319 {
320     document()->updateLayoutIgnorePendingStylesheets();
321     if (RenderBoxModelObject* rend = renderBoxModelObject())
322         return adjustForLocalZoom(rend->offsetTop(), rend);
323     return 0;
324 }
325
326 int Element::offsetWidth()
327 {
328     document()->updateLayoutIgnorePendingStylesheets();
329     if (RenderBoxModelObject* rend = renderBoxModelObject())
330         return adjustForAbsoluteZoom(rend->offsetWidth(), rend);
331     return 0;
332 }
333
334 int Element::offsetHeight()
335 {
336     document()->updateLayoutIgnorePendingStylesheets();
337     if (RenderBoxModelObject* rend = renderBoxModelObject())
338         return adjustForAbsoluteZoom(rend->offsetHeight(), rend);
339     return 0;
340 }
341
342 Element* Element::offsetParent()
343 {
344     document()->updateLayoutIgnorePendingStylesheets();
345     if (RenderObject* rend = renderer())
346         if (RenderObject* offsetParent = rend->offsetParent())
347             return static_cast<Element*>(offsetParent->node());
348     return 0;
349 }
350
351 int Element::clientLeft()
352 {
353     document()->updateLayoutIgnorePendingStylesheets();
354
355     if (RenderBox* rend = renderBox())
356         return adjustForAbsoluteZoom(rend->clientLeft(), rend);
357     return 0;
358 }
359
360 int Element::clientTop()
361 {
362     document()->updateLayoutIgnorePendingStylesheets();
363
364     if (RenderBox* rend = renderBox())
365         return adjustForAbsoluteZoom(rend->clientTop(), rend);
366     return 0;
367 }
368
369 int Element::clientWidth()
370 {
371     document()->updateLayoutIgnorePendingStylesheets();
372
373     // When in strict mode, clientWidth for the document element should return the width of the containing frame.
374     // When in quirks mode, clientWidth for the body element should return the width of the containing frame.
375     bool inCompatMode = document()->inCompatMode();
376     if ((!inCompatMode && document()->documentElement() == this) ||
377         (inCompatMode && isHTMLElement() && document()->body() == this)) {
378         if (FrameView* view = document()->view()) {
379             if (RenderView* renderView = document()->renderView())
380                 return adjustForAbsoluteZoom(view->layoutWidth(), renderView);
381         }
382     }
383     
384     if (RenderBox* rend = renderBox())
385         return adjustForAbsoluteZoom(rend->clientWidth(), rend);
386     return 0;
387 }
388
389 int Element::clientHeight()
390 {
391     document()->updateLayoutIgnorePendingStylesheets();
392
393     // When in strict mode, clientHeight for the document element should return the height of the containing frame.
394     // When in quirks mode, clientHeight for the body element should return the height of the containing frame.
395     bool inCompatMode = document()->inCompatMode();     
396
397     if ((!inCompatMode && document()->documentElement() == this) ||
398         (inCompatMode && isHTMLElement() && document()->body() == this)) {
399         if (FrameView* view = document()->view()) {
400             if (RenderView* renderView = document()->renderView())
401                 return adjustForAbsoluteZoom(view->layoutHeight(), renderView);
402         }
403     }
404     
405     if (RenderBox* rend = renderBox())
406         return adjustForAbsoluteZoom(rend->clientHeight(), rend);
407     return 0;
408 }
409
410 int Element::scrollLeft() const
411 {
412     document()->updateLayoutIgnorePendingStylesheets();
413     if (RenderBox* rend = renderBox())
414         return adjustForAbsoluteZoom(rend->scrollLeft(), rend);
415     return 0;
416 }
417
418 int Element::scrollTop() const
419 {
420     document()->updateLayoutIgnorePendingStylesheets();
421     if (RenderBox* rend = renderBox())
422         return adjustForAbsoluteZoom(rend->scrollTop(), rend);
423     return 0;
424 }
425
426 void Element::setScrollLeft(int newLeft)
427 {
428     document()->updateLayoutIgnorePendingStylesheets();
429     if (RenderBox* rend = renderBox())
430         rend->setScrollLeft(static_cast<int>(newLeft * rend->style()->effectiveZoom()));
431 }
432
433 void Element::setScrollTop(int newTop)
434 {
435     document()->updateLayoutIgnorePendingStylesheets();
436     if (RenderBox* rend = renderBox())
437         rend->setScrollTop(static_cast<int>(newTop * rend->style()->effectiveZoom()));
438 }
439
440 int Element::scrollWidth() const
441 {
442     document()->updateLayoutIgnorePendingStylesheets();
443     if (RenderBox* rend = renderBox())
444         return adjustForAbsoluteZoom(rend->scrollWidth(), rend);
445     return 0;
446 }
447
448 int Element::scrollHeight() const
449 {
450     document()->updateLayoutIgnorePendingStylesheets();
451     if (RenderBox* rend = renderBox())
452         return adjustForAbsoluteZoom(rend->scrollHeight(), rend);
453     return 0;
454 }
455
456 PassRefPtr<ClientRectList> Element::getClientRects() const
457 {
458     document()->updateLayoutIgnorePendingStylesheets();
459
460     RenderBoxModelObject* renderBoxModelObject = this->renderBoxModelObject();
461     if (!renderBoxModelObject)
462         return ClientRectList::create();
463
464     // FIXME: Handle SVG elements.
465     // FIXME: Handle table/inline-table with a caption.
466
467     Vector<FloatQuad> quads;
468     renderBoxModelObject->absoluteQuads(quads);
469
470     if (FrameView* view = document()->view()) {
471         IntRect visibleContentRect = view->visibleContentRect();
472         for (size_t i = 0; i < quads.size(); ++i) {
473             quads[i].move(-visibleContentRect.x(), -visibleContentRect.y());
474             adjustFloatQuadForAbsoluteZoom(quads[i], renderBoxModelObject);
475         }
476     }
477
478     return ClientRectList::create(quads);
479 }
480
481 PassRefPtr<ClientRect> Element::getBoundingClientRect() const
482 {
483     document()->updateLayoutIgnorePendingStylesheets();
484     RenderBoxModelObject* renderBoxModelObject = this->renderBoxModelObject();
485     if (!renderBoxModelObject)
486         return ClientRect::create();
487
488     Vector<FloatQuad> quads;
489     renderBoxModelObject->absoluteQuads(quads);
490
491     if (quads.isEmpty())
492         return ClientRect::create();
493
494     IntRect result = quads[0].enclosingBoundingBox();
495     for (size_t i = 1; i < quads.size(); ++i)
496         result.unite(quads[i].enclosingBoundingBox());
497
498     if (FrameView* view = document()->view()) {
499         IntRect visibleContentRect = view->visibleContentRect();
500         result.move(-visibleContentRect.x(), -visibleContentRect.y());
501     }
502
503     adjustIntRectForAbsoluteZoom(result, renderBoxModelObject);
504
505     return ClientRect::create(result);
506 }
507
508 static inline bool shouldIgnoreAttributeCase(const Element* e)
509 {
510     return e && e->document()->isHTMLDocument() && e->isHTMLElement();
511 }
512
513 const AtomicString& Element::getAttribute(const String& name) const
514 {
515     bool ignoreCase = shouldIgnoreAttributeCase(this);
516     
517     // Update the 'style' attribute if it's invalid and being requested:
518     if (!isStyleAttributeValid() && equalPossiblyIgnoringCase(name, styleAttr.localName(), ignoreCase))
519         updateStyleAttribute();
520
521 #if ENABLE(SVG)
522     if (!areSVGAttributesValid()) {
523         // We're not passing a namespace argument on purpose. SVGNames::*Attr are defined w/o namespaces as well.
524         updateAnimatedSVGAttribute(QualifiedName(nullAtom, name, nullAtom));
525     }
526 #endif
527
528     if (namedAttrMap) {
529         if (Attribute* attribute = namedAttrMap->getAttributeItem(name, ignoreCase))
530             return attribute->value();
531     }
532
533     return nullAtom;
534 }
535
536 const AtomicString& Element::getAttributeNS(const String& namespaceURI, const String& localName) const
537 {
538     return getAttribute(QualifiedName(nullAtom, localName, namespaceURI));
539 }
540
541 void Element::setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode& ec)
542 {
543     if (!Document::isValidName(name)) {
544         ec = INVALID_CHARACTER_ERR;
545         return;
546     }
547
548     const AtomicString& localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
549
550     // Allocate attribute map if necessary.
551     Attribute* old = attributes(false)->getAttributeItem(localName, false);
552
553     document()->incDOMTreeVersion();
554
555     // FIXME: This check is probably not correct for the case where the document has an id attribute
556     // with a non-null namespace, because it will return true if the local name happens to match
557     // but the namespace does not.
558     if (localName == document()->idAttributeName().localName())
559         updateId(old ? old->value() : nullAtom, value);
560
561     if (old && value.isNull())
562         namedAttrMap->removeAttribute(old->name());
563     else if (!old && !value.isNull())
564         namedAttrMap->addAttribute(createAttribute(QualifiedName(nullAtom, localName, nullAtom), value));
565     else if (old && !value.isNull()) {
566         old->setValue(value);
567         attributeChanged(old);
568     }
569
570 #if ENABLE(INSPECTOR)
571     if (Page* page = document()->page()) {
572         if (InspectorController* inspectorController = page->inspectorController()) {
573             if (!isSynchronizingStyleAttribute())
574                 inspectorController->didModifyDOMAttr(this);
575         }
576     }
577 #endif
578 }
579
580 void Element::setAttribute(const QualifiedName& name, const AtomicString& value, ExceptionCode&)
581 {
582     document()->incDOMTreeVersion();
583
584     // Allocate attribute map if necessary.
585     Attribute* old = attributes(false)->getAttributeItem(name);
586
587     if (isIdAttributeName(name))
588         updateId(old ? old->value() : nullAtom, value);
589
590     if (old && value.isNull())
591         namedAttrMap->removeAttribute(name);
592     else if (!old && !value.isNull())
593         namedAttrMap->addAttribute(createAttribute(name, value));
594     else if (old) {
595         old->setValue(value);
596         attributeChanged(old);
597     }
598
599 #if ENABLE(INSPECTOR)
600     if (Page* page = document()->page()) {
601         if (InspectorController* inspectorController = page->inspectorController()) {
602             if (!isSynchronizingStyleAttribute())
603                 inspectorController->didModifyDOMAttr(this);
604         }
605     }
606 #endif
607 }
608
609 PassRefPtr<Attribute> Element::createAttribute(const QualifiedName& name, const AtomicString& value)
610 {
611     return Attribute::create(name, value);
612 }
613
614 void Element::attributeChanged(Attribute* attr, bool)
615 {
616     recalcStyleIfNeededAfterAttributeChanged(attr);
617     updateAfterAttributeChanged(attr);
618 }
619
620 void Element::updateAfterAttributeChanged(Attribute* attr)
621 {
622     if (!AXObjectCache::accessibilityEnabled())
623         return;
624
625     const QualifiedName& attrName = attr->name();
626     if (attrName == aria_activedescendantAttr) {
627         // any change to aria-activedescendant attribute triggers accessibility focus change, but document focus remains intact
628         document()->axObjectCache()->handleActiveDescendantChanged(renderer());
629     } else if (attrName == roleAttr) {
630         // the role attribute can change at any time, and the AccessibilityObject must pick up these changes
631         document()->axObjectCache()->handleAriaRoleChanged(renderer());
632     } else if (attrName == aria_valuenowAttr) {
633         // If the valuenow attribute changes, AX clients need to be notified.
634         document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXValueChanged, true);
635     } else if (attrName == aria_labelAttr || attrName == aria_labeledbyAttr || attrName == altAttr || attrName == titleAttr) {
636         // If the content of an element changes due to an attribute change, notify accessibility.
637         document()->axObjectCache()->contentChanged(renderer());
638     } else if (attrName == aria_selectedAttr)
639         document()->axObjectCache()->selectedChildrenChanged(renderer());
640     else if (attrName == aria_expandedAttr)
641         document()->axObjectCache()->handleAriaExpandedChange(renderer());
642 }
643     
644 void Element::recalcStyleIfNeededAfterAttributeChanged(Attribute* attr)
645 {
646     if (document()->attached() && document()->styleSelector()->hasSelectorForAttribute(attr->name().localName()))
647         setNeedsStyleRecalc();
648 }
649
650 // Returns true is the given attribute is an event handler.
651 // We consider an event handler any attribute that begins with "on".
652 // It is a simple solution that has the advantage of not requiring any
653 // code or configuration change if a new event handler is defined.
654
655 static bool isEventHandlerAttribute(const QualifiedName& name)
656 {
657     return name.namespaceURI().isNull() && name.localName().startsWith("on");
658 }
659
660 static bool isAttributeToRemove(const QualifiedName& name, const AtomicString& value)
661 {    
662     return (name.localName().endsWith(hrefAttr.localName()) || name == srcAttr || name == actionAttr) && protocolIsJavaScript(deprecatedParseURL(value));       
663 }
664
665 void Element::setAttributeMap(PassRefPtr<NamedNodeMap> list, FragmentScriptingPermission scriptingPermission)
666 {
667     document()->incDOMTreeVersion();
668
669     // If setting the whole map changes the id attribute, we need to call updateId.
670
671     const QualifiedName& idName = document()->idAttributeName();
672     Attribute* oldId = namedAttrMap ? namedAttrMap->getAttributeItem(idName) : 0;
673     Attribute* newId = list ? list->getAttributeItem(idName) : 0;
674
675     if (oldId || newId)
676         updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom);
677
678     if (namedAttrMap)
679         namedAttrMap->m_element = 0;
680
681     namedAttrMap = list;
682
683     if (namedAttrMap) {
684         namedAttrMap->m_element = this;
685         // If the element is created as result of a paste or drag-n-drop operation
686         // we want to remove all the script and event handlers.
687         if (scriptingPermission == FragmentScriptingNotAllowed) {
688             unsigned i = 0;
689             while (i < namedAttrMap->length()) {
690                 const QualifiedName& attributeName = namedAttrMap->m_attributes[i]->name();
691                 if (isEventHandlerAttribute(attributeName)) {
692                     namedAttrMap->m_attributes.remove(i);
693                     continue;
694                 }
695
696                 if (isAttributeToRemove(attributeName, namedAttrMap->m_attributes[i]->value()))
697                     namedAttrMap->m_attributes[i]->setValue(nullAtom);
698                 i++;
699             }
700         }
701         unsigned len = namedAttrMap->length();
702         for (unsigned i = 0; i < len; i++)
703             attributeChanged(namedAttrMap->m_attributes[i].get());
704         // FIXME: What about attributes that were in the old map that are not in the new map?
705     }
706 }
707
708 bool Element::hasAttributes() const
709 {
710     if (!isStyleAttributeValid())
711         updateStyleAttribute();
712
713 #if ENABLE(SVG)
714     if (!areSVGAttributesValid())
715         updateAnimatedSVGAttribute(anyQName());
716 #endif
717
718     return namedAttrMap && namedAttrMap->length() > 0;
719 }
720
721 String Element::nodeName() const
722 {
723     return m_tagName.toString();
724 }
725
726 String Element::nodeNamePreservingCase() const
727 {
728     return m_tagName.toString();
729 }
730
731 void Element::setPrefix(const AtomicString& prefix, ExceptionCode& ec)
732 {
733     ec = 0;
734     checkSetPrefix(prefix, ec);
735     if (ec)
736         return;
737
738     m_tagName.setPrefix(prefix.isEmpty() ? AtomicString() : prefix);
739 }
740
741 KURL Element::baseURI() const
742 {
743     const AtomicString& baseAttribute = getAttribute(baseAttr);
744     KURL base(KURL(), baseAttribute);
745     if (!base.protocol().isEmpty())
746         return base;
747
748     Node* parent = parentNode();
749     if (!parent)
750         return base;
751
752     const KURL& parentBase = parent->baseURI();
753     if (parentBase.isNull())
754         return base;
755
756     return KURL(parentBase, baseAttribute);
757 }
758
759 void Element::createAttributeMap() const
760 {
761     namedAttrMap = NamedNodeMap::create(const_cast<Element*>(this));
762 }
763
764 bool Element::isURLAttribute(Attribute*) const
765 {
766     return false;
767 }
768
769 const QualifiedName& Element::imageSourceAttributeName() const
770 {
771     return srcAttr;
772 }
773
774 RenderObject* Element::createRenderer(RenderArena* arena, RenderStyle* style)
775 {
776     if (document()->documentElement() == this && style->display() == NONE) {
777         // Ignore display: none on root elements.  Force a display of block in that case.
778         RenderBlock* result = new (arena) RenderBlock(this);
779         if (result)
780             result->setAnimatableStyle(style);
781         return result;
782     }
783     return RenderObject::createObject(this, style);
784 }
785
786
787 void Element::insertedIntoDocument()
788 {
789     // need to do superclass processing first so inDocument() is true
790     // by the time we reach updateId
791     ContainerNode::insertedIntoDocument();
792
793     if (hasID()) {
794         if (NamedNodeMap* attrs = namedAttrMap.get()) {
795             Attribute* idItem = attrs->getAttributeItem(document()->idAttributeName());
796             if (idItem && !idItem->isNull())
797                 updateId(nullAtom, idItem->value());
798         }
799     }
800 }
801
802 void Element::removedFromDocument()
803 {
804     if (hasID()) {
805         if (NamedNodeMap* attrs = namedAttrMap.get()) {
806             Attribute* idItem = attrs->getAttributeItem(document()->idAttributeName());
807             if (idItem && !idItem->isNull())
808                 updateId(idItem->value(), nullAtom);
809         }
810     }
811
812     ContainerNode::removedFromDocument();
813 }
814
815 void Element::attach()
816 {
817     suspendPostAttachCallbacks();
818     RenderWidget::suspendWidgetHierarchyUpdates();
819
820     createRendererIfNeeded();
821     ContainerNode::attach();
822     if (hasRareData()) {   
823         ElementRareData* data = rareData();
824         if (data->needsFocusAppearanceUpdateSoonAfterAttach()) {
825             if (isFocusable() && document()->focusedNode() == this)
826                 document()->updateFocusAppearanceSoon(false /* don't restore selection */);
827             data->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
828         }
829     }
830
831     RenderWidget::resumeWidgetHierarchyUpdates();
832     resumePostAttachCallbacks();
833 }
834
835 void Element::detach()
836 {
837     RenderWidget::suspendWidgetHierarchyUpdates();
838
839     cancelFocusAppearanceUpdate();
840     if (hasRareData())
841         rareData()->resetComputedStyle();
842     ContainerNode::detach();
843
844     RenderWidget::resumeWidgetHierarchyUpdates();
845 }
846
847 bool Element::pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle)
848 {
849     ASSERT(currentStyle == renderStyle());
850
851     if (!renderer() || !currentStyle)
852         return false;
853
854     const PseudoStyleCache* pseudoStyleCache = currentStyle->cachedPseudoStyles();
855     if (!pseudoStyleCache)
856         return false;
857
858     size_t cacheSize = pseudoStyleCache->size();
859     for (size_t i = 0; i < cacheSize; ++i) {
860         RefPtr<RenderStyle> newPseudoStyle;
861         PseudoId pseudoId = pseudoStyleCache->at(i)->styleType();
862         if (pseudoId == VISITED_LINK) {
863             newPseudoStyle =  newStyle->getCachedPseudoStyle(VISITED_LINK); // This pseudo-style was aggressively computed already when we first called styleForElement on the new style.
864             if (!newPseudoStyle || *newPseudoStyle != *pseudoStyleCache->at(i))
865                 return true;
866         } else if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED)
867             newPseudoStyle = renderer()->uncachedFirstLineStyle(newStyle);
868         else
869             newPseudoStyle = renderer()->getUncachedPseudoStyle(pseudoId, newStyle, newStyle);
870         if (!newPseudoStyle)
871             return true;
872         if (*newPseudoStyle != *pseudoStyleCache->at(i)) {
873             if (pseudoId < FIRST_INTERNAL_PSEUDOID)
874                 newStyle->setHasPseudoStyle(pseudoId);
875             newStyle->addCachedPseudoStyle(newPseudoStyle);
876             if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED) {
877                 // FIXME: We should do an actual diff to determine whether a repaint vs. layout
878                 // is needed, but for now just assume a layout will be required.  The diff code
879                 // in RenderObject::setStyle would need to be factored out so that it could be reused.
880                 renderer()->setNeedsLayoutAndPrefWidthsRecalc();
881             }
882             return true;
883         }
884     }
885     return false;
886 }
887
888 void Element::recalcStyle(StyleChange change)
889 {
890     // Ref currentStyle in case it would otherwise be deleted when setRenderStyle() is called.
891     RefPtr<RenderStyle> currentStyle(renderStyle());
892     bool hasParentStyle = parentNode() ? parentNode()->renderStyle() : false;
893     bool hasPositionalRules = needsStyleRecalc() && currentStyle && currentStyle->childrenAffectedByPositionalRules();
894     bool hasDirectAdjacentRules = currentStyle && currentStyle->childrenAffectedByDirectAdjacentRules();
895
896 #if ENABLE(SVG)
897     if (!hasParentStyle && isShadowNode() && isSVGElement())
898         hasParentStyle = true;
899 #endif
900
901     if ((change > NoChange || needsStyleRecalc())) {
902         if (hasRareData())
903             rareData()->resetComputedStyle();
904     }
905     if (hasParentStyle && (change >= Inherit || needsStyleRecalc())) {
906         RefPtr<RenderStyle> newStyle = document()->styleSelector()->styleForElement(this);
907         StyleChange ch = diff(currentStyle.get(), newStyle.get());
908         if (ch == Detach || !currentStyle) {
909             if (attached())
910                 detach();
911             attach(); // FIXME: The style gets computed twice by calling attach. We could do better if we passed the style along.
912             // attach recalulates the style for all children. No need to do it twice.
913             setNeedsStyleRecalc(NoStyleChange);
914             clearChildNeedsStyleRecalc();
915             return;
916         }
917
918         if (currentStyle) {
919             // Preserve "affected by" bits that were propagated to us from descendants in the case where we didn't do a full
920             // style change (e.g., only inline style changed).
921             if (currentStyle->affectedByHoverRules())
922                 newStyle->setAffectedByHoverRules(true);
923             if (currentStyle->affectedByActiveRules())
924                 newStyle->setAffectedByActiveRules(true);
925             if (currentStyle->affectedByDragRules())
926                 newStyle->setAffectedByDragRules(true);
927             if (currentStyle->childrenAffectedByForwardPositionalRules())
928                 newStyle->setChildrenAffectedByForwardPositionalRules();
929             if (currentStyle->childrenAffectedByBackwardPositionalRules())
930                 newStyle->setChildrenAffectedByBackwardPositionalRules();
931             if (currentStyle->childrenAffectedByFirstChildRules())
932                 newStyle->setChildrenAffectedByFirstChildRules();
933             if (currentStyle->childrenAffectedByLastChildRules())
934                 newStyle->setChildrenAffectedByLastChildRules();
935             if (currentStyle->childrenAffectedByDirectAdjacentRules())
936                 newStyle->setChildrenAffectedByDirectAdjacentRules();
937         }
938
939         if (ch != NoChange || pseudoStyleCacheIsInvalid(currentStyle.get(), newStyle.get()) || (change == Force && renderer() && renderer()->requiresForcedStyleRecalcPropagation())) {
940             setRenderStyle(newStyle);
941         } else if (needsStyleRecalc() && (styleChangeType() != SyntheticStyleChange) && (document()->usesSiblingRules() || document()->usesDescendantRules())) {
942             // Although no change occurred, we use the new style so that the cousin style sharing code won't get
943             // fooled into believing this style is the same.  This is only necessary if the document actually uses
944             // sibling/descendant rules, since otherwise it isn't possible for ancestor styles to affect sharing of
945             // descendants.
946             if (renderer())
947                 renderer()->setStyleInternal(newStyle.get());
948             else
949                 setRenderStyle(newStyle);
950         } else if (styleChangeType() == SyntheticStyleChange)
951              setRenderStyle(newStyle);
952
953         if (change != Force) {
954             // 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
955             // 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).
956             if (document()->usesRemUnits() && ch != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize() && document()->documentElement() == this)
957                 change = Force;
958             else if ((document()->usesDescendantRules() || hasPositionalRules) && styleChangeType() >= FullStyleChange)
959                 change = Force;
960             else
961                 change = ch;
962         }
963     }
964
965     // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
966     // For now we will just worry about the common case, since it's a lot trickier to get the second case right
967     // without doing way too much re-resolution.
968     bool forceCheckOfNextElementSibling = false;
969     for (Node *n = firstChild(); n; n = n->nextSibling()) {
970         bool childRulesChanged = n->needsStyleRecalc() && n->styleChangeType() == FullStyleChange;
971         if (forceCheckOfNextElementSibling && n->isElementNode())
972             n->setNeedsStyleRecalc();
973         if (change >= Inherit || n->isTextNode() || n->childNeedsStyleRecalc() || n->needsStyleRecalc())
974             n->recalcStyle(change);
975         if (n->isElementNode())
976             forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
977     }
978
979     setNeedsStyleRecalc(NoStyleChange);
980     clearChildNeedsStyleRecalc();
981 }
982
983 bool Element::childTypeAllowed(NodeType type)
984 {
985     switch (type) {
986         case ELEMENT_NODE:
987         case TEXT_NODE:
988         case COMMENT_NODE:
989         case PROCESSING_INSTRUCTION_NODE:
990         case CDATA_SECTION_NODE:
991         case ENTITY_REFERENCE_NODE:
992             return true;
993             break;
994         default:
995             return false;
996     }
997 }
998
999 static void checkForSiblingStyleChanges(Element* e, RenderStyle* style, bool finishedParsingCallback,
1000                                         Node* beforeChange, Node* afterChange, int childCountDelta)
1001 {
1002     if (!style || (e->needsStyleRecalc() && style->childrenAffectedByPositionalRules()))
1003         return;
1004
1005     // :first-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
1006     // In the DOM case, we only need to do something if |afterChange| is not 0.
1007     // |afterChange| is 0 in the parser case, so it works out that we'll skip this block.
1008     if (style->childrenAffectedByFirstChildRules() && afterChange) {
1009         // Find our new first child.
1010         Node* newFirstChild = 0;
1011         for (newFirstChild = e->firstChild(); newFirstChild && !newFirstChild->isElementNode(); newFirstChild = newFirstChild->nextSibling()) {};
1012         
1013         // Find the first element node following |afterChange|
1014         Node* firstElementAfterInsertion = 0;
1015         for (firstElementAfterInsertion = afterChange;
1016              firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
1017              firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
1018         
1019         // This is the insert/append case.
1020         if (newFirstChild != firstElementAfterInsertion && firstElementAfterInsertion && firstElementAfterInsertion->attached() &&
1021             firstElementAfterInsertion->renderStyle() && firstElementAfterInsertion->renderStyle()->firstChildState())
1022             firstElementAfterInsertion->setNeedsStyleRecalc();
1023             
1024         // We also have to handle node removal.
1025         if (childCountDelta < 0 && newFirstChild == firstElementAfterInsertion && newFirstChild && newFirstChild->renderStyle() && !newFirstChild->renderStyle()->firstChildState())
1026             newFirstChild->setNeedsStyleRecalc();
1027     }
1028
1029     // :last-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
1030     // In the DOM case, we only need to do something if |afterChange| is not 0.
1031     if (style->childrenAffectedByLastChildRules() && beforeChange) {
1032         // Find our new last child.
1033         Node* newLastChild = 0;
1034         for (newLastChild = e->lastChild(); newLastChild && !newLastChild->isElementNode(); newLastChild = newLastChild->previousSibling()) {};
1035         
1036         // Find the last element node going backwards from |beforeChange|
1037         Node* lastElementBeforeInsertion = 0;
1038         for (lastElementBeforeInsertion = beforeChange;
1039              lastElementBeforeInsertion && !lastElementBeforeInsertion->isElementNode();
1040              lastElementBeforeInsertion = lastElementBeforeInsertion->previousSibling()) {};
1041         
1042         if (newLastChild != lastElementBeforeInsertion && lastElementBeforeInsertion && lastElementBeforeInsertion->attached() &&
1043             lastElementBeforeInsertion->renderStyle() && lastElementBeforeInsertion->renderStyle()->lastChildState())
1044             lastElementBeforeInsertion->setNeedsStyleRecalc();
1045             
1046         // 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
1047         // to match now.
1048         if ((childCountDelta < 0 || finishedParsingCallback) && newLastChild == lastElementBeforeInsertion && newLastChild && newLastChild->renderStyle() && !newLastChild->renderStyle()->lastChildState())
1049             newLastChild->setNeedsStyleRecalc();
1050     }
1051
1052     // The + selector.  We need to invalidate the first element following the insertion point.  It is the only possible element
1053     // that could be affected by this DOM change.
1054     if (style->childrenAffectedByDirectAdjacentRules() && afterChange) {
1055         Node* firstElementAfterInsertion = 0;
1056         for (firstElementAfterInsertion = afterChange;
1057              firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
1058              firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
1059         if (firstElementAfterInsertion && firstElementAfterInsertion->attached())
1060             firstElementAfterInsertion->setNeedsStyleRecalc();
1061     }
1062
1063     // Forward positional selectors include the ~ selector, nth-child, nth-of-type, first-of-type and only-of-type.
1064     // Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type.
1065     // We have to invalidate everything following the insertion point in the forward case, and everything before the insertion point in the
1066     // backward case.
1067     // |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.
1068     // 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
1069     // here.  recalcStyle will then force a walk of the children when it sees that this has happened.
1070     if ((style->childrenAffectedByForwardPositionalRules() && afterChange) ||
1071         (style->childrenAffectedByBackwardPositionalRules() && beforeChange))
1072         e->setNeedsStyleRecalc();
1073     
1074     // :empty selector.
1075     if (style->affectedByEmpty() && (!style->emptyState() || e->hasChildNodes()))
1076         e->setNeedsStyleRecalc();
1077 }
1078
1079 void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
1080 {
1081     ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
1082     if (!changedByParser)
1083         checkForSiblingStyleChanges(this, renderStyle(), false, beforeChange, afterChange, childCountDelta);
1084 }
1085
1086 void Element::finishParsingChildren()
1087 {
1088     ContainerNode::finishParsingChildren();
1089     setIsParsingChildrenFinished();
1090     checkForSiblingStyleChanges(this, renderStyle(), true, lastChild(), 0, 0);
1091 }
1092
1093 void Element::dispatchAttrRemovalEvent(Attribute*)
1094 {
1095     ASSERT(!eventDispatchForbidden());
1096
1097 #if 0
1098     if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
1099         return;
1100     ExceptionCode ec = 0;
1101     dispatchEvent(MutationEvent::create(DOMAttrModifiedEvent, true, attr, attr->value(),
1102         attr->value(), document()->attrName(attr->id()), MutationEvent::REMOVAL), ec);
1103 #endif
1104 }
1105
1106 void Element::dispatchAttrAdditionEvent(Attribute*)
1107 {
1108     ASSERT(!eventDispatchForbidden());
1109
1110 #if 0
1111     if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
1112         return;
1113     ExceptionCode ec = 0;
1114     dispatchEvent(MutationEvent::create(DOMAttrModifiedEvent, true, attr, attr->value(),
1115         attr->value(), document()->attrName(attr->id()), MutationEvent::ADDITION), ec);
1116 #endif
1117 }
1118
1119 String Element::openTagStartToString() const
1120 {
1121     String result = "<" + nodeName();
1122
1123     NamedNodeMap* attrMap = attributes(true);
1124
1125     if (attrMap) {
1126         unsigned numAttrs = attrMap->length();
1127         for (unsigned i = 0; i < numAttrs; i++) {
1128             result += " ";
1129
1130             Attribute *attribute = attrMap->attributeItem(i);
1131             result += attribute->name().toString();
1132             if (!attribute->value().isNull()) {
1133                 result += "=\"";
1134                 // FIXME: substitute entities for any instances of " or '
1135                 result += attribute->value();
1136                 result += "\"";
1137             }
1138         }
1139     }
1140
1141     return result;
1142 }
1143
1144 #ifndef NDEBUG
1145 void Element::formatForDebugger(char* buffer, unsigned length) const
1146 {
1147     String result;
1148     String s;
1149     
1150     s = nodeName();
1151     if (s.length() > 0) {
1152         result += s;
1153     }
1154           
1155     s = getIdAttribute();
1156     if (s.length() > 0) {
1157         if (result.length() > 0)
1158             result += "; ";
1159         result += "id=";
1160         result += s;
1161     }
1162           
1163     s = getAttribute(classAttr);
1164     if (s.length() > 0) {
1165         if (result.length() > 0)
1166             result += "; ";
1167         result += "class=";
1168         result += s;
1169     }
1170           
1171     strncpy(buffer, result.utf8().data(), length - 1);
1172 }
1173 #endif
1174
1175 PassRefPtr<Attr> Element::setAttributeNode(Attr* attr, ExceptionCode& ec)
1176 {
1177     if (!attr) {
1178         ec = TYPE_MISMATCH_ERR;
1179         return 0;
1180     }
1181     return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));
1182 }
1183
1184 PassRefPtr<Attr> Element::setAttributeNodeNS(Attr* attr, ExceptionCode& ec)
1185 {
1186     if (!attr) {
1187         ec = TYPE_MISMATCH_ERR;
1188         return 0;
1189     }
1190     return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));
1191 }
1192
1193 PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionCode& ec)
1194 {
1195     if (!attr) {
1196         ec = TYPE_MISMATCH_ERR;
1197         return 0;
1198     }
1199     if (attr->ownerElement() != this) {
1200         ec = NOT_FOUND_ERR;
1201         return 0;
1202     }
1203     if (document() != attr->document()) {
1204         ec = WRONG_DOCUMENT_ERR;
1205         return 0;
1206     }
1207
1208     NamedNodeMap* attrs = attributes(true);
1209     if (!attrs)
1210         return 0;
1211
1212     return static_pointer_cast<Attr>(attrs->removeNamedItem(attr->qualifiedName(), ec));
1213 }
1214
1215 void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode& ec, FragmentScriptingPermission scriptingPermission)
1216 {
1217     String prefix, localName;
1218     if (!Document::parseQualifiedName(qualifiedName, prefix, localName, ec))
1219         return;
1220
1221     QualifiedName qName(prefix, localName, namespaceURI);
1222
1223     if (scriptingPermission == FragmentScriptingNotAllowed && (isEventHandlerAttribute(qName) || isAttributeToRemove(qName, value)))
1224         return;
1225
1226     setAttribute(qName, value, ec);
1227 }
1228
1229 void Element::removeAttribute(const String& name, ExceptionCode& ec)
1230 {
1231     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
1232
1233     if (namedAttrMap) {
1234         namedAttrMap->removeNamedItem(localName, ec);
1235         if (ec == NOT_FOUND_ERR)
1236             ec = 0;
1237     }
1238     
1239 #if ENABLE(INSPECTOR)
1240     if (Page* page = document()->page()) {
1241         if (InspectorController* inspectorController = page->inspectorController())
1242             inspectorController->didModifyDOMAttr(this);
1243     }
1244 #endif
1245     
1246 }
1247
1248 void Element::removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode& ec)
1249 {
1250     removeAttribute(QualifiedName(nullAtom, localName, namespaceURI), ec);
1251 }
1252
1253 PassRefPtr<Attr> Element::getAttributeNode(const String& name)
1254 {
1255     NamedNodeMap* attrs = attributes(true);
1256     if (!attrs)
1257         return 0;
1258     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
1259     return static_pointer_cast<Attr>(attrs->getNamedItem(localName));
1260 }
1261
1262 PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const String& localName)
1263 {
1264     NamedNodeMap* attrs = attributes(true);
1265     if (!attrs)
1266         return 0;
1267     return static_pointer_cast<Attr>(attrs->getNamedItem(QualifiedName(nullAtom, localName, namespaceURI)));
1268 }
1269
1270 bool Element::hasAttribute(const String& name) const
1271 {
1272     NamedNodeMap* attrs = attributes(true);
1273     if (!attrs)
1274         return false;
1275
1276     // This call to String::lower() seems to be required but
1277     // there may be a way to remove it.
1278     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
1279     return attrs->getAttributeItem(localName, false);
1280 }
1281
1282 bool Element::hasAttributeNS(const String& namespaceURI, const String& localName) const
1283 {
1284     NamedNodeMap* attrs = attributes(true);
1285     if (!attrs)
1286         return false;
1287     return attrs->getAttributeItem(QualifiedName(nullAtom, localName, namespaceURI));
1288 }
1289
1290 CSSStyleDeclaration *Element::style()
1291 {
1292     return 0;
1293 }
1294
1295 void Element::focus(bool restorePreviousSelection)
1296 {
1297     Document* doc = document();
1298     if (doc->focusedNode() == this)
1299         return;
1300
1301     if (!supportsFocus())
1302         return;
1303
1304     // If the stylesheets have already been loaded we can reliably check isFocusable.
1305     // If not, we continue and set the focused node on the focus controller below so
1306     // that it can be updated soon after attach. 
1307     if (doc->haveStylesheetsLoaded()) {
1308         doc->updateLayoutIgnorePendingStylesheets();
1309         if (!isFocusable())
1310             return;
1311     }
1312
1313     RefPtr<Node> protect;
1314     if (Page* page = doc->page()) {
1315         // Focus and change event handlers can cause us to lose our last ref.
1316         protect = this;
1317         page->focusController()->setFocusedNode(this, doc->frame());
1318     }
1319
1320     // Setting the focused node above might have invalidated the layout due to scripts.
1321     doc->updateLayoutIgnorePendingStylesheets();
1322
1323     if (!isFocusable()) {
1324         ensureRareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(true);
1325         return;
1326     }
1327         
1328     cancelFocusAppearanceUpdate();
1329     updateFocusAppearance(restorePreviousSelection);
1330 }
1331
1332 void Element::updateFocusAppearance(bool /*restorePreviousSelection*/)
1333 {
1334     if (this == rootEditableElement()) { 
1335         Frame* frame = document()->frame();
1336         if (!frame)
1337             return;
1338
1339         // FIXME: We should restore the previous selection if there is one.
1340         VisibleSelection newSelection = hasTagName(htmlTag) || hasTagName(bodyTag) ? VisibleSelection(Position(this, 0), DOWNSTREAM) : VisibleSelection::selectionFromContentsOfNode(this);
1341         
1342         if (frame->shouldChangeSelection(newSelection)) {
1343             frame->selection()->setSelection(newSelection);
1344             frame->revealSelection();
1345         }
1346     } else if (renderer() && !renderer()->isWidget())
1347         renderer()->enclosingLayer()->scrollRectToVisible(getRect());
1348 }
1349
1350 void Element::blur()
1351 {
1352     cancelFocusAppearanceUpdate();
1353     Document* doc = document();
1354     if (doc->focusedNode() == this) {
1355         if (doc->frame())
1356             doc->frame()->page()->focusController()->setFocusedNode(0, doc->frame());
1357         else
1358             doc->setFocusedNode(0);
1359     }
1360 }
1361
1362 String Element::innerText() const
1363 {
1364     // We need to update layout, since plainText uses line boxes in the render tree.
1365     document()->updateLayoutIgnorePendingStylesheets();
1366
1367     if (!renderer())
1368         return textContent(true);
1369
1370     return plainText(rangeOfContents(const_cast<Element*>(this)).get());
1371 }
1372
1373 String Element::outerText() const
1374 {
1375     // Getting outerText is the same as getting innerText, only
1376     // setting is different. You would think this should get the plain
1377     // text for the outer range, but this is wrong, <br> for instance
1378     // would return different values for inner and outer text by such
1379     // a rule, but it doesn't in WinIE, and we want to match that.
1380     return innerText();
1381 }
1382
1383 String Element::title() const
1384 {
1385     return String();
1386 }
1387
1388 IntSize Element::minimumSizeForResizing() const
1389 {
1390     return hasRareData() ? rareData()->m_minimumSizeForResizing : defaultMinimumSizeForResizing();
1391 }
1392
1393 void Element::setMinimumSizeForResizing(const IntSize& size)
1394 {
1395     if (size == defaultMinimumSizeForResizing() && !hasRareData())
1396         return;
1397     ensureRareData()->m_minimumSizeForResizing = size;
1398 }
1399
1400 RenderStyle* Element::computedStyle(PseudoId pseudoElementSpecifier)
1401 {
1402     // FIXME: Find and use the renderer from the pseudo element instead of the actual element so that the 'length'
1403     // properties, which are only known by the renderer because it did the layout, will be correct and so that the
1404     // values returned for the ":selection" pseudo-element will be correct.
1405     if (RenderStyle* usedStyle = renderStyle())
1406         return pseudoElementSpecifier ? usedStyle->getCachedPseudoStyle(pseudoElementSpecifier) : usedStyle;
1407
1408     if (!attached())
1409         // FIXME: Try to do better than this. Ensure that styleForElement() works for elements that are not in the
1410         // document tree and figure out when to destroy the computed style for such elements.
1411         return 0;
1412
1413     ElementRareData* data = ensureRareData();
1414     if (!data->m_computedStyle)
1415         data->m_computedStyle = document()->styleForElementIgnoringPendingStylesheets(this);
1416     return pseudoElementSpecifier ? data->m_computedStyle->getCachedPseudoStyle(pseudoElementSpecifier) : data->m_computedStyle.get();
1417 }
1418
1419 void Element::cancelFocusAppearanceUpdate()
1420 {
1421     if (hasRareData())
1422         rareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
1423     if (document()->focusedNode() == this)
1424         document()->cancelFocusAppearanceUpdate();
1425 }
1426
1427 void Element::normalizeAttributes()
1428 {
1429     // Normalize attributes.
1430     NamedNodeMap* attrs = attributes(true);
1431     if (!attrs)
1432         return;
1433
1434     if (attrs->isEmpty())
1435         return;
1436
1437     Vector<RefPtr<Attribute> > attributeVector;
1438     attrs->copyAttributesToVector(attributeVector);
1439     size_t numAttrs = attributeVector.size();
1440     for (size_t i = 0; i < numAttrs; ++i) {
1441         if (Attr* attr = attributeVector[i]->attr())
1442             attr->normalize();
1443     }
1444 }
1445
1446 // ElementTraversal API
1447 Element* Element::firstElementChild() const
1448 {
1449     Node* n = firstChild();
1450     while (n && !n->isElementNode())
1451         n = n->nextSibling();
1452     return static_cast<Element*>(n);
1453 }
1454
1455 Element* Element::lastElementChild() const
1456 {
1457     Node* n = lastChild();
1458     while (n && !n->isElementNode())
1459         n = n->previousSibling();
1460     return static_cast<Element*>(n);
1461 }
1462
1463 Element* Element::previousElementSibling() const
1464 {
1465     Node* n = previousSibling();
1466     while (n && !n->isElementNode())
1467         n = n->previousSibling();
1468     return static_cast<Element*>(n);
1469 }
1470
1471 Element* Element::nextElementSibling() const
1472 {
1473     Node* n = nextSibling();
1474     while (n && !n->isElementNode())
1475         n = n->nextSibling();
1476     return static_cast<Element*>(n);
1477 }
1478
1479 unsigned Element::childElementCount() const
1480 {
1481     unsigned count = 0;
1482     Node* n = firstChild();
1483     while (n) {
1484         count += n->isElementNode();
1485         n = n->nextSibling();
1486     }
1487     return count;
1488 }
1489
1490 bool Element::webkitMatchesSelector(const String& selector, ExceptionCode& ec)
1491 {
1492     if (selector.isEmpty()) {
1493         ec = SYNTAX_ERR;
1494         return false;
1495     }
1496
1497     bool strictParsing = !document()->inCompatMode();
1498     CSSParser p(strictParsing);
1499
1500     CSSSelectorList selectorList;
1501     p.parseSelector(selector, document(), selectorList);
1502
1503     if (!selectorList.first()) {
1504         ec = SYNTAX_ERR;
1505         return false;
1506     }
1507
1508     // Throw a NAMESPACE_ERR if the selector includes any namespace prefixes.
1509     if (selectorList.selectorsNeedNamespaceResolution()) {
1510         ec = NAMESPACE_ERR;
1511         return false;
1512     }
1513
1514     CSSStyleSelector::SelectorChecker selectorChecker(document(), strictParsing);
1515     for (CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
1516         if (selectorChecker.checkSelector(selector, this))
1517             return true;
1518     }
1519
1520     return false;
1521 }
1522
1523 KURL Element::getURLAttribute(const QualifiedName& name) const
1524 {
1525 #if !ASSERT_DISABLED
1526     if (namedAttrMap) {
1527         if (Attribute* attribute = namedAttrMap->getAttributeItem(name))
1528             ASSERT(isURLAttribute(attribute));
1529     }
1530 #endif
1531     return document()->completeURL(deprecatedParseURL(getAttribute(name)));
1532 }
1533
1534 int Element::getIntegralAttribute(const QualifiedName& attributeName) const
1535 {
1536     return getAttribute(attributeName).string().toInt();
1537 }
1538
1539 void Element::setIntegralAttribute(const QualifiedName& attributeName, int value)
1540 {
1541     // FIXME: Need an AtomicString version of String::number.
1542     ExceptionCode ec;
1543     setAttribute(attributeName, String::number(value), ec);
1544 }
1545
1546 unsigned Element::getUnsignedIntegralAttribute(const QualifiedName& attributeName) const
1547 {
1548     return getAttribute(attributeName).string().toUInt();
1549 }
1550
1551 void Element::setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value)
1552 {
1553     // FIXME: Need an AtomicString version of String::number.
1554     ExceptionCode ec;
1555     setAttribute(attributeName, String::number(value), ec);
1556 }
1557
1558 #if ENABLE(SVG)
1559 bool Element::childShouldCreateRenderer(Node* child) const
1560 {
1561     // Only create renderers for SVG elements whose parents are SVG elements, or for proper <svg xmlns="svgNS"> subdocuments.
1562     if (child->isSVGElement())
1563         return child->hasTagName(SVGNames::svgTag) || isSVGElement();
1564
1565     return Node::childShouldCreateRenderer(child);
1566 }
1567 #endif
1568
1569 } // namespace WebCore