Bug 763343 - Handle classinfo singletons in cross-compartment wrapping. r=peterv
authorBobby Holley <bobbyholley@gmail.com>
Fri, 13 Jul 2012 14:33:25 +0200
changeset 101899 43e70deac1241da9c04f0b28877136a3fb196cfc
parent 101898 ab3a6f89cb7f9e14a205cdd292477ab90a0428e8
child 101900 784d3448dfe3b68f420d225d1cd2a78dd1418342
push id1729
push userlsblakk@mozilla.com
push dateMon, 16 Jul 2012 20:02:43 +0000
treeherdermozilla-aurora@f4e75e148951 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs763343
milestone16.0a1
Bug 763343 - Handle classinfo singletons in cross-compartment wrapping. r=peterv
dom/base/nsDOMClassInfo.cpp
js/xpconnect/src/XPCWrappedNative.cpp
js/xpconnect/tests/chrome/Makefile.in
js/xpconnect/tests/chrome/test_bug763343.xul
xpcom/components/nsIClassInfo.idl
xpcom/glue/nsIClassInfoImpl.h
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -604,17 +604,19 @@ static const char kDOMStringBundleURL[] 
 #define EVENTTARGET_SCRIPTABLE_FLAGS                                          \
   (DOM_DEFAULT_SCRIPTABLE_FLAGS       |                                       \
    nsIXPCScriptable::WANT_ADDPROPERTY)
 
 #define IDBEVENTTARGET_SCRIPTABLE_FLAGS                                       \
   (EVENTTARGET_SCRIPTABLE_FLAGS)
 
 #define DOMCLASSINFO_STANDARD_FLAGS                                           \
-  (nsIClassInfo::MAIN_THREAD_ONLY | nsIClassInfo::DOM_OBJECT)
+  (nsIClassInfo::MAIN_THREAD_ONLY |                                           \
+   nsIClassInfo::DOM_OBJECT       |                                           \
+   nsIClassInfo::SINGLETON_CLASSINFO)
 
 
 #ifdef DEBUG
 #define NS_DEFINE_CLASSINFO_DATA_DEBUG(_class)                                \
     eDOMClassInfo_##_class##_id,
 #else
 #define NS_DEFINE_CLASSINFO_DATA_DEBUG(_class)                                \
   // nothing
@@ -10707,17 +10709,17 @@ nsDOMConstructorSH::HasInstance(nsIXPCon
 }
 
 NS_IMETHODIMP
 nsNonDOMObjectSH::GetFlags(PRUint32 *aFlags)
 {
   // This is NOT a DOM Object.  Use this helper class for cases when you need
   // to do something like implement nsISecurityCheckedComponent in a meaningful
   // way.
-  *aFlags = nsIClassInfo::MAIN_THREAD_ONLY;
+  *aFlags = nsIClassInfo::MAIN_THREAD_ONLY | nsIClassInfo::SINGLETON_CLASSINFO;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAttributeSH::GetFlags(PRUint32 *aFlags)
 {
   // Just like nsNodeSH, but without CONTENT_NODE
   *aFlags = DOMCLASSINFO_STANDARD_FLAGS;
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -482,18 +482,24 @@ XPCWrappedNative::GetNewOrUsed(XPCCallCo
     //
     // To handle this we need to get the scriptable helper early and ask it.
     // It is possible that we will then end up forwarding this entire call
     // to this same function but with a different scope.
 
     // If we are making a wrapper for the nsIClassInfo interface then
     // We *don't* want to have it use the prototype meant for instances
     // of that class.
-    JSBool isClassInfo = Interface &&
-                         Interface->GetIID()->Equals(NS_GET_IID(nsIClassInfo));
+    bool iidIsClassInfo = Interface &&
+                          Interface->GetIID()->Equals(NS_GET_IID(nsIClassInfo));
+    PRUint32 classInfoFlags;
+    bool isClassInfoSingleton = helper.GetClassInfo() == helper.Object() &&
+                                NS_SUCCEEDED(helper.GetClassInfo()
+                                                   ->GetFlags(&classInfoFlags)) &&
+                                (classInfoFlags & nsIClassInfo::SINGLETON_CLASSINFO);
+    bool isClassInfo = iidIsClassInfo || isClassInfoSingleton;
 
     nsIClassInfo *info = helper.GetClassInfo();
 
     XPCNativeScriptableCreateInfo sciProto;
     XPCNativeScriptableCreateInfo sci;
 
     // Gather scriptable create info if we are wrapping something
     // other than an nsIClassInfo object. We need to not do this for
--- a/js/xpconnect/tests/chrome/Makefile.in
+++ b/js/xpconnect/tests/chrome/Makefile.in
@@ -7,55 +7,56 @@ topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
 relativesrcdir  = js/xpconnect/tests/chrome
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_CHROME_FILES = \
 		test_bug448587.xul \
+		test_bug484459.xul \
 		test_bug500931.xul \
 		bug503926.xul \
 		test_bug503926.xul \
+		test_bug517163.xul \
 		test_bug533596.xul \
-		test_doublewrappedcompartments.xul \
-		test_evalInSandbox.xul \
-		file_evalInSandbox.html \
-		test_sandboxImport.xul \
-		test_wrappers.xul \
-		test_bug484459.xul \
-		test_cows.xul \
-		test_bug517163.xul \
 		test_bug571849.xul \
+		test_bug596580.xul \
 		test_bug601803.xul \
 		test_bug610390.xul \
 		test_bug614757.xul \
 		test_bug616992.xul \
 		test_bug618176.xul \
 		file_bug618176.xul \
-		test_bug596580.xul \
 		test_bug654370.xul \
 		test_bug658560.xul \
+		test_bug664689.xul \
 		test_bug679861.xul \
-		test_bug664689.xul \
 		test_bug706301.xul \
+		test_bug726949.xul \
 		test_bug743843.xul \
+		test_bug758563.xul \
+		test_bug760076.xul \
+		test_bug763343.xul \
 		test_APIExposer.xul \
-		test_precisegc.xul \
-		test_nodelists.xul \
-		test_getweakmapkeys.xul \
-		test_weakmaps.xul \
+		test_cows.xul \
+		test_documentdomain.xul \
+		test_doublewrappedcompartments.xul \
+		test_evalInSandbox.xul \
+		file_evalInSandbox.html \
 		test_exnstack.xul \
-		test_weakref.xul \
-		test_bug726949.xul \
 		test_expandosharing.xul \
 		file_expandosharing.jsm \
-		test_bug758563.xul \
-		test_bug760076.xul \
-		test_documentdomain.xul \
+		test_getweakmapkeys.xul \
+		test_nodelists.xul \
+		test_precisegc.xul \
+		test_sandboxImport.xul \
+		test_weakmaps.xul \
+		test_weakref.xul \
+		test_wrappers.xul \
 		$(NULL)
 
 # Disabled until this test gets updated to test the new proxy based
 # wrappers.
 #		test_wrappers-2.xul \
 
 # Disabled due to apparent conservative stack scanner false positives on Linux64 debug.
 #		test_watchpoints.xul \
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/chrome/test_bug763343.xul
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=763343
+-->
+<window title="Mozilla Bug 763343"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=763343"
+     target="_blank">Mozilla Bug 763343</a>
+  </body>
+
+  <!-- test code goes here -->
+  <script type="application/javascript">
+  <![CDATA[
+
+  /** Test for Cross-compartment nsIClassInfo singleton wrapping. **/
+  const Cc = Components.classes;
+  const Ci = Components.interfaces;
+  const Cu = Components.utils;
+
+  var singleton = window.QueryInterface(Ci.nsIClassInfo);
+  var sb = new Cu.Sandbox(window);
+
+  // Don't crash.
+  sb.singleton = singleton;
+  ok(true, "didn't crash");
+
+  ]]>
+  </script>
+</window>
--- a/xpcom/components/nsIClassInfo.idl
+++ b/xpcom/components/nsIClassInfo.idl
@@ -78,16 +78,17 @@ interface nsIClassInfo : nsISupports
     /**
      * Bitflags for 'flags' attribute.
      */
     const PRUint32 SINGLETON            = 1 << 0;
     const PRUint32 THREADSAFE           = 1 << 1;
     const PRUint32 MAIN_THREAD_ONLY     = 1 << 2;
     const PRUint32 DOM_OBJECT           = 1 << 3;
     const PRUint32 PLUGIN_OBJECT        = 1 << 4;
+    const PRUint32 SINGLETON_CLASSINFO  = 1 << 5;
 
     /**
      * 'flags' attribute bitflag: whether objects of this type implement
      * nsIContent.
      */
     const PRUint32 CONTENT_NODE         = 1 << 6;
     
     // The high order bit is RESERVED for consumers of these flags. 
--- a/xpcom/glue/nsIClassInfoImpl.h
+++ b/xpcom/glue/nsIClassInfoImpl.h
@@ -111,17 +111,17 @@ private:
   extern NS_IMETHODIMP NS_CI_INTERFACE_GETTER_NAME(_class)                    \
      (PRUint32 * NS_OUTPARAM, nsIID *** NS_OUTPARAM);
 
 #define NS_IMPL_CLASSINFO(_class, _getlanguagehelper, _flags, _cid)     \
   NS_DECL_CI_INTERFACE_GETTER(_class)                                   \
   static const GenericClassInfo::ClassInfoData k##_class##ClassInfoData = { \
     NS_CI_INTERFACE_GETTER_NAME(_class),                                \
     _getlanguagehelper,                                                 \
-    _flags,                                                             \
+    _flags | nsIClassInfo::SINGLETON_CLASSINFO,                         \
     _cid,                                                               \
   };                                                                    \
   static char k##_class##ClassInfoDataPlace[sizeof(GenericClassInfo)];  \
   nsIClassInfo* NS_CLASSINFO_NAME(_class) = NULL;
 
 #define NS_IMPL_QUERY_CLASSINFO(_class)                                       \
   if ( aIID.Equals(NS_GET_IID(nsIClassInfo)) ) {                              \
     if (!NS_CLASSINFO_NAME(_class))                                           \