diff --git a/dom/workers/EventTarget.cpp b/dom/workers/EventTarget.cpp index 890acdc4fc5..45968658608 100644 --- a/dom/workers/EventTarget.cpp +++ b/dom/workers/EventTarget.cpp @@ -42,6 +42,11 @@ #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 @@ -63,6 +68,23 @@ 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) @@ -143,6 +165,10 @@ EventTarget::AddEventListener(JSContext* aCx, uintN aArgc, jsval* aVp) return true; } + if (!EnsureObjectIsEventTarget(aCx, obj, "AddEventListener")) { + return false; + } + EventTarget* self = GetPrivate(aCx, obj); if (!self) { return true; @@ -174,6 +200,10 @@ EventTarget::RemoveEventListener(JSContext* aCx, uintN aArgc, jsval* aVp) return true; } + if (!EnsureObjectIsEventTarget(aCx, obj, "RemoveEventListener")) { + return false; + } + EventTarget* self = GetPrivate(aCx, obj); if (!self) { return true; @@ -205,6 +235,10 @@ EventTarget::DispatchEvent(JSContext* aCx, uintN aArgc, jsval* aVp) return true; } + if (!EnsureObjectIsEventTarget(aCx, obj, "DispatchEvent")) { + return false; + } + EventTarget* self = GetPrivate(aCx, obj); if (!self) { return true; diff --git a/dom/workers/EventTarget.h b/dom/workers/EventTarget.h index cd07328e170..913ab7134e8 100644 --- a/dom/workers/EventTarget.h +++ b/dom/workers/EventTarget.h @@ -47,6 +47,8 @@ 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; diff --git a/dom/workers/Worker.cpp b/dom/workers/Worker.cpp index b840dce9ed2..a2f2b25ebc2 100644 --- a/dom/workers/Worker.cpp +++ b/dom/workers/Worker.cpp @@ -499,4 +499,10 @@ InitClass(JSContext* aCx, JSObject* aGlobal, JSObject* aProto, } // namespace chromeworker +bool +ClassIsWorker(JSClass* aClass) +{ + return Worker::Class() == aClass || ChromeWorker::Class() == aClass; +} + END_WORKERS_NAMESPACE diff --git a/dom/workers/Worker.h b/dom/workers/Worker.h index 3a219f0ec93..94b80d7ecf0 100644 --- a/dom/workers/Worker.h +++ b/dom/workers/Worker.h @@ -64,6 +64,9 @@ InitClass(JSContext* aCx, JSObject* aGlobal, JSObject* aProto, } // namespace chromeworker +bool +ClassIsWorker(JSClass* aClass); + END_WORKERS_NAMESPACE #endif /* mozilla_dom_workers_worker_h__ */ diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp index d8929e1a723..8cf44ce97c5 100644 --- a/dom/workers/WorkerScope.cpp +++ b/dom/workers/WorkerScope.cpp @@ -937,4 +937,11 @@ CreateDedicatedWorkerGlobalScope(JSContext* aCx) return global; } +bool +ClassIsWorkerGlobalScope(JSClass* aClass) +{ + return WorkerGlobalScope::Class() == aClass || + DedicatedWorkerGlobalScope::Class() == aClass; +} + END_WORKERS_NAMESPACE diff --git a/dom/workers/WorkerScope.h b/dom/workers/WorkerScope.h index 20f5716ebf9..ed21ac58e21 100644 --- a/dom/workers/WorkerScope.h +++ b/dom/workers/WorkerScope.h @@ -48,6 +48,9 @@ BEGIN_WORKERS_NAMESPACE JSObject* CreateDedicatedWorkerGlobalScope(JSContext* aCx); +bool +ClassIsWorkerGlobalScope(JSClass* aClass); + END_WORKERS_NAMESPACE #endif /* mozilla_dom_workers_workerscope_h__ */ diff --git a/dom/workers/XMLHttpRequest.cpp b/dom/workers/XMLHttpRequest.cpp index ab3d389d2a5..3181e7aba85 100644 --- a/dom/workers/XMLHttpRequest.cpp +++ b/dom/workers/XMLHttpRequest.cpp @@ -929,4 +929,11 @@ UpdateXHRState(JSContext* aCx, JSObject* aObj, bool aIsUpload, } // namespace xhr +bool +ClassIsXMLHttpRequest(JSClass* aClass) +{ + return XMLHttpRequest::Class() == aClass || + XMLHttpRequestUpload::Class() == aClass; +} + END_WORKERS_NAMESPACE diff --git a/dom/workers/XMLHttpRequest.h b/dom/workers/XMLHttpRequest.h index 601d1f79539..d1bdf8224b6 100644 --- a/dom/workers/XMLHttpRequest.h +++ b/dom/workers/XMLHttpRequest.h @@ -70,6 +70,9 @@ UpdateXHRState(JSContext* aCx, JSObject* aObj, bool aIsUpload, } // namespace xhr +bool +ClassIsXMLHttpRequest(JSClass* aClass); + END_WORKERS_NAMESPACE #endif /* mozilla_dom_workers_xmlhttprequest_h__ */