1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_EventTarget_h_
#define mozilla_dom_EventTarget_h_
#include "mozilla/dom/Nullable.h"
#include "nsAtom.h"
#include "nsISupports.h"
#include "nsWrapperCache.h"
class nsIDOMEventListener;
class nsIGlobalObject;
class nsINode;
class nsPIDOMWindowInner;
class nsPIDOMWindowOuter;
class nsPIWindowRoot;
namespace mozilla {
class AsyncEventDispatcher;
class ErrorResult;
class EventChainPostVisitor;
class EventChainPreVisitor;
class EventChainVisitor;
class EventListenerManager;
namespace dom {
class AddEventListenerOptionsOrBoolean;
class Event;
class EventListener;
class EventListenerOptionsOrBoolean;
class EventHandlerNonNull;
class GlobalObject;
class Navigation;
class WindowProxyHolder;
enum class CallerType : uint32_t;
enum class EventCallbackDebuggerNotificationType : uint8_t;
// IID for the dom::EventTarget interface
#define NS_EVENTTARGET_IID \
{0xde651c36, 0x0053, 0x4c67, {0xb1, 0x3d, 0x67, 0xb9, 0x40, 0xfc, 0x82, 0xe4}}
class EventTarget : public nsISupports, public nsWrapperCache {
public:
NS_INLINE_DECL_STATIC_IID(NS_EVENTTARGET_IID)
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
void SetIsOnMainThread() {
MOZ_ASSERT(NS_IsMainThread());
mRefCnt.SetIsOnMainThread();
}
#ifndef NS_BUILD_REFCNT_LOGGING
MozExternalRefCountType NonVirtualAddRef();
MozExternalRefCountType NonVirtualRelease();
#endif
// WebIDL API
static already_AddRefed<EventTarget> Constructor(const GlobalObject& aGlobal,
ErrorResult& aRv);
void AddEventListener(const nsAString& aType, EventListener* aCallback,
const AddEventListenerOptionsOrBoolean& aOptions,
const Nullable<bool>& aWantsUntrusted);
void RemoveEventListener(const nsAString& aType, EventListener* aCallback,
const EventListenerOptionsOrBoolean& aOptions);
protected:
/**
* This method allows addition of event listeners represented by
* nsIDOMEventListener, with almost the same semantics as the
* standard AddEventListener. The one difference is that it just
* has a "use capture" boolean, not an EventListenerOptions.
*/
nsresult AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener, bool aUseCapture,
const Nullable<bool>& aWantsUntrusted);
public:
/**
* Helper methods to make the nsIDOMEventListener version of
* AddEventListener simpler to call for consumers.
*/
nsresult AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener, bool aUseCapture) {
return AddEventListener(aType, aListener, aUseCapture, Nullable<bool>());
}
nsresult AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener, bool aUseCapture,
bool aWantsUntrusted) {
return AddEventListener(aType, aListener, aUseCapture,
Nullable<bool>(aWantsUntrusted));
}
/**
* This method allows the removal of event listeners represented by
* nsIDOMEventListener from the event target, with the same semantics as the
* standard RemoveEventListener.
*/
void RemoveEventListener(const nsAString& aType,
nsIDOMEventListener* aListener, bool aUseCapture);
/**
* RemoveSystemEventListener() should be used if you have used
* AddSystemEventListener().
*/
void RemoveSystemEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture);
/**
* Add a system event listener with the default wantsUntrusted value.
*/
nsresult AddSystemEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture) {
return AddSystemEventListener(aType, aListener, aUseCapture,
Nullable<bool>());
}
/**
* Add a system event listener with the given wantsUntrusted value.
*/
nsresult AddSystemEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture, bool aWantsUntrusted) {
return AddSystemEventListener(aType, aListener, aUseCapture,
Nullable<bool>(aWantsUntrusted));
}
virtual bool IsNode() const { return false; }
inline nsINode* GetAsNode();
inline const nsINode* GetAsNode() const;
inline nsINode* AsNode();
inline const nsINode* AsNode() const;
virtual bool IsNavigation() const { return false; }
inline Navigation* GetAsNavigation();
inline const Navigation* GetAsNavigation() const;
inline Navigation* AsNavigation();
inline const Navigation* AsNavigation() const;
virtual bool IsInnerWindow() const { return false; }
virtual bool IsOuterWindow() const { return false; }
virtual bool IsRootWindow() const { return false; }
nsPIDOMWindowInner* GetAsInnerWindow();
const nsPIDOMWindowInner* GetAsInnerWindow() const;
nsPIDOMWindowOuter* GetAsOuterWindow();
const nsPIDOMWindowOuter* GetAsOuterWindow() const;
inline nsPIWindowRoot* GetAsWindowRoot();
inline const nsPIWindowRoot* GetAsWindowRoot() const;
nsPIDOMWindowInner* AsInnerWindow();
const nsPIDOMWindowInner* AsInnerWindow() const;
nsPIDOMWindowOuter* AsOuterWindow();
const nsPIDOMWindowOuter* AsOuterWindow() const;
inline nsPIWindowRoot* AsWindowRoot();
inline const nsPIWindowRoot* AsWindowRoot() const;
/**
* Returns the EventTarget object which should be used as the target
* of DOMEvents.
* Usually |this| is returned, but for example Window (inner windw) returns
* the WindowProxy (outer window).
*/
virtual EventTarget* GetTargetForDOMEvent() { return this; };
/**
* Returns the EventTarget object which should be used as the target
* of the event and when constructing event target chain.
* Usually |this| is returned, but for example WindowProxy (outer window)
* returns the Window (inner window).
*/
virtual EventTarget* GetTargetForEventTargetChain() { return this; }
/**
* The most general DispatchEvent method. This is the one the bindings call.
*/
// TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual bool DispatchEvent(Event& aEvent,
CallerType aCallerType,
ErrorResult& aRv) = 0;
/**
* A version of DispatchEvent you can use if you really don't care whether it
* succeeds or not and whether default is prevented or not.
*/
// TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
MOZ_CAN_RUN_SCRIPT_BOUNDARY void DispatchEvent(Event& aEvent);
/**
* A version of DispatchEvent you can use if you really don't care whether
* default is prevented or not.
*/
// TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
MOZ_CAN_RUN_SCRIPT_BOUNDARY void DispatchEvent(Event& aEvent,
ErrorResult& aRv);
nsIGlobalObject* GetParentObject() const { return GetOwnerGlobal(); }
// Note, this takes the type in onfoo form!
EventHandlerNonNull* GetEventHandler(const nsAString& aType) {
RefPtr<nsAtom> type = NS_Atomize(aType);
return GetEventHandler(type);
}
// Note, this takes the type in onfoo form!
void SetEventHandler(const nsAString& aType, EventHandlerNonNull* aHandler,
ErrorResult& rv);
// For an event 'foo' aType will be 'onfoo'.
virtual void EventListenerAdded(nsAtom* aType) {}
// For an event 'foo' aType will be 'onfoo'.
virtual void EventListenerRemoved(nsAtom* aType) {}
// Returns an outer window that corresponds to the inner window this event
// target is associated with. Will return null if the inner window is not the
// current inner or if there is no window around at all.
Nullable<WindowProxyHolder> GetOwnerGlobalForBindings();
virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindingsInternal() = 0;
// The global object this event target is associated with, if any.
// This may be an inner window or some other global object. This
// will never be an outer window.
virtual nsIGlobalObject* GetOwnerGlobal() const = 0;
/**
* Get the event listener manager, creating it if it does not already exist.
*/
virtual EventListenerManager* GetOrCreateListenerManager() = 0;
/**
* Get the event listener manager, returning null if it does not already
* exist.
*/
virtual EventListenerManager* GetExistingListenerManager() const = 0;
virtual Maybe<EventCallbackDebuggerNotificationType>
GetDebuggerNotificationType() const {
return Nothing();
}
// Called from AsyncEventDispatcher to notify it is running.
virtual void AsyncEventRunning(AsyncEventDispatcher* aEvent) {}
// Used by APZ to determine whether this event target has non-chrome event
// listeners for untrusted key events.
bool HasNonSystemGroupListenersForUntrustedKeyEvents() const;
// Used by APZ to determine whether this event target has non-chrome and
// non-passive event listeners for untrusted key events.
bool HasNonPassiveNonSystemGroupListenersForUntrustedKeyEvents() const;
virtual bool IsApzAware() const;
/**
* Called before the capture phase of the event flow.
* This is used to create the event target chain and implementations
* should set the necessary members of EventChainPreVisitor.
* At least aVisitor.mCanHandle must be set,
* usually also aVisitor.mParentTarget if mCanHandle is true.
* mCanHandle says that this object can handle the aVisitor.mEvent event and
* the mParentTarget is the possible parent object for the event target chain.
* @see EventDispatcher.h for more documentation about aVisitor.
*
* @param aVisitor the visitor object which is used to create the
* event target chain for event dispatching.
*
* @note Only EventDispatcher should call this method.
*/
virtual void GetEventTargetParent(EventChainPreVisitor& aVisitor) = 0;
/**
* Called on the activation target during dispatch of activation events.
* https://dom.spec.whatwg.org/#eventtarget-legacy-pre-activation-behavior
*/
virtual void LegacyPreActivationBehavior(EventChainVisitor& aVisitor) {}
/**
* Called on the activation target during dispatch of activation events.
* https://dom.spec.whatwg.org/#eventtarget-activation-behavior
*/
MOZ_CAN_RUN_SCRIPT
virtual void ActivationBehavior(EventChainPostVisitor& aVisitor) {}
/**
* Called on the activation target during dispatch of activation events.
* https://dom.spec.whatwg.org/#eventtarget-legacy-canceled-activation-behavior
*/
virtual void LegacyCanceledActivationBehavior(
EventChainPostVisitor& aVisitor) {}
/**
* Called before the capture phase of the event flow and after event target
* chain creation. This is used to handle things that must be executed before
* dispatching the event to DOM.
*/
virtual nsresult PreHandleEvent(EventChainVisitor& aVisitor) { return NS_OK; }
/**
* If EventChainPreVisitor.mWantsWillHandleEvent is set true,
* called just before possible event handlers on this object will be called.
*/
virtual void WillHandleEvent(EventChainPostVisitor& aVisitor) {}
/**
* Called after the bubble phase of the system event group.
* The default handling of the event should happen here.
* @param aVisitor the visitor object which is used during post handling.
*
* @see EventDispatcher.h for documentation about aVisitor.
* @note Only EventDispatcher should call this method.
*/
MOZ_CAN_RUN_SCRIPT
virtual nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) = 0;
protected:
EventHandlerNonNull* GetEventHandler(nsAtom* aType);
void SetEventHandler(nsAtom* aType, EventHandlerNonNull* aHandler);
/**
* Hook for AddEventListener that allows it to compute the right
* wantsUntrusted boolean when one is not provided. If this returns failure,
* the listener will not be added.
*
* This hook will NOT be called unless aWantsUntrusted is null in
* AddEventListener. If you need to take action when event listeners are
* added, use EventListenerAdded. Especially because not all event listener
* additions go through AddEventListener!
*/
virtual bool ComputeDefaultWantsUntrusted(ErrorResult& aRv) = 0;
/**
* A method to compute the right wantsUntrusted value for AddEventListener.
* This will call the above hook as needed.
*
* If aOptions is non-null, and it contains a value for mWantUntrusted, that
* value takes precedence over aWantsUntrusted.
*/
bool ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted,
const AddEventListenerOptionsOrBoolean* aOptions,
ErrorResult& aRv);
/**
* addSystemEventListener() adds an event listener of aType to the system
* group. Typically, core code should use the system group for listening to
* content (i.e., non-chrome) element's events. If core code uses
* EventTarget::AddEventListener for a content node, it means
* that the listener cannot listen to the event when web content calls
* stopPropagation() of the event.
*
* @param aType An event name you're going to handle.
* @param aListener An event listener.
* @param aUseCapture true if you want to listen the event in capturing
* phase. Otherwise, false.
* @param aWantsUntrusted true if you want to handle untrusted events.
* false if not.
* Null if you want the default behavior.
*/
nsresult AddSystemEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture,
const Nullable<bool>& aWantsUntrusted);
};
#define NS_IMPL_FROMEVENTTARGET_GENERIC(_class, _check, _const) \
template <typename T> \
static auto FromEventTarget(_const T& aEventTarget) \
-> decltype(static_cast<_const _class*>(&aEventTarget)) { \
return aEventTarget._check ? static_cast<_const _class*>(&aEventTarget) \
: nullptr; \
} \
template <typename T> \
static _const _class* FromEventTarget(_const T* aEventTarget) { \
MOZ_DIAGNOSTIC_ASSERT(aEventTarget); \
return FromEventTarget(*aEventTarget); \
} \
template <typename T> \
static _const _class* FromEventTargetOrNull(_const T* aEventTarget) { \
return aEventTarget ? FromEventTarget(*aEventTarget) : nullptr; \
}
#define NS_IMPL_FROMEVENTTARGET_HELPER(_class, _check) \
NS_IMPL_FROMEVENTTARGET_GENERIC(_class, _check, ) \
NS_IMPL_FROMEVENTTARGET_GENERIC(_class, _check, const) \
template <typename T> \
static _class* FromEventTarget(T&& aEventTarget) { \
MOZ_DIAGNOSTIC_ASSERT(!!aEventTarget); \
/* We need the double-cast in case aEventTarget is a smartptr. Those */ \
/* can cast to superclasses of the type they're templated on, */ \
/* but not directly to subclasses. */ \
return aEventTarget->_check \
? static_cast<_class*>(static_cast<EventTarget*>(aEventTarget)) \
: nullptr; \
} \
template <typename T> \
static _class* FromEventTargetOrNull(T&& aEventTarget) { \
return aEventTarget ? FromEventTarget(aEventTarget) : nullptr; \
}
// Unfortunately, nsPIDOMWindowInner and nsPIDOMWindowOuter do not inherit
// EventTarget directly, but they are public interfaces which should have
// these helper methods. Therefore, we cannot cast from EventTarget to
// the interfaces in their header file. That's the reason why we cannot use
// the zero cost casts nor decltype for the template methods which take a
// reference.
#define NS_IMPL_FROMEVENTTARGET_GENERIC_WITH_GETTER(_class, _getter, _const) \
static _const _class* FromEventTarget( \
_const mozilla::dom::EventTarget& aEventTarget) { \
return aEventTarget._getter; \
} \
template <typename T> \
static _const _class* FromEventTarget(_const T* aEventTarget) { \
return aEventTarget->_getter; \
} \
template <typename T> \
static _const _class* FromEventTargetOrNull(_const T* aEventTarget) { \
return aEventTarget ? aEventTarget->_getter : nullptr; \
}
#define NS_IMPL_FROMEVENTTARGET_HELPER_WITH_GETTER_INNER(_class, _getter) \
template <typename T> \
static _class* FromEventTarget(T&& aEventTarget) { \
return aEventTarget->_getter; \
} \
template <typename T> \
static _class* FromEventTargetOrNull(T&& aEventTarget) { \
return aEventTarget ? aEventTarget->_getter : nullptr; \
}
#define NS_IMPL_FROMEVENTTARGET_HELPER_WITH_GETTER(_class, _getter) \
NS_IMPL_FROMEVENTTARGET_GENERIC_WITH_GETTER(_class, _getter, ) \
NS_IMPL_FROMEVENTTARGET_GENERIC_WITH_GETTER(_class, _getter, const) \
NS_IMPL_FROMEVENTTARGET_HELPER_WITH_GETTER_INNER(_class, _getter)
} // namespace dom
} // namespace mozilla
#ifdef NS_BUILD_REFCNT_LOGGING
# define NON_VIRTUAL_ADDREF_RELEASE(class_) /* Nothing */
#else
# define NON_VIRTUAL_ADDREF_RELEASE(class_) \
namespace mozilla { \
template <> \
class RefPtrTraits<class_> { \
public: \
static void Release(class_* aObject) { aObject->NonVirtualRelease(); } \
static void AddRef(class_* aObject) { aObject->NonVirtualAddRef(); } \
}; \
}
#endif
NON_VIRTUAL_ADDREF_RELEASE(mozilla::dom::EventTarget)
#endif // mozilla_dom_EventTarget_h_
|