tor-browser

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

PerformanceResourceTiming.h (8232B)


      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 #ifndef mozilla_dom_PerformanceResourceTiming_h___
      8 #define mozilla_dom_PerformanceResourceTiming_h___
      9 
     10 #include "Performance.h"
     11 #include "PerformanceEntry.h"
     12 #include "PerformanceServerTiming.h"
     13 #include "PerformanceTiming.h"
     14 #include "mozilla/UniquePtr.h"
     15 #include "nsCOMPtr.h"
     16 
     17 namespace mozilla::dom {
     18 enum class RenderBlockingStatusType : uint8_t;
     19 
     20 #define IMPL_RESOURCE_TIMING_TAO_PROTECTED_TIMING_PROP(name)                \
     21  DOMHighResTimeStamp name(nsIPrincipal& aSubjectPrincipal) const {         \
     22    bool allowed = !mTimingData->RedirectCountReal()                        \
     23                       ? TimingAllowedForCaller(aSubjectPrincipal)          \
     24                       : ReportRedirectForCaller(aSubjectPrincipal, false); \
     25    return allowed ? mTimingData->name##HighRes(mPerformance) : 0;          \
     26  }
     27 
     28 #define IMPL_RESOURCE_TIMING_TAO_PROTECTED_SIZE_PROP(name)                  \
     29  uint64_t name(nsIPrincipal& aSubjectPrincipal) const {                    \
     30    bool allowed = !mTimingData->RedirectCountReal()                        \
     31                       ? TimingAllowedForCaller(aSubjectPrincipal)          \
     32                       : ReportRedirectForCaller(aSubjectPrincipal, false); \
     33    return allowed ? mTimingData->name() : 0;                               \
     34  }
     35 
     36 #define IMPL_RESOURCE_TIMING_CORS_PROTECTED_SIZE_PROP(name)  \
     37  uint64_t name(nsIPrincipal& aSubjectPrincipal) const {     \
     38    if (BodyInfoAccessAllowedForCaller(aSubjectPrincipal)) { \
     39      return mTimingData->name();                            \
     40    }                                                        \
     41    return 0;                                                \
     42  }
     43 
     44 // http://www.w3.org/TR/resource-timing/#performanceresourcetiming
     45 class PerformanceResourceTiming : public PerformanceEntry {
     46 public:
     47  using TimeStamp = mozilla::TimeStamp;
     48 
     49  NS_DECL_ISUPPORTS_INHERITED
     50  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(
     51      PerformanceResourceTiming, PerformanceEntry)
     52 
     53  // aPerformanceTimingData and aPerformance must be non-null
     54  PerformanceResourceTiming(
     55      UniquePtr<PerformanceTimingData>&& aPerformanceTimingData,
     56      Performance* aPerformance, const nsAString& aName);
     57 
     58  virtual JSObject* WrapObject(JSContext* aCx,
     59                               JS::Handle<JSObject*> aGivenProto) override;
     60 
     61  virtual DOMHighResTimeStamp StartTime() const override;
     62 
     63  virtual DOMHighResTimeStamp Duration() const override {
     64    return ResponseEnd() - StartTime();
     65  }
     66 
     67  void GetInitiatorType(nsAString& aInitiatorType) const {
     68    aInitiatorType = mInitiatorType;
     69  }
     70 
     71  void SetInitiatorType(const nsAString& aInitiatorType) {
     72    mInitiatorType = aInitiatorType;
     73  }
     74 
     75  RenderBlockingStatusType RenderBlockingStatus() const;
     76 
     77  void GetNextHopProtocol(nsAString& aNextHopProtocol) const {
     78    if (mTimingData->TimingAllowed()) {
     79      aNextHopProtocol = mTimingData->NextHopProtocol();
     80    }
     81  }
     82 
     83  DOMHighResTimeStamp WorkerStart() const {
     84    return mTimingData->WorkerStartHighRes(mPerformance);
     85  }
     86 
     87  DOMHighResTimeStamp FetchStart() const;
     88 
     89  DOMHighResTimeStamp RedirectStart(nsIPrincipal& aSubjectPrincipal,
     90                                    bool aEnsureSameOriginAndIgnoreTAO) const {
     91    // We have to check if all the redirect URIs whether had the same origin or
     92    // different origins with TAO headers set (since there is no check in
     93    // RedirectStartHighRes())
     94    return ReportRedirectForCaller(aSubjectPrincipal,
     95                                   aEnsureSameOriginAndIgnoreTAO)
     96               ? mTimingData->RedirectStartHighRes(mPerformance)
     97               : 0;
     98  }
     99 
    100  virtual DOMHighResTimeStamp RedirectStart(
    101      nsIPrincipal& aSubjectPrincipal) const {
    102    return RedirectStart(aSubjectPrincipal,
    103                         false /* aEnsureSameOriginAndIgnoreTAO */);
    104  }
    105 
    106  DOMHighResTimeStamp RedirectEnd(nsIPrincipal& aSubjectPrincipal,
    107                                  bool aEnsureSameOriginAndIgnoreTAO) const {
    108    // We have to check if all the redirect URIs whether had the same origin or
    109    // different origins with TAO headers set (since there is no check in
    110    // RedirectEndHighRes())
    111    return ReportRedirectForCaller(aSubjectPrincipal,
    112                                   aEnsureSameOriginAndIgnoreTAO)
    113               ? mTimingData->RedirectEndHighRes(mPerformance)
    114               : 0;
    115  }
    116 
    117  virtual DOMHighResTimeStamp RedirectEnd(
    118      nsIPrincipal& aSubjectPrincipal) const {
    119    return RedirectEnd(aSubjectPrincipal,
    120                       false /* aEnsureSameOriginAndIgnoreTAO */);
    121  }
    122 
    123  IMPL_RESOURCE_TIMING_TAO_PROTECTED_TIMING_PROP(DomainLookupStart)
    124 
    125  IMPL_RESOURCE_TIMING_TAO_PROTECTED_TIMING_PROP(DomainLookupEnd)
    126 
    127  IMPL_RESOURCE_TIMING_TAO_PROTECTED_TIMING_PROP(ConnectStart)
    128 
    129  IMPL_RESOURCE_TIMING_TAO_PROTECTED_TIMING_PROP(ConnectEnd)
    130 
    131  IMPL_RESOURCE_TIMING_TAO_PROTECTED_TIMING_PROP(RequestStart)
    132 
    133  IMPL_RESOURCE_TIMING_TAO_PROTECTED_TIMING_PROP(ResponseStart)
    134 
    135  DOMHighResTimeStamp ResponseEnd() const {
    136    return mTimingData->ResponseEndHighRes(mPerformance);
    137  }
    138 
    139  IMPL_RESOURCE_TIMING_TAO_PROTECTED_TIMING_PROP(SecureConnectionStart)
    140 
    141  virtual const PerformanceResourceTiming* ToResourceTiming() const override {
    142    return this;
    143  }
    144 
    145  IMPL_RESOURCE_TIMING_CORS_PROTECTED_SIZE_PROP(EncodedBodySize);
    146  IMPL_RESOURCE_TIMING_CORS_PROTECTED_SIZE_PROP(DecodedBodySize);
    147 
    148  uint64_t TransferSize(nsIPrincipal& aSubjectPrincipal) const {
    149    const bool allowed =
    150        !mTimingData->RedirectCountReal()
    151            ? TimingAllowedForCaller(aSubjectPrincipal)
    152            : ReportRedirectForCaller(aSubjectPrincipal, false);
    153    if (!allowed) {
    154      return 0;
    155    }
    156    // Resource is cached.
    157    if (!mTimingData->TransferSize()) {
    158      return 0;
    159    }
    160    auto encodedBodySize = EncodedBodySize(aSubjectPrincipal);
    161    // The constant number added to transferSize replaces exposing the
    162    // total byte size of the HTTP headers, as that may expose the
    163    // presence of certain cookies.
    164    // https://github.com/w3c/resource-timing/issues/238
    165    return encodedBodySize + 300;
    166  }
    167 
    168  uint16_t ResponseStatus(nsIPrincipal& aSubjectPrincipal) const {
    169    if (BodyInfoAccessAllowedForCaller(aSubjectPrincipal)) {
    170      return mTimingData->ResponseStatus();
    171    }
    172    return 0;
    173  }
    174 
    175  void GetContentType(nsAString& aContentType,
    176                      nsIPrincipal& aSubjectPrincipal) const {
    177    if (BodyInfoAccessAllowedForCaller(aSubjectPrincipal) ==
    178        nsITimedChannel::BodyInfoAccess::ALLOW_ALL) {
    179      aContentType = mTimingData->ContentType();
    180    }
    181  }
    182 
    183  void GetServerTiming(nsTArray<RefPtr<PerformanceServerTiming>>& aRetval,
    184                       nsIPrincipal& aSubjectPrincipal);
    185 
    186  size_t SizeOfIncludingThis(
    187      mozilla::MallocSizeOf aMallocSizeOf) const override;
    188 
    189 protected:
    190  virtual ~PerformanceResourceTiming();
    191 
    192  size_t SizeOfExcludingThis(
    193      mozilla::MallocSizeOf aMallocSizeOf) const override;
    194 
    195  // Check if caller has access to the bodyInfo of the request, per Fetch spec.
    196  nsITimedChannel::BodyInfoAccess BodyInfoAccessAllowedForCaller(
    197      nsIPrincipal& aCaller) const;
    198 
    199  // Check if caller has access to cross-origin timings, either by the rules
    200  // from the spec, or based on addon permissions.
    201  bool TimingAllowedForCaller(nsIPrincipal& aCaller) const;
    202 
    203  // Check if cross-origin redirects should be reported to the caller.
    204  bool ReportRedirectForCaller(nsIPrincipal& aCaller,
    205                               bool aEnsureSameOriginAndIgnoreTAO) const;
    206 
    207  nsString mInitiatorType;
    208  const UniquePtr<PerformanceTimingData> mTimingData;  // always non-null
    209  RefPtr<Performance> mPerformance;
    210 
    211  // The same initial requested URI as the `name` attribute.
    212  nsCOMPtr<nsIURI> mOriginalURI;
    213 
    214 private:
    215  mutable Maybe<DOMHighResTimeStamp> mCachedStartTime;
    216 };
    217 
    218 }  // namespace mozilla::dom
    219 
    220 #endif /* mozilla_dom_PerformanceResourceTiming_h___ */