dom/events/DOMEventTargetHelper.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial