1 /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is Web Workers.
17 * The Initial Developer of the Original Code is
18 * Mozilla Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 2008
20 * the Initial Developer. All Rights Reserved.
23 * Ben Turner <bent.mozilla@gmail.com> (Original Author)
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #include "nsDOMWorkerMessageHandler.h"
41 #include "nsIDOMEvent.h"
42 #include "nsIXPConnect.h"
44 #include "nsContentUtils.h"
46 #include "nsDOMThreadService.h"
47 #include "nsDOMWorkerEvents.h"
49 NS_IMPL_THREADSAFE_ADDREF(nsDOMWorkerEventListenerBase
)
50 NS_IMPL_THREADSAFE_RELEASE(nsDOMWorkerEventListenerBase
)
53 nsDOMWorkerWeakEventListener::Init(nsIDOMEventListener
* aListener
)
55 NS_ENSURE_ARG_POINTER(aListener
);
57 nsCOMPtr
<nsIXPConnectWrappedJS
> wrappedJS(do_QueryInterface(aListener
));
58 NS_ENSURE_TRUE(wrappedJS
, NS_NOINTERFACE
);
61 nsresult rv
= wrappedJS
->GetJSObject(&obj
);
62 NS_ENSURE_SUCCESS(rv
, rv
);
69 already_AddRefed
<nsIDOMEventListener
>
70 nsDOMWorkerWeakEventListener::GetListener()
72 JSContext
* cx
= nsDOMThreadService::GetCurrentContext();
73 NS_ENSURE_TRUE(cx
, nsnull
);
75 nsIXPConnect
* xpc
= nsContentUtils::XPConnect();
77 nsCOMPtr
<nsIDOMEventListener
> listener
;
78 nsresult rv
= xpc
->WrapJS(cx
, mObj
, NS_GET_IID(nsIDOMEventListener
),
79 getter_AddRefs(listener
));
80 NS_ENSURE_SUCCESS(rv
, nsnull
);
82 return listener
.forget();
85 nsDOMWorkerWrappedWeakEventListener::
86 nsDOMWorkerWrappedWeakEventListener(nsDOMWorkerWeakEventListener
* aInner
)
89 NS_ASSERTION(aInner
, "Null pointer!");
92 NS_IMPL_THREADSAFE_ISUPPORTS2(nsDOMWorkerMessageHandler
,
96 NS_IMPL_CI_INTERFACE_GETTER1(nsDOMWorkerMessageHandler
,
99 NS_IMPL_THREADSAFE_DOM_CI(nsDOMWorkerMessageHandler
)
101 const nsDOMWorkerMessageHandler::ListenerCollection
*
102 nsDOMWorkerMessageHandler::GetListenerCollection(const nsAString
& aType
) const
104 PRUint32 count
= mCollections
.Length();
105 for (PRUint32 index
= 0; index
< count
; index
++) {
106 const ListenerCollection
& collection
= mCollections
[index
];
107 if (collection
.type
.Equals(aType
)) {
115 nsDOMWorkerMessageHandler::GetListenersForType(const nsAString
& aType
,
116 ListenerArray
& _retval
) const
120 const ListenerCollection
* collection
= GetListenerCollection(aType
);
122 PRUint32 count
= collection
->listeners
.Length();
124 if (!_retval
.SetLength(count
)) {
125 NS_WARNING("Out of memory!");
129 for (PRUint32 index
= 0; index
< count
; index
++) {
130 nsCOMPtr
<nsIDOMEventListener
> listener
=
131 collection
->listeners
[index
]->GetListener();
132 _retval
[index
].swap(listener
);
138 nsDOMWorkerMessageHandler::SetOnXListener(const nsAString
& aType
,
139 nsIDOMEventListener
* aListener
)
141 nsRefPtr
<nsDOMWorkerWrappedWeakEventListener
> wrappedListener
;
143 ListenerCollection
* collection
=
144 const_cast<ListenerCollection
*>(GetListenerCollection(aType
));
151 wrappedListener
.swap(collection
->onXListener
);
152 if (wrappedListener
) {
156 collection
->listeners
.RemoveElement(wrappedListener
);
157 NS_ASSERTION(removed
, "Element wasn't in the list!");
162 if (collection
&& !collection
->listeners
.Length()) {
166 mCollections
.RemoveElement(*collection
);
167 NS_ASSERTION(removed
, "Element wasn't in the list!");
172 nsRefPtr
<nsDOMWorkerWeakEventListener
> weakListener
=
173 new nsDOMWorkerWeakEventListener();
174 NS_ENSURE_TRUE(weakListener
, NS_ERROR_OUT_OF_MEMORY
);
176 nsresult rv
= weakListener
->Init(aListener
);
177 NS_ENSURE_SUCCESS(rv
, rv
);
179 wrappedListener
= new nsDOMWorkerWrappedWeakEventListener(weakListener
);
180 NS_ENSURE_TRUE(wrappedListener
, NS_ERROR_OUT_OF_MEMORY
);
183 collection
= mCollections
.AppendElement(aType
);
184 NS_ENSURE_TRUE(collection
, NS_ERROR_OUT_OF_MEMORY
);
187 WeakListener
* newListener
=
188 collection
->listeners
.AppendElement(wrappedListener
);
189 NS_ENSURE_TRUE(newListener
, NS_ERROR_OUT_OF_MEMORY
);
191 wrappedListener
.swap(collection
->onXListener
);
195 already_AddRefed
<nsIDOMEventListener
>
196 nsDOMWorkerMessageHandler::GetOnXListener(const nsAString
& aType
) const
198 const ListenerCollection
* collection
= GetListenerCollection(aType
);
199 if (collection
&& collection
->onXListener
) {
200 return collection
->onXListener
->GetListener();
207 nsDOMWorkerMessageHandler::ClearListeners(const nsAString
& aType
)
209 PRUint32 count
= mCollections
.Length();
210 for (PRUint32 index
= 0; index
< count
; index
++) {
211 if (mCollections
[index
].type
.Equals(aType
)) {
212 mCollections
.RemoveElementAt(index
);
219 nsDOMWorkerMessageHandler::HasListeners(const nsAString
& aType
)
221 const ListenerCollection
* collection
= GetListenerCollection(aType
);
222 return collection
&& collection
->listeners
.Length();
226 nsDOMWorkerMessageHandler::ClearAllListeners()
228 mCollections
.Clear();
232 nsDOMWorkerMessageHandler::Trace(JSTracer
* aTracer
)
234 PRUint32 cCount
= mCollections
.Length();
235 for (PRUint32 cIndex
= 0; cIndex
< cCount
; cIndex
++) {
236 const ListenerCollection
& collection
= mCollections
[cIndex
];
237 PRUint32 lCount
= collection
.listeners
.Length();
238 for (PRUint32 lIndex
= 0; lIndex
< lCount
; lIndex
++) {
239 JSObject
* obj
= collection
.listeners
[lIndex
]->GetJSObject();
240 NS_ASSERTION(obj
, "Null object!");
241 JS_SET_TRACING_DETAILS(aTracer
, nsnull
, this, 0);
242 JS_CallTracer(aTracer
, obj
, JSTRACE_OBJECT
);
248 * See nsIDOMEventTarget
251 nsDOMWorkerMessageHandler::AddEventListener(const nsAString
& aType
,
252 nsIDOMEventListener
* aListener
,
255 ListenerCollection
* collection
=
256 const_cast<ListenerCollection
*>(GetListenerCollection(aType
));
259 collection
= mCollections
.AppendElement(aType
);
260 NS_ENSURE_TRUE(collection
, NS_ERROR_OUT_OF_MEMORY
);
263 nsRefPtr
<nsDOMWorkerWeakEventListener
> weakListener
=
264 new nsDOMWorkerWeakEventListener();
265 NS_ENSURE_TRUE(weakListener
, NS_ERROR_OUT_OF_MEMORY
);
267 nsresult rv
= weakListener
->Init(aListener
);
268 NS_ENSURE_SUCCESS(rv
, rv
);
270 WeakListener
* newListener
= collection
->listeners
.AppendElement(weakListener
);
271 NS_ENSURE_TRUE(newListener
, NS_ERROR_OUT_OF_MEMORY
);
277 * See nsIDOMEventTarget
280 nsDOMWorkerMessageHandler::RemoveEventListener(const nsAString
& aType
,
281 nsIDOMEventListener
* aListener
,
284 ListenerCollection
* collection
=
285 const_cast<ListenerCollection
*>(GetListenerCollection(aType
));
288 PRUint32 count
= collection
->listeners
.Length();
289 for (PRUint32 index
= 0; index
< count
; index
++) {
290 WeakListener
& weakListener
= collection
->listeners
[index
];
291 if (weakListener
== collection
->onXListener
) {
294 nsCOMPtr
<nsIDOMEventListener
> listener
= weakListener
->GetListener();
295 if (listener
== aListener
) {
296 collection
->listeners
.RemoveElementAt(index
);
301 if (!collection
->listeners
.Length()) {
305 mCollections
.RemoveElement(*collection
);
306 NS_ASSERTION(removed
, "Somehow this wasn't in the list!");
314 * See nsIDOMEventTarget
317 nsDOMWorkerMessageHandler::DispatchEvent(nsIDOMEvent
* aEvent
,
320 NS_ENSURE_ARG_POINTER(aEvent
);
322 nsCOMPtr
<nsIDOMWorkerPrivateEvent
> event
;
325 event
= do_QueryInterface(aEvent
);
327 event
= new nsDOMWorkerPrivateEvent(aEvent
);
328 NS_ENSURE_TRUE(event
, NS_ERROR_OUT_OF_MEMORY
);
334 nsresult rv
= aEvent
->GetType(type
);
335 NS_ENSURE_SUCCESS(rv
, rv
);
337 nsAutoTArray
<Listener
, 10> listeners
;
338 GetListenersForType(type
, listeners
);
340 PRUint32 count
= listeners
.Length();
341 for (PRUint32 index
= 0; index
< count
; index
++) {
342 const Listener
& listener
= listeners
[index
];
343 NS_ASSERTION(listener
, "Null listener in array!");
345 listener
->HandleEvent(aEvent
);
349 *_retval
= event
->PreventDefaultCalled();