Files
palemoon27/dom/events/DOMEventTargetHelper.cpp
T
roytam1 5c3e1ed7ef import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1255818. Switch from JS_ClearPendingException to AutoJSAPI::ClearException for cases when we have an AutoJSAPI around. r=bholley (e1e0413493)
- Bug 1253591. HTMLAllCollection should be rooted at the document, not the root element, so it can find the root element. r=peterv (c5f2f253a9)
- Bug 1257270 - Use std::nullptr_t instead of nullptr_t in WMFUtils.h. r=cpearce (539e705876)
- Bug 1251881 - use UniquePtr instead of ScopedDeletePtr in mozglue/linker/; r=glandium (2fe329e32c)
- Bug 1219068 - Compute size correctly when a character consists entirely of glue. r=karlt (80f2e23268)
- Bug 1246132 - Improve register allocation speed on large functions, r=sunfish. (6e023c252b)
- Bug 1150354: Make nsPluginDirServiceProvider build with MSVC 2015 CTP 6, r=jmathies (0113760730)
- Bug 1197311 - Remove PR_snprintf calls in dom/ r=froydnj (6268400ef0)
- Bug 1255099 - XHR CTOR doesn't need to use implicitJSContext, r=bz (72f08fbc36)
- Bug 1255597 - Part 1: Remove redundent trailing spaces. r=khuey (7f2240cb05)
- Bug 1255597 - Part 2: Follow spec to modify the content-type check conditions which determine parsing XHR body or not. r=khuey (ba6f7fc536)
- Bug 1255597 - Part 3: Synchronize content-type hint of HttpChannelChild to HttpChannelParent. r=jduell (bb97478b01)
- Bug 1255597 - Part 4: Remove 'expected fail' settings and expect test cases in responsexml-media-type.htm should be passed. r=khuey (772884b4fb)
- Bug 1201170 - During message diversion must be possible to suspend them. r=jduell (abb2361b7f)
- Bug 1201174 - For FTP - in case of divertToParent, it myst be possible to delay delivering of OnDataAv./OnStopR. r=jduell (9299ef81be)
- Bug 1247393 - use arrays of UniquePtr in ChannelEventQueue; r=mcmanus (7621205b53)
- Bug 1254730 - ChannelEventQueue must be thread-safe, r=michal (b8e01204e9)
- Bug 1254859 part 2. Switch the AutoEntryScript in nsXULTemplateBuilder::InitHTMLTemplateRoot to take ownership of error reporting. r=bholley (f183ec692c)
- Bug 1254859 part 1. Switch the AutoEntryScript in nsGlobalWindow::FireOnNewGlobalObject to take ownership of error reporting. r=bholley (b0cd891917)
- Bug 1254860. Switch the AutoEntryScript TestShellCommandParent::RunCallback to taking ownership of error reporting. r=bholley (0c9697e60f)
- Bug 1254857. Switch the AutoEntryScript in xpc::EvalInSandbox to take ownership of error reporting. r=bholley (93b6bfc87c)
- Bug 1254847 part 3. Make AutoEntryScript always take ownership of error reporting. r=bholley (3c2929462f)
- Bug 1256688 - Continue using getPropertyDescriptor for has in Sandbox창. r=peterv (be7e50b715)
- Bug 1254730 - patch 2 - Better comments and a better management of lifetime of ChannelEvents, r=michal (8348911e35)
- Bug 1163198 - Remove instances of #ifdef PR_LOGGING in dom/plugins. r=froydnj (ba13039dfa)
- Bug 1253216 - clean up the atomic ops ifdef nest. r=jorendorff (6ca747d3cf)
- Bug 1257055 - Use jit/arm64/Architecture-arm64.h on non-JIT aarch64. r=lth (4f3949cd19)
- Bug 1253379 - Cache timings not send to HttpChannelChild r=mayhemer (395172278f)
- align SetAllowStaleCacheContent to FF52, possible misspatch (9d29d27011)
2024-03-19 22:11:27 +08:00

387 lines
12 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsContentUtils.h"
#include "nsIDocument.h"
#include "mozilla/Snprintf.h"
#include "nsGlobalWindow.h"
#include "ScriptSettings.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/Likely.h"
namespace mozilla {
using namespace dom;
NS_IMPL_CYCLE_COLLECTION_CLASS(DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(DOMEventTargetHelper)
if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
char name[512];
nsAutoString uri;
if (tmp->mOwnerWindow && tmp->mOwnerWindow->GetExtantDoc()) {
tmp->mOwnerWindow->GetExtantDoc()->GetDocumentURI(uri);
}
snprintf_literal(name, "DOMEventTargetHelper %s",
NS_ConvertUTF16toUTF8(uri).get());
cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
} else {
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(DOMEventTargetHelper, tmp->mRefCnt.get())
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListenerManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK(mListenerManager)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(DOMEventTargetHelper)
if (tmp->IsBlack() || tmp->IsCertainlyAliveForCC()) {
if (tmp->mListenerManager) {
tmp->mListenerManager->MarkForCC();
}
if (!tmp->IsBlack() && tmp->PreservingWrapper()) {
// This marks the wrapper black.
tmp->GetWrapper();
}
return true;
}
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(DOMEventTargetHelper)
return tmp->IsBlackAndDoesNotNeedTracing(tmp);
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(DOMEventTargetHelper)
return tmp->IsBlack();
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMEventTargetHelper)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
NS_INTERFACE_MAP_ENTRY(dom::EventTarget)
NS_INTERFACE_MAP_ENTRY(DOMEventTargetHelper)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(DOMEventTargetHelper,
LastRelease())
NS_IMPL_DOMTARGET_DEFAULTS(DOMEventTargetHelper)
DOMEventTargetHelper::~DOMEventTargetHelper()
{
if (nsPIDOMWindow* owner = GetOwner()) {
static_cast<nsGlobalWindow*>(owner)->RemoveEventTargetObject(this);
}
if (mListenerManager) {
mListenerManager->Disconnect();
}
ReleaseWrapper(this);
}
void
DOMEventTargetHelper::BindToOwner(nsPIDOMWindow* aOwner)
{
MOZ_ASSERT_IF(aOwner, aOwner->IsInnerWindow());
nsCOMPtr<nsIGlobalObject> glob = do_QueryInterface(aOwner);
BindToOwner(glob);
}
void
DOMEventTargetHelper::BindToOwner(nsIGlobalObject* aOwner)
{
nsCOMPtr<nsIGlobalObject> parentObject = do_QueryReferent(mParentObject);
if (parentObject) {
if (mOwnerWindow) {
static_cast<nsGlobalWindow*>(mOwnerWindow)->RemoveEventTargetObject(this);
mOwnerWindow = nullptr;
}
mParentObject = nullptr;
mHasOrHasHadOwnerWindow = false;
}
if (aOwner) {
mParentObject = do_GetWeakReference(aOwner);
MOZ_ASSERT(mParentObject, "All nsIGlobalObjects must support nsISupportsWeakReference");
// Let's cache the result of this QI for fast access and off main thread usage
mOwnerWindow = nsCOMPtr<nsPIDOMWindow>(do_QueryInterface(aOwner)).get();
if (mOwnerWindow) {
MOZ_ASSERT(mOwnerWindow->IsInnerWindow());
mHasOrHasHadOwnerWindow = true;
static_cast<nsGlobalWindow*>(mOwnerWindow)->AddEventTargetObject(this);
}
}
}
void
DOMEventTargetHelper::BindToOwner(DOMEventTargetHelper* aOther)
{
if (mOwnerWindow) {
static_cast<nsGlobalWindow*>(mOwnerWindow)->RemoveEventTargetObject(this);
mOwnerWindow = nullptr;
mParentObject = nullptr;
mHasOrHasHadOwnerWindow = false;
}
if (aOther) {
mHasOrHasHadOwnerWindow = aOther->HasOrHasHadOwner();
if (aOther->GetParentObject()) {
mParentObject = do_GetWeakReference(aOther->GetParentObject());
MOZ_ASSERT(mParentObject, "All nsIGlobalObjects must support nsISupportsWeakReference");
// Let's cache the result of this QI for fast access and off main thread usage
mOwnerWindow = nsCOMPtr<nsPIDOMWindow>(do_QueryInterface(aOther->GetParentObject())).get();
if (mOwnerWindow) {
MOZ_ASSERT(mOwnerWindow->IsInnerWindow());
mHasOrHasHadOwnerWindow = true;
static_cast<nsGlobalWindow*>(mOwnerWindow)->AddEventTargetObject(this);
}
}
}
}
void
DOMEventTargetHelper::DisconnectFromOwner()
{
mOwnerWindow = nullptr;
mParentObject = nullptr;
// Event listeners can't be handled anymore, so we can release them here.
if (mListenerManager) {
mListenerManager->Disconnect();
mListenerManager = nullptr;
}
}
NS_IMETHODIMP
DOMEventTargetHelper::RemoveEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture)
{
EventListenerManager* elm = GetExistingListenerManager();
if (elm) {
elm->RemoveEventListener(aType, aListener, aUseCapture);
}
return NS_OK;
}
NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(DOMEventTargetHelper)
NS_IMETHODIMP
DOMEventTargetHelper::AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture,
bool aWantsUntrusted,
uint8_t aOptionalArgc)
{
NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
"Won't check if this is chrome, you want to set "
"aWantsUntrusted to false or make the aWantsUntrusted "
"explicit by making aOptionalArgc non-zero.");
if (aOptionalArgc < 2) {
nsresult rv = WantsUntrusted(&aWantsUntrusted);
NS_ENSURE_SUCCESS(rv, rv);
}
EventListenerManager* elm = GetOrCreateListenerManager();
NS_ENSURE_STATE(elm);
elm->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted);
return NS_OK;
}
void
DOMEventTargetHelper::AddEventListener(const nsAString& aType,
EventListener* aListener,
bool aUseCapture,
const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv)
{
bool wantsUntrusted;
if (aWantsUntrusted.IsNull()) {
nsresult rv = WantsUntrusted(&wantsUntrusted);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return;
}
} else {
wantsUntrusted = aWantsUntrusted.Value();
}
EventListenerManager* elm = GetOrCreateListenerManager();
if (!elm) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
elm->AddEventListener(aType, aListener, aUseCapture, wantsUntrusted);
}
NS_IMETHODIMP
DOMEventTargetHelper::AddSystemEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture,
bool aWantsUntrusted,
uint8_t aOptionalArgc)
{
NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
"Won't check if this is chrome, you want to set "
"aWantsUntrusted to false or make the aWantsUntrusted "
"explicit by making aOptionalArgc non-zero.");
if (aOptionalArgc < 2) {
nsresult rv = WantsUntrusted(&aWantsUntrusted);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_AddSystemEventListener(this, aType, aListener, aUseCapture,
aWantsUntrusted);
}
NS_IMETHODIMP
DOMEventTargetHelper::DispatchEvent(nsIDOMEvent* aEvent, bool* aRetVal)
{
nsEventStatus status = nsEventStatus_eIgnore;
nsresult rv =
EventDispatcher::DispatchDOMEvent(this, nullptr, aEvent, nullptr, &status);
*aRetVal = (status != nsEventStatus_eConsumeNoDefault);
return rv;
}
nsresult
DOMEventTargetHelper::DispatchTrustedEvent(const nsAString& aEventName)
{
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
event->InitEvent(aEventName, false, false);
return DispatchTrustedEvent(event);
}
nsresult
DOMEventTargetHelper::DispatchTrustedEvent(nsIDOMEvent* event)
{
event->SetTrusted(true);
bool dummy;
return DispatchEvent(event, &dummy);
}
nsresult
DOMEventTargetHelper::SetEventHandler(nsIAtom* aType,
JSContext* aCx,
const JS::Value& aValue)
{
RefPtr<EventHandlerNonNull> handler;
JS::Rooted<JSObject*> callable(aCx);
if (aValue.isObject() && JS::IsCallable(callable = &aValue.toObject())) {
handler = new EventHandlerNonNull(aCx, callable, dom::GetIncumbentGlobal());
}
SetEventHandler(aType, EmptyString(), handler);
return NS_OK;
}
void
DOMEventTargetHelper::GetEventHandler(nsIAtom* aType,
JSContext* aCx,
JS::Value* aValue)
{
EventHandlerNonNull* handler = GetEventHandler(aType, EmptyString());
if (handler) {
*aValue = JS::ObjectValue(*handler->Callable());
} else {
*aValue = JS::NullValue();
}
}
nsresult
DOMEventTargetHelper::PreHandleEvent(EventChainPreVisitor& aVisitor)
{
aVisitor.mCanHandle = true;
aVisitor.mParentTarget = nullptr;
return NS_OK;
}
nsresult
DOMEventTargetHelper::PostHandleEvent(EventChainPostVisitor& aVisitor)
{
return NS_OK;
}
nsresult
DOMEventTargetHelper::DispatchDOMEvent(WidgetEvent* aEvent,
nsIDOMEvent* aDOMEvent,
nsPresContext* aPresContext,
nsEventStatus* aEventStatus)
{
return EventDispatcher::DispatchDOMEvent(this, aEvent, aDOMEvent,
aPresContext, aEventStatus);
}
EventListenerManager*
DOMEventTargetHelper::GetOrCreateListenerManager()
{
if (!mListenerManager) {
mListenerManager = new EventListenerManager(this);
}
return mListenerManager;
}
EventListenerManager*
DOMEventTargetHelper::GetExistingListenerManager() const
{
return mListenerManager;
}
nsIScriptContext*
DOMEventTargetHelper::GetContextForEventHandlers(nsresult* aRv)
{
*aRv = CheckInnerWindowCorrectness();
if (NS_FAILED(*aRv)) {
return nullptr;
}
nsPIDOMWindow* owner = GetOwner();
return owner ? static_cast<nsGlobalWindow*>(owner)->GetContextInternal()
: nullptr;
}
nsresult
DOMEventTargetHelper::WantsUntrusted(bool* aRetVal)
{
nsresult rv;
nsIScriptContext* context = GetContextForEventHandlers(&rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDocument> doc =
nsContentUtils::GetDocumentFromScriptContext(context);
// We can let listeners on workers to always handle all the events.
*aRetVal = (doc && !nsContentUtils::IsChromeDoc(doc)) || !NS_IsMainThread();
return rv;
}
void
DOMEventTargetHelper::EventListenerAdded(nsIAtom* aType)
{
ErrorResult rv;
EventListenerWasAdded(Substring(nsDependentAtomString(aType), 2), rv);
}
void
DOMEventTargetHelper::EventListenerRemoved(nsIAtom* aType)
{
ErrorResult rv;
EventListenerWasRemoved(Substring(nsDependentAtomString(aType), 2), rv);
}
} // namespace mozilla