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 "AccessCheck.h"
8 : #include "base/basictypes.h"
9 : #include "ipc/IPCMessageUtils.h"
10 : #include "mozilla/dom/Event.h"
11 : #include "mozilla/dom/ShadowRoot.h"
12 : #include "mozilla/ContentEvents.h"
13 : #include "mozilla/DOMEventTargetHelper.h"
14 : #include "mozilla/EventStateManager.h"
15 : #include "mozilla/InternalMutationEvent.h"
16 : #include "mozilla/dom/Performance.h"
17 : #include "mozilla/MiscEvents.h"
18 : #include "mozilla/MouseEvents.h"
19 : #include "mozilla/Preferences.h"
20 : #include "mozilla/TextEvents.h"
21 : #include "mozilla/TouchEvents.h"
22 : #include "nsContentUtils.h"
23 : #include "nsCOMPtr.h"
24 : #include "nsDeviceContext.h"
25 : #include "nsError.h"
26 : #include "nsGlobalWindow.h"
27 : #include "nsIFrame.h"
28 : #include "nsIContent.h"
29 : #include "nsIDocument.h"
30 : #include "nsIPresShell.h"
31 : #include "nsIScrollableFrame.h"
32 : #include "nsJSEnvironment.h"
33 : #include "nsLayoutUtils.h"
34 : #include "nsPIWindowRoot.h"
35 : #include "nsRFPService.h"
36 : #include "WorkerPrivate.h"
37 :
38 : namespace mozilla {
39 : namespace dom {
40 :
41 : static char *sPopupAllowedEvents;
42 :
43 : static bool sReturnHighResTimeStamp = false;
44 : static bool sReturnHighResTimeStampIsSet = false;
45 :
46 366 : Event::Event(EventTarget* aOwner,
47 : nsPresContext* aPresContext,
48 366 : WidgetEvent* aEvent)
49 : {
50 366 : ConstructorInit(aOwner, aPresContext, aEvent);
51 366 : }
52 :
53 0 : Event::Event(nsPIDOMWindowInner* aParent)
54 : {
55 0 : ConstructorInit(nsGlobalWindow::Cast(aParent), nullptr, nullptr);
56 0 : }
57 :
58 : void
59 366 : Event::ConstructorInit(EventTarget* aOwner,
60 : nsPresContext* aPresContext,
61 : WidgetEvent* aEvent)
62 : {
63 366 : SetOwner(aOwner);
64 366 : mIsMainThreadEvent = NS_IsMainThread();
65 :
66 366 : if (mIsMainThreadEvent && !sReturnHighResTimeStampIsSet) {
67 2 : Preferences::AddBoolVarCache(&sReturnHighResTimeStamp,
68 : "dom.event.highrestimestamp.enabled",
69 2 : sReturnHighResTimeStamp);
70 2 : sReturnHighResTimeStampIsSet = true;
71 : }
72 :
73 366 : mPrivateDataDuplicated = false;
74 366 : mWantsPopupControlCheck = false;
75 :
76 366 : if (aEvent) {
77 31 : mEvent = aEvent;
78 31 : mEventIsInternal = false;
79 : }
80 : else {
81 335 : mEventIsInternal = true;
82 : /*
83 : A derived class might want to allocate its own type of aEvent
84 : (derived from WidgetEvent). To do this, it should take care to pass
85 : a non-nullptr aEvent to this ctor, e.g.:
86 :
87 : FooEvent::FooEvent(..., WidgetEvent* aEvent)
88 : : Event(..., aEvent ? aEvent : new WidgetEvent())
89 :
90 : Then, to override the mEventIsInternal assignments done by the
91 : base ctor, it should do this in its own ctor:
92 :
93 : FooEvent::FooEvent(..., WidgetEvent* aEvent)
94 : ...
95 : {
96 : ...
97 : if (aEvent) {
98 : mEventIsInternal = false;
99 : }
100 : else {
101 : mEventIsInternal = true;
102 : }
103 : ...
104 : }
105 : */
106 335 : mEvent = new WidgetEvent(false, eVoidEvent);
107 335 : mEvent->mTime = PR_Now();
108 : }
109 :
110 366 : InitPresContextData(aPresContext);
111 366 : }
112 :
113 : void
114 375 : Event::InitPresContextData(nsPresContext* aPresContext)
115 : {
116 375 : mPresContext = aPresContext;
117 : // Get the explicit original target (if it's anonymous make it null)
118 : {
119 750 : nsCOMPtr<nsIContent> content = GetTargetFromFrame();
120 375 : mExplicitOriginalTarget = content;
121 375 : if (content && content->IsInAnonymousSubtree()) {
122 4 : mExplicitOriginalTarget = nullptr;
123 : }
124 : }
125 375 : }
126 :
127 738 : Event::~Event()
128 : {
129 260 : NS_ASSERT_OWNINGTHREAD(Event);
130 :
131 260 : if (mEventIsInternal && mEvent) {
132 258 : delete mEvent;
133 : }
134 696 : }
135 :
136 2510 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Event)
137 354 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
138 269 : NS_INTERFACE_MAP_ENTRY(nsISupports)
139 269 : NS_INTERFACE_MAP_ENTRY(nsIDOMEvent)
140 0 : NS_INTERFACE_MAP_END
141 :
142 701 : NS_IMPL_CYCLE_COLLECTING_ADDREF(Event)
143 903 : NS_IMPL_CYCLE_COLLECTING_RELEASE(Event)
144 :
145 : NS_IMPL_CYCLE_COLLECTION_CLASS(Event)
146 :
147 350 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Event)
148 350 : NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
149 350 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
150 :
151 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Event)
152 0 : if (tmp->mEventIsInternal) {
153 0 : tmp->mEvent->mTarget = nullptr;
154 0 : tmp->mEvent->mCurrentTarget = nullptr;
155 0 : tmp->mEvent->mOriginalTarget = nullptr;
156 0 : switch (tmp->mEvent->mClass) {
157 : case eMouseEventClass:
158 : case eMouseScrollEventClass:
159 : case eWheelEventClass:
160 : case eSimpleGestureEventClass:
161 : case ePointerEventClass:
162 0 : tmp->mEvent->AsMouseEventBase()->relatedTarget = nullptr;
163 0 : break;
164 : case eDragEventClass: {
165 0 : WidgetDragEvent* dragEvent = tmp->mEvent->AsDragEvent();
166 0 : dragEvent->mDataTransfer = nullptr;
167 0 : dragEvent->relatedTarget = nullptr;
168 0 : break;
169 : }
170 : case eClipboardEventClass:
171 0 : tmp->mEvent->AsClipboardEvent()->mClipboardData = nullptr;
172 0 : break;
173 : case eMutationEventClass:
174 0 : tmp->mEvent->AsMutationEvent()->mRelatedNode = nullptr;
175 0 : break;
176 : case eFocusEventClass:
177 0 : tmp->mEvent->AsFocusEvent()->mRelatedTarget = nullptr;
178 0 : break;
179 : default:
180 0 : break;
181 : }
182 : }
183 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mPresContext);
184 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mExplicitOriginalTarget);
185 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner);
186 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
187 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
188 :
189 44 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Event)
190 44 : if (tmp->mEventIsInternal) {
191 20 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvent->mTarget)
192 20 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvent->mCurrentTarget)
193 20 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvent->mOriginalTarget)
194 20 : switch (tmp->mEvent->mClass) {
195 : case eMouseEventClass:
196 : case eMouseScrollEventClass:
197 : case eWheelEventClass:
198 : case eSimpleGestureEventClass:
199 : case ePointerEventClass:
200 0 : NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->relatedTarget");
201 0 : cb.NoteXPCOMChild(tmp->mEvent->AsMouseEventBase()->relatedTarget);
202 0 : break;
203 : case eDragEventClass: {
204 0 : WidgetDragEvent* dragEvent = tmp->mEvent->AsDragEvent();
205 0 : NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->mDataTransfer");
206 0 : cb.NoteXPCOMChild(dragEvent->mDataTransfer);
207 0 : NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->relatedTarget");
208 0 : cb.NoteXPCOMChild(dragEvent->relatedTarget);
209 0 : break;
210 : }
211 : case eClipboardEventClass:
212 0 : NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->mClipboardData");
213 0 : cb.NoteXPCOMChild(tmp->mEvent->AsClipboardEvent()->mClipboardData);
214 0 : break;
215 : case eMutationEventClass:
216 0 : NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->mRelatedNode");
217 0 : cb.NoteXPCOMChild(tmp->mEvent->AsMutationEvent()->mRelatedNode);
218 0 : break;
219 : case eFocusEventClass:
220 0 : NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->mRelatedTarget");
221 0 : cb.NoteXPCOMChild(tmp->mEvent->AsFocusEvent()->mRelatedTarget);
222 0 : break;
223 : default:
224 20 : break;
225 : }
226 : }
227 44 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresContext)
228 44 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExplicitOriginalTarget)
229 44 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
230 44 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
231 :
232 :
233 : JSObject*
234 56 : Event::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
235 : {
236 56 : return WrapObjectInternal(aCx, aGivenProto);
237 : }
238 :
239 : JSObject*
240 27 : Event::WrapObjectInternal(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
241 : {
242 27 : return EventBinding::Wrap(aCx, this, aGivenProto);
243 : }
244 :
245 : // nsIDOMEventInterface
246 : NS_IMETHODIMP
247 92 : Event::GetType(nsAString& aType)
248 : {
249 92 : if (!mIsMainThreadEvent) {
250 0 : aType = mEvent->mSpecifiedEventTypeString;
251 0 : return NS_OK;
252 : }
253 92 : GetWidgetEventType(mEvent, aType);
254 92 : return NS_OK;
255 : }
256 :
257 : EventTarget*
258 45 : Event::GetTarget() const
259 : {
260 45 : return mEvent->GetDOMEventTarget();
261 : }
262 :
263 : NS_IMETHODIMP
264 18 : Event::GetTarget(nsIDOMEventTarget** aTarget)
265 : {
266 18 : NS_IF_ADDREF(*aTarget = GetTarget());
267 18 : return NS_OK;
268 : }
269 :
270 : EventTarget*
271 30 : Event::GetCurrentTarget() const
272 : {
273 30 : return mEvent->GetCurrentDOMEventTarget();
274 : }
275 :
276 : NS_IMETHODIMP
277 0 : Event::GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget)
278 : {
279 0 : NS_IF_ADDREF(*aCurrentTarget = GetCurrentTarget());
280 0 : return NS_OK;
281 : }
282 :
283 : //
284 : // Get the actual event target node (may have been retargeted for mouse events)
285 : //
286 : already_AddRefed<nsIContent>
287 375 : Event::GetTargetFromFrame()
288 : {
289 375 : if (!mPresContext) { return nullptr; }
290 :
291 : // Get the mTarget frame (have to get the ESM first)
292 183 : nsIFrame* targetFrame = mPresContext->EventStateManager()->GetEventTarget();
293 183 : if (!targetFrame) { return nullptr; }
294 :
295 : // get the real content
296 10 : nsCOMPtr<nsIContent> realEventContent;
297 5 : targetFrame->GetContentForEvent(mEvent, getter_AddRefs(realEventContent));
298 5 : return realEventContent.forget();
299 : }
300 :
301 : EventTarget*
302 0 : Event::GetExplicitOriginalTarget() const
303 : {
304 0 : if (mExplicitOriginalTarget) {
305 0 : return mExplicitOriginalTarget;
306 : }
307 0 : return GetTarget();
308 : }
309 :
310 : NS_IMETHODIMP
311 0 : Event::GetExplicitOriginalTarget(nsIDOMEventTarget** aRealEventTarget)
312 : {
313 0 : NS_IF_ADDREF(*aRealEventTarget = GetExplicitOriginalTarget());
314 0 : return NS_OK;
315 : }
316 :
317 : EventTarget*
318 7 : Event::GetOriginalTarget() const
319 : {
320 7 : return mEvent->GetOriginalDOMEventTarget();
321 : }
322 :
323 : NS_IMETHODIMP
324 0 : Event::GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget)
325 : {
326 0 : NS_IF_ADDREF(*aOriginalTarget = GetOriginalTarget());
327 0 : return NS_OK;
328 : }
329 :
330 : EventTarget*
331 0 : Event::GetComposedTarget() const
332 : {
333 0 : EventTarget* et = GetOriginalTarget();
334 0 : nsCOMPtr<nsIContent> content = do_QueryInterface(et);
335 0 : if (!content) {
336 0 : return et;
337 : }
338 0 : nsIContent* nonChrome = content->FindFirstNonChromeOnlyAccessContent();
339 0 : return nonChrome ?
340 : static_cast<EventTarget*>(nonChrome) :
341 0 : static_cast<EventTarget*>(content->GetComposedDoc());
342 : }
343 :
344 : NS_IMETHODIMP_(void)
345 365 : Event::SetTrusted(bool aTrusted)
346 : {
347 365 : mEvent->mFlags.mIsTrusted = aTrusted;
348 365 : }
349 :
350 : bool
351 36 : Event::Init(mozilla::dom::EventTarget* aGlobal)
352 : {
353 36 : if (!mIsMainThreadEvent) {
354 8 : return workers::IsCurrentThreadRunningChromeWorker();
355 : }
356 28 : bool trusted = false;
357 56 : nsCOMPtr<nsPIDOMWindowInner> w = do_QueryInterface(aGlobal);
358 28 : if (w) {
359 18 : nsCOMPtr<nsIDocument> d = w->GetExtantDoc();
360 9 : if (d) {
361 9 : trusted = nsContentUtils::IsChromeDoc(d);
362 9 : nsIPresShell* s = d->GetShell();
363 9 : if (s) {
364 9 : InitPresContextData(s->GetPresContext());
365 : }
366 : }
367 : }
368 28 : return trusted;
369 : }
370 :
371 : // static
372 : already_AddRefed<Event>
373 0 : Event::Constructor(const GlobalObject& aGlobal,
374 : const nsAString& aType,
375 : const EventInit& aParam,
376 : ErrorResult& aRv)
377 : {
378 0 : nsCOMPtr<mozilla::dom::EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports());
379 0 : return Constructor(t, aType, aParam);
380 : }
381 :
382 : // static
383 : already_AddRefed<Event>
384 0 : Event::Constructor(EventTarget* aEventTarget,
385 : const nsAString& aType,
386 : const EventInit& aParam)
387 : {
388 0 : RefPtr<Event> e = new Event(aEventTarget, nullptr, nullptr);
389 0 : bool trusted = e->Init(aEventTarget);
390 0 : e->InitEvent(aType, aParam.mBubbles, aParam.mCancelable);
391 0 : e->SetTrusted(trusted);
392 0 : e->SetComposed(aParam.mComposed);
393 0 : return e.forget();
394 : }
395 :
396 : uint16_t
397 0 : Event::EventPhase() const
398 : {
399 : // Note, remember to check that this works also
400 : // if or when Bug 235441 is fixed.
401 0 : if ((mEvent->mCurrentTarget &&
402 0 : mEvent->mCurrentTarget == mEvent->mTarget) ||
403 0 : mEvent->mFlags.InTargetPhase()) {
404 0 : return nsIDOMEvent::AT_TARGET;
405 : }
406 0 : if (mEvent->mFlags.mInCapturePhase) {
407 0 : return nsIDOMEvent::CAPTURING_PHASE;
408 : }
409 0 : if (mEvent->mFlags.mInBubblingPhase) {
410 0 : return nsIDOMEvent::BUBBLING_PHASE;
411 : }
412 0 : return nsIDOMEvent::NONE;
413 : }
414 :
415 : NS_IMETHODIMP
416 0 : Event::GetEventPhase(uint16_t* aEventPhase)
417 : {
418 0 : *aEventPhase = EventPhase();
419 0 : return NS_OK;
420 : }
421 :
422 : NS_IMETHODIMP
423 0 : Event::GetBubbles(bool* aBubbles)
424 : {
425 0 : *aBubbles = Bubbles();
426 0 : return NS_OK;
427 : }
428 :
429 : NS_IMETHODIMP
430 0 : Event::GetCancelable(bool* aCancelable)
431 : {
432 0 : *aCancelable = Cancelable();
433 0 : return NS_OK;
434 : }
435 :
436 : NS_IMETHODIMP
437 0 : Event::GetTimeStamp(uint64_t* aTimeStamp)
438 : {
439 0 : *aTimeStamp = mEvent->mTime;
440 0 : return NS_OK;
441 : }
442 :
443 : NS_IMETHODIMP
444 0 : Event::StopPropagation()
445 : {
446 0 : mEvent->StopPropagation();
447 0 : return NS_OK;
448 : }
449 :
450 : NS_IMETHODIMP
451 0 : Event::StopImmediatePropagation()
452 : {
453 0 : mEvent->StopImmediatePropagation();
454 0 : return NS_OK;
455 : }
456 :
457 : NS_IMETHODIMP
458 0 : Event::StopCrossProcessForwarding()
459 : {
460 0 : mEvent->StopCrossProcessForwarding();
461 0 : return NS_OK;
462 : }
463 :
464 : NS_IMETHODIMP
465 290 : Event::GetIsTrusted(bool* aIsTrusted)
466 : {
467 290 : *aIsTrusted = IsTrusted();
468 290 : return NS_OK;
469 : }
470 :
471 : NS_IMETHODIMP
472 0 : Event::PreventDefault()
473 : {
474 : // This method is called only from C++ code which must handle default action
475 : // of this event. So, pass true always.
476 0 : PreventDefaultInternal(true);
477 0 : return NS_OK;
478 : }
479 :
480 : void
481 0 : Event::PreventDefault(JSContext* aCx, CallerType aCallerType)
482 : {
483 : // Note that at handling default action, another event may be dispatched.
484 : // Then, JS in content mey be call preventDefault()
485 : // even in the event is in system event group. Therefore, don't refer
486 : // mInSystemGroup here.
487 0 : PreventDefaultInternal(aCallerType == CallerType::System);
488 0 : }
489 :
490 : void
491 0 : Event::PreventDefaultInternal(bool aCalledByDefaultHandler)
492 : {
493 0 : if (!mEvent->mFlags.mCancelable) {
494 0 : return;
495 : }
496 0 : if (mEvent->mFlags.mInPassiveListener) {
497 0 : nsCOMPtr<nsPIDOMWindowInner> win(do_QueryInterface(mOwner));
498 0 : if (win) {
499 0 : if (nsIDocument* doc = win->GetExtantDoc()) {
500 0 : nsString type;
501 0 : GetType(type);
502 0 : const char16_t* params[] = { type.get() };
503 0 : doc->WarnOnceAbout(nsIDocument::ePreventDefaultFromPassiveListener,
504 0 : false, params, ArrayLength(params));
505 : }
506 : }
507 0 : return;
508 : }
509 :
510 0 : mEvent->PreventDefault(aCalledByDefaultHandler);
511 :
512 0 : if (!IsTrusted()) {
513 0 : return;
514 : }
515 :
516 0 : WidgetDragEvent* dragEvent = mEvent->AsDragEvent();
517 0 : if (!dragEvent) {
518 0 : return;
519 : }
520 :
521 0 : nsCOMPtr<nsINode> node = do_QueryInterface(mEvent->mCurrentTarget);
522 0 : if (!node) {
523 : nsCOMPtr<nsPIDOMWindowOuter> win =
524 0 : do_QueryInterface(mEvent->mCurrentTarget);
525 0 : if (!win) {
526 0 : return;
527 : }
528 0 : node = win->GetExtantDoc();
529 : }
530 0 : if (!nsContentUtils::IsChromeDoc(node->OwnerDoc())) {
531 0 : dragEvent->mDefaultPreventedOnContent = true;
532 : }
533 : }
534 :
535 : void
536 310 : Event::SetEventType(const nsAString& aEventTypeArg)
537 : {
538 310 : if (mIsMainThreadEvent) {
539 293 : mEvent->mSpecifiedEventTypeString.Truncate();
540 293 : mEvent->mSpecifiedEventType =
541 293 : nsContentUtils::GetEventMessageAndAtom(aEventTypeArg, mEvent->mClass,
542 879 : &(mEvent->mMessage));
543 293 : mEvent->SetDefaultComposed();
544 : } else {
545 17 : mEvent->mSpecifiedEventType = nullptr;
546 17 : mEvent->mMessage = eUnidentifiedEvent;
547 17 : mEvent->mSpecifiedEventTypeString = aEventTypeArg;
548 17 : mEvent->SetComposed(aEventTypeArg);
549 : }
550 310 : mEvent->SetDefaultComposedInNativeAnonymousContent();
551 310 : }
552 :
553 : already_AddRefed<EventTarget>
554 0 : Event::EnsureWebAccessibleRelatedTarget(EventTarget* aRelatedTarget)
555 : {
556 0 : nsCOMPtr<EventTarget> relatedTarget = aRelatedTarget;
557 0 : if (relatedTarget) {
558 0 : nsCOMPtr<nsIContent> content = do_QueryInterface(relatedTarget);
559 : nsCOMPtr<nsIContent> currentTarget =
560 0 : do_QueryInterface(mEvent->mCurrentTarget);
561 :
562 0 : if (content && content->ChromeOnlyAccess() &&
563 0 : !nsContentUtils::CanAccessNativeAnon()) {
564 0 : content = content->FindFirstNonChromeOnlyAccessContent();
565 0 : relatedTarget = do_QueryInterface(content);
566 : }
567 :
568 : nsIContent* shadowRelatedTarget =
569 0 : GetShadowRelatedTarget(currentTarget, content);
570 0 : if (shadowRelatedTarget) {
571 0 : relatedTarget = shadowRelatedTarget;
572 : }
573 :
574 0 : if (relatedTarget) {
575 0 : relatedTarget = relatedTarget->GetTargetForDOMEvent();
576 : }
577 : }
578 0 : return relatedTarget.forget();
579 : }
580 :
581 : void
582 310 : Event::InitEvent(const nsAString& aEventTypeArg,
583 : bool aCanBubbleArg,
584 : bool aCancelableArg)
585 : {
586 : // Make sure this event isn't already being dispatched.
587 310 : NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
588 :
589 310 : if (IsTrusted()) {
590 : // Ensure the caller is permitted to dispatch trusted DOM events.
591 0 : if (!nsContentUtils::ThreadsafeIsCallerChrome()) {
592 0 : SetTrusted(false);
593 : }
594 : }
595 :
596 310 : SetEventType(aEventTypeArg);
597 :
598 310 : mEvent->mFlags.mBubbles = aCanBubbleArg;
599 310 : mEvent->mFlags.mCancelable = aCancelableArg;
600 :
601 310 : mEvent->mFlags.mDefaultPrevented = false;
602 310 : mEvent->mFlags.mDefaultPreventedByContent = false;
603 310 : mEvent->mFlags.mDefaultPreventedByChrome = false;
604 310 : mEvent->mFlags.mPropagationStopped = false;
605 310 : mEvent->mFlags.mImmediatePropagationStopped = false;
606 :
607 : // Clearing the old targets, so that the event is targeted correctly when
608 : // re-dispatching it.
609 310 : mEvent->mTarget = nullptr;
610 310 : mEvent->mOriginalTarget = nullptr;
611 : }
612 :
613 : NS_IMETHODIMP
614 25 : Event::DuplicatePrivateData()
615 : {
616 25 : NS_ASSERTION(mEvent, "No WidgetEvent for Event duplication!");
617 25 : if (mEventIsInternal) {
618 0 : return NS_OK;
619 : }
620 :
621 25 : mEvent = mEvent->Duplicate();
622 25 : mPresContext = nullptr;
623 25 : mEventIsInternal = true;
624 25 : mPrivateDataDuplicated = true;
625 :
626 25 : return NS_OK;
627 : }
628 :
629 : NS_IMETHODIMP
630 163 : Event::SetTarget(nsIDOMEventTarget* aTarget)
631 : {
632 163 : mEvent->mTarget = do_QueryInterface(aTarget);
633 163 : return NS_OK;
634 : }
635 :
636 : NS_IMETHODIMP_(bool)
637 0 : Event::IsDispatchStopped()
638 : {
639 0 : return mEvent->PropagationStopped();
640 : }
641 :
642 : NS_IMETHODIMP_(WidgetEvent*)
643 774 : Event::WidgetEventPtr()
644 : {
645 774 : return mEvent;
646 : }
647 :
648 : NS_IMETHODIMP_(Event*)
649 603 : Event::InternalDOMEvent()
650 : {
651 603 : return this;
652 : }
653 :
654 : // return true if eventName is contained within events, delimited by
655 : // spaces
656 : static bool
657 0 : PopupAllowedForEvent(const char *eventName)
658 : {
659 0 : if (!sPopupAllowedEvents) {
660 0 : Event::PopupAllowedEventsChanged();
661 :
662 0 : if (!sPopupAllowedEvents) {
663 0 : return false;
664 : }
665 : }
666 :
667 0 : nsDependentCString events(sPopupAllowedEvents);
668 :
669 0 : nsCString::const_iterator start, end;
670 0 : nsCString::const_iterator startiter(events.BeginReading(start));
671 0 : events.EndReading(end);
672 :
673 0 : while (startiter != end) {
674 0 : nsCString::const_iterator enditer(end);
675 :
676 0 : if (!FindInReadable(nsDependentCString(eventName), startiter, enditer))
677 0 : return false;
678 :
679 : // the match is surrounded by spaces, or at a string boundary
680 0 : if ((startiter == start || *--startiter == ' ') &&
681 0 : (enditer == end || *enditer == ' ')) {
682 0 : return true;
683 : }
684 :
685 : // Move on and see if there are other matches. (The delimitation
686 : // requirement makes it pointless to begin the next search before
687 : // the end of the invalid match just found.)
688 0 : startiter = enditer;
689 : }
690 :
691 0 : return false;
692 : }
693 :
694 : // static
695 : PopupControlState
696 810 : Event::GetEventPopupControlState(WidgetEvent* aEvent, nsIDOMEvent* aDOMEvent)
697 : {
698 : // generally if an event handler is running, new windows are disallowed.
699 : // check for exceptions:
700 810 : PopupControlState abuse = openAbused;
701 :
702 810 : if (aDOMEvent && aDOMEvent->InternalDOMEvent()->GetWantsPopupControlCheck()) {
703 0 : nsAutoString type;
704 0 : aDOMEvent->GetType(type);
705 0 : if (PopupAllowedForEvent(NS_ConvertUTF16toUTF8(type).get())) {
706 0 : return openAllowed;
707 : }
708 : }
709 :
710 810 : switch(aEvent->mClass) {
711 : case eBasicEventClass:
712 : // For these following events only allow popups if they're
713 : // triggered while handling user input. See
714 : // nsPresShell::HandleEventInternal() for details.
715 576 : if (EventStateManager::IsHandlingUserInput()) {
716 0 : switch(aEvent->mMessage) {
717 : case eFormSelect:
718 0 : if (PopupAllowedForEvent("select")) {
719 0 : abuse = openControlled;
720 : }
721 0 : break;
722 : case eFormChange:
723 0 : if (PopupAllowedForEvent("change")) {
724 0 : abuse = openControlled;
725 : }
726 0 : break;
727 : default:
728 0 : break;
729 : }
730 : }
731 576 : break;
732 : case eEditorInputEventClass:
733 : // For this following event only allow popups if it's triggered
734 : // while handling user input. See
735 : // nsPresShell::HandleEventInternal() for details.
736 0 : if (EventStateManager::IsHandlingUserInput()) {
737 0 : switch(aEvent->mMessage) {
738 : case eEditorInput:
739 0 : if (PopupAllowedForEvent("input")) {
740 0 : abuse = openControlled;
741 : }
742 0 : break;
743 : default:
744 0 : break;
745 : }
746 : }
747 0 : break;
748 : case eInputEventClass:
749 : // For this following event only allow popups if it's triggered
750 : // while handling user input. See
751 : // nsPresShell::HandleEventInternal() for details.
752 0 : if (EventStateManager::IsHandlingUserInput()) {
753 0 : switch(aEvent->mMessage) {
754 : case eFormChange:
755 0 : if (PopupAllowedForEvent("change")) {
756 0 : abuse = openControlled;
757 : }
758 0 : break;
759 : case eXULCommand:
760 0 : abuse = openControlled;
761 0 : break;
762 : default:
763 0 : break;
764 : }
765 : }
766 0 : break;
767 : case eKeyboardEventClass:
768 0 : if (aEvent->IsTrusted()) {
769 0 : uint32_t key = aEvent->AsKeyboardEvent()->mKeyCode;
770 0 : switch(aEvent->mMessage) {
771 : case eKeyPress:
772 : // return key on focused button. see note at eMouseClick.
773 0 : if (key == NS_VK_RETURN) {
774 0 : abuse = openAllowed;
775 0 : } else if (PopupAllowedForEvent("keypress")) {
776 0 : abuse = openControlled;
777 : }
778 0 : break;
779 : case eKeyUp:
780 : // space key on focused button. see note at eMouseClick.
781 0 : if (key == NS_VK_SPACE) {
782 0 : abuse = openAllowed;
783 0 : } else if (PopupAllowedForEvent("keyup")) {
784 0 : abuse = openControlled;
785 : }
786 0 : break;
787 : case eKeyDown:
788 0 : if (PopupAllowedForEvent("keydown")) {
789 0 : abuse = openControlled;
790 : }
791 0 : break;
792 : default:
793 0 : break;
794 : }
795 : }
796 0 : break;
797 : case eTouchEventClass:
798 0 : if (aEvent->IsTrusted()) {
799 0 : switch (aEvent->mMessage) {
800 : case eTouchStart:
801 0 : if (PopupAllowedForEvent("touchstart")) {
802 0 : abuse = openControlled;
803 : }
804 0 : break;
805 : case eTouchEnd:
806 0 : if (PopupAllowedForEvent("touchend")) {
807 0 : abuse = openControlled;
808 : }
809 0 : break;
810 : default:
811 0 : break;
812 : }
813 : }
814 0 : break;
815 : case eMouseEventClass:
816 134 : if (aEvent->IsTrusted() &&
817 67 : aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
818 67 : switch(aEvent->mMessage) {
819 : case eMouseUp:
820 0 : if (PopupAllowedForEvent("mouseup")) {
821 0 : abuse = openControlled;
822 : }
823 0 : break;
824 : case eMouseDown:
825 0 : if (PopupAllowedForEvent("mousedown")) {
826 0 : abuse = openControlled;
827 : }
828 0 : break;
829 : case eMouseClick:
830 : /* Click events get special treatment because of their
831 : historical status as a more legitimate event handler. If
832 : click popups are enabled in the prefs, clear the popup
833 : status completely. */
834 0 : if (PopupAllowedForEvent("click")) {
835 0 : abuse = openAllowed;
836 : }
837 0 : break;
838 : case eMouseDoubleClick:
839 0 : if (PopupAllowedForEvent("dblclick")) {
840 0 : abuse = openControlled;
841 : }
842 0 : break;
843 : default:
844 67 : break;
845 : }
846 : }
847 67 : break;
848 : case ePointerEventClass:
849 84 : if (aEvent->IsTrusted() &&
850 42 : aEvent->AsPointerEvent()->button == WidgetMouseEvent::eLeftButton) {
851 7 : switch(aEvent->mMessage) {
852 : case ePointerUp:
853 0 : if (PopupAllowedForEvent("pointerup")) {
854 0 : abuse = openControlled;
855 : }
856 0 : break;
857 : case ePointerDown:
858 0 : if (PopupAllowedForEvent("pointerdown")) {
859 0 : abuse = openControlled;
860 : }
861 0 : break;
862 : default:
863 7 : break;
864 : }
865 : }
866 42 : break;
867 : case eFormEventClass:
868 : // For these following events only allow popups if they're
869 : // triggered while handling user input. See
870 : // nsPresShell::HandleEventInternal() for details.
871 0 : if (EventStateManager::IsHandlingUserInput()) {
872 0 : switch(aEvent->mMessage) {
873 : case eFormSubmit:
874 0 : if (PopupAllowedForEvent("submit")) {
875 0 : abuse = openControlled;
876 : }
877 0 : break;
878 : case eFormReset:
879 0 : if (PopupAllowedForEvent("reset")) {
880 0 : abuse = openControlled;
881 : }
882 0 : break;
883 : default:
884 0 : break;
885 : }
886 : }
887 0 : break;
888 : default:
889 125 : break;
890 : }
891 :
892 810 : return abuse;
893 : }
894 :
895 : // static
896 : void
897 0 : Event::PopupAllowedEventsChanged()
898 : {
899 0 : if (sPopupAllowedEvents) {
900 0 : free(sPopupAllowedEvents);
901 : }
902 :
903 0 : nsAdoptingCString str = Preferences::GetCString("dom.popup_allowed_events");
904 :
905 : // We'll want to do this even if str is empty to avoid looking up
906 : // this pref all the time if it's not set.
907 0 : sPopupAllowedEvents = ToNewCString(str);
908 0 : }
909 :
910 : // static
911 : void
912 0 : Event::Shutdown()
913 : {
914 0 : if (sPopupAllowedEvents) {
915 0 : free(sPopupAllowedEvents);
916 : }
917 0 : }
918 :
919 : // static
920 : CSSIntPoint
921 38 : Event::GetScreenCoords(nsPresContext* aPresContext,
922 : WidgetEvent* aEvent,
923 : LayoutDeviceIntPoint aPoint)
924 : {
925 38 : if (EventStateManager::sIsPointerLocked) {
926 0 : return EventStateManager::sLastScreenPoint;
927 : }
928 :
929 76 : if (!aEvent ||
930 50 : (aEvent->mClass != eMouseEventClass &&
931 24 : aEvent->mClass != eMouseScrollEventClass &&
932 24 : aEvent->mClass != eWheelEventClass &&
933 20 : aEvent->mClass != ePointerEventClass &&
934 16 : aEvent->mClass != eTouchEventClass &&
935 16 : aEvent->mClass != eDragEventClass &&
936 8 : aEvent->mClass != eSimpleGestureEventClass)) {
937 8 : return CSSIntPoint(0, 0);
938 : }
939 :
940 : // Doing a straight conversion from LayoutDeviceIntPoint to CSSIntPoint
941 : // seem incorrect, but it is needed to maintain legacy functionality.
942 30 : WidgetGUIEvent* guiEvent = aEvent->AsGUIEvent();
943 30 : if (!aPresContext || !(guiEvent && guiEvent->mWidget)) {
944 0 : return CSSIntPoint(aPoint.x, aPoint.y);
945 : }
946 :
947 : nsPoint pt =
948 30 : LayoutDevicePixel::ToAppUnits(aPoint, aPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom());
949 :
950 30 : if (nsIPresShell* ps = aPresContext->GetPresShell()) {
951 30 : pt = pt.RemoveResolution(nsLayoutUtils::GetCurrentAPZResolutionScale(ps));
952 : }
953 :
954 60 : pt += LayoutDevicePixel::ToAppUnits(guiEvent->mWidget->WidgetToScreenOffset(),
955 30 : aPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom());
956 :
957 30 : return CSSPixel::FromAppUnitsRounded(pt);
958 : }
959 :
960 : // static
961 : CSSIntPoint
962 12 : Event::GetPageCoords(nsPresContext* aPresContext,
963 : WidgetEvent* aEvent,
964 : LayoutDeviceIntPoint aPoint,
965 : CSSIntPoint aDefaultPoint)
966 : {
967 : CSSIntPoint pagePoint =
968 12 : Event::GetClientCoords(aPresContext, aEvent, aPoint, aDefaultPoint);
969 :
970 : // If there is some scrolling, add scroll info to client point.
971 12 : if (aPresContext && aPresContext->GetPresShell()) {
972 12 : nsIPresShell* shell = aPresContext->GetPresShell();
973 12 : nsIScrollableFrame* scrollframe = shell->GetRootScrollFrameAsScrollable();
974 12 : if (scrollframe) {
975 0 : pagePoint += CSSIntPoint::FromAppUnitsRounded(scrollframe->GetScrollPosition());
976 : }
977 : }
978 :
979 12 : return pagePoint;
980 : }
981 :
982 : // static
983 : CSSIntPoint
984 34 : Event::GetClientCoords(nsPresContext* aPresContext,
985 : WidgetEvent* aEvent,
986 : LayoutDeviceIntPoint aPoint,
987 : CSSIntPoint aDefaultPoint)
988 : {
989 34 : if (EventStateManager::sIsPointerLocked) {
990 0 : return EventStateManager::sLastClientPoint;
991 : }
992 :
993 68 : if (!aEvent ||
994 54 : (aEvent->mClass != eMouseEventClass &&
995 40 : aEvent->mClass != eMouseScrollEventClass &&
996 40 : aEvent->mClass != eWheelEventClass &&
997 40 : aEvent->mClass != eTouchEventClass &&
998 40 : aEvent->mClass != eDragEventClass &&
999 36 : aEvent->mClass != ePointerEventClass &&
1000 34 : aEvent->mClass != eSimpleGestureEventClass) ||
1001 52 : !aPresContext ||
1002 18 : !aEvent->AsGUIEvent()->mWidget) {
1003 16 : return aDefaultPoint;
1004 : }
1005 :
1006 18 : nsIPresShell* shell = aPresContext->GetPresShell();
1007 18 : if (!shell) {
1008 0 : return CSSIntPoint(0, 0);
1009 : }
1010 18 : nsIFrame* rootFrame = shell->GetRootFrame();
1011 18 : if (!rootFrame) {
1012 0 : return CSSIntPoint(0, 0);
1013 : }
1014 : nsPoint pt =
1015 18 : nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, aPoint, rootFrame);
1016 :
1017 18 : return CSSIntPoint::FromAppUnitsRounded(pt);
1018 : }
1019 :
1020 : // static
1021 : CSSIntPoint
1022 0 : Event::GetOffsetCoords(nsPresContext* aPresContext,
1023 : WidgetEvent* aEvent,
1024 : LayoutDeviceIntPoint aPoint,
1025 : CSSIntPoint aDefaultPoint)
1026 : {
1027 0 : if (!aEvent->mTarget) {
1028 0 : return GetPageCoords(aPresContext, aEvent, aPoint, aDefaultPoint);
1029 : }
1030 0 : nsCOMPtr<nsIContent> content = do_QueryInterface(aEvent->mTarget);
1031 0 : if (!content || !aPresContext) {
1032 0 : return CSSIntPoint(0, 0);
1033 : }
1034 0 : nsCOMPtr<nsIPresShell> shell = aPresContext->GetPresShell();
1035 0 : if (!shell) {
1036 0 : return CSSIntPoint(0, 0);
1037 : }
1038 0 : shell->FlushPendingNotifications(FlushType::Layout);
1039 0 : nsIFrame* frame = content->GetPrimaryFrame();
1040 0 : if (!frame) {
1041 0 : return CSSIntPoint(0, 0);
1042 : }
1043 0 : nsIFrame* rootFrame = shell->GetRootFrame();
1044 0 : if (!rootFrame) {
1045 0 : return CSSIntPoint(0, 0);
1046 : }
1047 : CSSIntPoint clientCoords =
1048 0 : GetClientCoords(aPresContext, aEvent, aPoint, aDefaultPoint);
1049 0 : nsPoint pt = CSSPixel::ToAppUnits(clientCoords);
1050 0 : if (nsLayoutUtils::TransformPoint(rootFrame, frame, pt) ==
1051 : nsLayoutUtils::TRANSFORM_SUCCEEDED) {
1052 0 : pt -= frame->GetPaddingRectRelativeToSelf().TopLeft();
1053 0 : return CSSPixel::FromAppUnitsRounded(pt);
1054 : }
1055 0 : return CSSIntPoint(0, 0);
1056 : }
1057 :
1058 : // To be called ONLY by Event::GetType (which has the additional
1059 : // logic for handling user-defined events).
1060 : // static
1061 : const char*
1062 87 : Event::GetEventName(EventMessage aEventType)
1063 : {
1064 87 : switch(aEventType) {
1065 : #define MESSAGE_TO_EVENT(name_, _message, _type, _struct) \
1066 : case _message: return #name_;
1067 : #include "mozilla/EventNameList.h"
1068 : #undef MESSAGE_TO_EVENT
1069 : default:
1070 31 : break;
1071 : }
1072 : // XXXldb We can hit this case for WidgetEvent objects that we didn't
1073 : // create and that are not user defined events since this function and
1074 : // SetEventType are incomplete. (But fixing that requires fixing the
1075 : // arrays in nsEventListenerManager too, since the events for which
1076 : // this is a problem generally *are* created by Event.)
1077 31 : return nullptr;
1078 : }
1079 :
1080 : bool
1081 12 : Event::DefaultPrevented(CallerType aCallerType) const
1082 : {
1083 12 : NS_ENSURE_TRUE(mEvent, false);
1084 :
1085 : // If preventDefault() has never been called, just return false.
1086 12 : if (!mEvent->DefaultPrevented()) {
1087 12 : return false;
1088 : }
1089 :
1090 : // If preventDefault() has been called by content, return true. Otherwise,
1091 : // i.e., preventDefault() has been called by chrome, return true only when
1092 : // this is called by chrome.
1093 0 : return mEvent->DefaultPreventedByContent() ||
1094 0 : aCallerType == CallerType::System;
1095 : }
1096 :
1097 : double
1098 0 : Event::TimeStampImpl() const
1099 : {
1100 0 : if (!sReturnHighResTimeStamp) {
1101 0 : return static_cast<double>(mEvent->mTime);
1102 : }
1103 :
1104 0 : if (mEvent->mTimeStamp.IsNull()) {
1105 0 : return 0.0;
1106 : }
1107 :
1108 0 : if (mIsMainThreadEvent) {
1109 0 : if (NS_WARN_IF(!mOwner)) {
1110 0 : return 0.0;
1111 : }
1112 :
1113 0 : nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(mOwner);
1114 0 : if (NS_WARN_IF(!win)) {
1115 0 : return 0.0;
1116 : }
1117 :
1118 0 : Performance* perf = win->GetPerformance();
1119 0 : if (NS_WARN_IF(!perf)) {
1120 0 : return 0.0;
1121 : }
1122 :
1123 0 : return perf->GetDOMTiming()->TimeStampToDOMHighRes(mEvent->mTimeStamp);
1124 : }
1125 :
1126 : workers::WorkerPrivate* workerPrivate =
1127 0 : workers::GetCurrentThreadWorkerPrivate();
1128 0 : MOZ_ASSERT(workerPrivate);
1129 :
1130 0 : return workerPrivate->TimeStampToDOMHighRes(mEvent->mTimeStamp);
1131 : }
1132 :
1133 : double
1134 0 : Event::TimeStamp() const
1135 : {
1136 0 : return nsRFPService::ReduceTimePrecisionAsMSecs(TimeStampImpl());
1137 : }
1138 :
1139 : bool
1140 0 : Event::GetPreventDefault() const
1141 : {
1142 0 : nsCOMPtr<nsPIDOMWindowInner> win(do_QueryInterface(mOwner));
1143 0 : if (win) {
1144 0 : if (nsIDocument* doc = win->GetExtantDoc()) {
1145 0 : doc->WarnOnceAbout(nsIDocument::eGetPreventDefault);
1146 : }
1147 : }
1148 : // GetPreventDefault() is legacy and Gecko specific method. Although,
1149 : // the result should be same as defaultPrevented, we don't need to break
1150 : // backward compatibility of legacy method. Let's behave traditionally.
1151 0 : return DefaultPrevented();
1152 : }
1153 :
1154 : NS_IMETHODIMP
1155 0 : Event::GetPreventDefault(bool* aReturn)
1156 : {
1157 0 : NS_ENSURE_ARG_POINTER(aReturn);
1158 0 : *aReturn = GetPreventDefault();
1159 0 : return NS_OK;
1160 : }
1161 :
1162 : NS_IMETHODIMP
1163 0 : Event::GetDefaultPrevented(bool* aReturn)
1164 : {
1165 0 : NS_ENSURE_ARG_POINTER(aReturn);
1166 : // This method must be called by only event handlers implemented by C++.
1167 : // Then, the handlers must handle default action. So, this method don't need
1168 : // to check if preventDefault() has been called by content or chrome.
1169 0 : *aReturn = DefaultPrevented();
1170 0 : return NS_OK;
1171 : }
1172 :
1173 : NS_IMETHODIMP_(void)
1174 0 : Event::Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType)
1175 : {
1176 0 : if (aSerializeInterfaceType) {
1177 0 : IPC::WriteParam(aMsg, NS_LITERAL_STRING("event"));
1178 : }
1179 :
1180 0 : nsString type;
1181 0 : GetType(type);
1182 0 : IPC::WriteParam(aMsg, type);
1183 :
1184 0 : IPC::WriteParam(aMsg, Bubbles());
1185 0 : IPC::WriteParam(aMsg, Cancelable());
1186 0 : IPC::WriteParam(aMsg, IsTrusted());
1187 0 : IPC::WriteParam(aMsg, Composed());
1188 :
1189 : // No timestamp serialization for now!
1190 0 : }
1191 :
1192 : NS_IMETHODIMP_(bool)
1193 0 : Event::Deserialize(const IPC::Message* aMsg, PickleIterator* aIter)
1194 : {
1195 0 : nsString type;
1196 0 : NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &type), false);
1197 :
1198 0 : bool bubbles = false;
1199 0 : NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &bubbles), false);
1200 :
1201 0 : bool cancelable = false;
1202 0 : NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &cancelable), false);
1203 :
1204 0 : bool trusted = false;
1205 0 : NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &trusted), false);
1206 :
1207 0 : bool composed = false;
1208 0 : NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &composed), false);
1209 :
1210 0 : InitEvent(type, bubbles, cancelable);
1211 0 : SetTrusted(trusted);
1212 0 : SetComposed(composed);
1213 :
1214 0 : return true;
1215 : }
1216 :
1217 : NS_IMETHODIMP_(void)
1218 366 : Event::SetOwner(EventTarget* aOwner)
1219 : {
1220 366 : mOwner = nullptr;
1221 :
1222 366 : if (!aOwner) {
1223 366 : return;
1224 : }
1225 :
1226 366 : nsCOMPtr<nsINode> n = do_QueryInterface(aOwner);
1227 366 : if (n) {
1228 291 : mOwner = n->OwnerDoc()->GetScopeObject();
1229 291 : return;
1230 : }
1231 :
1232 75 : nsCOMPtr<nsPIDOMWindowInner> w = do_QueryInterface(aOwner);
1233 75 : if (w) {
1234 38 : mOwner = do_QueryInterface(w);
1235 38 : return;
1236 : }
1237 :
1238 37 : nsCOMPtr<DOMEventTargetHelper> eth = do_QueryInterface(aOwner);
1239 37 : if (eth) {
1240 37 : mOwner = eth->GetParentObject();
1241 37 : return;
1242 : }
1243 :
1244 : #ifdef DEBUG
1245 0 : nsCOMPtr<nsPIWindowRoot> root = do_QueryInterface(aOwner);
1246 0 : MOZ_ASSERT(root, "Unexpected EventTarget!");
1247 : #endif
1248 : }
1249 :
1250 : // static
1251 : nsIContent*
1252 0 : Event::GetShadowRelatedTarget(nsIContent* aCurrentTarget,
1253 : nsIContent* aRelatedTarget)
1254 : {
1255 0 : if (!aCurrentTarget || !aRelatedTarget) {
1256 0 : return nullptr;
1257 : }
1258 :
1259 : // Walk up the ancestor node trees of the related target until
1260 : // we encounter the node tree of the current target in order
1261 : // to find the adjusted related target. Walking up the tree may
1262 : // not find a common ancestor node tree if the related target is in
1263 : // an ancestor tree, but in that case it does not need to be adjusted.
1264 0 : ShadowRoot* currentTargetShadow = aCurrentTarget->GetContainingShadow();
1265 0 : if (!currentTargetShadow) {
1266 0 : return nullptr;
1267 : }
1268 :
1269 0 : nsIContent* relatedTarget = aCurrentTarget;
1270 0 : while (relatedTarget) {
1271 0 : ShadowRoot* ancestorShadow = relatedTarget->GetContainingShadow();
1272 0 : if (currentTargetShadow == ancestorShadow) {
1273 0 : return relatedTarget;
1274 : }
1275 :
1276 : // Didn't find the ancestor tree, thus related target does not have to
1277 : // adjusted.
1278 0 : if (!ancestorShadow) {
1279 0 : return nullptr;
1280 : }
1281 :
1282 0 : relatedTarget = ancestorShadow->GetHost();
1283 : }
1284 :
1285 0 : return nullptr;
1286 : }
1287 :
1288 : void
1289 92 : Event::GetWidgetEventType(WidgetEvent* aEvent, nsAString& aType)
1290 : {
1291 92 : if (!aEvent->mSpecifiedEventTypeString.IsEmpty()) {
1292 5 : aType = aEvent->mSpecifiedEventTypeString;
1293 5 : return;
1294 : }
1295 :
1296 87 : const char* name = GetEventName(aEvent->mMessage);
1297 :
1298 87 : if (name) {
1299 56 : CopyASCIItoUTF16(name, aType);
1300 56 : return;
1301 62 : } else if (aEvent->mMessage == eUnidentifiedEvent &&
1302 31 : aEvent->mSpecifiedEventType) {
1303 : // Remove "on"
1304 31 : aType = Substring(nsDependentAtomString(aEvent->mSpecifiedEventType), 2);
1305 31 : aEvent->mSpecifiedEventTypeString = aType;
1306 31 : return;
1307 : }
1308 :
1309 0 : aType.Truncate();
1310 : }
1311 :
1312 : NS_IMETHODIMP
1313 0 : Event::GetCancelBubble(bool* aCancelBubble)
1314 : {
1315 0 : NS_ENSURE_ARG_POINTER(aCancelBubble);
1316 0 : *aCancelBubble = CancelBubble();
1317 0 : return NS_OK;
1318 : }
1319 :
1320 : NS_IMETHODIMP
1321 0 : Event::SetCancelBubble(bool aCancelBubble)
1322 : {
1323 0 : if (aCancelBubble) {
1324 0 : mEvent->StopPropagation();
1325 : }
1326 0 : return NS_OK;
1327 : }
1328 :
1329 : } // namespace dom
1330 : } // namespace mozilla
1331 :
1332 : using namespace mozilla;
1333 : using namespace mozilla::dom;
1334 :
1335 : already_AddRefed<Event>
1336 280 : NS_NewDOMEvent(EventTarget* aOwner,
1337 : nsPresContext* aPresContext,
1338 : WidgetEvent* aEvent)
1339 : {
1340 560 : RefPtr<Event> it = new Event(aOwner, aPresContext, aEvent);
1341 560 : return it.forget();
1342 : }
|