summaryrefslogtreecommitdiffstats
path: root/dom/performance/PerformanceEventTiming.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/performance/PerformanceEventTiming.cpp')
-rw-r--r--dom/performance/PerformanceEventTiming.cpp207
1 files changed, 207 insertions, 0 deletions
diff --git a/dom/performance/PerformanceEventTiming.cpp b/dom/performance/PerformanceEventTiming.cpp
new file mode 100644
index 0000000000..7a89329362
--- /dev/null
+++ b/dom/performance/PerformanceEventTiming.cpp
@@ -0,0 +1,207 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "PerformanceEventTiming.h"
+#include "PerformanceMainThread.h"
+#include "mozilla/StaticPrefs_dom.h"
+#include "mozilla/dom/PerformanceEventTimingBinding.h"
+#include "mozilla/dom/Document.h"
+#include "mozilla/dom/Performance.h"
+#include "mozilla/dom/Event.h"
+#include "nsContentUtils.h"
+#include "nsIDocShell.h"
+#include <algorithm>
+
+namespace mozilla::dom {
+
+NS_IMPL_CYCLE_COLLECTION_INHERITED(PerformanceEventTiming, PerformanceEntry,
+ mPerformance, mTarget)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformanceEventTiming)
+NS_INTERFACE_MAP_END_INHERITING(PerformanceEntry)
+
+NS_IMPL_ADDREF_INHERITED(PerformanceEventTiming, PerformanceEntry)
+NS_IMPL_RELEASE_INHERITED(PerformanceEventTiming, PerformanceEntry)
+
+PerformanceEventTiming::PerformanceEventTiming(Performance* aPerformance,
+ const nsAString& aName,
+ const TimeStamp& aStartTime,
+ bool aIsCacelable,
+ EventMessage aMessage)
+ : PerformanceEntry(aPerformance->GetParentObject(), aName, u"event"_ns),
+ mPerformance(aPerformance),
+ mProcessingStart(aPerformance->NowUnclamped()),
+ mProcessingEnd(0),
+ mStartTime(
+ aPerformance->GetDOMTiming()->TimeStampToDOMHighRes(aStartTime)),
+ mDuration(0),
+ mCancelable(aIsCacelable),
+ mMessage(aMessage) {}
+
+PerformanceEventTiming::PerformanceEventTiming(
+ const PerformanceEventTiming& aEventTimingEntry)
+ : PerformanceEntry(aEventTimingEntry.mPerformance->GetParentObject(),
+ nsDependentAtomString(aEventTimingEntry.GetName()),
+ nsDependentAtomString(aEventTimingEntry.GetEntryType())),
+ mPerformance(aEventTimingEntry.mPerformance),
+ mProcessingStart(aEventTimingEntry.mProcessingStart),
+ mProcessingEnd(aEventTimingEntry.mProcessingEnd),
+ mTarget(aEventTimingEntry.mTarget),
+ mStartTime(aEventTimingEntry.mStartTime),
+ mDuration(aEventTimingEntry.mDuration),
+ mCancelable(aEventTimingEntry.mCancelable),
+ mMessage(aEventTimingEntry.mMessage) {}
+
+JSObject* PerformanceEventTiming::WrapObject(
+ JSContext* cx, JS::Handle<JSObject*> aGivenProto) {
+ return PerformanceEventTiming_Binding::Wrap(cx, this, aGivenProto);
+}
+
+already_AddRefed<PerformanceEventTiming>
+PerformanceEventTiming::TryGenerateEventTiming(const EventTarget* aTarget,
+ const WidgetEvent* aEvent) {
+ MOZ_ASSERT(NS_IsMainThread());
+ if (!StaticPrefs::dom_enable_event_timing() ||
+ aEvent->mFlags.mOnlyChromeDispatch) {
+ return nullptr;
+ }
+
+ if (!aEvent->IsTrusted()) {
+ return nullptr;
+ }
+
+ switch (aEvent->mMessage) {
+ case eMouseAuxClick:
+ case eMouseClick:
+ case eContextMenu:
+ case eMouseDoubleClick:
+ case eMouseDown:
+ case eMouseEnter:
+ case eMouseLeave:
+ case eMouseOut:
+ case eMouseOver:
+ case eMouseUp:
+ case ePointerOver:
+ case ePointerEnter:
+ case ePointerDown:
+ case ePointerUp:
+ case ePointerCancel:
+ case ePointerOut:
+ case ePointerLeave:
+ case ePointerGotCapture:
+ case ePointerLostCapture:
+ case eTouchStart:
+ case eTouchEnd:
+ case eTouchCancel:
+ case eKeyDown:
+ case eKeyPress:
+ case eKeyUp:
+ case eEditorBeforeInput:
+ case eEditorInput:
+ case eCompositionStart:
+ case eCompositionUpdate:
+ case eCompositionEnd:
+ case eDragStart:
+ case eDragEnd:
+ case eDragEnter:
+ case eDragLeave:
+ case eDragOver:
+ case eDrop:
+ break;
+ default:
+ return nullptr;
+ }
+
+ nsCOMPtr<nsPIDOMWindowInner> innerWindow =
+ do_QueryInterface(aTarget->GetOwnerGlobal());
+ if (!innerWindow) {
+ return nullptr;
+ }
+
+ if (Performance* performance = innerWindow->GetPerformance()) {
+ const char16_t* eventName = Event::GetEventName(aEvent->mMessage);
+ MOZ_ASSERT(eventName,
+ "User defined events shouldn't be considered as event timing");
+ return RefPtr<PerformanceEventTiming>(
+ new PerformanceEventTiming(
+ performance, nsDependentString(eventName),
+ aEvent->mTimeStamp, aEvent->mFlags.mCancelable,
+ aEvent->mMessage))
+ .forget();
+ }
+ return nullptr;
+}
+
+bool PerformanceEventTiming::ShouldAddEntryToBuffer(double aDuration) const {
+ if (GetEntryType() == nsGkAtoms::firstInput) {
+ return true;
+ }
+ MOZ_ASSERT(GetEntryType() == nsGkAtoms::event);
+ return RawDuration() >= aDuration;
+}
+
+bool PerformanceEventTiming::ShouldAddEntryToObserverBuffer(
+ PerformanceObserverInit& aOption) const {
+ if (!PerformanceEntry::ShouldAddEntryToObserverBuffer(aOption)) {
+ return false;
+ }
+
+ const double minDuration =
+ aOption.mDurationThreshold.WasPassed()
+ ? std::max(aOption.mDurationThreshold.Value(),
+ PerformanceMainThread::kDefaultEventTimingMinDuration)
+ : PerformanceMainThread::kDefaultEventTimingDurationThreshold;
+
+ return ShouldAddEntryToBuffer(minDuration);
+}
+
+void PerformanceEventTiming::BufferEntryIfNeeded() {
+ if (ShouldAddEntryToBuffer(
+ PerformanceMainThread::kDefaultEventTimingDurationThreshold)) {
+ if (GetEntryType() != nsGkAtoms::firstInput) {
+ MOZ_ASSERT(GetEntryType() == nsGkAtoms::event);
+ mPerformance->BufferEventTimingEntryIfNeeded(this);
+ }
+ }
+}
+
+nsINode* PerformanceEventTiming::GetTarget() const {
+ nsCOMPtr<Element> element = do_QueryReferent(mTarget);
+ if (!element) {
+ return nullptr;
+ }
+
+ nsCOMPtr<nsPIDOMWindowInner> global =
+ do_QueryInterface(element->GetOwnerGlobal());
+ if (!global) {
+ return nullptr;
+ }
+ return nsContentUtils::GetAnElementForTiming(element, global->GetExtantDoc(),
+ mPerformance->GetParentObject());
+}
+
+void PerformanceEventTiming::FinalizeEventTiming(EventTarget* aTarget) {
+ if (!aTarget) {
+ return;
+ }
+ nsCOMPtr<nsPIDOMWindowInner> global =
+ do_QueryInterface(aTarget->GetOwnerGlobal());
+ if (!global) {
+ return;
+ }
+
+ mProcessingEnd = mPerformance->NowUnclamped();
+
+ Element* element = Element::FromEventTarget(aTarget);
+ if (!element || element->ChromeOnlyAccess()) {
+ return;
+ }
+
+ mTarget = do_GetWeakReference(element);
+
+ mPerformance->InsertEventTimingEntry(this);
+}
+} // namespace mozilla::dom