|
Packit |
f0b94e |
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
Packit |
f0b94e |
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
Packit |
f0b94e |
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
Packit |
f0b94e |
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
Packit |
f0b94e |
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
#include "EventListenerService.h"
|
|
Packit |
f0b94e |
#include "mozilla/BasicEvents.h"
|
|
Packit |
f0b94e |
#include "mozilla/EventDispatcher.h"
|
|
Packit |
f0b94e |
#include "mozilla/EventListenerManager.h"
|
|
Packit |
f0b94e |
#include "mozilla/JSEventHandler.h"
|
|
Packit |
f0b94e |
#include "mozilla/Maybe.h"
|
|
Packit |
f0b94e |
#include "nsArrayUtils.h"
|
|
Packit |
f0b94e |
#include "nsCOMArray.h"
|
|
Packit |
f0b94e |
#include "nsDOMClassInfoID.h"
|
|
Packit |
f0b94e |
#include "nsIXPConnect.h"
|
|
Packit |
f0b94e |
#include "nsJSUtils.h"
|
|
Packit |
f0b94e |
#include "nsMemory.h"
|
|
Packit |
f0b94e |
#include "nsServiceManagerUtils.h"
|
|
Packit |
f0b94e |
#include "nsArray.h"
|
|
Packit |
f0b94e |
#include "nsThreadUtils.h"
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
namespace mozilla {
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
using namespace dom;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/******************************************************************************
|
|
Packit |
f0b94e |
* mozilla::EventListenerChange
|
|
Packit |
f0b94e |
******************************************************************************/
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMPL_ISUPPORTS(EventListenerChange, nsIEventListenerChange)
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
EventListenerChange::~EventListenerChange() {}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
EventListenerChange::EventListenerChange(dom::EventTarget* aTarget)
|
|
Packit |
f0b94e |
: mTarget(aTarget) {}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void EventListenerChange::AddChangedListenerName(nsAtom* aEventName) {
|
|
Packit |
f0b94e |
mChangedListenerNames.AppendElement(aEventName);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
EventListenerChange::GetTarget(nsIDOMEventTarget** aTarget) {
|
|
Packit |
f0b94e |
NS_ENSURE_ARG_POINTER(aTarget);
|
|
Packit |
f0b94e |
NS_ADDREF(*aTarget = mTarget);
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
EventListenerChange::GetCountOfEventListenerChangesAffectingAccessibility(
|
|
Packit |
f0b94e |
uint32_t* aCount) {
|
|
Packit |
f0b94e |
*aCount = 0;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
size_t length = mChangedListenerNames.Length();
|
|
Packit |
f0b94e |
for (size_t i = 0; i < length; i++) {
|
|
Packit |
f0b94e |
RefPtr<nsAtom> listenerName = mChangedListenerNames[i];
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// These are the event listener changes which may make an element
|
|
Packit |
f0b94e |
// accessible or inaccessible.
|
|
Packit |
f0b94e |
if (listenerName == nsGkAtoms::onclick ||
|
|
Packit |
f0b94e |
listenerName == nsGkAtoms::onmousedown ||
|
|
Packit |
f0b94e |
listenerName == nsGkAtoms::onmouseup) {
|
|
Packit |
f0b94e |
*aCount += 1;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/******************************************************************************
|
|
Packit |
f0b94e |
* mozilla::EventListenerInfo
|
|
Packit |
f0b94e |
******************************************************************************/
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMPL_CYCLE_COLLECTION(EventListenerInfo, mListener)
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EventListenerInfo)
|
|
Packit |
f0b94e |
NS_INTERFACE_MAP_ENTRY(nsIEventListenerInfo)
|
|
Packit |
f0b94e |
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
Packit |
f0b94e |
NS_INTERFACE_MAP_END
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMPL_CYCLE_COLLECTING_ADDREF(EventListenerInfo)
|
|
Packit |
f0b94e |
NS_IMPL_CYCLE_COLLECTING_RELEASE(EventListenerInfo)
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
EventListenerInfo::GetType(nsAString& aType) {
|
|
Packit |
f0b94e |
aType = mType;
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
EventListenerInfo::GetCapturing(bool* aCapturing) {
|
|
Packit |
f0b94e |
*aCapturing = mCapturing;
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
EventListenerInfo::GetAllowsUntrusted(bool* aAllowsUntrusted) {
|
|
Packit |
f0b94e |
*aAllowsUntrusted = mAllowsUntrusted;
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
EventListenerInfo::GetInSystemEventGroup(bool* aInSystemEventGroup) {
|
|
Packit |
f0b94e |
*aInSystemEventGroup = mInSystemEventGroup;
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
EventListenerInfo::GetListenerObject(JSContext* aCx,
|
|
Packit |
f0b94e |
JS::MutableHandle<JS::Value> aObject) {
|
|
Packit |
f0b94e |
Maybe<JSAutoCompartment> ac;
|
|
Packit |
f0b94e |
GetJSVal(aCx, ac, aObject);
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/******************************************************************************
|
|
Packit |
f0b94e |
* mozilla::EventListenerService
|
|
Packit |
f0b94e |
******************************************************************************/
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMPL_ISUPPORTS(EventListenerService, nsIEventListenerService)
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
bool EventListenerInfo::GetJSVal(JSContext* aCx, Maybe<JSAutoCompartment>& aAc,
|
|
Packit |
f0b94e |
JS::MutableHandle<JS::Value> aJSVal) {
|
|
Packit |
f0b94e |
aJSVal.setNull();
|
|
Packit |
f0b94e |
nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS = do_QueryInterface(mListener);
|
|
Packit |
f0b94e |
if (wrappedJS) {
|
|
Packit |
f0b94e |
JS::Rooted<JSObject*> object(aCx, wrappedJS->GetJSObject());
|
|
Packit |
f0b94e |
if (!object) {
|
|
Packit |
f0b94e |
return false;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
aAc.emplace(aCx, object);
|
|
Packit |
f0b94e |
aJSVal.setObject(*object);
|
|
Packit |
f0b94e |
return true;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
nsCOMPtr<JSEventHandler> jsHandler = do_QueryInterface(mListener);
|
|
Packit |
f0b94e |
if (jsHandler && jsHandler->GetTypedEventHandler().HasEventHandler()) {
|
|
Packit |
f0b94e |
JS::Handle<JSObject*> handler =
|
|
Packit |
f0b94e |
jsHandler->GetTypedEventHandler().Ptr()->CallableOrNull();
|
|
Packit |
f0b94e |
if (handler) {
|
|
Packit |
f0b94e |
aAc.emplace(aCx, handler);
|
|
Packit |
f0b94e |
aJSVal.setObject(*handler);
|
|
Packit |
f0b94e |
return true;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
return false;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
EventListenerInfo::ToSource(nsAString& aResult) {
|
|
Packit |
f0b94e |
aResult.SetIsVoid(true);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
AutoSafeJSContext cx;
|
|
Packit |
f0b94e |
Maybe<JSAutoCompartment> ac;
|
|
Packit |
f0b94e |
JS::Rooted<JS::Value> v(cx);
|
|
Packit |
f0b94e |
if (GetJSVal(cx, ac, &v)) {
|
|
Packit |
f0b94e |
JSString* str = JS_ValueToSource(cx, v);
|
|
Packit |
f0b94e |
if (str) {
|
|
Packit |
f0b94e |
nsAutoJSString autoStr;
|
|
Packit |
f0b94e |
if (autoStr.init(cx, str)) {
|
|
Packit |
f0b94e |
aResult.Assign(autoStr);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
EventListenerService* EventListenerService::sInstance = nullptr;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
EventListenerService::EventListenerService() {
|
|
Packit |
f0b94e |
MOZ_ASSERT(!sInstance);
|
|
Packit |
f0b94e |
sInstance = this;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
EventListenerService::~EventListenerService() {
|
|
Packit |
f0b94e |
MOZ_ASSERT(sInstance == this);
|
|
Packit |
f0b94e |
sInstance = nullptr;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
EventListenerService::GetListenerInfoFor(nsIDOMEventTarget* aEventTarget,
|
|
Packit |
f0b94e |
uint32_t* aCount,
|
|
Packit |
f0b94e |
nsIEventListenerInfo*** aOutArray) {
|
|
Packit |
f0b94e |
NS_ENSURE_ARG_POINTER(aEventTarget);
|
|
Packit |
f0b94e |
*aCount = 0;
|
|
Packit |
f0b94e |
*aOutArray = nullptr;
|
|
Packit |
f0b94e |
nsCOMArray<nsIEventListenerInfo> listenerInfos;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aEventTarget);
|
|
Packit |
f0b94e |
NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
EventListenerManager* elm = eventTarget->GetExistingListenerManager();
|
|
Packit |
f0b94e |
if (elm) {
|
|
Packit |
f0b94e |
elm->GetListenerInfo(&listenerInfos);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
int32_t count = listenerInfos.Count();
|
|
Packit |
f0b94e |
if (count == 0) {
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
listenerInfos.Forget(aOutArray);
|
|
Packit |
f0b94e |
*aCount = count;
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
EventListenerService::GetEventTargetChainFor(nsIDOMEventTarget* aEventTarget,
|
|
Packit |
f0b94e |
bool aComposed, uint32_t* aCount,
|
|
Packit |
f0b94e |
nsIDOMEventTarget*** aOutArray) {
|
|
Packit |
f0b94e |
*aCount = 0;
|
|
Packit |
f0b94e |
*aOutArray = nullptr;
|
|
Packit |
f0b94e |
NS_ENSURE_ARG(aEventTarget);
|
|
Packit |
f0b94e |
WidgetEvent event(true, eVoidEvent);
|
|
Packit |
f0b94e |
event.SetComposed(aComposed);
|
|
Packit |
f0b94e |
nsTArray<EventTarget*> targets;
|
|
Packit |
f0b94e |
nsresult rv = EventDispatcher::Dispatch(aEventTarget, nullptr, &event,
|
|
Packit |
f0b94e |
nullptr, nullptr, nullptr, &targets;;
|
|
Packit |
f0b94e |
NS_ENSURE_SUCCESS(rv, rv);
|
|
Packit |
f0b94e |
int32_t count = targets.Length();
|
|
Packit |
f0b94e |
if (count == 0) {
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
*aOutArray = static_cast<nsIDOMEventTarget**>(
|
|
Packit |
f0b94e |
moz_xmalloc(sizeof(nsIDOMEventTarget*) * count));
|
|
Packit |
f0b94e |
NS_ENSURE_TRUE(*aOutArray, NS_ERROR_OUT_OF_MEMORY);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
for (int32_t i = 0; i < count; ++i) {
|
|
Packit |
f0b94e |
NS_ADDREF((*aOutArray)[i] = targets[i]);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
*aCount = count;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
EventListenerService::HasListenersFor(nsIDOMEventTarget* aEventTarget,
|
|
Packit |
f0b94e |
const nsAString& aType, bool* aRetVal) {
|
|
Packit |
f0b94e |
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aEventTarget);
|
|
Packit |
f0b94e |
NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
EventListenerManager* elm = eventTarget->GetExistingListenerManager();
|
|
Packit |
f0b94e |
*aRetVal = elm && elm->HasListenersFor(aType);
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
EventListenerService::AddSystemEventListener(nsIDOMEventTarget* aTarget,
|
|
Packit |
f0b94e |
const nsAString& aType,
|
|
Packit |
f0b94e |
nsIDOMEventListener* aListener,
|
|
Packit |
f0b94e |
bool aUseCapture) {
|
|
Packit |
f0b94e |
NS_PRECONDITION(aTarget, "Missing target");
|
|
Packit |
f0b94e |
NS_PRECONDITION(aListener, "Missing listener");
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
|
|
Packit |
f0b94e |
NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
EventListenerManager* manager = eventTarget->GetOrCreateListenerManager();
|
|
Packit |
f0b94e |
NS_ENSURE_STATE(manager);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
EventListenerFlags flags = aUseCapture ? TrustedEventsAtSystemGroupCapture()
|
|
Packit |
f0b94e |
: TrustedEventsAtSystemGroupBubble();
|
|
Packit |
f0b94e |
manager->AddEventListenerByType(aListener, aType, flags);
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
EventListenerService::RemoveSystemEventListener(nsIDOMEventTarget* aTarget,
|
|
Packit |
f0b94e |
const nsAString& aType,
|
|
Packit |
f0b94e |
nsIDOMEventListener* aListener,
|
|
Packit |
f0b94e |
bool aUseCapture) {
|
|
Packit |
f0b94e |
NS_PRECONDITION(aTarget, "Missing target");
|
|
Packit |
f0b94e |
NS_PRECONDITION(aListener, "Missing listener");
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
|
|
Packit |
f0b94e |
NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
EventListenerManager* manager = eventTarget->GetExistingListenerManager();
|
|
Packit |
f0b94e |
if (manager) {
|
|
Packit |
f0b94e |
EventListenerFlags flags = aUseCapture ? TrustedEventsAtSystemGroupCapture()
|
|
Packit |
f0b94e |
: TrustedEventsAtSystemGroupBubble();
|
|
Packit |
f0b94e |
manager->RemoveEventListenerByType(aListener, aType, flags);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
EventListenerService::AddListenerForAllEvents(nsIDOMEventTarget* aTarget,
|
|
Packit |
f0b94e |
nsIDOMEventListener* aListener,
|
|
Packit |
f0b94e |
bool aUseCapture,
|
|
Packit |
f0b94e |
bool aWantsUntrusted,
|
|
Packit |
f0b94e |
bool aSystemEventGroup) {
|
|
Packit |
f0b94e |
NS_ENSURE_STATE(aTarget && aListener);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
|
|
Packit |
f0b94e |
NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
EventListenerManager* manager = eventTarget->GetOrCreateListenerManager();
|
|
Packit |
f0b94e |
NS_ENSURE_STATE(manager);
|
|
Packit |
f0b94e |
manager->AddListenerForAllEvents(aListener, aUseCapture, aWantsUntrusted,
|
|
Packit |
f0b94e |
aSystemEventGroup);
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
EventListenerService::RemoveListenerForAllEvents(nsIDOMEventTarget* aTarget,
|
|
Packit |
f0b94e |
nsIDOMEventListener* aListener,
|
|
Packit |
f0b94e |
bool aUseCapture,
|
|
Packit |
f0b94e |
bool aSystemEventGroup) {
|
|
Packit |
f0b94e |
NS_ENSURE_STATE(aTarget && aListener);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
|
|
Packit |
f0b94e |
NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
EventListenerManager* manager = eventTarget->GetExistingListenerManager();
|
|
Packit |
f0b94e |
if (manager) {
|
|
Packit |
f0b94e |
manager->RemoveListenerForAllEvents(aListener, aUseCapture,
|
|
Packit |
f0b94e |
aSystemEventGroup);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
EventListenerService::AddListenerChangeListener(
|
|
Packit |
f0b94e |
nsIListenerChangeListener* aListener) {
|
|
Packit |
f0b94e |
if (!mChangeListeners.Contains(aListener)) {
|
|
Packit |
f0b94e |
mChangeListeners.AppendElement(aListener);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
EventListenerService::RemoveListenerChangeListener(
|
|
Packit |
f0b94e |
nsIListenerChangeListener* aListener) {
|
|
Packit |
f0b94e |
mChangeListeners.RemoveElement(aListener);
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void EventListenerService::NotifyAboutMainThreadListenerChangeInternal(
|
|
Packit |
f0b94e |
dom::EventTarget* aTarget, nsAtom* aName) {
|
|
Packit |
f0b94e |
MOZ_ASSERT(NS_IsMainThread());
|
|
Packit |
f0b94e |
MOZ_ASSERT(aTarget);
|
|
Packit |
f0b94e |
if (mChangeListeners.IsEmpty()) {
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (!mPendingListenerChanges) {
|
|
Packit |
f0b94e |
mPendingListenerChanges = nsArrayBase::Create();
|
|
Packit |
f0b94e |
nsCOMPtr<nsIRunnable> runnable =
|
|
Packit |
f0b94e |
NewRunnableMethod("EventListenerService::NotifyPendingChanges", this,
|
|
Packit |
f0b94e |
&EventListenerService::NotifyPendingChanges);
|
|
Packit |
f0b94e |
if (nsCOMPtr<nsIGlobalObject> global = aTarget->GetOwnerGlobal()) {
|
|
Packit |
f0b94e |
global->Dispatch(TaskCategory::Other, runnable.forget());
|
|
Packit |
f0b94e |
} else if (nsCOMPtr<nsINode> node = do_QueryInterface(aTarget)) {
|
|
Packit |
f0b94e |
node->OwnerDoc()->Dispatch(TaskCategory::Other, runnable.forget());
|
|
Packit |
f0b94e |
} else {
|
|
Packit |
f0b94e |
NS_DispatchToCurrentThread(runnable);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
RefPtr<EventListenerChange> changes =
|
|
Packit |
f0b94e |
mPendingListenerChangesSet.LookupForAdd(aTarget).OrInsert(
|
|
Packit |
f0b94e |
[this, aTarget]() {
|
|
Packit |
f0b94e |
EventListenerChange* c = new EventListenerChange(aTarget);
|
|
Packit |
f0b94e |
mPendingListenerChanges->AppendElement(c);
|
|
Packit |
f0b94e |
return c;
|
|
Packit |
f0b94e |
});
|
|
Packit |
f0b94e |
changes->AddChangedListenerName(aName);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void EventListenerService::NotifyPendingChanges() {
|
|
Packit |
f0b94e |
nsCOMPtr<nsIMutableArray> changes;
|
|
Packit |
f0b94e |
mPendingListenerChanges.swap(changes);
|
|
Packit |
f0b94e |
mPendingListenerChangesSet.Clear();
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
nsTObserverArray<nsCOMPtr<nsIListenerChangeListener>>::EndLimitedIterator
|
|
Packit |
f0b94e |
iter(mChangeListeners);
|
|
Packit |
f0b94e |
while (iter.HasMore()) {
|
|
Packit |
f0b94e |
nsCOMPtr<nsIListenerChangeListener> listener = iter.GetNext();
|
|
Packit |
f0b94e |
listener->ListenersChanged(changes);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
} // namespace mozilla
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
nsresult NS_NewEventListenerService(nsIEventListenerService** aResult) {
|
|
Packit |
f0b94e |
*aResult = new mozilla::EventListenerService();
|
|
Packit |
f0b94e |
NS_ADDREF(*aResult);
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|