summaryrefslogtreecommitdiffstats
path: root/WebCore/dom/Element.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/dom/Element.cpp')
-rw-r--r--WebCore/dom/Element.cpp156
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