2015-05-03 22:32:37 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2009-06-15 12:27:29 +04:00
|
|
|
|
|
|
|
#include "nsContentUtils.h"
|
2019-01-02 16:05:23 +03:00
|
|
|
#include "mozilla/dom/Document.h"
|
2016-08-15 09:43:21 +03:00
|
|
|
#include "mozilla/Sprintf.h"
|
2012-03-13 04:56:07 +04:00
|
|
|
#include "nsGlobalWindow.h"
|
2018-04-20 19:55:30 +03:00
|
|
|
#include "mozilla/dom/Event.h"
|
2017-05-08 09:24:22 +03:00
|
|
|
#include "mozilla/dom/ScriptSettings.h"
|
2014-04-01 10:13:50 +04:00
|
|
|
#include "mozilla/DOMEventTargetHelper.h"
|
2014-03-18 08:48:21 +04:00
|
|
|
#include "mozilla/EventDispatcher.h"
|
2014-03-17 10:56:53 +04:00
|
|
|
#include "mozilla/EventListenerManager.h"
|
2012-10-26 17:32:10 +04:00
|
|
|
#include "mozilla/Likely.h"
|
2009-06-15 12:27:29 +04:00
|
|
|
|
2014-04-01 10:13:50 +04:00
|
|
|
namespace mozilla {
|
2012-11-09 20:00:25 +04:00
|
|
|
|
2014-04-01 10:13:50 +04:00
|
|
|
using namespace dom;
|
2013-08-02 05:29:05 +04:00
|
|
|
|
2014-04-01 10:13:50 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(DOMEventTargetHelper)
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMEventTargetHelper)
|
2012-02-08 06:53:33 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
|
|
|
|
2014-04-01 10:13:50 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(DOMEventTargetHelper)
|
2012-10-26 17:32:10 +04:00
|
|
|
if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
|
2012-02-12 17:09:18 +04:00
|
|
|
char name[512];
|
|
|
|
nsAutoString uri;
|
2013-04-24 08:22:37 +04:00
|
|
|
if (tmp->mOwnerWindow && tmp->mOwnerWindow->GetExtantDoc()) {
|
2016-09-20 15:03:05 +03:00
|
|
|
Unused << tmp->mOwnerWindow->GetExtantDoc()->GetDocumentURI(uri);
|
2012-02-12 17:09:18 +04:00
|
|
|
}
|
2016-05-12 20:54:34 +03:00
|
|
|
|
|
|
|
nsXPCOMCycleCollectionParticipant* participant = nullptr;
|
|
|
|
CallQueryInterface(tmp, &participant);
|
|
|
|
|
2016-08-15 09:44:00 +03:00
|
|
|
SprintfLiteral(name, "%s %s", participant->ClassName(),
|
|
|
|
NS_ConvertUTF16toUTF8(uri).get());
|
2012-08-27 21:41:04 +04:00
|
|
|
cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
|
2012-02-12 17:09:18 +04:00
|
|
|
} else {
|
2014-04-01 10:13:50 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(DOMEventTargetHelper, tmp->mRefCnt.get())
|
2012-02-12 17:09:18 +04:00
|
|
|
}
|
|
|
|
|
2012-11-15 11:32:40 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListenerManager)
|
2009-06-15 12:27:29 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
|
2014-04-01 10:13:50 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMEventTargetHelper)
|
2012-02-08 06:53:33 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
2019-11-03 03:03:12 +03:00
|
|
|
if (tmp->mListenerManager) {
|
|
|
|
tmp->mListenerManager->Disconnect();
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mListenerManager)
|
|
|
|
}
|
2017-04-18 14:51:27 +03:00
|
|
|
tmp->MaybeDontKeepAlive();
|
2009-06-15 12:27:29 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
|
2014-04-01 10:13:50 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(DOMEventTargetHelper)
|
2017-01-25 04:40:11 +03:00
|
|
|
bool hasLiveWrapper = tmp->HasKnownLiveWrapper();
|
|
|
|
if (hasLiveWrapper || tmp->IsCertainlyAliveForCC()) {
|
2012-09-24 15:05:30 +04:00
|
|
|
if (tmp->mListenerManager) {
|
2012-10-17 05:22:02 +04:00
|
|
|
tmp->mListenerManager->MarkForCC();
|
2012-09-24 15:05:30 +04:00
|
|
|
}
|
2017-01-25 04:40:11 +03:00
|
|
|
if (!hasLiveWrapper && tmp->PreservingWrapper()) {
|
2017-01-25 04:33:54 +03:00
|
|
|
tmp->MarkWrapperLive();
|
2015-06-29 19:42:41 +03:00
|
|
|
}
|
2012-09-24 15:05:30 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
|
|
|
|
|
2014-04-01 10:13:50 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(DOMEventTargetHelper)
|
2017-01-25 04:39:37 +03:00
|
|
|
return tmp->HasKnownLiveWrapperAndDoesNotNeedTracing(tmp);
|
2012-09-24 15:05:30 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
|
|
|
|
|
2014-04-01 10:13:50 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(DOMEventTargetHelper)
|
2017-01-25 04:38:58 +03:00
|
|
|
return tmp->HasKnownLiveWrapper();
|
2012-09-24 15:05:30 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
|
|
|
|
|
2014-04-01 10:13:50 +04:00
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMEventTargetHelper)
|
2012-02-08 06:53:33 +04:00
|
|
|
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
2011-06-24 06:18:01 +04:00
|
|
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
2014-04-01 10:13:50 +04:00
|
|
|
NS_INTERFACE_MAP_ENTRY(dom::EventTarget)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(DOMEventTargetHelper)
|
2009-06-15 12:27:29 +04:00
|
|
|
NS_INTERFACE_MAP_END
|
|
|
|
|
2014-04-01 10:13:50 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMEventTargetHelper)
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(DOMEventTargetHelper,
|
2013-07-09 21:30:58 +04:00
|
|
|
LastRelease())
|
2009-06-15 12:27:29 +04:00
|
|
|
|
2014-04-01 10:13:50 +04:00
|
|
|
DOMEventTargetHelper::~DOMEventTargetHelper() {
|
2018-02-21 21:53:22 +03:00
|
|
|
if (mParentObject) {
|
|
|
|
mParentObject->RemoveEventTargetObject(this);
|
2012-03-13 04:56:07 +04:00
|
|
|
}
|
2011-12-08 12:31:14 +04:00
|
|
|
if (mListenerManager) {
|
|
|
|
mListenerManager->Disconnect();
|
|
|
|
}
|
2013-08-02 11:04:01 +04:00
|
|
|
ReleaseWrapper(this);
|
2011-12-08 12:31:14 +04:00
|
|
|
}
|
|
|
|
|
2014-04-01 10:13:50 +04:00
|
|
|
void DOMEventTargetHelper::DisconnectFromOwner() {
|
2018-02-21 21:53:22 +03:00
|
|
|
if (mParentObject) {
|
|
|
|
mParentObject->RemoveEventTargetObject(this);
|
|
|
|
}
|
2013-04-04 13:30:36 +04:00
|
|
|
mOwnerWindow = nullptr;
|
|
|
|
mParentObject = nullptr;
|
2012-03-13 04:56:07 +04:00
|
|
|
// Event listeners can't be handled anymore, so we can release them here.
|
|
|
|
if (mListenerManager) {
|
|
|
|
mListenerManager->Disconnect();
|
2012-07-30 18:20:58 +04:00
|
|
|
mListenerManager = nullptr;
|
2012-03-13 04:56:07 +04:00
|
|
|
}
|
2017-04-18 14:51:27 +03:00
|
|
|
|
|
|
|
MaybeDontKeepAlive();
|
2012-03-13 04:56:07 +04:00
|
|
|
}
|
|
|
|
|
2016-04-21 01:04:29 +03:00
|
|
|
nsPIDOMWindowInner* DOMEventTargetHelper::GetWindowIfCurrent() const {
|
2019-04-01 19:46:46 +03:00
|
|
|
if (NS_FAILED(CheckCurrentGlobalCorrectness())) {
|
2016-04-21 01:04:29 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return GetOwner();
|
|
|
|
}
|
|
|
|
|
2019-01-02 16:05:23 +03:00
|
|
|
Document* DOMEventTargetHelper::GetDocumentIfCurrent() const {
|
2016-04-21 01:04:29 +03:00
|
|
|
nsPIDOMWindowInner* win = GetWindowIfCurrent();
|
|
|
|
if (!win) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return win->GetDoc();
|
|
|
|
}
|
|
|
|
|
2018-04-05 20:42:42 +03:00
|
|
|
bool DOMEventTargetHelper::ComputeDefaultWantsUntrusted(ErrorResult& aRv) {
|
2018-04-05 20:42:42 +03:00
|
|
|
bool wantsUntrusted;
|
|
|
|
nsresult rv = WantsUntrusted(&wantsUntrusted);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
aRv.Throw(rv);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return wantsUntrusted;
|
|
|
|
}
|
|
|
|
|
2018-04-05 20:42:41 +03:00
|
|
|
bool DOMEventTargetHelper::DispatchEvent(Event& aEvent, CallerType aCallerType,
|
|
|
|
ErrorResult& aRv) {
|
2009-06-15 12:27:29 +04:00
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
2018-04-05 20:42:41 +03:00
|
|
|
nsresult rv = EventDispatcher::DispatchDOMEvent(this, nullptr, &aEvent,
|
|
|
|
nullptr, &status);
|
|
|
|
bool retval = !aEvent.DefaultPrevented(aCallerType);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
aRv.Throw(rv);
|
|
|
|
}
|
|
|
|
return retval;
|
2009-06-15 12:27:29 +04:00
|
|
|
}
|
|
|
|
|
2014-04-01 10:13:50 +04:00
|
|
|
nsresult DOMEventTargetHelper::DispatchTrustedEvent(
|
|
|
|
const nsAString& aEventName) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
|
2015-11-13 03:09:42 +03:00
|
|
|
event->InitEvent(aEventName, false, false);
|
2012-09-28 00:11:31 +04:00
|
|
|
|
|
|
|
return DispatchTrustedEvent(event);
|
|
|
|
}
|
|
|
|
|
2018-04-20 19:55:30 +03:00
|
|
|
nsresult DOMEventTargetHelper::DispatchTrustedEvent(Event* event) {
|
2012-12-22 12:18:08 +04:00
|
|
|
event->SetTrusted(true);
|
2012-09-28 00:11:31 +04:00
|
|
|
|
2018-04-05 20:42:41 +03:00
|
|
|
ErrorResult rv;
|
2018-04-20 19:55:30 +03:00
|
|
|
DispatchEvent(*event, rv);
|
2018-04-05 20:42:41 +03:00
|
|
|
return rv.StealNSResult();
|
2012-09-28 00:11:31 +04:00
|
|
|
}
|
|
|
|
|
2016-10-21 05:11:07 +03:00
|
|
|
void DOMEventTargetHelper::GetEventTargetParent(
|
|
|
|
EventChainPreVisitor& aVisitor) {
|
2011-10-17 18:59:28 +04:00
|
|
|
aVisitor.mCanHandle = true;
|
2017-12-18 19:07:36 +03:00
|
|
|
aVisitor.SetParentTarget(nullptr, false);
|
2009-06-15 12:27:29 +04:00
|
|
|
}
|
|
|
|
|
2014-04-01 10:13:50 +04:00
|
|
|
nsresult DOMEventTargetHelper::PostHandleEvent(
|
|
|
|
EventChainPostVisitor& aVisitor) {
|
2009-06-15 12:27:29 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2014-04-01 10:13:50 +04:00
|
|
|
EventListenerManager* DOMEventTargetHelper::GetOrCreateListenerManager() {
|
2013-10-23 03:32:04 +04:00
|
|
|
if (!mListenerManager) {
|
2014-03-17 10:56:53 +04:00
|
|
|
mListenerManager = new EventListenerManager(this);
|
2009-06-15 12:27:29 +04:00
|
|
|
}
|
|
|
|
|
2009-06-23 15:23:52 +04:00
|
|
|
return mListenerManager;
|
2009-06-15 12:27:29 +04:00
|
|
|
}
|
|
|
|
|
2014-04-01 10:13:50 +04:00
|
|
|
EventListenerManager* DOMEventTargetHelper::GetExistingListenerManager() const {
|
2013-10-23 03:32:04 +04:00
|
|
|
return mListenerManager;
|
|
|
|
}
|
|
|
|
|
2014-04-01 10:13:50 +04:00
|
|
|
nsresult DOMEventTargetHelper::WantsUntrusted(bool* aRetVal) {
|
2019-04-01 19:46:46 +03:00
|
|
|
nsresult rv = CheckCurrentGlobalCorrectness();
|
2013-09-06 01:08:24 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2017-04-18 14:51:27 +03:00
|
|
|
|
2019-01-02 16:05:23 +03:00
|
|
|
nsCOMPtr<Document> doc = GetDocumentIfCurrent();
|
2013-09-06 01:08:24 +04:00
|
|
|
// We can let listeners on workers to always handle all the events.
|
|
|
|
*aRetVal = (doc && !nsContentUtils::IsChromeDoc(doc)) || !NS_IsMainThread();
|
|
|
|
return rv;
|
|
|
|
}
|
2013-11-27 19:22:16 +04:00
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
void DOMEventTargetHelper::EventListenerAdded(nsAtom* aType) {
|
2017-04-18 14:51:27 +03:00
|
|
|
MaybeUpdateKeepAlive();
|
|
|
|
}
|
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
void DOMEventTargetHelper::EventListenerRemoved(nsAtom* aType) {
|
2017-04-18 14:51:27 +03:00
|
|
|
MaybeUpdateKeepAlive();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DOMEventTargetHelper::KeepAliveIfHasListenersFor(const nsAString& aType) {
|
|
|
|
mKeepingAliveTypes.mStrings.AppendElement(aType);
|
|
|
|
MaybeUpdateKeepAlive();
|
|
|
|
}
|
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
void DOMEventTargetHelper::KeepAliveIfHasListenersFor(nsAtom* aType) {
|
2017-04-18 14:51:27 +03:00
|
|
|
mKeepingAliveTypes.mAtoms.AppendElement(aType);
|
|
|
|
MaybeUpdateKeepAlive();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DOMEventTargetHelper::IgnoreKeepAliveIfHasListenersFor(
|
|
|
|
const nsAString& aType) {
|
|
|
|
mKeepingAliveTypes.mStrings.RemoveElement(aType);
|
|
|
|
MaybeUpdateKeepAlive();
|
|
|
|
}
|
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
void DOMEventTargetHelper::IgnoreKeepAliveIfHasListenersFor(nsAtom* aType) {
|
2017-04-18 14:51:27 +03:00
|
|
|
mKeepingAliveTypes.mAtoms.RemoveElement(aType);
|
|
|
|
MaybeUpdateKeepAlive();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DOMEventTargetHelper::MaybeUpdateKeepAlive() {
|
|
|
|
bool shouldBeKeptAlive = false;
|
|
|
|
|
2019-04-01 19:46:46 +03:00
|
|
|
if (NS_SUCCEEDED(CheckCurrentGlobalCorrectness())) {
|
2018-08-01 01:19:15 +03:00
|
|
|
if (!mKeepingAliveTypes.mAtoms.IsEmpty()) {
|
|
|
|
for (uint32_t i = 0; i < mKeepingAliveTypes.mAtoms.Length(); ++i) {
|
|
|
|
if (HasListenersFor(mKeepingAliveTypes.mAtoms[i])) {
|
|
|
|
shouldBeKeptAlive = true;
|
|
|
|
break;
|
|
|
|
}
|
2017-04-18 14:51:27 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-01 01:19:15 +03:00
|
|
|
if (!shouldBeKeptAlive && !mKeepingAliveTypes.mStrings.IsEmpty()) {
|
|
|
|
for (uint32_t i = 0; i < mKeepingAliveTypes.mStrings.Length(); ++i) {
|
|
|
|
if (HasListenersFor(mKeepingAliveTypes.mStrings[i])) {
|
|
|
|
shouldBeKeptAlive = true;
|
|
|
|
break;
|
|
|
|
}
|
2017-04-18 14:51:27 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (shouldBeKeptAlive == mIsKeptAlive) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mIsKeptAlive = shouldBeKeptAlive;
|
|
|
|
if (mIsKeptAlive) {
|
|
|
|
AddRef();
|
|
|
|
} else {
|
|
|
|
Release();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DOMEventTargetHelper::MaybeDontKeepAlive() {
|
|
|
|
if (mIsKeptAlive) {
|
|
|
|
mIsKeptAlive = false;
|
|
|
|
Release();
|
|
|
|
}
|
2013-11-27 19:22:16 +04:00
|
|
|
}
|
2014-04-01 10:13:50 +04:00
|
|
|
|
2018-04-16 16:08:51 +03:00
|
|
|
void DOMEventTargetHelper::BindToOwnerInternal(nsIGlobalObject* aOwner) {
|
2020-05-14 22:51:55 +03:00
|
|
|
MOZ_ASSERT(!mParentObject);
|
|
|
|
|
2018-04-16 16:08:51 +03:00
|
|
|
if (aOwner) {
|
|
|
|
mParentObject = aOwner;
|
|
|
|
aOwner->AddEventTargetObject(this);
|
|
|
|
// Let's cache the result of this QI for fast access and off main thread
|
|
|
|
// usage
|
|
|
|
mOwnerWindow =
|
|
|
|
nsCOMPtr<nsPIDOMWindowInner>(do_QueryInterface(aOwner)).get();
|
|
|
|
if (mOwnerWindow) {
|
|
|
|
mHasOrHasHadOwnerWindow = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-01 19:46:46 +03:00
|
|
|
nsresult DOMEventTargetHelper::CheckCurrentGlobalCorrectness() const {
|
|
|
|
NS_ENSURE_STATE(!mHasOrHasHadOwnerWindow || mOwnerWindow);
|
|
|
|
|
|
|
|
// Main-thread.
|
|
|
|
if (mOwnerWindow && !mOwnerWindow->IsCurrentInnerWindow()) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_IsMainThread()) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mParentObject) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2020-03-28 01:40:58 +03:00
|
|
|
if (mParentObject->IsDying()) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2019-04-01 19:46:46 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2014-04-01 10:13:50 +04:00
|
|
|
} // namespace mozilla
|