Bug 820902. nsAttrValue::Equals should do ASCII-case-insensitive compares when it's doing case-insensitive compares. r=sicking
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 13 Dec 2012 17:08:44 -0500
changeset 125204 7b9ffa4e1e64753b5ca65dbcd967815ae15cfac8
parent 125203 ba8c91f1d468724d44065727d771e50baf4386a9
child 125205 3e0b4ce62d6dd8c24c23b531ffb7ac8974ba2c3e
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking
bugs820902
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 820902. nsAttrValue::Equals should do ASCII-case-insensitive compares when it's doing case-insensitive compares. r=sicking
content/base/public/Element.h
content/base/src/nsAttrValue.cpp
content/base/src/nsAttrValue.h
content/base/src/nsDocument.cpp
content/events/src/nsEventStateManager.cpp
editor/libeditor/html/nsHTMLEditorStyle.cpp
layout/reftests/css-selectors/attr-case-insensitive-1-ref.html
layout/reftests/css-selectors/attr-case-insensitive-1.html
layout/reftests/css-selectors/reftest.list
--- a/content/base/public/Element.h
+++ b/content/base/public/Element.h
@@ -458,16 +458,17 @@ public:
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix,
                            const nsAString& aValue, bool aNotify);
   virtual nsresult SetParsedAttr(int32_t aNameSpaceID, nsIAtom* aName,
                                  nsIAtom* aPrefix, nsAttrValue& aParsedValue,
                                  bool aNotify);
   virtual bool GetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                          nsAString& aResult) const;
   virtual bool HasAttr(int32_t aNameSpaceID, nsIAtom* aName) const;
+  // aCaseSensitive == eIgnoreCaase means ASCII case-insensitive matching.
   virtual bool AttrValueIs(int32_t aNameSpaceID, nsIAtom* aName,
                              const nsAString& aValue,
                              nsCaseTreatment aCaseSensitive) const;
   virtual bool AttrValueIs(int32_t aNameSpaceID, nsIAtom* aName,
                              nsIAtom* aValue,
                              nsCaseTreatment aCaseSensitive) const;
   virtual int32_t FindAttrValueIn(int32_t aNameSpaceID,
                                   nsIAtom* aName,
--- a/content/base/src/nsAttrValue.cpp
+++ b/content/base/src/nsAttrValue.cpp
@@ -1061,34 +1061,35 @@ nsAttrValue::Equals(const nsAString& aVa
   switch (BaseType()) {
     case eStringBase:
     {
       nsStringBuffer* str = static_cast<nsStringBuffer*>(GetPtr());
       if (str) {
         nsDependentString dep(static_cast<PRUnichar*>(str->Data()),
                               str->StorageSize()/sizeof(PRUnichar) - 1);
         return aCaseSensitive == eCaseMatters ? aValue.Equals(dep) :
-          aValue.Equals(dep, nsCaseInsensitiveStringComparator());
+          nsContentUtils::EqualsIgnoreASCIICase(aValue, dep);
       }
       return aValue.IsEmpty();
     }
     case eAtomBase:
       if (aCaseSensitive == eCaseMatters) {
         return static_cast<nsIAtom*>(GetPtr())->Equals(aValue);
       }
-      return nsDependentAtomString(static_cast<nsIAtom*>(GetPtr())).
-        Equals(aValue, nsCaseInsensitiveStringComparator());
+      return nsContentUtils::EqualsIgnoreASCIICase(
+          nsDependentAtomString(static_cast<nsIAtom*>(GetPtr())),
+          aValue);
     default:
       break;
   }
 
   nsAutoString val;
   ToString(val);
   return aCaseSensitive == eCaseMatters ? val.Equals(aValue) :
-    val.Equals(aValue, nsCaseInsensitiveStringComparator());
+    nsContentUtils::EqualsIgnoreASCIICase(val, aValue);
 }
 
 bool
 nsAttrValue::Equals(nsIAtom* aValue, nsCaseTreatment aCaseSensitive) const
 {
   if (aCaseSensitive != eCaseMatters) {
     // Need a better way to handle this!
     nsAutoString value;
--- a/content/base/src/nsAttrValue.h
+++ b/content/base/src/nsAttrValue.h
@@ -195,16 +195,17 @@ public:
   // to call this without checking the type first; it handles that.
   uint32_t GetAtomCount() const;
   // Returns the atom at aIndex (0-based).  Do not call this with
   // aIndex >= GetAtomCount().
   nsIAtom* AtomAt(int32_t aIndex) const;
 
   uint32_t HashValue() const;
   bool Equals(const nsAttrValue& aOther) const;
+  // aCaseSensitive == eIgnoreCase means ASCII case-insenstive matching
   bool Equals(const nsAString& aValue, nsCaseTreatment aCaseSensitive) const;
   bool Equals(nsIAtom* aValue, nsCaseTreatment aCaseSensitive) const;
 
   /**
    * Compares this object with aOther according to their string representation.
    *
    * For example, when called on an object with type eInteger and value 4, and
    * given aOther of type eString and value "4", EqualsAsStrings will return
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -7940,22 +7940,23 @@ nsDocument::FindImageMap(const nsAString
 
   const nsAString& mapName = Substring(start, end);
 
   if (!mImageMaps) {
     mImageMaps = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::map, nsGkAtoms::map);
   }
 
   uint32_t i, n = mImageMaps->Length(true);
+  nsString name;
   for (i = 0; i < n; ++i) {
     nsIContent* map = mImageMaps->Item(i);
     if (map->AttrValueIs(kNameSpaceID_None, nsGkAtoms::id, mapName,
                          eCaseMatters) ||
-        map->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, mapName,
-                         eIgnoreCase)) {
+        (map->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name) &&
+         mapName.Equals(name, nsCaseInsensitiveStringComparator()))) {
       return map->AsElement();
     }
   }
 
   return nullptr;
 }
 
 #define DEPRECATED_OPERATION(_op) #_op "Warning",
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -1293,18 +1293,21 @@ GetAccessModifierMask(nsISupports* aDocS
   default:
     return -1; // invalid modifier
   }
 }
 
 static bool
 IsAccessKeyTarget(nsIContent* aContent, nsIFrame* aFrame, nsAString& aKey)
 {
-  if (!aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::accesskey, aKey,
-                             eIgnoreCase))
+  // Use GetAttr because we want Unicode case=insensitive matching
+  // XXXbz shouldn't this be case-sensitive, per spec?
+  nsString contentKey;
+  if (!aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, contentKey) ||
+      !contentKey.Equals(aKey, nsCaseInsensitiveStringComparator()))
     return false;
 
   nsCOMPtr<nsIDOMXULDocument> xulDoc =
     do_QueryInterface(aContent->OwnerDoc());
   if (!xulDoc && !aContent->IsXUL())
     return true;
 
     // For XUL we do visibility checks.
--- a/editor/libeditor/html/nsHTMLEditorStyle.cpp
+++ b/editor/libeditor/html/nsHTMLEditorStyle.cpp
@@ -293,18 +293,20 @@ nsHTMLEditor::IsSimpleModifiableNode(nsI
     return true;
   }
 
   // Now look for things like <font>
   if (aAttribute && !aAttribute->IsEmpty()) {
     nsCOMPtr<nsIAtom> atom = do_GetAtom(*aAttribute);
     MOZ_ASSERT(atom);
 
+    nsString attrValue;
     if (element->IsHTML(aProperty) && IsOnlyAttribute(element, *aAttribute) &&
-        element->AttrValueIs(kNameSpaceID_None, atom, *aValue, eIgnoreCase)) {
+        element->GetAttr(kNameSpaceID_None, atom, attrValue) &&
+        attrValue.Equals(*aValue, nsCaseInsensitiveStringComparator())) {
       // This is not quite correct, because it excludes cases like
       // <font face=000> being the same as <font face=#000000>.
       // Property-specific handling is needed (bug 760211).
       return true;
     }
   }
 
   // No luck so far.  Now we check for a <span> with a single style=""
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-selectors/attr-case-insensitive-1-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+<style type="text/css">
+.ascii > span {
+  background-color: yellow;
+}
+</style>
+</head>
+<body>
+
+<div class="ascii"><span lang="paSSfield-killroyß">case-sensitive</span></div>
+<div class="ascii"><span lang="passfield-killroyß">lowercase</span></div>
+<div class="ascii"><span lang="PASSFIELD-KILLROYß">uppercase</span></div>
+<div class="nonascii"><span lang="paſſfield-killroyß">small long s (C)</span></div>
+<div class="nonascii"><span lang="passfield-&#x212a;illroyß">kelvin sign (C)</span></div>
+<div class="nonascii"><span lang="paßfield-killroyß">small sharp s (F)</span></div>
+<div class="nonascii"><span lang="paẞfield-killroyß">capital sharp s (F)</span></div>
+<div class="nonascii"><span lang="passfield-killroyẞ">capital sharp s (S)</span></div>
+<div class="nonascii"><span lang="passfield-killroyß">fi ligature (U+fb01) (F)</span></div>
+<div class="nonascii"><span lang="passfıeld-killroyß"> dotless i (T)</span></div>
+<div class="nonascii"><span lang="passfİeld-killroyß">dotted I (T)</span></div>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-selectors/attr-case-insensitive-1.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+<style type="text/css">
+span[lang="paSSfield-killroyß"] {
+  background-color: yellow;
+}
+</style>
+</head>
+<body>
+
+<div class="ascii"><span lang="paSSfield-killroyß">case-sensitive</span></div>
+<div class="ascii"><span lang="passfield-killroyß">lowercase</span></div>
+<div class="ascii"><span lang="PASSFIELD-KILLROYß">uppercase</span></div>
+<div class="nonascii"><span lang="paſſfield-killroyß">small long s (C)</span></div>
+<div class="nonascii"><span lang="passfield-&#x212a;illroyß">kelvin sign (C)</span></div>
+<div class="nonascii"><span lang="paßfield-killroyß">small sharp s (F)</span></div>
+<div class="nonascii"><span lang="paẞfield-killroyß">capital sharp s (F)</span></div>
+<div class="nonascii"><span lang="passfield-killroyẞ">capital sharp s (S)</span></div>
+<div class="nonascii"><span lang="passfield-killroyß">fi ligature (U+fb01) (F)</span></div>
+<div class="nonascii"><span lang="passfıeld-killroyß"> dotless i (T)</span></div>
+<div class="nonascii"><span lang="passfİeld-killroyß">dotted I (T)</span></div>
+
+</body>
+</html>
--- a/layout/reftests/css-selectors/reftest.list
+++ b/layout/reftests/css-selectors/reftest.list
@@ -1,1 +1,2 @@
 == state-dependent-in-any.html state-dependent-in-any-ref.html
+== attr-case-insensitive-1.html attr-case-insensitive-1-ref.html