tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

PerformanceEventTiming.cpp (7111B)


      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 "PerformanceEventTiming.h"
      8 
      9 #include <algorithm>
     10 
     11 #include "PerformanceInteractionMetrics.h"
     12 #include "PerformanceMainThread.h"
     13 #include "mozilla/EventForwards.h"
     14 #include "mozilla/MouseEvents.h"
     15 #include "mozilla/StaticPrefs_dom.h"
     16 #include "mozilla/TextEvents.h"
     17 #include "mozilla/dom/Document.h"
     18 #include "mozilla/dom/Event.h"
     19 #include "mozilla/dom/Performance.h"
     20 #include "mozilla/dom/PerformanceEventTimingBinding.h"
     21 #include "nsContentUtils.h"
     22 #include "nsGkAtoms.h"
     23 #include "nsIDocShell.h"
     24 
     25 namespace mozilla::dom {
     26 
     27 NS_IMPL_CYCLE_COLLECTION_INHERITED(PerformanceEventTiming, PerformanceEntry,
     28                                   mPerformance, mTarget)
     29 
     30 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformanceEventTiming)
     31 NS_INTERFACE_MAP_END_INHERITING(PerformanceEntry)
     32 
     33 NS_IMPL_ADDREF_INHERITED(PerformanceEventTiming, PerformanceEntry)
     34 NS_IMPL_RELEASE_INHERITED(PerformanceEventTiming, PerformanceEntry)
     35 
     36 PerformanceEventTiming::PerformanceEventTiming(Performance* aPerformance,
     37                                               const nsAString& aName,
     38                                               const TimeStamp& aStartTime,
     39                                               bool aIsCancelable,
     40                                               EventMessage aMessage)
     41    : PerformanceEntry(aPerformance->GetParentObject(), aName,
     42                       nsGkAtoms::event),
     43      mPerformance(aPerformance),
     44      mProcessingStart(aPerformance->NowUnclamped()),
     45      mProcessingEnd(0),
     46      mStartTime(
     47          aPerformance->GetDOMTiming()->TimeStampToDOMHighRes(aStartTime)),
     48      mCancelable(aIsCancelable),
     49      mMessage(aMessage) {}
     50 
     51 PerformanceEventTiming::PerformanceEventTiming(
     52    const PerformanceEventTiming& aEventTimingEntry)
     53    : PerformanceEntry(aEventTimingEntry.mPerformance->GetParentObject(),
     54                       nsDependentAtomString(aEventTimingEntry.GetName()),
     55                       aEventTimingEntry.GetEntryTypeAsStaticAtom()),
     56      mPerformance(aEventTimingEntry.mPerformance),
     57      mProcessingStart(aEventTimingEntry.mProcessingStart),
     58      mProcessingEnd(aEventTimingEntry.mProcessingEnd),
     59      mTarget(aEventTimingEntry.mTarget),
     60      mStartTime(aEventTimingEntry.mStartTime),
     61      mDuration(aEventTimingEntry.mDuration),
     62      mCancelable(aEventTimingEntry.mCancelable),
     63      mInteractionId(aEventTimingEntry.mInteractionId),
     64      mMessage(aEventTimingEntry.mMessage) {}
     65 
     66 JSObject* PerformanceEventTiming::WrapObject(
     67    JSContext* cx, JS::Handle<JSObject*> aGivenProto) {
     68  return PerformanceEventTiming_Binding::Wrap(cx, this, aGivenProto);
     69 }
     70 
     71 already_AddRefed<PerformanceEventTiming>
     72 PerformanceEventTiming::TryGenerateEventTiming(const EventTarget* aTarget,
     73                                               const WidgetEvent* aEvent) {
     74  MOZ_ASSERT(NS_IsMainThread());
     75  if (!StaticPrefs::dom_enable_event_timing() ||
     76      aEvent->mFlags.mOnlyChromeDispatch) {
     77    return nullptr;
     78  }
     79 
     80  if (!aEvent->IsTrusted()) {
     81    return nullptr;
     82  }
     83 
     84  switch (aEvent->mMessage) {
     85    case eContextMenu:
     86    case eMouseDoubleClick:
     87    case eMouseDown:
     88    case eMouseEnter:
     89    case eMouseLeave:
     90    case eMouseOut:
     91    case eMouseOver:
     92    case eMouseUp:
     93    case ePointerAuxClick:
     94    case ePointerClick:
     95    case ePointerOver:
     96    case ePointerEnter:
     97    case ePointerDown:
     98    case ePointerUp:
     99    case ePointerCancel:
    100    case ePointerOut:
    101    case ePointerLeave:
    102    case ePointerGotCapture:
    103    case ePointerLostCapture:
    104    case eTouchStart:
    105    case eTouchEnd:
    106    case eTouchCancel:
    107    case eKeyDown:
    108    case eKeyPress:
    109    case eKeyUp:
    110    case eEditorBeforeInput:
    111    case eEditorInput:
    112    case eCompositionStart:
    113    case eCompositionUpdate:
    114    case eCompositionEnd:
    115    case eDragStart:
    116    case eDragEnd:
    117    case eDragEnter:
    118    case eDragLeave:
    119    case eDragOver:
    120    case eDrop:
    121      break;
    122    default:
    123      return nullptr;
    124  }
    125 
    126  nsCOMPtr<nsPIDOMWindowInner> innerWindow =
    127      do_QueryInterface(aTarget->GetOwnerGlobal());
    128  if (!innerWindow) {
    129    return nullptr;
    130  }
    131 
    132  if (Performance* performance = innerWindow->GetPerformance()) {
    133    const char16_t* eventName = Event::GetEventName(aEvent->mMessage);
    134    MOZ_ASSERT(eventName,
    135               "User defined events shouldn't be considered as event timing");
    136    auto eventTiming =
    137        RefPtr<PerformanceEventTiming>(new PerformanceEventTiming(
    138            performance, nsDependentString(eventName), aEvent->mTimeStamp,
    139            aEvent->mFlags.mCancelable, aEvent->mMessage));
    140    performance->SetInteractionId(eventTiming, aEvent);
    141    return eventTiming.forget();
    142  }
    143  return nullptr;
    144 }
    145 
    146 bool PerformanceEventTiming::ShouldAddEntryToBuffer(double aDuration) const {
    147  if (GetEntryType() == nsGkAtoms::firstInput) {
    148    return true;
    149  }
    150  MOZ_ASSERT(GetEntryType() == nsGkAtoms::event);
    151  return RawDuration().valueOr(0) >= aDuration;
    152 }
    153 
    154 bool PerformanceEventTiming::ShouldAddEntryToObserverBuffer(
    155    PerformanceObserverInit& aOption) const {
    156  if (!PerformanceEntry::ShouldAddEntryToObserverBuffer(aOption)) {
    157    return false;
    158  }
    159 
    160  const double minDuration =
    161      aOption.mDurationThreshold.WasPassed()
    162          ? std::max(aOption.mDurationThreshold.Value(),
    163                     PerformanceMainThread::kDefaultEventTimingMinDuration)
    164          : PerformanceMainThread::kDefaultEventTimingDurationThreshold;
    165 
    166  return ShouldAddEntryToBuffer(minDuration);
    167 }
    168 
    169 void PerformanceEventTiming::BufferEntryIfNeeded() {
    170  if (ShouldAddEntryToBuffer(
    171          PerformanceMainThread::kDefaultEventTimingDurationThreshold)) {
    172    if (GetEntryType() != nsGkAtoms::firstInput) {
    173      MOZ_ASSERT(GetEntryType() == nsGkAtoms::event);
    174      mPerformance->BufferEventTimingEntryIfNeeded(this);
    175    }
    176  }
    177 }
    178 
    179 nsINode* PerformanceEventTiming::GetTarget() const {
    180  nsCOMPtr<Element> element = do_QueryReferent(mTarget);
    181  if (!element) {
    182    return nullptr;
    183  }
    184 
    185  nsCOMPtr<nsPIDOMWindowInner> global =
    186      do_QueryInterface(element->GetOwnerGlobal());
    187  if (!global) {
    188    return nullptr;
    189  }
    190  return nsContentUtils::GetAnElementForTiming(element, global->GetExtantDoc(),
    191                                               mPerformance->GetParentObject());
    192 }
    193 
    194 void PerformanceEventTiming::FinalizeEventTiming(const WidgetEvent* aEvent) {
    195  MOZ_ASSERT(aEvent);
    196  EventTarget* target = aEvent->mTarget;
    197  if (!target) {
    198    return;
    199  }
    200  nsCOMPtr<nsPIDOMWindowInner> global =
    201      do_QueryInterface(target->GetOwnerGlobal());
    202  if (!global) {
    203    return;
    204  }
    205 
    206  mProcessingEnd = mPerformance->NowUnclamped();
    207 
    208  Element* element = Element::FromEventTarget(target);
    209  if (!element || element->ChromeOnlyAccess()) {
    210    return;
    211  }
    212 
    213  mTarget = do_GetWeakReference(element);
    214 
    215  mPerformance->InsertEventTimingEntry(this);
    216 }
    217 }  // namespace mozilla::dom