dom/events/DOMEventTargetHelper.h

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:49393d5d6b29
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_DOMEventTargetHelper_h_
7 #define mozilla_DOMEventTargetHelper_h_
8
9 #include "nsCOMPtr.h"
10 #include "nsGkAtoms.h"
11 #include "nsCycleCollectionParticipant.h"
12 #include "nsPIDOMWindow.h"
13 #include "nsIScriptGlobalObject.h"
14 #include "nsIScriptContext.h"
15 #include "MainThreadUtils.h"
16 #include "mozilla/Attributes.h"
17 #include "mozilla/EventListenerManager.h"
18 #include "mozilla/dom/EventTarget.h"
19
20 class JSCompartment;
21
22 namespace mozilla {
23
24 class ErrorResult;
25
26 #define NS_DOMEVENTTARGETHELPER_IID \
27 { 0xa28385c6, 0x9451, 0x4d7e, \
28 { 0xa3, 0xdd, 0xf4, 0xb6, 0x87, 0x2f, 0xa4, 0x76 } }
29
30 class DOMEventTargetHelper : public dom::EventTarget
31 {
32 public:
33 DOMEventTargetHelper()
34 : mParentObject(nullptr)
35 , mOwnerWindow(nullptr)
36 , mHasOrHasHadOwnerWindow(false)
37 {
38 }
39 DOMEventTargetHelper(nsPIDOMWindow* aWindow)
40 : mParentObject(nullptr)
41 , mOwnerWindow(nullptr)
42 , mHasOrHasHadOwnerWindow(false)
43 {
44 BindToOwner(aWindow);
45 // All objects coming through here are WebIDL objects
46 SetIsDOMBinding();
47 }
48 DOMEventTargetHelper(DOMEventTargetHelper* aOther)
49 : mParentObject(nullptr)
50 , mOwnerWindow(nullptr)
51 , mHasOrHasHadOwnerWindow(false)
52 {
53 BindToOwner(aOther);
54 // All objects coming through here are WebIDL objects
55 SetIsDOMBinding();
56 }
57
58 virtual ~DOMEventTargetHelper();
59 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
60 NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(DOMEventTargetHelper)
61
62 NS_DECL_NSIDOMEVENTTARGET
63
64 virtual EventListenerManager* GetExistingListenerManager() const MOZ_OVERRIDE;
65 virtual EventListenerManager* GetOrCreateListenerManager() MOZ_OVERRIDE;
66
67 using dom::EventTarget::RemoveEventListener;
68 virtual void AddEventListener(const nsAString& aType,
69 dom::EventListener* aListener,
70 bool aCapture,
71 const dom::Nullable<bool>& aWantsUntrusted,
72 ErrorResult& aRv) MOZ_OVERRIDE;
73
74 NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOMEVENTTARGETHELPER_IID)
75
76 void GetParentObject(nsIScriptGlobalObject **aParentObject)
77 {
78 if (mParentObject) {
79 CallQueryInterface(mParentObject, aParentObject);
80 } else {
81 *aParentObject = nullptr;
82 }
83 }
84
85 static DOMEventTargetHelper* FromSupports(nsISupports* aSupports)
86 {
87 dom::EventTarget* target = static_cast<dom::EventTarget*>(aSupports);
88 #ifdef DEBUG
89 {
90 nsCOMPtr<dom::EventTarget> target_qi = do_QueryInterface(aSupports);
91
92 // If this assertion fires the QI implementation for the object in
93 // question doesn't use the EventTarget pointer as the
94 // nsISupports pointer. That must be fixed, or we'll crash...
95 NS_ASSERTION(target_qi == target, "Uh, fix QI!");
96 }
97 #endif
98
99 return static_cast<DOMEventTargetHelper*>(target);
100 }
101
102 bool HasListenersFor(nsIAtom* aTypeWithOn)
103 {
104 return mListenerManager && mListenerManager->HasListenersFor(aTypeWithOn);
105 }
106
107 nsresult SetEventHandler(nsIAtom* aType,
108 JSContext* aCx,
109 const JS::Value& aValue);
110 using dom::EventTarget::SetEventHandler;
111 void GetEventHandler(nsIAtom* aType,
112 JSContext* aCx,
113 JS::Value* aValue);
114 using dom::EventTarget::GetEventHandler;
115 virtual nsIDOMWindow* GetOwnerGlobal() MOZ_OVERRIDE
116 {
117 return nsPIDOMWindow::GetOuterFromCurrentInner(GetOwner());
118 }
119
120 nsresult CheckInnerWindowCorrectness()
121 {
122 NS_ENSURE_STATE(!mHasOrHasHadOwnerWindow || mOwnerWindow);
123 if (mOwnerWindow) {
124 NS_ASSERTION(mOwnerWindow->IsInnerWindow(), "Should have inner window here!\n");
125 nsPIDOMWindow* outer = mOwnerWindow->GetOuterWindow();
126 if (!outer || outer->GetCurrentInnerWindow() != mOwnerWindow) {
127 return NS_ERROR_FAILURE;
128 }
129 }
130 return NS_OK;
131 }
132
133 nsPIDOMWindow* GetOwner() const { return mOwnerWindow; }
134 void BindToOwner(nsIGlobalObject* aOwner);
135 void BindToOwner(nsPIDOMWindow* aOwner);
136 void BindToOwner(DOMEventTargetHelper* aOther);
137 virtual void DisconnectFromOwner();
138 nsIGlobalObject* GetParentObject() const { return mParentObject; }
139 bool HasOrHasHadOwner() { return mHasOrHasHadOwnerWindow; }
140
141 virtual void EventListenerAdded(nsIAtom* aType) MOZ_OVERRIDE;
142 virtual void EventListenerRemoved(nsIAtom* aType) MOZ_OVERRIDE;
143 virtual void EventListenerWasAdded(const nsAString& aType,
144 ErrorResult& aRv,
145 JSCompartment* aCompartment = nullptr) {}
146 virtual void EventListenerWasRemoved(const nsAString& aType,
147 ErrorResult& aRv,
148 JSCompartment* aCompartment = nullptr) {}
149 protected:
150 nsresult WantsUntrusted(bool* aRetVal);
151
152 nsRefPtr<EventListenerManager> mListenerManager;
153 // Dispatch a trusted, non-cancellable and non-bubbling event to |this|.
154 nsresult DispatchTrustedEvent(const nsAString& aEventName);
155 // Make |event| trusted and dispatch |aEvent| to |this|.
156 nsresult DispatchTrustedEvent(nsIDOMEvent* aEvent);
157
158 virtual void LastRelease() {}
159 private:
160 // Inner window or sandbox.
161 nsIGlobalObject* mParentObject;
162 // mParentObject pre QI-ed and cached
163 // (it is needed for off main thread access)
164 nsPIDOMWindow* mOwnerWindow;
165 bool mHasOrHasHadOwnerWindow;
166 };
167
168 NS_DEFINE_STATIC_IID_ACCESSOR(DOMEventTargetHelper,
169 NS_DOMEVENTTARGETHELPER_IID)
170
171 } // namespace mozilla
172
173 // XPIDL event handlers
174 #define NS_IMPL_EVENT_HANDLER(_class, _event) \
175 NS_IMETHODIMP _class::GetOn##_event(JSContext* aCx, \
176 JS::MutableHandle<JS::Value> aValue) \
177 { \
178 GetEventHandler(nsGkAtoms::on##_event, aCx, aValue.address()); \
179 return NS_OK; \
180 } \
181 NS_IMETHODIMP _class::SetOn##_event(JSContext* aCx, \
182 JS::Handle<JS::Value> aValue) \
183 { \
184 return SetEventHandler(nsGkAtoms::on##_event, aCx, aValue); \
185 }
186
187 #define NS_IMPL_FORWARD_EVENT_HANDLER(_class, _event, _baseclass) \
188 NS_IMETHODIMP _class::GetOn##_event(JSContext* aCx, \
189 JS::MutableHandle<JS::Value> aValue) \
190 { \
191 return _baseclass::GetOn##_event(aCx, aValue); \
192 } \
193 NS_IMETHODIMP _class::SetOn##_event(JSContext* aCx, \
194 JS::Handle<JS::Value> aValue) \
195 { \
196 return _baseclass::SetOn##_event(aCx, aValue); \
197 }
198
199 // WebIDL event handlers
200 #define IMPL_EVENT_HANDLER(_event) \
201 inline mozilla::dom::EventHandlerNonNull* GetOn##_event() \
202 { \
203 if (NS_IsMainThread()) { \
204 return GetEventHandler(nsGkAtoms::on##_event, EmptyString()); \
205 } \
206 return GetEventHandler(nullptr, NS_LITERAL_STRING(#_event)); \
207 } \
208 inline void SetOn##_event(mozilla::dom::EventHandlerNonNull* aCallback) \
209 { \
210 if (NS_IsMainThread()) { \
211 SetEventHandler(nsGkAtoms::on##_event, EmptyString(), aCallback); \
212 } else { \
213 SetEventHandler(nullptr, NS_LITERAL_STRING(#_event), aCallback); \
214 } \
215 }
216
217 /* Use this macro to declare functions that forward the behavior of this
218 * interface to another object.
219 * This macro doesn't forward PreHandleEvent because sometimes subclasses
220 * want to override it.
221 */
222 #define NS_FORWARD_NSIDOMEVENTTARGET_NOPREHANDLEEVENT(_to) \
223 NS_IMETHOD AddEventListener(const nsAString & type, nsIDOMEventListener *listener, bool useCapture, bool wantsUntrusted, uint8_t _argc) { \
224 return _to AddEventListener(type, listener, useCapture, wantsUntrusted, _argc); \
225 } \
226 NS_IMETHOD AddSystemEventListener(const nsAString & type, nsIDOMEventListener *listener, bool aUseCapture, bool aWantsUntrusted, uint8_t _argc) { \
227 return _to AddSystemEventListener(type, listener, aUseCapture, aWantsUntrusted, _argc); \
228 } \
229 NS_IMETHOD RemoveEventListener(const nsAString & type, nsIDOMEventListener *listener, bool useCapture) { \
230 return _to RemoveEventListener(type, listener, useCapture); \
231 } \
232 NS_IMETHOD RemoveSystemEventListener(const nsAString & type, nsIDOMEventListener *listener, bool aUseCapture) { \
233 return _to RemoveSystemEventListener(type, listener, aUseCapture); \
234 } \
235 NS_IMETHOD DispatchEvent(nsIDOMEvent *evt, bool *_retval) { \
236 return _to DispatchEvent(evt, _retval); \
237 } \
238 virtual mozilla::dom::EventTarget* GetTargetForDOMEvent() { \
239 return _to GetTargetForDOMEvent(); \
240 } \
241 virtual mozilla::dom::EventTarget* GetTargetForEventTargetChain() { \
242 return _to GetTargetForEventTargetChain(); \
243 } \
244 virtual nsresult WillHandleEvent( \
245 mozilla::EventChainPostVisitor & aVisitor) { \
246 return _to WillHandleEvent(aVisitor); \
247 } \
248 virtual nsresult PostHandleEvent( \
249 mozilla::EventChainPostVisitor & aVisitor) { \
250 return _to PostHandleEvent(aVisitor); \
251 } \
252 virtual nsresult DispatchDOMEvent(mozilla::WidgetEvent* aEvent, nsIDOMEvent* aDOMEvent, nsPresContext* aPresContext, nsEventStatus* aEventStatus) { \
253 return _to DispatchDOMEvent(aEvent, aDOMEvent, aPresContext, aEventStatus); \
254 } \
255 virtual mozilla::EventListenerManager* GetOrCreateListenerManager() { \
256 return _to GetOrCreateListenerManager(); \
257 } \
258 virtual mozilla::EventListenerManager* GetExistingListenerManager() const { \
259 return _to GetExistingListenerManager(); \
260 } \
261 virtual nsIScriptContext * GetContextForEventHandlers(nsresult *aRv) { \
262 return _to GetContextForEventHandlers(aRv); \
263 } \
264 virtual JSContext * GetJSContextForEventHandlers(void) { \
265 return _to GetJSContextForEventHandlers(); \
266 }
267
268 #define NS_REALLY_FORWARD_NSIDOMEVENTTARGET(_class) \
269 using _class::AddEventListener; \
270 using _class::RemoveEventListener; \
271 NS_FORWARD_NSIDOMEVENTTARGET(_class::) \
272 virtual mozilla::EventListenerManager* \
273 GetOrCreateListenerManager() { \
274 return _class::GetOrCreateListenerManager(); \
275 } \
276 virtual mozilla::EventListenerManager* \
277 GetExistingListenerManager() const { \
278 return _class::GetExistingListenerManager(); \
279 }
280
281 #endif // mozilla_DOMEventTargetHelper_h_

mercurial