Bug 378518 - Remove support for tag names in XBL extends attribute
authorSurya Ismail <suryaismail@gmail.com>
Thu, 17 Jul 2008 12:46:51 -0400
changeset 16019 e888893e48ba591e6003a6106ef3b039dbe484e3
parent 16018 46f960ae599461db1105b0d3ae538dd4d5694ff0
child 16020 2ac85f53e36b49274aeff8685038016c00468f06
push id691
push usersdwilsh@shawnwilsher.com
push dateThu, 17 Jul 2008 16:47:57 +0000
treeherderautoland@e888893e48ba [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs378518
milestone1.9.1a1pre
Bug 378518 - Remove support for tag names in XBL extends attribute r=Enn, sr=sicking
content/xbl/src/nsXBLService.cpp
content/xbl/test/Makefile.in
content/xbl/test/test_bug378518.xul
dom/locales/en-US/chrome/layout/xbl.properties
--- a/content/xbl/src/nsXBLService.cpp
+++ b/content/xbl/src/nsXBLService.cpp
@@ -142,16 +142,41 @@ IsAncestorBinding(nsIDocument* aDocument
                                       "XBL");
       return PR_TRUE;
     }
   }
 
   return PR_FALSE;
 }
 
+PRBool CheckTagNameWhiteList(PRInt32 aNameSpaceID, nsIAtom *aTagName)
+{
+  static nsIContent::AttrValuesArray kValidXULTagNames[] =  {
+    &nsGkAtoms::autorepeatbutton, &nsGkAtoms::box, &nsGkAtoms::browser,
+    &nsGkAtoms::button, &nsGkAtoms::hbox, &nsGkAtoms::image, &nsGkAtoms::menu,
+    &nsGkAtoms::menubar, &nsGkAtoms::menuitem, &nsGkAtoms::menupopup,
+    &nsGkAtoms::row, &nsGkAtoms::slider, &nsGkAtoms::spacer,
+    &nsGkAtoms::splitter, &nsGkAtoms::text, &nsGkAtoms::tree, nsnull};
+
+  PRUint32 i;
+  if (aNameSpaceID == kNameSpaceID_XUL) {
+    for (i = 0; kValidXULTagNames[i]; ++i) {
+      if (aTagName == *(kValidXULTagNames[i])) {
+        return PR_TRUE;
+      }
+    }
+  }
+  else if (aNameSpaceID == kNameSpaceID_SVG &&
+           aTagName == nsGkAtoms::generic) {
+    return PR_TRUE;
+  }
+
+  return PR_FALSE;
+}
+
 // Individual binding requests.
 class nsXBLBindingRequest
 {
 public:
   nsCOMPtr<nsIURI> mBindingURI;
   nsCOMPtr<nsIContent> mBoundElement;
 
   static nsXBLBindingRequest*
@@ -864,16 +889,30 @@ nsXBLService::GetBinding(nsIContent* aBo
               protoBinding->SetHasBasePrototype(PR_FALSE);
               //child->UnsetAttr(kNameSpaceID_None, nsGkAtoms::extends, PR_FALSE);
             }
 
             PRInt32 nameSpaceID =
               nsContentUtils::NameSpaceManager()->GetNameSpaceID(nameSpace);
 
             nsCOMPtr<nsIAtom> tagName = do_GetAtom(display);
+            // Check the white list
+            if (!CheckTagNameWhiteList(nameSpaceID, tagName)) {
+              const PRUnichar* params[] = { display.get() };
+              nsContentUtils::ReportToConsole(nsContentUtils::eXBL_PROPERTIES,
+                                              "InvalidExtendsBinding",
+                                              params, NS_ARRAY_LENGTH(params),
+                                              doc->GetDocumentURI(),
+                                              EmptyString(), 0, 0,
+                                              nsIScriptError::errorFlag,
+                                              "XBL");
+              NS_ERROR("Invalid extends value");
+              return NS_ERROR_ILLEGAL_VALUE;
+            }
+
             protoBinding->SetBaseTag(nameSpaceID, tagName);
           }
         }
       }
 
       if (hasExtends && (hasDisplay || nameSpace.IsEmpty())) {
         // Look up the prefix.
         // We have a base class binding. Load it right now.
--- a/content/xbl/test/Makefile.in
+++ b/content/xbl/test/Makefile.in
@@ -48,16 +48,17 @@ include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =	\
 		test_bug296375.xul \
 		test_bug310107.html \
 		bug310107-resource.xhtml \
 		test_bug366770.html \
 		test_bug371724.xhtml \
 		test_bug372769.xhtml \
+		test_bug378518.xul \
 		test_bug378866.xhtml \
 		test_bug397934.xhtml \
 		test_bug389322.xhtml \
 		test_bug398135.xhtml \
 		test_bug398492.xul \
 		test_bug400705.xhtml \
 		test_bug401907.xhtml \
 		test_bug403162.xhtml \
new file mode 100644
--- /dev/null
+++ b/content/xbl/test/test_bug378518.xul
@@ -0,0 +1,83 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="/tests/SimpleTest/test.css" type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=378518
+-->
+<window title="Mozilla Bug 378518"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+    
+  <script type="application/javascript" src="/MochiKit/packed.js" />
+  <script type="application/javascript"
+    src="/tests/SimpleTest/SimpleTest.js"/>
+
+  <bindings xmlns="http://www.mozilla.org/xbl"
+    xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+      <binding id="mybinding" extends="xul:checkbox">
+          <content>
+          </content>
+      </binding>
+
+  </bindings>
+
+  <!-- test resuls are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+      <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=378518"
+         target="_blank">Mozilla Bug 378518</a>
+  </body>
+
+   <!-- The elements we're testing with -->
+  <command id="myBoxCommand" oncommand="myBoxClicked = true;"/>
+  <command id="myCheckBoxCommand" oncommand="myCheckBoxClicked = true;"/>
+  <command id="myExtendedBoxCommand" oncommand="myExtendedBoxClicked = true;"/>
+
+  <box id="myBox" command="myBoxCommand">
+    <label>myBox</label>
+  </box>
+
+  <checkbox id="myCheckBox" command="myCheckBoxCommand" label="myCheckBox"/>
+
+  <box id="myExtendedBox" command="myExtendedBoxCommand"
+    style="-moz-binding:url(#mybinding)">
+    <label>myExtendedBox</label>
+  </box>
+
+  <!-- test code goes here -->
+  <script type="application/javascript"> <![CDATA[
+
+    var myBoxClicked = false;
+    var myCheckBoxClicked = false;
+    var myExtendedBoxClicked = false;
+
+    function testClick(elemName) {
+      netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+      var wu  =
+        window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+              .getInterface(Components.interfaces.nsIDOMWindowUtils);
+
+      var a = document.getElementById(elemName).getBoundingClientRect();
+      wu.sendMouseEvent('mousedown',  a.left + 1, a.top + 1, 0, 1, 0);
+      wu.sendMouseEvent('mouseup',  a.left + 1, a.top + 1, 0, 1, 0);
+    }
+
+    function doTest() {
+      testClick('myBox');
+      testClick('myCheckBox');
+      testClick('myExtendedBox');
+      ok(!myBoxClicked, "Shouldn't fire");
+      ok(myCheckBoxClicked, "Should fire");
+      ok(!myExtendedBoxClicked, "Shouldn't fire");
+      SimpleTest.finish();
+    }
+
+    /** Test for Bug 378518 **/
+    SimpleTest.waitForExplicitFinish();
+
+    addLoadEvent(function() {
+      setTimeout(doTest, 0);
+    });
+
+    ]]>
+    </script>
+</window>
--- a/dom/locales/en-US/chrome/layout/xbl.properties
+++ b/dom/locales/en-US/chrome/layout/xbl.properties
@@ -36,8 +36,9 @@
 UnexpectedElement=Unexpected <%1$S> element.
 # LOCALIZATION NOTE: do not localize key="%S" modifiers="%S"
 GTK2Conflict=Key event not available on GTK2: key="%S" modifiers="%S"
 WinConflict=Key event not available on some keyboard layouts: key="%S" modifiers="%S"
 TooDeepBindingRecursion=The XBL binding "%S" is already used by too many ancestor elements; not applying it to prevent infinite recursion.
 CircularExtendsBinding=Extending the XBL binding "%S" with "%S" would lead to it extending itself
 # LOCALIZATION NOTE: do not localize <handler command="…">
 CommandNotInChrome=Use of <handler command="…"> not allowed outside chrome.
+InvalidExtendsBinding=Extending "%S" is invalid. In general, do not extend tag names.