tor-browser

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

RTCStatsReport.h (7577B)


      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 https://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef RTCStatsReport_h_
      8 #define RTCStatsReport_h_
      9 
     10 #include "api/units/timestamp.h"  // webrtc::Timestamp
     11 #include "js/RootingAPI.h"        // JS::Rooted
     12 #include "js/Value.h"
     13 #include "mozilla/ErrorResult.h"
     14 #include "mozilla/MozPromise.h"
     15 #include "mozilla/TimeStamp.h"
     16 #include "mozilla/UniquePtr.h"
     17 #include "mozilla/dom/AutoEntryScript.h"
     18 #include "mozilla/dom/PerformanceService.h"
     19 #include "mozilla/dom/RTCStatsReportBinding.h"  // RTCStatsCollection
     20 #include "mozilla/dom/ToJSValue.h"
     21 #include "nsCOMPtr.h"
     22 #include "nsContentUtils.h"
     23 #include "nsIGlobalObject.h"
     24 #include "nsPIDOMWindow.h"  // nsPIDOMWindowInner
     25 #include "nsWrapperCache.h"
     26 #include "prtime.h"  // PR_Now
     27 
     28 namespace mozilla {
     29 
     30 extern TimeStamp WebrtcSystemTimeBase();
     31 
     32 namespace dom {
     33 
     34 /**
     35 * Keeps the state needed to convert RTCStatsTimestamps.
     36 */
     37 struct RTCStatsTimestampState {
     38  RTCStatsTimestampState();
     39  explicit RTCStatsTimestampState(Performance& aPerformance);
     40 
     41  RTCStatsTimestampState(const RTCStatsTimestampState&) = default;
     42 
     43  // These members are sampled when a non-copy constructor is called.
     44 
     45  // Performance's random timeline seed.
     46  const uint64_t mRandomTimelineSeed;
     47  // TimeStamp::Now() when the members were sampled. This is equivalent to time
     48  // 0 in DomRealtime.
     49  const TimeStamp mStartDomRealtime;
     50  // WebrtcSystemTime() when the members were sampled. This represents the same
     51  // point in time as mStartDomRealtime, but as a webrtc timestamp.
     52  const webrtc::Timestamp mStartRealtime;
     53  // Performance's RTPCallerType.
     54  const RTPCallerType mRTPCallerType;
     55  // Performance.timeOrigin for mStartDomRealtime when the members were sampled.
     56  const DOMHighResTimeStamp mStartWallClockRaw;
     57 
     58 protected:
     59  RTCStatsTimestampState(TimeStamp aStartDomRealtime,
     60                         webrtc::Timestamp aStartRealtime);
     61 };
     62 
     63 /**
     64 * Classes that facilitate creating timestamps for webrtc stats by mimicking
     65 * dom::Performance, as well as getting and converting timestamps for libwebrtc
     66 * and our integration with it.
     67 *
     68 * They use the same clock to avoid drift and inconsistencies, base on
     69 * mozilla::TimeStamp, and convert to and from these time bases:
     70 * - Moz        : Monotonic, unspecified (but constant) and inaccessible epoch,
     71 *                as implemented by mozilla::TimeStamp
     72 * - Realtime   : Monotonic, unspecified (but constant) epoch.
     73 * - 1Jan1970   : Monotonic, unix epoch (00:00:00 UTC on 1 January 1970).
     74 * - Ntp        : Monotonic, ntp epoch (00:00:00 UTC on 1 January 1900).
     75 * - Dom        : Monotonic, milliseconds since unix epoch, as the timestamps
     76 *                defined by webrtc-pc. Corresponds to Performance.timeOrigin +
     77 *                Performance.now(). Has reduced precision.
     78 * - DomRealtime: Like Dom, but with full precision.
     79 * - WallClock  : Non-monotonic, unix epoch. Not used here since it is
     80 *                non-monotonic and cannot be correlated to the other time
     81 *                bases.
     82 */
     83 class RTCStatsTimestampMaker;
     84 class RTCStatsTimestamp {
     85 public:
     86  TimeStamp ToMozTime() const;
     87  webrtc::Timestamp ToRealtime() const;
     88  webrtc::Timestamp To1Jan1970() const;
     89  webrtc::Timestamp ToNtp() const;
     90  webrtc::Timestamp ToDomRealtime() const;
     91  DOMHighResTimeStamp ToDom() const;
     92 
     93  static RTCStatsTimestamp FromMozTime(const RTCStatsTimestampMaker& aMaker,
     94                                       TimeStamp aMozTime);
     95  static RTCStatsTimestamp FromRealtime(const RTCStatsTimestampMaker& aMaker,
     96                                        webrtc::Timestamp aRealtime);
     97  static RTCStatsTimestamp From1Jan1970(const RTCStatsTimestampMaker& aMaker,
     98                                        webrtc::Timestamp aRealtime);
     99  static RTCStatsTimestamp FromNtp(const RTCStatsTimestampMaker& aMaker,
    100                                   webrtc::Timestamp aRealtime);
    101  static RTCStatsTimestamp FromDomRealtime(const RTCStatsTimestampMaker& aMaker,
    102                                           webrtc::Timestamp aDomRealtime);
    103  // There is on purpose no conversion functions from DOMHighResTimeStamp
    104  // because of the loss in precision of a floating point to integer conversion.
    105 
    106 private:
    107  RTCStatsTimestamp(RTCStatsTimestampState aState, TimeStamp aMozTime);
    108 
    109  const RTCStatsTimestampState mState;
    110  const TimeStamp mMozTime;
    111 };
    112 
    113 class RTCStatsTimestampMaker {
    114 public:
    115  static RTCStatsTimestampMaker Create(nsPIDOMWindowInner* aWindow = nullptr);
    116 
    117  RTCStatsTimestamp GetNow() const;
    118 
    119  const RTCStatsTimestampState mState;
    120 
    121 protected:
    122  explicit RTCStatsTimestampMaker(RTCStatsTimestampState aState);
    123 };
    124 
    125 // TODO(bug 1588303): If we ever get move semantics for webidl dictionaries, we
    126 // can stop wrapping these in UniquePtr, which will allow us to simplify code
    127 // in several places.
    128 typedef MozPromise<UniquePtr<RTCStatsCollection>, nsresult, true>
    129    RTCStatsPromise;
    130 
    131 typedef MozPromise<UniquePtr<RTCStatsReportInternal>, nsresult, true>
    132    RTCStatsReportPromise;
    133 
    134 class RTCStatsReport final : public nsWrapperCache {
    135 public:
    136  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(RTCStatsReport)
    137  NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(RTCStatsReport)
    138 
    139  explicit RTCStatsReport(nsPIDOMWindowInner* aParent);
    140 
    141  // TODO(bug 1586109): Remove this once we no longer have to create empty
    142  // RTCStatsReports from JS.
    143  static already_AddRefed<RTCStatsReport> Constructor(
    144      const GlobalObject& aGlobal);
    145 
    146  void Incorporate(RTCStatsCollection& aStats);
    147 
    148  nsPIDOMWindowInner* GetParentObject() const { return mParent; }
    149 
    150  JSObject* WrapObject(JSContext* aCx,
    151                       JS::Handle<JSObject*> aGivenProto) override;
    152 
    153 private:
    154  ~RTCStatsReport() = default;
    155  void Set(const nsAString& aKey, JS::Handle<JSObject*> aValue,
    156           ErrorResult& aRv);
    157 
    158  template <typename T>
    159  nsresult SetRTCStats(Sequence<T>& aValues) {
    160    for (T& value : aValues) {
    161      nsresult rv = SetRTCStats(value);
    162      if (NS_FAILED(rv)) {
    163        return rv;
    164      }
    165    }
    166    return NS_OK;
    167  }
    168 
    169  // We cannot just declare this as SetRTCStats(RTCStats&), because the
    170  // conversion function that ToJSValue uses is non-virtual.
    171  template <typename T>
    172  nsresult SetRTCStats(T& aValue) {
    173    static_assert(std::is_base_of<RTCStats, T>::value,
    174                  "SetRTCStats is for setting RTCStats only");
    175 
    176    if (!aValue.mId.WasPassed()) {
    177      return NS_OK;
    178    }
    179 
    180    const nsString key(aValue.mId.Value());
    181 
    182    // Cargo-culted from dom::Promise; converts aValue to a JSObject
    183    AutoEntryScript aes(mParent->AsGlobal()->GetGlobalJSObject(),
    184                        "RTCStatsReport::SetRTCStats");
    185    JSContext* cx = aes.cx();
    186    JS::Rooted<JS::Value> val(cx);
    187    if (!ToJSValue(cx, std::forward<T>(aValue), &val)) {
    188      return NS_ERROR_FAILURE;
    189    }
    190    JS::Rooted<JSObject*> jsObject(cx, &val.toObject());
    191 
    192    ErrorResult rv;
    193    Set(key, jsObject, rv);
    194    return rv.StealNSResult();
    195  }
    196 
    197  nsCOMPtr<nsPIDOMWindowInner> mParent;
    198 };
    199 
    200 void MergeStats(UniquePtr<dom::RTCStatsCollection> aFromStats,
    201                dom::RTCStatsCollection* aIntoStats);
    202 
    203 void FlattenStats(nsTArray<UniquePtr<dom::RTCStatsCollection>> aFromStats,
    204                  dom::RTCStatsCollection* aIntoStats);
    205 
    206 }  // namespace dom
    207 }  // namespace mozilla
    208 
    209 #endif  // RTCStatsReport_h_