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