1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/AsyncEventDispatcher.h"
8 #include "mozilla/BasicEvents.h"
9 #include "mozilla/EventDispatcher.h"
10 #include "mozilla/dom/DocumentInlines.h"
11 #include "mozilla/dom/Event.h"
12 #include "mozilla/dom/EventTarget.h"
13 #include "nsContentUtils.h"
19 /******************************************************************************
20 * mozilla::AsyncEventDispatcher
21 ******************************************************************************/
23 AsyncEventDispatcher::AsyncEventDispatcher(EventTarget
* aTarget
,
25 : CancelableRunnable("AsyncEventDispatcher"),
27 mEventMessage(eUnidentifiedEvent
) {
30 EventDispatcher::CreateEvent(aTarget
, nullptr, &aEvent
, u
""_ns
);
31 mEvent
= std::move(event
);
32 mEventType
.SetIsVoid(true);
33 NS_ASSERTION(mEvent
, "Should never fail to create an event");
34 mEvent
->DuplicatePrivateData();
35 mEvent
->SetTrusted(aEvent
.IsTrusted());
39 AsyncEventDispatcher::Run() {
43 nsINode
* node
= nsINode::FromEventTargetOrNull(mTarget
);
44 if (mCheckStillInDoc
) {
46 if (!node
->IsInComposedDoc()) {
50 mTarget
->AsyncEventRunning(this);
51 if (mEventMessage
!= eUnidentifiedEvent
) {
52 MOZ_ASSERT(mComposed
== Composed::eDefault
);
53 return nsContentUtils::DispatchTrustedEvent
<WidgetEvent
>(
54 node
->OwnerDoc(), mTarget
, mEventMessage
, mCanBubble
, Cancelable::eNo
,
55 nullptr /* aDefaultAction */, mOnlyChromeDispatch
);
57 // MOZ_KnownLives because this instance shouldn't be touched while running.
59 DispatchEventOnTarget(MOZ_KnownLive(mTarget
), MOZ_KnownLive(mEvent
),
60 mOnlyChromeDispatch
, mComposed
);
62 DispatchEventOnTarget(MOZ_KnownLive(mTarget
), mEventType
, mCanBubble
,
63 mOnlyChromeDispatch
, mComposed
);
69 void AsyncEventDispatcher::DispatchEventOnTarget(
70 EventTarget
* aTarget
, const nsAString
& aEventType
, CanBubble aCanBubble
,
71 ChromeOnlyDispatch aOnlyChromeDispatch
, Composed aComposed
) {
72 RefPtr
<Event
> event
= NS_NewDOMEvent(aTarget
, nullptr, nullptr);
73 event
->InitEvent(aEventType
, aCanBubble
, Cancelable::eNo
);
74 event
->SetTrusted(true);
75 DispatchEventOnTarget(aTarget
, event
, aOnlyChromeDispatch
, aComposed
);
79 void AsyncEventDispatcher::DispatchEventOnTarget(
80 EventTarget
* aTarget
, Event
* aEvent
, ChromeOnlyDispatch aOnlyChromeDispatch
,
82 if (aComposed
!= Composed::eDefault
) {
83 aEvent
->WidgetEventPtr()->mFlags
.mComposed
= aComposed
== Composed::eYes
;
85 if (aOnlyChromeDispatch
== ChromeOnlyDispatch::eYes
) {
86 MOZ_ASSERT(aEvent
->IsTrusted());
87 aEvent
->WidgetEventPtr()->mFlags
.mOnlyChromeDispatch
= true;
89 aTarget
->DispatchEvent(*aEvent
);
92 nsresult
AsyncEventDispatcher::Cancel() {
97 nsresult
AsyncEventDispatcher::PostDOMEvent() {
98 RefPtr
<AsyncEventDispatcher
> ensureDeletionWhenFailing
= this;
99 return NS_DispatchToCurrentThread(ensureDeletionWhenFailing
.forget());
102 void AsyncEventDispatcher::RunDOMEventWhenSafe() {
103 RefPtr
<AsyncEventDispatcher
> ensureDeletionWhenFailing
= this;
104 nsContentUtils::AddScriptRunner(ensureDeletionWhenFailing
.forget());
108 void AsyncEventDispatcher::RunDOMEventWhenSafe(
109 EventTarget
& aTarget
, const nsAString
& aEventType
, CanBubble aCanBubble
,
110 ChromeOnlyDispatch aOnlyChromeDispatch
/* = ChromeOnlyDispatch::eNo */,
111 Composed aComposed
/* = Composed::eDefault */) {
112 if (nsContentUtils::IsSafeToRunScript()) {
113 OwningNonNull
<EventTarget
> target
= aTarget
;
114 DispatchEventOnTarget(target
, aEventType
, aCanBubble
, aOnlyChromeDispatch
,
118 (new AsyncEventDispatcher(&aTarget
, aEventType
, aCanBubble
,
119 aOnlyChromeDispatch
, aComposed
))
120 ->RunDOMEventWhenSafe();
123 void AsyncEventDispatcher::RunDOMEventWhenSafe(
124 EventTarget
& aTarget
, Event
& aEvent
,
125 ChromeOnlyDispatch aOnlyChromeDispatch
/* = ChromeOnlyDispatch::eNo */) {
126 if (nsContentUtils::IsSafeToRunScript()) {
127 DispatchEventOnTarget(&aTarget
, &aEvent
, aOnlyChromeDispatch
,
131 (new AsyncEventDispatcher(&aTarget
, do_AddRef(&aEvent
), aOnlyChromeDispatch
))
132 ->RunDOMEventWhenSafe();
136 nsresult
AsyncEventDispatcher::RunDOMEventWhenSafe(
137 nsINode
& aTarget
, WidgetEvent
& aEvent
,
138 nsEventStatus
* aEventStatus
/* = nullptr */) {
139 if (nsContentUtils::IsSafeToRunScript()) {
140 // MOZ_KnownLive due to bug 1832202
141 nsPresContext
* presContext
= aTarget
.OwnerDoc()->GetPresContext();
142 return EventDispatcher::Dispatch(MOZ_KnownLive(&aTarget
),
143 MOZ_KnownLive(presContext
), &aEvent
,
144 nullptr, aEventStatus
);
146 (new AsyncEventDispatcher(&aTarget
, aEvent
))->RunDOMEventWhenSafe();
150 void AsyncEventDispatcher::RequireNodeInDocument() {
152 MOZ_ASSERT(mTarget
->IsNode());
153 mCheckStillInDoc
= true;
156 } // namespace mozilla