Line data Source code
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/. */
6 :
7 : #include "nsPresContext.h"
8 : #include "nsContentUtils.h"
9 : #include "nsError.h"
10 : #include <new>
11 : #include "nsIContent.h"
12 : #include "nsIDocument.h"
13 : #include "nsINode.h"
14 : #include "nsPIDOMWindow.h"
15 : #include "AnimationEvent.h"
16 : #include "BeforeUnloadEvent.h"
17 : #include "ClipboardEvent.h"
18 : #include "CommandEvent.h"
19 : #include "CompositionEvent.h"
20 : #include "DeviceMotionEvent.h"
21 : #include "DragEvent.h"
22 : #include "GeckoProfiler.h"
23 : #include "KeyboardEvent.h"
24 : #include "mozilla/ContentEvents.h"
25 : #include "mozilla/dom/CloseEvent.h"
26 : #include "mozilla/dom/CustomEvent.h"
27 : #include "mozilla/dom/DeviceOrientationEvent.h"
28 : #include "mozilla/dom/ErrorEvent.h"
29 : #include "mozilla/dom/EventTarget.h"
30 : #include "mozilla/dom/FocusEvent.h"
31 : #include "mozilla/dom/HashChangeEvent.h"
32 : #include "mozilla/dom/InputEvent.h"
33 : #include "mozilla/dom/MessageEvent.h"
34 : #include "mozilla/dom/MouseScrollEvent.h"
35 : #include "mozilla/dom/MutationEvent.h"
36 : #include "mozilla/dom/NotifyPaintEvent.h"
37 : #include "mozilla/dom/PageTransitionEvent.h"
38 : #include "mozilla/dom/PointerEvent.h"
39 : #include "mozilla/dom/PopStateEvent.h"
40 : #include "mozilla/dom/RootedDictionary.h"
41 : #include "mozilla/dom/ScrollAreaEvent.h"
42 : #include "mozilla/dom/SimpleGestureEvent.h"
43 : #include "mozilla/dom/ScriptSettings.h"
44 : #include "mozilla/dom/StorageEvent.h"
45 : #include "mozilla/dom/TimeEvent.h"
46 : #include "mozilla/dom/TouchEvent.h"
47 : #include "mozilla/dom/TransitionEvent.h"
48 : #include "mozilla/dom/WheelEvent.h"
49 : #include "mozilla/dom/WorkerPrivate.h"
50 : #include "mozilla/dom/XULCommandEvent.h"
51 : #include "mozilla/EventDispatcher.h"
52 : #include "mozilla/EventListenerManager.h"
53 : #include "mozilla/InternalMutationEvent.h"
54 : #include "mozilla/ipc/MessageChannel.h"
55 : #include "mozilla/MiscEvents.h"
56 : #include "mozilla/MouseEvents.h"
57 : #include "mozilla/Telemetry.h"
58 : #include "mozilla/TextEvents.h"
59 : #include "mozilla/TouchEvents.h"
60 : #include "mozilla/Unused.h"
61 :
62 : #ifdef MOZ_TASK_TRACER
63 : #include "GeckoTaskTracer.h"
64 : #include "mozilla/dom/Element.h"
65 : #include "mozilla/Likely.h"
66 : using namespace mozilla::tasktracer;
67 : #endif
68 :
69 : namespace mozilla {
70 :
71 : using namespace dom;
72 :
73 : class ELMCreationDetector
74 : {
75 : public:
76 499 : ELMCreationDetector()
77 : // We can do this optimization only in the main thread.
78 499 : : mNonMainThread(!NS_IsMainThread())
79 499 : , mInitialCount(mNonMainThread ?
80 998 : 0 : EventListenerManager::sMainThreadCreatedCount)
81 : {
82 499 : }
83 :
84 2812 : bool MayHaveNewListenerManager()
85 : {
86 5624 : return mNonMainThread ||
87 5624 : mInitialCount != EventListenerManager::sMainThreadCreatedCount;
88 : }
89 :
90 998 : bool IsMainThread()
91 : {
92 998 : return !mNonMainThread;
93 : }
94 :
95 : private:
96 : bool mNonMainThread;
97 : uint32_t mInitialCount;
98 : };
99 :
100 8 : static bool IsEventTargetChrome(EventTarget* aEventTarget,
101 : nsIDocument** aDocument = nullptr)
102 : {
103 8 : if (aDocument) {
104 8 : *aDocument = nullptr;
105 : }
106 :
107 8 : if (NS_WARN_IF(!aEventTarget)) {
108 0 : return false;
109 : }
110 :
111 16 : nsCOMPtr<nsIDocument> doc = do_QueryInterface(aEventTarget);
112 8 : if (!doc) {
113 16 : nsCOMPtr<nsINode> node = do_QueryInterface(aEventTarget);
114 8 : if (node) {
115 4 : doc = node->OwnerDoc();
116 : } else {
117 8 : nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aEventTarget);
118 4 : if (!window) {
119 0 : return false;
120 : }
121 4 : doc = window->GetExtantDoc();
122 : }
123 8 : if (!doc) {
124 0 : return false;
125 : }
126 : }
127 8 : bool isChrome = nsContentUtils::IsChromeDoc(doc);
128 8 : if (aDocument) {
129 8 : doc.swap(*aDocument);
130 : }
131 8 : return isChrome;
132 : }
133 :
134 :
135 : // EventTargetChainItem represents a single item in the event target chain.
136 2323 : class EventTargetChainItem
137 : {
138 : private:
139 : explicit EventTargetChainItem(EventTarget* aTarget);
140 : public:
141 2323 : EventTargetChainItem()
142 2323 : : mItemFlags(0)
143 : {
144 2323 : }
145 :
146 2323 : static EventTargetChainItem* Create(nsTArray<EventTargetChainItem>& aChain,
147 : EventTarget* aTarget,
148 : EventTargetChainItem* aChild = nullptr)
149 : {
150 : // The last item which can handle the event must be aChild.
151 2323 : MOZ_ASSERT(GetLastCanHandleEventTarget(aChain) == aChild);
152 2323 : return new (aChain.AppendElement()) EventTargetChainItem(aTarget);
153 : }
154 :
155 0 : static void DestroyLast(nsTArray<EventTargetChainItem>& aChain,
156 : EventTargetChainItem* aItem)
157 : {
158 0 : uint32_t lastIndex = aChain.Length() - 1;
159 0 : MOZ_ASSERT(&aChain[lastIndex] == aItem);
160 0 : aChain.RemoveElementAt(lastIndex);
161 0 : }
162 :
163 0 : static EventTargetChainItem* GetFirstCanHandleEventTarget(
164 : nsTArray<EventTargetChainItem>& aChain)
165 : {
166 0 : return &aChain[GetFirstCanHandleEventTargetIdx(aChain)];
167 : }
168 :
169 892 : static uint32_t GetFirstCanHandleEventTargetIdx(nsTArray<EventTargetChainItem>& aChain)
170 : {
171 : // aChain[i].PreHandleEventOnly() = true only when the target element wants
172 : // PreHandleEvent and set mCanHandle=false. So we find the first element
173 : // which can handle the event.
174 892 : for (uint32_t i = 0; i < aChain.Length(); ++i) {
175 892 : if (!aChain[i].PreHandleEventOnly()) {
176 892 : return i;
177 : }
178 : }
179 0 : MOZ_ASSERT(false);
180 : return 0;
181 : }
182 :
183 2323 : static EventTargetChainItem* GetLastCanHandleEventTarget(
184 : nsTArray<EventTargetChainItem>& aChain)
185 : {
186 : // Fine the last item which can handle the event.
187 2323 : for (int32_t i = aChain.Length() - 1; i >= 0; --i) {
188 1824 : if (!aChain[i].PreHandleEventOnly()) {
189 1824 : return &aChain[i];
190 : }
191 : }
192 499 : return nullptr;
193 : }
194 :
195 2323 : bool IsValid()
196 : {
197 2323 : NS_WARNING_ASSERTION(!!(mTarget), "Event target is not valid!");
198 2323 : return !!(mTarget);
199 : }
200 :
201 7170 : EventTarget* GetNewTarget()
202 : {
203 7170 : return mNewTarget;
204 : }
205 :
206 590 : void SetNewTarget(EventTarget* aNewTarget)
207 : {
208 590 : mNewTarget = aNewTarget;
209 590 : }
210 :
211 2323 : void SetForceContentDispatch(bool aForce)
212 : {
213 2323 : mFlags.mForceContentDispatch = aForce;
214 2323 : }
215 :
216 0 : bool ForceContentDispatch()
217 : {
218 0 : return mFlags.mForceContentDispatch;
219 : }
220 :
221 2323 : void SetWantsWillHandleEvent(bool aWants)
222 : {
223 2323 : mFlags.mWantsWillHandleEvent = aWants;
224 2323 : }
225 :
226 6024 : bool WantsWillHandleEvent()
227 : {
228 6024 : return mFlags.mWantsWillHandleEvent;
229 : }
230 :
231 2323 : void SetWantsPreHandleEvent(bool aWants)
232 : {
233 2323 : mFlags.mWantsPreHandleEvent = aWants;
234 2323 : }
235 :
236 2171 : bool WantsPreHandleEvent()
237 : {
238 2171 : return mFlags.mWantsPreHandleEvent;
239 : }
240 :
241 2323 : void SetPreHandleEventOnly(bool aWants)
242 : {
243 2323 : mFlags.mPreHandleEventOnly = aWants;
244 2323 : }
245 :
246 9412 : bool PreHandleEventOnly()
247 : {
248 9412 : return mFlags.mPreHandleEventOnly;
249 : }
250 :
251 2323 : void SetMayHaveListenerManager(bool aMayHave)
252 : {
253 2323 : mFlags.mMayHaveManager = aMayHave;
254 2323 : }
255 :
256 4095 : bool MayHaveListenerManager()
257 : {
258 4095 : return mFlags.mMayHaveManager;
259 : }
260 :
261 3462 : EventTarget* CurrentTarget()
262 : {
263 3462 : return mTarget;
264 : }
265 :
266 : /**
267 : * Dispatches event through the event target chain.
268 : * Handles capture, target and bubble phases both in default
269 : * and system event group and calls also PostHandleEvent for each
270 : * item in the chain.
271 : */
272 : static void HandleEventTargetChain(nsTArray<EventTargetChainItem>& aChain,
273 : EventChainPostVisitor& aVisitor,
274 : EventDispatchingCallback* aCallback,
275 : ELMCreationDetector& aCd);
276 :
277 : /**
278 : * Resets aVisitor object and calls GetEventTargetParent.
279 : * Copies mItemFlags and mItemData to the current EventTargetChainItem.
280 : */
281 : void GetEventTargetParent(EventChainPreVisitor& aVisitor);
282 :
283 : /**
284 : * Calls PreHandleEvent for those items which called SetWantsPreHandleEvent.
285 : */
286 : void PreHandleEvent(EventChainVisitor& aVisitor);
287 :
288 : /**
289 : * If the current item in the event target chain has an event listener
290 : * manager, this method calls EventListenerManager::HandleEvent().
291 : */
292 6024 : void HandleEvent(EventChainPostVisitor& aVisitor,
293 : ELMCreationDetector& aCd)
294 : {
295 6024 : if (WantsWillHandleEvent()) {
296 0 : mTarget->WillHandleEvent(aVisitor);
297 : }
298 6024 : if (aVisitor.mEvent->PropagationStopped()) {
299 0 : return;
300 : }
301 12048 : if (aVisitor.mEvent->mFlags.mOnlySystemGroupDispatchInContent &&
302 6024 : !aVisitor.mEvent->mFlags.mInSystemGroup &&
303 0 : !IsCurrentTargetChrome()) {
304 0 : return;
305 : }
306 6024 : if (!mManager) {
307 4095 : if (!MayHaveListenerManager() && !aCd.MayHaveNewListenerManager()) {
308 2812 : return;
309 : }
310 1283 : mManager = mTarget->GetExistingListenerManager();
311 : }
312 3212 : if (mManager) {
313 2944 : NS_ASSERTION(aVisitor.mEvent->mCurrentTarget == nullptr,
314 : "CurrentTarget should be null!");
315 2944 : mManager->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent,
316 : &aVisitor.mDOMEvent,
317 : CurrentTarget(),
318 2944 : &aVisitor.mEventStatus);
319 2944 : NS_ASSERTION(aVisitor.mEvent->mCurrentTarget == nullptr,
320 : "CurrentTarget should be null!");
321 : }
322 : }
323 :
324 : /**
325 : * Copies mItemFlags and mItemData to aVisitor and calls PostHandleEvent.
326 : */
327 : void PostHandleEvent(EventChainPostVisitor& aVisitor);
328 :
329 : private:
330 : nsCOMPtr<EventTarget> mTarget;
331 :
332 : class EventTargetChainFlags
333 : {
334 : public:
335 4646 : explicit EventTargetChainFlags()
336 4646 : {
337 4646 : SetRawFlags(0);
338 4646 : }
339 : // Cached flags for each EventTargetChainItem which are set when calling
340 : // GetEventTargetParent to create event target chain. They are used to
341 : // manage or speedup event dispatching.
342 : bool mForceContentDispatch : 1;
343 : bool mWantsWillHandleEvent : 1;
344 : bool mMayHaveManager : 1;
345 : bool mChechedIfChrome : 1;
346 : bool mIsChromeContent : 1;
347 : bool mWantsPreHandleEvent : 1;
348 : bool mPreHandleEventOnly : 1;
349 : private:
350 : typedef uint32_t RawFlags;
351 4646 : void SetRawFlags(RawFlags aRawFlags)
352 : {
353 : static_assert(sizeof(EventTargetChainFlags) <= sizeof(RawFlags),
354 : "EventTargetChainFlags must not be bigger than the RawFlags");
355 4646 : memcpy(this, &aRawFlags, sizeof(EventTargetChainFlags));
356 4646 : }
357 : } mFlags;
358 :
359 : uint16_t mItemFlags;
360 : nsCOMPtr<nsISupports> mItemData;
361 : // Event retargeting must happen whenever mNewTarget is non-null.
362 : nsCOMPtr<EventTarget> mNewTarget;
363 : // Cache mTarget's event listener manager.
364 : RefPtr<EventListenerManager> mManager;
365 :
366 0 : bool IsCurrentTargetChrome()
367 : {
368 0 : if (!mFlags.mChechedIfChrome) {
369 0 : mFlags.mChechedIfChrome = true;
370 0 : if (IsEventTargetChrome(mTarget)) {
371 0 : mFlags.mIsChromeContent = true;
372 : }
373 : }
374 0 : return mFlags.mIsChromeContent;
375 : }
376 : };
377 :
378 2323 : EventTargetChainItem::EventTargetChainItem(EventTarget* aTarget)
379 : : mTarget(aTarget)
380 2323 : , mItemFlags(0)
381 : {
382 2323 : MOZ_ASSERT(!aTarget || mTarget == aTarget->GetTargetForEventTargetChain());
383 2323 : }
384 :
385 : void
386 2323 : EventTargetChainItem::GetEventTargetParent(EventChainPreVisitor& aVisitor)
387 : {
388 2323 : aVisitor.Reset();
389 2323 : Unused << mTarget->GetEventTargetParent(aVisitor);
390 2323 : SetForceContentDispatch(aVisitor.mForceContentDispatch);
391 2323 : SetWantsWillHandleEvent(aVisitor.mWantsWillHandleEvent);
392 2323 : SetMayHaveListenerManager(aVisitor.mMayHaveListenerManager);
393 2323 : SetWantsPreHandleEvent(aVisitor.mWantsPreHandleEvent);
394 2323 : SetPreHandleEventOnly(aVisitor.mWantsPreHandleEvent && !aVisitor.mCanHandle);
395 2323 : mItemFlags = aVisitor.mItemFlags;
396 2323 : mItemData = aVisitor.mItemData;
397 2323 : }
398 :
399 : void
400 2171 : EventTargetChainItem::PreHandleEvent(EventChainVisitor& aVisitor)
401 : {
402 2171 : if (!WantsPreHandleEvent()) {
403 2171 : return;
404 : }
405 0 : aVisitor.mItemFlags = mItemFlags;
406 0 : aVisitor.mItemData = mItemData;
407 0 : Unused << mTarget->PreHandleEvent(aVisitor);
408 : }
409 :
410 : void
411 1287 : EventTargetChainItem::PostHandleEvent(EventChainPostVisitor& aVisitor)
412 : {
413 1287 : aVisitor.mItemFlags = mItemFlags;
414 1287 : aVisitor.mItemData = mItemData;
415 1287 : mTarget->PostHandleEvent(aVisitor);
416 1287 : }
417 :
418 : void
419 892 : EventTargetChainItem::HandleEventTargetChain(
420 : nsTArray<EventTargetChainItem>& aChain,
421 : EventChainPostVisitor& aVisitor,
422 : EventDispatchingCallback* aCallback,
423 : ELMCreationDetector& aCd)
424 : {
425 : // Save the target so that it can be restored later.
426 1784 : nsCOMPtr<EventTarget> firstTarget = aVisitor.mEvent->mTarget;
427 892 : uint32_t chainLength = aChain.Length();
428 : uint32_t firstCanHandleEventTargetIdx =
429 892 : EventTargetChainItem::GetFirstCanHandleEventTargetIdx(aChain);
430 :
431 : // Capture
432 892 : aVisitor.mEvent->mFlags.mInCapturePhase = true;
433 892 : aVisitor.mEvent->mFlags.mInBubblingPhase = false;
434 4240 : for (uint32_t i = chainLength - 1; i > firstCanHandleEventTargetIdx; --i) {
435 3348 : EventTargetChainItem& item = aChain[i];
436 3348 : if (item.PreHandleEventOnly()) {
437 0 : continue;
438 : }
439 6696 : if ((!aVisitor.mEvent->mFlags.mNoContentDispatch ||
440 6696 : item.ForceContentDispatch()) &&
441 3348 : !aVisitor.mEvent->PropagationStopped()) {
442 3348 : item.HandleEvent(aVisitor, aCd);
443 : }
444 :
445 3348 : if (item.GetNewTarget()) {
446 : // item is at anonymous boundary. Need to retarget for the child items.
447 474 : for (uint32_t j = i; j > 0; --j) {
448 474 : uint32_t childIndex = j - 1;
449 474 : EventTarget* newTarget = aChain[childIndex].GetNewTarget();
450 474 : if (newTarget) {
451 176 : aVisitor.mEvent->mTarget = newTarget;
452 176 : break;
453 : }
454 : }
455 : }
456 : }
457 :
458 : // Target
459 892 : aVisitor.mEvent->mFlags.mInBubblingPhase = true;
460 892 : EventTargetChainItem& targetItem = aChain[firstCanHandleEventTargetIdx];
461 2676 : if (!aVisitor.mEvent->PropagationStopped() &&
462 892 : (!aVisitor.mEvent->mFlags.mNoContentDispatch ||
463 0 : targetItem.ForceContentDispatch())) {
464 892 : targetItem.HandleEvent(aVisitor, aCd);
465 : }
466 892 : if (aVisitor.mEvent->mFlags.mInSystemGroup) {
467 443 : targetItem.PostHandleEvent(aVisitor);
468 : }
469 :
470 : // Bubble
471 892 : aVisitor.mEvent->mFlags.mInCapturePhase = false;
472 4240 : for (uint32_t i = firstCanHandleEventTargetIdx + 1; i < chainLength; ++i) {
473 3348 : EventTargetChainItem& item = aChain[i];
474 3348 : if (item.PreHandleEventOnly()) {
475 0 : continue;
476 : }
477 3348 : EventTarget* newTarget = item.GetNewTarget();
478 3348 : if (newTarget) {
479 : // Item is at anonymous boundary. Need to retarget for the current item
480 : // and for parent items.
481 176 : aVisitor.mEvent->mTarget = newTarget;
482 : }
483 :
484 3348 : if (aVisitor.mEvent->mFlags.mBubbles || newTarget) {
485 3568 : if ((!aVisitor.mEvent->mFlags.mNoContentDispatch ||
486 3568 : item.ForceContentDispatch()) &&
487 1784 : !aVisitor.mEvent->PropagationStopped()) {
488 1784 : item.HandleEvent(aVisitor, aCd);
489 : }
490 1784 : if (aVisitor.mEvent->mFlags.mInSystemGroup) {
491 844 : item.PostHandleEvent(aVisitor);
492 : }
493 : }
494 : }
495 892 : aVisitor.mEvent->mFlags.mInBubblingPhase = false;
496 :
497 1341 : if (!aVisitor.mEvent->mFlags.mInSystemGroup &&
498 449 : aVisitor.mEvent->IsAllowedToDispatchInSystemGroup()) {
499 : // Dispatch to the system event group. Make sure to clear the
500 : // STOP_DISPATCH flag since this resets for each event group.
501 443 : aVisitor.mEvent->mFlags.mPropagationStopped = false;
502 443 : aVisitor.mEvent->mFlags.mImmediatePropagationStopped = false;
503 :
504 : // Setting back the original target of the event.
505 443 : aVisitor.mEvent->mTarget = aVisitor.mEvent->mOriginalTarget;
506 :
507 : // Special handling if PresShell (or some other caller)
508 : // used a callback object.
509 443 : if (aCallback) {
510 7 : aCallback->HandleEvent(aVisitor);
511 : }
512 :
513 : // Retarget for system event group (which does the default handling too).
514 : // Setting back the target which was used also for default event group.
515 443 : aVisitor.mEvent->mTarget = firstTarget;
516 443 : aVisitor.mEvent->mFlags.mInSystemGroup = true;
517 : HandleEventTargetChain(aChain,
518 : aVisitor,
519 : aCallback,
520 443 : aCd);
521 443 : aVisitor.mEvent->mFlags.mInSystemGroup = false;
522 :
523 : // After dispatch, clear all the propagation flags so that
524 : // system group listeners don't affect to the event.
525 443 : aVisitor.mEvent->mFlags.mPropagationStopped = false;
526 443 : aVisitor.mEvent->mFlags.mImmediatePropagationStopped = false;
527 : }
528 892 : }
529 :
530 : static nsTArray<EventTargetChainItem>* sCachedMainThreadChain = nullptr;
531 :
532 : /* static */ void
533 0 : EventDispatcher::Shutdown()
534 : {
535 0 : delete sCachedMainThreadChain;
536 0 : sCachedMainThreadChain = nullptr;
537 0 : }
538 :
539 : EventTargetChainItem*
540 0 : EventTargetChainItemForChromeTarget(nsTArray<EventTargetChainItem>& aChain,
541 : nsINode* aNode,
542 : EventTargetChainItem* aChild = nullptr)
543 : {
544 0 : if (!aNode->IsInComposedDoc()) {
545 0 : return nullptr;
546 : }
547 0 : nsPIDOMWindowInner* win = aNode->OwnerDoc()->GetInnerWindow();
548 0 : EventTarget* piTarget = win ? win->GetParentTarget() : nullptr;
549 0 : NS_ENSURE_TRUE(piTarget, nullptr);
550 :
551 : EventTargetChainItem* etci =
552 0 : EventTargetChainItem::Create(aChain,
553 0 : piTarget->GetTargetForEventTargetChain(),
554 0 : aChild);
555 0 : if (!etci->IsValid()) {
556 0 : EventTargetChainItem::DestroyLast(aChain, etci);
557 0 : return nullptr;
558 : }
559 0 : return etci;
560 : }
561 :
562 : /* static */ EventTargetChainItem*
563 0 : MayRetargetToChromeIfCanNotHandleEvent(
564 : nsTArray<EventTargetChainItem>& aChain, EventChainPreVisitor& aPreVisitor,
565 : EventTargetChainItem* aTargetEtci, EventTargetChainItem* aChildEtci,
566 : nsINode* aContent)
567 : {
568 0 : if (!aPreVisitor.mWantsPreHandleEvent) {
569 : // Keep EventTargetChainItem if we need to call PreHandleEvent on it.
570 0 : EventTargetChainItem::DestroyLast(aChain, aTargetEtci);
571 : }
572 0 : if (aPreVisitor.mAutomaticChromeDispatch && aContent) {
573 : // Event target couldn't handle the event. Try to propagate to chrome.
574 : EventTargetChainItem* chromeTargetEtci =
575 0 : EventTargetChainItemForChromeTarget(aChain, aContent, aChildEtci);
576 0 : if (chromeTargetEtci) {
577 0 : chromeTargetEtci->GetEventTargetParent(aPreVisitor);
578 0 : return chromeTargetEtci;
579 : }
580 : }
581 0 : return nullptr;
582 : }
583 :
584 : /* static */ nsresult
585 499 : EventDispatcher::Dispatch(nsISupports* aTarget,
586 : nsPresContext* aPresContext,
587 : WidgetEvent* aEvent,
588 : nsIDOMEvent* aDOMEvent,
589 : nsEventStatus* aEventStatus,
590 : EventDispatchingCallback* aCallback,
591 : nsTArray<EventTarget*>* aTargets)
592 : {
593 998 : AUTO_PROFILER_LABEL("EventDispatcher::Dispatch", EVENTS);
594 :
595 499 : NS_ASSERTION(aEvent, "Trying to dispatch without WidgetEvent!");
596 499 : NS_ENSURE_TRUE(!aEvent->mFlags.mIsBeingDispatched,
597 : NS_ERROR_DOM_INVALID_STATE_ERR);
598 499 : NS_ASSERTION(!aTargets || !aEvent->mMessage, "Wrong parameters!");
599 :
600 : // If we're dispatching an already created DOMEvent object, make
601 : // sure it is initialized!
602 : // If aTargets is non-null, the event isn't going to be dispatched.
603 499 : NS_ENSURE_TRUE(aEvent->mMessage || !aDOMEvent || aTargets,
604 : NS_ERROR_DOM_INVALID_STATE_ERR);
605 :
606 : #ifdef MOZ_TASK_TRACER
607 : if (MOZ_UNLIKELY(mozilla::tasktracer::IsStartLogging())) {
608 : nsAutoCString eventType;
609 : nsAutoString eventTypeU16;
610 : if (aDOMEvent) {
611 : aDOMEvent->GetType(eventTypeU16);
612 : } else {
613 : Event::GetWidgetEventType(aEvent, eventTypeU16);
614 : }
615 : eventType = NS_ConvertUTF16toUTF8(eventTypeU16);
616 :
617 : nsCOMPtr<Element> element = do_QueryInterface(aTarget);
618 : nsAutoString elementId;
619 : nsAutoString elementTagName;
620 : if (element) {
621 : element->GetId(elementId);
622 : element->GetTagName(elementTagName);
623 : }
624 : AddLabel("Event [%s] dispatched at target [id:%s tag:%s]",
625 : eventType.get(),
626 : NS_ConvertUTF16toUTF8(elementId).get(),
627 : NS_ConvertUTF16toUTF8(elementTagName).get());
628 : }
629 : #endif
630 :
631 998 : nsCOMPtr<EventTarget> target = do_QueryInterface(aTarget);
632 :
633 499 : bool retargeted = false;
634 :
635 499 : if (aEvent->mFlags.mRetargetToNonNativeAnonymous) {
636 0 : nsCOMPtr<nsIContent> content = do_QueryInterface(target);
637 0 : if (content && content->IsInNativeAnonymousSubtree()) {
638 : nsCOMPtr<EventTarget> newTarget =
639 0 : do_QueryInterface(content->FindFirstNonChromeOnlyAccessContent());
640 0 : NS_ENSURE_STATE(newTarget);
641 :
642 0 : aEvent->mOriginalTarget = target;
643 0 : target = newTarget;
644 0 : retargeted = true;
645 : }
646 : }
647 :
648 499 : if (aEvent->mFlags.mOnlyChromeDispatch) {
649 16 : nsCOMPtr<nsIDocument> doc;
650 8 : if (!IsEventTargetChrome(target, getter_AddRefs(doc)) && doc) {
651 5 : nsPIDOMWindowInner* win = doc->GetInnerWindow();
652 : // If we can't dispatch the event to chrome, do nothing.
653 5 : EventTarget* piTarget = win ? win->GetParentTarget() : nullptr;
654 5 : if (!piTarget) {
655 0 : return NS_OK;
656 : }
657 :
658 : // Set the target to be the original dispatch target,
659 5 : aEvent->mTarget = target;
660 : // but use chrome event handler or TabChildGlobal for event target chain.
661 5 : target = piTarget;
662 3 : } else if (NS_WARN_IF(!doc)) {
663 0 : return NS_ERROR_UNEXPECTED;
664 : }
665 : }
666 :
667 : #ifdef DEBUG
668 947 : if (aEvent->mMessage != eVoidEvent &&
669 448 : !nsContentUtils::IsSafeToRunScript()) {
670 2 : nsresult rv = NS_ERROR_FAILURE;
671 4 : if (target->GetContextForEventHandlers(&rv) ||
672 2 : NS_FAILED(rv)) {
673 0 : nsCOMPtr<nsINode> node = do_QueryInterface(target);
674 0 : if (node && nsContentUtils::IsChromeDoc(node->OwnerDoc())) {
675 0 : NS_WARNING("Fix the caller!");
676 : } else {
677 0 : NS_ERROR("This is unsafe! Fix the caller!");
678 : }
679 : }
680 : }
681 :
682 499 : if (aDOMEvent) {
683 291 : WidgetEvent* innerEvent = aDOMEvent->WidgetEventPtr();
684 291 : NS_ASSERTION(innerEvent == aEvent,
685 : "The inner event of aDOMEvent is not the same as aEvent!");
686 : }
687 : #endif
688 :
689 499 : nsresult rv = NS_OK;
690 499 : bool externalDOMEvent = !!(aDOMEvent);
691 :
692 : // If we have a PresContext, make sure it doesn't die before
693 : // event dispatching is finished.
694 998 : RefPtr<nsPresContext> kungFuDeathGrip(aPresContext);
695 :
696 499 : ELMCreationDetector cd;
697 998 : nsTArray<EventTargetChainItem> chain;
698 499 : if (cd.IsMainThread()) {
699 482 : if (!sCachedMainThreadChain) {
700 2 : sCachedMainThreadChain = new nsTArray<EventTargetChainItem>();
701 : }
702 482 : chain.SwapElements(*sCachedMainThreadChain);
703 482 : chain.SetCapacity(128);
704 : }
705 :
706 : // Create the event target chain item for the event target.
707 : EventTargetChainItem* targetEtci =
708 499 : EventTargetChainItem::Create(chain, target->GetTargetForEventTargetChain());
709 499 : MOZ_ASSERT(&chain[0] == targetEtci);
710 499 : if (!targetEtci->IsValid()) {
711 0 : EventTargetChainItem::DestroyLast(chain, targetEtci);
712 0 : return NS_ERROR_FAILURE;
713 : }
714 :
715 : // Make sure that nsIDOMEvent::target and nsIDOMEvent::originalTarget
716 : // point to the last item in the chain.
717 499 : if (!aEvent->mTarget) {
718 : // Note, CurrentTarget() points always to the object returned by
719 : // GetTargetForEventTargetChain().
720 366 : aEvent->mTarget = targetEtci->CurrentTarget();
721 : } else {
722 : // XXX But if the target is already set, use that. This is a hack
723 : // for the 'load', 'beforeunload' and 'unload' events,
724 : // which are dispatched to |window| but have document as their target.
725 : //
726 : // Make sure that the event target points to the right object.
727 133 : aEvent->mTarget = aEvent->mTarget->GetTargetForEventTargetChain();
728 133 : NS_ENSURE_STATE(aEvent->mTarget);
729 : }
730 :
731 499 : if (retargeted) {
732 : aEvent->mOriginalTarget =
733 0 : aEvent->mOriginalTarget->GetTargetForEventTargetChain();
734 0 : NS_ENSURE_STATE(aEvent->mOriginalTarget);
735 : }
736 : else {
737 499 : aEvent->mOriginalTarget = aEvent->mTarget;
738 : }
739 :
740 998 : nsCOMPtr<nsIContent> content = do_QueryInterface(aEvent->mOriginalTarget);
741 594 : bool isInAnon = (content && (content->IsInAnonymousSubtree() ||
742 1093 : content->IsInShadowTree()));
743 :
744 499 : aEvent->mFlags.mIsBeingDispatched = true;
745 :
746 : // Create visitor object and start event dispatching.
747 : // GetEventTargetParent for the original target.
748 499 : nsEventStatus status = aEventStatus ? *aEventStatus : nsEventStatus_eIgnore;
749 : EventChainPreVisitor preVisitor(aPresContext, aEvent, aDOMEvent, status,
750 998 : isInAnon);
751 499 : targetEtci->GetEventTargetParent(preVisitor);
752 :
753 499 : if (!preVisitor.mCanHandle) {
754 : targetEtci = MayRetargetToChromeIfCanNotHandleEvent(chain, preVisitor,
755 : targetEtci, nullptr,
756 0 : content);
757 : }
758 499 : if (!preVisitor.mCanHandle) {
759 : // The original target and chrome target (mAutomaticChromeDispatch=true)
760 : // can not handle the event but we still have to call their PreHandleEvent.
761 0 : for (uint32_t i = 0; i < chain.Length(); ++i) {
762 0 : chain[i].PreHandleEvent(preVisitor);
763 : }
764 : } else {
765 : // At least the original target can handle the event.
766 : // Setting the retarget to the |target| simplifies retargeting code.
767 998 : nsCOMPtr<EventTarget> t = do_QueryInterface(aEvent->mTarget);
768 499 : targetEtci->SetNewTarget(t);
769 499 : EventTargetChainItem* topEtci = targetEtci;
770 499 : targetEtci = nullptr;
771 4147 : while (preVisitor.mParentTarget) {
772 1824 : EventTarget* parentTarget = preVisitor.mParentTarget;
773 : EventTargetChainItem* parentEtci =
774 1824 : EventTargetChainItem::Create(chain, preVisitor.mParentTarget, topEtci);
775 1824 : if (!parentEtci->IsValid()) {
776 0 : EventTargetChainItem::DestroyLast(chain, parentEtci);
777 0 : rv = NS_ERROR_FAILURE;
778 0 : break;
779 : }
780 :
781 : // Item needs event retargetting.
782 1824 : if (preVisitor.mEventTargetAtParent) {
783 : // Need to set the target of the event
784 : // so that also the next retargeting works.
785 91 : preVisitor.mEvent->mTarget = preVisitor.mEventTargetAtParent;
786 91 : parentEtci->SetNewTarget(preVisitor.mEventTargetAtParent);
787 : }
788 :
789 1824 : parentEtci->GetEventTargetParent(preVisitor);
790 1824 : if (preVisitor.mCanHandle) {
791 1824 : topEtci = parentEtci;
792 : } else {
793 0 : nsCOMPtr<nsINode> disabledTarget = do_QueryInterface(parentTarget);
794 0 : parentEtci = MayRetargetToChromeIfCanNotHandleEvent(chain,
795 : preVisitor,
796 : parentEtci,
797 : topEtci,
798 0 : disabledTarget);
799 0 : if (parentEtci && preVisitor.mCanHandle) {
800 : EventTargetChainItem* item =
801 0 : EventTargetChainItem::GetFirstCanHandleEventTarget(chain);
802 0 : item->SetNewTarget(parentTarget);
803 0 : topEtci = parentEtci;
804 0 : continue;
805 : }
806 0 : break;
807 : }
808 : }
809 499 : if (NS_SUCCEEDED(rv)) {
810 499 : if (aTargets) {
811 50 : aTargets->Clear();
812 50 : uint32_t numTargets = chain.Length();
813 50 : EventTarget** targets = aTargets->AppendElements(numTargets);
814 202 : for (uint32_t i = 0; i < numTargets; ++i) {
815 152 : targets[i] = chain[i].CurrentTarget()->GetTargetForDOMEvent();
816 : }
817 : } else {
818 : // Event target chain is created. PreHandle the chain.
819 2620 : for (uint32_t i = 0; i < chain.Length(); ++i) {
820 2171 : chain[i].PreHandleEvent(preVisitor);
821 : }
822 : // Handle the chain.
823 898 : EventChainPostVisitor postVisitor(preVisitor);
824 : EventTargetChainItem::HandleEventTargetChain(chain, postVisitor,
825 449 : aCallback, cd);
826 :
827 449 : preVisitor.mEventStatus = postVisitor.mEventStatus;
828 : // If the DOM event was created during event flow.
829 449 : if (!preVisitor.mDOMEvent && postVisitor.mDOMEvent) {
830 31 : preVisitor.mDOMEvent = postVisitor.mDOMEvent;
831 : }
832 : }
833 : }
834 : }
835 :
836 : // Note, EventTargetChainItem objects are deleted when the chain goes out of
837 : // the scope.
838 :
839 499 : aEvent->mFlags.mIsBeingDispatched = false;
840 499 : aEvent->mFlags.mDispatchedAtLeastOnce = true;
841 :
842 499 : if (!externalDOMEvent && preVisitor.mDOMEvent) {
843 : // An dom::Event was created while dispatching the event.
844 : // Duplicate private data if someone holds a pointer to it.
845 31 : nsrefcnt rc = 0;
846 31 : NS_RELEASE2(preVisitor.mDOMEvent, rc);
847 31 : if (preVisitor.mDOMEvent) {
848 25 : preVisitor.mDOMEvent->DuplicatePrivateData();
849 : }
850 : }
851 :
852 499 : if (aEventStatus) {
853 303 : *aEventStatus = preVisitor.mEventStatus;
854 : }
855 :
856 499 : if (cd.IsMainThread() && chain.Capacity() == 128 && sCachedMainThreadChain) {
857 482 : chain.ClearAndRetainStorage();
858 482 : chain.SwapElements(*sCachedMainThreadChain);
859 : }
860 :
861 499 : return rv;
862 : }
863 :
864 : /* static */ nsresult
865 294 : EventDispatcher::DispatchDOMEvent(nsISupports* aTarget,
866 : WidgetEvent* aEvent,
867 : nsIDOMEvent* aDOMEvent,
868 : nsPresContext* aPresContext,
869 : nsEventStatus* aEventStatus)
870 : {
871 294 : if (aDOMEvent) {
872 290 : WidgetEvent* innerEvent = aDOMEvent->WidgetEventPtr();
873 290 : NS_ENSURE_TRUE(innerEvent, NS_ERROR_ILLEGAL_VALUE);
874 :
875 290 : bool dontResetTrusted = false;
876 290 : if (innerEvent->mFlags.mDispatchedAtLeastOnce) {
877 0 : innerEvent->mTarget = nullptr;
878 0 : innerEvent->mOriginalTarget = nullptr;
879 : } else {
880 290 : aDOMEvent->GetIsTrusted(&dontResetTrusted);
881 : }
882 :
883 290 : if (!dontResetTrusted) {
884 : //Check security state to determine if dispatcher is trusted
885 6 : bool trusted = NS_IsMainThread() ? nsContentUtils::LegacyIsCallerChromeOrNativeCode()
886 6 : : mozilla::dom::workers::IsCurrentThreadRunningChromeWorker();
887 6 : aDOMEvent->SetTrusted(trusted);
888 : }
889 :
890 : return EventDispatcher::Dispatch(aTarget, aPresContext, innerEvent,
891 290 : aDOMEvent, aEventStatus);
892 4 : } else if (aEvent) {
893 : return EventDispatcher::Dispatch(aTarget, aPresContext, aEvent,
894 4 : aDOMEvent, aEventStatus);
895 : }
896 0 : return NS_ERROR_ILLEGAL_VALUE;
897 : }
898 :
899 : /* static */ already_AddRefed<dom::Event>
900 158 : EventDispatcher::CreateEvent(EventTarget* aOwner,
901 : nsPresContext* aPresContext,
902 : WidgetEvent* aEvent,
903 : const nsAString& aEventType,
904 : CallerType aCallerType)
905 : {
906 158 : if (aEvent) {
907 31 : switch(aEvent->mClass) {
908 : case eMutationEventClass:
909 0 : return NS_NewDOMMutationEvent(aOwner, aPresContext,
910 0 : aEvent->AsMutationEvent());
911 : case eGUIEventClass:
912 : case eScrollPortEventClass:
913 : case eUIEventClass:
914 8 : return NS_NewDOMUIEvent(aOwner, aPresContext, aEvent->AsGUIEvent());
915 : case eScrollAreaEventClass:
916 0 : return NS_NewDOMScrollAreaEvent(aOwner, aPresContext,
917 0 : aEvent->AsScrollAreaEvent());
918 : case eKeyboardEventClass:
919 0 : return NS_NewDOMKeyboardEvent(aOwner, aPresContext,
920 0 : aEvent->AsKeyboardEvent());
921 : case eCompositionEventClass:
922 0 : return NS_NewDOMCompositionEvent(aOwner, aPresContext,
923 0 : aEvent->AsCompositionEvent());
924 : case eMouseEventClass:
925 5 : return NS_NewDOMMouseEvent(aOwner, aPresContext, aEvent->AsMouseEvent());
926 : case eFocusEventClass:
927 5 : return NS_NewDOMFocusEvent(aOwner, aPresContext, aEvent->AsFocusEvent());
928 : case eMouseScrollEventClass:
929 0 : return NS_NewDOMMouseScrollEvent(aOwner, aPresContext,
930 0 : aEvent->AsMouseScrollEvent());
931 : case eWheelEventClass:
932 0 : return NS_NewDOMWheelEvent(aOwner, aPresContext, aEvent->AsWheelEvent());
933 : case eEditorInputEventClass:
934 0 : return NS_NewDOMInputEvent(aOwner, aPresContext,
935 0 : aEvent->AsEditorInputEvent());
936 : case eDragEventClass:
937 0 : return NS_NewDOMDragEvent(aOwner, aPresContext, aEvent->AsDragEvent());
938 : case eClipboardEventClass:
939 0 : return NS_NewDOMClipboardEvent(aOwner, aPresContext,
940 0 : aEvent->AsClipboardEvent());
941 : case eSMILTimeEventClass:
942 0 : return NS_NewDOMTimeEvent(aOwner, aPresContext,
943 0 : aEvent->AsSMILTimeEvent());
944 : case eCommandEventClass:
945 0 : return NS_NewDOMCommandEvent(aOwner, aPresContext,
946 0 : aEvent->AsCommandEvent());
947 : case eSimpleGestureEventClass:
948 0 : return NS_NewDOMSimpleGestureEvent(aOwner, aPresContext,
949 0 : aEvent->AsSimpleGestureEvent());
950 : case ePointerEventClass:
951 0 : return NS_NewDOMPointerEvent(aOwner, aPresContext,
952 0 : aEvent->AsPointerEvent());
953 : case eTouchEventClass:
954 0 : return NS_NewDOMTouchEvent(aOwner, aPresContext, aEvent->AsTouchEvent());
955 : case eTransitionEventClass:
956 4 : return NS_NewDOMTransitionEvent(aOwner, aPresContext,
957 4 : aEvent->AsTransitionEvent());
958 : case eAnimationEventClass:
959 0 : return NS_NewDOMAnimationEvent(aOwner, aPresContext,
960 0 : aEvent->AsAnimationEvent());
961 : default:
962 : // For all other types of events, create a vanilla event object.
963 11 : return NS_NewDOMEvent(aOwner, aPresContext, aEvent);
964 : }
965 : }
966 :
967 : // And if we didn't get an event, check the type argument.
968 :
969 : #define LOG_EVENT_CREATION(name) mozilla::Telemetry::Accumulate( \
970 : mozilla::Telemetry::CREATE_EVENT_##name, true);
971 :
972 127 : if (aEventType.LowerCaseEqualsLiteral("mouseevent")) {
973 0 : LOG_EVENT_CREATION(MOUSEEVENT);
974 0 : return NS_NewDOMMouseEvent(aOwner, aPresContext, nullptr);
975 : }
976 127 : if (aEventType.LowerCaseEqualsLiteral("mouseevents")) {
977 0 : LOG_EVENT_CREATION(MOUSEEVENTS);
978 0 : return NS_NewDOMMouseEvent(aOwner, aPresContext, nullptr);
979 : }
980 127 : if (aEventType.LowerCaseEqualsLiteral("mousescrollevents")) {
981 0 : LOG_EVENT_CREATION(MOUSESCROLLEVENTS);
982 0 : return NS_NewDOMMouseScrollEvent(aOwner, aPresContext, nullptr);
983 : }
984 127 : if (aEventType.LowerCaseEqualsLiteral("dragevent")) {
985 0 : LOG_EVENT_CREATION(DRAGEVENT);
986 0 : return NS_NewDOMDragEvent(aOwner, aPresContext, nullptr);
987 : }
988 127 : if (aEventType.LowerCaseEqualsLiteral("keyboardevent")) {
989 0 : LOG_EVENT_CREATION(KEYBOARDEVENT);
990 0 : return NS_NewDOMKeyboardEvent(aOwner, aPresContext, nullptr);
991 : }
992 127 : if (aEventType.LowerCaseEqualsLiteral("keyevents")) {
993 0 : LOG_EVENT_CREATION(KEYEVENTS);
994 0 : return NS_NewDOMKeyboardEvent(aOwner, aPresContext, nullptr);
995 : }
996 127 : if (aEventType.LowerCaseEqualsLiteral("compositionevent")) {
997 0 : LOG_EVENT_CREATION(COMPOSITIONEVENT);
998 0 : return NS_NewDOMCompositionEvent(aOwner, aPresContext, nullptr);
999 : }
1000 127 : if (aEventType.LowerCaseEqualsLiteral("textevent")) {
1001 0 : LOG_EVENT_CREATION(TEXTEVENT);
1002 0 : return NS_NewDOMCompositionEvent(aOwner, aPresContext, nullptr);
1003 : }
1004 127 : if (aEventType.LowerCaseEqualsLiteral("mutationevent")) {
1005 0 : LOG_EVENT_CREATION(MUTATIONEVENT);
1006 0 : return NS_NewDOMMutationEvent(aOwner, aPresContext, nullptr);
1007 : }
1008 127 : if (aEventType.LowerCaseEqualsLiteral("mutationevents")) {
1009 0 : LOG_EVENT_CREATION(MUTATIONEVENTS);
1010 0 : return NS_NewDOMMutationEvent(aOwner, aPresContext, nullptr);
1011 : }
1012 127 : if (aEventType.LowerCaseEqualsLiteral("deviceorientationevent")) {
1013 0 : LOG_EVENT_CREATION(DEVICEORIENTATIONEVENT);
1014 0 : DeviceOrientationEventInit init;
1015 : RefPtr<Event> event =
1016 0 : DeviceOrientationEvent::Constructor(aOwner, EmptyString(), init);
1017 0 : event->MarkUninitialized();
1018 0 : return event.forget();
1019 : }
1020 127 : if (aEventType.LowerCaseEqualsLiteral("devicemotionevent")) {
1021 0 : LOG_EVENT_CREATION(DEVICEMOTIONEVENT);
1022 0 : return NS_NewDOMDeviceMotionEvent(aOwner, aPresContext, nullptr);
1023 : }
1024 127 : if (aEventType.LowerCaseEqualsLiteral("uievent")) {
1025 0 : LOG_EVENT_CREATION(UIEVENT);
1026 0 : return NS_NewDOMUIEvent(aOwner, aPresContext, nullptr);
1027 : }
1028 127 : if (aEventType.LowerCaseEqualsLiteral("uievents")) {
1029 0 : LOG_EVENT_CREATION(UIEVENTS);
1030 0 : return NS_NewDOMUIEvent(aOwner, aPresContext, nullptr);
1031 : }
1032 127 : if (aEventType.LowerCaseEqualsLiteral("event")) {
1033 0 : LOG_EVENT_CREATION(EVENT);
1034 0 : return NS_NewDOMEvent(aOwner, aPresContext, nullptr);
1035 : }
1036 127 : if (aEventType.LowerCaseEqualsLiteral("events")) {
1037 127 : LOG_EVENT_CREATION(EVENTS);
1038 127 : return NS_NewDOMEvent(aOwner, aPresContext, nullptr);
1039 : }
1040 0 : if (aEventType.LowerCaseEqualsLiteral("htmlevents")) {
1041 0 : LOG_EVENT_CREATION(HTMLEVENTS);
1042 0 : return NS_NewDOMEvent(aOwner, aPresContext, nullptr);
1043 : }
1044 0 : if (aEventType.LowerCaseEqualsLiteral("svgevents")) {
1045 0 : LOG_EVENT_CREATION(SVGEVENTS);
1046 0 : return NS_NewDOMEvent(aOwner, aPresContext, nullptr);
1047 : }
1048 0 : if (aEventType.LowerCaseEqualsLiteral("timeevent")) {
1049 0 : LOG_EVENT_CREATION(TIMEEVENT);
1050 0 : return NS_NewDOMTimeEvent(aOwner, aPresContext, nullptr);
1051 : }
1052 0 : if (aEventType.LowerCaseEqualsLiteral("messageevent")) {
1053 0 : LOG_EVENT_CREATION(MESSAGEEVENT);
1054 0 : RefPtr<Event> event = new MessageEvent(aOwner, aPresContext, nullptr);
1055 0 : return event.forget();
1056 : }
1057 0 : if (aEventType.LowerCaseEqualsLiteral("beforeunloadevent")) {
1058 0 : LOG_EVENT_CREATION(BEFOREUNLOADEVENT);
1059 0 : return NS_NewDOMBeforeUnloadEvent(aOwner, aPresContext, nullptr);
1060 : }
1061 0 : if (aEventType.LowerCaseEqualsLiteral("scrollareaevent")) {
1062 0 : LOG_EVENT_CREATION(SCROLLAREAEVENT);
1063 0 : return NS_NewDOMScrollAreaEvent(aOwner, aPresContext, nullptr);
1064 : }
1065 : // XXXkhuey Chrome supports popstateevent here, even though it provides no
1066 : // initPopStateEvent method. This is nuts ... but copying it is unlikely to
1067 : // break the web.
1068 0 : if (aEventType.LowerCaseEqualsLiteral("popstateevent")) {
1069 0 : LOG_EVENT_CREATION(POPSTATEEVENT);
1070 0 : AutoJSContext cx;
1071 0 : RootedDictionary<PopStateEventInit> init(cx);
1072 : RefPtr<Event> event =
1073 0 : PopStateEvent::Constructor(aOwner, EmptyString(), init);
1074 0 : event->MarkUninitialized();
1075 0 : return event.forget();
1076 : }
1077 0 : if (aEventType.LowerCaseEqualsLiteral("touchevent") &&
1078 0 : TouchEvent::PrefEnabled(nsContentUtils::GetDocShellForEventTarget(aOwner))) {
1079 0 : LOG_EVENT_CREATION(TOUCHEVENT);
1080 0 : return NS_NewDOMTouchEvent(aOwner, aPresContext, nullptr);
1081 : }
1082 0 : if (aEventType.LowerCaseEqualsLiteral("hashchangeevent")) {
1083 0 : LOG_EVENT_CREATION(HASHCHANGEEVENT);
1084 0 : HashChangeEventInit init;
1085 : RefPtr<Event> event =
1086 0 : HashChangeEvent::Constructor(aOwner, EmptyString(), init);
1087 0 : event->MarkUninitialized();
1088 0 : return event.forget();
1089 : }
1090 0 : if (aEventType.LowerCaseEqualsLiteral("customevent")) {
1091 0 : LOG_EVENT_CREATION(CUSTOMEVENT);
1092 0 : return NS_NewDOMCustomEvent(aOwner, aPresContext, nullptr);
1093 : }
1094 0 : if (aEventType.LowerCaseEqualsLiteral("storageevent")) {
1095 0 : LOG_EVENT_CREATION(STORAGEEVENT);
1096 : RefPtr<Event> event =
1097 0 : StorageEvent::Constructor(aOwner, EmptyString(), StorageEventInit());
1098 0 : event->MarkUninitialized();
1099 0 : return event.forget();
1100 : }
1101 0 : if (aEventType.LowerCaseEqualsLiteral("errorevent")) {
1102 0 : LOG_EVENT_CREATION(ERROREVENT);
1103 0 : RootedDictionary<ErrorEventInit> init(RootingCx());
1104 : RefPtr<Event> event =
1105 0 : ErrorEvent::Constructor(aOwner, EmptyString(), init);
1106 0 : event->MarkUninitialized();
1107 0 : return event.forget();
1108 : }
1109 :
1110 : // Only allow these events for chrome
1111 0 : if (aCallerType == CallerType::System) {
1112 0 : if (aEventType.LowerCaseEqualsLiteral("simplegestureevent")) {
1113 0 : return NS_NewDOMSimpleGestureEvent(aOwner, aPresContext, nullptr);
1114 : }
1115 0 : if (aEventType.LowerCaseEqualsLiteral("xulcommandevent")) {
1116 0 : LOG_EVENT_CREATION(XULCOMMANDEVENT);
1117 0 : return NS_NewDOMXULCommandEvent(aOwner, aPresContext, nullptr);
1118 : }
1119 0 : if (aEventType.LowerCaseEqualsLiteral("xulcommandevents")) {
1120 0 : LOG_EVENT_CREATION(XULCOMMANDEVENTS);
1121 0 : return NS_NewDOMXULCommandEvent(aOwner, aPresContext, nullptr);
1122 : }
1123 : }
1124 :
1125 : #undef LOG_EVENT_CREATION
1126 :
1127 : // NEW EVENT TYPES SHOULD NOT BE ADDED HERE; THEY SHOULD USE ONLY EVENT
1128 : // CONSTRUCTORS
1129 :
1130 0 : return nullptr;
1131 : }
1132 :
1133 : } // namespace mozilla
|