|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #ifndef mozilla_EventListenerManager_h_ |
|
7 #define mozilla_EventListenerManager_h_ |
|
8 |
|
9 #include "mozilla/BasicEvents.h" |
|
10 #include "mozilla/dom/EventListenerBinding.h" |
|
11 #include "mozilla/JSEventHandler.h" |
|
12 #include "mozilla/MemoryReporting.h" |
|
13 #include "nsCOMPtr.h" |
|
14 #include "nsCycleCollectionParticipant.h" |
|
15 #include "nsGkAtoms.h" |
|
16 #include "nsIDOMEventListener.h" |
|
17 #include "nsTObserverArray.h" |
|
18 |
|
19 class nsIDOMEvent; |
|
20 class nsIEventListenerInfo; |
|
21 class nsIScriptContext; |
|
22 class nsPIDOMWindow; |
|
23 |
|
24 struct EventTypeData; |
|
25 |
|
26 template<class T> class nsCOMArray; |
|
27 |
|
28 namespace mozilla { |
|
29 |
|
30 class ELMCreationDetector; |
|
31 class EventListenerManager; |
|
32 |
|
33 namespace dom { |
|
34 class EventTarget; |
|
35 class Element; |
|
36 } // namespace dom |
|
37 |
|
38 typedef dom::CallbackObjectHolder<dom::EventListener, |
|
39 nsIDOMEventListener> EventListenerHolder; |
|
40 |
|
41 struct EventListenerFlags |
|
42 { |
|
43 friend class EventListenerManager; |
|
44 private: |
|
45 // If mListenerIsJSListener is true, the listener is implemented by JS. |
|
46 // Otherwise, it's implemented by native code or JS but it's wrapped. |
|
47 bool mListenerIsJSListener : 1; |
|
48 |
|
49 public: |
|
50 // If mCapture is true, it means the listener captures the event. Otherwise, |
|
51 // it's listening at bubbling phase. |
|
52 bool mCapture : 1; |
|
53 // If mInSystemGroup is true, the listener is listening to the events in the |
|
54 // system group. |
|
55 bool mInSystemGroup : 1; |
|
56 // If mAllowUntrustedEvents is true, the listener is listening to the |
|
57 // untrusted events too. |
|
58 bool mAllowUntrustedEvents : 1; |
|
59 |
|
60 EventListenerFlags() : |
|
61 mListenerIsJSListener(false), |
|
62 mCapture(false), mInSystemGroup(false), mAllowUntrustedEvents(false) |
|
63 { |
|
64 } |
|
65 |
|
66 bool Equals(const EventListenerFlags& aOther) const |
|
67 { |
|
68 return (mCapture == aOther.mCapture && |
|
69 mInSystemGroup == aOther.mInSystemGroup && |
|
70 mListenerIsJSListener == aOther.mListenerIsJSListener && |
|
71 mAllowUntrustedEvents == aOther.mAllowUntrustedEvents); |
|
72 } |
|
73 |
|
74 bool EqualsIgnoringTrustness(const EventListenerFlags& aOther) const |
|
75 { |
|
76 return (mCapture == aOther.mCapture && |
|
77 mInSystemGroup == aOther.mInSystemGroup && |
|
78 mListenerIsJSListener == aOther.mListenerIsJSListener); |
|
79 } |
|
80 |
|
81 bool operator==(const EventListenerFlags& aOther) const |
|
82 { |
|
83 return Equals(aOther); |
|
84 } |
|
85 }; |
|
86 |
|
87 inline EventListenerFlags TrustedEventsAtBubble() |
|
88 { |
|
89 EventListenerFlags flags; |
|
90 return flags; |
|
91 } |
|
92 |
|
93 inline EventListenerFlags TrustedEventsAtCapture() |
|
94 { |
|
95 EventListenerFlags flags; |
|
96 flags.mCapture = true; |
|
97 return flags; |
|
98 } |
|
99 |
|
100 inline EventListenerFlags AllEventsAtBubbe() |
|
101 { |
|
102 EventListenerFlags flags; |
|
103 flags.mAllowUntrustedEvents = true; |
|
104 return flags; |
|
105 } |
|
106 |
|
107 inline EventListenerFlags AllEventsAtCapture() |
|
108 { |
|
109 EventListenerFlags flags; |
|
110 flags.mCapture = true; |
|
111 flags.mAllowUntrustedEvents = true; |
|
112 return flags; |
|
113 } |
|
114 |
|
115 inline EventListenerFlags TrustedEventsAtSystemGroupBubble() |
|
116 { |
|
117 EventListenerFlags flags; |
|
118 flags.mInSystemGroup = true; |
|
119 return flags; |
|
120 } |
|
121 |
|
122 inline EventListenerFlags TrustedEventsAtSystemGroupCapture() |
|
123 { |
|
124 EventListenerFlags flags; |
|
125 flags.mCapture = true; |
|
126 flags.mInSystemGroup = true; |
|
127 return flags; |
|
128 } |
|
129 |
|
130 inline EventListenerFlags AllEventsAtSystemGroupBubble() |
|
131 { |
|
132 EventListenerFlags flags; |
|
133 flags.mInSystemGroup = true; |
|
134 flags.mAllowUntrustedEvents = true; |
|
135 return flags; |
|
136 } |
|
137 |
|
138 inline EventListenerFlags AllEventsAtSystemGroupCapture() |
|
139 { |
|
140 EventListenerFlags flags; |
|
141 flags.mCapture = true; |
|
142 flags.mInSystemGroup = true; |
|
143 flags.mAllowUntrustedEvents = true; |
|
144 return flags; |
|
145 } |
|
146 |
|
147 /* |
|
148 * Event listener manager |
|
149 */ |
|
150 |
|
151 class EventListenerManager MOZ_FINAL |
|
152 { |
|
153 public: |
|
154 struct Listener |
|
155 { |
|
156 EventListenerHolder mListener; |
|
157 nsCOMPtr<nsIAtom> mTypeAtom; // for the main thread |
|
158 nsString mTypeString; // for non-main-threads |
|
159 uint16_t mEventType; |
|
160 |
|
161 enum ListenerType MOZ_ENUM_TYPE(uint8_t) |
|
162 { |
|
163 eNativeListener = 0, |
|
164 eJSEventListener, |
|
165 eWrappedJSListener, |
|
166 eWebIDLListener, |
|
167 eListenerTypeCount |
|
168 }; |
|
169 uint8_t mListenerType; |
|
170 |
|
171 bool mListenerIsHandler : 1; |
|
172 bool mHandlerIsString : 1; |
|
173 bool mAllEvents : 1; |
|
174 |
|
175 EventListenerFlags mFlags; |
|
176 |
|
177 JSEventHandler* GetJSEventHandler() const |
|
178 { |
|
179 return (mListenerType == eJSEventListener) ? |
|
180 static_cast<JSEventHandler*>(mListener.GetXPCOMCallback()) : |
|
181 nullptr; |
|
182 } |
|
183 |
|
184 Listener() |
|
185 { |
|
186 MOZ_ASSERT(sizeof(mListenerType) == 1); |
|
187 MOZ_ASSERT(eListenerTypeCount < 255); |
|
188 } |
|
189 |
|
190 ~Listener() |
|
191 { |
|
192 if ((mListenerType == eJSEventListener) && mListener) { |
|
193 static_cast<JSEventHandler*>( |
|
194 mListener.GetXPCOMCallback())->Disconnect(); |
|
195 } |
|
196 } |
|
197 |
|
198 MOZ_ALWAYS_INLINE bool IsListening(const WidgetEvent* aEvent) const |
|
199 { |
|
200 if (mFlags.mInSystemGroup != aEvent->mFlags.mInSystemGroup) { |
|
201 return false; |
|
202 } |
|
203 // FIXME Should check !mFlags.mCapture when the event is in target |
|
204 // phase because capture phase event listeners should not be fired. |
|
205 // But it breaks at least <xul:dialog>'s buttons. Bug 235441. |
|
206 return ((mFlags.mCapture && aEvent->mFlags.mInCapturePhase) || |
|
207 (!mFlags.mCapture && aEvent->mFlags.mInBubblingPhase)); |
|
208 } |
|
209 }; |
|
210 |
|
211 EventListenerManager(dom::EventTarget* aTarget); |
|
212 virtual ~EventListenerManager(); |
|
213 |
|
214 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(EventListenerManager) |
|
215 |
|
216 NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(EventListenerManager) |
|
217 |
|
218 void AddEventListener(const nsAString& aType, |
|
219 nsIDOMEventListener* aListener, |
|
220 bool aUseCapture, |
|
221 bool aWantsUntrusted) |
|
222 { |
|
223 EventListenerHolder holder(aListener); |
|
224 AddEventListener(aType, holder, aUseCapture, aWantsUntrusted); |
|
225 } |
|
226 void AddEventListener(const nsAString& aType, |
|
227 dom::EventListener* aListener, |
|
228 bool aUseCapture, |
|
229 bool aWantsUntrusted) |
|
230 { |
|
231 EventListenerHolder holder(aListener); |
|
232 AddEventListener(aType, holder, aUseCapture, aWantsUntrusted); |
|
233 } |
|
234 void RemoveEventListener(const nsAString& aType, |
|
235 nsIDOMEventListener* aListener, |
|
236 bool aUseCapture) |
|
237 { |
|
238 EventListenerHolder holder(aListener); |
|
239 RemoveEventListener(aType, holder, aUseCapture); |
|
240 } |
|
241 void RemoveEventListener(const nsAString& aType, |
|
242 dom::EventListener* aListener, |
|
243 bool aUseCapture) |
|
244 { |
|
245 EventListenerHolder holder(aListener); |
|
246 RemoveEventListener(aType, holder, aUseCapture); |
|
247 } |
|
248 |
|
249 void AddListenerForAllEvents(nsIDOMEventListener* aListener, |
|
250 bool aUseCapture, |
|
251 bool aWantsUntrusted, |
|
252 bool aSystemEventGroup); |
|
253 void RemoveListenerForAllEvents(nsIDOMEventListener* aListener, |
|
254 bool aUseCapture, |
|
255 bool aSystemEventGroup); |
|
256 |
|
257 /** |
|
258 * Sets events listeners of all types. |
|
259 * @param an event listener |
|
260 */ |
|
261 void AddEventListenerByType(nsIDOMEventListener *aListener, |
|
262 const nsAString& type, |
|
263 const EventListenerFlags& aFlags) |
|
264 { |
|
265 EventListenerHolder holder(aListener); |
|
266 AddEventListenerByType(holder, type, aFlags); |
|
267 } |
|
268 void AddEventListenerByType(const EventListenerHolder& aListener, |
|
269 const nsAString& type, |
|
270 const EventListenerFlags& aFlags); |
|
271 void RemoveEventListenerByType(nsIDOMEventListener *aListener, |
|
272 const nsAString& type, |
|
273 const EventListenerFlags& aFlags) |
|
274 { |
|
275 EventListenerHolder holder(aListener); |
|
276 RemoveEventListenerByType(holder, type, aFlags); |
|
277 } |
|
278 void RemoveEventListenerByType(const EventListenerHolder& aListener, |
|
279 const nsAString& type, |
|
280 const EventListenerFlags& aFlags); |
|
281 |
|
282 /** |
|
283 * Sets the current "inline" event listener for aName to be a |
|
284 * function compiled from aFunc if !aDeferCompilation. If |
|
285 * aDeferCompilation, then we assume that we can get the string from |
|
286 * mTarget later and compile lazily. |
|
287 * |
|
288 * aElement, if not null, is the element the string is associated with. |
|
289 */ |
|
290 // XXXbz does that play correctly with nodes being adopted across |
|
291 // documents? Need to double-check the spec here. |
|
292 nsresult SetEventHandler(nsIAtom *aName, |
|
293 const nsAString& aFunc, |
|
294 uint32_t aLanguage, |
|
295 bool aDeferCompilation, |
|
296 bool aPermitUntrustedEvents, |
|
297 dom::Element* aElement); |
|
298 /** |
|
299 * Remove the current "inline" event listener for aName. |
|
300 */ |
|
301 void RemoveEventHandler(nsIAtom *aName, const nsAString& aTypeString); |
|
302 |
|
303 void HandleEvent(nsPresContext* aPresContext, |
|
304 WidgetEvent* aEvent, |
|
305 nsIDOMEvent** aDOMEvent, |
|
306 dom::EventTarget* aCurrentTarget, |
|
307 nsEventStatus* aEventStatus) |
|
308 { |
|
309 if (mListeners.IsEmpty() || aEvent->mFlags.mPropagationStopped) { |
|
310 return; |
|
311 } |
|
312 |
|
313 if (!mMayHaveCapturingListeners && !aEvent->mFlags.mInBubblingPhase) { |
|
314 return; |
|
315 } |
|
316 |
|
317 if (!mMayHaveSystemGroupListeners && aEvent->mFlags.mInSystemGroup) { |
|
318 return; |
|
319 } |
|
320 |
|
321 // Check if we already know that there is no event listener for the event. |
|
322 if (mNoListenerForEvent == aEvent->message && |
|
323 (mNoListenerForEvent != NS_USER_DEFINED_EVENT || |
|
324 mNoListenerForEventAtom == aEvent->userType)) { |
|
325 return; |
|
326 } |
|
327 HandleEventInternal(aPresContext, aEvent, aDOMEvent, aCurrentTarget, |
|
328 aEventStatus); |
|
329 } |
|
330 |
|
331 /** |
|
332 * Tells the event listener manager that its target (which owns it) is |
|
333 * no longer using it (and could go away). |
|
334 */ |
|
335 void Disconnect(); |
|
336 |
|
337 /** |
|
338 * Allows us to quickly determine if we have mutation listeners registered. |
|
339 */ |
|
340 bool HasMutationListeners(); |
|
341 |
|
342 /** |
|
343 * Allows us to quickly determine whether we have unload or beforeunload |
|
344 * listeners registered. |
|
345 */ |
|
346 bool HasUnloadListeners(); |
|
347 |
|
348 /** |
|
349 * Returns the mutation bits depending on which mutation listeners are |
|
350 * registered to this listener manager. |
|
351 * @note If a listener is an nsIDOMMutationListener, all possible mutation |
|
352 * event bits are returned. All bits are also returned if one of the |
|
353 * event listeners is registered to handle DOMSubtreeModified events. |
|
354 */ |
|
355 uint32_t MutationListenerBits(); |
|
356 |
|
357 /** |
|
358 * Returns true if there is at least one event listener for aEventName. |
|
359 */ |
|
360 bool HasListenersFor(const nsAString& aEventName); |
|
361 |
|
362 /** |
|
363 * Returns true if there is at least one event listener for aEventNameWithOn. |
|
364 * Note that aEventNameWithOn must start with "on"! |
|
365 */ |
|
366 bool HasListenersFor(nsIAtom* aEventNameWithOn); |
|
367 |
|
368 /** |
|
369 * Returns true if there is at least one event listener. |
|
370 */ |
|
371 bool HasListeners(); |
|
372 |
|
373 /** |
|
374 * Sets aList to the list of nsIEventListenerInfo objects representing the |
|
375 * listeners managed by this listener manager. |
|
376 */ |
|
377 nsresult GetListenerInfo(nsCOMArray<nsIEventListenerInfo>* aList); |
|
378 |
|
379 uint32_t GetIdentifierForEvent(nsIAtom* aEvent); |
|
380 |
|
381 static void Shutdown(); |
|
382 |
|
383 /** |
|
384 * Returns true if there may be a paint event listener registered, |
|
385 * false if there definitely isn't. |
|
386 */ |
|
387 bool MayHavePaintEventListener() { return mMayHavePaintEventListener; } |
|
388 |
|
389 /** |
|
390 * Returns true if there may be a touch event listener registered, |
|
391 * false if there definitely isn't. |
|
392 */ |
|
393 bool MayHaveTouchEventListener() { return mMayHaveTouchEventListener; } |
|
394 |
|
395 bool MayHaveMouseEnterLeaveEventListener() { return mMayHaveMouseEnterLeaveEventListener; } |
|
396 bool MayHavePointerEnterLeaveEventListener() { return mMayHavePointerEnterLeaveEventListener; } |
|
397 |
|
398 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const; |
|
399 |
|
400 uint32_t ListenerCount() const |
|
401 { |
|
402 return mListeners.Length(); |
|
403 } |
|
404 |
|
405 void MarkForCC(); |
|
406 |
|
407 dom::EventTarget* GetTarget() { return mTarget; } |
|
408 |
|
409 protected: |
|
410 void HandleEventInternal(nsPresContext* aPresContext, |
|
411 WidgetEvent* aEvent, |
|
412 nsIDOMEvent** aDOMEvent, |
|
413 dom::EventTarget* aCurrentTarget, |
|
414 nsEventStatus* aEventStatus); |
|
415 |
|
416 nsresult HandleEventSubType(Listener* aListener, |
|
417 nsIDOMEvent* aDOMEvent, |
|
418 dom::EventTarget* aCurrentTarget); |
|
419 |
|
420 /** |
|
421 * Compile the "inline" event listener for aListener. The |
|
422 * body of the listener can be provided in aBody; if this is null we |
|
423 * will look for it on mTarget. If aBody is provided, aElement should be |
|
424 * as well; otherwise it will also be inferred from mTarget. |
|
425 */ |
|
426 nsresult CompileEventHandlerInternal(Listener* aListener, |
|
427 const nsAString* aBody, |
|
428 dom::Element* aElement); |
|
429 |
|
430 /** |
|
431 * Find the Listener for the "inline" event listener for aTypeAtom. |
|
432 */ |
|
433 Listener* FindEventHandler(uint32_t aEventType, |
|
434 nsIAtom* aTypeAtom, |
|
435 const nsAString& aTypeString); |
|
436 |
|
437 /** |
|
438 * Set the "inline" event listener for aName to aHandler. aHandler may be |
|
439 * have no actual handler set to indicate that we should lazily get and |
|
440 * compile the string for this listener, but in that case aContext and |
|
441 * aScopeGlobal must be non-null. Otherwise, aContext and aScopeGlobal are |
|
442 * allowed to be null. |
|
443 */ |
|
444 Listener* SetEventHandlerInternal(nsIAtom* aName, |
|
445 const nsAString& aTypeString, |
|
446 const TypedEventHandler& aHandler, |
|
447 bool aPermitUntrustedEvents); |
|
448 |
|
449 bool IsDeviceType(uint32_t aType); |
|
450 void EnableDevice(uint32_t aType); |
|
451 void DisableDevice(uint32_t aType); |
|
452 |
|
453 public: |
|
454 /** |
|
455 * Set the "inline" event listener for aEventName to aHandler. If |
|
456 * aHandler is null, this will actually remove the event listener |
|
457 */ |
|
458 void SetEventHandler(nsIAtom* aEventName, |
|
459 const nsAString& aTypeString, |
|
460 dom::EventHandlerNonNull* aHandler); |
|
461 void SetEventHandler(dom::OnErrorEventHandlerNonNull* aHandler); |
|
462 void SetEventHandler(dom::OnBeforeUnloadEventHandlerNonNull* aHandler); |
|
463 |
|
464 /** |
|
465 * Get the value of the "inline" event listener for aEventName. |
|
466 * This may cause lazy compilation if the listener is uncompiled. |
|
467 * |
|
468 * Note: It's the caller's responsibility to make sure to call the right one |
|
469 * of these methods. In particular, "onerror" events use |
|
470 * OnErrorEventHandlerNonNull for some event targets and EventHandlerNonNull |
|
471 * for others. |
|
472 */ |
|
473 dom::EventHandlerNonNull* GetEventHandler(nsIAtom* aEventName, |
|
474 const nsAString& aTypeString) |
|
475 { |
|
476 const TypedEventHandler* typedHandler = |
|
477 GetTypedEventHandler(aEventName, aTypeString); |
|
478 return typedHandler ? typedHandler->NormalEventHandler() : nullptr; |
|
479 } |
|
480 |
|
481 dom::OnErrorEventHandlerNonNull* GetOnErrorEventHandler() |
|
482 { |
|
483 const TypedEventHandler* typedHandler = mIsMainThreadELM ? |
|
484 GetTypedEventHandler(nsGkAtoms::onerror, EmptyString()) : |
|
485 GetTypedEventHandler(nullptr, NS_LITERAL_STRING("error")); |
|
486 return typedHandler ? typedHandler->OnErrorEventHandler() : nullptr; |
|
487 } |
|
488 |
|
489 dom::OnBeforeUnloadEventHandlerNonNull* GetOnBeforeUnloadEventHandler() |
|
490 { |
|
491 const TypedEventHandler* typedHandler = |
|
492 GetTypedEventHandler(nsGkAtoms::onbeforeunload, EmptyString()); |
|
493 return typedHandler ? typedHandler->OnBeforeUnloadEventHandler() : nullptr; |
|
494 } |
|
495 |
|
496 protected: |
|
497 /** |
|
498 * Helper method for implementing the various Get*EventHandler above. Will |
|
499 * return null if we don't have an event handler for this event name. |
|
500 */ |
|
501 const TypedEventHandler* GetTypedEventHandler(nsIAtom* aEventName, |
|
502 const nsAString& aTypeString); |
|
503 |
|
504 void AddEventListener(const nsAString& aType, |
|
505 const EventListenerHolder& aListener, |
|
506 bool aUseCapture, |
|
507 bool aWantsUntrusted); |
|
508 void RemoveEventListener(const nsAString& aType, |
|
509 const EventListenerHolder& aListener, |
|
510 bool aUseCapture); |
|
511 |
|
512 void AddEventListenerInternal(const EventListenerHolder& aListener, |
|
513 uint32_t aType, |
|
514 nsIAtom* aTypeAtom, |
|
515 const nsAString& aTypeString, |
|
516 const EventListenerFlags& aFlags, |
|
517 bool aHandler = false, |
|
518 bool aAllEvents = false); |
|
519 void RemoveEventListenerInternal(const EventListenerHolder& aListener, |
|
520 uint32_t aType, |
|
521 nsIAtom* aUserType, |
|
522 const nsAString& aTypeString, |
|
523 const EventListenerFlags& aFlags, |
|
524 bool aAllEvents = false); |
|
525 void RemoveAllListeners(); |
|
526 const EventTypeData* GetTypeDataForIID(const nsIID& aIID); |
|
527 const EventTypeData* GetTypeDataForEventName(nsIAtom* aName); |
|
528 nsPIDOMWindow* GetInnerWindowForTarget(); |
|
529 already_AddRefed<nsPIDOMWindow> GetTargetAsInnerWindow() const; |
|
530 |
|
531 bool ListenerCanHandle(Listener* aListener, WidgetEvent* aEvent); |
|
532 |
|
533 already_AddRefed<nsIScriptGlobalObject> |
|
534 GetScriptGlobalAndDocument(nsIDocument** aDoc); |
|
535 |
|
536 uint32_t mMayHavePaintEventListener : 1; |
|
537 uint32_t mMayHaveMutationListeners : 1; |
|
538 uint32_t mMayHaveCapturingListeners : 1; |
|
539 uint32_t mMayHaveSystemGroupListeners : 1; |
|
540 uint32_t mMayHaveTouchEventListener : 1; |
|
541 uint32_t mMayHaveMouseEnterLeaveEventListener : 1; |
|
542 uint32_t mMayHavePointerEnterLeaveEventListener : 1; |
|
543 uint32_t mClearingListeners : 1; |
|
544 uint32_t mIsMainThreadELM : 1; |
|
545 uint32_t mNoListenerForEvent : 23; |
|
546 |
|
547 nsAutoTObserverArray<Listener, 2> mListeners; |
|
548 dom::EventTarget* mTarget; // WEAK |
|
549 nsCOMPtr<nsIAtom> mNoListenerForEventAtom; |
|
550 |
|
551 friend class ELMCreationDetector; |
|
552 static uint32_t sMainThreadCreatedCount; |
|
553 }; |
|
554 |
|
555 } // namespace mozilla |
|
556 |
|
557 /** |
|
558 * NS_AddSystemEventListener() is a helper function for implementing |
|
559 * EventTarget::AddSystemEventListener(). |
|
560 */ |
|
561 inline nsresult |
|
562 NS_AddSystemEventListener(mozilla::dom::EventTarget* aTarget, |
|
563 const nsAString& aType, |
|
564 nsIDOMEventListener *aListener, |
|
565 bool aUseCapture, |
|
566 bool aWantsUntrusted) |
|
567 { |
|
568 mozilla::EventListenerManager* listenerManager = |
|
569 aTarget->GetOrCreateListenerManager(); |
|
570 NS_ENSURE_STATE(listenerManager); |
|
571 mozilla::EventListenerFlags flags; |
|
572 flags.mInSystemGroup = true; |
|
573 flags.mCapture = aUseCapture; |
|
574 flags.mAllowUntrustedEvents = aWantsUntrusted; |
|
575 listenerManager->AddEventListenerByType(aListener, aType, flags); |
|
576 return NS_OK; |
|
577 } |
|
578 |
|
579 #endif // mozilla_EventListenerManager_h_ |