diff options
Diffstat (limited to 'WebCore/dom/Element.cpp')
-rw-r--r-- | WebCore/dom/Element.cpp | 156 |
1 files changed, 100 insertions, 56 deletions
diff --git a/WebCore/dom/Element.cpp b/WebCore/dom/Element.cpp index d7f1b11..ac4fdb3 100644 --- a/WebCore/dom/Element.cpp +++ b/WebCore/dom/Element.cpp @@ -42,6 +42,7 @@ #include "FrameView.h" #include "HTMLElement.h" #include "HTMLNames.h" +#include "InspectorController.h" #include "NamedNodeMap.h" #include "NodeList.h" #include "NodeRenderStyle.h" @@ -159,21 +160,6 @@ NamedNodeMap* Element::attributes() const return attributes(false); } -NamedNodeMap* Element::attributes(bool readonly) const -{ - if (!m_isStyleAttributeValid) - updateStyleAttribute(); - -#if ENABLE(SVG) - if (!m_areSVGAttributesValid) - updateAnimatedSVGAttribute(String()); -#endif - - if (!readonly && !namedAttrMap) - createAttributeMap(); - return namedAttrMap.get(); -} - Node::NodeType Element::nodeType() const { return ELEMENT_NODE; @@ -196,7 +182,7 @@ const AtomicString& Element::getAttribute(const QualifiedName& name) const #if ENABLE(SVG) if (!m_areSVGAttributesValid) - updateAnimatedSVGAttribute(name.localName()); + updateAnimatedSVGAttribute(name); #endif if (namedAttrMap) @@ -502,8 +488,10 @@ const AtomicString& Element::getAttribute(const String& name) const updateStyleAttribute(); #if ENABLE(SVG) - if (!m_areSVGAttributesValid) - updateAnimatedSVGAttribute(name); + if (!m_areSVGAttributesValid) { + // We're not passing a namespace argument on purpose. SVGNames::*Attr are defined w/o namespaces as well. + updateAnimatedSVGAttribute(QualifiedName(nullAtom, name, nullAtom)); + } #endif if (namedAttrMap) @@ -532,9 +520,9 @@ void Element::setAttribute(const AtomicString& name, const AtomicString& value, document()->incDOMTreeVersion(); - if (localName == idAttr.localName()) + if (localName == idAttributeName().localName()) updateId(old ? old->value() : nullAtom, value); - + if (old && value.isNull()) namedAttrMap->removeAttribute(old->name()); else if (!old && !value.isNull()) @@ -543,6 +531,15 @@ void Element::setAttribute(const AtomicString& name, const AtomicString& value, old->setValue(value); attributeChanged(old); } + +#if ENABLE(INSPECTOR) + if (Page* page = document()->page()) { + if (InspectorController* inspectorController = page->inspectorController()) { + if (!m_synchronizingStyleAttribute) + inspectorController->didModifyDOMAttr(this); + } + } +#endif } void Element::setAttribute(const QualifiedName& name, const AtomicString& value, ExceptionCode&) @@ -552,9 +549,9 @@ void Element::setAttribute(const QualifiedName& name, const AtomicString& value, // allocate attributemap if necessary Attribute* old = attributes(false)->getAttributeItem(name); - if (name == idAttr) + if (name == idAttributeName()) updateId(old ? old->value() : nullAtom, value); - + if (old && value.isNull()) namedAttrMap->removeAttribute(name); else if (!old && !value.isNull()) @@ -563,6 +560,15 @@ void Element::setAttribute(const QualifiedName& name, const AtomicString& value, old->setValue(value); attributeChanged(old); } + +#if ENABLE(INSPECTOR) + if (Page* page = document()->page()) { + if (InspectorController* inspectorController = page->inspectorController()) { + if (!m_synchronizingStyleAttribute) + inspectorController->didModifyDOMAttr(this); + } + } +#endif } PassRefPtr<Attribute> Element::createAttribute(const QualifiedName& name, const AtomicString& value) @@ -578,20 +584,22 @@ void Element::attributeChanged(Attribute* attr, bool) void Element::updateAfterAttributeChanged(Attribute* attr) { - AXObjectCache* axObjectCache = document()->axObjectCache(); - if (!axObjectCache->accessibilityEnabled()) + if (!AXObjectCache::accessibilityEnabled()) return; const QualifiedName& attrName = attr->name(); if (attrName == aria_activedescendantAttr) { // any change to aria-activedescendant attribute triggers accessibility focus change, but document focus remains intact - axObjectCache->handleActiveDescendantChanged(renderer()); + document()->axObjectCache()->handleActiveDescendantChanged(renderer()); } else if (attrName == roleAttr) { // the role attribute can change at any time, and the AccessibilityObject must pick up these changes - axObjectCache->handleAriaRoleChanged(renderer()); + document()->axObjectCache()->handleAriaRoleChanged(renderer()); } else if (attrName == aria_valuenowAttr) { // If the valuenow attribute changes, AX clients need to be notified. - axObjectCache->postNotification(renderer(), AXObjectCache::AXValueChanged, true); + document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXValueChanged, true); + } else if (attrName == aria_labelAttr || attrName == aria_labeledbyAttr || attrName == altAttr || attrName == titleAttr) { + // If the content of an element changes due to an attribute change, notify accessibility. + document()->axObjectCache()->contentChanged(renderer()); } } @@ -600,15 +608,31 @@ void Element::recalcStyleIfNeededAfterAttributeChanged(Attribute* attr) if (document()->attached() && document()->styleSelector()->hasSelectorForAttribute(attr->name().localName())) setNeedsStyleRecalc(); } - -void Element::setAttributeMap(PassRefPtr<NamedNodeMap> list) + +// Returns true is the given attribute is an event handler. +// We consider an event handler any attribute that begins with "on". +// It is a simple solution that has the advantage of not requiring any +// code or configuration change if a new event handler is defined. + +static bool isEventHandlerAttribute(const QualifiedName& name) +{ + return name.namespaceURI().isNull() && name.localName().startsWith("on"); +} + +static bool isAttributeToRemove(const QualifiedName& name, const AtomicString& value) +{ + return (name.localName().endsWith(hrefAttr.localName()) || name == srcAttr || name == actionAttr) && protocolIsJavaScript(deprecatedParseURL(value)); +} + +void Element::setAttributeMap(PassRefPtr<NamedNodeMap> list, FragmentScriptingPermission scriptingPermission) { document()->incDOMTreeVersion(); // If setting the whole map changes the id attribute, we need to call updateId. - Attribute* oldId = namedAttrMap ? namedAttrMap->getAttributeItem(idAttr) : 0; - Attribute* newId = list ? list->getAttributeItem(idAttr) : 0; + const QualifiedName& idName = idAttributeName(); + Attribute* oldId = namedAttrMap ? namedAttrMap->getAttributeItem(idName) : 0; + Attribute* newId = list ? list->getAttributeItem(idName) : 0; if (oldId || newId) updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom); @@ -620,6 +644,22 @@ void Element::setAttributeMap(PassRefPtr<NamedNodeMap> list) if (namedAttrMap) { namedAttrMap->m_element = this; + // If the element is created as result of a paste or drag-n-drop operation + // we want to remove all the script and event handlers. + if (scriptingPermission == FragmentScriptingNotAllowed) { + unsigned i = 0; + while (i < namedAttrMap->length()) { + const QualifiedName& attributeName = namedAttrMap->m_attributes[i]->name(); + if (isEventHandlerAttribute(attributeName)) { + namedAttrMap->m_attributes.remove(i); + continue; + } + + if (isAttributeToRemove(attributeName, namedAttrMap->m_attributes[i]->value())) + namedAttrMap->m_attributes[i]->setValue(nullAtom); + i++; + } + } unsigned len = namedAttrMap->length(); for (unsigned i = 0; i < len; i++) attributeChanged(namedAttrMap->m_attributes[i].get()); @@ -634,7 +674,7 @@ bool Element::hasAttributes() const #if ENABLE(SVG) if (!m_areSVGAttributesValid) - updateAnimatedSVGAttribute(String()); + updateAnimatedSVGAttribute(anyQName()); #endif return namedAttrMap && namedAttrMap->length() > 0; @@ -650,14 +690,14 @@ String Element::nodeNamePreservingCase() const return m_tagName.toString(); } -void Element::setPrefix(const AtomicString &_prefix, ExceptionCode& ec) +void Element::setPrefix(const AtomicString& prefix, ExceptionCode& ec) { ec = 0; - checkSetPrefix(_prefix, ec); + checkSetPrefix(prefix, ec); if (ec) return; - m_tagName.setPrefix(_prefix); + m_tagName.setPrefix(prefix.isEmpty() ? AtomicString() : prefix); } KURL Element::baseURI() const @@ -713,7 +753,7 @@ void Element::insertedIntoDocument() if (hasID()) { if (NamedNodeMap* attrs = namedAttrMap.get()) { - Attribute* idItem = attrs->getAttributeItem(idAttr); + Attribute* idItem = attrs->getAttributeItem(idAttributeName()); if (idItem && !idItem->isNull()) updateId(nullAtom, idItem->value()); } @@ -724,7 +764,7 @@ void Element::removedFromDocument() { if (hasID()) { if (NamedNodeMap* attrs = namedAttrMap.get()) { - Attribute* idItem = attrs->getAttributeItem(idAttr); + Attribute* idItem = attrs->getAttributeItem(idAttributeName()); if (idItem && !idItem->isNull()) updateId(idItem->value(), nullAtom); } @@ -1001,6 +1041,7 @@ void Element::finishParsingChildren() void Element::dispatchAttrRemovalEvent(Attribute*) { ASSERT(!eventDispatchForbidden()); + #if 0 if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER)) return; @@ -1013,6 +1054,7 @@ void Element::dispatchAttrRemovalEvent(Attribute*) void Element::dispatchAttrAdditionEvent(Attribute*) { ASSERT(!eventDispatchForbidden()); + #if 0 if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER)) return; @@ -1047,21 +1089,6 @@ String Element::openTagStartToString() const return result; } -void Element::updateId(const AtomicString& oldId, const AtomicString& newId) -{ - if (!inDocument()) - return; - - if (oldId == newId) - return; - - Document* doc = document(); - if (!oldId.isEmpty()) - doc->removeElementById(oldId, this); - if (!newId.isEmpty()) - doc->addElementById(newId, this); -} - #ifndef NDEBUG void Element::formatForDebugger(char* buffer, unsigned length) const { @@ -1073,7 +1100,7 @@ void Element::formatForDebugger(char* buffer, unsigned length) const result += s; } - s = getAttribute(idAttr); + s = getAttribute(idAttributeName()); if (s.length() > 0) { if (result.length() > 0) result += "; "; @@ -1133,13 +1160,17 @@ PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionCode& ec) return static_pointer_cast<Attr>(attrs->removeNamedItem(attr->qualifiedName(), ec)); } -void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode& ec) +void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode& ec, FragmentScriptingPermission scriptingPermission) { String prefix, localName; if (!Document::parseQualifiedName(qualifiedName, prefix, localName, ec)) return; QualifiedName qName(prefix, localName, namespaceURI); + + if (scriptingPermission == FragmentScriptingNotAllowed && (isEventHandlerAttribute(qName) || isAttributeToRemove(qName, value))) + return; + setAttribute(qName, value, ec); } @@ -1152,6 +1183,14 @@ void Element::removeAttribute(const String& name, ExceptionCode& ec) if (ec == NOT_FOUND_ERR) ec = 0; } + +#if ENABLE(INSPECTOR) + if (Page* page = document()->page()) { + if (InspectorController* inspectorController = page->inspectorController()) + inspectorController->didModifyDOMAttr(this); + } +#endif + } void Element::removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode& ec) @@ -1250,7 +1289,7 @@ void Element::updateFocusAppearance(bool /*restorePreviousSelection*/) } } // FIXME: I'm not sure all devices will want this off, but this is - // currently turned off for Andriod. + // currently turned off for Android. #if !ENABLE(DIRECTIONAL_PAD_NAVIGATION) else if (renderer() && !renderer()->isWidget()) renderer()->enclosingLayer()->scrollRectToVisible(getRect()); @@ -1423,7 +1462,7 @@ bool Element::webkitMatchesSelector(const String& selector, ExceptionCode& ec) KURL Element::getURLAttribute(const QualifiedName& name) const { -#ifndef NDEBUG +#if !ASSERT_DISABLED if (namedAttrMap) { if (Attribute* attribute = namedAttrMap->getAttributeItem(name)) ASSERT(isURLAttribute(attribute)); @@ -1432,4 +1471,9 @@ KURL Element::getURLAttribute(const QualifiedName& name) const return document()->completeURL(deprecatedParseURL(getAttribute(name))); } +const QualifiedName& Element::rareIDAttributeName() const +{ + return rareData()->m_idAttributeName; +} + } // namespace WebCore |