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
|
|
|
// Microsoft's API Name hackery sucks
|
|
|
|
#undef CreateEvent
|
|
|
|
|
2014-06-21 22:55:15 +04:00
|
|
|
#include "mozilla/AddonPathService.h"
|
2013-09-25 15:21:22 +04:00
|
|
|
#include "mozilla/BasicEvents.h"
|
2014-06-05 03:48:50 +04:00
|
|
|
#include "mozilla/CycleCollectedJSRuntime.h"
|
2014-10-28 14:18:00 +03:00
|
|
|
#include "mozilla/DOMEventTargetHelper.h"
|
2014-03-18 08:48:21 +04:00
|
|
|
#include "mozilla/EventDispatcher.h"
|
2014-03-17 10:56:53 +04:00
|
|
|
#include "mozilla/EventListenerManager.h"
|
2013-08-30 01:18:25 +04:00
|
|
|
#ifdef MOZ_B2G
|
2012-03-25 04:29:49 +04:00
|
|
|
#include "mozilla/Hal.h"
|
2014-03-17 10:56:53 +04:00
|
|
|
#endif // #ifdef MOZ_B2G
|
2012-03-25 04:29:49 +04:00
|
|
|
#include "mozilla/HalSensor.h"
|
2014-03-17 10:56:53 +04:00
|
|
|
#include "mozilla/InternalMutationEvent.h"
|
2014-04-02 06:00:45 +04:00
|
|
|
#include "mozilla/JSEventHandler.h"
|
2016-02-02 21:03:49 +03:00
|
|
|
#include "mozilla/Maybe.h"
|
2013-06-23 16:03:39 +04:00
|
|
|
#include "mozilla/MemoryReporting.h"
|
2016-02-02 21:03:49 +03:00
|
|
|
#include "mozilla/Preferences.h"
|
2014-03-17 10:56:53 +04:00
|
|
|
#include "mozilla/dom/BindingUtils.h"
|
|
|
|
#include "mozilla/dom/Element.h"
|
|
|
|
#include "mozilla/dom/Event.h"
|
2016-04-26 11:23:17 +03:00
|
|
|
#include "mozilla/dom/EventTargetBinding.h"
|
2016-05-24 18:24:31 +03:00
|
|
|
#include "mozilla/dom/TouchEvent.h"
|
2015-07-18 16:35:59 +03:00
|
|
|
#include "mozilla/TimelineConsumers.h"
|
2015-08-31 15:56:37 +03:00
|
|
|
#include "mozilla/EventTimelineMarker.h"
|
2014-03-17 10:56:53 +04:00
|
|
|
|
|
|
|
#include "EventListenerService.h"
|
|
|
|
#include "nsCOMArray.h"
|
1999-09-09 04:28:11 +04:00
|
|
|
#include "nsCOMPtr.h"
|
2014-03-17 10:56:53 +04:00
|
|
|
#include "nsContentUtils.h"
|
|
|
|
#include "nsDOMCID.h"
|
2012-07-27 18:03:27 +04:00
|
|
|
#include "nsError.h"
|
2014-03-17 10:56:53 +04:00
|
|
|
#include "nsGkAtoms.h"
|
2014-12-09 13:38:23 +03:00
|
|
|
#include "nsHtml5Atoms.h"
|
2014-03-17 10:56:53 +04:00
|
|
|
#include "nsIContent.h"
|
|
|
|
#include "nsIContentSecurityPolicy.h"
|
2000-05-16 15:35:12 +04:00
|
|
|
#include "nsIDocument.h"
|
2014-03-17 10:56:53 +04:00
|
|
|
#include "nsIDOMEventListener.h"
|
|
|
|
#include "nsIScriptGlobalObject.h"
|
|
|
|
#include "nsISupports.h"
|
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
|
|
|
#include "nsIXPConnect.h"
|
2004-04-13 07:21:50 +04:00
|
|
|
#include "nsJSUtils.h"
|
2014-03-17 10:56:53 +04:00
|
|
|
#include "nsNameSpaceManager.h"
|
|
|
|
#include "nsPIDOMWindow.h"
|
2012-08-20 22:34:32 +04:00
|
|
|
#include "nsSandboxFlags.h"
|
2014-03-17 10:56:53 +04:00
|
|
|
#include "xpcpublic.h"
|
2016-02-11 02:47:59 +03:00
|
|
|
#include "nsIFrame.h"
|
2016-03-04 00:52:09 +03:00
|
|
|
#include "nsDisplayList.h"
|
2014-03-17 10:56:53 +04:00
|
|
|
|
|
|
|
namespace mozilla {
|
2006-10-06 09:24:02 +04:00
|
|
|
|
2016-06-02 13:15:23 +03:00
|
|
|
namespace dom {
|
|
|
|
namespace workers {
|
|
|
|
extern bool IsCurrentThreadRunningChromeWorker();
|
|
|
|
} // namespace workers
|
|
|
|
} // namespace dom
|
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
using namespace dom;
|
|
|
|
using namespace hal;
|
2010-04-30 17:12:05 +04:00
|
|
|
|
2015-08-26 15:56:59 +03:00
|
|
|
#define EVENT_TYPE_EQUALS(ls, message, userType, typeString, allEvents) \
|
|
|
|
((ls->mEventMessage == message && \
|
2015-09-10 04:40:04 +03:00
|
|
|
(ls->mEventMessage != eUnidentifiedEvent || \
|
2015-08-26 15:56:59 +03:00
|
|
|
(mIsMainThreadELM && ls->mTypeAtom == userType) || \
|
|
|
|
(!mIsMainThreadELM && ls->mTypeString.Equals(typeString)))) || \
|
2012-11-01 16:42:29 +04:00
|
|
|
(allEvents && ls->mAllEvents))
|
2006-10-06 09:24:02 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
static const uint32_t kAllMutationBits =
|
2007-02-01 01:54:24 +03:00
|
|
|
NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED |
|
|
|
|
NS_EVENT_BITS_MUTATION_NODEINSERTED |
|
|
|
|
NS_EVENT_BITS_MUTATION_NODEREMOVED |
|
|
|
|
NS_EVENT_BITS_MUTATION_NODEREMOVEDFROMDOCUMENT |
|
|
|
|
NS_EVENT_BITS_MUTATION_NODEINSERTEDINTODOCUMENT |
|
|
|
|
NS_EVENT_BITS_MUTATION_ATTRMODIFIED |
|
|
|
|
NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED;
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
static uint32_t
|
2015-08-26 15:56:59 +03:00
|
|
|
MutationBitForEventType(EventMessage aEventType)
|
2007-02-01 01:54:24 +03:00
|
|
|
{
|
|
|
|
switch (aEventType) {
|
2015-09-07 17:55:51 +03:00
|
|
|
case eLegacySubtreeModified:
|
2007-02-01 01:54:24 +03:00
|
|
|
return NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED;
|
2015-09-07 17:55:51 +03:00
|
|
|
case eLegacyNodeInserted:
|
2007-02-01 01:54:24 +03:00
|
|
|
return NS_EVENT_BITS_MUTATION_NODEINSERTED;
|
2015-09-07 17:55:51 +03:00
|
|
|
case eLegacyNodeRemoved:
|
2007-02-01 01:54:24 +03:00
|
|
|
return NS_EVENT_BITS_MUTATION_NODEREMOVED;
|
2015-09-07 17:55:50 +03:00
|
|
|
case eLegacyNodeRemovedFromDocument:
|
2007-02-01 01:54:24 +03:00
|
|
|
return NS_EVENT_BITS_MUTATION_NODEREMOVEDFROMDOCUMENT;
|
2015-09-07 17:55:50 +03:00
|
|
|
case eLegacyNodeInsertedIntoDocument:
|
2007-02-01 01:54:24 +03:00
|
|
|
return NS_EVENT_BITS_MUTATION_NODEINSERTEDINTODOCUMENT;
|
2015-09-07 17:55:51 +03:00
|
|
|
case eLegacyAttrModified:
|
2007-02-01 01:54:24 +03:00
|
|
|
return NS_EVENT_BITS_MUTATION_ATTRMODIFIED;
|
2015-09-07 17:55:50 +03:00
|
|
|
case eLegacyCharacterDataModified:
|
2007-02-01 01:54:24 +03:00
|
|
|
return NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
uint32_t EventListenerManager::sMainThreadCreatedCount = 0;
|
|
|
|
|
2016-02-02 21:03:49 +03:00
|
|
|
static bool
|
|
|
|
IsWebkitPrefixSupportEnabled()
|
|
|
|
{
|
|
|
|
static bool sIsWebkitPrefixSupportEnabled;
|
|
|
|
static bool sIsPrefCached = false;
|
|
|
|
|
|
|
|
if (!sIsPrefCached) {
|
|
|
|
sIsPrefCached = true;
|
|
|
|
Preferences::AddBoolVarCache(&sIsWebkitPrefixSupportEnabled,
|
|
|
|
"layout.css.prefixes.webkit");
|
|
|
|
}
|
|
|
|
|
|
|
|
return sIsWebkitPrefixSupportEnabled;
|
|
|
|
}
|
|
|
|
|
2015-08-26 15:56:59 +03:00
|
|
|
EventListenerManagerBase::EventListenerManagerBase()
|
2015-08-29 02:58:26 +03:00
|
|
|
: mNoListenerForEvent(eVoidEvent)
|
2015-08-26 15:56:59 +03:00
|
|
|
, mMayHavePaintEventListener(false)
|
2014-03-17 10:56:53 +04:00
|
|
|
, mMayHaveMutationListeners(false)
|
|
|
|
, mMayHaveCapturingListeners(false)
|
|
|
|
, mMayHaveSystemGroupListeners(false)
|
2015-04-03 03:45:50 +03:00
|
|
|
, mMayHaveTouchEventListener(false)
|
2014-03-17 10:56:53 +04:00
|
|
|
, mMayHaveMouseEnterLeaveEventListener(false)
|
|
|
|
, mMayHavePointerEnterLeaveEventListener(false)
|
2015-06-17 02:02:39 +03:00
|
|
|
, mMayHaveKeyEventListener(false)
|
|
|
|
, mMayHaveInputOrCompositionEventListener(false)
|
2014-03-17 10:56:53 +04:00
|
|
|
, mClearingListeners(false)
|
|
|
|
, mIsMainThreadELM(NS_IsMainThread())
|
2015-08-26 15:56:59 +03:00
|
|
|
{
|
|
|
|
static_assert(sizeof(EventListenerManagerBase) == sizeof(uint32_t),
|
|
|
|
"Keep the size of EventListenerManagerBase size compact!");
|
|
|
|
}
|
|
|
|
|
|
|
|
EventListenerManager::EventListenerManager(EventTarget* aTarget)
|
|
|
|
: EventListenerManagerBase()
|
2014-03-17 10:56:53 +04:00
|
|
|
, mTarget(aTarget)
|
1998-07-23 06:55:33 +04:00
|
|
|
{
|
2011-06-24 06:18:01 +04:00
|
|
|
NS_ASSERTION(aTarget, "unexpected null pointer");
|
|
|
|
|
2013-08-16 14:06:24 +04:00
|
|
|
if (mIsMainThreadELM) {
|
2013-06-28 13:53:37 +04:00
|
|
|
++sMainThreadCreatedCount;
|
|
|
|
}
|
1998-06-07 11:55:55 +04:00
|
|
|
}
|
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::~EventListenerManager()
|
1998-07-23 06:55:33 +04:00
|
|
|
{
|
2010-08-11 17:59:00 +04:00
|
|
|
// If your code fails this assertion, a possible reason is that
|
|
|
|
// a class did not call our Disconnect() manually. Note that
|
|
|
|
// this class can have Disconnect called in one of two ways:
|
|
|
|
// if it is part of a cycle, then in Unlink() (such a cycle
|
|
|
|
// would be with one of the listeners, not mTarget which is weak).
|
|
|
|
// If not part of a cycle, then Disconnect must be called manually,
|
|
|
|
// typically from the destructor of the owner class (mTarget).
|
|
|
|
// XXX azakai: Is there any reason to not just call Disconnect
|
|
|
|
// from right here, if not previously called?
|
2006-09-20 05:13:59 +04:00
|
|
|
NS_ASSERTION(!mTarget, "didn't call Disconnect");
|
2006-01-12 22:11:44 +03:00
|
|
|
RemoveAllListeners();
|
2001-04-17 09:52:11 +04:00
|
|
|
}
|
|
|
|
|
2011-06-24 06:18:02 +04:00
|
|
|
void
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::RemoveAllListeners()
|
2001-04-17 09:52:11 +04:00
|
|
|
{
|
2012-11-30 13:13:16 +04:00
|
|
|
if (mClearingListeners) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mClearingListeners = true;
|
2006-10-06 09:24:02 +04:00
|
|
|
mListeners.Clear();
|
2012-11-30 13:13:16 +04:00
|
|
|
mClearingListeners = false;
|
1998-06-07 11:55:55 +04:00
|
|
|
}
|
|
|
|
|
2005-04-29 03:48:28 +04:00
|
|
|
void
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::Shutdown()
|
2002-02-13 07:20:46 +03:00
|
|
|
{
|
2014-03-05 04:37:43 +04:00
|
|
|
Event::Shutdown();
|
2002-02-13 07:20:46 +03:00
|
|
|
}
|
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(EventListenerManager, AddRef)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(EventListenerManager, Release)
|
2007-01-05 01:31:26 +03:00
|
|
|
|
2012-11-23 23:13:39 +04:00
|
|
|
inline void
|
|
|
|
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::Listener& aField,
|
2012-11-23 23:13:39 +04:00
|
|
|
const char* aName,
|
|
|
|
unsigned aFlags)
|
|
|
|
{
|
2013-07-31 02:04:38 +04:00
|
|
|
if (MOZ_UNLIKELY(aCallback.WantDebugInfo())) {
|
|
|
|
nsAutoCString name;
|
|
|
|
name.AppendASCII(aName);
|
|
|
|
if (aField.mTypeAtom) {
|
|
|
|
name.AppendASCII(" event=");
|
|
|
|
name.Append(nsAtomCString(aField.mTypeAtom));
|
|
|
|
name.AppendASCII(" listenerType=");
|
|
|
|
name.AppendInt(aField.mListenerType);
|
|
|
|
name.AppendASCII(" ");
|
|
|
|
}
|
|
|
|
CycleCollectionNoteChild(aCallback, aField.mListener.GetISupports(), name.get(),
|
|
|
|
aFlags);
|
|
|
|
} else {
|
|
|
|
CycleCollectionNoteChild(aCallback, aField.mListener.GetISupports(), aName,
|
|
|
|
aFlags);
|
|
|
|
}
|
2012-11-23 23:13:39 +04:00
|
|
|
}
|
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(EventListenerManager)
|
2013-08-02 05:29:05 +04:00
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(EventListenerManager)
|
2012-11-23 23:13:39 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListeners)
|
2007-01-05 01:31:26 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(EventListenerManager)
|
2007-01-05 01:31:26 +03:00
|
|
|
tmp->Disconnect();
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsPIDOMWindowInner*
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::GetInnerWindowForTarget()
|
2008-10-16 01:06:32 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsINode> node = do_QueryInterface(mTarget);
|
|
|
|
if (node) {
|
|
|
|
// XXX sXBL/XBL2 issue -- do we really want the owner here? What
|
|
|
|
// if that's the XBL document?
|
2011-10-18 15:19:44 +04:00
|
|
|
return node->OwnerDoc()->GetInnerWindow();
|
2008-10-16 01:06:32 +04:00
|
|
|
}
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowInner> window = GetTargetAsInnerWindow();
|
2012-10-01 13:43:53 +04:00
|
|
|
return window;
|
2008-10-16 01:06:32 +04:00
|
|
|
}
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
already_AddRefed<nsPIDOMWindowInner>
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::GetTargetAsInnerWindow() const
|
2012-09-30 17:47:48 +04:00
|
|
|
{
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(mTarget);
|
2012-09-30 17:47:48 +04:00
|
|
|
return window.forget();
|
|
|
|
}
|
|
|
|
|
2011-08-18 13:45:00 +04:00
|
|
|
void
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::AddEventListenerInternal(
|
2014-03-17 10:56:53 +04:00
|
|
|
const EventListenerHolder& aListenerHolder,
|
2015-08-26 15:56:59 +03:00
|
|
|
EventMessage aEventMessage,
|
2014-03-17 10:56:53 +04:00
|
|
|
nsIAtom* aTypeAtom,
|
|
|
|
const nsAString& aTypeString,
|
|
|
|
const EventListenerFlags& aFlags,
|
|
|
|
bool aHandler,
|
|
|
|
bool aAllEvents)
|
1998-06-07 11:55:55 +04:00
|
|
|
{
|
2015-08-26 15:56:59 +03:00
|
|
|
MOZ_ASSERT(// Main thread
|
|
|
|
(NS_IsMainThread() && aEventMessage && aTypeAtom) ||
|
|
|
|
// non-main-thread
|
2016-01-07 00:18:29 +03:00
|
|
|
(!NS_IsMainThread() && aEventMessage) ||
|
2013-08-16 14:06:24 +04:00
|
|
|
aAllEvents, "Missing type"); // all-events listener
|
2011-08-18 13:45:00 +04:00
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
if (!aListenerHolder || mClearingListeners) {
|
2011-08-18 13:45:00 +04:00
|
|
|
return;
|
|
|
|
}
|
2001-04-23 09:33:07 +04:00
|
|
|
|
2013-04-17 01:16:08 +04:00
|
|
|
// Since there is no public API to call us with an EventListenerHolder, we
|
|
|
|
// know that there's an EventListenerHolder on the stack holding a strong ref
|
|
|
|
// to the listener.
|
2006-09-10 15:53:55 +04:00
|
|
|
|
2014-03-17 10:56:51 +04:00
|
|
|
Listener* listener;
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t count = mListeners.Length();
|
|
|
|
for (uint32_t i = 0; i < count; i++) {
|
2014-03-17 10:56:51 +04:00
|
|
|
listener = &mListeners.ElementAt(i);
|
2014-03-17 10:56:53 +04:00
|
|
|
// mListener == aListenerHolder is the last one, since it can be a bit slow.
|
2014-03-17 10:56:51 +04:00
|
|
|
if (listener->mListenerIsHandler == aHandler &&
|
2016-05-12 21:50:22 +03:00
|
|
|
listener->mFlags.EqualsForAddition(aFlags) &&
|
2015-08-26 15:56:59 +03:00
|
|
|
EVENT_TYPE_EQUALS(listener, aEventMessage, aTypeAtom, aTypeString,
|
2014-03-17 10:56:51 +04:00
|
|
|
aAllEvents) &&
|
2014-03-17 10:56:53 +04:00
|
|
|
listener->mListener == aListenerHolder) {
|
2011-08-18 13:45:00 +04:00
|
|
|
return;
|
1999-03-29 02:22:54 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-29 02:58:26 +03:00
|
|
|
mNoListenerForEvent = eVoidEvent;
|
2012-07-30 18:20:58 +04:00
|
|
|
mNoListenerForEventAtom = nullptr;
|
2006-10-06 09:24:02 +04:00
|
|
|
|
2014-03-17 10:56:51 +04:00
|
|
|
listener = aAllEvents ? mListeners.InsertElementAt(0) :
|
|
|
|
mListeners.AppendElement();
|
2014-03-17 10:56:53 +04:00
|
|
|
listener->mListener = aListenerHolder;
|
2015-08-26 15:56:59 +03:00
|
|
|
listener->mEventMessage = aEventMessage;
|
2014-03-17 10:56:51 +04:00
|
|
|
listener->mTypeString = aTypeString;
|
|
|
|
listener->mTypeAtom = aTypeAtom;
|
|
|
|
listener->mFlags = aFlags;
|
|
|
|
listener->mListenerIsHandler = aHandler;
|
|
|
|
listener->mHandlerIsString = false;
|
|
|
|
listener->mAllEvents = aAllEvents;
|
2016-05-04 06:29:14 +03:00
|
|
|
listener->mIsChrome = mIsMainThreadELM &&
|
|
|
|
nsContentUtils::LegacyIsCallerChromeOrNativeCode();
|
2011-06-24 06:18:02 +04:00
|
|
|
|
2012-06-29 01:47:56 +04:00
|
|
|
// Detect the type of event listener.
|
|
|
|
nsCOMPtr<nsIXPConnectWrappedJS> wjs;
|
2012-12-16 05:26:05 +04:00
|
|
|
if (aFlags.mListenerIsJSListener) {
|
2014-03-17 10:56:53 +04:00
|
|
|
MOZ_ASSERT(!aListenerHolder.HasWebIDLCallback());
|
2014-03-17 10:56:51 +04:00
|
|
|
listener->mListenerType = Listener::eJSEventListener;
|
2014-03-17 10:56:53 +04:00
|
|
|
} else if (aListenerHolder.HasWebIDLCallback()) {
|
2014-03-17 10:56:51 +04:00
|
|
|
listener->mListenerType = Listener::eWebIDLListener;
|
2014-03-17 10:56:53 +04:00
|
|
|
} else if ((wjs = do_QueryInterface(aListenerHolder.GetXPCOMCallback()))) {
|
2014-03-17 10:56:51 +04:00
|
|
|
listener->mListenerType = Listener::eWrappedJSListener;
|
2012-06-29 01:47:56 +04:00
|
|
|
} else {
|
2014-03-17 10:56:51 +04:00
|
|
|
listener->mListenerType = Listener::eNativeListener;
|
2012-01-26 18:45:12 +04:00
|
|
|
}
|
2012-06-29 01:47:56 +04:00
|
|
|
|
|
|
|
|
2012-12-16 05:26:05 +04:00
|
|
|
if (aFlags.mInSystemGroup) {
|
2011-10-17 18:59:28 +04:00
|
|
|
mMayHaveSystemGroupListeners = true;
|
2011-06-24 06:18:02 +04:00
|
|
|
}
|
2012-12-16 05:26:05 +04:00
|
|
|
if (aFlags.mCapture) {
|
2011-10-17 18:59:28 +04:00
|
|
|
mMayHaveCapturingListeners = true;
|
2009-10-24 19:52:29 +04:00
|
|
|
}
|
2006-10-06 09:24:02 +04:00
|
|
|
|
2015-09-10 04:40:06 +03:00
|
|
|
if (aEventMessage == eAfterPaint) {
|
2011-10-17 18:59:28 +04:00
|
|
|
mMayHavePaintEventListener = true;
|
2016-01-30 20:05:36 +03:00
|
|
|
if (nsPIDOMWindowInner* window = GetInnerWindowForTarget()) {
|
2008-10-16 01:24:19 +04:00
|
|
|
window->SetHasPaintEventListeners();
|
2008-10-16 01:06:32 +04:00
|
|
|
}
|
2015-09-07 17:55:50 +03:00
|
|
|
} else if (aEventMessage >= eLegacyMutationEventFirst &&
|
2015-09-07 17:55:51 +03:00
|
|
|
aEventMessage <= eLegacyMutationEventLast) {
|
2008-10-16 01:06:32 +04:00
|
|
|
// For mutation listeners, we need to update the global bit on the DOM window.
|
|
|
|
// Otherwise we won't actually fire the mutation event.
|
2011-10-17 18:59:28 +04:00
|
|
|
mMayHaveMutationListeners = true;
|
2006-10-06 09:24:02 +04:00
|
|
|
// Go from our target to the nearest enclosing DOM window.
|
2016-01-30 20:05:36 +03:00
|
|
|
if (nsPIDOMWindowInner* window = GetInnerWindowForTarget()) {
|
2013-04-24 08:22:37 +04:00
|
|
|
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
|
2012-05-23 14:45:14 +04:00
|
|
|
if (doc) {
|
|
|
|
doc->WarnOnceAbout(nsIDocument::eMutationEvent);
|
|
|
|
}
|
2015-09-07 17:55:51 +03:00
|
|
|
// If aEventMessage is eLegacySubtreeModified, we need to listen all
|
2008-04-12 02:44:48 +04:00
|
|
|
// mutations. nsContentUtils::HasMutationListeners relies on this.
|
2015-08-26 15:56:59 +03:00
|
|
|
window->SetMutationListeners(
|
2015-09-07 17:55:51 +03:00
|
|
|
(aEventMessage == eLegacySubtreeModified) ?
|
2015-08-26 15:56:59 +03:00
|
|
|
kAllMutationBits : MutationBitForEventType(aEventMessage));
|
2006-10-06 09:24:02 +04:00
|
|
|
}
|
2012-03-25 04:29:49 +04:00
|
|
|
} else if (aTypeAtom == nsGkAtoms::ondeviceorientation) {
|
2015-09-11 19:19:28 +03:00
|
|
|
EnableDevice(eDeviceOrientation);
|
2015-12-18 01:14:51 +03:00
|
|
|
} else if (aTypeAtom == nsGkAtoms::onabsolutedeviceorientation) {
|
|
|
|
EnableDevice(eAbsoluteDeviceOrientation);
|
2012-05-17 00:27:54 +04:00
|
|
|
} else if (aTypeAtom == nsGkAtoms::ondeviceproximity || aTypeAtom == nsGkAtoms::onuserproximity) {
|
2015-09-11 19:19:28 +03:00
|
|
|
EnableDevice(eDeviceProximity);
|
2012-05-02 20:43:45 +04:00
|
|
|
} else if (aTypeAtom == nsGkAtoms::ondevicelight) {
|
2015-09-11 19:19:29 +03:00
|
|
|
EnableDevice(eDeviceLight);
|
2012-03-25 04:29:49 +04:00
|
|
|
} else if (aTypeAtom == nsGkAtoms::ondevicemotion) {
|
2015-09-11 19:19:28 +03:00
|
|
|
EnableDevice(eDeviceMotion);
|
2015-10-24 07:37:28 +03:00
|
|
|
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
|
|
|
|
} else if (aTypeAtom == nsGkAtoms::onorientationchange) {
|
|
|
|
EnableDevice(eOrientationChange);
|
|
|
|
#endif
|
2012-11-07 22:10:40 +04:00
|
|
|
#ifdef MOZ_B2G
|
2012-09-11 10:05:00 +04:00
|
|
|
} else if (aTypeAtom == nsGkAtoms::onmoztimechange) {
|
2016-01-30 20:05:36 +03:00
|
|
|
if (nsCOMPtr<nsPIDOMWindowInner> window = GetTargetAsInnerWindow()) {
|
2012-10-01 13:43:53 +04:00
|
|
|
window->EnableTimeChangeNotifications();
|
|
|
|
}
|
2012-09-30 17:47:48 +04:00
|
|
|
} else if (aTypeAtom == nsGkAtoms::onmoznetworkupload) {
|
2016-01-30 20:05:36 +03:00
|
|
|
if (nsCOMPtr<nsPIDOMWindowInner> window = GetTargetAsInnerWindow()) {
|
2015-09-11 19:19:26 +03:00
|
|
|
window->EnableNetworkEvent(eNetworkUpload);
|
2012-09-30 17:47:48 +04:00
|
|
|
}
|
|
|
|
} else if (aTypeAtom == nsGkAtoms::onmoznetworkdownload) {
|
2016-01-30 20:05:36 +03:00
|
|
|
if (nsCOMPtr<nsPIDOMWindowInner> window = GetTargetAsInnerWindow()) {
|
2015-09-11 19:19:26 +03:00
|
|
|
window->EnableNetworkEvent(eNetworkDownload);
|
2012-09-30 17:47:48 +04:00
|
|
|
}
|
2012-11-07 22:10:40 +04:00
|
|
|
#endif // MOZ_B2G
|
2015-04-03 03:45:50 +03:00
|
|
|
} else if (aTypeAtom == nsGkAtoms::ontouchstart ||
|
|
|
|
aTypeAtom == nsGkAtoms::ontouchend ||
|
|
|
|
aTypeAtom == nsGkAtoms::ontouchmove ||
|
|
|
|
aTypeAtom == nsGkAtoms::ontouchcancel) {
|
|
|
|
mMayHaveTouchEventListener = true;
|
2016-01-30 20:05:36 +03:00
|
|
|
nsPIDOMWindowInner* window = GetInnerWindowForTarget();
|
2015-04-03 03:45:50 +03:00
|
|
|
// we don't want touchevent listeners added by scrollbars to flip this flag
|
|
|
|
// so we ignore listeners created with system event flag
|
|
|
|
if (window && !aFlags.mInSystemGroup) {
|
|
|
|
window->SetHasTouchEventListeners();
|
|
|
|
}
|
2015-08-31 18:20:05 +03:00
|
|
|
} else if (aEventMessage >= ePointerEventFirst &&
|
|
|
|
aEventMessage <= ePointerEventLast) {
|
2016-01-30 20:05:36 +03:00
|
|
|
nsPIDOMWindowInner* window = GetInnerWindowForTarget();
|
2014-02-11 10:33:29 +04:00
|
|
|
if (aTypeAtom == nsGkAtoms::onpointerenter ||
|
|
|
|
aTypeAtom == nsGkAtoms::onpointerleave) {
|
|
|
|
mMayHavePointerEnterLeaveEventListener = true;
|
|
|
|
if (window) {
|
|
|
|
#ifdef DEBUG
|
|
|
|
nsCOMPtr<nsIDocument> d = window->GetExtantDoc();
|
|
|
|
NS_WARN_IF_FALSE(!nsContentUtils::IsChromeDoc(d),
|
|
|
|
"Please do not use pointerenter/leave events in chrome. "
|
|
|
|
"They are slower than pointerover/out!");
|
|
|
|
#endif
|
|
|
|
window->SetHasPointerEnterLeaveEventListeners();
|
|
|
|
}
|
|
|
|
}
|
2011-09-18 11:45:14 +04:00
|
|
|
} else if (aTypeAtom == nsGkAtoms::onmouseenter ||
|
|
|
|
aTypeAtom == nsGkAtoms::onmouseleave) {
|
2011-10-17 18:59:28 +04:00
|
|
|
mMayHaveMouseEnterLeaveEventListener = true;
|
2016-01-30 20:05:36 +03:00
|
|
|
if (nsPIDOMWindowInner* window = GetInnerWindowForTarget()) {
|
2011-09-18 11:45:14 +04:00
|
|
|
#ifdef DEBUG
|
2013-04-24 08:22:37 +04:00
|
|
|
nsCOMPtr<nsIDocument> d = window->GetExtantDoc();
|
2011-09-18 11:45:14 +04:00
|
|
|
NS_WARN_IF_FALSE(!nsContentUtils::IsChromeDoc(d),
|
|
|
|
"Please do not use mouseenter/leave events in chrome. "
|
|
|
|
"They are slower than mouseover/out!");
|
|
|
|
#endif
|
|
|
|
window->SetHasMouseEnterLeaveEventListeners();
|
|
|
|
}
|
2011-08-03 22:12:08 +04:00
|
|
|
#ifdef MOZ_GAMEPAD
|
2015-09-11 15:21:28 +03:00
|
|
|
} else if (aEventMessage >= eGamepadEventFirst &&
|
2015-09-11 15:21:28 +03:00
|
|
|
aEventMessage <= eGamepadEventLast) {
|
2016-01-30 20:05:36 +03:00
|
|
|
if (nsPIDOMWindowInner* window = GetInnerWindowForTarget()) {
|
2011-08-03 22:12:08 +04:00
|
|
|
window->SetHasGamepadEventListener();
|
|
|
|
}
|
|
|
|
#endif
|
2015-06-17 02:02:39 +03:00
|
|
|
} else if (aTypeAtom == nsGkAtoms::onkeydown ||
|
|
|
|
aTypeAtom == nsGkAtoms::onkeypress ||
|
|
|
|
aTypeAtom == nsGkAtoms::onkeyup) {
|
|
|
|
if (!aFlags.mInSystemGroup) {
|
|
|
|
mMayHaveKeyEventListener = true;
|
|
|
|
}
|
|
|
|
} else if (aTypeAtom == nsGkAtoms::oncompositionend ||
|
|
|
|
aTypeAtom == nsGkAtoms::oncompositionstart ||
|
|
|
|
aTypeAtom == nsGkAtoms::oncompositionupdate ||
|
|
|
|
aTypeAtom == nsGkAtoms::oninput) {
|
|
|
|
if (!aFlags.mInSystemGroup) {
|
|
|
|
mMayHaveInputOrCompositionEventListener = true;
|
|
|
|
}
|
1999-03-29 02:22:54 +04:00
|
|
|
}
|
2015-06-17 02:02:39 +03:00
|
|
|
|
2016-05-12 21:50:58 +03:00
|
|
|
if (IsApzAwareListener(listener)) {
|
2016-02-11 02:47:59 +03:00
|
|
|
ProcessApzAwareEventListenerAdd();
|
2015-09-17 13:16:20 +03:00
|
|
|
}
|
|
|
|
|
2013-05-23 15:41:00 +04:00
|
|
|
if (aTypeAtom && mTarget) {
|
|
|
|
mTarget->EventListenerAdded(aTypeAtom);
|
|
|
|
}
|
2015-04-28 23:10:05 +03:00
|
|
|
|
|
|
|
if (mIsMainThreadELM && mTarget) {
|
2015-07-17 18:07:37 +03:00
|
|
|
EventListenerService::NotifyAboutMainThreadListenerChange(mTarget,
|
|
|
|
aTypeAtom);
|
2015-04-28 23:10:05 +03:00
|
|
|
}
|
1998-06-07 11:55:55 +04:00
|
|
|
}
|
1999-03-29 02:22:54 +04:00
|
|
|
|
2016-02-11 02:47:59 +03:00
|
|
|
void
|
|
|
|
EventListenerManager::ProcessApzAwareEventListenerAdd()
|
|
|
|
{
|
|
|
|
// Mark the node as having apz aware listeners
|
|
|
|
nsCOMPtr<nsINode> node = do_QueryInterface(mTarget);
|
|
|
|
if (node) {
|
|
|
|
node->SetMayHaveApzAwareListeners();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Schedule a paint so event regions on the layer tree gets updated
|
|
|
|
nsIDocument* doc = nullptr;
|
|
|
|
if (node) {
|
|
|
|
doc = node->OwnerDoc();
|
|
|
|
}
|
|
|
|
if (!doc) {
|
|
|
|
if (nsCOMPtr<nsPIDOMWindowInner> window = GetTargetAsInnerWindow()) {
|
|
|
|
doc = window->GetExtantDoc();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!doc) {
|
|
|
|
if (nsCOMPtr<DOMEventTargetHelper> helper = do_QueryInterface(mTarget)) {
|
|
|
|
if (nsPIDOMWindowInner* window = helper->GetOwner()) {
|
|
|
|
doc = window->GetExtantDoc();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-04 00:52:09 +03:00
|
|
|
if (doc && nsDisplayListBuilder::LayerEventRegionsEnabled()) {
|
2016-02-11 02:47:59 +03:00
|
|
|
nsIPresShell* ps = doc->GetShell();
|
|
|
|
if (ps) {
|
|
|
|
nsIFrame* f = ps->GetRootFrame();
|
|
|
|
if (f) {
|
|
|
|
f->SchedulePaint();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-29 21:23:27 +04:00
|
|
|
bool
|
2015-08-26 15:56:59 +03:00
|
|
|
EventListenerManager::IsDeviceType(EventMessage aEventMessage)
|
2012-03-29 21:23:27 +04:00
|
|
|
{
|
2015-08-26 15:56:59 +03:00
|
|
|
switch (aEventMessage) {
|
2015-09-11 19:19:28 +03:00
|
|
|
case eDeviceOrientation:
|
2015-12-18 01:14:51 +03:00
|
|
|
case eAbsoluteDeviceOrientation:
|
2015-09-11 19:19:28 +03:00
|
|
|
case eDeviceMotion:
|
2015-09-11 19:19:29 +03:00
|
|
|
case eDeviceLight:
|
2015-09-11 19:19:28 +03:00
|
|
|
case eDeviceProximity:
|
2015-09-11 19:19:28 +03:00
|
|
|
case eUserProximity:
|
2015-10-24 07:37:28 +03:00
|
|
|
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
|
|
|
|
case eOrientationChange:
|
|
|
|
#endif
|
2012-03-29 21:23:27 +04:00
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-04-04 20:26:12 +04:00
|
|
|
void
|
2015-08-26 15:56:59 +03:00
|
|
|
EventListenerManager::EnableDevice(EventMessage aEventMessage)
|
2012-04-04 20:26:12 +04:00
|
|
|
{
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowInner> window = GetTargetAsInnerWindow();
|
2012-04-04 20:26:12 +04:00
|
|
|
if (!window) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-08-26 15:56:59 +03:00
|
|
|
switch (aEventMessage) {
|
2015-09-11 19:19:28 +03:00
|
|
|
case eDeviceOrientation:
|
2015-12-15 04:03:56 +03:00
|
|
|
#ifdef MOZ_WIDGET_ANDROID
|
2015-12-17 23:49:44 +03:00
|
|
|
// Falls back to SENSOR_ROTATION_VECTOR and SENSOR_ORIENTATION if
|
|
|
|
// unavailable on device.
|
|
|
|
window->EnableDeviceSensor(SENSOR_GAME_ROTATION_VECTOR);
|
2015-12-15 04:03:56 +03:00
|
|
|
#else
|
2012-04-04 20:26:12 +04:00
|
|
|
window->EnableDeviceSensor(SENSOR_ORIENTATION);
|
2015-12-18 01:14:51 +03:00
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
case eAbsoluteDeviceOrientation:
|
|
|
|
#ifdef MOZ_WIDGET_ANDROID
|
|
|
|
// Falls back to SENSOR_ORIENTATION if unavailable on device.
|
|
|
|
window->EnableDeviceSensor(SENSOR_ROTATION_VECTOR);
|
|
|
|
#else
|
|
|
|
window->EnableDeviceSensor(SENSOR_ORIENTATION);
|
2015-12-15 04:03:56 +03:00
|
|
|
#endif
|
2012-04-04 20:26:12 +04:00
|
|
|
break;
|
2015-09-11 19:19:28 +03:00
|
|
|
case eDeviceProximity:
|
2015-09-11 19:19:28 +03:00
|
|
|
case eUserProximity:
|
2012-05-02 20:43:45 +04:00
|
|
|
window->EnableDeviceSensor(SENSOR_PROXIMITY);
|
|
|
|
break;
|
2015-09-11 19:19:29 +03:00
|
|
|
case eDeviceLight:
|
2012-05-02 20:43:45 +04:00
|
|
|
window->EnableDeviceSensor(SENSOR_LIGHT);
|
|
|
|
break;
|
2015-09-11 19:19:28 +03:00
|
|
|
case eDeviceMotion:
|
2012-04-04 20:26:12 +04:00
|
|
|
window->EnableDeviceSensor(SENSOR_ACCELERATION);
|
|
|
|
window->EnableDeviceSensor(SENSOR_LINEAR_ACCELERATION);
|
|
|
|
window->EnableDeviceSensor(SENSOR_GYROSCOPE);
|
|
|
|
break;
|
2015-10-24 07:37:28 +03:00
|
|
|
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
|
|
|
|
case eOrientationChange:
|
|
|
|
window->EnableOrientationChangeListener();
|
|
|
|
break;
|
|
|
|
#endif
|
2012-04-04 20:26:12 +04:00
|
|
|
default:
|
|
|
|
NS_WARNING("Enabling an unknown device sensor.");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-29 21:23:27 +04:00
|
|
|
void
|
2015-08-26 15:56:59 +03:00
|
|
|
EventListenerManager::DisableDevice(EventMessage aEventMessage)
|
2012-03-29 21:23:27 +04:00
|
|
|
{
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowInner> window = GetTargetAsInnerWindow();
|
2012-03-29 21:23:27 +04:00
|
|
|
if (!window) {
|
|
|
|
return;
|
|
|
|
}
|
2012-04-04 20:26:12 +04:00
|
|
|
|
2015-08-26 15:56:59 +03:00
|
|
|
switch (aEventMessage) {
|
2015-09-11 19:19:28 +03:00
|
|
|
case eDeviceOrientation:
|
2015-12-15 04:03:56 +03:00
|
|
|
#ifdef MOZ_WIDGET_ANDROID
|
2015-12-18 01:14:51 +03:00
|
|
|
// Disable all potential fallback sensors.
|
|
|
|
window->DisableDeviceSensor(SENSOR_GAME_ROTATION_VECTOR);
|
2015-12-15 04:03:56 +03:00
|
|
|
window->DisableDeviceSensor(SENSOR_ROTATION_VECTOR);
|
2015-12-18 01:14:51 +03:00
|
|
|
#endif
|
2012-03-29 21:23:27 +04:00
|
|
|
window->DisableDeviceSensor(SENSOR_ORIENTATION);
|
2015-12-18 01:14:51 +03:00
|
|
|
break;
|
|
|
|
case eAbsoluteDeviceOrientation:
|
|
|
|
#ifdef MOZ_WIDGET_ANDROID
|
|
|
|
window->DisableDeviceSensor(SENSOR_ROTATION_VECTOR);
|
2015-12-15 04:03:56 +03:00
|
|
|
#endif
|
2015-12-18 01:14:51 +03:00
|
|
|
window->DisableDeviceSensor(SENSOR_ORIENTATION);
|
2012-03-29 21:23:27 +04:00
|
|
|
break;
|
2015-09-11 19:19:28 +03:00
|
|
|
case eDeviceMotion:
|
2012-03-29 21:23:27 +04:00
|
|
|
window->DisableDeviceSensor(SENSOR_ACCELERATION);
|
|
|
|
window->DisableDeviceSensor(SENSOR_LINEAR_ACCELERATION);
|
|
|
|
window->DisableDeviceSensor(SENSOR_GYROSCOPE);
|
|
|
|
break;
|
2015-09-11 19:19:28 +03:00
|
|
|
case eDeviceProximity:
|
2015-09-11 19:19:28 +03:00
|
|
|
case eUserProximity:
|
2012-05-02 20:43:45 +04:00
|
|
|
window->DisableDeviceSensor(SENSOR_PROXIMITY);
|
|
|
|
break;
|
2015-09-11 19:19:29 +03:00
|
|
|
case eDeviceLight:
|
2012-05-02 20:43:45 +04:00
|
|
|
window->DisableDeviceSensor(SENSOR_LIGHT);
|
|
|
|
break;
|
2015-10-24 07:37:28 +03:00
|
|
|
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
|
|
|
|
case eOrientationChange:
|
|
|
|
window->DisableOrientationChangeListener();
|
|
|
|
break;
|
|
|
|
#endif
|
2012-03-29 21:23:27 +04:00
|
|
|
default:
|
|
|
|
NS_WARNING("Disabling an unknown device sensor.");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-24 06:18:02 +04:00
|
|
|
void
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::RemoveEventListenerInternal(
|
2014-03-17 10:56:53 +04:00
|
|
|
const EventListenerHolder& aListenerHolder,
|
2015-08-26 15:56:59 +03:00
|
|
|
EventMessage aEventMessage,
|
2014-03-17 10:56:53 +04:00
|
|
|
nsIAtom* aUserType,
|
|
|
|
const nsAString& aTypeString,
|
|
|
|
const EventListenerFlags& aFlags,
|
|
|
|
bool aAllEvents)
|
1999-03-29 02:22:54 +04:00
|
|
|
{
|
2015-08-26 15:56:59 +03:00
|
|
|
if (!aListenerHolder || !aEventMessage || mClearingListeners) {
|
2011-06-24 06:18:02 +04:00
|
|
|
return;
|
2006-09-09 21:28:57 +04:00
|
|
|
}
|
|
|
|
|
2014-03-17 10:56:51 +04:00
|
|
|
Listener* listener;
|
1999-03-29 02:22:54 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t count = mListeners.Length();
|
|
|
|
uint32_t typeCount = 0;
|
2015-08-26 15:56:59 +03:00
|
|
|
bool deviceType = IsDeviceType(aEventMessage);
|
2012-11-07 22:10:40 +04:00
|
|
|
#ifdef MOZ_B2G
|
2015-09-11 19:19:25 +03:00
|
|
|
bool timeChangeEvent = (aEventMessage == eTimeChange);
|
2015-09-11 19:19:26 +03:00
|
|
|
bool networkEvent = (aEventMessage == eNetworkUpload ||
|
2015-09-11 19:19:26 +03:00
|
|
|
aEventMessage == eNetworkDownload);
|
2012-11-07 22:10:40 +04:00
|
|
|
#endif // MOZ_B2G
|
2012-03-29 21:23:27 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
2014-03-17 10:56:51 +04:00
|
|
|
listener = &mListeners.ElementAt(i);
|
2015-08-26 15:56:59 +03:00
|
|
|
if (EVENT_TYPE_EQUALS(listener, aEventMessage, aUserType, aTypeString,
|
2014-03-17 10:56:51 +04:00
|
|
|
aAllEvents)) {
|
2012-03-29 21:23:27 +04:00
|
|
|
++typeCount;
|
2014-03-17 10:56:53 +04:00
|
|
|
if (listener->mListener == aListenerHolder &&
|
2016-05-12 21:50:22 +03:00
|
|
|
listener->mFlags.EqualsForRemoval(aFlags)) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<EventListenerManager> kungFuDeathGrip(this);
|
2012-03-29 21:23:27 +04:00
|
|
|
mListeners.RemoveElementAt(i);
|
|
|
|
--count;
|
2015-08-29 02:58:26 +03:00
|
|
|
mNoListenerForEvent = eVoidEvent;
|
2012-07-30 18:20:58 +04:00
|
|
|
mNoListenerForEventAtom = nullptr;
|
2013-05-23 15:41:00 +04:00
|
|
|
if (mTarget && aUserType) {
|
|
|
|
mTarget->EventListenerRemoved(aUserType);
|
|
|
|
}
|
2015-04-28 23:10:05 +03:00
|
|
|
if (mIsMainThreadELM && mTarget) {
|
2015-07-17 18:07:37 +03:00
|
|
|
EventListenerService::NotifyAboutMainThreadListenerChange(mTarget,
|
|
|
|
aUserType);
|
2015-04-28 23:10:05 +03:00
|
|
|
}
|
2012-03-29 21:23:27 +04:00
|
|
|
|
2012-11-07 22:10:40 +04:00
|
|
|
if (!deviceType
|
|
|
|
#ifdef MOZ_B2G
|
|
|
|
&& !timeChangeEvent && !networkEvent
|
|
|
|
#endif // MOZ_B2G
|
|
|
|
) {
|
2012-03-29 21:23:27 +04:00
|
|
|
return;
|
2012-03-25 04:29:49 +04:00
|
|
|
}
|
2012-03-29 21:23:27 +04:00
|
|
|
--typeCount;
|
2011-10-06 21:27:41 +04:00
|
|
|
}
|
1999-03-29 02:22:54 +04:00
|
|
|
}
|
|
|
|
}
|
2012-03-29 21:23:27 +04:00
|
|
|
|
2012-11-01 16:42:29 +04:00
|
|
|
if (!aAllEvents && deviceType && typeCount == 0) {
|
2015-08-26 15:56:59 +03:00
|
|
|
DisableDevice(aEventMessage);
|
2012-11-07 22:10:40 +04:00
|
|
|
#ifdef MOZ_B2G
|
2012-09-11 10:05:00 +04:00
|
|
|
} else if (timeChangeEvent && typeCount == 0) {
|
2016-01-30 20:05:36 +03:00
|
|
|
if (nsCOMPtr<nsPIDOMWindowInner> window = GetTargetAsInnerWindow()) {
|
2012-10-01 13:43:53 +04:00
|
|
|
window->DisableTimeChangeNotifications();
|
|
|
|
}
|
2012-11-01 16:42:29 +04:00
|
|
|
} else if (!aAllEvents && networkEvent && typeCount == 0) {
|
2016-01-30 20:05:36 +03:00
|
|
|
if (nsCOMPtr<nsPIDOMWindowInner> window = GetTargetAsInnerWindow()) {
|
2015-08-26 15:56:59 +03:00
|
|
|
window->DisableNetworkEvent(aEventMessage);
|
2012-09-30 17:47:48 +04:00
|
|
|
}
|
2012-11-07 22:10:40 +04:00
|
|
|
#endif // MOZ_B2G
|
2012-03-29 21:23:27 +04:00
|
|
|
}
|
1999-03-29 02:22:54 +04:00
|
|
|
}
|
|
|
|
|
2013-08-16 14:06:24 +04:00
|
|
|
bool
|
2016-02-02 21:03:49 +03:00
|
|
|
EventListenerManager::ListenerCanHandle(const Listener* aListener,
|
|
|
|
const WidgetEvent* aEvent,
|
|
|
|
EventMessage aEventMessage) const
|
|
|
|
|
2006-10-06 09:24:02 +04:00
|
|
|
{
|
2016-02-02 21:03:49 +03:00
|
|
|
MOZ_ASSERT(aEventMessage == aEvent->mMessage ||
|
|
|
|
aEventMessage == GetLegacyEventMessage(aEvent->mMessage),
|
|
|
|
"aEvent and aEventMessage should agree, modulo legacyness");
|
|
|
|
|
2011-08-08 22:26:26 +04:00
|
|
|
// This is slightly different from EVENT_TYPE_EQUALS in that it returns
|
2015-09-10 04:40:04 +03:00
|
|
|
// true even when aEvent->mMessage == eUnidentifiedEvent and
|
|
|
|
// aListener=>mEventMessage != eUnidentifiedEvent as long as the atoms are
|
2014-03-17 10:56:51 +04:00
|
|
|
// the same
|
|
|
|
if (aListener->mAllEvents) {
|
2013-08-16 14:06:24 +04:00
|
|
|
return true;
|
|
|
|
}
|
2015-09-10 04:40:04 +03:00
|
|
|
if (aEvent->mMessage == eUnidentifiedEvent) {
|
2013-08-16 14:06:24 +04:00
|
|
|
if (mIsMainThreadELM) {
|
2016-04-18 17:53:03 +03:00
|
|
|
return aListener->mTypeAtom == aEvent->mSpecifiedEventType;
|
2013-08-16 14:06:24 +04:00
|
|
|
}
|
2016-04-18 18:10:17 +03:00
|
|
|
return aListener->mTypeString.Equals(aEvent->mSpecifiedEventTypeString);
|
2013-08-16 14:06:24 +04:00
|
|
|
}
|
2016-05-04 06:29:14 +03:00
|
|
|
if (!nsContentUtils::IsUnprefixedFullscreenApiEnabled() &&
|
|
|
|
aEvent->IsTrusted() && (aEventMessage == eFullscreenChange ||
|
|
|
|
aEventMessage == eFullscreenError)) {
|
|
|
|
// If unprefixed Fullscreen API is not enabled, don't dispatch it
|
|
|
|
// to the content.
|
|
|
|
if (!aEvent->mFlags.mInSystemGroup && !aListener->mIsChrome) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2013-12-21 04:22:13 +04:00
|
|
|
MOZ_ASSERT(mIsMainThreadELM);
|
2016-02-02 21:03:49 +03:00
|
|
|
return aListener->mEventMessage == aEventMessage;
|
1999-03-29 02:22:54 +04:00
|
|
|
}
|
|
|
|
|
2011-08-18 13:45:00 +04:00
|
|
|
void
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::AddEventListenerByType(
|
2014-03-17 10:56:53 +04:00
|
|
|
const EventListenerHolder& aListenerHolder,
|
2014-03-17 10:56:53 +04:00
|
|
|
const nsAString& aType,
|
|
|
|
const EventListenerFlags& aFlags)
|
1999-03-29 02:22:54 +04:00
|
|
|
{
|
2016-05-20 12:15:05 +03:00
|
|
|
nsCOMPtr<nsIAtom> atom;
|
|
|
|
EventMessage message = mIsMainThreadELM ?
|
|
|
|
nsContentUtils::GetEventMessageAndAtomForListener(aType,
|
|
|
|
getter_AddRefs(atom)) :
|
|
|
|
eUnidentifiedEvent;
|
2015-08-26 15:56:59 +03:00
|
|
|
AddEventListenerInternal(aListenerHolder, message, atom, aType, aFlags);
|
1999-03-29 02:22:54 +04:00
|
|
|
}
|
|
|
|
|
2011-06-24 06:18:02 +04:00
|
|
|
void
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::RemoveEventListenerByType(
|
2014-03-17 10:56:53 +04:00
|
|
|
const EventListenerHolder& aListenerHolder,
|
2014-03-17 10:56:53 +04:00
|
|
|
const nsAString& aType,
|
|
|
|
const EventListenerFlags& aFlags)
|
1999-03-29 02:22:54 +04:00
|
|
|
{
|
2016-05-20 12:15:05 +03:00
|
|
|
nsCOMPtr<nsIAtom> atom;
|
|
|
|
EventMessage message = mIsMainThreadELM ?
|
|
|
|
nsContentUtils::GetEventMessageAndAtomForListener(aType,
|
|
|
|
getter_AddRefs(atom)) :
|
|
|
|
eUnidentifiedEvent;
|
2015-08-26 15:56:59 +03:00
|
|
|
RemoveEventListenerInternal(aListenerHolder, message, atom, aType, aFlags);
|
1999-03-29 02:22:54 +04:00
|
|
|
}
|
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::Listener*
|
2015-08-26 15:56:59 +03:00
|
|
|
EventListenerManager::FindEventHandler(EventMessage aEventMessage,
|
2014-03-17 10:56:53 +04:00
|
|
|
nsIAtom* aTypeAtom,
|
|
|
|
const nsAString& aTypeString)
|
1998-07-31 22:21:37 +04:00
|
|
|
{
|
2006-10-06 09:24:02 +04:00
|
|
|
// Run through the listeners for this type and see if a script
|
|
|
|
// listener is registered
|
2014-03-17 10:56:51 +04:00
|
|
|
Listener* listener;
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t count = mListeners.Length();
|
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
2014-03-17 10:56:51 +04:00
|
|
|
listener = &mListeners.ElementAt(i);
|
|
|
|
if (listener->mListenerIsHandler &&
|
2015-08-26 15:56:59 +03:00
|
|
|
EVENT_TYPE_EQUALS(listener, aEventMessage, aTypeAtom, aTypeString,
|
2014-03-17 10:56:51 +04:00
|
|
|
false)) {
|
|
|
|
return listener;
|
1998-07-31 22:21:37 +04:00
|
|
|
}
|
1999-11-25 03:05:21 +03:00
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
1999-11-25 03:05:21 +03:00
|
|
|
}
|
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::Listener*
|
|
|
|
EventListenerManager::SetEventHandlerInternal(
|
|
|
|
nsIAtom* aName,
|
|
|
|
const nsAString& aTypeString,
|
2014-04-02 06:00:45 +04:00
|
|
|
const TypedEventHandler& aTypedHandler,
|
2014-03-17 10:56:53 +04:00
|
|
|
bool aPermitUntrustedEvents)
|
1999-11-25 03:05:21 +03:00
|
|
|
{
|
2013-09-17 15:01:28 +04:00
|
|
|
MOZ_ASSERT(aName || !aTypeString.IsEmpty());
|
2012-08-31 07:45:16 +04:00
|
|
|
|
2015-08-26 15:56:59 +03:00
|
|
|
EventMessage eventMessage = nsContentUtils::GetEventMessage(aName);
|
|
|
|
Listener* listener = FindEventHandler(eventMessage, aName, aTypeString);
|
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
|
|
|
|
2014-03-17 10:56:51 +04:00
|
|
|
if (!listener) {
|
2005-04-29 03:48:28 +04:00
|
|
|
// If we didn't find a script listener or no listeners existed
|
|
|
|
// create and add a new one.
|
2012-12-16 05:26:05 +04:00
|
|
|
EventListenerFlags flags;
|
|
|
|
flags.mListenerIsJSListener = true;
|
2012-11-09 20:00:25 +04:00
|
|
|
|
2014-04-02 06:00:46 +04:00
|
|
|
nsCOMPtr<JSEventHandler> jsEventHandler;
|
2014-04-02 06:00:45 +04:00
|
|
|
NS_NewJSEventHandler(mTarget, aName,
|
2014-04-02 06:00:46 +04:00
|
|
|
aTypedHandler, getter_AddRefs(jsEventHandler));
|
|
|
|
EventListenerHolder listenerHolder(jsEventHandler);
|
2015-08-26 15:56:59 +03:00
|
|
|
AddEventListenerInternal(listenerHolder, eventMessage, aName, aTypeString,
|
2014-03-17 10:56:53 +04:00
|
|
|
flags, true);
|
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
|
|
|
|
2015-08-26 15:56:59 +03:00
|
|
|
listener = FindEventHandler(eventMessage, aName, aTypeString);
|
2011-08-24 23:49:25 +04:00
|
|
|
} else {
|
2014-04-02 06:00:46 +04:00
|
|
|
JSEventHandler* jsEventHandler = listener->GetJSEventHandler();
|
|
|
|
MOZ_ASSERT(jsEventHandler,
|
|
|
|
"How can we have an event handler with no JSEventHandler?");
|
2012-08-31 07:45:16 +04:00
|
|
|
|
2014-04-02 06:00:46 +04:00
|
|
|
bool same = jsEventHandler->GetTypedEventHandler() == aTypedHandler;
|
2013-05-24 21:22:20 +04:00
|
|
|
// Possibly the same listener, but update still the context and scope.
|
2014-04-02 06:00:46 +04:00
|
|
|
jsEventHandler->SetHandler(aTypedHandler);
|
2013-11-27 19:22:16 +04:00
|
|
|
if (mTarget && !same && aName) {
|
2013-05-24 21:22:20 +04:00
|
|
|
mTarget->EventListenerRemoved(aName);
|
|
|
|
mTarget->EventListenerAdded(aName);
|
|
|
|
}
|
2015-04-28 23:10:05 +03:00
|
|
|
if (mIsMainThreadELM && mTarget) {
|
2015-07-17 18:07:37 +03:00
|
|
|
EventListenerService::NotifyAboutMainThreadListenerChange(mTarget, aName);
|
2015-04-28 23:10:05 +03:00
|
|
|
}
|
1998-07-31 22:21:37 +04:00
|
|
|
}
|
1999-11-25 03:05:21 +03:00
|
|
|
|
2013-09-17 15:01:28 +04:00
|
|
|
// Set flag to indicate possible need for compilation later
|
2014-04-02 06:00:45 +04:00
|
|
|
listener->mHandlerIsString = !aTypedHandler.HasEventHandler();
|
2013-09-17 15:01:28 +04:00
|
|
|
if (aPermitUntrustedEvents) {
|
2014-03-17 10:56:51 +04:00
|
|
|
listener->mFlags.mAllowUntrustedEvents = true;
|
1999-11-25 03:05:21 +03:00
|
|
|
}
|
|
|
|
|
2014-03-17 10:56:51 +04:00
|
|
|
return listener;
|
1998-07-31 22:21:37 +04:00
|
|
|
}
|
|
|
|
|
2011-06-24 06:18:02 +04:00
|
|
|
nsresult
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::SetEventHandler(nsIAtom* aName,
|
|
|
|
const nsAString& aBody,
|
|
|
|
bool aDeferCompilation,
|
|
|
|
bool aPermitUntrustedEvents,
|
|
|
|
Element* aElement)
|
1998-07-31 22:21:37 +04:00
|
|
|
{
|
2004-06-16 17:18:47 +04:00
|
|
|
nsCOMPtr<nsIDocument> doc;
|
2013-11-27 13:12:41 +04:00
|
|
|
nsCOMPtr<nsIScriptGlobalObject> global =
|
|
|
|
GetScriptGlobalAndDocument(getter_AddRefs(doc));
|
2004-02-10 01:48:53 +03:00
|
|
|
|
2007-05-01 23:08:08 +04:00
|
|
|
if (!global) {
|
|
|
|
// This can happen; for example this document might have been
|
|
|
|
// loaded as data.
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2010-02-24 00:20:46 +03:00
|
|
|
|
2012-11-21 20:19:03 +04:00
|
|
|
#ifdef DEBUG
|
2016-01-30 20:05:36 +03:00
|
|
|
if (nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(global)) {
|
2012-11-21 20:19:03 +04:00
|
|
|
MOZ_ASSERT(win->IsInnerWindow(), "We should not have an outer window here!");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-04-14 16:04:12 +04:00
|
|
|
nsresult rv = NS_OK;
|
2010-02-24 00:20:46 +03:00
|
|
|
// return early preventing the event listener from being added
|
|
|
|
// 'doc' is fetched above
|
|
|
|
if (doc) {
|
2012-08-20 22:34:32 +04:00
|
|
|
// Don't allow adding an event listener if the document is sandboxed
|
|
|
|
// without 'allow-scripts'.
|
|
|
|
if (doc->GetSandboxFlags() & SANDBOXED_SCRIPTS) {
|
|
|
|
return NS_ERROR_DOM_SECURITY_ERR;
|
|
|
|
}
|
|
|
|
|
2015-09-18 08:34:34 +03:00
|
|
|
// Perform CSP check
|
2010-02-24 00:20:46 +03:00
|
|
|
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
|
|
|
rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
if (csp) {
|
2015-09-18 08:34:34 +03:00
|
|
|
// let's generate a script sample and pass it as aContent,
|
|
|
|
// it will not match the hash, but allows us to pass
|
|
|
|
// the script sample in aCOntent.
|
|
|
|
nsAutoString scriptSample, attr, tagName(NS_LITERAL_STRING("UNKNOWN"));
|
|
|
|
aName->ToString(attr);
|
|
|
|
nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mTarget));
|
|
|
|
if (domNode) {
|
|
|
|
domNode->GetNodeName(tagName);
|
2012-10-16 00:54:58 +04:00
|
|
|
}
|
2015-09-18 08:34:34 +03:00
|
|
|
// build a "script sample" based on what we know about this element
|
|
|
|
scriptSample.Assign(attr);
|
|
|
|
scriptSample.AppendLiteral(" attribute on ");
|
|
|
|
scriptSample.Append(tagName);
|
|
|
|
scriptSample.AppendLiteral(" element");
|
|
|
|
|
|
|
|
bool allowsInlineScript = true;
|
|
|
|
rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_SCRIPT,
|
|
|
|
EmptyString(), // aNonce
|
|
|
|
scriptSample,
|
|
|
|
0, // aLineNumber
|
|
|
|
&allowsInlineScript);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2012-10-16 00:54:58 +04:00
|
|
|
|
|
|
|
// return early if CSP wants us to block inline scripts
|
2015-09-18 08:34:34 +03:00
|
|
|
if (!allowsInlineScript) {
|
2010-02-24 00:20:46 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-05-01 23:08:08 +04:00
|
|
|
// This might be the first reference to this language in the global
|
|
|
|
// We must init the language before we attempt to fetch its context.
|
2012-03-23 21:13:29 +04:00
|
|
|
if (NS_FAILED(global->EnsureScriptEnvironment())) {
|
2007-05-01 23:08:08 +04:00
|
|
|
NS_WARNING("Failed to setup script environment for this language");
|
|
|
|
// but fall through and let the inevitable failure below handle it.
|
2006-06-13 07:07:47 +04:00
|
|
|
}
|
2005-07-31 00:57:07 +04:00
|
|
|
|
2012-03-23 21:13:29 +04:00
|
|
|
nsIScriptContext* context = global->GetScriptContext();
|
2007-05-01 23:08:08 +04:00
|
|
|
NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
|
2014-01-06 17:36:10 +04:00
|
|
|
NS_ENSURE_STATE(global->GetGlobalJSObject());
|
|
|
|
|
2014-03-22 06:31:03 +04:00
|
|
|
Listener* listener = SetEventHandlerInternal(aName,
|
2014-03-17 10:56:51 +04:00
|
|
|
EmptyString(),
|
2014-04-02 06:00:45 +04:00
|
|
|
TypedEventHandler(),
|
2014-03-17 10:56:51 +04:00
|
|
|
aPermitUntrustedEvents);
|
2009-03-15 06:42:50 +03:00
|
|
|
|
2011-08-24 23:49:25 +04:00
|
|
|
if (!aDeferCompilation) {
|
2014-03-17 10:56:51 +04:00
|
|
|
return CompileEventHandlerInternal(listener, &aBody, aElement);
|
1999-11-25 03:05:21 +03:00
|
|
|
}
|
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
|
|
|
return NS_OK;
|
1998-07-31 22:21:37 +04:00
|
|
|
}
|
|
|
|
|
2011-06-24 06:18:02 +04:00
|
|
|
void
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::RemoveEventHandler(nsIAtom* aName,
|
|
|
|
const nsAString& aTypeString)
|
2001-05-04 09:34:58 +04:00
|
|
|
{
|
2012-11-30 13:13:16 +04:00
|
|
|
if (mClearingListeners) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-08-26 15:56:59 +03:00
|
|
|
EventMessage eventMessage = nsContentUtils::GetEventMessage(aName);
|
|
|
|
Listener* listener = FindEventHandler(eventMessage, aName, aTypeString);
|
2001-05-04 09:34:58 +04:00
|
|
|
|
2014-03-17 10:56:51 +04:00
|
|
|
if (listener) {
|
|
|
|
mListeners.RemoveElementAt(uint32_t(listener - &mListeners.ElementAt(0)));
|
2015-08-29 02:58:26 +03:00
|
|
|
mNoListenerForEvent = eVoidEvent;
|
2012-07-30 18:20:58 +04:00
|
|
|
mNoListenerForEventAtom = nullptr;
|
2013-12-04 22:17:53 +04:00
|
|
|
if (mTarget && aName) {
|
2013-05-23 15:41:00 +04:00
|
|
|
mTarget->EventListenerRemoved(aName);
|
|
|
|
}
|
2015-04-28 23:10:05 +03:00
|
|
|
if (mIsMainThreadELM && mTarget) {
|
2015-07-17 18:07:37 +03:00
|
|
|
EventListenerService::NotifyAboutMainThreadListenerChange(mTarget, aName);
|
2015-04-28 23:10:05 +03:00
|
|
|
}
|
2001-05-04 09:34:58 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-03-13 14:37:16 +03:00
|
|
|
nsresult
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::CompileEventHandlerInternal(Listener* aListener,
|
|
|
|
const nsAString* aBody,
|
|
|
|
Element* aElement)
|
2001-03-13 14:37:16 +03:00
|
|
|
{
|
2014-04-02 06:00:46 +04:00
|
|
|
MOZ_ASSERT(aListener->GetJSEventHandler());
|
2014-03-22 06:31:02 +04:00
|
|
|
MOZ_ASSERT(aListener->mHandlerIsString, "Why are we compiling a non-string JS listener?");
|
2014-04-02 06:00:46 +04:00
|
|
|
JSEventHandler* jsEventHandler = aListener->GetJSEventHandler();
|
|
|
|
MOZ_ASSERT(!jsEventHandler->GetTypedEventHandler().HasEventHandler(),
|
2014-04-02 06:00:45 +04:00
|
|
|
"What is there to compile?");
|
2011-08-24 23:49:25 +04:00
|
|
|
|
2014-03-22 06:31:02 +04:00
|
|
|
nsresult result = NS_OK;
|
2013-11-27 13:12:41 +04:00
|
|
|
nsCOMPtr<nsIDocument> doc;
|
|
|
|
nsCOMPtr<nsIScriptGlobalObject> global =
|
|
|
|
GetScriptGlobalAndDocument(getter_AddRefs(doc));
|
|
|
|
NS_ENSURE_STATE(global);
|
|
|
|
|
2014-04-15 07:26:59 +04:00
|
|
|
// Activate JSAPI, and make sure that exceptions are reported on the right
|
|
|
|
// Window.
|
2014-06-19 11:21:14 +04:00
|
|
|
AutoJSAPI jsapi;
|
2014-09-29 17:34:21 +04:00
|
|
|
if (NS_WARN_IF(!jsapi.Init(global))) {
|
2014-06-19 11:21:14 +04:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
2014-04-15 07:26:59 +04:00
|
|
|
JSContext* cx = jsapi.cx();
|
2013-11-26 20:47:52 +04:00
|
|
|
|
2014-03-17 10:56:51 +04:00
|
|
|
nsCOMPtr<nsIAtom> typeAtom = aListener->mTypeAtom;
|
2014-03-05 17:16:42 +04:00
|
|
|
nsIAtom* attrName = typeAtom;
|
2013-11-26 20:47:52 +04:00
|
|
|
|
2014-03-22 06:31:02 +04:00
|
|
|
// Flag us as not a string so we don't keep trying to compile strings which
|
|
|
|
// can't be compiled.
|
2014-03-22 06:31:02 +04:00
|
|
|
aListener->mHandlerIsString = false;
|
|
|
|
|
|
|
|
// mTarget may not be an Element if it's a window and we're
|
|
|
|
// getting an inline event listener forwarded from <html:body> or
|
|
|
|
// <html:frameset> or <xul:window> or the like.
|
|
|
|
// XXX I don't like that we have to reference content from
|
|
|
|
// here. The alternative is to store the event handler string on
|
2014-04-02 06:00:46 +04:00
|
|
|
// the JSEventHandler itself, and that still doesn't address
|
2014-03-22 06:31:02 +04:00
|
|
|
// the arg names issue.
|
|
|
|
nsCOMPtr<Element> element = do_QueryInterface(mTarget);
|
|
|
|
MOZ_ASSERT(element || aBody, "Where will we get our body?");
|
|
|
|
nsAutoString handlerBody;
|
|
|
|
const nsAString* body = aBody;
|
|
|
|
if (!aBody) {
|
|
|
|
if (aListener->mTypeAtom == nsGkAtoms::onSVGLoad) {
|
|
|
|
attrName = nsGkAtoms::onload;
|
|
|
|
} else if (aListener->mTypeAtom == nsGkAtoms::onSVGUnload) {
|
|
|
|
attrName = nsGkAtoms::onunload;
|
|
|
|
} else if (aListener->mTypeAtom == nsGkAtoms::onSVGResize) {
|
|
|
|
attrName = nsGkAtoms::onresize;
|
|
|
|
} else if (aListener->mTypeAtom == nsGkAtoms::onSVGScroll) {
|
|
|
|
attrName = nsGkAtoms::onscroll;
|
|
|
|
} else if (aListener->mTypeAtom == nsGkAtoms::onSVGZoom) {
|
|
|
|
attrName = nsGkAtoms::onzoom;
|
|
|
|
} else if (aListener->mTypeAtom == nsGkAtoms::onbeginEvent) {
|
|
|
|
attrName = nsGkAtoms::onbegin;
|
|
|
|
} else if (aListener->mTypeAtom == nsGkAtoms::onrepeatEvent) {
|
|
|
|
attrName = nsGkAtoms::onrepeat;
|
|
|
|
} else if (aListener->mTypeAtom == nsGkAtoms::onendEvent) {
|
|
|
|
attrName = nsGkAtoms::onend;
|
2011-08-24 23:49:25 +04:00
|
|
|
}
|
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
|
|
|
|
2014-03-22 06:31:02 +04:00
|
|
|
element->GetAttr(kNameSpaceID_None, attrName, handlerBody);
|
|
|
|
body = &handlerBody;
|
|
|
|
aElement = element;
|
|
|
|
}
|
|
|
|
aListener = nullptr;
|
|
|
|
|
|
|
|
uint32_t lineNo = 0;
|
|
|
|
nsAutoCString url (NS_LITERAL_CSTRING("-moz-evil:lying-event-listener"));
|
|
|
|
MOZ_ASSERT(body);
|
|
|
|
MOZ_ASSERT(aElement);
|
|
|
|
nsIURI *uri = aElement->OwnerDoc()->GetDocumentURI();
|
|
|
|
if (uri) {
|
|
|
|
uri->GetSpec(url);
|
|
|
|
lineNo = 1;
|
|
|
|
}
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(mTarget);
|
2014-03-22 06:31:02 +04:00
|
|
|
uint32_t argCount;
|
|
|
|
const char **argNames;
|
|
|
|
nsContentUtils::GetEventArgNames(aElement->GetNameSpaceID(),
|
2014-05-09 06:20:54 +04:00
|
|
|
typeAtom, win,
|
2014-03-22 06:31:02 +04:00
|
|
|
&argCount, &argNames);
|
|
|
|
|
2014-06-21 22:55:15 +04:00
|
|
|
JSAddonId *addonId = MapURIToAddonID(uri);
|
|
|
|
|
2014-03-22 06:31:02 +04:00
|
|
|
// Wrap the event target, so that we can use it as the scope for the event
|
|
|
|
// handler. Note that mTarget is different from aElement in the <body> case,
|
|
|
|
// where mTarget is a Window.
|
|
|
|
//
|
|
|
|
// The wrapScope doesn't really matter here, because the target will create
|
|
|
|
// its reflector in the proper scope, and then we'll enter that compartment.
|
2014-06-19 11:21:14 +04:00
|
|
|
JS::Rooted<JSObject*> wrapScope(cx, global->GetGlobalJSObject());
|
2014-03-22 06:31:02 +04:00
|
|
|
JS::Rooted<JS::Value> v(cx);
|
|
|
|
{
|
|
|
|
JSAutoCompartment ac(cx, wrapScope);
|
2014-04-10 08:58:41 +04:00
|
|
|
nsresult rv = nsContentUtils::WrapNative(cx, mTarget, &v,
|
2014-03-22 06:31:02 +04:00
|
|
|
/* aAllowWrapping = */ false);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
2014-10-25 08:50:29 +04:00
|
|
|
|
2014-06-21 22:55:15 +04:00
|
|
|
if (addonId) {
|
|
|
|
JS::Rooted<JSObject*> vObj(cx, &v.toObject());
|
|
|
|
JS::Rooted<JSObject*> addonScope(cx, xpc::GetAddonScope(cx, vObj, addonId));
|
|
|
|
if (!addonScope) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
JSAutoCompartment ac(cx, addonScope);
|
2014-10-25 08:50:29 +04:00
|
|
|
|
2014-10-31 00:40:13 +03:00
|
|
|
// Wrap our event target into the addon scope, since that's where we want to
|
|
|
|
// do all our work.
|
2014-06-21 22:55:15 +04:00
|
|
|
if (!JS_WrapValue(cx, &v)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
2014-03-22 06:31:02 +04:00
|
|
|
JS::Rooted<JSObject*> target(cx, &v.toObject());
|
|
|
|
JSAutoCompartment ac(cx, target);
|
|
|
|
|
2014-10-31 00:40:13 +03:00
|
|
|
// Now that we've entered the compartment we actually care about, create our
|
|
|
|
// scope chain. Note that we start with |element|, not aElement, because
|
|
|
|
// mTarget is different from aElement in the <body> case, where mTarget is a
|
|
|
|
// Window, and in that case we do not want the scope chain to include the body
|
|
|
|
// or the document.
|
|
|
|
JS::AutoObjectVector scopeChain(cx);
|
|
|
|
if (!nsJSUtils::GetScopeChainForElement(cx, element, scopeChain)) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
2014-03-22 06:31:02 +04:00
|
|
|
nsDependentAtomString str(attrName);
|
|
|
|
// Most of our names are short enough that we don't even have to malloc
|
|
|
|
// the JS string stuff, so don't worry about playing games with
|
|
|
|
// refcounting XPCOM stringbuffers.
|
|
|
|
JS::Rooted<JSString*> jsStr(cx, JS_NewUCStringCopyN(cx,
|
|
|
|
str.BeginReading(),
|
|
|
|
str.Length()));
|
|
|
|
NS_ENSURE_TRUE(jsStr, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
|
|
|
|
// Get the reflector for |aElement|, so that we can pass to setElement.
|
2015-07-31 20:30:55 +03:00
|
|
|
if (NS_WARN_IF(!GetOrCreateDOMReflector(cx, aElement, &v))) {
|
2014-03-22 06:31:02 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2014-03-22 06:31:02 +04:00
|
|
|
JS::CompileOptions options(cx);
|
|
|
|
options.setIntroductionType("eventHandler")
|
|
|
|
.setFileAndLine(url.get(), lineNo)
|
2014-06-06 12:06:26 +04:00
|
|
|
.setVersion(JSVERSION_DEFAULT)
|
2014-03-22 06:31:02 +04:00
|
|
|
.setElement(&v.toObject())
|
2014-10-31 02:40:29 +03:00
|
|
|
.setElementAttributeName(jsStr);
|
2014-03-22 06:31:02 +04:00
|
|
|
|
2014-03-22 06:31:02 +04:00
|
|
|
JS::Rooted<JSObject*> handler(cx);
|
2014-10-25 08:50:29 +04:00
|
|
|
result = nsJSUtils::CompileFunction(jsapi, scopeChain, options,
|
2014-03-22 06:31:02 +04:00
|
|
|
nsAtomCString(typeAtom),
|
2014-03-22 06:31:02 +04:00
|
|
|
argCount, argNames, *body, handler.address());
|
2014-03-22 06:31:02 +04:00
|
|
|
NS_ENSURE_SUCCESS(result, result);
|
|
|
|
NS_ENSURE_TRUE(handler, NS_ERROR_FAILURE);
|
|
|
|
|
2014-04-02 06:00:46 +04:00
|
|
|
if (jsEventHandler->EventName() == nsGkAtoms::onerror && win) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<OnErrorEventHandlerNonNull> handlerCallback =
|
2015-07-24 14:00:00 +03:00
|
|
|
new OnErrorEventHandlerNonNull(nullptr, handler, /* aIncumbentGlobal = */ nullptr);
|
2014-04-02 06:00:46 +04:00
|
|
|
jsEventHandler->SetHandler(handlerCallback);
|
|
|
|
} else if (jsEventHandler->EventName() == nsGkAtoms::onbeforeunload && win) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<OnBeforeUnloadEventHandlerNonNull> handlerCallback =
|
2015-07-24 14:00:00 +03:00
|
|
|
new OnBeforeUnloadEventHandlerNonNull(nullptr, handler, /* aIncumbentGlobal = */ nullptr);
|
2014-04-02 06:00:46 +04:00
|
|
|
jsEventHandler->SetHandler(handlerCallback);
|
2014-03-05 17:16:42 +04:00
|
|
|
} else {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<EventHandlerNonNull> handlerCallback =
|
2015-07-24 14:00:00 +03:00
|
|
|
new EventHandlerNonNull(nullptr, handler, /* aIncumbentGlobal = */ nullptr);
|
2014-04-02 06:00:46 +04:00
|
|
|
jsEventHandler->SetHandler(handlerCallback);
|
2011-10-30 00:16:43 +04:00
|
|
|
}
|
2011-08-24 23:49:25 +04:00
|
|
|
|
2001-03-13 14:37:16 +03:00
|
|
|
return result;
|
1999-11-25 03:05:21 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::HandleEventSubType(Listener* aListener,
|
|
|
|
nsIDOMEvent* aDOMEvent,
|
|
|
|
EventTarget* aCurrentTarget)
|
1999-11-25 03:05:21 +03:00
|
|
|
{
|
|
|
|
nsresult result = NS_OK;
|
2014-03-17 10:56:51 +04:00
|
|
|
EventListenerHolder listenerHolder(aListener->mListener); // strong ref
|
1999-11-25 03:05:21 +03:00
|
|
|
|
|
|
|
// If this is a script handler and we haven't yet
|
|
|
|
// compiled the event handler itself
|
2014-03-17 10:56:51 +04:00
|
|
|
if ((aListener->mListenerType == Listener::eJSEventListener) &&
|
2014-03-17 10:56:51 +04:00
|
|
|
aListener->mHandlerIsString) {
|
|
|
|
result = CompileEventHandlerInternal(aListener, nullptr, nullptr);
|
|
|
|
aListener = nullptr;
|
1998-07-31 22:21:37 +04:00
|
|
|
}
|
1999-11-25 03:05:21 +03:00
|
|
|
|
2009-05-14 11:03:15 +04:00
|
|
|
if (NS_SUCCEEDED(result)) {
|
2013-09-14 04:22:39 +04:00
|
|
|
if (mIsMainThreadELM) {
|
|
|
|
nsContentUtils::EnterMicroTask();
|
|
|
|
}
|
2014-03-18 08:48:21 +04:00
|
|
|
// nsIDOMEvent::currentTarget is set in EventDispatcher.
|
2014-03-17 10:56:51 +04:00
|
|
|
if (listenerHolder.HasWebIDLCallback()) {
|
2013-04-17 01:15:57 +04:00
|
|
|
ErrorResult rv;
|
2014-03-17 10:56:51 +04:00
|
|
|
listenerHolder.GetWebIDLCallback()->
|
2013-04-17 01:15:57 +04:00
|
|
|
HandleEvent(aCurrentTarget, *(aDOMEvent->InternalDOMEvent()), rv);
|
2015-04-27 16:18:52 +03:00
|
|
|
result = rv.StealNSResult();
|
2013-04-17 01:15:57 +04:00
|
|
|
} else {
|
2014-03-17 10:56:51 +04:00
|
|
|
result = listenerHolder.GetXPCOMCallback()->HandleEvent(aDOMEvent);
|
2013-04-17 01:15:57 +04:00
|
|
|
}
|
2013-09-14 04:22:39 +04:00
|
|
|
if (mIsMainThreadELM) {
|
|
|
|
nsContentUtils::LeaveMicroTask();
|
|
|
|
}
|
1999-11-25 03:05:21 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
1998-07-31 22:21:37 +04:00
|
|
|
}
|
|
|
|
|
2016-02-02 21:03:49 +03:00
|
|
|
EventMessage
|
|
|
|
EventListenerManager::GetLegacyEventMessage(EventMessage aEventMessage) const
|
|
|
|
{
|
|
|
|
// (If we're off-main-thread, we can't check the pref; so we just behave as
|
|
|
|
// if it's disabled.)
|
|
|
|
if (mIsMainThreadELM && IsWebkitPrefixSupportEnabled()) {
|
|
|
|
// webkit-prefixed legacy events:
|
|
|
|
if (aEventMessage == eTransitionEnd) {
|
|
|
|
return eWebkitTransitionEnd;
|
|
|
|
}
|
|
|
|
if (aEventMessage == eAnimationStart) {
|
|
|
|
return eWebkitAnimationStart;
|
|
|
|
}
|
|
|
|
if (aEventMessage == eAnimationEnd) {
|
|
|
|
return eWebkitAnimationEnd;
|
|
|
|
}
|
|
|
|
if (aEventMessage == eAnimationIteration) {
|
|
|
|
return eWebkitAnimationIteration;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-17 03:47:11 +03:00
|
|
|
switch (aEventMessage) {
|
|
|
|
case eFullscreenChange:
|
|
|
|
return eMozFullscreenChange;
|
|
|
|
case eFullscreenError:
|
|
|
|
return eMozFullscreenError;
|
|
|
|
default:
|
|
|
|
return aEventMessage;
|
|
|
|
}
|
2016-02-02 21:03:49 +03:00
|
|
|
}
|
|
|
|
|
2014-10-28 14:18:00 +03:00
|
|
|
nsIDocShell*
|
|
|
|
EventListenerManager::GetDocShellForTarget()
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsINode> node(do_QueryInterface(mTarget));
|
|
|
|
nsIDocument* doc = nullptr;
|
|
|
|
nsIDocShell* docShell = nullptr;
|
|
|
|
|
|
|
|
if (node) {
|
|
|
|
doc = node->OwnerDoc();
|
|
|
|
if (!doc->GetDocShell()) {
|
|
|
|
bool ignore;
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowInner> window =
|
2014-10-28 14:18:00 +03:00
|
|
|
do_QueryInterface(doc->GetScriptHandlingObject(ignore));
|
|
|
|
if (window) {
|
|
|
|
doc = window->GetExtantDoc();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2016-01-30 20:05:36 +03:00
|
|
|
if (nsCOMPtr<nsPIDOMWindowInner> window = GetTargetAsInnerWindow()) {
|
2014-10-28 14:18:00 +03:00
|
|
|
doc = window->GetExtantDoc();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!doc) {
|
|
|
|
nsCOMPtr<DOMEventTargetHelper> helper(do_QueryInterface(mTarget));
|
|
|
|
if (helper) {
|
2016-01-30 20:05:36 +03:00
|
|
|
if (nsPIDOMWindowInner* window = helper->GetOwner()) {
|
2014-10-28 14:18:00 +03:00
|
|
|
doc = window->GetExtantDoc();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (doc) {
|
|
|
|
docShell = doc->GetDocShell();
|
|
|
|
}
|
|
|
|
|
|
|
|
return docShell;
|
|
|
|
}
|
|
|
|
|
1998-06-07 11:55:55 +04:00
|
|
|
/**
|
|
|
|
* Causes a check for event listeners and processing by them if they exist.
|
|
|
|
* @param an event listener
|
|
|
|
*/
|
|
|
|
|
2011-06-24 06:18:02 +04:00
|
|
|
void
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
|
|
|
|
WidgetEvent* aEvent,
|
|
|
|
nsIDOMEvent** aDOMEvent,
|
|
|
|
EventTarget* aCurrentTarget,
|
|
|
|
nsEventStatus* aEventStatus)
|
1998-06-07 11:55:55 +04:00
|
|
|
{
|
2000-09-15 10:11:15 +04:00
|
|
|
//Set the value of the internal PreventDefault flag properly based on aEventStatus
|
2016-03-22 10:47:52 +03:00
|
|
|
if (!aEvent->DefaultPrevented() &&
|
2016-03-22 10:26:27 +03:00
|
|
|
*aEventStatus == nsEventStatus_eConsumeNoDefault) {
|
|
|
|
// Assume that if only aEventStatus claims that the event has already been
|
|
|
|
// consumed, the consumer is default event handler.
|
|
|
|
aEvent->PreventDefault();
|
2000-09-15 10:11:15 +04:00
|
|
|
}
|
1998-06-07 11:55:55 +04:00
|
|
|
|
2013-11-05 18:16:26 +04:00
|
|
|
Maybe<nsAutoPopupStatePusher> popupStatePusher;
|
|
|
|
if (mIsMainThreadELM) {
|
2014-10-15 18:48:04 +04:00
|
|
|
popupStatePusher.emplace(Event::GetEventPopupControlState(aEvent, *aDOMEvent));
|
2013-11-05 18:16:26 +04:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool hasListener = false;
|
2016-02-17 03:47:11 +03:00
|
|
|
bool hasListenerForCurrentGroup = false;
|
2016-02-02 21:03:49 +03:00
|
|
|
bool usingLegacyMessage = false;
|
|
|
|
EventMessage eventMessage = aEvent->mMessage;
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
nsAutoTObserverArray<Listener, 2>::EndLimitedIterator iter(mListeners);
|
|
|
|
Maybe<EventMessageAutoOverride> legacyAutoOverride;
|
|
|
|
while (iter.HasMore()) {
|
|
|
|
if (aEvent->mFlags.mImmediatePropagationStopped) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Listener* listener = &iter.GetNext();
|
|
|
|
// Check that the phase is same in event and event listener.
|
|
|
|
// Handle only trusted events, except when listener permits untrusted events.
|
|
|
|
if (ListenerCanHandle(listener, aEvent, eventMessage)) {
|
|
|
|
hasListener = true;
|
2016-02-17 03:47:11 +03:00
|
|
|
hasListenerForCurrentGroup = hasListenerForCurrentGroup ||
|
|
|
|
listener->mFlags.mInSystemGroup == aEvent->mFlags.mInSystemGroup;
|
2016-02-02 21:03:49 +03:00
|
|
|
if (listener->IsListening(aEvent) &&
|
2016-03-17 10:01:30 +03:00
|
|
|
(aEvent->IsTrusted() || listener->mFlags.mAllowUntrustedEvents)) {
|
2016-02-02 21:03:49 +03:00
|
|
|
if (!*aDOMEvent) {
|
|
|
|
// This is tiny bit slow, but happens only once per event.
|
|
|
|
nsCOMPtr<EventTarget> et =
|
2016-04-18 19:33:23 +03:00
|
|
|
do_QueryInterface(aEvent->mOriginalTarget);
|
2016-02-02 21:03:49 +03:00
|
|
|
RefPtr<Event> event = EventDispatcher::CreateEvent(et, aPresContext,
|
2015-08-12 14:39:31 +03:00
|
|
|
aEvent,
|
|
|
|
EmptyString());
|
2016-02-02 21:03:49 +03:00
|
|
|
event.forget(aDOMEvent);
|
|
|
|
}
|
|
|
|
if (*aDOMEvent) {
|
2016-04-18 19:15:16 +03:00
|
|
|
if (!aEvent->mCurrentTarget) {
|
|
|
|
aEvent->mCurrentTarget = aCurrentTarget->GetTargetForDOMEvent();
|
|
|
|
if (!aEvent->mCurrentTarget) {
|
2016-02-02 21:03:49 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (usingLegacyMessage && !legacyAutoOverride) {
|
|
|
|
// Override the aDOMEvent's event-message (its .type) until we
|
|
|
|
// finish traversing listeners (when legacyAutoOverride destructs)
|
|
|
|
legacyAutoOverride.emplace(*aDOMEvent, eventMessage);
|
2009-06-15 14:21:06 +04:00
|
|
|
}
|
2012-06-29 01:47:56 +04:00
|
|
|
|
2016-02-02 21:03:49 +03:00
|
|
|
// Maybe add a marker to the docshell's timeline, but only
|
|
|
|
// bother with all the logic if some docshell is recording.
|
2016-02-10 02:21:36 +03:00
|
|
|
nsCOMPtr<nsIDocShell> docShell;
|
2016-02-02 21:03:49 +03:00
|
|
|
RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
|
|
|
|
bool needsEndEventMarker = false;
|
|
|
|
|
|
|
|
if (mIsMainThreadELM &&
|
|
|
|
listener->mListenerType != Listener::eNativeListener) {
|
2016-02-10 02:21:36 +03:00
|
|
|
docShell = GetDocShellForTarget();
|
|
|
|
if (docShell) {
|
2016-02-02 21:03:49 +03:00
|
|
|
if (timelines && timelines->HasConsumer(docShell)) {
|
|
|
|
needsEndEventMarker = true;
|
|
|
|
nsAutoString typeStr;
|
|
|
|
(*aDOMEvent)->GetType(typeStr);
|
|
|
|
uint16_t phase;
|
|
|
|
(*aDOMEvent)->GetEventPhase(&phase);
|
|
|
|
timelines->AddMarkerForDocShell(docShell, Move(
|
|
|
|
MakeUnique<EventTimelineMarker>(
|
|
|
|
typeStr, phase, MarkerTracingType::START)));
|
|
|
|
}
|
2015-10-22 00:10:05 +03:00
|
|
|
}
|
2014-10-28 14:18:00 +03:00
|
|
|
}
|
|
|
|
|
2016-05-12 21:50:22 +03:00
|
|
|
aEvent->mFlags.mInPassiveListener = listener->mFlags.mPassive;
|
2016-02-02 21:03:49 +03:00
|
|
|
if (NS_FAILED(HandleEventSubType(listener, *aDOMEvent, aCurrentTarget))) {
|
2016-05-09 08:16:42 +03:00
|
|
|
aEvent->mFlags.mExceptionWasRaised = true;
|
2016-02-02 21:03:49 +03:00
|
|
|
}
|
2016-05-12 21:50:22 +03:00
|
|
|
aEvent->mFlags.mInPassiveListener = false;
|
2014-10-28 14:18:00 +03:00
|
|
|
|
2016-02-02 21:03:49 +03:00
|
|
|
if (needsEndEventMarker) {
|
|
|
|
timelines->AddMarkerForDocShell(
|
|
|
|
docShell, "DOMEvent", MarkerTracingType::END);
|
|
|
|
}
|
2014-10-28 14:18:00 +03:00
|
|
|
}
|
2000-11-27 10:55:20 +03:00
|
|
|
}
|
|
|
|
}
|
2003-09-11 10:31:58 +04:00
|
|
|
}
|
2016-02-02 21:03:49 +03:00
|
|
|
|
|
|
|
// If we didn't find any matching listeners, and our event has a legacy
|
|
|
|
// version, we'll now switch to looking for that legacy version and we'll
|
|
|
|
// recheck our listeners.
|
2016-02-17 03:47:11 +03:00
|
|
|
if (hasListenerForCurrentGroup || usingLegacyMessage) {
|
2016-02-02 21:03:49 +03:00
|
|
|
// (No need to recheck listeners, because we already found a match, or we
|
|
|
|
// already rechecked them.)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
EventMessage legacyEventMessage = GetLegacyEventMessage(eventMessage);
|
|
|
|
if (legacyEventMessage == eventMessage) {
|
|
|
|
break; // There's no legacy version of our event; no need to recheck.
|
|
|
|
}
|
|
|
|
MOZ_ASSERT(GetLegacyEventMessage(legacyEventMessage) == legacyEventMessage,
|
|
|
|
"Legacy event messages should not themselves have legacy versions");
|
|
|
|
|
|
|
|
// Recheck our listeners, using the legacy event message we just looked up:
|
|
|
|
eventMessage = legacyEventMessage;
|
|
|
|
usingLegacyMessage = true;
|
1998-06-07 11:55:55 +04:00
|
|
|
}
|
2000-11-08 03:31:06 +03:00
|
|
|
|
2016-04-18 19:15:16 +03:00
|
|
|
aEvent->mCurrentTarget = nullptr;
|
2009-06-15 14:21:06 +04:00
|
|
|
|
2013-09-27 01:59:27 +04:00
|
|
|
if (mIsMainThreadELM && !hasListener) {
|
2015-08-22 04:34:51 +03:00
|
|
|
mNoListenerForEvent = aEvent->mMessage;
|
2016-04-18 17:53:03 +03:00
|
|
|
mNoListenerForEventAtom = aEvent->mSpecifiedEventType;
|
2006-10-06 09:24:02 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 10:47:52 +03:00
|
|
|
if (aEvent->DefaultPrevented()) {
|
2000-11-08 03:31:06 +03:00
|
|
|
*aEventStatus = nsEventStatus_eConsumeNoDefault;
|
|
|
|
}
|
1998-06-07 11:55:55 +04:00
|
|
|
}
|
|
|
|
|
2011-06-24 06:18:02 +04:00
|
|
|
void
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::Disconnect()
|
2006-01-19 05:43:39 +03:00
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
mTarget = nullptr;
|
2011-06-24 06:18:02 +04:00
|
|
|
RemoveAllListeners();
|
2006-01-19 05:43:39 +03:00
|
|
|
}
|
|
|
|
|
2016-06-01 04:35:53 +03:00
|
|
|
static EventListenerFlags
|
2016-06-02 13:15:23 +03:00
|
|
|
GetEventListenerFlagsFromOptions(const EventListenerOptions& aOptions,
|
|
|
|
bool aIsMainThread)
|
2016-06-01 04:35:53 +03:00
|
|
|
{
|
|
|
|
EventListenerFlags flags;
|
|
|
|
flags.mCapture = aOptions.mCapture;
|
|
|
|
if (aOptions.mMozSystemGroup) {
|
2016-06-02 13:15:23 +03:00
|
|
|
if (aIsMainThread) {
|
|
|
|
JSContext* cx = nsContentUtils::GetCurrentJSContext();
|
|
|
|
MOZ_ASSERT(cx, "Not being called from JS?");
|
|
|
|
flags.mInSystemGroup = IsChromeOrXBL(cx, nullptr);
|
|
|
|
} else {
|
|
|
|
flags.mInSystemGroup = workers::IsCurrentThreadRunningChromeWorker();
|
|
|
|
}
|
2016-06-01 04:35:53 +03:00
|
|
|
}
|
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
2011-08-18 13:45:00 +04:00
|
|
|
void
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::AddEventListener(
|
|
|
|
const nsAString& aType,
|
|
|
|
const EventListenerHolder& aListenerHolder,
|
|
|
|
bool aUseCapture,
|
|
|
|
bool aWantsUntrusted)
|
Landing changes Vidur made while the tree was closed for beta1 work, here's a list of the changes. r=me
[1] Cutting down the size of content. Made nsIJSScriptObject inherit from nsIScriptObjectOwner
[2] Cutting down the size of content. Made nsITextContent inherit from nsIContent.
[3] Cutting down the size of content. Moved implementation of nsIDOMReceiver to nsListenerManager. This is not true aggregation since it isn't transitive, but it's OK for now. It will be necessary for nsListenerManager to have a reference to its content in the future anyway, so the transitivity could be done.
dom/public/nsDOMPropEnums.h,v - bug 12559
dom/public/nsIJSScriptObject.h,v - [1]
dom/public/html/MANIFEST,v - bug 12559
dom/public/html/Makefile.in,v - bug 12559
dom/public/html/makefile.win,v - bug 12559
dom/public/html/nsIDOMHTMLInputElement.h,v - bug 17544
dom/public/idl/html/HTMLAnchorElement.idl,v - bug 12559
dom/public/idl/html/HTMLAreaElement.idl,v - bug 12559
dom/public/idl/html/HTMLInputElement.idl,v - bug 17544
dom/src/base/nsGlobalWindow.cpp,v - bug 30700
dom/src/base/nsGlobalWindow.h,v - [1]
dom/src/base/nsLocation.cpp,v - [1]
dom/src/html/nsJSHTMLAnchorElement.cpp,v - bug 12559
dom/src/html/nsJSHTMLAreaElement.cpp,v - bug 12559
dom/src/html/nsJSHTMLInputElement.cpp,v - bug 17544
layout/base/public/nsIDocument.h,v - bug 27953
layout/base/public/nsITextContent.h,v - [2]
layout/base/src/nsCommentNode.cpp,v - [2]
layout/base/src/nsDocument.cpp,v - bug 27953
layout/base/src/nsDocument.h,v - bug 27953
layout/base/src/nsDocumentViewer.cpp,v - bug 27953
layout/base/src/nsGenericDOMDataNode.cpp,v - [3]
layout/base/src/nsGenericDOMDataNode.h,v - [3]
layout/base/src/nsGenericElement.cpp,v - [3]
layout/base/src/nsGenericElement.h,v - [3]
layout/base/src/nsNameSpaceManager.cpp,v - bug 7834
layout/base/src/nsStyleContext.cpp,v - outline property shouldn't reflow
layout/base/src/nsTextNode.cpp,v - [2]
layout/events/src/nsEventListenerManager.cpp,v - [3]
layout/events/src/nsEventListenerManager.h,v - [3]
layout/html/base/src/nsGfxScrollFrame.cpp,v - nsString->nsAutoString
layout/html/content/src/nsAttributeContent.cpp,v - [2]
layout/html/content/src/nsHTMLAnchorElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLAppletElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLAreaElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLBRElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLBaseElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLBaseFontElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLBodyElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLButtonElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLDListElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLDelElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLDirectoryElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLDivElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLEmbedElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLFieldSetElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLFontElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLFormElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLFrameElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLFrameSetElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLHRElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLHeadElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLHeadingElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLHtmlElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLIFrameElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLImageElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLInputElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLInsElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLIsIndexElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLLIElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLLabelElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLLayerElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLLegendElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLLinkElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLMapElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLMenuElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLMetaElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLModElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLOListElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLObjectElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLOptGroupElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLOptionElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLParagraphElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLParamElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLPreElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLQuoteElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLScriptElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLSelectElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLSpacerElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLSpanElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLStyleElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLTableCaptionElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLTableCellElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLTableColElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLTableColGroupElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLTableElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLTableRowElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLTableSectionElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLTextAreaElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLTitleElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLUListElement.cpp,v - [1][3]
layout/html/content/src/nsHTMLWBRElement.cpp,v - [1][3]
layout/html/document/src/nsHTMLDocument.cpp,v - bug 27953
layout/html/document/src/nsHTMLDocument.h,v - bug 27953
layout/xml/content/src/nsXMLCDATASection.cpp,v - [1][2]
layout/xml/content/src/nsXMLDocumentType.cpp,v - [1][2]
layout/xml/content/src/nsXMLElement.h,v - [1][2]
layout/xml/content/src/nsXMLEntity.cpp,v - [1][2]
layout/xml/content/src/nsXMLNotation.cpp,v - [1][2]
layout/xml/content/src/nsXMLProcessingInstruction.cpp,v - [1][2]
layout/xul/base/src/nsBoxFrame.cpp,v - nsString->nsAutoString
layout/xul/base/src/nsSliderFrame.cpp,v - nsString->nsAutoString
netwerk/protocol/http/src/nsHTTPRequest.cpp,v - nsString->nsAutoString
rdf/content/src/nsXULDocument.cpp,v - bug 27953
rdf/content/src/nsXULDocument.h,v - bug 27953
rdf/content/src/nsXULElement.h,v - [1]
xpcom/base/IIDS.h,v - bug 12559
2000-03-17 16:27:00 +03:00
|
|
|
{
|
2012-12-16 05:26:05 +04:00
|
|
|
EventListenerFlags flags;
|
|
|
|
flags.mCapture = aUseCapture;
|
|
|
|
flags.mAllowUntrustedEvents = aWantsUntrusted;
|
2014-03-17 10:56:53 +04:00
|
|
|
return AddEventListenerByType(aListenerHolder, aType, flags);
|
2011-06-24 06:18:02 +04:00
|
|
|
}
|
2003-02-22 22:12:21 +03:00
|
|
|
|
2016-04-26 11:23:17 +03:00
|
|
|
void
|
|
|
|
EventListenerManager::AddEventListener(
|
|
|
|
const nsAString& aType,
|
|
|
|
const EventListenerHolder& aListenerHolder,
|
|
|
|
const dom::AddEventListenerOptionsOrBoolean& aOptions,
|
|
|
|
bool aWantsUntrusted)
|
|
|
|
{
|
|
|
|
EventListenerFlags flags;
|
2016-05-12 21:50:22 +03:00
|
|
|
if (aOptions.IsBoolean()) {
|
|
|
|
flags.mCapture = aOptions.GetAsBoolean();
|
|
|
|
} else {
|
2016-06-01 04:35:53 +03:00
|
|
|
const auto& options = aOptions.GetAsAddEventListenerOptions();
|
2016-06-02 13:15:23 +03:00
|
|
|
flags = GetEventListenerFlagsFromOptions(options, mIsMainThreadELM);
|
2016-06-01 04:35:53 +03:00
|
|
|
flags.mPassive = options.mPassive;
|
2016-05-12 21:50:22 +03:00
|
|
|
}
|
2016-04-26 11:23:17 +03:00
|
|
|
flags.mAllowUntrustedEvents = aWantsUntrusted;
|
|
|
|
return AddEventListenerByType(aListenerHolder, aType, flags);
|
|
|
|
}
|
|
|
|
|
2011-06-24 06:18:02 +04:00
|
|
|
void
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::RemoveEventListener(
|
|
|
|
const nsAString& aType,
|
|
|
|
const EventListenerHolder& aListenerHolder,
|
|
|
|
bool aUseCapture)
|
2011-06-24 06:18:02 +04:00
|
|
|
{
|
2012-12-16 05:26:05 +04:00
|
|
|
EventListenerFlags flags;
|
|
|
|
flags.mCapture = aUseCapture;
|
2014-03-17 10:56:53 +04:00
|
|
|
RemoveEventListenerByType(aListenerHolder, aType, flags);
|
2002-11-09 03:25:25 +03:00
|
|
|
}
|
|
|
|
|
2016-04-26 11:23:17 +03:00
|
|
|
void
|
|
|
|
EventListenerManager::RemoveEventListener(
|
|
|
|
const nsAString& aType,
|
|
|
|
const EventListenerHolder& aListenerHolder,
|
|
|
|
const dom::EventListenerOptionsOrBoolean& aOptions)
|
|
|
|
{
|
|
|
|
EventListenerFlags flags;
|
2016-06-01 04:35:53 +03:00
|
|
|
if (aOptions.IsBoolean()) {
|
|
|
|
flags.mCapture = aOptions.GetAsBoolean();
|
|
|
|
} else {
|
|
|
|
const auto& options = aOptions.GetAsEventListenerOptions();
|
2016-06-02 13:15:23 +03:00
|
|
|
flags = GetEventListenerFlagsFromOptions(options, mIsMainThreadELM);
|
2016-06-01 04:35:53 +03:00
|
|
|
}
|
2016-04-26 11:23:17 +03:00
|
|
|
RemoveEventListenerByType(aListenerHolder, aType, flags);
|
|
|
|
}
|
|
|
|
|
2012-11-01 16:42:29 +04:00
|
|
|
void
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::AddListenerForAllEvents(nsIDOMEventListener* aDOMListener,
|
2014-03-17 10:56:53 +04:00
|
|
|
bool aUseCapture,
|
|
|
|
bool aWantsUntrusted,
|
|
|
|
bool aSystemEventGroup)
|
2012-11-01 16:42:29 +04:00
|
|
|
{
|
2012-12-16 05:26:05 +04:00
|
|
|
EventListenerFlags flags;
|
|
|
|
flags.mCapture = aUseCapture;
|
|
|
|
flags.mAllowUntrustedEvents = aWantsUntrusted;
|
|
|
|
flags.mInSystemGroup = aSystemEventGroup;
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerHolder listenerHolder(aDOMListener);
|
2015-08-29 02:58:26 +03:00
|
|
|
AddEventListenerInternal(listenerHolder, eAllEvents, nullptr, EmptyString(),
|
2013-08-16 14:06:24 +04:00
|
|
|
flags, false, true);
|
2012-11-01 16:42:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::RemoveListenerForAllEvents(
|
|
|
|
nsIDOMEventListener* aDOMListener,
|
|
|
|
bool aUseCapture,
|
|
|
|
bool aSystemEventGroup)
|
2012-11-01 16:42:29 +04:00
|
|
|
{
|
2012-12-16 05:26:05 +04:00
|
|
|
EventListenerFlags flags;
|
|
|
|
flags.mCapture = aUseCapture;
|
|
|
|
flags.mInSystemGroup = aSystemEventGroup;
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerHolder listenerHolder(aDOMListener);
|
2015-08-29 02:58:26 +03:00
|
|
|
RemoveEventListenerInternal(listenerHolder, eAllEvents, nullptr,
|
2014-03-17 10:56:53 +04:00
|
|
|
EmptyString(), flags, true);
|
2012-11-01 16:42:29 +04:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::HasMutationListeners()
|
2006-09-09 21:28:57 +04:00
|
|
|
{
|
2006-10-06 09:24:02 +04:00
|
|
|
if (mMayHaveMutationListeners) {
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t count = mListeners.Length();
|
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
2014-03-17 10:56:51 +04:00
|
|
|
Listener* listener = &mListeners.ElementAt(i);
|
2015-09-07 17:55:50 +03:00
|
|
|
if (listener->mEventMessage >= eLegacyMutationEventFirst &&
|
2015-09-07 17:55:51 +03:00
|
|
|
listener->mEventMessage <= eLegacyMutationEventLast) {
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2006-10-06 09:24:02 +04:00
|
|
|
}
|
2006-09-09 21:28:57 +04:00
|
|
|
}
|
|
|
|
}
|
2006-09-10 15:53:55 +04:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2006-10-06 09:24:02 +04:00
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::MutationListenerBits()
|
2007-02-01 01:54:24 +03:00
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t bits = 0;
|
2007-02-01 01:54:24 +03:00
|
|
|
if (mMayHaveMutationListeners) {
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t count = mListeners.Length();
|
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
2014-03-17 10:56:51 +04:00
|
|
|
Listener* listener = &mListeners.ElementAt(i);
|
2015-09-07 17:55:50 +03:00
|
|
|
if (listener->mEventMessage >= eLegacyMutationEventFirst &&
|
2015-09-07 17:55:51 +03:00
|
|
|
listener->mEventMessage <= eLegacyMutationEventLast) {
|
2015-09-07 17:55:51 +03:00
|
|
|
if (listener->mEventMessage == eLegacySubtreeModified) {
|
2007-03-24 15:18:02 +03:00
|
|
|
return kAllMutationBits;
|
|
|
|
}
|
2015-08-26 15:56:59 +03:00
|
|
|
bits |= MutationBitForEventType(listener->mEventMessage);
|
2007-02-01 01:54:24 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return bits;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::HasListenersFor(const nsAString& aEventName)
|
2007-05-09 01:13:13 +04:00
|
|
|
{
|
2015-01-15 19:58:40 +03:00
|
|
|
if (mIsMainThreadELM) {
|
2016-03-29 02:09:43 +03:00
|
|
|
nsCOMPtr<nsIAtom> atom = NS_Atomize(NS_LITERAL_STRING("on") + aEventName);
|
2015-01-15 19:58:40 +03:00
|
|
|
return HasListenersFor(atom);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t count = mListeners.Length();
|
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
|
|
|
Listener* listener = &mListeners.ElementAt(i);
|
|
|
|
if (listener->mTypeString == aEventName) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2012-08-17 18:12:58 +04:00
|
|
|
}
|
2007-05-09 01:13:13 +04:00
|
|
|
|
2012-08-17 18:12:58 +04:00
|
|
|
bool
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::HasListenersFor(nsIAtom* aEventNameWithOn)
|
2012-08-17 18:12:58 +04:00
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
nsAutoString name;
|
|
|
|
aEventNameWithOn->ToString(name);
|
|
|
|
#endif
|
|
|
|
NS_ASSERTION(StringBeginsWith(name, NS_LITERAL_STRING("on")),
|
|
|
|
"Event name does not start with 'on'");
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t count = mListeners.Length();
|
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
2014-03-17 10:56:51 +04:00
|
|
|
Listener* listener = &mListeners.ElementAt(i);
|
|
|
|
if (listener->mTypeAtom == aEventNameWithOn) {
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2007-05-09 01:13:13 +04:00
|
|
|
}
|
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2007-05-09 01:13:13 +04:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::HasListeners()
|
2008-10-01 04:51:53 +04:00
|
|
|
{
|
|
|
|
return !mListeners.IsEmpty();
|
|
|
|
}
|
|
|
|
|
2009-10-16 12:57:32 +04:00
|
|
|
nsresult
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::GetListenerInfo(nsCOMArray<nsIEventListenerInfo>* aList)
|
2009-10-16 12:57:32 +04:00
|
|
|
{
|
2013-04-06 04:44:15 +04:00
|
|
|
nsCOMPtr<EventTarget> target = do_QueryInterface(mTarget);
|
2009-10-16 12:57:32 +04:00
|
|
|
NS_ENSURE_STATE(target);
|
|
|
|
aList->Clear();
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t count = mListeners.Length();
|
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
2014-03-17 10:56:51 +04:00
|
|
|
const Listener& listener = mListeners.ElementAt(i);
|
2009-10-16 12:57:32 +04:00
|
|
|
// If this is a script handler and we haven't yet
|
2011-08-24 23:49:25 +04:00
|
|
|
// compiled the event handler itself go ahead and compile it
|
2014-03-17 10:56:51 +04:00
|
|
|
if (listener.mListenerType == Listener::eJSEventListener &&
|
2014-03-17 10:56:51 +04:00
|
|
|
listener.mHandlerIsString) {
|
|
|
|
CompileEventHandlerInternal(const_cast<Listener*>(&listener), nullptr,
|
2013-11-26 20:44:37 +04:00
|
|
|
nullptr);
|
2009-10-16 12:57:32 +04:00
|
|
|
}
|
2013-06-14 21:10:22 +04:00
|
|
|
nsAutoString eventType;
|
2014-03-17 10:56:51 +04:00
|
|
|
if (listener.mAllEvents) {
|
2013-06-14 21:10:22 +04:00
|
|
|
eventType.SetIsVoid(true);
|
|
|
|
} else {
|
2014-03-17 10:56:51 +04:00
|
|
|
eventType.Assign(Substring(nsDependentAtomString(listener.mTypeAtom), 2));
|
2013-06-14 21:10:22 +04:00
|
|
|
}
|
2013-04-17 01:15:57 +04:00
|
|
|
// EventListenerInfo is defined in XPCOM, so we have to go ahead
|
|
|
|
// and convert to an XPCOM callback here...
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<EventListenerInfo> info =
|
2014-03-17 10:56:51 +04:00
|
|
|
new EventListenerInfo(eventType, listener.mListener.ToXPCOMCallback(),
|
|
|
|
listener.mFlags.mCapture,
|
|
|
|
listener.mFlags.mAllowUntrustedEvents,
|
|
|
|
listener.mFlags.mInSystemGroup);
|
2011-08-08 22:26:26 +04:00
|
|
|
aList->AppendObject(info);
|
2009-10-16 12:57:32 +04:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::HasUnloadListeners()
|
2006-10-06 09:24:02 +04:00
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t count = mListeners.Length();
|
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
2014-03-17 10:56:51 +04:00
|
|
|
Listener* listener = &mListeners.ElementAt(i);
|
2015-09-02 09:07:59 +03:00
|
|
|
if (listener->mEventMessage == eUnload ||
|
2015-09-02 09:07:59 +03:00
|
|
|
listener->mEventMessage == eBeforeUnload) {
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2006-10-06 09:24:02 +04:00
|
|
|
}
|
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2005-05-05 00:22:32 +04:00
|
|
|
}
|
2011-08-24 23:49:25 +04:00
|
|
|
|
2013-09-17 15:01:28 +04:00
|
|
|
void
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::SetEventHandler(nsIAtom* aEventName,
|
|
|
|
const nsAString& aTypeString,
|
|
|
|
EventHandlerNonNull* aHandler)
|
2011-08-24 23:49:25 +04:00
|
|
|
{
|
2012-11-09 20:00:25 +04:00
|
|
|
if (!aHandler) {
|
2013-08-16 14:06:24 +04:00
|
|
|
RemoveEventHandler(aEventName, aTypeString);
|
2013-09-17 15:01:28 +04:00
|
|
|
return;
|
2011-08-24 23:49:25 +04:00
|
|
|
}
|
|
|
|
|
2012-11-09 20:00:25 +04:00
|
|
|
// Untrusted events are always permitted for non-chrome script
|
|
|
|
// handlers.
|
2014-04-02 06:00:45 +04:00
|
|
|
SetEventHandlerInternal(aEventName, aTypeString, TypedEventHandler(aHandler),
|
2013-09-17 15:01:28 +04:00
|
|
|
!mIsMainThreadELM ||
|
|
|
|
!nsContentUtils::IsCallerChrome());
|
2012-11-09 20:00:25 +04:00
|
|
|
}
|
|
|
|
|
2013-09-17 15:01:28 +04:00
|
|
|
void
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::SetEventHandler(OnErrorEventHandlerNonNull* aHandler)
|
2012-11-09 20:00:25 +04:00
|
|
|
{
|
2013-11-05 18:16:26 +04:00
|
|
|
if (mIsMainThreadELM) {
|
|
|
|
if (!aHandler) {
|
|
|
|
RemoveEventHandler(nsGkAtoms::onerror, EmptyString());
|
|
|
|
return;
|
|
|
|
}
|
2012-06-14 21:22:34 +04:00
|
|
|
|
2013-11-05 18:16:26 +04:00
|
|
|
// Untrusted events are always permitted for non-chrome script
|
|
|
|
// handlers.
|
2014-03-22 06:31:03 +04:00
|
|
|
SetEventHandlerInternal(nsGkAtoms::onerror, EmptyString(),
|
2014-04-02 06:00:45 +04:00
|
|
|
TypedEventHandler(aHandler),
|
2013-11-05 18:16:26 +04:00
|
|
|
!nsContentUtils::IsCallerChrome());
|
|
|
|
} else {
|
|
|
|
if (!aHandler) {
|
|
|
|
RemoveEventHandler(nullptr, NS_LITERAL_STRING("error"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Untrusted events are always permitted.
|
2014-03-22 06:31:03 +04:00
|
|
|
SetEventHandlerInternal(nullptr, NS_LITERAL_STRING("error"),
|
2014-04-02 06:00:45 +04:00
|
|
|
TypedEventHandler(aHandler), true);
|
2013-11-05 18:16:26 +04:00
|
|
|
}
|
2011-08-24 23:49:25 +04:00
|
|
|
}
|
|
|
|
|
2013-09-17 15:01:28 +04:00
|
|
|
void
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::SetEventHandler(
|
|
|
|
OnBeforeUnloadEventHandlerNonNull* aHandler)
|
2012-11-09 20:00:25 +04:00
|
|
|
{
|
|
|
|
if (!aHandler) {
|
2013-08-16 14:06:24 +04:00
|
|
|
RemoveEventHandler(nsGkAtoms::onbeforeunload, EmptyString());
|
2013-09-17 15:01:28 +04:00
|
|
|
return;
|
2012-11-09 20:00:25 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Untrusted events are always permitted for non-chrome script
|
|
|
|
// handlers.
|
2014-03-22 06:31:03 +04:00
|
|
|
SetEventHandlerInternal(nsGkAtoms::onbeforeunload, EmptyString(),
|
2014-04-02 06:00:45 +04:00
|
|
|
TypedEventHandler(aHandler),
|
2013-09-17 15:01:28 +04:00
|
|
|
!mIsMainThreadELM ||
|
|
|
|
!nsContentUtils::IsCallerChrome());
|
2012-11-09 20:00:25 +04:00
|
|
|
}
|
|
|
|
|
2014-04-02 06:00:45 +04:00
|
|
|
const TypedEventHandler*
|
|
|
|
EventListenerManager::GetTypedEventHandler(nsIAtom* aEventName,
|
|
|
|
const nsAString& aTypeString)
|
2011-08-24 23:49:25 +04:00
|
|
|
{
|
2015-08-26 15:56:59 +03:00
|
|
|
EventMessage eventMessage = nsContentUtils::GetEventMessage(aEventName);
|
|
|
|
Listener* listener = FindEventHandler(eventMessage, aEventName, aTypeString);
|
2011-08-24 23:49:25 +04:00
|
|
|
|
2014-03-17 10:56:51 +04:00
|
|
|
if (!listener) {
|
2012-11-09 20:00:25 +04:00
|
|
|
return nullptr;
|
2011-08-24 23:49:25 +04:00
|
|
|
}
|
|
|
|
|
2014-04-02 06:00:46 +04:00
|
|
|
JSEventHandler* jsEventHandler = listener->GetJSEventHandler();
|
2014-03-17 10:56:51 +04:00
|
|
|
|
|
|
|
if (listener->mHandlerIsString) {
|
|
|
|
CompileEventHandlerInternal(listener, nullptr, nullptr);
|
2011-08-24 23:49:25 +04:00
|
|
|
}
|
|
|
|
|
2014-04-02 06:00:46 +04:00
|
|
|
const TypedEventHandler& typedHandler =
|
|
|
|
jsEventHandler->GetTypedEventHandler();
|
2014-04-02 06:00:45 +04:00
|
|
|
return typedHandler.HasEventHandler() ? &typedHandler : nullptr;
|
2011-08-24 23:49:25 +04:00
|
|
|
}
|
|
|
|
|
2012-02-02 01:58:01 +04:00
|
|
|
size_t
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
2011-08-27 02:39:00 +04:00
|
|
|
{
|
2012-02-02 01:58:01 +04:00
|
|
|
size_t n = aMallocSizeOf(this);
|
2015-07-29 09:24:24 +03:00
|
|
|
n += mListeners.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t count = mListeners.Length();
|
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
2014-04-02 06:00:46 +04:00
|
|
|
JSEventHandler* jsEventHandler =
|
|
|
|
mListeners.ElementAt(i).GetJSEventHandler();
|
|
|
|
if (jsEventHandler) {
|
|
|
|
n += jsEventHandler->SizeOfIncludingThis(aMallocSizeOf);
|
2011-08-27 02:39:00 +04:00
|
|
|
}
|
|
|
|
}
|
2012-02-02 01:58:01 +04:00
|
|
|
return n;
|
2011-08-27 02:39:00 +04:00
|
|
|
}
|
2012-01-26 18:45:12 +04:00
|
|
|
|
|
|
|
void
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::MarkForCC()
|
2012-01-26 18:45:12 +04:00
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t count = mListeners.Length();
|
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
2014-03-17 10:56:51 +04:00
|
|
|
const Listener& listener = mListeners.ElementAt(i);
|
2014-04-02 06:00:46 +04:00
|
|
|
JSEventHandler* jsEventHandler = listener.GetJSEventHandler();
|
|
|
|
if (jsEventHandler) {
|
2014-04-02 06:00:45 +04:00
|
|
|
const TypedEventHandler& typedHandler =
|
2014-04-02 06:00:46 +04:00
|
|
|
jsEventHandler->GetTypedEventHandler();
|
2014-04-02 06:00:45 +04:00
|
|
|
if (typedHandler.HasEventHandler()) {
|
2015-08-20 18:36:06 +03:00
|
|
|
typedHandler.Ptr()->MarkForCC();
|
2013-09-09 07:28:48 +04:00
|
|
|
}
|
2014-03-17 10:56:51 +04:00
|
|
|
} else if (listener.mListenerType == Listener::eWrappedJSListener) {
|
2014-03-17 10:56:51 +04:00
|
|
|
xpc_TryUnmarkWrappedGrayObject(listener.mListener.GetXPCOMCallback());
|
2014-03-17 10:56:51 +04:00
|
|
|
} else if (listener.mListenerType == Listener::eWebIDLListener) {
|
2015-08-20 18:36:06 +03:00
|
|
|
listener.mListener.GetWebIDLCallback()->MarkForCC();
|
2012-01-26 18:45:12 +04:00
|
|
|
}
|
|
|
|
}
|
2012-10-17 05:22:02 +04:00
|
|
|
if (mRefCnt.IsPurple()) {
|
|
|
|
mRefCnt.RemovePurple();
|
|
|
|
}
|
2012-01-26 18:45:12 +04:00
|
|
|
}
|
2013-11-27 13:12:41 +04:00
|
|
|
|
2014-06-05 03:48:50 +04:00
|
|
|
void
|
|
|
|
EventListenerManager::TraceListeners(JSTracer* aTrc)
|
|
|
|
{
|
|
|
|
uint32_t count = mListeners.Length();
|
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
|
|
|
const Listener& listener = mListeners.ElementAt(i);
|
|
|
|
JSEventHandler* jsEventHandler = listener.GetJSEventHandler();
|
|
|
|
if (jsEventHandler) {
|
|
|
|
const TypedEventHandler& typedHandler =
|
|
|
|
jsEventHandler->GetTypedEventHandler();
|
|
|
|
if (typedHandler.HasEventHandler()) {
|
|
|
|
mozilla::TraceScriptHolder(typedHandler.Ptr(), aTrc);
|
|
|
|
}
|
|
|
|
} else if (listener.mListenerType == Listener::eWebIDLListener) {
|
|
|
|
mozilla::TraceScriptHolder(listener.mListener.GetWebIDLCallback(), aTrc);
|
|
|
|
}
|
|
|
|
// We might have eWrappedJSListener, but that is the legacy type for
|
|
|
|
// JS implemented event listeners, and trickier to handle here.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-17 13:16:20 +03:00
|
|
|
bool
|
|
|
|
EventListenerManager::HasApzAwareListeners()
|
|
|
|
{
|
|
|
|
uint32_t count = mListeners.Length();
|
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
|
|
|
Listener* listener = &mListeners.ElementAt(i);
|
2016-05-12 21:50:58 +03:00
|
|
|
if (IsApzAwareListener(listener)) {
|
2015-09-17 13:16:20 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-05-12 21:50:58 +03:00
|
|
|
bool
|
|
|
|
EventListenerManager::IsApzAwareListener(Listener* aListener)
|
|
|
|
{
|
|
|
|
return !aListener->mFlags.mPassive && IsApzAwareEvent(aListener->mTypeAtom);
|
|
|
|
}
|
|
|
|
|
2015-09-17 13:16:20 +03:00
|
|
|
bool
|
|
|
|
EventListenerManager::IsApzAwareEvent(nsIAtom* aEvent)
|
|
|
|
{
|
2016-05-24 18:24:31 +03:00
|
|
|
if (aEvent == nsGkAtoms::onwheel ||
|
|
|
|
aEvent == nsGkAtoms::onDOMMouseScroll ||
|
|
|
|
aEvent == nsHtml5Atoms::onmousewheel ||
|
|
|
|
aEvent == nsGkAtoms::onMozMousePixelScroll) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// In theory we should schedule a repaint if the touch event pref changes,
|
|
|
|
// because the event regions might be out of date. In practice that seems like
|
|
|
|
// overkill because users generally shouldn't be flipping this pref, much
|
|
|
|
// less expecting touch listeners on the page to immediately start preventing
|
|
|
|
// scrolling without so much as a repaint. Tests that we write can work
|
|
|
|
// around this constraint easily enough.
|
|
|
|
if (TouchEvent::PrefEnabled()) {
|
|
|
|
if (aEvent == nsGkAtoms::ontouchstart ||
|
|
|
|
aEvent == nsGkAtoms::ontouchmove) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2015-09-17 13:16:20 +03:00
|
|
|
}
|
|
|
|
|
2013-11-27 13:12:41 +04:00
|
|
|
already_AddRefed<nsIScriptGlobalObject>
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::GetScriptGlobalAndDocument(nsIDocument** aDoc)
|
2013-11-27 13:12:41 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsINode> node(do_QueryInterface(mTarget));
|
|
|
|
nsCOMPtr<nsIDocument> doc;
|
|
|
|
nsCOMPtr<nsIScriptGlobalObject> global;
|
|
|
|
if (node) {
|
|
|
|
// Try to get context from doc
|
|
|
|
// XXX sXBL/XBL2 issue -- do we really want the owner here? What
|
|
|
|
// if that's the XBL document?
|
|
|
|
doc = node->OwnerDoc();
|
2013-12-13 18:36:29 +04:00
|
|
|
if (doc->IsLoadedAsData()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2013-11-27 13:12:41 +04:00
|
|
|
|
|
|
|
// We want to allow compiling an event handler even in an unloaded
|
|
|
|
// document, so use GetScopeObject here, not GetScriptHandlingObject.
|
|
|
|
global = do_QueryInterface(doc->GetScopeObject());
|
|
|
|
} else {
|
2016-01-30 20:05:36 +03:00
|
|
|
if (nsCOMPtr<nsPIDOMWindowInner> win = GetTargetAsInnerWindow()) {
|
2013-11-27 13:12:41 +04:00
|
|
|
doc = win->GetExtantDoc();
|
|
|
|
global = do_QueryInterface(win);
|
|
|
|
} else {
|
|
|
|
global = do_QueryInterface(mTarget);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
doc.forget(aDoc);
|
|
|
|
return global.forget();
|
|
|
|
}
|
2014-03-17 10:56:53 +04:00
|
|
|
|
|
|
|
} // namespace mozilla
|