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