зеркало из https://github.com/mozilla/gecko-dev.git
413 строки
18 KiB
C++
413 строки
18 KiB
C++
/* -*- 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_
|