2001-09-25 05:32:19 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
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
|
|
|
|
|
2013-09-25 15:21:22 +04:00
|
|
|
#include "mozilla/BasicEvents.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"
|
2013-06-23 16:03:39 +04:00
|
|
|
#include "mozilla/MemoryReporting.h"
|
2014-03-17 10:56:53 +04:00
|
|
|
#include "mozilla/dom/BindingUtils.h"
|
|
|
|
#include "mozilla/dom/Element.h"
|
|
|
|
#include "mozilla/dom/Event.h"
|
|
|
|
|
|
|
|
#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"
|
|
|
|
#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 "nsIJSEventListener.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"
|
|
|
|
|
|
|
|
namespace mozilla {
|
2006-10-06 09:24:02 +04:00
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
using namespace dom;
|
|
|
|
using namespace hal;
|
2010-04-30 17:12:05 +04:00
|
|
|
|
2013-08-16 14:06:24 +04:00
|
|
|
#define EVENT_TYPE_EQUALS(ls, type, userType, typeString, allEvents) \
|
|
|
|
((ls->mEventType == type && \
|
|
|
|
(ls->mEventType != NS_USER_DEFINED_EVENT || \
|
|
|
|
(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
|
|
|
|
MutationBitForEventType(uint32_t aEventType)
|
2007-02-01 01:54:24 +03:00
|
|
|
{
|
|
|
|
switch (aEventType) {
|
|
|
|
case NS_MUTATION_SUBTREEMODIFIED:
|
|
|
|
return NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED;
|
|
|
|
case NS_MUTATION_NODEINSERTED:
|
|
|
|
return NS_EVENT_BITS_MUTATION_NODEINSERTED;
|
|
|
|
case NS_MUTATION_NODEREMOVED:
|
|
|
|
return NS_EVENT_BITS_MUTATION_NODEREMOVED;
|
|
|
|
case NS_MUTATION_NODEREMOVEDFROMDOCUMENT:
|
|
|
|
return NS_EVENT_BITS_MUTATION_NODEREMOVEDFROMDOCUMENT;
|
|
|
|
case NS_MUTATION_NODEINSERTEDINTODOCUMENT:
|
|
|
|
return NS_EVENT_BITS_MUTATION_NODEINSERTEDINTODOCUMENT;
|
|
|
|
case NS_MUTATION_ATTRMODIFIED:
|
|
|
|
return NS_EVENT_BITS_MUTATION_ATTRMODIFIED;
|
|
|
|
case NS_MUTATION_CHARACTERDATAMODIFIED:
|
|
|
|
return NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
uint32_t EventListenerManager::sMainThreadCreatedCount = 0;
|
|
|
|
|
|
|
|
EventListenerManager::EventListenerManager(EventTarget* aTarget)
|
|
|
|
: mMayHavePaintEventListener(false)
|
|
|
|
, mMayHaveMutationListeners(false)
|
|
|
|
, mMayHaveCapturingListeners(false)
|
|
|
|
, mMayHaveSystemGroupListeners(false)
|
|
|
|
, mMayHaveAudioAvailableEventListener(false)
|
|
|
|
, mMayHaveTouchEventListener(false)
|
|
|
|
, mMayHaveMouseEnterLeaveEventListener(false)
|
|
|
|
, mMayHavePointerEnterLeaveEventListener(false)
|
|
|
|
, mClearingListeners(false)
|
|
|
|
, mIsMainThreadELM(NS_IsMainThread())
|
|
|
|
, mNoListenerForEvent(0)
|
|
|
|
, 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
|
|
|
|
|
|
|
|
|
2008-10-16 01:06:32 +04:00
|
|
|
nsPIDOMWindow*
|
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
|
|
|
}
|
|
|
|
|
2012-10-01 13:43:53 +04:00
|
|
|
nsCOMPtr<nsPIDOMWindow> window = GetTargetAsInnerWindow();
|
|
|
|
return window;
|
2008-10-16 01:06:32 +04:00
|
|
|
}
|
|
|
|
|
2012-09-30 17:47:48 +04:00
|
|
|
already_AddRefed<nsPIDOMWindow>
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::GetTargetAsInnerWindow() const
|
2012-09-30 17:47:48 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mTarget);
|
|
|
|
if (!window) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_ASSERTION(window->IsInnerWindow(), "Target should not be an outer window");
|
|
|
|
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,
|
2014-03-17 10:56:53 +04:00
|
|
|
uint32_t aType,
|
|
|
|
nsIAtom* aTypeAtom,
|
|
|
|
const nsAString& aTypeString,
|
|
|
|
const EventListenerFlags& aFlags,
|
|
|
|
bool aHandler,
|
|
|
|
bool aAllEvents)
|
1998-06-07 11:55:55 +04:00
|
|
|
{
|
2013-08-16 14:06:24 +04:00
|
|
|
MOZ_ASSERT((NS_IsMainThread() && aType && aTypeAtom) || // Main thread
|
|
|
|
(!NS_IsMainThread() && aType && !aTypeString.IsEmpty()) || // non-main-thread
|
|
|
|
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 &&
|
|
|
|
listener->mFlags == aFlags &&
|
|
|
|
EVENT_TYPE_EQUALS(listener, aType, aTypeAtom, aTypeString,
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-24 14:04:16 +04:00
|
|
|
mNoListenerForEvent = NS_EVENT_NULL;
|
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;
|
2013-08-16 14:06:24 +04:00
|
|
|
MOZ_ASSERT(aType < PR_UINT16_MAX);
|
2014-03-17 10:56:51 +04:00
|
|
|
listener->mEventType = aType;
|
|
|
|
listener->mTypeString = aTypeString;
|
|
|
|
listener->mTypeAtom = aTypeAtom;
|
|
|
|
listener->mFlags = aFlags;
|
|
|
|
listener->mListenerIsHandler = aHandler;
|
|
|
|
listener->mHandlerIsString = false;
|
|
|
|
listener->mAllEvents = aAllEvents;
|
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
|
|
|
|
2008-10-16 01:06:32 +04:00
|
|
|
if (aType == NS_AFTERPAINT) {
|
2011-10-17 18:59:28 +04:00
|
|
|
mMayHavePaintEventListener = true;
|
2008-10-16 01:06:32 +04:00
|
|
|
nsPIDOMWindow* window = GetInnerWindowForTarget();
|
|
|
|
if (window) {
|
2008-10-16 01:24:19 +04:00
|
|
|
window->SetHasPaintEventListeners();
|
2008-10-16 01:06:32 +04:00
|
|
|
}
|
2010-08-25 17:10:00 +04:00
|
|
|
} else if (aType == NS_MOZAUDIOAVAILABLE) {
|
2011-10-17 18:59:28 +04:00
|
|
|
mMayHaveAudioAvailableEventListener = true;
|
2010-08-25 17:10:00 +04:00
|
|
|
nsPIDOMWindow* window = GetInnerWindowForTarget();
|
|
|
|
if (window) {
|
|
|
|
window->SetHasAudioAvailableEventListeners();
|
|
|
|
}
|
2008-10-16 01:06:32 +04:00
|
|
|
} else if (aType >= NS_MUTATION_START && aType <= NS_MUTATION_END) {
|
|
|
|
// 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.
|
2008-10-16 01:06:32 +04:00
|
|
|
nsPIDOMWindow* window = GetInnerWindowForTarget();
|
2006-10-06 09:24:02 +04:00
|
|
|
if (window) {
|
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);
|
|
|
|
}
|
2007-03-24 15:18:02 +03:00
|
|
|
// If aType is NS_MUTATION_SUBTREEMODIFIED, we need to listen all
|
2008-04-12 02:44:48 +04:00
|
|
|
// mutations. nsContentUtils::HasMutationListeners relies on this.
|
2007-03-24 15:18:02 +03:00
|
|
|
window->SetMutationListeners((aType == NS_MUTATION_SUBTREEMODIFIED) ?
|
|
|
|
kAllMutationBits :
|
|
|
|
MutationBitForEventType(aType));
|
2006-10-06 09:24:02 +04:00
|
|
|
}
|
2012-03-25 04:29:49 +04:00
|
|
|
} else if (aTypeAtom == nsGkAtoms::ondeviceorientation) {
|
2012-04-04 20:26:12 +04:00
|
|
|
EnableDevice(NS_DEVICE_ORIENTATION);
|
2012-05-17 00:27:54 +04:00
|
|
|
} else if (aTypeAtom == nsGkAtoms::ondeviceproximity || aTypeAtom == nsGkAtoms::onuserproximity) {
|
2012-05-02 20:43:45 +04:00
|
|
|
EnableDevice(NS_DEVICE_PROXIMITY);
|
2012-05-02 20:43:45 +04:00
|
|
|
} else if (aTypeAtom == nsGkAtoms::ondevicelight) {
|
|
|
|
EnableDevice(NS_DEVICE_LIGHT);
|
2012-03-25 04:29:49 +04:00
|
|
|
} else if (aTypeAtom == nsGkAtoms::ondevicemotion) {
|
2012-04-04 20:26:12 +04:00
|
|
|
EnableDevice(NS_DEVICE_MOTION);
|
2012-11-07 22:10:40 +04:00
|
|
|
#ifdef MOZ_B2G
|
2012-09-11 10:05:00 +04:00
|
|
|
} else if (aTypeAtom == nsGkAtoms::onmoztimechange) {
|
2012-10-01 13:43:53 +04:00
|
|
|
nsCOMPtr<nsPIDOMWindow> window = GetTargetAsInnerWindow();
|
|
|
|
if (window) {
|
|
|
|
window->EnableTimeChangeNotifications();
|
|
|
|
}
|
2012-09-30 17:47:48 +04:00
|
|
|
} else if (aTypeAtom == nsGkAtoms::onmoznetworkupload) {
|
|
|
|
nsCOMPtr<nsPIDOMWindow> window = GetTargetAsInnerWindow();
|
|
|
|
if (window) {
|
|
|
|
window->EnableNetworkEvent(NS_NETWORK_UPLOAD_EVENT);
|
|
|
|
}
|
|
|
|
} else if (aTypeAtom == nsGkAtoms::onmoznetworkdownload) {
|
|
|
|
nsCOMPtr<nsPIDOMWindow> window = GetTargetAsInnerWindow();
|
|
|
|
if (window) {
|
|
|
|
window->EnableNetworkEvent(NS_NETWORK_DOWNLOAD_EVENT);
|
|
|
|
}
|
2012-11-07 22:10:40 +04:00
|
|
|
#endif // MOZ_B2G
|
2012-09-22 23:28:08 +04:00
|
|
|
} else if (aTypeAtom == nsGkAtoms::ontouchstart ||
|
|
|
|
aTypeAtom == nsGkAtoms::ontouchend ||
|
|
|
|
aTypeAtom == nsGkAtoms::ontouchmove ||
|
|
|
|
aTypeAtom == nsGkAtoms::ontouchenter ||
|
|
|
|
aTypeAtom == nsGkAtoms::ontouchleave ||
|
|
|
|
aTypeAtom == nsGkAtoms::ontouchcancel) {
|
2011-10-17 18:59:28 +04:00
|
|
|
mMayHaveTouchEventListener = true;
|
2010-08-02 17:34:54 +04:00
|
|
|
nsPIDOMWindow* window = GetInnerWindowForTarget();
|
2012-07-09 20:55:37 +04:00
|
|
|
// we don't want touchevent listeners added by scrollbars to flip this flag
|
|
|
|
// so we ignore listeners created with system event flag
|
2012-12-16 05:26:05 +04:00
|
|
|
if (window && !aFlags.mInSystemGroup) {
|
2010-08-02 17:34:54 +04:00
|
|
|
window->SetHasTouchEventListeners();
|
2012-12-16 05:26:05 +04:00
|
|
|
}
|
2014-02-11 10:33:29 +04:00
|
|
|
} else if (aType >= NS_POINTER_EVENT_START && aType <= NS_POINTER_LOST_CAPTURE) {
|
|
|
|
nsPIDOMWindow* window = GetInnerWindowForTarget();
|
|
|
|
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;
|
2011-09-18 11:45:14 +04:00
|
|
|
nsPIDOMWindow* window = GetInnerWindowForTarget();
|
|
|
|
if (window) {
|
|
|
|
#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
|
|
|
|
} else if (aType >= NS_GAMEPAD_START &&
|
|
|
|
aType <= NS_GAMEPAD_END) {
|
|
|
|
nsPIDOMWindow* window = GetInnerWindowForTarget();
|
|
|
|
if (window) {
|
|
|
|
window->SetHasGamepadEventListener();
|
|
|
|
}
|
|
|
|
#endif
|
1999-03-29 02:22:54 +04:00
|
|
|
}
|
2013-05-23 15:41:00 +04:00
|
|
|
if (aTypeAtom && mTarget) {
|
|
|
|
mTarget->EventListenerAdded(aTypeAtom);
|
|
|
|
}
|
1998-06-07 11:55:55 +04:00
|
|
|
}
|
1999-03-29 02:22:54 +04:00
|
|
|
|
2012-03-29 21:23:27 +04:00
|
|
|
bool
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::IsDeviceType(uint32_t aType)
|
2012-03-29 21:23:27 +04:00
|
|
|
{
|
|
|
|
switch (aType) {
|
|
|
|
case NS_DEVICE_ORIENTATION:
|
|
|
|
case NS_DEVICE_MOTION:
|
2012-06-04 20:17:16 +04:00
|
|
|
case NS_DEVICE_LIGHT:
|
|
|
|
case NS_DEVICE_PROXIMITY:
|
|
|
|
case NS_USER_PROXIMITY:
|
2012-03-29 21:23:27 +04:00
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-04-04 20:26:12 +04:00
|
|
|
void
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::EnableDevice(uint32_t aType)
|
2012-04-04 20:26:12 +04:00
|
|
|
{
|
2012-10-01 13:43:53 +04:00
|
|
|
nsCOMPtr<nsPIDOMWindow> window = GetTargetAsInnerWindow();
|
2012-04-04 20:26:12 +04:00
|
|
|
if (!window) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (aType) {
|
|
|
|
case NS_DEVICE_ORIENTATION:
|
|
|
|
window->EnableDeviceSensor(SENSOR_ORIENTATION);
|
|
|
|
break;
|
2012-05-02 20:43:45 +04:00
|
|
|
case NS_DEVICE_PROXIMITY:
|
2012-05-17 00:27:54 +04:00
|
|
|
case NS_USER_PROXIMITY:
|
2012-05-02 20:43:45 +04:00
|
|
|
window->EnableDeviceSensor(SENSOR_PROXIMITY);
|
|
|
|
break;
|
2012-05-02 20:43:45 +04:00
|
|
|
case NS_DEVICE_LIGHT:
|
|
|
|
window->EnableDeviceSensor(SENSOR_LIGHT);
|
|
|
|
break;
|
2012-04-04 20:26:12 +04:00
|
|
|
case NS_DEVICE_MOTION:
|
|
|
|
window->EnableDeviceSensor(SENSOR_ACCELERATION);
|
|
|
|
window->EnableDeviceSensor(SENSOR_LINEAR_ACCELERATION);
|
|
|
|
window->EnableDeviceSensor(SENSOR_GYROSCOPE);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
NS_WARNING("Enabling an unknown device sensor.");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-29 21:23:27 +04:00
|
|
|
void
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::DisableDevice(uint32_t aType)
|
2012-03-29 21:23:27 +04:00
|
|
|
{
|
2012-10-01 13:43:53 +04:00
|
|
|
nsCOMPtr<nsPIDOMWindow> window = GetTargetAsInnerWindow();
|
2012-03-29 21:23:27 +04:00
|
|
|
if (!window) {
|
|
|
|
return;
|
|
|
|
}
|
2012-04-04 20:26:12 +04:00
|
|
|
|
2012-03-29 21:23:27 +04:00
|
|
|
switch (aType) {
|
|
|
|
case NS_DEVICE_ORIENTATION:
|
|
|
|
window->DisableDeviceSensor(SENSOR_ORIENTATION);
|
|
|
|
break;
|
|
|
|
case NS_DEVICE_MOTION:
|
|
|
|
window->DisableDeviceSensor(SENSOR_ACCELERATION);
|
|
|
|
window->DisableDeviceSensor(SENSOR_LINEAR_ACCELERATION);
|
|
|
|
window->DisableDeviceSensor(SENSOR_GYROSCOPE);
|
|
|
|
break;
|
2012-05-02 20:43:45 +04:00
|
|
|
case NS_DEVICE_PROXIMITY:
|
2012-05-17 00:27:54 +04:00
|
|
|
case NS_USER_PROXIMITY:
|
2012-05-02 20:43:45 +04:00
|
|
|
window->DisableDeviceSensor(SENSOR_PROXIMITY);
|
|
|
|
break;
|
2012-05-02 20:43:45 +04:00
|
|
|
case NS_DEVICE_LIGHT:
|
|
|
|
window->DisableDeviceSensor(SENSOR_LIGHT);
|
|
|
|
break;
|
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,
|
2014-03-17 10:56:53 +04:00
|
|
|
uint32_t aType,
|
|
|
|
nsIAtom* aUserType,
|
|
|
|
const nsAString& aTypeString,
|
|
|
|
const EventListenerFlags& aFlags,
|
|
|
|
bool aAllEvents)
|
1999-03-29 02:22:54 +04:00
|
|
|
{
|
2014-03-17 10:56:53 +04:00
|
|
|
if (!aListenerHolder || !aType || 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;
|
2012-04-04 20:26:12 +04:00
|
|
|
bool deviceType = IsDeviceType(aType);
|
2012-11-07 22:10:40 +04:00
|
|
|
#ifdef MOZ_B2G
|
2012-09-11 10:05:00 +04:00
|
|
|
bool timeChangeEvent = (aType == NS_MOZ_TIME_CHANGE_EVENT);
|
2012-09-30 17:47:48 +04:00
|
|
|
bool networkEvent = (aType == NS_NETWORK_UPLOAD_EVENT ||
|
|
|
|
aType == NS_NETWORK_DOWNLOAD_EVENT);
|
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);
|
|
|
|
if (EVENT_TYPE_EQUALS(listener, aType, aUserType, aTypeString,
|
|
|
|
aAllEvents)) {
|
2012-03-29 21:23:27 +04:00
|
|
|
++typeCount;
|
2014-03-17 10:56:53 +04:00
|
|
|
if (listener->mListener == aListenerHolder &&
|
2014-03-17 10:56:51 +04:00
|
|
|
listener->mFlags.EqualsIgnoringTrustness(aFlags)) {
|
2014-03-17 10:56:53 +04:00
|
|
|
nsRefPtr<EventListenerManager> kungFuDeathGrip(this);
|
2012-03-29 21:23:27 +04:00
|
|
|
mListeners.RemoveElementAt(i);
|
|
|
|
--count;
|
2013-09-24 14:04:16 +04:00
|
|
|
mNoListenerForEvent = NS_EVENT_NULL;
|
2012-07-30 18:20:58 +04:00
|
|
|
mNoListenerForEventAtom = nullptr;
|
2013-05-23 15:41:00 +04:00
|
|
|
if (mTarget && aUserType) {
|
|
|
|
mTarget->EventListenerRemoved(aUserType);
|
|
|
|
}
|
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) {
|
2012-03-29 21:23:27 +04:00
|
|
|
DisableDevice(aType);
|
2012-11-07 22:10:40 +04:00
|
|
|
#ifdef MOZ_B2G
|
2012-09-11 10:05:00 +04:00
|
|
|
} else if (timeChangeEvent && typeCount == 0) {
|
2012-10-01 13:43:53 +04:00
|
|
|
nsCOMPtr<nsPIDOMWindow> window = GetTargetAsInnerWindow();
|
|
|
|
if (window) {
|
|
|
|
window->DisableTimeChangeNotifications();
|
|
|
|
}
|
2012-11-01 16:42:29 +04:00
|
|
|
} else if (!aAllEvents && networkEvent && typeCount == 0) {
|
2012-09-30 17:47:48 +04:00
|
|
|
nsCOMPtr<nsPIDOMWindow> window = GetTargetAsInnerWindow();
|
|
|
|
if (window) {
|
|
|
|
window->DisableNetworkEvent(aType);
|
|
|
|
}
|
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
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::ListenerCanHandle(Listener* aListener,
|
|
|
|
WidgetEvent* aEvent)
|
2006-10-06 09:24:02 +04:00
|
|
|
{
|
2011-08-08 22:26:26 +04:00
|
|
|
// This is slightly different from EVENT_TYPE_EQUALS in that it returns
|
|
|
|
// true even when aEvent->message == NS_USER_DEFINED_EVENT and
|
2014-03-17 10:56:51 +04:00
|
|
|
// aListener=>mEventType != NS_USER_DEFINED_EVENT as long as the atoms are
|
|
|
|
// the same
|
|
|
|
if (aListener->mAllEvents) {
|
2013-08-16 14:06:24 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (aEvent->message == NS_USER_DEFINED_EVENT) {
|
|
|
|
if (mIsMainThreadELM) {
|
2014-03-17 10:56:51 +04:00
|
|
|
return aListener->mTypeAtom == aEvent->userType;
|
2013-08-16 14:06:24 +04:00
|
|
|
}
|
2014-03-17 10:56:51 +04:00
|
|
|
return aListener->mTypeString.Equals(aEvent->typeString);
|
2013-08-16 14:06:24 +04:00
|
|
|
}
|
2013-12-21 04:22:13 +04:00
|
|
|
MOZ_ASSERT(mIsMainThreadELM);
|
2014-03-17 10:56:51 +04:00
|
|
|
return aListener->mEventType == aEvent->message;
|
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
|
|
|
{
|
2013-08-16 14:06:24 +04:00
|
|
|
nsCOMPtr<nsIAtom> atom =
|
|
|
|
mIsMainThreadELM ? do_GetAtom(NS_LITERAL_STRING("on") + aType) : nullptr;
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t type = nsContentUtils::GetEventId(atom);
|
2014-03-17 10:56:53 +04:00
|
|
|
AddEventListenerInternal(aListenerHolder, type, 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
|
|
|
{
|
2013-08-16 14:06:24 +04:00
|
|
|
nsCOMPtr<nsIAtom> atom =
|
|
|
|
mIsMainThreadELM ? do_GetAtom(NS_LITERAL_STRING("on") + aType) : nullptr;
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t type = nsContentUtils::GetEventId(atom);
|
2014-03-17 10:56:53 +04:00
|
|
|
RemoveEventListenerInternal(aListenerHolder, type, atom, aType, aFlags);
|
1999-03-29 02:22:54 +04:00
|
|
|
}
|
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::Listener*
|
|
|
|
EventListenerManager::FindEventHandler(uint32_t aEventType,
|
|
|
|
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 &&
|
|
|
|
EVENT_TYPE_EQUALS(listener, aEventType, aTypeAtom, aTypeString,
|
|
|
|
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(
|
|
|
|
JS::Handle<JSObject*> aScopeObject,
|
|
|
|
nsIAtom* aName,
|
|
|
|
const nsAString& aTypeString,
|
|
|
|
const nsEventHandler& aHandler,
|
|
|
|
bool aPermitUntrustedEvents)
|
1999-11-25 03:05:21 +03:00
|
|
|
{
|
2013-11-27 13:12:41 +04:00
|
|
|
MOZ_ASSERT(aScopeObject || aHandler.HasEventHandler(),
|
2013-09-17 15:01:28 +04:00
|
|
|
"Must have one or the other!");
|
|
|
|
MOZ_ASSERT(aName || !aTypeString.IsEmpty());
|
2012-08-31 07:45:16 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t eventType = nsContentUtils::GetEventId(aName);
|
2014-03-17 10:56:51 +04:00
|
|
|
Listener* listener = FindEventHandler(eventType, 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-03-17 10:56:53 +04:00
|
|
|
nsCOMPtr<nsIJSEventListener> jsListener;
|
2013-11-27 13:12:41 +04:00
|
|
|
NS_NewJSEventListener(aScopeObject, mTarget, aName,
|
2014-03-17 10:56:53 +04:00
|
|
|
aHandler, getter_AddRefs(jsListener));
|
|
|
|
EventListenerHolder listenerHolder(jsListener);
|
|
|
|
AddEventListenerInternal(listenerHolder, eventType, aName, aTypeString,
|
|
|
|
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
|
|
|
|
2014-03-17 10:56:51 +04:00
|
|
|
listener = FindEventHandler(eventType, aName, aTypeString);
|
2011-08-24 23:49:25 +04:00
|
|
|
} else {
|
2014-03-17 10:56:53 +04:00
|
|
|
nsIJSEventListener* jsListener = listener->GetJSListener();
|
|
|
|
MOZ_ASSERT(jsListener,
|
2012-11-09 20:00:25 +04:00
|
|
|
"How can we have an event handler with no nsIJSEventListener?");
|
2012-08-31 07:45:16 +04:00
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
bool same = jsListener->GetHandler() == aHandler;
|
2013-05-24 21:22:20 +04:00
|
|
|
// Possibly the same listener, but update still the context and scope.
|
2014-03-17 10:56:53 +04:00
|
|
|
jsListener->SetHandler(aHandler, aScopeObject);
|
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);
|
|
|
|
}
|
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-03-17 10:56:51 +04:00
|
|
|
listener->mHandlerIsString = !aHandler.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,
|
|
|
|
uint32_t aLanguage,
|
|
|
|
bool aDeferCompilation,
|
|
|
|
bool aPermitUntrustedEvents,
|
|
|
|
Element* aElement)
|
1998-07-31 22:21:37 +04:00
|
|
|
{
|
2006-06-13 07:07:47 +04:00
|
|
|
NS_PRECONDITION(aLanguage != nsIProgrammingLanguage::UNKNOWN,
|
|
|
|
"Must know the language for the script event listener");
|
|
|
|
|
|
|
|
// |aPermitUntrustedEvents| is set to False for chrome - events
|
|
|
|
// *generated* from an unknown source are not allowed.
|
|
|
|
// However, for script languages with no 'sandbox', we want to reject
|
|
|
|
// such scripts based on the source of their code, not just the source
|
|
|
|
// of the event.
|
|
|
|
if (aPermitUntrustedEvents &&
|
|
|
|
aLanguage != nsIProgrammingLanguage::JAVASCRIPT) {
|
|
|
|
NS_WARNING("Discarding non-JS event listener from untrusted source");
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2004-02-10 01:48:53 +03: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
|
|
|
|
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(global);
|
|
|
|
if (win) {
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
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) {
|
2012-10-16 00:54:58 +04:00
|
|
|
bool inlineOK = true;
|
|
|
|
bool reportViolations = false;
|
|
|
|
rv = csp->GetAllowsInlineScript(&reportViolations, &inlineOK);
|
2010-02-24 00:20:46 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2012-10-16 00:54:58 +04:00
|
|
|
if (reportViolations) {
|
2011-01-31 21:09:44 +03:00
|
|
|
// gather information to log with violation report
|
|
|
|
nsIURI* uri = doc->GetDocumentURI();
|
2012-09-02 06:35:17 +04:00
|
|
|
nsAutoCString asciiSpec;
|
2011-01-31 21:09:44 +03:00
|
|
|
if (uri)
|
|
|
|
uri->GetAsciiSpec(asciiSpec);
|
|
|
|
nsAutoString scriptSample, attr, tagName(NS_LITERAL_STRING("UNKNOWN"));
|
|
|
|
aName->ToString(attr);
|
2011-07-29 23:37:17 +04:00
|
|
|
nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mTarget));
|
2011-01-31 21:09:44 +03:00
|
|
|
if (domNode)
|
|
|
|
domNode->GetNodeName(tagName);
|
|
|
|
// 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");
|
|
|
|
csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_INLINE_SCRIPT,
|
|
|
|
NS_ConvertUTF8toUTF16(asciiSpec),
|
|
|
|
scriptSample,
|
2013-11-09 03:44:39 +04:00
|
|
|
0,
|
2014-01-02 23:14:06 +04:00
|
|
|
EmptyString(),
|
2013-11-09 03:44:39 +04:00
|
|
|
EmptyString());
|
2012-10-16 00:54:58 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// return early if CSP wants us to block inline scripts
|
|
|
|
if (!inlineOK) {
|
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);
|
2004-02-10 01:48:53 +03:00
|
|
|
|
2014-01-06 17:36:10 +04:00
|
|
|
NS_ENSURE_STATE(global->GetGlobalJSObject());
|
|
|
|
|
2013-06-20 22:05:34 +04:00
|
|
|
JSAutoRequest ar(context->GetNativeContext());
|
2013-05-04 11:52:57 +04:00
|
|
|
JS::Rooted<JSObject*> scope(context->GetNativeContext(),
|
|
|
|
global->GetGlobalJSObject());
|
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
|
|
|
Listener* listener = SetEventHandlerInternal(scope, aName,
|
|
|
|
EmptyString(),
|
|
|
|
nsEventHandler(),
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t eventType = nsContentUtils::GetEventId(aName);
|
2014-03-17 10:56:51 +04:00
|
|
|
Listener* listener = FindEventHandler(eventType, 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)));
|
2013-09-24 14:04:16 +04:00
|
|
|
mNoListenerForEvent = NS_EVENT_NULL;
|
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);
|
|
|
|
}
|
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-03-22 06:31:02 +04:00
|
|
|
MOZ_ASSERT(aListener->GetJSListener());
|
|
|
|
MOZ_ASSERT(aListener->mHandlerIsString, "Why are we compiling a non-string JS listener?");
|
2014-03-17 10:56:51 +04:00
|
|
|
nsIJSEventListener* jsListener = aListener->GetJSListener();
|
2014-03-22 06:31:02 +04:00
|
|
|
MOZ_ASSERT(!jsListener->GetHandler().HasEventHandler(), "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);
|
|
|
|
|
|
|
|
nsIScriptContext* context = global->GetScriptContext();
|
|
|
|
NS_ENSURE_STATE(context);
|
|
|
|
|
2013-12-14 06:22:18 +04:00
|
|
|
// Push a context to make sure exceptions are reported in the right place.
|
2014-03-19 15:08:13 +04:00
|
|
|
AutoPushJSContextForErrorReporting cx(context->GetNativeContext());
|
2013-03-21 00:09:09 +04:00
|
|
|
JS::Rooted<JSObject*> handler(cx);
|
2014-03-17 10:56:51 +04:00
|
|
|
JS::Rooted<JSObject*> scope(cx, jsListener->GetEventScope());
|
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
|
|
|
|
// the nsIJSEventListener itself, and that still doesn't address
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t argCount;
|
|
|
|
const char **argNames;
|
|
|
|
nsContentUtils::GetEventArgNames(aElement->GetNameSpaceID(),
|
|
|
|
typeAtom,
|
|
|
|
&argCount, &argNames);
|
|
|
|
|
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.
|
|
|
|
JS::Rooted<JSObject*> wrapScope(cx, context->GetWindowProxy());
|
|
|
|
JS::Rooted<JS::Value> v(cx);
|
|
|
|
{
|
|
|
|
JSAutoCompartment ac(cx, wrapScope);
|
|
|
|
nsresult rv = nsContentUtils::WrapNative(cx, wrapScope, mTarget, &v,
|
|
|
|
/* aAllowWrapping = */ false);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
JS::Rooted<JSObject*> target(cx, &v.toObject());
|
|
|
|
JSAutoCompartment ac(cx, target);
|
|
|
|
|
|
|
|
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.
|
|
|
|
if (NS_WARN_IF(!WrapNewBindingObject(cx, target, aElement, &v))) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2014-03-22 06:31:02 +04:00
|
|
|
JS::CompileOptions options(cx);
|
|
|
|
options.setIntroductionType("eventHandler")
|
|
|
|
.setFileAndLine(url.get(), lineNo)
|
2014-03-22 06:31:02 +04:00
|
|
|
.setVersion(SCRIPTVERSION_DEFAULT)
|
|
|
|
.setElement(&v.toObject())
|
|
|
|
.setElementAttributeName(jsStr);
|
2014-03-22 06:31:02 +04:00
|
|
|
|
|
|
|
JS::Rooted<JSObject*> handlerFun(cx);
|
|
|
|
result = nsJSUtils::CompileFunction(cx, JS::NullPtr(), options,
|
|
|
|
nsAtomCString(typeAtom),
|
|
|
|
argCount, argNames, *body, handlerFun.address());
|
|
|
|
NS_ENSURE_SUCCESS(result, result);
|
|
|
|
handler = handlerFun;
|
|
|
|
NS_ENSURE_TRUE(handler, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mTarget);
|
|
|
|
// Bind it
|
|
|
|
JS::Rooted<JSObject*> boundHandler(cx);
|
|
|
|
context->BindCompiledEventHandler(mTarget, scope, handler, &boundHandler);
|
|
|
|
// Note - We pass null for aIncumbentGlobal below. We could also pass the
|
|
|
|
// compilation global, but since the handler is guaranteed to be scripted,
|
|
|
|
// there's no need to use an override, since the JS engine will always give
|
|
|
|
// us the right answer.
|
|
|
|
if (!boundHandler) {
|
|
|
|
jsListener->ForgetHandler();
|
|
|
|
} else if (jsListener->EventName() == nsGkAtoms::onerror && win) {
|
|
|
|
nsRefPtr<OnErrorEventHandlerNonNull> handlerCallback =
|
|
|
|
new OnErrorEventHandlerNonNull(boundHandler, /* aIncumbentGlobal = */ nullptr);
|
|
|
|
jsListener->SetHandler(handlerCallback);
|
|
|
|
} else if (jsListener->EventName() == nsGkAtoms::onbeforeunload && win) {
|
|
|
|
nsRefPtr<OnBeforeUnloadEventHandlerNonNull> handlerCallback =
|
|
|
|
new OnBeforeUnloadEventHandlerNonNull(boundHandler, /* aIncumbentGlobal = */ nullptr);
|
|
|
|
jsListener->SetHandler(handlerCallback);
|
2014-03-05 17:16:42 +04:00
|
|
|
} else {
|
2014-03-22 06:31:02 +04:00
|
|
|
nsRefPtr<EventHandlerNonNull> handlerCallback =
|
|
|
|
new EventHandlerNonNull(boundHandler, /* aIncumbentGlobal = */ nullptr);
|
|
|
|
jsListener->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);
|
|
|
|
result = rv.ErrorCode();
|
|
|
|
} 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
|
|
|
}
|
|
|
|
|
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
|
|
|
|
if (*aEventStatus == nsEventStatus_eConsumeNoDefault) {
|
2012-12-16 05:26:04 +04:00
|
|
|
aEvent->mFlags.mDefaultPrevented = true;
|
2000-09-15 10:11:15 +04:00
|
|
|
}
|
1998-06-07 11:55:55 +04:00
|
|
|
|
2014-03-17 10:56:51 +04:00
|
|
|
nsAutoTObserverArray<Listener, 2>::EndLimitedIterator iter(mListeners);
|
2013-11-05 18:16:26 +04:00
|
|
|
Maybe<nsAutoPopupStatePusher> popupStatePusher;
|
|
|
|
if (mIsMainThreadELM) {
|
2014-03-05 04:37:43 +04:00
|
|
|
popupStatePusher.construct(Event::GetEventPopupControlState(aEvent));
|
2013-11-05 18:16:26 +04:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool hasListener = false;
|
2007-12-20 10:30:04 +03:00
|
|
|
while (iter.HasMore()) {
|
2012-12-16 05:26:03 +04:00
|
|
|
if (aEvent->mFlags.mImmediatePropagationStopped) {
|
2011-11-04 21:17:19 +04:00
|
|
|
break;
|
|
|
|
}
|
2014-03-17 10:56:51 +04:00
|
|
|
Listener* listener = &iter.GetNext();
|
2006-10-06 09:24:02 +04:00
|
|
|
// Check that the phase is same in event and event listener.
|
|
|
|
// Handle only trusted events, except when listener permits untrusted events.
|
2014-03-17 10:56:51 +04:00
|
|
|
if (ListenerCanHandle(listener, aEvent)) {
|
2011-10-17 18:59:28 +04:00
|
|
|
hasListener = true;
|
2014-03-17 10:56:51 +04:00
|
|
|
if (listener->IsListening(aEvent) &&
|
|
|
|
(aEvent->mFlags.mIsTrusted ||
|
|
|
|
listener->mFlags.mAllowUntrustedEvents)) {
|
2011-08-08 22:26:26 +04:00
|
|
|
if (!*aDOMEvent) {
|
2013-03-09 15:34:29 +04:00
|
|
|
// This is tiny bit slow, but happens only once per event.
|
2014-03-17 10:56:53 +04:00
|
|
|
nsCOMPtr<EventTarget> et =
|
2013-03-09 15:34:29 +04:00
|
|
|
do_QueryInterface(aEvent->originalTarget);
|
2014-03-18 08:48:21 +04:00
|
|
|
EventDispatcher::CreateEvent(et, aPresContext,
|
|
|
|
aEvent, EmptyString(), aDOMEvent);
|
2011-08-08 22:26:26 +04:00
|
|
|
}
|
|
|
|
if (*aDOMEvent) {
|
|
|
|
if (!aEvent->currentTarget) {
|
|
|
|
aEvent->currentTarget = aCurrentTarget->GetTargetForDOMEvent();
|
2009-06-15 14:21:06 +04:00
|
|
|
if (!aEvent->currentTarget) {
|
2011-08-08 22:26:26 +04:00
|
|
|
break;
|
2009-06-15 14:21:06 +04:00
|
|
|
}
|
2011-08-08 22:26:26 +04:00
|
|
|
}
|
2012-06-29 01:47:56 +04:00
|
|
|
|
2014-03-17 10:56:51 +04:00
|
|
|
if (NS_FAILED(HandleEventSubType(listener, *aDOMEvent,
|
|
|
|
aCurrentTarget))) {
|
2012-12-16 05:26:04 +04:00
|
|
|
aEvent->mFlags.mExceptionHasBeenRisen = true;
|
2005-04-29 03:48:28 +04:00
|
|
|
}
|
2000-11-27 10:55:20 +03:00
|
|
|
}
|
|
|
|
}
|
2003-09-11 10:31:58 +04:00
|
|
|
}
|
1998-06-07 11:55:55 +04:00
|
|
|
}
|
2000-11-08 03:31:06 +03:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
aEvent->currentTarget = nullptr;
|
2009-06-15 14:21:06 +04:00
|
|
|
|
2013-09-27 01:59:27 +04:00
|
|
|
if (mIsMainThreadELM && !hasListener) {
|
2006-10-06 09:24:02 +04:00
|
|
|
mNoListenerForEvent = aEvent->message;
|
|
|
|
mNoListenerForEventAtom = aEvent->userType;
|
|
|
|
}
|
|
|
|
|
2012-12-16 05:26:04 +04:00
|
|
|
if (aEvent->mFlags.mDefaultPrevented) {
|
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
|
|
|
}
|
|
|
|
|
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
|
|
|
|
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
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
AddEventListenerInternal(listenerHolder, NS_EVENT_ALL, 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);
|
|
|
|
RemoveEventListenerInternal(listenerHolder, NS_EVENT_ALL, nullptr,
|
|
|
|
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);
|
|
|
|
if (listener->mEventType >= NS_MUTATION_START &&
|
|
|
|
listener->mEventType <= NS_MUTATION_END) {
|
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);
|
|
|
|
if (listener->mEventType >= NS_MUTATION_START &&
|
|
|
|
listener->mEventType <= NS_MUTATION_END) {
|
|
|
|
if (listener->mEventType == NS_MUTATION_SUBTREEMODIFIED) {
|
2007-03-24 15:18:02 +03:00
|
|
|
return kAllMutationBits;
|
|
|
|
}
|
2014-03-17 10:56:51 +04:00
|
|
|
bits |= MutationBitForEventType(listener->mEventType);
|
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
|
|
|
{
|
|
|
|
nsCOMPtr<nsIAtom> atom = do_GetAtom(NS_LITERAL_STRING("on") + aEventName);
|
2012-08-17 18:12:58 +04:00
|
|
|
return HasListenersFor(atom);
|
|
|
|
}
|
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...
|
2014-03-17 10:56:50 +04:00
|
|
|
nsRefPtr<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);
|
|
|
|
if (listener->mEventType == NS_PAGE_UNLOAD ||
|
|
|
|
listener->mEventType == NS_BEFORE_PAGE_UNLOAD) {
|
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.
|
2013-11-27 13:12:41 +04:00
|
|
|
SetEventHandlerInternal(JS::NullPtr(), aEventName,
|
2013-09-17 15:01:28 +04:00
|
|
|
aTypeString, nsEventHandler(aHandler),
|
|
|
|
!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.
|
2013-11-27 13:12:41 +04:00
|
|
|
SetEventHandlerInternal(JS::NullPtr(), nsGkAtoms::onerror,
|
2013-11-05 18:16:26 +04:00
|
|
|
EmptyString(), nsEventHandler(aHandler),
|
|
|
|
!nsContentUtils::IsCallerChrome());
|
|
|
|
} else {
|
|
|
|
if (!aHandler) {
|
|
|
|
RemoveEventHandler(nullptr, NS_LITERAL_STRING("error"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Untrusted events are always permitted.
|
2013-11-27 13:12:41 +04:00
|
|
|
SetEventHandlerInternal(JS::NullPtr(), nullptr,
|
2013-11-05 18:16:26 +04:00
|
|
|
NS_LITERAL_STRING("error"),
|
|
|
|
nsEventHandler(aHandler), true);
|
|
|
|
}
|
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.
|
2013-11-27 13:12:41 +04:00
|
|
|
SetEventHandlerInternal(JS::NullPtr(), nsGkAtoms::onbeforeunload,
|
2013-09-17 15:01:28 +04:00
|
|
|
EmptyString(), nsEventHandler(aHandler),
|
|
|
|
!mIsMainThreadELM ||
|
|
|
|
!nsContentUtils::IsCallerChrome());
|
2012-11-09 20:00:25 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
const nsEventHandler*
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager::GetEventHandlerInternal(nsIAtom* aEventName,
|
|
|
|
const nsAString& aTypeString)
|
2011-08-24 23:49:25 +04:00
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t eventType = nsContentUtils::GetEventId(aEventName);
|
2014-03-17 10:56:51 +04:00
|
|
|
Listener* listener = FindEventHandler(eventType, 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-03-17 10:56:51 +04:00
|
|
|
nsIJSEventListener* jsListener = listener->GetJSListener();
|
|
|
|
|
|
|
|
if (listener->mHandlerIsString) {
|
|
|
|
CompileEventHandlerInternal(listener, nullptr, nullptr);
|
2011-08-24 23:49:25 +04:00
|
|
|
}
|
|
|
|
|
2014-03-17 10:56:51 +04:00
|
|
|
const nsEventHandler& handler = jsListener->GetHandler();
|
2012-11-09 20:00:25 +04:00
|
|
|
if (handler.HasEventHandler()) {
|
2012-11-09 20:00:25 +04:00
|
|
|
return &handler;
|
2012-11-09 20:00:25 +04:00
|
|
|
}
|
2012-11-09 20:00:25 +04:00
|
|
|
|
|
|
|
return 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);
|
|
|
|
n += mListeners.SizeOfExcludingThis(aMallocSizeOf);
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t count = mListeners.Length();
|
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
2012-02-02 01:58:01 +04:00
|
|
|
nsIJSEventListener* jsl = mListeners.ElementAt(i).GetJSListener();
|
2011-08-27 02:39:00 +04:00
|
|
|
if (jsl) {
|
2012-02-02 01:58:01 +04:00
|
|
|
n += jsl->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-03-17 10:56:53 +04:00
|
|
|
nsIJSEventListener* jsListener = listener.GetJSListener();
|
|
|
|
if (jsListener) {
|
|
|
|
if (jsListener->GetHandler().HasEventHandler()) {
|
|
|
|
JS::ExposeObjectToActiveJS(jsListener->GetHandler().Ptr()->Callable());
|
2013-09-09 07:28:48 +04:00
|
|
|
}
|
2014-03-17 10:56:53 +04:00
|
|
|
if (JSObject* scope = jsListener->GetEventScope()) {
|
2013-09-09 07:28:48 +04:00
|
|
|
JS::ExposeObjectToActiveJS(scope);
|
2012-11-09 20:00:25 +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) {
|
2013-04-17 01:15:57 +04:00
|
|
|
// Callback() unmarks gray
|
2014-03-17 10:56:51 +04:00
|
|
|
listener.mListener.GetWebIDLCallback()->Callback();
|
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
|
|
|
|
|
|
|
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 {
|
|
|
|
nsCOMPtr<nsPIDOMWindow> win = GetTargetAsInnerWindow();
|
|
|
|
if (win) {
|
|
|
|
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
|