Bug 718202. r=jst.
authorBen Turner <bent.mozilla@gmail.com>
Wed, 18 Jan 2012 10:05:38 -0800
changeset 84786 be734df2dcab1834060ca072a2bd96ca1b5a716b
parent 84785 1024e7260173e78c72a67dca365a4f91ad96567d
child 84787 a363fe2b2d3fff61b0da93d24486f7981433a239
push id5006
push userbturner@mozilla.com
push dateWed, 18 Jan 2012 18:11:25 +0000
treeherdermozilla-inbound@be734df2dcab [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjst
bugs718202
milestone12.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 718202. r=jst.
dom/workers/EventTarget.cpp
dom/workers/EventTarget.h
dom/workers/Worker.cpp
dom/workers/Worker.h
dom/workers/WorkerScope.cpp
dom/workers/WorkerScope.h
dom/workers/XMLHttpRequest.cpp
dom/workers/XMLHttpRequest.h
--- a/dom/workers/EventTarget.cpp
+++ b/dom/workers/EventTarget.cpp
@@ -37,16 +37,21 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "EventTarget.h"
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "nsTraceRefcnt.h"
 
+// All the EventTarget subclasses have to be included here.
+#include "Worker.h"
+#include "WorkerScope.h"
+#include "XMLHttpRequest.h"
+
 #include "WorkerInlines.h"
 
 USING_WORKERS_NAMESPACE
 
 using mozilla::dom::workers::events::EventTarget;
 
 namespace {
 
@@ -59,16 +64,33 @@ namespace {
   };
 
 DECL_EVENTTARGET_CLASS(gClass, "EventTarget")
 DECL_EVENTTARGET_CLASS(gMainThreadClass, "WorkerEventTarget")
 
 #undef DECL_EVENTTARGET_CLASS
 
 inline
+bool
+EnsureObjectIsEventTarget(JSContext* aCx, JSObject* aObj, char* aFunctionName)
+{
+  JSClass* classPtr = JS_GET_CLASS(aCx, aObj);
+  if (classPtr &&
+      (ClassIsWorker(classPtr) || ClassIsWorkerGlobalScope(classPtr) ||
+       ClassIsXMLHttpRequest(classPtr))) {
+    return true;
+  }
+
+  JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
+                       "EventTarget", aFunctionName,
+                        classPtr ? classPtr->name : "object");
+  return false;
+}
+
+inline
 EventTarget*
 GetPrivate(JSContext* aCx, JSObject* aObj)
 {
   return GetJSPrivateSafeish<EventTarget>(aCx, aObj);
 }
 
 JSBool
 Construct(JSContext* aCx, uintN aArgc, jsval* aVp)
@@ -138,16 +160,20 @@ EventTarget::FromJSObject(JSContext* aCx
 JSBool
 EventTarget::AddEventListener(JSContext* aCx, uintN aArgc, jsval* aVp)
 {
   JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
   if (!obj) {
     return true;
   }
 
+  if (!EnsureObjectIsEventTarget(aCx, obj, "AddEventListener")) {
+    return false;
+  }
+
   EventTarget* self = GetPrivate(aCx, obj);
   if (!self) {
     return true;
   }
 
   JSString* type;
   JSObject* listener;
   JSBool capturing = false, wantsUntrusted = false;
@@ -169,16 +195,20 @@ EventTarget::AddEventListener(JSContext*
 JSBool
 EventTarget::RemoveEventListener(JSContext* aCx, uintN aArgc, jsval* aVp)
 {
   JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
   if (!obj) {
     return true;
   }
 
+  if (!EnsureObjectIsEventTarget(aCx, obj, "RemoveEventListener")) {
+    return false;
+  }
+
   EventTarget* self = GetPrivate(aCx, obj);
   if (!self) {
     return true;
   }
 
   JSString* type;
   JSObject* listener;
   JSBool capturing = false;
@@ -200,16 +230,20 @@ EventTarget::RemoveEventListener(JSConte
 JSBool
 EventTarget::DispatchEvent(JSContext* aCx, uintN aArgc, jsval* aVp)
 {
   JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
   if (!obj) {
     return true;
   }
 
+  if (!EnsureObjectIsEventTarget(aCx, obj, "DispatchEvent")) {
+    return false;
+  }
+
   EventTarget* self = GetPrivate(aCx, obj);
   if (!self) {
     return true;
   }
 
   JSObject* event;
   if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "o", &event)) {
     return false;
--- a/dom/workers/EventTarget.h
+++ b/dom/workers/EventTarget.h
@@ -42,16 +42,18 @@
 #include "jspubtd.h"
 
 #include "ListenerManager.h"
 
 BEGIN_WORKERS_NAMESPACE
 
 namespace events {
 
+// If you inherit this class then you need to add some way to compare the
+// JSClass for your subclass in EnsureObjectIsEventTarget().
 class EventTarget : public PrivatizableBase
 {
   ListenerManager mListenerManager;
 
 protected:
   EventTarget();
   ~EventTarget();
 
--- a/dom/workers/Worker.cpp
+++ b/dom/workers/Worker.cpp
@@ -494,9 +494,15 @@ bool
 InitClass(JSContext* aCx, JSObject* aGlobal, JSObject* aProto,
           bool aMainRuntime)
 {
   return !!ChromeWorker::InitClass(aCx, aGlobal, aProto, aMainRuntime);
 }
 
 } // namespace chromeworker
 
+bool
+ClassIsWorker(JSClass* aClass)
+{
+  return Worker::Class() == aClass || ChromeWorker::Class() == aClass;
+}
+
 END_WORKERS_NAMESPACE
--- a/dom/workers/Worker.h
+++ b/dom/workers/Worker.h
@@ -59,11 +59,14 @@ ClearPrivateSlot(JSContext* aCx, JSObjec
 namespace chromeworker {
 
 bool
 InitClass(JSContext* aCx, JSObject* aGlobal, JSObject* aProto,
           bool aMainRuntime);
 
 } // namespace chromeworker
 
+bool
+ClassIsWorker(JSClass* aClass);
+
 END_WORKERS_NAMESPACE
 
 #endif /* mozilla_dom_workers_worker_h__ */
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -932,9 +932,16 @@ CreateDedicatedWorkerGlobalScope(JSConte
 
   if (!JS_DefineProfilingFunctions(aCx, global)) {
     return NULL;
   }
 
   return global;
 }
 
+bool
+ClassIsWorkerGlobalScope(JSClass* aClass)
+{
+  return WorkerGlobalScope::Class() == aClass ||
+         DedicatedWorkerGlobalScope::Class() == aClass;
+}
+
 END_WORKERS_NAMESPACE
--- a/dom/workers/WorkerScope.h
+++ b/dom/workers/WorkerScope.h
@@ -43,11 +43,14 @@
 
 #include "jspubtd.h"
 
 BEGIN_WORKERS_NAMESPACE
 
 JSObject*
 CreateDedicatedWorkerGlobalScope(JSContext* aCx);
 
+bool
+ClassIsWorkerGlobalScope(JSClass* aClass);
+
 END_WORKERS_NAMESPACE
 
 #endif /* mozilla_dom_workers_workerscope_h__ */
--- a/dom/workers/XMLHttpRequest.cpp
+++ b/dom/workers/XMLHttpRequest.cpp
@@ -924,9 +924,16 @@ UpdateXHRState(JSContext* aCx, JSObject*
 {
   return aIsUpload ?
          XMLHttpRequestUpload::UpdateState(aCx, aObj, aNewState) :
          XMLHttpRequest::UpdateState(aCx, aObj, aNewState);
 }
 
 } // namespace xhr
 
+bool
+ClassIsXMLHttpRequest(JSClass* aClass)
+{
+  return XMLHttpRequest::Class() == aClass ||
+         XMLHttpRequestUpload::Class() == aClass;
+}
+
 END_WORKERS_NAMESPACE
--- a/dom/workers/XMLHttpRequest.h
+++ b/dom/workers/XMLHttpRequest.h
@@ -65,11 +65,14 @@ struct StateData
 };
 
 bool
 UpdateXHRState(JSContext* aCx, JSObject* aObj, bool aIsUpload,
                const StateData& aNewState);
 
 } // namespace xhr
 
+bool
+ClassIsXMLHttpRequest(JSClass* aClass);
+
 END_WORKERS_NAMESPACE
 
 #endif /* mozilla_dom_workers_xmlhttprequest_h__ */