Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/dom/media/webrtc/jsapi/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 25 kB image not shown  

Quelle  WebrtcGlobalInformation.cpp   Sprache: C

 
/* 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 "WebrtcGlobalInformation.h"
#include "WebrtcGlobalStatsHistory.h"
#include "libwebrtcglue/VideoConduit.h"
#include "mozilla/Assertions.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/dom/PWebrtcGlobal.h"
#include "mozilla/dom/PWebrtcGlobalChild.h"
#include "WebrtcGlobalChild.h"
#include "WebrtcGlobalParent.h"

#include <algorithm>
#include <vector>

#include "mozilla/dom/WebrtcGlobalInformationBinding.h"
#include "mozilla/dom/RTCStatsReportBinding.h"  // for RTCStatsReportInternal
#include "mozilla/dom/ContentChild.h"

#include "ErrorList.h"
#include "nsISupports.h"
#include "nsITimer.h"
#include "nsLiteralString.h"
#include "nsNetCID.h"               // NS_SOCKETTRANSPORTSERVICE_CONTRACTID
#include "nsServiceManagerUtils.h"  // do_GetService
#include "nsXULAppAPI.h"
#include "mozilla/ErrorResult.h"
#include "nsProxyRelease.h"  // nsMainThreadPtrHolder
#include "mozilla/Unused.h"
#include "mozilla/RefPtr.h"
#include "mozilla/ClearOnShutdown.h"

#include "common/browser_logging/WebRtcLog.h"
#include "nsString.h"
#include "transport/runnable_utils.h"
#include "MediaTransportHandler.h"
#include "PeerConnectionCtx.h"
#include "PeerConnectionImpl.h"

#ifdef XP_WIN
#  include <process.h>
#endif

namespace mozilla::dom {

using StatsRequestCallback =
    nsMainThreadPtrHandle<WebrtcGlobalStatisticsCallback>;

using LogRequestCallback = nsMainThreadPtrHandle<WebrtcGlobalLoggingCallback>;

class WebrtcContentParents {
 public:
  static WebrtcGlobalParent* Alloc();
  static void Dealloc(WebrtcGlobalParent* aParent);
  static bool Empty() { return sContentParents.empty(); }
  static const std::vector<RefPtr<WebrtcGlobalParent>>& GetAll() {
    return sContentParents;
  }

  WebrtcContentParents() = delete;
  WebrtcContentParents(const WebrtcContentParents&) = delete;
  WebrtcContentParents& operator=(const WebrtcContentParents&) = delete;

 private:
  static std::vector<RefPtr<WebrtcGlobalParent>> sContentParents;
};

MOZ_RUNINIT std::vector<RefPtr<WebrtcGlobalParent>>
    WebrtcContentParents::sContentParents;

WebrtcGlobalParent* WebrtcContentParents::Alloc() {
  RefPtr<WebrtcGlobalParent> cp = new WebrtcGlobalParent;
  sContentParents.push_back(cp);
  return cp.get();
}

void WebrtcContentParents::Dealloc(WebrtcGlobalParent* aParent) {
  if (aParent) {
    aParent->mShutdown = true;
    auto cp =
        std::find(sContentParents.begin(), sContentParents.end(), aParent);
    if (cp != sContentParents.end()) {
      sContentParents.erase(cp);
    }
  }
}

static PeerConnectionCtx* GetPeerConnectionCtx() {
  if (PeerConnectionCtx::isActive()) {
    MOZ_ASSERT(PeerConnectionCtx::GetInstance());
    return PeerConnectionCtx::GetInstance();
  }
  return nullptr;
}

static nsTArray<dom::RTCStatsReportInternal>& GetWebrtcGlobalStatsStash() {
  static StaticAutoPtr<nsTArray<dom::RTCStatsReportInternal>> sStash;
  if (!sStash) {
    sStash = new nsTArray<dom::RTCStatsReportInternal>();
    ClearOnShutdown(&sStash);
  }
  return *sStash;
}

static RefPtr<PWebrtcGlobalParent::GetStatsPromise>
GetStatsPromiseForThisProcess(const nsAString& aPcIdFilter) {
  nsTArray<RefPtr<dom::RTCStatsReportPromise>> promises;

  std::set<nsString> pcids;
  if (auto* ctx = GetPeerConnectionCtx()) {
    // Grab stats for PCs that still exist
    ctx->ForEachPeerConnection([&](PeerConnectionImpl* aPc) {
      if (!aPcIdFilter.IsEmpty() &&
          !aPcIdFilter.EqualsASCII(aPc->GetIdAsAscii().c_str())) {
        return;
      }
      if (!aPc->IsClosed() || !aPc->LongTermStatsIsDisabled()) {
        nsString id;
        aPc->GetId(id);
        pcids.insert(id);
        promises.AppendElement(aPc->GetStats(nullptr, true));
      }
    });

    // Grab previously stashed stats, if they aren't dupes, and ensure they
    // are marked closed. (In a content process, this should already have
    // happened, but in the parent process, the stash will contain the last
    // observed stats from the content processes. From the perspective of the
    // parent process, these are assumed closed unless we see new stats from the
    // content process that say otherwise.)
    for (auto& report : GetWebrtcGlobalStatsStash()) {
      report.mClosed = true;
      if ((aPcIdFilter.IsEmpty() || aPcIdFilter == report.mPcid) &&
          !pcids.count(report.mPcid)) {
        promises.AppendElement(dom::RTCStatsReportPromise::CreateAndResolve(
            MakeUnique<dom::RTCStatsReportInternal>(report), __func__));
      }
    }
  }

  auto UnwrapUniquePtrs = [](dom::RTCStatsReportPromise::AllSettledPromiseType::
                                 ResolveOrRejectValue&& aResult) {
    nsTArray<dom::RTCStatsReportInternal> reports;
    MOZ_RELEASE_ASSERT(aResult.IsResolve(), "AllSettled should never reject!");
    for (auto& reportResult : aResult.ResolveValue()) {
      if (reportResult.IsResolve()) {
        reports.AppendElement(*reportResult.ResolveValue());
      }
    }
    return PWebrtcGlobalParent::GetStatsPromise::CreateAndResolve(
        std::move(reports), __func__);
  };

  return dom::RTCStatsReportPromise::AllSettled(
             GetMainThreadSerialEventTarget(), promises)
      ->Then(GetMainThreadSerialEventTarget(), __func__,
             std::move(UnwrapUniquePtrs));
}

static std::map<int32_t, dom::Sequence<nsString>>& GetWebrtcGlobalLogStash() {
  static StaticAutoPtr<std::map<int32_t, dom::Sequence<nsString>>> sStash;
  if (!sStash) {
    sStash = new std::map<int32_t, dom::Sequence<nsString>>();
    ClearOnShutdown(&sStash);
  }
  return *sStash;
}

static void ClearLongTermStats() {
  if (!NS_IsMainThread()) {
    MOZ_ASSERT(NS_IsMainThread());
    return;
  }

  GetWebrtcGlobalStatsStash().Clear();
  if (XRE_IsParentProcess()) {
    WebrtcGlobalStatsHistory::Clear();
  }
  if (auto* ctx = GetPeerConnectionCtx()) {
    ctx->ClearClosedStats();
  }
}

void WebrtcGlobalInformation::ClearAllStats(const GlobalObject& aGlobal) {
  if (!NS_IsMainThread()) {
    return;
  }

  // Chrome-only API
  MOZ_ASSERT(XRE_IsParentProcess());

  if (!WebrtcContentParents::Empty()) {
    // Pass on the request to any content process based PeerConnections.
    for (const auto& cp : WebrtcContentParents::GetAll()) {
      Unused << cp->SendClearStats();
    }
  }

  // Flush the history for the chrome process
  ClearLongTermStats();
}

void WebrtcGlobalInformation::GetStatsHistoryPcIds(
    const GlobalObject& aGlobal,
    WebrtcGlobalStatisticsHistoryPcIdsCallback& aPcIdsCallback,
    ErrorResult& aRv) {
  if (!NS_IsMainThread()) {
    aRv.Throw(NS_ERROR_NOT_SAME_THREAD);
    return;
  }

  MOZ_ASSERT(XRE_IsParentProcess());

  IgnoredErrorResult rv;
  aPcIdsCallback.Call(WebrtcGlobalStatsHistory::PcIds(), rv);
  aRv = NS_OK;
}

void WebrtcGlobalInformation::GetStatsHistorySince(
    const GlobalObject& aGlobal,
    WebrtcGlobalStatisticsHistoryCallback& aStatsCallback,
    const nsAString& pcIdFilter, const Optional<DOMHighResTimeStamp>& aAfter,
    const Optional<DOMHighResTimeStamp>& aSdpAfter, ErrorResult& aRv) {
  if (!NS_IsMainThread()) {
    aRv.Throw(NS_ERROR_NOT_SAME_THREAD);
    return;
  }

  MOZ_ASSERT(XRE_IsParentProcess());

  WebrtcGlobalStatisticsReport history;

  auto statsAfter = aAfter.WasPassed() ? Some(aAfter.Value()) : Nothing();
  auto sdpAfter = aSdpAfter.WasPassed() ? Some(aSdpAfter.Value()) : Nothing();

  WebrtcGlobalStatsHistory::GetHistory(pcIdFilter).apply([&](const auto& hist) {
    if (!history.mReports.AppendElements(hist->Since(statsAfter), fallible)) {
      mozalloc_handle_oom(0);
    }
    if (!history.mSdpHistories.AppendElement(hist->SdpSince(sdpAfter),
                                             fallible)) {
      mozalloc_handle_oom(0);
    }
  });

  IgnoredErrorResult rv;
  aStatsCallback.Call(history, rv);
  aRv = NS_OK;
}

void WebrtcGlobalInformation::GetMediaContext(
    const GlobalObject& aGlobal, WebrtcGlobalMediaContext& aContext) {
  aContext.mHasH264Hardware = WebrtcVideoConduit::HasH264Hardware();
  aContext.mHasAv1 = WebrtcVideoConduit::HasAv1();
}

using StatsPromiseArray =
    nsTArray<RefPtr<PWebrtcGlobalParent::GetStatsPromise>>;

void WebrtcGlobalInformation::GatherHistory() {
  const nsString emptyFilter;
  if (!NS_IsMainThread()) {
    MOZ_ASSERT(NS_IsMainThread());
    return;
  }

  MOZ_ASSERT(XRE_IsParentProcess());
  using StatsPromise = PWebrtcGlobalParent::GetStatsPromise;
  auto resolveThenAppendStatsHistory = [](RefPtr<StatsPromise>&& promise) {
    auto AppendStatsHistory = [](StatsPromise::ResolveOrRejectValue&& result) {
      if (result.IsReject()) {
        return;
      }
      for (const auto& report : result.ResolveValue()) {
        WebrtcGlobalStatsHistory::Record(
            MakeUnique<RTCStatsReportInternal>(report));
      }
    };
    promise->Then(GetMainThreadSerialEventTarget(), __func__,
                  std::move(AppendStatsHistory));
  };
  for (const auto& cp : WebrtcContentParents::GetAll()) {
    resolveThenAppendStatsHistory(cp->SendGetStats(emptyFilter));
  }
  resolveThenAppendStatsHistory(GetStatsPromiseForThisProcess(emptyFilter));
}

void WebrtcGlobalInformation::GetAllStats(
    const GlobalObject& aGlobal, WebrtcGlobalStatisticsCallback& aStatsCallback,
    const Optional<nsAString>& aPcIdFilter, ErrorResult& aRv) {
  if (!NS_IsMainThread()) {
    aRv.Throw(NS_ERROR_NOT_SAME_THREAD);
    return;
  }

  MOZ_ASSERT(XRE_IsParentProcess());

  StatsPromiseArray statsPromises;

  nsString filter;
  if (aPcIdFilter.WasPassed()) {
    filter = aPcIdFilter.Value();
  }

  for (const auto& cp : WebrtcContentParents::GetAll()) {
    statsPromises.AppendElement(cp->SendGetStats(filter));
  }

  // Stats from this (the parent) process. How long do we keep supporting this?
  statsPromises.AppendElement(GetStatsPromiseForThisProcess(filter));

  // CallbackObject does not support threadsafe refcounting, and must be
  // used and destroyed on main.
  StatsRequestCallback callbackHandle(
      new nsMainThreadPtrHolder<WebrtcGlobalStatisticsCallback>(
          "WebrtcGlobalStatisticsCallback", &aStatsCallback));

  auto FlattenThenStashThenCallback =
      [callbackHandle,
       filter](PWebrtcGlobalParent::GetStatsPromise::AllSettledPromiseType::
                   ResolveOrRejectValue&& aResult) MOZ_CAN_RUN_SCRIPT_BOUNDARY {
        std::set<nsString> pcids;
        WebrtcGlobalStatisticsReport flattened;
        MOZ_RELEASE_ASSERT(aResult.IsResolve(),
                           "AllSettled should never reject!");
        // Flatten stats from content processes and parent process.
        // The stats from the parent process (which will come last) might
        // contain some stale content-process stats, so skip those.
        for (auto& processResult : aResult.ResolveValue()) {
          // TODO: Report rejection on individual content processes someday?
          if (processResult.IsResolve()) {
            for (auto& pcStats : processResult.ResolveValue()) {
              if (!pcids.count(pcStats.mPcid)) {
                pcids.insert(pcStats.mPcid);
                if (!flattened.mReports.AppendElement(std::move(pcStats),
                                                      fallible)) {
                  mozalloc_handle_oom(0);
                }
              }
            }
          }
        }

        if (filter.IsEmpty()) {
          // Unfiltered is simple; the flattened result becomes the new stash.
          GetWebrtcGlobalStatsStash() = flattened.mReports;
        } else if (!flattened.mReports.IsEmpty()) {
          // Update our stash with the single result.
          MOZ_ASSERT(flattened.mReports.Length() == 1);
          StashStats(flattened.mReports[0]);
        }

        IgnoredErrorResult rv;
        callbackHandle->Call(flattened, rv);
      };

  PWebrtcGlobalParent::GetStatsPromise::AllSettled(
      GetMainThreadSerialEventTarget(), statsPromises)
      ->Then(GetMainThreadSerialEventTarget(), __func__,
             std::move(FlattenThenStashThenCallback));

  aRv = NS_OK;
}

static RefPtr<PWebrtcGlobalParent::GetLogPromise> GetLogPromise() {
  PeerConnectionCtx* ctx = GetPeerConnectionCtx();
  if (!ctx) {
    // This process has never created a PeerConnection, so no ICE logging.
    return PWebrtcGlobalParent::GetLogPromise::CreateAndResolve(
        Sequence<nsString>(), __func__);
  }

  nsresult rv;
  nsCOMPtr<nsISerialEventTarget> stsThread =
      do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);

  if (NS_WARN_IF(NS_FAILED(rv) || !stsThread)) {
    return PWebrtcGlobalParent::GetLogPromise::CreateAndResolve(
        Sequence<nsString>(), __func__);
  }

  RefPtr<MediaTransportHandler> transportHandler = ctx->GetTransportHandler();

  auto AddMarkers =
      [](MediaTransportHandler::IceLogPromise::ResolveOrRejectValue&& aValue) {
        nsString pid;
        pid.AppendInt(getpid());
        Sequence<nsString> logs;
        if (aValue.IsResolve() && !aValue.ResolveValue().IsEmpty()) {
          bool ok = logs.AppendElement(
              u"+++++++ BEGIN (process id "_ns + pid + u") ++++++++"_ns,
              fallible);
          ok &=
              !!logs.AppendElements(std::move(aValue.ResolveValue()), fallible);
          ok &= !!logs.AppendElement(
              u"+++++++ END (process id "_ns + pid + u") ++++++++"_ns,
              fallible);
          if (!ok) {
            mozalloc_handle_oom(0);
          }
        }
        return PWebrtcGlobalParent::GetLogPromise::CreateAndResolve(
            std::move(logs), __func__);
      };

  return transportHandler->GetIceLog(nsCString())
      ->Then(GetMainThreadSerialEventTarget(), __func__, std::move(AddMarkers));
}

static nsresult RunLogClear() {
  PeerConnectionCtx* ctx = GetPeerConnectionCtx();
  if (!ctx) {
    // This process has never created a PeerConnection, so no ICE logging.
    return NS_OK;
  }

  nsresult rv;
  nsCOMPtr<nsISerialEventTarget> stsThread =
      do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);

  if (NS_FAILED(rv)) {
    return rv;
  }
  if (!stsThread) {
    return NS_ERROR_FAILURE;
  }

  RefPtr<MediaTransportHandler> transportHandler = ctx->GetTransportHandler();

  return RUN_ON_THREAD(
      stsThread,
      WrapRunnable(transportHandler, &MediaTransportHandler::ClearIceLog),
      NS_DISPATCH_NORMAL);
}

void WebrtcGlobalInformation::ClearLogging(const GlobalObject& aGlobal) {
  if (!NS_IsMainThread()) {
    return;
  }

  // Chrome-only API
  MOZ_ASSERT(XRE_IsParentProcess());
  GetWebrtcGlobalLogStash().clear();

  if (!WebrtcContentParents::Empty()) {
    // Clear content process signaling logs
    for (const auto& cp : WebrtcContentParents::GetAll()) {
      Unused << cp->SendClearLog();
    }
  }

  // Clear chrome process signaling logs
  Unused << RunLogClear();
}

static RefPtr<GenericPromise> UpdateLogStash() {
  nsTArray<RefPtr<GenericPromise>> logPromises;
  MOZ_ASSERT(XRE_IsParentProcess());
  for (const auto& cp : WebrtcContentParents::GetAll()) {
    auto StashLog =
        [id = cp->Id() * 2 /* Make sure 1 isn't used */](
            PWebrtcGlobalParent::GetLogPromise::ResolveOrRejectValue&& aValue) {
          if (aValue.IsResolve() && !aValue.ResolveValue().IsEmpty()) {
            GetWebrtcGlobalLogStash()[id] = aValue.ResolveValue();
          }
          return GenericPromise::CreateAndResolve(true, __func__);
        };
    logPromises.AppendElement(cp->SendGetLog()->Then(
        GetMainThreadSerialEventTarget(), __func__, std::move(StashLog)));
  }

  // Get ICE logging for this (the parent) process. How long do we support this?
  logPromises.AppendElement(GetLogPromise()->Then(
      GetMainThreadSerialEventTarget(), __func__,
      [](PWebrtcGlobalParent::GetLogPromise::ResolveOrRejectValue&& aValue) {
        if (aValue.IsResolve()) {
          GetWebrtcGlobalLogStash()[1] = aValue.ResolveValue();
        }
        return GenericPromise::CreateAndResolve(true, __func__);
      }));

  return GenericPromise::AllSettled(GetMainThreadSerialEventTarget(),
                                    logPromises)
      ->Then(GetMainThreadSerialEventTarget(), __func__,
             [](GenericPromise::AllSettledPromiseType::ResolveOrRejectValue&&
                    aValue) {
               // We don't care about the value, since we're just going to copy
               // what is in the stash. This ignores failures too, which is what
               // we want.
               return GenericPromise::CreateAndResolve(true, __func__);
             });
}

void WebrtcGlobalInformation::GetLogging(
    const GlobalObject& aGlobal, const nsAString& aPattern,
    WebrtcGlobalLoggingCallback& aLoggingCallback, ErrorResult& aRv) {
  if (!NS_IsMainThread()) {
    aRv.Throw(NS_ERROR_NOT_SAME_THREAD);
    return;
  }

  MOZ_ASSERT(XRE_IsParentProcess());

  nsAutoString pattern(aPattern);

  // CallbackObject does not support threadsafe refcounting, and must be
  // destroyed on main.
  LogRequestCallback callbackHandle(
      new nsMainThreadPtrHolder<WebrtcGlobalLoggingCallback>(
          "WebrtcGlobalLoggingCallback", &aLoggingCallback));

  auto FilterThenCallback =
      [pattern, callbackHandle](GenericPromise::ResolveOrRejectValue&& aValue)
          MOZ_CAN_RUN_SCRIPT_BOUNDARY {
            dom::Sequence<nsString> flattened;
            for (const auto& [id, log] : GetWebrtcGlobalLogStash()) {
              (void)id;
              for (const auto& line : log) {
                if (pattern.IsEmpty() || (line.Find(pattern) != kNotFound)) {
                  if (!flattened.AppendElement(line, fallible)) {
                    mozalloc_handle_oom(0);
                  }
                }
              }
            }
            IgnoredErrorResult rv;
            callbackHandle->Call(flattened, rv);
          };

  UpdateLogStash()->Then(GetMainThreadSerialEventTarget(), __func__,
                         std::move(FilterThenCallback));
  aRv = NS_OK;
}

static bool sLastAECDebug = false;
MOZ_RUNINIT static Maybe<nsCString> sAecDebugLogDir;

void WebrtcGlobalInformation::SetAecDebug(const GlobalObject& aGlobal,
                                          bool aEnable) {
  if (aEnable) {
    sAecDebugLogDir = Some(StartAecLog());
  } else {
    StopAecLog();
  }

  sLastAECDebug = aEnable;

  for (const auto& cp : WebrtcContentParents::GetAll()) {
    Unused << cp->SendSetAecLogging(aEnable);
  }
}

bool WebrtcGlobalInformation::AecDebug(const GlobalObject& aGlobal) {
  return sLastAECDebug;
}

void WebrtcGlobalInformation::GetAecDebugLogDir(const GlobalObject& aGlobal,
                                                nsAString& aDir) {
  aDir = NS_ConvertASCIItoUTF16(sAecDebugLogDir.valueOr(""_ns));
}

/*static*/
void WebrtcGlobalInformation::StashStats(
    const dom::RTCStatsReportInternal& aReport) {
  // Remove previous report, if present
  // TODO: Make this a map instead of an array?
  for (size_t i = 0; i < GetWebrtcGlobalStatsStash().Length();) {
    auto& pcStats = GetWebrtcGlobalStatsStash()[i];
    if (pcStats.mPcid == aReport.mPcid) {
      GetWebrtcGlobalStatsStash().RemoveElementAt(i);
      break;
    }
    ++i;
  }
  // Stash final stats
  GetWebrtcGlobalStatsStash().AppendElement(aReport);
}

void WebrtcGlobalInformation::AdjustTimerReferences(
    PcTrackingUpdate&& aUpdate) {
  static StaticRefPtr<nsITimer> sHistoryTimer;
  static StaticAutoPtr<nsTHashSet<nsString>> sPcids;

  MOZ_ASSERT(NS_IsMainThread());

  auto HandleAdd = [&](nsString&& aPcid, bool aIsLongTermStatsDisabled) {
    if (!sPcids) {
      sPcids = new nsTHashSet<nsString>();
      ClearOnShutdown(&sPcids);
    }
    sPcids->EnsureInserted(aPcid);
    // Reserve a stats history
    WebrtcGlobalStatsHistory::InitHistory(nsString(aPcid),
                                          aIsLongTermStatsDisabled);
    if (!sHistoryTimer) {
      sHistoryTimer = NS_NewTimer(GetMainThreadSerialEventTarget());
      if (sHistoryTimer) {
        sHistoryTimer->InitWithNamedFuncCallback(
            [](nsITimer* aTimer, void* aClosure) {
              if (WebrtcGlobalStatsHistory::Pref::Enabled()) {
                WebrtcGlobalInformation::GatherHistory();
              }
            },
            nullptr, WebrtcGlobalStatsHistory::Pref::PollIntervalMs(),
            nsITimer::TYPE_REPEATING_SLACK,
            "WebrtcGlobalInformation::GatherHistory");
      }
      ClearOnShutdown(&sHistoryTimer);
    }
  };

  auto HandleRemove = [&](const nsString& aRemoved) {
    WebrtcGlobalStatsHistory::CloseHistory(nsString(aRemoved));
    if (!sPcids || !sPcids->Count()) {
      return;
    }
    if (!sPcids->Contains(aRemoved)) {
      return;
    }
    sPcids->Remove(aRemoved);
    if (!sPcids->Count() && sHistoryTimer) {
      sHistoryTimer->Cancel();
      sHistoryTimer = nullptr;
    }
  };

  switch (aUpdate.Type()) {
    case PcTrackingUpdate::Type::Add: {
      HandleAdd(std::move(aUpdate.mPcid),
                aUpdate.mLongTermStatsDisabled.valueOrFrom([&]() {
                  MOZ_ASSERT(aUpdate.mLongTermStatsDisabled.isNothing());
                  return true;
                }));
      return;
    }
    case PcTrackingUpdate::Type::Remove: {
      HandleRemove(aUpdate.mPcid);
      return;
    }
    default: {
      MOZ_ASSERT(false"Invalid PcCount operation");
    }
  }
}

WebrtcGlobalParent* WebrtcGlobalParent::Alloc() {
  return WebrtcContentParents::Alloc();
}

bool WebrtcGlobalParent::Dealloc(WebrtcGlobalParent* aActor) {
  WebrtcContentParents::Dealloc(aActor);
  return true;
}

void WebrtcGlobalParent::ActorDestroy(ActorDestroyReason aWhy) {
  mShutdown = true;
  for (const auto& pcId : mPcids) {
    using Update = WebrtcGlobalInformation::PcTrackingUpdate;
    auto update = Update::Remove(nsString(pcId));
    WebrtcGlobalInformation::PeerConnectionTracking(update);
  }
}

mozilla::ipc::IPCResult WebrtcGlobalParent::Recv__delete__() {
  return IPC_OK();
}

mozilla::ipc::IPCResult WebrtcGlobalParent::RecvPeerConnectionCreated(
    const nsAString& aPcId, const bool& aIsLongTermStatsDisabled) {
  if (mShutdown) {
    return IPC_OK();
  }
  mPcids.EnsureInserted(aPcId);
  using Update = WebrtcGlobalInformation::PcTrackingUpdate;
  auto update = Update::Add(nsString(aPcId), aIsLongTermStatsDisabled);
  WebrtcGlobalInformation::PeerConnectionTracking(update);
  return IPC_OK();
}

mozilla::ipc::IPCResult WebrtcGlobalParent::RecvPeerConnectionDestroyed(
    const nsAString& aPcId) {
  mPcids.EnsureRemoved(aPcId);
  using Update = WebrtcGlobalInformation::PcTrackingUpdate;
  auto update = Update::Remove(nsString(aPcId));
  WebrtcGlobalStatsHistory::CloseHistory(aPcId);
  WebrtcGlobalInformation::PeerConnectionTracking(update);
  return IPC_OK();
}

mozilla::ipc::IPCResult WebrtcGlobalParent::RecvPeerConnectionFinalStats(
    const RTCStatsReportInternal& aFinalStats) {
  auto finalStats = MakeUnique<RTCStatsReportInternal>(aFinalStats);
  WebrtcGlobalStatsHistory::Record(std::move(finalStats));
  WebrtcGlobalStatsHistory::CloseHistory(aFinalStats.mPcid);
  return IPC_OK();
}

MOZ_IMPLICIT WebrtcGlobalParent::WebrtcGlobalParent() : mShutdown(false) {
  MOZ_COUNT_CTOR(WebrtcGlobalParent);
}

MOZ_IMPLICIT WebrtcGlobalParent::~WebrtcGlobalParent() {
  MOZ_COUNT_DTOR(WebrtcGlobalParent);
}

mozilla::ipc::IPCResult WebrtcGlobalChild::RecvGetStats(
    const nsAString& aPcIdFilter, GetStatsResolver&& aResolve) {
  if (!mShutdown) {
    GetStatsPromiseForThisProcess(aPcIdFilter)
        ->Then(
            GetMainThreadSerialEventTarget(), __func__,
            [resolve = std::move(aResolve)](
                nsTArray<dom::RTCStatsReportInternal>&& aReports) {
              resolve(std::move(aReports));
            },
            []() { MOZ_CRASH(); });
    return IPC_OK();
  }

  aResolve(nsTArray<RTCStatsReportInternal>());
  return IPC_OK();
}

mozilla::ipc::IPCResult WebrtcGlobalChild::RecvClearStats() {
  if (mShutdown) {
    return IPC_OK();
  }

  ClearLongTermStats();
  return IPC_OK();
}

mozilla::ipc::IPCResult WebrtcGlobalChild::RecvGetLog(
    GetLogResolver&& aResolve) {
  if (mShutdown) {
    aResolve(Sequence<nsString>());
    return IPC_OK();
  }

  GetLogPromise()->Then(
      GetMainThreadSerialEventTarget(), __func__,
      [aResolve = std::move(aResolve)](
          PWebrtcGlobalParent::GetLogPromise::ResolveOrRejectValue&& aValue) {
        if (aValue.IsResolve()) {
          aResolve(aValue.ResolveValue());
        } else {
          aResolve(Sequence<nsString>());
        }
      });

  return IPC_OK();
}

mozilla::ipc::IPCResult WebrtcGlobalChild::RecvClearLog() {
  if (mShutdown) {
    return IPC_OK();
  }

  RunLogClear();
  return IPC_OK();
}

mozilla::ipc::IPCResult WebrtcGlobalChild::RecvSetAecLogging(
    const bool& aEnable) {
  if (!mShutdown) {
    if (aEnable) {
      StartAecLog();
    } else {
      StopAecLog();
    }
  }
  return IPC_OK();
}

WebrtcGlobalChild* WebrtcGlobalChild::GetOrSet(
    const Maybe<WebrtcGlobalChild*>& aChild) {
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(XRE_IsContentProcess());
  static WebrtcGlobalChild* sChild;
  if (!sChild && !aChild) {
    sChild = static_cast<WebrtcGlobalChild*>(
        ContentChild::GetSingleton()->SendPWebrtcGlobalConstructor());
  }
  aChild.apply([](auto* child) { sChild = child; });
  return sChild;
}

WebrtcGlobalChild* WebrtcGlobalChild::Get() { return GetOrSet(Nothing()); }

void WebrtcGlobalChild::ActorDestroy(ActorDestroyReason aWhy) {
  mShutdown = true;
}

MOZ_IMPLICIT WebrtcGlobalChild::WebrtcGlobalChild() : mShutdown(false) {
  MOZ_COUNT_CTOR(WebrtcGlobalChild);
}

MOZ_IMPLICIT WebrtcGlobalChild::~WebrtcGlobalChild() {
  MOZ_COUNT_DTOR(WebrtcGlobalChild);
  GetOrSet(Some(nullptr));
}

}  // namespace mozilla::dom

Messung V0.5
C=95 H=91 G=92

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.