Skip to content

Commit

Permalink
Bug 1830790 - P4 - adding webrtc hist to webrtc global info;r=bwc
Browse files Browse the repository at this point in the history
Depends on D176860

Differential Revision: https://phabricator.services.mozilla.com/D176861
  • Loading branch information
na-g committed May 31, 2023
1 parent dce9df0 commit 15d9589
Show file tree
Hide file tree
Showing 2 changed files with 260 additions and 10 deletions.
223 changes: 214 additions & 9 deletions dom/media/webrtc/jsapi/WebrtcGlobalInformation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "WebrtcGlobalInformation.h"
#include "WebrtcGlobalStatsHistory.h"
#include "mozilla/Assertions.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/dom/PWebrtcGlobal.h"
#include "mozilla/dom/PWebrtcGlobalChild.h"
#include "mozilla/media/webrtc/WebrtcGlobal.h"
#include "WebrtcGlobalChild.h"
#include "WebrtcGlobalParent.h"
Expand All @@ -15,6 +20,9 @@
#include "mozilla/dom/RTCStatsReportBinding.h" // for RTCStatsReportInternal
#include "mozilla/dom/ContentChild.h"

#include "nsISupports.h"
#include "nsITimer.h"
#include "nsLiteralString.h"
#include "nsNetCID.h" // NS_SOCKETTRANSPORTSERVICE_CONTRACTID
#include "nsServiceManagerUtils.h" // do_GetService
#include "mozilla/ErrorResult.h"
Expand All @@ -25,6 +33,7 @@
#include "mozilla/ClearOnShutdown.h"

#include "common/browser_logging/WebRtcLog.h"
#include "nsString.h"
#include "transport/runnable_utils.h"
#include "MediaTransportHandler.h"
#include "PeerConnectionCtx.h"
Expand Down Expand Up @@ -159,7 +168,13 @@ static std::map<int32_t, dom::Sequence<nsString>>& GetWebrtcGlobalLogStash() {
}

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

GetWebrtcGlobalStatsStash().Clear();
WebrtcGlobalStatsHistory::Clear();
if (auto* ctx = GetPeerConnectionCtx()) {
ctx->ClearClosedStats();
}
Expand All @@ -184,21 +199,95 @@ void WebrtcGlobalInformation::ClearAllStats(const GlobalObject& aGlobal) {
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,
ErrorResult& aRv) {
if (!NS_IsMainThread()) {
aRv.Throw(NS_ERROR_NOT_SAME_THREAD);
return;
}

MOZ_ASSERT(XRE_IsParentProcess());

WebrtcGlobalStatisticsReport history;

auto after = aAfter.WasPassed() ? Some(aAfter.Value()) : Nothing();

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

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

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>& pcIdFilter, ErrorResult& aRv) {
const Optional<nsAString>& aPcIdFilter, ErrorResult& aRv) {
if (!NS_IsMainThread()) {
aRv.Throw(NS_ERROR_NOT_SAME_THREAD);
return;
}

MOZ_ASSERT(XRE_IsParentProcess());

nsTArray<RefPtr<PWebrtcGlobalParent::GetStatsPromise>> statsPromises;
StatsPromiseArray statsPromises;

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

for (const auto& cp : WebrtcContentParents::GetAll()) {
Expand Down Expand Up @@ -490,10 +579,77 @@ void WebrtcGlobalInformation::StashStats(
}
++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();
}
Expand All @@ -505,12 +661,50 @@ bool WebrtcGlobalParent::Dealloc(WebrtcGlobalParent* aActor) {

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) {
mPcids.EnsureRemoved(aFinalStats.mPcid);
using Update = WebrtcGlobalInformation::PcTrackingUpdate;
auto update = Update::Remove(nsString(aFinalStats.mPcid));
auto finalStats = MakeUnique<RTCStatsReportInternal>(aFinalStats);
WebrtcGlobalStatsHistory::Record(std::move(finalStats));
WebrtcGlobalInformation::PeerConnectionTracking(update);
return IPC_OK();
}

MOZ_IMPLICIT WebrtcGlobalParent::WebrtcGlobalParent() : mShutdown(false) {
MOZ_COUNT_CTOR(WebrtcGlobalParent);
}
Expand Down Expand Up @@ -543,6 +737,7 @@ mozilla::ipc::IPCResult WebrtcGlobalChild::RecvClearStats() {
}

ClearLongTermStats();
WebrtcGlobalStatsHistory::Clear();
return IPC_OK();
}

Expand Down Expand Up @@ -599,12 +794,21 @@ mozilla::ipc::IPCResult WebrtcGlobalChild::RecvSetDebugMode(const int& aLevel) {
return IPC_OK();
}

WebrtcGlobalChild* WebrtcGlobalChild::Create() {
WebrtcGlobalChild* child = static_cast<WebrtcGlobalChild*>(
ContentChild::GetSingleton()->SendPWebrtcGlobalConstructor());
return child;
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;
}
Expand All @@ -615,6 +819,7 @@ MOZ_IMPLICIT WebrtcGlobalChild::WebrtcGlobalChild() : mShutdown(false) {

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

} // namespace mozilla::dom
47 changes: 46 additions & 1 deletion dom/media/webrtc/jsapi/WebrtcGlobalInformation.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@
#ifndef _WEBRTC_GLOBAL_INFORMATION_H_
#define _WEBRTC_GLOBAL_INFORMATION_H_

#include <tuple>
#include "mozilla/dom/WebrtcGlobalInformationBinding.h"
#include "nsString.h"
#include "mozilla/dom/BindingDeclarations.h" // for Optional
#include "nsDOMNavigationTiming.h"
#include "WebrtcGlobalStatsHistory.h"

namespace mozilla {
class PeerConnectionImpl;
Expand All @@ -16,6 +20,7 @@ namespace dom {

class GlobalObject;
class WebrtcGlobalStatisticsCallback;
class WebrtcGlobalStatisticsHistoryPcIdsCallback;
class WebrtcGlobalLoggingCallback;
struct RTCStatsReportInternal;

Expand All @@ -24,9 +29,24 @@ class WebrtcGlobalInformation {
MOZ_CAN_RUN_SCRIPT
static void GetAllStats(const GlobalObject& aGlobal,
WebrtcGlobalStatisticsCallback& aStatsCallback,
const Optional<nsAString>& pcIdFilter,
const Optional<nsAString>& aPcIdFilter,
ErrorResult& aRv);

MOZ_CAN_RUN_SCRIPT
static void GetStatsHistoryPcIds(
const GlobalObject& aGlobal,
WebrtcGlobalStatisticsHistoryPcIdsCallback& aPcIdsCallback,
ErrorResult& aRv);

MOZ_CAN_RUN_SCRIPT
static void GetStatsHistorySince(
const GlobalObject& aGlobal,
WebrtcGlobalStatisticsHistoryCallback& aStatsCallback,
const nsAString& aPcIdFilter, const Optional<DOMHighResTimeStamp>& aAfter,
ErrorResult& aRv);

static void GatherHistory();

static void ClearAllStats(const GlobalObject& aGlobal);

MOZ_CAN_RUN_SCRIPT
Expand All @@ -49,6 +69,31 @@ class WebrtcGlobalInformation {
WebrtcGlobalInformation(const WebrtcGlobalInformation& aOrig) = delete;
WebrtcGlobalInformation& operator=(const WebrtcGlobalInformation& aRhs) =
delete;

struct PcTrackingUpdate {
static PcTrackingUpdate Add(const nsString& aPcid,
const bool& aLongTermStatsDisabled) {
return PcTrackingUpdate{aPcid, Some(aLongTermStatsDisabled)};
}
static PcTrackingUpdate Remove(const nsString& aPcid) {
return PcTrackingUpdate{aPcid, Nothing()};
}
nsString mPcid;
Maybe<bool> mLongTermStatsDisabled;
enum class Type {
Add,
Remove,
};
Type Type() const {
return mLongTermStatsDisabled ? Type::Add : Type::Remove;
}
};
static void PeerConnectionTracking(PcTrackingUpdate& aUpdate) {
AdjustTimerReferences(std::move(aUpdate));
}

private:
static void AdjustTimerReferences(PcTrackingUpdate&& aUpdate);
};

} // namespace dom
Expand Down

0 comments on commit 15d9589

Please sign in to comment.