tor-browser

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

RTCStatsReport.cpp (8749B)


      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 #include "RTCStatsReport.h"
      8 
      9 #include "WebrtcGlobal.h"
     10 #include "libwebrtcglue/SystemTime.h"
     11 #include "mozilla/dom/Performance.h"
     12 #include "nsRFPService.h"
     13 
     14 namespace mozilla::dom {
     15 
     16 RTCStatsTimestampState::RTCStatsTimestampState(TimeStamp aStartDomRealtime,
     17                                               webrtc::Timestamp aStartRealtime)
     18    : mRandomTimelineSeed(0),
     19      mStartDomRealtime(aStartDomRealtime),
     20      mStartRealtime(webrtc::Timestamp::Micros(0)),
     21      mRTPCallerType(RTPCallerType::Normal),
     22      mStartWallClockRaw(0) {}
     23 
     24 RTCStatsTimestampState::RTCStatsTimestampState()
     25    : mRandomTimelineSeed(0),
     26      mStartDomRealtime(WebrtcSystemTimeBase()),
     27      mStartRealtime(
     28          WebrtcSystemTime() -
     29          webrtc::TimeDelta::Micros(
     30              (TimeStamp::Now() - mStartDomRealtime).ToMicroseconds())),
     31      mRTPCallerType(RTPCallerType::Normal),
     32      mStartWallClockRaw(
     33          PerformanceService::GetOrCreate()->TimeOrigin(mStartDomRealtime)) {}
     34 
     35 RTCStatsTimestampState::RTCStatsTimestampState(Performance& aPerformance)
     36    : mRandomTimelineSeed(aPerformance.GetRandomTimelineSeed()),
     37      mStartDomRealtime(aPerformance.CreationTimeStamp()),
     38      mStartRealtime(
     39          WebrtcSystemTime() -
     40          webrtc::TimeDelta::Micros(
     41              (TimeStamp::Now() - mStartDomRealtime).ToMicroseconds())),
     42      mRTPCallerType(aPerformance.GetRTPCallerType()),
     43      mStartWallClockRaw(
     44          PerformanceService::GetOrCreate()->TimeOrigin(mStartDomRealtime)) {}
     45 
     46 TimeStamp RTCStatsTimestamp::ToMozTime() const { return mMozTime; }
     47 
     48 webrtc::Timestamp RTCStatsTimestamp::ToRealtime() const {
     49  return ToDomRealtime() +
     50         webrtc::TimeDelta::Micros(mState.mStartRealtime.us());
     51 }
     52 
     53 webrtc::Timestamp RTCStatsTimestamp::To1Jan1970() const {
     54  return ToDomRealtime() + webrtc::TimeDelta::Millis(mState.mStartWallClockRaw);
     55 }
     56 
     57 webrtc::Timestamp RTCStatsTimestamp::ToNtp() const {
     58  return To1Jan1970() + webrtc::TimeDelta::Seconds(webrtc::kNtpJan1970);
     59 }
     60 
     61 webrtc::Timestamp RTCStatsTimestamp::ToDomRealtime() const {
     62  return webrtc::Timestamp::Micros(
     63      (mMozTime - mState.mStartDomRealtime).ToMicroseconds());
     64 }
     65 
     66 DOMHighResTimeStamp RTCStatsTimestamp::ToDom() const {
     67  // webrtc-pc says to use performance.timeOrigin + performance.now(), but
     68  // keeping a Performance object around is difficult because it is
     69  // main-thread-only. So, we perform the same calculation here. Note that this
     70  // can be very different from the current wall-clock time because of changes
     71  // to the wall clock, or monotonic clock drift over long periods of time.
     72  // We are very careful to do exactly what Performance does, to avoid timestamp
     73  // discrepancies.
     74 
     75  DOMHighResTimeStamp realtime = ToDomRealtime().ms<double>();
     76  // mRandomTimelineSeed is not set in the unit-tests.
     77  if (mState.mRandomTimelineSeed) {
     78    realtime = nsRFPService::ReduceTimePrecisionAsMSecs(
     79        realtime, mState.mRandomTimelineSeed, mState.mRTPCallerType);
     80  }
     81 
     82  // Ugh. Performance::TimeOrigin is not constant, which means we need to
     83  // emulate this weird behavior so our time stamps are consistent with JS
     84  // timeOrigin. This is based on the code here:
     85  // https://searchfox.org/mozilla-central/rev/
     86  // 053826b10f838f77c27507e5efecc96e34718541/dom/performance/Performance.cpp#111-117
     87  DOMHighResTimeStamp start = nsRFPService::ReduceTimePrecisionAsMSecs(
     88      mState.mStartWallClockRaw, 0, mState.mRTPCallerType);
     89 
     90  return start + realtime;
     91 }
     92 
     93 /* static */ RTCStatsTimestamp RTCStatsTimestamp::FromMozTime(
     94    const RTCStatsTimestampMaker& aMaker, TimeStamp aMozTime) {
     95  return RTCStatsTimestamp(aMaker.mState, aMozTime);
     96 }
     97 
     98 /* static */ RTCStatsTimestamp RTCStatsTimestamp::FromRealtime(
     99    const RTCStatsTimestampMaker& aMaker, webrtc::Timestamp aRealtime) {
    100  return FromDomRealtime(
    101      aMaker,
    102      aRealtime - webrtc::TimeDelta::Micros(aMaker.mState.mStartRealtime.us()));
    103 }
    104 
    105 /* static */ RTCStatsTimestamp RTCStatsTimestamp::From1Jan1970(
    106    const RTCStatsTimestampMaker& aMaker, webrtc::Timestamp a1Jan1970) {
    107  const auto& state = aMaker.mState;
    108  return FromDomRealtime(
    109      aMaker, a1Jan1970 - webrtc::TimeDelta::Millis(state.mStartWallClockRaw));
    110 }
    111 
    112 /* static */ RTCStatsTimestamp RTCStatsTimestamp::FromNtp(
    113    const RTCStatsTimestampMaker& aMaker, webrtc::Timestamp aNtpTime) {
    114  const auto& state = aMaker.mState;
    115  const auto domRealtime = aNtpTime -
    116                           webrtc::TimeDelta::Seconds(webrtc::kNtpJan1970) -
    117                           webrtc::TimeDelta::Millis(state.mStartWallClockRaw);
    118  // Ntp times exposed by libwebrtc to stats are always **rounded** to
    119  // milliseconds. That means they can jump up to half a millisecond into the
    120  // future. We compensate for that here so that things seem consistent to js.
    121  return FromDomRealtime(aMaker, domRealtime - webrtc::TimeDelta::Micros(500));
    122 }
    123 
    124 /* static */ RTCStatsTimestamp RTCStatsTimestamp::FromDomRealtime(
    125    const RTCStatsTimestampMaker& aMaker, webrtc::Timestamp aDomRealtime) {
    126  return RTCStatsTimestamp(aMaker.mState, aMaker.mState.mStartDomRealtime +
    127                                              TimeDuration::FromMicroseconds(
    128                                                  aDomRealtime.us<double>()));
    129 }
    130 
    131 RTCStatsTimestamp::RTCStatsTimestamp(RTCStatsTimestampState aState,
    132                                     TimeStamp aMozTime)
    133    : mState(aState), mMozTime(aMozTime) {}
    134 
    135 RTCStatsTimestampMaker::RTCStatsTimestampMaker(RTCStatsTimestampState aState)
    136    : mState(aState) {}
    137 
    138 /* static */
    139 RTCStatsTimestampMaker RTCStatsTimestampMaker::Create(
    140    nsPIDOMWindowInner* aWindow /* = nullptr */) {
    141  if (!aWindow) {
    142    return RTCStatsTimestampMaker(RTCStatsTimestampState());
    143  }
    144  if (Performance* p = aWindow->GetPerformance()) {
    145    return RTCStatsTimestampMaker(RTCStatsTimestampState(*p));
    146  }
    147  return RTCStatsTimestampMaker(RTCStatsTimestampState());
    148 }
    149 
    150 RTCStatsTimestamp RTCStatsTimestampMaker::GetNow() const {
    151  return RTCStatsTimestamp::FromMozTime(*this, TimeStamp::Now());
    152 }
    153 
    154 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(RTCStatsReport, mParent)
    155 
    156 RTCStatsReport::RTCStatsReport(nsPIDOMWindowInner* aParent)
    157    : mParent(aParent) {}
    158 
    159 /*static*/
    160 already_AddRefed<RTCStatsReport> RTCStatsReport::Constructor(
    161    const GlobalObject& aGlobal) {
    162  nsCOMPtr<nsPIDOMWindowInner> window(
    163      do_QueryInterface(aGlobal.GetAsSupports()));
    164  RefPtr<RTCStatsReport> report(new RTCStatsReport(window));
    165  return report.forget();
    166 }
    167 
    168 JSObject* RTCStatsReport::WrapObject(JSContext* aCx,
    169                                     JS::Handle<JSObject*> aGivenProto) {
    170  return RTCStatsReport_Binding::Wrap(aCx, this, aGivenProto);
    171 }
    172 
    173 void RTCStatsReport::Incorporate(RTCStatsCollection& aStats) {
    174  ForAllPublicRTCStatsCollectionMembers(
    175      aStats, [&](auto... aMember) { (SetRTCStats(aMember), ...); });
    176 }
    177 
    178 void RTCStatsReport::Set(const nsAString& aKey, JS::Handle<JSObject*> aValue,
    179                         ErrorResult& aRv) {
    180  RTCStatsReport_Binding::MaplikeHelpers::Set(this, aKey, aValue, aRv);
    181 }
    182 
    183 namespace {
    184 template <size_t I, typename... Ts>
    185 bool MoveInto(std::tuple<Ts...>& aFrom, std::tuple<Ts*...>& aInto) {
    186  return std::get<I>(aInto)->AppendElements(std::move(std::get<I>(aFrom)),
    187                                            fallible);
    188 }
    189 
    190 template <size_t... Is, typename... Ts>
    191 bool MoveInto(std::tuple<Ts...>&& aFrom, std::tuple<Ts*...>& aInto,
    192              std::index_sequence<Is...>) {
    193  return (... && MoveInto<Is>(aFrom, aInto));
    194 }
    195 
    196 template <typename... Ts>
    197 bool MoveInto(std::tuple<Ts...>&& aFrom, std::tuple<Ts*...>& aInto) {
    198  return MoveInto(std::move(aFrom), aInto, std::index_sequence_for<Ts...>());
    199 }
    200 }  // namespace
    201 
    202 void MergeStats(UniquePtr<RTCStatsCollection> aFromStats,
    203                RTCStatsCollection* aIntoStats) {
    204  auto fromTuple = ForAllRTCStatsCollectionMembers(
    205      *aFromStats,
    206      [&](auto&... aMember) { return std::make_tuple(std::move(aMember)...); });
    207  auto intoTuple = ForAllRTCStatsCollectionMembers(
    208      *aIntoStats,
    209      [&](auto&... aMember) { return std::make_tuple(&aMember...); });
    210  if (!MoveInto(std::move(fromTuple), intoTuple)) {
    211    mozalloc_handle_oom(0);
    212  }
    213 }
    214 
    215 void FlattenStats(nsTArray<UniquePtr<RTCStatsCollection>> aFromStats,
    216                  RTCStatsCollection* aIntoStats) {
    217  for (auto& stats : aFromStats) {
    218    MergeStats(std::move(stats), aIntoStats);
    219  }
    220 }
    221 
    222 }  // namespace mozilla::dom