Cherry-pick WebKit security fix (webkit.org r68096) Do not merge

See http://trac.webkit.org/changeset/68096

Note that this is not an exact cherry pick of the above webkit
CL as it is dependant on http://trac.webkit.org/changeset/61094
that we do not have and provides the Element::isIdAttributName and
Element::getIdAttribute methods. 61094 is a large change so we do
not take it, rather use methods that achieve the same effect.

Change-Id: Ifae90116f794673a610dd7988ba366a0b51888d9
diff --git a/WebCore/dom/Attr.cpp b/WebCore/dom/Attr.cpp
index 2ef5f9b..1272b38 100644
--- a/WebCore/dom/Attr.cpp
+++ b/WebCore/dom/Attr.cpp
@@ -117,13 +117,21 @@
     return value();
 }
 
-void Attr::setValue(const AtomicString& value, ExceptionCode&)
+void Attr::setValue(const AtomicString& value)
 {
     m_ignoreChildrenChanged++;
     removeChildren();
     m_attribute->setValue(value);
     createTextChild();
     m_ignoreChildrenChanged--;
+}
+
+void Attr::setValue(const AtomicString& value, ExceptionCode&)
+{
+    if (m_element && m_attribute->name() == m_element->idAttributeName())
+        m_element->updateId(m_element->getIDAttribute(), value);
+
+    setValue(value);
 
     if (m_element)
         m_element->attributeChanged(m_attribute.get());
@@ -167,7 +175,10 @@
         if (n->isTextNode())
             val += static_cast<Text *>(n)->data();
     }
-    
+
+    if (m_element && m_attribute->name() == m_element->idAttributeName())
+        m_element->updateId(m_attribute->value(), val);
+
     m_attribute->setValue(val.impl());
     if (m_element)
         m_element->attributeChanged(m_attribute.get());
diff --git a/WebCore/dom/Attr.h b/WebCore/dom/Attr.h
index 2e02a02..e76d2fa 100644
--- a/WebCore/dom/Attr.h
+++ b/WebCore/dom/Attr.h
@@ -48,6 +48,7 @@
 
     const AtomicString& value() const { return m_attribute->value(); }
     void setValue(const AtomicString&, ExceptionCode&);
+    void setValue(const AtomicString&);
 
     Attribute* attr() const { return m_attribute.get(); }
     const QualifiedName& qualifiedName() const { return m_attribute->name(); }
diff --git a/WebCore/dom/Document.cpp b/WebCore/dom/Document.cpp
index c631956..9b8ffb7 100644
--- a/WebCore/dom/Document.cpp
+++ b/WebCore/dom/Document.cpp
@@ -1112,8 +1112,10 @@
 
     if (m_elementsById.get(elementId.impl()) == element)
         m_elementsById.remove(elementId.impl());
-    else
+    else {
+        ASSERT(m_inRemovedLastRefFunction || m_duplicateIds.contains(elementId.impl()));
         m_duplicateIds.remove(elementId.impl());
+    }
 }
 
 Element* Document::getElementByAccessKey(const String& key) const
diff --git a/WebCore/dom/Element.cpp b/WebCore/dom/Element.cpp
index e12d326..93200a7 100644
--- a/WebCore/dom/Element.cpp
+++ b/WebCore/dom/Element.cpp
@@ -528,7 +528,10 @@
     else if (!old && !value.isNull())
         namedAttrMap->addAttribute(createAttribute(QualifiedName(nullAtom, localName, nullAtom), value));
     else if (old && !value.isNull()) {
-        old->setValue(value);
+        if (Attr* attrNode = old->attr())
+            attrNode->setValue(value);
+        else
+            old->setValue(value);
         attributeChanged(old);
     }
 
@@ -557,7 +560,10 @@
     else if (!old && !value.isNull())
         namedAttrMap->addAttribute(createAttribute(name, value));
     else if (old) {
-        old->setValue(value);
+        if (Attr* attrNode = old->attr())
+            attrNode->setValue(value);
+        else
+            old->setValue(value);
         attributeChanged(old);
     }