2015-05-03 22:32:37 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* 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/. */
|
1998-06-07 11:55:55 +04:00
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
#ifndef mozilla_EventListenerManager_h_
|
|
|
|
#define mozilla_EventListenerManager_h_
|
1998-06-07 11:55:55 +04:00
|
|
|
|
2013-09-25 15:21:22 +04:00
|
|
|
#include "mozilla/BasicEvents.h"
|
2013-07-24 11:31:06 +04:00
|
|
|
#include "mozilla/dom/EventListenerBinding.h"
|
2014-04-02 06:00:45 +04:00
|
|
|
#include "mozilla/JSEventHandler.h"
|
2013-07-24 11:31:06 +04:00
|
|
|
#include "mozilla/MemoryReporting.h"
|
|
|
|
#include "nsCOMPtr.h"
|
2007-01-05 01:31:26 +03:00
|
|
|
#include "nsCycleCollectionParticipant.h"
|
2013-07-24 11:31:06 +04:00
|
|
|
#include "nsGkAtoms.h"
|
|
|
|
#include "nsIDOMEventListener.h"
|
|
|
|
#include "nsTObserverArray.h"
|
1998-07-31 22:21:37 +04:00
|
|
|
|
2014-10-28 14:18:00 +03:00
|
|
|
class nsIDocShell;
|
2011-06-24 06:18:01 +04:00
|
|
|
class nsIEventListenerInfo;
|
2016-01-30 20:05:36 +03:00
|
|
|
class nsPIDOMWindowInner;
|
2014-06-05 03:48:50 +04:00
|
|
|
class JSTracer;
|
1999-03-29 02:22:54 +04:00
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
struct EventTypeData;
|
2012-12-16 05:26:05 +04:00
|
|
|
|
2013-08-30 01:18:25 +04:00
|
|
|
template<class T> class nsCOMArray;
|
|
|
|
|
2012-12-16 05:26:05 +04:00
|
|
|
namespace mozilla {
|
|
|
|
|
2014-03-18 08:48:22 +04:00
|
|
|
class ELMCreationDetector;
|
2014-03-17 10:56:53 +04:00
|
|
|
class EventListenerManager;
|
|
|
|
|
2014-03-17 10:56:52 +04:00
|
|
|
namespace dom {
|
2018-04-20 19:53:16 +03:00
|
|
|
class Event;
|
2013-08-19 14:15:55 +04:00
|
|
|
class EventTarget;
|
2013-11-26 20:44:37 +04:00
|
|
|
class Element;
|
2014-03-17 10:56:52 +04:00
|
|
|
} // namespace dom
|
2013-08-19 14:15:55 +04:00
|
|
|
|
2014-03-17 10:56:52 +04:00
|
|
|
typedef dom::CallbackObjectHolder<dom::EventListener,
|
|
|
|
nsIDOMEventListener> EventListenerHolder;
|
2013-04-17 01:15:57 +04:00
|
|
|
|
2012-12-16 05:26:05 +04:00
|
|
|
struct EventListenerFlags
|
|
|
|
{
|
2014-03-17 10:56:53 +04:00
|
|
|
friend class EventListenerManager;
|
2012-12-16 05:26:05 +04:00
|
|
|
private:
|
|
|
|
// If mListenerIsJSListener is true, the listener is implemented by JS.
|
|
|
|
// Otherwise, it's implemented by native code or JS but it's wrapped.
|
|
|
|
bool mListenerIsJSListener : 1;
|
|
|
|
|
|
|
|
public:
|
|
|
|
// If mCapture is true, it means the listener captures the event. Otherwise,
|
|
|
|
// it's listening at bubbling phase.
|
|
|
|
bool mCapture : 1;
|
|
|
|
// If mInSystemGroup is true, the listener is listening to the events in the
|
|
|
|
// system group.
|
|
|
|
bool mInSystemGroup : 1;
|
|
|
|
// If mAllowUntrustedEvents is true, the listener is listening to the
|
|
|
|
// untrusted events too.
|
|
|
|
bool mAllowUntrustedEvents : 1;
|
2016-05-12 21:50:22 +03:00
|
|
|
// If mPassive is true, the listener will not be calling preventDefault on the
|
|
|
|
// event. (If it does call preventDefault, we should ignore it).
|
|
|
|
bool mPassive : 1;
|
2016-07-28 05:00:06 +03:00
|
|
|
// If mOnce is true, the listener will be removed from the manager before it
|
|
|
|
// is invoked, so that it would only be invoked once.
|
|
|
|
bool mOnce : 1;
|
2012-12-16 05:26:05 +04:00
|
|
|
|
|
|
|
EventListenerFlags() :
|
|
|
|
mListenerIsJSListener(false),
|
2016-05-12 21:50:22 +03:00
|
|
|
mCapture(false), mInSystemGroup(false), mAllowUntrustedEvents(false),
|
2016-07-28 05:00:06 +03:00
|
|
|
mPassive(false), mOnce(false)
|
2012-12-16 05:26:05 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-05-12 21:50:22 +03:00
|
|
|
bool EqualsForAddition(const EventListenerFlags& aOther) const
|
2012-12-16 05:26:05 +04:00
|
|
|
{
|
|
|
|
return (mCapture == aOther.mCapture &&
|
|
|
|
mInSystemGroup == aOther.mInSystemGroup &&
|
|
|
|
mListenerIsJSListener == aOther.mListenerIsJSListener &&
|
|
|
|
mAllowUntrustedEvents == aOther.mAllowUntrustedEvents);
|
2016-07-28 05:00:06 +03:00
|
|
|
// Don't compare mPassive or mOnce
|
2012-12-16 05:26:05 +04:00
|
|
|
}
|
|
|
|
|
2016-05-12 21:50:22 +03:00
|
|
|
bool EqualsForRemoval(const EventListenerFlags& aOther) const
|
2012-12-16 05:26:05 +04:00
|
|
|
{
|
|
|
|
return (mCapture == aOther.mCapture &&
|
|
|
|
mInSystemGroup == aOther.mInSystemGroup &&
|
|
|
|
mListenerIsJSListener == aOther.mListenerIsJSListener);
|
2016-07-28 05:00:06 +03:00
|
|
|
// Don't compare mAllowUntrustedEvents, mPassive, or mOnce
|
2012-12-16 05:26:05 +04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
inline EventListenerFlags TrustedEventsAtBubble()
|
|
|
|
{
|
|
|
|
EventListenerFlags flags;
|
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline EventListenerFlags TrustedEventsAtCapture()
|
|
|
|
{
|
|
|
|
EventListenerFlags flags;
|
|
|
|
flags.mCapture = true;
|
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
2016-06-21 02:06:58 +03:00
|
|
|
inline EventListenerFlags AllEventsAtBubble()
|
2012-12-16 05:26:05 +04:00
|
|
|
{
|
|
|
|
EventListenerFlags flags;
|
|
|
|
flags.mAllowUntrustedEvents = true;
|
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline EventListenerFlags AllEventsAtCapture()
|
|
|
|
{
|
|
|
|
EventListenerFlags flags;
|
|
|
|
flags.mCapture = true;
|
|
|
|
flags.mAllowUntrustedEvents = true;
|
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline EventListenerFlags TrustedEventsAtSystemGroupBubble()
|
|
|
|
{
|
|
|
|
EventListenerFlags flags;
|
|
|
|
flags.mInSystemGroup = true;
|
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline EventListenerFlags TrustedEventsAtSystemGroupCapture()
|
|
|
|
{
|
|
|
|
EventListenerFlags flags;
|
|
|
|
flags.mCapture = true;
|
|
|
|
flags.mInSystemGroup = true;
|
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline EventListenerFlags AllEventsAtSystemGroupBubble()
|
|
|
|
{
|
|
|
|
EventListenerFlags flags;
|
|
|
|
flags.mInSystemGroup = true;
|
|
|
|
flags.mAllowUntrustedEvents = true;
|
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline EventListenerFlags AllEventsAtSystemGroupCapture()
|
|
|
|
{
|
|
|
|
EventListenerFlags flags;
|
|
|
|
flags.mCapture = true;
|
|
|
|
flags.mInSystemGroup = true;
|
|
|
|
flags.mAllowUntrustedEvents = true;
|
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
2015-08-26 15:56:59 +03:00
|
|
|
class EventListenerManagerBase
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
EventListenerManagerBase();
|
|
|
|
|
|
|
|
EventMessage mNoListenerForEvent;
|
|
|
|
uint16_t mMayHavePaintEventListener : 1;
|
|
|
|
uint16_t mMayHaveMutationListeners : 1;
|
|
|
|
uint16_t mMayHaveCapturingListeners : 1;
|
|
|
|
uint16_t mMayHaveSystemGroupListeners : 1;
|
|
|
|
uint16_t mMayHaveTouchEventListener : 1;
|
|
|
|
uint16_t mMayHaveMouseEnterLeaveEventListener : 1;
|
|
|
|
uint16_t mMayHavePointerEnterLeaveEventListener : 1;
|
|
|
|
uint16_t mMayHaveKeyEventListener : 1;
|
|
|
|
uint16_t mMayHaveInputOrCompositionEventListener : 1;
|
2017-06-22 21:01:27 +03:00
|
|
|
uint16_t mMayHaveSelectionChangeEventListener : 1;
|
2015-08-26 15:56:59 +03:00
|
|
|
uint16_t mClearingListeners : 1;
|
|
|
|
uint16_t mIsMainThreadELM : 1;
|
2017-06-22 21:01:27 +03:00
|
|
|
// uint16_t mUnused : 4;
|
2015-08-26 15:56:59 +03:00
|
|
|
};
|
|
|
|
|
2014-03-17 10:56:51 +04:00
|
|
|
/*
|
|
|
|
* Event listener manager
|
|
|
|
*/
|
2011-11-29 13:44:06 +04:00
|
|
|
|
2015-08-26 15:56:59 +03:00
|
|
|
class EventListenerManager final : public EventListenerManagerBase
|
2014-03-17 10:56:51 +04:00
|
|
|
{
|
2014-06-23 23:56:07 +04:00
|
|
|
~EventListenerManager();
|
|
|
|
|
2014-03-17 10:56:51 +04:00
|
|
|
public:
|
|
|
|
struct Listener
|
2011-11-29 13:44:06 +04:00
|
|
|
{
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerHolder mListener;
|
2018-07-25 01:15:19 +03:00
|
|
|
RefPtr<nsAtom> mTypeAtom;
|
2015-08-26 15:56:59 +03:00
|
|
|
EventMessage mEventMessage;
|
2014-03-17 10:56:51 +04:00
|
|
|
|
2015-01-21 16:35:19 +03:00
|
|
|
enum ListenerType : uint8_t
|
2014-03-17 10:56:51 +04:00
|
|
|
{
|
2018-04-12 07:03:44 +03:00
|
|
|
// No listener.
|
2016-07-28 05:00:06 +03:00
|
|
|
eNoListener,
|
2018-04-12 07:03:44 +03:00
|
|
|
// A generic C++ implementation of nsIDOMEventListener.
|
2016-07-28 05:00:06 +03:00
|
|
|
eNativeListener,
|
2018-04-12 07:03:44 +03:00
|
|
|
// An event handler attribute using JSEventHandler.
|
2014-03-17 10:56:51 +04:00
|
|
|
eJSEventListener,
|
2018-04-12 07:03:44 +03:00
|
|
|
// A scripted EventListener.
|
2014-03-17 10:56:51 +04:00
|
|
|
eWebIDLListener,
|
|
|
|
};
|
2016-07-28 05:00:06 +03:00
|
|
|
ListenerType mListenerType;
|
2014-03-17 10:56:51 +04:00
|
|
|
|
2014-03-17 10:56:51 +04:00
|
|
|
bool mListenerIsHandler : 1;
|
|
|
|
bool mHandlerIsString : 1;
|
|
|
|
bool mAllEvents : 1;
|
2016-05-04 06:29:14 +03:00
|
|
|
bool mIsChrome : 1;
|
2014-03-17 10:56:51 +04:00
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerFlags mFlags;
|
2014-03-17 10:56:51 +04:00
|
|
|
|
2014-04-02 06:00:46 +04:00
|
|
|
JSEventHandler* GetJSEventHandler() const
|
2014-03-17 10:56:51 +04:00
|
|
|
{
|
|
|
|
return (mListenerType == eJSEventListener) ?
|
2014-04-02 06:00:46 +04:00
|
|
|
static_cast<JSEventHandler*>(mListener.GetXPCOMCallback()) :
|
2014-03-17 10:56:51 +04:00
|
|
|
nullptr;
|
2011-11-29 13:44:06 +04:00
|
|
|
}
|
2012-12-16 05:26:05 +04:00
|
|
|
|
2016-07-28 05:00:06 +03:00
|
|
|
Listener()
|
|
|
|
: mEventMessage(eVoidEvent)
|
|
|
|
, mListenerType(eNoListener)
|
|
|
|
, mListenerIsHandler(false)
|
|
|
|
, mHandlerIsString(false)
|
|
|
|
, mAllEvents(false)
|
|
|
|
, mIsChrome(false)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Listener(Listener&& aOther)
|
2018-05-30 22:15:35 +03:00
|
|
|
: mListener(std::move(aOther.mListener))
|
2016-07-28 05:00:06 +03:00
|
|
|
, mTypeAtom(aOther.mTypeAtom.forget())
|
|
|
|
, mEventMessage(aOther.mEventMessage)
|
|
|
|
, mListenerType(aOther.mListenerType)
|
|
|
|
, mListenerIsHandler(aOther.mListenerIsHandler)
|
|
|
|
, mHandlerIsString(aOther.mHandlerIsString)
|
|
|
|
, mAllEvents(aOther.mAllEvents)
|
|
|
|
, mIsChrome(aOther.mIsChrome)
|
|
|
|
{
|
|
|
|
aOther.mEventMessage = eVoidEvent;
|
|
|
|
aOther.mListenerType = eNoListener;
|
|
|
|
aOther.mListenerIsHandler = false;
|
|
|
|
aOther.mHandlerIsString = false;
|
|
|
|
aOther.mAllEvents = false;
|
|
|
|
aOther.mIsChrome = false;
|
|
|
|
}
|
1999-03-29 02:22:54 +04:00
|
|
|
|
2014-03-17 10:56:51 +04:00
|
|
|
~Listener()
|
|
|
|
{
|
|
|
|
if ((mListenerType == eJSEventListener) && mListener) {
|
2014-04-02 06:00:46 +04:00
|
|
|
static_cast<JSEventHandler*>(
|
2014-03-17 10:56:51 +04:00
|
|
|
mListener.GetXPCOMCallback())->Disconnect();
|
|
|
|
}
|
|
|
|
}
|
1998-06-07 11:55:55 +04:00
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
MOZ_ALWAYS_INLINE bool IsListening(const WidgetEvent* aEvent) const
|
2014-03-17 10:56:51 +04:00
|
|
|
{
|
|
|
|
if (mFlags.mInSystemGroup != aEvent->mFlags.mInSystemGroup) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// FIXME Should check !mFlags.mCapture when the event is in target
|
|
|
|
// phase because capture phase event listeners should not be fired.
|
|
|
|
// But it breaks at least <xul:dialog>'s buttons. Bug 235441.
|
|
|
|
return ((mFlags.mCapture && aEvent->mFlags.mInCapturePhase) ||
|
|
|
|
(!mFlags.mCapture && aEvent->mFlags.mInBubblingPhase));
|
|
|
|
}
|
|
|
|
};
|
1998-06-07 11:55:55 +04:00
|
|
|
|
2014-08-05 17:19:51 +04:00
|
|
|
explicit EventListenerManager(dom::EventTarget* aTarget);
|
1998-06-07 11:55:55 +04:00
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(EventListenerManager)
|
2011-06-24 06:18:01 +04:00
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(EventListenerManager)
|
2011-06-24 06:18:01 +04:00
|
|
|
|
2011-08-18 13:45:00 +04:00
|
|
|
void AddEventListener(const nsAString& aType,
|
|
|
|
nsIDOMEventListener* aListener,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aUseCapture,
|
2013-04-17 01:16:08 +04:00
|
|
|
bool aWantsUntrusted)
|
|
|
|
{
|
2016-07-28 05:00:06 +03:00
|
|
|
AddEventListener(aType, EventListenerHolder(aListener),
|
|
|
|
aUseCapture, aWantsUntrusted);
|
2013-04-17 01:16:08 +04:00
|
|
|
}
|
|
|
|
void AddEventListener(const nsAString& aType,
|
2014-03-17 10:56:53 +04:00
|
|
|
dom::EventListener* aListener,
|
2016-04-26 11:23:17 +03:00
|
|
|
const dom::AddEventListenerOptionsOrBoolean& aOptions,
|
2013-04-17 01:16:08 +04:00
|
|
|
bool aWantsUntrusted)
|
|
|
|
{
|
2016-07-28 05:00:06 +03:00
|
|
|
AddEventListener(aType, EventListenerHolder(aListener),
|
|
|
|
aOptions, aWantsUntrusted);
|
2013-04-17 01:16:08 +04:00
|
|
|
}
|
2011-06-24 06:18:02 +04:00
|
|
|
void RemoveEventListener(const nsAString& aType,
|
|
|
|
nsIDOMEventListener* aListener,
|
2013-04-17 01:16:08 +04:00
|
|
|
bool aUseCapture)
|
|
|
|
{
|
2016-07-28 05:00:06 +03:00
|
|
|
RemoveEventListener(aType, EventListenerHolder(aListener), aUseCapture);
|
2013-04-17 01:16:08 +04:00
|
|
|
}
|
|
|
|
void RemoveEventListener(const nsAString& aType,
|
2014-03-17 10:56:53 +04:00
|
|
|
dom::EventListener* aListener,
|
2016-04-26 11:23:17 +03:00
|
|
|
const dom::EventListenerOptionsOrBoolean& aOptions)
|
2013-04-17 01:16:08 +04:00
|
|
|
{
|
2016-07-28 05:00:06 +03:00
|
|
|
RemoveEventListener(aType, EventListenerHolder(aListener), aOptions);
|
2013-04-17 01:16:08 +04:00
|
|
|
}
|
1998-06-07 11:55:55 +04:00
|
|
|
|
2018-04-11 17:27:01 +03:00
|
|
|
void AddListenerForAllEvents(dom::EventListener* aListener,
|
2012-11-01 16:42:29 +04:00
|
|
|
bool aUseCapture,
|
|
|
|
bool aWantsUntrusted,
|
|
|
|
bool aSystemEventGroup);
|
2018-04-11 17:27:01 +03:00
|
|
|
void RemoveListenerForAllEvents(dom::EventListener* aListener,
|
2012-11-01 16:42:29 +04:00
|
|
|
bool aUseCapture,
|
|
|
|
bool aSystemEventGroup);
|
|
|
|
|
1998-06-07 11:55:55 +04:00
|
|
|
/**
|
2017-07-06 15:00:35 +03:00
|
|
|
* Sets events listeners of all types.
|
1998-06-07 11:55:55 +04:00
|
|
|
* @param an event listener
|
|
|
|
*/
|
2018-04-11 17:27:01 +03:00
|
|
|
void AddEventListenerByType(nsIDOMEventListener* aListener,
|
|
|
|
const nsAString& type,
|
|
|
|
const EventListenerFlags& aFlags)
|
|
|
|
{
|
|
|
|
AddEventListenerByType(EventListenerHolder(aListener), type, aFlags);
|
|
|
|
}
|
|
|
|
void AddEventListenerByType(dom::EventListener* aListener,
|
2013-04-17 01:16:08 +04:00
|
|
|
const nsAString& type,
|
2014-03-17 10:56:53 +04:00
|
|
|
const EventListenerFlags& aFlags)
|
2013-04-17 01:16:08 +04:00
|
|
|
{
|
2016-07-28 05:00:06 +03:00
|
|
|
AddEventListenerByType(EventListenerHolder(aListener), type, aFlags);
|
2013-04-17 01:16:08 +04:00
|
|
|
}
|
2016-07-28 05:00:06 +03:00
|
|
|
void AddEventListenerByType(EventListenerHolder aListener,
|
2011-08-18 13:45:00 +04:00
|
|
|
const nsAString& type,
|
2018-04-04 19:19:54 +03:00
|
|
|
const EventListenerFlags& aFlags,
|
|
|
|
const dom::Optional<bool>& aPassive =
|
|
|
|
dom::Optional<bool>());
|
2018-04-11 17:27:01 +03:00
|
|
|
void RemoveEventListenerByType(nsIDOMEventListener* aListener,
|
|
|
|
const nsAString& type,
|
|
|
|
const EventListenerFlags& aFlags)
|
|
|
|
{
|
|
|
|
RemoveEventListenerByType(EventListenerHolder(aListener), type, aFlags);
|
|
|
|
}
|
|
|
|
void RemoveEventListenerByType(dom::EventListener* aListener,
|
2013-04-17 01:16:08 +04:00
|
|
|
const nsAString& type,
|
2014-03-17 10:56:53 +04:00
|
|
|
const EventListenerFlags& aFlags)
|
2013-04-17 01:16:08 +04:00
|
|
|
{
|
2016-07-28 05:00:06 +03:00
|
|
|
RemoveEventListenerByType(EventListenerHolder(aListener), type, aFlags);
|
2013-04-17 01:16:08 +04:00
|
|
|
}
|
2016-07-28 05:00:06 +03:00
|
|
|
void RemoveEventListenerByType(EventListenerHolder aListener,
|
2011-06-24 06:18:02 +04:00
|
|
|
const nsAString& type,
|
2014-03-17 10:56:53 +04:00
|
|
|
const EventListenerFlags& aFlags);
|
2011-08-24 23:49:25 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the current "inline" event listener for aName to be a
|
|
|
|
* function compiled from aFunc if !aDeferCompilation. If
|
|
|
|
* aDeferCompilation, then we assume that we can get the string from
|
|
|
|
* mTarget later and compile lazily.
|
2013-11-26 20:44:37 +04:00
|
|
|
*
|
|
|
|
* aElement, if not null, is the element the string is associated with.
|
2011-08-24 23:49:25 +04:00
|
|
|
*/
|
|
|
|
// XXXbz does that play correctly with nodes being adopted across
|
|
|
|
// documents? Need to double-check the spec here.
|
2017-10-03 01:05:19 +03:00
|
|
|
nsresult SetEventHandler(nsAtom *aName,
|
2012-08-30 20:25:10 +04:00
|
|
|
const nsAString& aFunc,
|
|
|
|
bool aDeferCompilation,
|
2013-11-26 20:44:37 +04:00
|
|
|
bool aPermitUntrustedEvents,
|
2014-03-17 10:56:53 +04:00
|
|
|
dom::Element* aElement);
|
2011-08-24 23:49:25 +04:00
|
|
|
/**
|
|
|
|
* Remove the current "inline" event listener for aName.
|
|
|
|
*/
|
2018-07-25 01:15:19 +03:00
|
|
|
void RemoveEventHandler(nsAtom *aName);
|
2011-06-24 06:18:02 +04:00
|
|
|
|
|
|
|
void HandleEvent(nsPresContext* aPresContext,
|
2017-07-06 15:00:35 +03:00
|
|
|
WidgetEvent* aEvent,
|
2018-04-20 19:53:16 +03:00
|
|
|
dom::Event** aDOMEvent,
|
2014-03-17 10:56:53 +04:00
|
|
|
dom::EventTarget* aCurrentTarget,
|
2018-04-04 15:57:17 +03:00
|
|
|
nsEventStatus* aEventStatus,
|
|
|
|
bool aItemInShadowTree)
|
2010-04-16 13:04:41 +04:00
|
|
|
{
|
2016-03-17 10:21:57 +03:00
|
|
|
if (mListeners.IsEmpty() || aEvent->PropagationStopped()) {
|
2011-06-24 06:18:02 +04:00
|
|
|
return;
|
2010-04-16 13:04:41 +04:00
|
|
|
}
|
|
|
|
|
2012-12-16 05:26:03 +04:00
|
|
|
if (!mMayHaveCapturingListeners && !aEvent->mFlags.mInBubblingPhase) {
|
2011-06-24 06:18:02 +04:00
|
|
|
return;
|
2010-04-16 13:04:41 +04:00
|
|
|
}
|
|
|
|
|
2012-12-16 05:26:05 +04:00
|
|
|
if (!mMayHaveSystemGroupListeners && aEvent->mFlags.mInSystemGroup) {
|
2011-06-24 06:18:02 +04:00
|
|
|
return;
|
2010-04-16 13:04:41 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check if we already know that there is no event listener for the event.
|
2015-08-22 04:34:51 +03:00
|
|
|
if (mNoListenerForEvent == aEvent->mMessage &&
|
2015-09-10 04:40:04 +03:00
|
|
|
(mNoListenerForEvent != eUnidentifiedEvent ||
|
2016-04-18 17:53:03 +03:00
|
|
|
mNoListenerForEventAtom == aEvent->mSpecifiedEventType)) {
|
2011-06-24 06:18:02 +04:00
|
|
|
return;
|
2010-04-16 13:04:41 +04:00
|
|
|
}
|
2011-06-24 06:18:02 +04:00
|
|
|
HandleEventInternal(aPresContext, aEvent, aDOMEvent, aCurrentTarget,
|
2018-04-04 15:57:17 +03:00
|
|
|
aEventStatus, aItemInShadowTree);
|
2010-04-16 13:04:41 +04:00
|
|
|
}
|
|
|
|
|
2011-08-24 23:49:25 +04:00
|
|
|
/**
|
|
|
|
* Tells the event listener manager that its target (which owns it) is
|
|
|
|
* no longer using it (and could go away).
|
|
|
|
*/
|
2011-06-24 06:18:02 +04:00
|
|
|
void Disconnect();
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 20:46:42 +04:00
|
|
|
|
2011-08-24 23:49:25 +04:00
|
|
|
/**
|
|
|
|
* Allows us to quickly determine if we have mutation listeners registered.
|
|
|
|
*/
|
2011-09-29 10:19:26 +04:00
|
|
|
bool HasMutationListeners();
|
2002-11-09 03:25:25 +03:00
|
|
|
|
2011-08-24 23:49:25 +04:00
|
|
|
/**
|
|
|
|
* Allows us to quickly determine whether we have unload or beforeunload
|
|
|
|
* listeners registered.
|
|
|
|
*/
|
2011-09-29 10:19:26 +04:00
|
|
|
bool HasUnloadListeners();
|
2005-05-05 00:22:32 +04:00
|
|
|
|
2011-08-24 23:49:25 +04:00
|
|
|
/**
|
|
|
|
* Returns the mutation bits depending on which mutation listeners are
|
|
|
|
* registered to this listener manager.
|
|
|
|
* @note If a listener is an nsIDOMMutationListener, all possible mutation
|
|
|
|
* event bits are returned. All bits are also returned if one of the
|
|
|
|
* event listeners is registered to handle DOMSubtreeModified events.
|
|
|
|
*/
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t MutationListenerBits();
|
2007-02-01 01:54:24 +03:00
|
|
|
|
2011-08-24 23:49:25 +04:00
|
|
|
/**
|
2011-10-17 18:59:28 +04:00
|
|
|
* Returns true if there is at least one event listener for aEventName.
|
2011-08-24 23:49:25 +04:00
|
|
|
*/
|
2018-03-29 05:40:32 +03:00
|
|
|
bool HasListenersFor(const nsAString& aEventName) const;
|
2007-05-09 01:13:13 +04:00
|
|
|
|
2012-08-17 18:12:58 +04:00
|
|
|
/**
|
|
|
|
* Returns true if there is at least one event listener for aEventNameWithOn.
|
|
|
|
* Note that aEventNameWithOn must start with "on"!
|
|
|
|
*/
|
2018-03-29 05:40:32 +03:00
|
|
|
bool HasListenersFor(nsAtom* aEventNameWithOn) const;
|
2012-08-17 18:12:58 +04:00
|
|
|
|
2011-08-24 23:49:25 +04:00
|
|
|
/**
|
2011-10-17 18:59:28 +04:00
|
|
|
* Returns true if there is at least one event listener.
|
2011-08-24 23:49:25 +04:00
|
|
|
*/
|
2018-03-29 05:40:32 +03:00
|
|
|
bool HasListeners() const;
|
2008-10-01 04:51:53 +04:00
|
|
|
|
2011-08-24 23:49:25 +04:00
|
|
|
/**
|
|
|
|
* Sets aList to the list of nsIEventListenerInfo objects representing the
|
|
|
|
* listeners managed by this listener manager.
|
|
|
|
*/
|
2011-06-24 06:18:02 +04:00
|
|
|
nsresult GetListenerInfo(nsCOMArray<nsIEventListenerInfo>* aList);
|
2009-10-16 12:57:32 +04:00
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
uint32_t GetIdentifierForEvent(nsAtom* aEvent);
|
1999-11-25 03:05:21 +03:00
|
|
|
|
2002-02-13 07:20:46 +03:00
|
|
|
static void Shutdown();
|
|
|
|
|
2011-06-24 06:18:01 +04:00
|
|
|
/**
|
2011-10-17 18:59:28 +04:00
|
|
|
* Returns true if there may be a paint event listener registered,
|
|
|
|
* false if there definitely isn't.
|
2011-06-24 06:18:01 +04:00
|
|
|
*/
|
2011-09-29 10:19:26 +04:00
|
|
|
bool MayHavePaintEventListener() { return mMayHavePaintEventListener; }
|
2011-06-24 06:18:01 +04:00
|
|
|
|
2015-04-03 03:45:50 +03:00
|
|
|
/**
|
|
|
|
* Returns true if there may be a touch event listener registered,
|
|
|
|
* false if there definitely isn't.
|
|
|
|
*/
|
|
|
|
bool MayHaveTouchEventListener() { return mMayHaveTouchEventListener; }
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool MayHaveMouseEnterLeaveEventListener() { return mMayHaveMouseEnterLeaveEventListener; }
|
2014-02-11 10:33:29 +04:00
|
|
|
bool MayHavePointerEnterLeaveEventListener() { return mMayHavePointerEnterLeaveEventListener; }
|
2017-06-22 21:01:27 +03:00
|
|
|
bool MayHaveSelectionChangeEventListener() { return mMayHaveSelectionChangeEventListener; }
|
2011-09-18 11:45:14 +04:00
|
|
|
|
2015-06-17 02:02:39 +03:00
|
|
|
/**
|
|
|
|
* Returns true if there may be a key event listener (keydown, keypress,
|
|
|
|
* or keyup) registered, or false if there definitely isn't.
|
|
|
|
*/
|
|
|
|
bool MayHaveKeyEventListener() { return mMayHaveKeyEventListener; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns true if there may be an advanced input event listener (input,
|
|
|
|
* compositionstart, compositionupdate, or compositionend) registered,
|
|
|
|
* or false if there definitely isn't.
|
|
|
|
*/
|
|
|
|
bool MayHaveInputOrCompositionEventListener() { return mMayHaveInputOrCompositionEventListener; }
|
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
|
2012-01-26 18:45:12 +04:00
|
|
|
|
2013-10-28 13:47:18 +04:00
|
|
|
uint32_t ListenerCount() const
|
|
|
|
{
|
|
|
|
return mListeners.Length();
|
|
|
|
}
|
|
|
|
|
2012-10-17 05:22:02 +04:00
|
|
|
void MarkForCC();
|
2012-01-26 18:45:12 +04:00
|
|
|
|
2014-06-05 03:48:50 +04:00
|
|
|
void TraceListeners(JSTracer* aTrc);
|
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
dom::EventTarget* GetTarget() { return mTarget; }
|
|
|
|
|
2017-07-28 02:46:44 +03:00
|
|
|
bool HasNonSystemGroupListenersForUntrustedKeyEvents();
|
|
|
|
bool HasNonPassiveNonSystemGroupListenersForUntrustedKeyEvents();
|
2017-06-06 03:22:16 +03:00
|
|
|
|
2015-09-17 13:16:20 +03:00
|
|
|
bool HasApzAwareListeners();
|
2016-05-12 21:50:58 +03:00
|
|
|
bool IsApzAwareListener(Listener* aListener);
|
2017-10-03 01:05:19 +03:00
|
|
|
bool IsApzAwareEvent(nsAtom* aEvent);
|
2015-09-17 13:16:20 +03:00
|
|
|
|
1998-06-07 11:55:55 +04:00
|
|
|
protected:
|
2012-12-16 05:26:05 +04:00
|
|
|
void HandleEventInternal(nsPresContext* aPresContext,
|
2014-03-17 10:56:53 +04:00
|
|
|
WidgetEvent* aEvent,
|
2018-04-20 19:53:16 +03:00
|
|
|
dom::Event** aDOMEvent,
|
2014-03-17 10:56:53 +04:00
|
|
|
dom::EventTarget* aCurrentTarget,
|
2018-04-04 15:57:17 +03:00
|
|
|
nsEventStatus* aEventStatus,
|
|
|
|
bool aItemInShadowTree);
|
2012-12-16 05:26:05 +04:00
|
|
|
|
2014-03-17 10:56:51 +04:00
|
|
|
nsresult HandleEventSubType(Listener* aListener,
|
2018-04-20 19:53:16 +03:00
|
|
|
dom::Event* aDOMEvent,
|
2014-03-17 10:56:53 +04:00
|
|
|
dom::EventTarget* aCurrentTarget);
|
2011-08-24 23:49:25 +04:00
|
|
|
|
2016-02-02 21:03:49 +03:00
|
|
|
/**
|
|
|
|
* If the given EventMessage has a legacy version that we support, then this
|
|
|
|
* function returns that legacy version. Otherwise, this function simply
|
|
|
|
* returns the passed-in EventMessage.
|
|
|
|
*/
|
|
|
|
EventMessage GetLegacyEventMessage(EventMessage aEventMessage) const;
|
|
|
|
|
2018-07-25 01:15:19 +03:00
|
|
|
/**
|
|
|
|
* Get the event message for the given event name.
|
|
|
|
*/
|
|
|
|
EventMessage GetEventMessage(nsAtom* aEventName) const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the event message and atom for the given event type.
|
|
|
|
*/
|
|
|
|
EventMessage GetEventMessageAndAtomForListener(const nsAString& aType,
|
|
|
|
nsAtom** aAtom);
|
|
|
|
|
2016-02-11 02:47:59 +03:00
|
|
|
void ProcessApzAwareEventListenerAdd();
|
|
|
|
|
2011-08-24 23:49:25 +04:00
|
|
|
/**
|
2014-03-17 10:56:51 +04:00
|
|
|
* Compile the "inline" event listener for aListener. The
|
2011-08-24 23:49:25 +04:00
|
|
|
* body of the listener can be provided in aBody; if this is null we
|
2013-11-26 20:44:37 +04:00
|
|
|
* will look for it on mTarget. If aBody is provided, aElement should be
|
|
|
|
* as well; otherwise it will also be inferred from mTarget.
|
2011-08-24 23:49:25 +04:00
|
|
|
*/
|
2014-03-17 10:56:51 +04:00
|
|
|
nsresult CompileEventHandlerInternal(Listener* aListener,
|
2013-11-26 20:44:37 +04:00
|
|
|
const nsAString* aBody,
|
2014-03-17 10:56:53 +04:00
|
|
|
dom::Element* aElement);
|
2011-08-24 23:49:25 +04:00
|
|
|
|
|
|
|
/**
|
2014-03-17 10:56:51 +04:00
|
|
|
* Find the Listener for the "inline" event listener for aTypeAtom.
|
2011-08-24 23:49:25 +04:00
|
|
|
*/
|
2015-08-26 15:56:59 +03:00
|
|
|
Listener* FindEventHandler(EventMessage aEventMessage,
|
2018-07-25 01:15:19 +03:00
|
|
|
nsAtom* aTypeAtom);
|
2011-08-24 23:49:25 +04:00
|
|
|
|
|
|
|
/**
|
2012-11-09 20:00:25 +04:00
|
|
|
* Set the "inline" event listener for aName to aHandler. aHandler may be
|
|
|
|
* have no actual handler set to indicate that we should lazily get and
|
2012-11-09 20:00:25 +04:00
|
|
|
* compile the string for this listener, but in that case aContext and
|
|
|
|
* aScopeGlobal must be non-null. Otherwise, aContext and aScopeGlobal are
|
2014-03-17 10:56:51 +04:00
|
|
|
* allowed to be null.
|
2011-08-24 23:49:25 +04:00
|
|
|
*/
|
2017-10-03 01:05:19 +03:00
|
|
|
Listener* SetEventHandlerInternal(nsAtom* aName,
|
2014-04-02 06:00:45 +04:00
|
|
|
const TypedEventHandler& aHandler,
|
2014-03-17 10:56:51 +04:00
|
|
|
bool aPermitUntrustedEvents);
|
2011-08-24 23:49:25 +04:00
|
|
|
|
2015-08-26 15:56:59 +03:00
|
|
|
bool IsDeviceType(EventMessage aEventMessage);
|
|
|
|
void EnableDevice(EventMessage aEventMessage);
|
|
|
|
void DisableDevice(EventMessage aEventMessage);
|
2012-03-29 21:23:27 +04:00
|
|
|
|
2011-08-24 23:49:25 +04:00
|
|
|
public:
|
|
|
|
/**
|
2012-11-09 20:00:25 +04:00
|
|
|
* Set the "inline" event listener for aEventName to aHandler. If
|
|
|
|
* aHandler is null, this will actually remove the event listener
|
2011-08-24 23:49:25 +04:00
|
|
|
*/
|
2017-10-03 01:05:19 +03:00
|
|
|
void SetEventHandler(nsAtom* aEventName,
|
2014-03-17 10:56:53 +04:00
|
|
|
dom::EventHandlerNonNull* aHandler);
|
|
|
|
void SetEventHandler(dom::OnErrorEventHandlerNonNull* aHandler);
|
|
|
|
void SetEventHandler(dom::OnBeforeUnloadEventHandlerNonNull* aHandler);
|
2012-11-09 20:00:25 +04:00
|
|
|
|
2011-08-24 23:49:25 +04:00
|
|
|
/**
|
|
|
|
* Get the value of the "inline" event listener for aEventName.
|
|
|
|
* This may cause lazy compilation if the listener is uncompiled.
|
2012-11-09 20:00:25 +04:00
|
|
|
*
|
|
|
|
* Note: It's the caller's responsibility to make sure to call the right one
|
|
|
|
* of these methods. In particular, "onerror" events use
|
|
|
|
* OnErrorEventHandlerNonNull for some event targets and EventHandlerNonNull
|
|
|
|
* for others.
|
2011-08-24 23:49:25 +04:00
|
|
|
*/
|
2018-07-25 01:15:19 +03:00
|
|
|
dom::EventHandlerNonNull* GetEventHandler(nsAtom* aEventName)
|
2012-11-09 20:00:25 +04:00
|
|
|
{
|
2018-07-25 01:15:19 +03:00
|
|
|
const TypedEventHandler* typedHandler = GetTypedEventHandler(aEventName);
|
2014-04-02 06:00:45 +04:00
|
|
|
return typedHandler ? typedHandler->NormalEventHandler() : nullptr;
|
2012-11-09 20:00:25 +04:00
|
|
|
}
|
2014-03-17 10:56:53 +04:00
|
|
|
|
|
|
|
dom::OnErrorEventHandlerNonNull* GetOnErrorEventHandler()
|
2012-11-09 20:00:25 +04:00
|
|
|
{
|
2018-07-25 01:15:19 +03:00
|
|
|
const TypedEventHandler* typedHandler =
|
|
|
|
GetTypedEventHandler(nsGkAtoms::onerror);
|
2014-04-02 06:00:45 +04:00
|
|
|
return typedHandler ? typedHandler->OnErrorEventHandler() : nullptr;
|
2012-11-09 20:00:25 +04:00
|
|
|
}
|
2014-03-17 10:56:53 +04:00
|
|
|
|
|
|
|
dom::OnBeforeUnloadEventHandlerNonNull* GetOnBeforeUnloadEventHandler()
|
2012-11-09 20:00:25 +04:00
|
|
|
{
|
2014-04-02 06:00:45 +04:00
|
|
|
const TypedEventHandler* typedHandler =
|
2018-07-25 01:15:19 +03:00
|
|
|
GetTypedEventHandler(nsGkAtoms::onbeforeunload);
|
2014-04-02 06:00:45 +04:00
|
|
|
return typedHandler ? typedHandler->OnBeforeUnloadEventHandler() : nullptr;
|
2012-11-09 20:00:25 +04:00
|
|
|
}
|
2011-08-24 23:49:25 +04:00
|
|
|
|
2018-04-04 15:57:17 +03:00
|
|
|
private:
|
|
|
|
already_AddRefed<nsPIDOMWindowInner> WindowFromListener(Listener* aListener,
|
|
|
|
bool aItemInShadowTree);
|
|
|
|
|
2011-08-24 23:49:25 +04:00
|
|
|
protected:
|
2012-11-09 20:00:25 +04:00
|
|
|
/**
|
|
|
|
* Helper method for implementing the various Get*EventHandler above. Will
|
|
|
|
* return null if we don't have an event handler for this event name.
|
|
|
|
*/
|
2018-07-25 01:15:19 +03:00
|
|
|
const TypedEventHandler* GetTypedEventHandler(nsAtom* aEventName);
|
2012-11-09 20:00:25 +04:00
|
|
|
|
2016-04-26 11:23:17 +03:00
|
|
|
void AddEventListener(const nsAString& aType,
|
2016-07-28 05:00:06 +03:00
|
|
|
EventListenerHolder aListener,
|
2016-04-26 11:23:17 +03:00
|
|
|
const dom::AddEventListenerOptionsOrBoolean& aOptions,
|
|
|
|
bool aWantsUntrusted);
|
2013-04-17 01:16:08 +04:00
|
|
|
void AddEventListener(const nsAString& aType,
|
2016-07-28 05:00:06 +03:00
|
|
|
EventListenerHolder aListener,
|
2013-04-17 01:16:08 +04:00
|
|
|
bool aUseCapture,
|
|
|
|
bool aWantsUntrusted);
|
2016-04-26 11:23:17 +03:00
|
|
|
void RemoveEventListener(const nsAString& aType,
|
2016-07-28 05:00:06 +03:00
|
|
|
EventListenerHolder aListener,
|
2016-04-26 11:23:17 +03:00
|
|
|
const dom::EventListenerOptionsOrBoolean& aOptions);
|
2013-04-17 01:16:08 +04:00
|
|
|
void RemoveEventListener(const nsAString& aType,
|
2016-07-28 05:00:06 +03:00
|
|
|
EventListenerHolder aListener,
|
2013-04-17 01:16:08 +04:00
|
|
|
bool aUseCapture);
|
|
|
|
|
2016-07-28 05:00:06 +03:00
|
|
|
void AddEventListenerInternal(EventListenerHolder aListener,
|
2015-08-26 15:56:59 +03:00
|
|
|
EventMessage aEventMessage,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* aTypeAtom,
|
2014-03-17 10:56:53 +04:00
|
|
|
const EventListenerFlags& aFlags,
|
|
|
|
bool aHandler = false,
|
|
|
|
bool aAllEvents = false);
|
2016-07-28 05:00:06 +03:00
|
|
|
void RemoveEventListenerInternal(EventListenerHolder aListener,
|
2015-08-26 15:56:59 +03:00
|
|
|
EventMessage aEventMessage,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* aUserType,
|
2014-03-17 10:56:53 +04:00
|
|
|
const EventListenerFlags& aFlags,
|
|
|
|
bool aAllEvents = false);
|
2011-06-24 06:18:02 +04:00
|
|
|
void RemoveAllListeners();
|
2018-07-25 01:15:19 +03:00
|
|
|
void NotifyEventListenerRemoved(nsAtom* aUserType);
|
2006-10-06 09:24:02 +04:00
|
|
|
const EventTypeData* GetTypeDataForIID(const nsIID& aIID);
|
2017-10-03 01:05:19 +03:00
|
|
|
const EventTypeData* GetTypeDataForEventName(nsAtom* aName);
|
2016-01-30 20:05:36 +03:00
|
|
|
nsPIDOMWindowInner* GetInnerWindowForTarget();
|
|
|
|
already_AddRefed<nsPIDOMWindowInner> GetTargetAsInnerWindow() const;
|
2006-10-06 09:24:02 +04:00
|
|
|
|
2016-02-02 21:03:49 +03:00
|
|
|
bool ListenerCanHandle(const Listener* aListener,
|
|
|
|
const WidgetEvent* aEvent,
|
|
|
|
EventMessage aEventMessage) const;
|
2013-08-16 14:06:24 +04:00
|
|
|
|
2015-08-26 15:56:59 +03:00
|
|
|
// BE AWARE, a lot of instances of EventListenerManager will be created.
|
|
|
|
// Therefor, we need to keep this class compact. When you add integer
|
|
|
|
// members, please add them to EventListemerManagerBase and check the size
|
|
|
|
// at build time.
|
|
|
|
|
2013-11-27 13:12:41 +04:00
|
|
|
already_AddRefed<nsIScriptGlobalObject>
|
|
|
|
GetScriptGlobalAndDocument(nsIDocument** aDoc);
|
|
|
|
|
2014-03-17 10:56:51 +04:00
|
|
|
nsAutoTObserverArray<Listener, 2> mListeners;
|
2015-01-18 06:15:47 +03:00
|
|
|
dom::EventTarget* MOZ_NON_OWNING_REF mTarget;
|
2017-10-03 01:05:19 +03:00
|
|
|
RefPtr<nsAtom> mNoListenerForEventAtom;
|
2006-10-06 09:24:02 +04:00
|
|
|
|
2014-03-18 08:48:22 +04:00
|
|
|
friend class ELMCreationDetector;
|
2014-03-17 10:56:53 +04:00
|
|
|
static uint32_t sMainThreadCreatedCount;
|
1998-06-07 11:55:55 +04:00
|
|
|
};
|
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
#endif // mozilla_EventListenerManager_h_
|