1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "PerformanceEventTiming.h"
8 #include "PerformanceMainThread.h"
9 #include "mozilla/StaticPrefs_dom.h"
10 #include "mozilla/dom/PerformanceEventTimingBinding.h"
11 #include "mozilla/dom/Document.h"
12 #include "mozilla/dom/Performance.h"
13 #include "mozilla/dom/Event.h"
14 #include "nsContentUtils.h"
15 #include "nsIDocShell.h"
18 namespace mozilla::dom
{
20 NS_IMPL_CYCLE_COLLECTION_INHERITED(PerformanceEventTiming
, PerformanceEntry
,
21 mPerformance
, mTarget
)
23 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformanceEventTiming
)
24 NS_INTERFACE_MAP_END_INHERITING(PerformanceEntry
)
26 NS_IMPL_ADDREF_INHERITED(PerformanceEventTiming
, PerformanceEntry
)
27 NS_IMPL_RELEASE_INHERITED(PerformanceEventTiming
, PerformanceEntry
)
29 PerformanceEventTiming::PerformanceEventTiming(Performance
* aPerformance
,
30 const nsAString
& aName
,
31 const TimeStamp
& aStartTime
,
33 EventMessage aMessage
)
34 : PerformanceEntry(aPerformance
->GetParentObject(), aName
, u
"event"_ns
),
35 mPerformance(aPerformance
),
36 mProcessingStart(aPerformance
->NowUnclamped()),
39 aPerformance
->GetDOMTiming()->TimeStampToDOMHighRes(aStartTime
)),
41 mCancelable(aIsCacelable
),
44 PerformanceEventTiming::PerformanceEventTiming(
45 const PerformanceEventTiming
& aEventTimingEntry
)
46 : PerformanceEntry(aEventTimingEntry
.mPerformance
->GetParentObject(),
47 nsDependentAtomString(aEventTimingEntry
.GetName()),
48 nsDependentAtomString(aEventTimingEntry
.GetEntryType())),
49 mPerformance(aEventTimingEntry
.mPerformance
),
50 mProcessingStart(aEventTimingEntry
.mProcessingStart
),
51 mProcessingEnd(aEventTimingEntry
.mProcessingEnd
),
52 mTarget(aEventTimingEntry
.mTarget
),
53 mStartTime(aEventTimingEntry
.mStartTime
),
54 mDuration(aEventTimingEntry
.mDuration
),
55 mCancelable(aEventTimingEntry
.mCancelable
),
56 mMessage(aEventTimingEntry
.mMessage
) {}
58 JSObject
* PerformanceEventTiming::WrapObject(
59 JSContext
* cx
, JS::Handle
<JSObject
*> aGivenProto
) {
60 return PerformanceEventTiming_Binding::Wrap(cx
, this, aGivenProto
);
63 already_AddRefed
<PerformanceEventTiming
>
64 PerformanceEventTiming::TryGenerateEventTiming(const EventTarget
* aTarget
,
65 const WidgetEvent
* aEvent
) {
66 MOZ_ASSERT(NS_IsMainThread());
67 if (!StaticPrefs::dom_enable_event_timing() ||
68 aEvent
->mFlags
.mOnlyChromeDispatch
) {
72 if (!aEvent
->IsTrusted()) {
76 switch (aEvent
->mMessage
) {
80 case eMouseDoubleClick
:
94 case ePointerGotCapture
:
95 case ePointerLostCapture
:
102 case eEditorBeforeInput
:
104 case eCompositionStart
:
105 case eCompositionUpdate
:
106 case eCompositionEnd
:
118 nsCOMPtr
<nsPIDOMWindowInner
> innerWindow
=
119 do_QueryInterface(aTarget
->GetOwnerGlobal());
124 if (Performance
* performance
= innerWindow
->GetPerformance()) {
125 const char16_t
* eventName
= Event::GetEventName(aEvent
->mMessage
);
126 MOZ_ASSERT(eventName
,
127 "User defined events shouldn't be considered as event timing");
128 return RefPtr
<PerformanceEventTiming
>(
129 new PerformanceEventTiming(
130 performance
, nsDependentString(eventName
),
131 aEvent
->mTimeStamp
, aEvent
->mFlags
.mCancelable
,
138 bool PerformanceEventTiming::ShouldAddEntryToBuffer(double aDuration
) const {
139 if (GetEntryType() == nsGkAtoms::firstInput
) {
142 MOZ_ASSERT(GetEntryType() == nsGkAtoms::event
);
143 return RawDuration() >= aDuration
;
146 bool PerformanceEventTiming::ShouldAddEntryToObserverBuffer(
147 PerformanceObserverInit
& aOption
) const {
148 if (!PerformanceEntry::ShouldAddEntryToObserverBuffer(aOption
)) {
152 const double minDuration
=
153 aOption
.mDurationThreshold
.WasPassed()
154 ? std::max(aOption
.mDurationThreshold
.Value(),
155 PerformanceMainThread::kDefaultEventTimingMinDuration
)
156 : PerformanceMainThread::kDefaultEventTimingDurationThreshold
;
158 return ShouldAddEntryToBuffer(minDuration
);
161 void PerformanceEventTiming::BufferEntryIfNeeded() {
162 if (ShouldAddEntryToBuffer(
163 PerformanceMainThread::kDefaultEventTimingDurationThreshold
)) {
164 if (GetEntryType() != nsGkAtoms::firstInput
) {
165 MOZ_ASSERT(GetEntryType() == nsGkAtoms::event
);
166 mPerformance
->BufferEventTimingEntryIfNeeded(this);
171 nsINode
* PerformanceEventTiming::GetTarget() const {
172 nsCOMPtr
<Element
> element
= do_QueryReferent(mTarget
);
177 nsCOMPtr
<nsPIDOMWindowInner
> global
=
178 do_QueryInterface(element
->GetOwnerGlobal());
182 return nsContentUtils::GetAnElementForTiming(element
, global
->GetExtantDoc(),
183 mPerformance
->GetParentObject());
186 void PerformanceEventTiming::FinalizeEventTiming(EventTarget
* aTarget
) {
190 nsCOMPtr
<nsPIDOMWindowInner
> global
=
191 do_QueryInterface(aTarget
->GetOwnerGlobal());
196 mProcessingEnd
= mPerformance
->NowUnclamped();
198 Element
* element
= Element::FromEventTarget(aTarget
);
199 if (!element
|| element
->ChromeOnlyAccess()) {
203 mTarget
= do_GetWeakReference(element
);
205 mPerformance
->InsertEventTimingEntry(this);
207 } // namespace mozilla::dom