summaryrefslogtreecommitdiffstats
path: root/dom/events/EventTarget.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/events/EventTarget.h')
-rw-r--r--dom/events/EventTarget.h412
1 files changed, 412 insertions, 0 deletions
diff --git a/dom/events/EventTarget.h b/dom/events/EventTarget.h
new file mode 100644
index 0000000000..ae1f94f584
--- /dev/null
+++ b/dom/events/EventTarget.h
@@ -0,0 +1,412 @@
+/* -*- 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 "nsISupports.h"
+#include "nsWrapperCache.h"
+#include "nsAtom.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 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_DECLARE_STATIC_IID_ACCESSOR(NS_EVENTTARGET_IID)
+
+ // 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,
+ ErrorResult& aRv);
+ void RemoveEventListener(const nsAString& aType, EventListener* aCallback,
+ const EventListenerOptionsOrBoolean& aOptions,
+ ErrorResult& aRv);
+
+ 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 IsInnerWindow() const { return false; }
+ virtual bool IsOuterWindow() const { return false; }
+ virtual bool IsRootWindow() const { return false; }
+ nsPIDOMWindowInner* GetAsWindowInner();
+ const nsPIDOMWindowInner* GetAsWindowInner() const;
+ nsPIDOMWindowOuter* GetAsWindowOuter();
+ const nsPIDOMWindowOuter* GetAsWindowOuter() const;
+ inline nsPIWindowRoot* GetAsWindowRoot();
+ inline const nsPIWindowRoot* GetAsWindowRoot() const;
+ nsPIDOMWindowInner* AsWindowInner();
+ const nsPIDOMWindowInner* AsWindowInner() const;
+ nsPIDOMWindowOuter* AsWindowOuter();
+ const nsPIDOMWindowOuter* AsWindowOuter() 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 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);
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(EventTarget, NS_EVENTTARGET_IID)
+
+#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
+
+#endif // mozilla_dom_EventTarget_h_