зеркало из https://github.com/mozilla/gecko-dev.git
227 строки
6.9 KiB
C++
227 строки
6.9 KiB
C++
/* -*- 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/dom/PerformanceEventTimingBinding.h"
|
|
#include "mozilla/dom/Document.h"
|
|
#include "mozilla/dom/Performance.h"
|
|
#include "mozilla/dom/Event.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 char* eventName = Event::GetEventName(aEvent->mMessage);
|
|
MOZ_ASSERT(eventName,
|
|
"User defined events shouldn't be considered as event timing");
|
|
return RefPtr<PerformanceEventTiming>(
|
|
new PerformanceEventTiming(
|
|
performance, NS_ConvertUTF8toUTF16(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 {
|
|
if (!mTarget) {
|
|
return nullptr;
|
|
}
|
|
|
|
nsCOMPtr<nsINode> target = do_QueryReferent(mTarget);
|
|
if (!target || !target->IsInUncomposedDoc()) {
|
|
return nullptr;
|
|
}
|
|
|
|
return target;
|
|
}
|
|
|
|
void PerformanceEventTiming::FinalizeEventTiming(EventTarget* aTarget) {
|
|
if (!aTarget) {
|
|
return;
|
|
}
|
|
nsCOMPtr<nsPIDOMWindowInner> global =
|
|
do_QueryInterface(aTarget->GetOwnerGlobal());
|
|
if (!global) {
|
|
return;
|
|
}
|
|
|
|
mProcessingEnd = mPerformance->NowUnclamped();
|
|
|
|
nsCOMPtr<nsINode> node = do_QueryInterface(aTarget);
|
|
if (!node || node->ChromeOnlyAccess()) {
|
|
return;
|
|
}
|
|
|
|
mTarget = do_GetWeakReference(GetAnElement(node, global->GetExtantDoc()));
|
|
|
|
mPerformance->InsertEventTimingEntry(this);
|
|
}
|
|
|
|
nsINode* PerformanceEventTiming::GetAnElement(nsINode* aTarget,
|
|
const Document* aDocument) {
|
|
if (!aTarget->IsInUncomposedDoc()) {
|
|
return nullptr;
|
|
}
|
|
|
|
if (!aDocument) {
|
|
nsCOMPtr<nsPIDOMWindowInner> inner =
|
|
do_QueryInterface(mPerformance->GetParentObject());
|
|
MOZ_ASSERT(inner);
|
|
aDocument = inner->GetExtantDoc();
|
|
}
|
|
|
|
MOZ_ASSERT(aDocument);
|
|
|
|
if (aTarget->GetComposedDoc() != aDocument ||
|
|
!aDocument->IsCurrentActiveDocument()) {
|
|
return nullptr;
|
|
}
|
|
|
|
return aTarget;
|
|
}
|
|
} // namespace mozilla::dom
|