LCOV - code coverage report
Current view: top level - media/webrtc/signaling/src/peerconnection - WebrtcGlobalInformation.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 4 534 0.7 %
Date: 2017-07-14 16:53:18 Functions: 2 72 2.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* This Source Code Form is subject to the terms of the Mozilla Public
       2             :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       3             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       4             : 
       5             : #include "WebrtcGlobalInformation.h"
       6             : #include "mozilla/media/webrtc/WebrtcGlobal.h"
       7             : #include "WebrtcGlobalChild.h"
       8             : #include "WebrtcGlobalParent.h"
       9             : 
      10             : #include <deque>
      11             : #include <string>
      12             : #include <algorithm>
      13             : #include <vector>
      14             : #include <map>
      15             : #include <queue>
      16             : 
      17             : #include "CSFLog.h"
      18             : #include "WebRtcLog.h"
      19             : #include "mozilla/dom/WebrtcGlobalInformationBinding.h"
      20             : #include "mozilla/dom/ContentChild.h"
      21             : 
      22             : #include "nsAutoPtr.h"
      23             : #include "nsNetCID.h" // NS_SOCKETTRANSPORTSERVICE_CONTRACTID
      24             : #include "nsServiceManagerUtils.h" // do_GetService
      25             : #include "mozilla/ErrorResult.h"
      26             : #include "mozilla/Vector.h"
      27             : #include "nsProxyRelease.h"
      28             : #include "mozilla/Telemetry.h"
      29             : #include "mozilla/Unused.h"
      30             : #include "mozilla/StaticMutex.h"
      31             : #include "mozilla/RefPtr.h"
      32             : 
      33             : #include "rlogconnector.h"
      34             : #include "runnable_utils.h"
      35             : #include "PeerConnectionCtx.h"
      36             : #include "PeerConnectionImpl.h"
      37             : #include "webrtc/system_wrappers/include/trace.h"
      38             : 
      39             : static const char* logTag = "WebrtcGlobalInformation";
      40             : 
      41             : namespace mozilla {
      42             : namespace dom {
      43             : 
      44             : typedef Vector<nsAutoPtr<RTCStatsQuery>> RTCStatsQueries;
      45             : typedef nsTArray<RTCStatsReportInternal> Stats;
      46             : 
      47             : template<class Request, typename Callback,
      48             :          typename Result, typename QueryParam>
      49           0 : class RequestManager
      50             : {
      51             : public:
      52             : 
      53           0 :   static Request* Create(Callback& aCallback, QueryParam& aParam)
      54             :   {
      55           0 :     mozilla::StaticMutexAutoLock lock(sMutex);
      56             : 
      57           0 :     int id = ++sLastRequestId;
      58             :     auto result = sRequests.insert(
      59           0 :       std::make_pair(id, Request(id, aCallback, aParam)));
      60             : 
      61           0 :     if (!result.second) {
      62           0 :       return nullptr;
      63             :     }
      64             : 
      65           0 :     return &result.first->second;
      66             :   }
      67             : 
      68           0 :   static void Delete(int aId)
      69             :   {
      70           0 :     mozilla::StaticMutexAutoLock lock(sMutex);
      71           0 :     sRequests.erase(aId);
      72           0 :   }
      73             : 
      74           0 :   static Request* Get(int aId)
      75             :   {
      76           0 :     mozilla::StaticMutexAutoLock lock(sMutex);
      77           0 :     auto r = sRequests.find(aId);
      78             : 
      79           0 :     if (r == sRequests.end()) {
      80           0 :       return nullptr;
      81             :     }
      82             : 
      83           0 :     return &r->second;
      84             :   }
      85             : 
      86             :   Result mResult;
      87             :   std::queue<RefPtr<WebrtcGlobalParent>> mContactList;
      88             :   const int mRequestId;
      89             : 
      90           0 :   RefPtr<WebrtcGlobalParent> GetNextParent()
      91             :   {
      92           0 :     while (!mContactList.empty()) {
      93           0 :       RefPtr<WebrtcGlobalParent> next = mContactList.front();
      94           0 :       mContactList.pop();
      95           0 :       if (next->IsActive()) {
      96           0 :         return next;
      97             :       }
      98             :     }
      99             : 
     100           0 :     return nullptr;
     101             :   }
     102             : 
     103           0 :   void Complete()
     104             :   {
     105           0 :     ErrorResult rv;
     106           0 :     mCallback.get()->Call(mResult, rv);
     107             : 
     108           0 :     if (rv.Failed()) {
     109           0 :       CSFLogError(logTag, "Error firing stats observer callback");
     110             :     }
     111           0 :   }
     112             : 
     113             : protected:
     114             :   // The mutex is used to protect two related operations involving the sRequest map
     115             :   // and the sLastRequestId. For the map, it prevents more than one thread from
     116             :   // adding or deleting map entries at the same time. For id generation,
     117             :   // it creates an atomic allocation and increment.
     118             :   static mozilla::StaticMutex sMutex;
     119             :   static std::map<int, Request> sRequests;
     120             :   static int sLastRequestId;
     121             : 
     122             :   Callback mCallback;
     123             : 
     124           0 :   explicit RequestManager(int aId, Callback& aCallback)
     125             :     : mRequestId(aId)
     126           0 :     , mCallback(aCallback)
     127           0 :   {}
     128           0 :   ~RequestManager() {}
     129             : private:
     130             : 
     131             :   RequestManager() = delete;
     132             :   RequestManager& operator=(const RequestManager&) = delete;
     133             : };
     134             : 
     135             : template<class Request, typename Callback,
     136             :          typename Result, typename QueryParam>
     137           6 : mozilla::StaticMutex RequestManager<Request, Callback, Result, QueryParam>::sMutex;
     138             : template<class Request, typename Callback,
     139             :          typename Result, typename QueryParam>
     140           6 : std::map<int, Request> RequestManager<Request, Callback, Result, QueryParam>::sRequests;
     141             : template<class Request, typename Callback,
     142             :          typename Result, typename QueryParam>
     143             : int RequestManager<Request, Callback, Result, QueryParam>::sLastRequestId;
     144             : 
     145             : typedef nsMainThreadPtrHandle<WebrtcGlobalStatisticsCallback> StatsRequestCallback;
     146             : 
     147           0 : class StatsRequest
     148             :   : public RequestManager<StatsRequest,
     149             :                           StatsRequestCallback,
     150             :                           WebrtcGlobalStatisticsReport,
     151             :                           nsAString>
     152             : {
     153             : public:
     154             :   const nsString mPcIdFilter;
     155           0 :   explicit StatsRequest(int aId, StatsRequestCallback& aCallback, nsAString& aFilter)
     156           0 :     : RequestManager(aId, aCallback)
     157           0 :     , mPcIdFilter(aFilter)
     158             :   {
     159           0 :     mResult.mReports.Construct();
     160           0 :   }
     161             : 
     162             : private:
     163             :   StatsRequest() = delete;
     164             :   StatsRequest& operator=(const StatsRequest&) = delete;
     165             : };
     166             : 
     167             : typedef nsMainThreadPtrHandle<WebrtcGlobalLoggingCallback> LogRequestCallback;
     168             : 
     169           0 : class LogRequest
     170             :   : public RequestManager<LogRequest,
     171             :                           LogRequestCallback,
     172             :                           Sequence<nsString>,
     173             :                           const nsACString>
     174             : {
     175             : public:
     176             :   const nsCString mPattern;
     177           0 :   explicit LogRequest(int aId, LogRequestCallback& aCallback, const nsACString& aPattern)
     178           0 :     : RequestManager(aId, aCallback)
     179           0 :     , mPattern(aPattern)
     180           0 :   {}
     181             : 
     182             : private:
     183             :   LogRequest() = delete;
     184             :   LogRequest& operator=(const LogRequest&) = delete;
     185             : };
     186             : 
     187             : class WebrtcContentParents
     188             : {
     189             : public:
     190             :   static WebrtcGlobalParent* Alloc();
     191             :   static void Dealloc(WebrtcGlobalParent* aParent);
     192           0 :   static bool Empty()
     193             :   {
     194           0 :     return sContentParents.empty();
     195             :   }
     196           0 :   static const std::vector<RefPtr<WebrtcGlobalParent>>& GetAll()
     197             :   {
     198           0 :     return sContentParents;
     199             :   }
     200             : private:
     201             :   static std::vector<RefPtr<WebrtcGlobalParent>> sContentParents;
     202             :   WebrtcContentParents() = delete;
     203             :   WebrtcContentParents(const WebrtcContentParents&) = delete;
     204             :   WebrtcContentParents& operator=(const WebrtcContentParents&) = delete;
     205             : };
     206             : 
     207           3 : std::vector<RefPtr<WebrtcGlobalParent>> WebrtcContentParents::sContentParents;
     208             : 
     209           0 : WebrtcGlobalParent* WebrtcContentParents::Alloc()
     210             : {
     211           0 :   RefPtr<WebrtcGlobalParent> cp = new WebrtcGlobalParent;
     212           0 :   sContentParents.push_back(cp);
     213           0 :   return cp.get();
     214             : }
     215             : 
     216           0 : void WebrtcContentParents::Dealloc(WebrtcGlobalParent* aParent)
     217             : {
     218           0 :   if (aParent) {
     219           0 :     aParent->mShutdown = true;
     220           0 :     auto cp = std::find(sContentParents.begin(), sContentParents.end(), aParent);
     221           0 :     if (cp != sContentParents.end()) {
     222           0 :       sContentParents.erase(cp);
     223             :     }
     224             :   }
     225           0 : }
     226             : 
     227           0 : static PeerConnectionCtx* GetPeerConnectionCtx()
     228             : {
     229           0 :   if(PeerConnectionCtx::isActive()) {
     230           0 :     MOZ_ASSERT(PeerConnectionCtx::GetInstance());
     231           0 :     return PeerConnectionCtx::GetInstance();
     232             :   }
     233           0 :   return nullptr;
     234             : }
     235             : 
     236             : static void
     237           0 : OnStatsReport_m(WebrtcGlobalChild* aThisChild,
     238             :                 const int aRequestId,
     239             :                 nsAutoPtr<RTCStatsQueries> aQueryList)
     240             : {
     241           0 :   MOZ_ASSERT(NS_IsMainThread());
     242           0 :   MOZ_ASSERT(aQueryList);
     243             : 
     244           0 :   if (aThisChild) {
     245           0 :     Stats stats;
     246             : 
     247             :     // Copy stats generated for the currently active PeerConnections
     248           0 :     for (auto&& query : *aQueryList) {
     249           0 :       stats.AppendElement(*(query->report));
     250             :     }
     251             :     // Reports saved for closed/destroyed PeerConnections
     252           0 :     auto ctx = PeerConnectionCtx::GetInstance();
     253           0 :     if (ctx) {
     254           0 :       for (auto&& pc : ctx->mStatsForClosedPeerConnections) {
     255           0 :         stats.AppendElement(pc);
     256             :       }
     257             :     }
     258             : 
     259           0 :     Unused << aThisChild->SendGetStatsResult(aRequestId, stats);
     260           0 :     return;
     261             :   }
     262             : 
     263             :   // This is the last stats report to be collected. (Must be the gecko process).
     264           0 :   MOZ_ASSERT(XRE_IsParentProcess());
     265             : 
     266           0 :   StatsRequest* request = StatsRequest::Get(aRequestId);
     267             : 
     268           0 :   if (!request) {
     269           0 :     CSFLogError(logTag, "Bad RequestId");
     270           0 :     return;
     271             :   }
     272             : 
     273           0 :   for (auto&& query : *aQueryList) {
     274           0 :     request->mResult.mReports.Value().AppendElement(*(query->report), fallible);
     275             :   }
     276             : 
     277             :   // Reports saved for closed/destroyed PeerConnections
     278           0 :   auto ctx = PeerConnectionCtx::GetInstance();
     279           0 :   if (ctx) {
     280           0 :     for (auto&& pc : ctx->mStatsForClosedPeerConnections) {
     281           0 :       request->mResult.mReports.Value().AppendElement(pc, fallible);
     282             :     }
     283             :   }
     284             : 
     285           0 :   request->Complete();
     286           0 :   StatsRequest::Delete(aRequestId);
     287             : }
     288             : 
     289             : static void
     290           0 : GetAllStats_s(WebrtcGlobalChild* aThisChild,
     291             :               const int aRequestId,
     292             :               nsAutoPtr<RTCStatsQueries> aQueryList)
     293             : {
     294           0 :   MOZ_ASSERT(aQueryList);
     295             :   // The call to PeerConnetionImpl must happen from a runnable
     296             :   // dispatched on the STS thread.
     297             : 
     298             :   // Get stats from active connections.
     299           0 :   for (auto&& query : *aQueryList) {
     300           0 :     PeerConnectionImpl::ExecuteStatsQuery_s(query);
     301             :   }
     302             : 
     303             :   // After the RTCStatsQueries have been filled in, control must return
     304             :   // to the main thread before their eventual destruction.
     305           0 :   NS_DispatchToMainThread(WrapRunnableNM(&OnStatsReport_m,
     306             :                                          aThisChild,
     307             :                                          aRequestId,
     308             :                                          aQueryList),
     309           0 :                           NS_DISPATCH_NORMAL);
     310           0 : }
     311             : 
     312           0 : static void OnGetLogging_m(WebrtcGlobalChild* aThisChild,
     313             :                            const int aRequestId,
     314             :                            nsAutoPtr<std::deque<std::string>> aLogList)
     315             : {
     316           0 :   MOZ_ASSERT(NS_IsMainThread());
     317             : 
     318           0 :   if (aThisChild) {
     319             :     // Add this log to the collection of logs and call into
     320             :     // the next content process.
     321           0 :     Sequence<nsString> nsLogs;
     322             : 
     323           0 :     if (!aLogList->empty()) {
     324           0 :       for (auto& line : *aLogList) {
     325           0 :         nsLogs.AppendElement(NS_ConvertUTF8toUTF16(line.c_str()), fallible);
     326             :       }
     327           0 :       nsLogs.AppendElement(NS_LITERAL_STRING("+++++++ END ++++++++"), fallible);
     328             :     }
     329             : 
     330           0 :     Unused << aThisChild->SendGetLogResult(aRequestId, nsLogs);
     331           0 :     return;
     332             :   }
     333             : 
     334             :   // This is the last log to be collected. (Must be the gecko process).
     335           0 :   MOZ_ASSERT(XRE_IsParentProcess());
     336             : 
     337           0 :   LogRequest* request = LogRequest::Get(aRequestId);
     338             : 
     339           0 :   if (!request) {
     340           0 :     CSFLogError(logTag, "Bad RequestId");
     341           0 :     return;
     342             :   }
     343             : 
     344           0 :   if (!aLogList->empty()) {
     345           0 :     for (auto& line : *aLogList) {
     346           0 :       request->mResult.AppendElement(NS_ConvertUTF8toUTF16(line.c_str()),
     347           0 :                                      fallible);
     348             :     }
     349           0 :     request->mResult.AppendElement(NS_LITERAL_STRING("+++++++ END ++++++++"),
     350           0 :                                    fallible);
     351             :   }
     352             : 
     353           0 :   request->Complete();
     354           0 :   LogRequest::Delete(aRequestId);
     355             : }
     356             : 
     357           0 : static void GetLogging_s(WebrtcGlobalChild* aThisChild,
     358             :                          const int aRequestId,
     359             :                          const std::string& aPattern)
     360             : {
     361             :   // Request log while not on the main thread.
     362           0 :   RLogConnector* logs = RLogConnector::GetInstance();
     363           0 :   nsAutoPtr<std::deque<std::string>> result(new std::deque<std::string>);
     364             :   // Might not exist yet.
     365           0 :   if (logs) {
     366           0 :     logs->Filter(aPattern, 0, result);
     367             :   }
     368             :   // Return to main thread to complete processing.
     369           0 :   NS_DispatchToMainThread(WrapRunnableNM(&OnGetLogging_m,
     370             :                                          aThisChild,
     371             :                                          aRequestId,
     372             :                                          result),
     373           0 :                           NS_DISPATCH_NORMAL);
     374           0 : }
     375             : 
     376             : static nsresult
     377           0 : BuildStatsQueryList(
     378             :   const std::map<const std::string, PeerConnectionImpl *>& aPeerConnections,
     379             :   const nsAString& aPcIdFilter,
     380             :   RTCStatsQueries* queries)
     381             : {
     382             :   nsresult rv;
     383             : 
     384           0 :   for (auto&& pc : aPeerConnections) {
     385           0 :     MOZ_ASSERT(pc.second);
     386           0 :     if (aPcIdFilter.IsEmpty() ||
     387           0 :         aPcIdFilter.EqualsASCII(pc.second->GetIdAsAscii().c_str())) {
     388           0 :       if (pc.second->HasMedia()) {
     389           0 :         if (!queries->append(nsAutoPtr<RTCStatsQuery>(new RTCStatsQuery(true)))) {
     390           0 :           return NS_ERROR_OUT_OF_MEMORY;
     391             :         }
     392           0 :         rv = pc.second->BuildStatsQuery_m(nullptr, queries->back()); // all tracks
     393           0 :         if (NS_WARN_IF(NS_FAILED(rv))) {
     394           0 :           return rv;
     395             :         }
     396           0 :         MOZ_ASSERT(queries->back()->report);
     397             :       }
     398             :     }
     399             :   }
     400             : 
     401           0 :   return NS_OK;
     402             : }
     403             : 
     404             : static nsresult
     405           0 : RunStatsQuery(
     406             :   const std::map<const std::string, PeerConnectionImpl *>& aPeerConnections,
     407             :   const nsAString& aPcIdFilter,
     408             :   WebrtcGlobalChild* aThisChild,
     409             :   const int aRequestId)
     410             : {
     411           0 :   nsAutoPtr<RTCStatsQueries> queries(new RTCStatsQueries);
     412           0 :   nsresult rv = BuildStatsQueryList(aPeerConnections, aPcIdFilter, queries);
     413             : 
     414           0 :   if (NS_FAILED(rv)) {
     415           0 :     return rv;
     416             :   }
     417             : 
     418             :   nsCOMPtr<nsIEventTarget> stsThread =
     419           0 :     do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
     420             : 
     421           0 :   if (NS_FAILED(rv)) {
     422           0 :     return rv;
     423             :   }
     424           0 :   if (!stsThread) {
     425           0 :     return NS_ERROR_FAILURE;
     426             :   }
     427             : 
     428           0 :   rv = RUN_ON_THREAD(stsThread,
     429           0 :                      WrapRunnableNM(&GetAllStats_s,
     430             :                                     aThisChild,
     431             :                                     aRequestId,
     432             :                                     queries),
     433             :                      NS_DISPATCH_NORMAL);
     434           0 :   return rv;
     435             : }
     436             : 
     437           0 : void ClearClosedStats()
     438             : {
     439           0 :   PeerConnectionCtx* ctx = GetPeerConnectionCtx();
     440             : 
     441           0 :   if (ctx) {
     442           0 :     ctx->mStatsForClosedPeerConnections.Clear();
     443             :   }
     444           0 : }
     445             : 
     446             : void
     447           0 : WebrtcGlobalInformation::ClearAllStats(
     448             :   const GlobalObject& aGlobal)
     449             : {
     450           0 :   if (!NS_IsMainThread()) {
     451           0 :     return;
     452             :   }
     453             : 
     454             :   // Chrome-only API
     455           0 :   MOZ_ASSERT(XRE_IsParentProcess());
     456             : 
     457           0 :   if (!WebrtcContentParents::Empty()) {
     458             :     // Pass on the request to any content process based PeerConnections.
     459           0 :     for (auto& cp : WebrtcContentParents::GetAll()) {
     460           0 :       Unused << cp->SendClearStatsRequest();
     461             :     }
     462             :   }
     463             : 
     464             :   // Flush the history for the chrome process
     465           0 :   ClearClosedStats();
     466             : }
     467             : 
     468             : void
     469           0 : WebrtcGlobalInformation::GetAllStats(
     470             :   const GlobalObject& aGlobal,
     471             :   WebrtcGlobalStatisticsCallback& aStatsCallback,
     472             :   const Optional<nsAString>& pcIdFilter,
     473             :   ErrorResult& aRv)
     474             : {
     475           0 :   if (!NS_IsMainThread()) {
     476           0 :     aRv.Throw(NS_ERROR_NOT_SAME_THREAD);
     477           0 :     return;
     478             :   }
     479             : 
     480           0 :   MOZ_ASSERT(XRE_IsParentProcess());
     481             : 
     482             :   // CallbackObject does not support threadsafe refcounting, and must be
     483             :   // used and destroyed on main.
     484             :   StatsRequestCallback callbackHandle(
     485             :     new nsMainThreadPtrHolder<WebrtcGlobalStatisticsCallback>(
     486           0 :       "WebrtcGlobalStatisticsCallback", &aStatsCallback));
     487             : 
     488           0 :   nsString filter;
     489           0 :   if (pcIdFilter.WasPassed()) {
     490           0 :     filter = pcIdFilter.Value();
     491             :   }
     492             : 
     493           0 :   auto* request = StatsRequest::Create(callbackHandle, filter);
     494             : 
     495           0 :   if (!request) {
     496           0 :     aRv.Throw(NS_ERROR_FAILURE);
     497           0 :     return;
     498             :   }
     499             : 
     500           0 :   if (!WebrtcContentParents::Empty()) {
     501             :     // Pass on the request to any content based PeerConnections.
     502           0 :     for (auto& cp : WebrtcContentParents::GetAll()) {
     503           0 :       request->mContactList.push(cp);
     504             :     }
     505             : 
     506           0 :     auto next = request->GetNextParent();
     507           0 :     if (next) {
     508           0 :       aRv = next->SendGetStatsRequest(request->mRequestId, request->mPcIdFilter) ?
     509           0 :                 NS_OK : NS_ERROR_FAILURE;
     510           0 :       return;
     511             :     }
     512             :   }
     513             :   // No content resident PeerConnectionCtx instances.
     514             :   // Check this process.
     515           0 :   PeerConnectionCtx* ctx = GetPeerConnectionCtx();
     516             :   nsresult rv;
     517             : 
     518           0 :   if (ctx) {
     519           0 :     rv = RunStatsQuery(ctx->mGetPeerConnections(),
     520           0 :                        filter, nullptr, request->mRequestId);
     521             : 
     522           0 :     if (NS_FAILED(rv)) {
     523           0 :       StatsRequest::Delete(request->mRequestId);
     524             :     }
     525             :   } else {
     526             :     // Just send back an empty report.
     527           0 :     rv = NS_OK;
     528           0 :     request->Complete();
     529           0 :     StatsRequest::Delete(request->mRequestId);
     530             :   }
     531             : 
     532           0 :   aRv = rv;
     533           0 :   return;
     534             : }
     535             : 
     536             : static nsresult
     537           0 : RunLogQuery(const nsCString& aPattern,
     538             :             WebrtcGlobalChild* aThisChild,
     539             :             const int aRequestId)
     540             : {
     541             :   nsresult rv;
     542             :   nsCOMPtr<nsIEventTarget> stsThread =
     543           0 :     do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
     544             : 
     545           0 :   if (NS_FAILED(rv)) {
     546           0 :     return rv;
     547             :   }
     548           0 :   if (!stsThread) {
     549           0 :     return NS_ERROR_FAILURE;
     550             :   }
     551             : 
     552           0 :   rv = RUN_ON_THREAD(stsThread,
     553           0 :                      WrapRunnableNM(&GetLogging_s,
     554             :                                     aThisChild,
     555             :                                     aRequestId,
     556           0 :                                     aPattern.get()),
     557             :                      NS_DISPATCH_NORMAL);
     558           0 :   return rv;
     559             : }
     560             : 
     561           0 : static void ClearLogs_s()
     562             : {
     563             :   // Make call off main thread.
     564           0 :   RLogConnector* logs = RLogConnector::GetInstance();
     565           0 :   if (logs) {
     566           0 :     logs->Clear();
     567             :   }
     568           0 : }
     569             : 
     570             : static nsresult
     571           0 : RunLogClear()
     572             : {
     573             :   nsresult rv;
     574             :   nsCOMPtr<nsIEventTarget> stsThread =
     575           0 :     do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
     576             : 
     577           0 :   if (NS_FAILED(rv)) {
     578           0 :     return rv;
     579             :   }
     580           0 :   if (!stsThread) {
     581           0 :     return NS_ERROR_FAILURE;
     582             :   }
     583             : 
     584           0 :   return RUN_ON_THREAD(stsThread,
     585           0 :                        WrapRunnableNM(&ClearLogs_s),
     586           0 :                        NS_DISPATCH_NORMAL);
     587             : }
     588             : 
     589             : void
     590           0 : WebrtcGlobalInformation::ClearLogging(
     591             :   const GlobalObject& aGlobal)
     592             : {
     593           0 :   if (!NS_IsMainThread()) {
     594           0 :     return;
     595             :   }
     596             : 
     597             :   // Chrome-only API
     598           0 :   MOZ_ASSERT(XRE_IsParentProcess());
     599             : 
     600           0 :   if (!WebrtcContentParents::Empty()) {
     601             :   // Clear content process signaling logs
     602           0 :     for (auto& cp : WebrtcContentParents::GetAll()) {
     603           0 :       Unused << cp->SendClearLogRequest();
     604             :     }
     605             :   }
     606             : 
     607             :   // Clear chrome process signaling logs
     608           0 :   Unused << RunLogClear();
     609             : }
     610             : 
     611             : void
     612           0 : WebrtcGlobalInformation::GetLogging(
     613             :   const GlobalObject& aGlobal,
     614             :   const nsAString& aPattern,
     615             :   WebrtcGlobalLoggingCallback& aLoggingCallback,
     616             :   ErrorResult& aRv)
     617             : {
     618           0 :   if (!NS_IsMainThread()) {
     619           0 :     aRv.Throw(NS_ERROR_NOT_SAME_THREAD);
     620           0 :     return;
     621             :   }
     622             : 
     623           0 :   MOZ_ASSERT(XRE_IsParentProcess());
     624             : 
     625             :   // CallbackObject does not support threadsafe refcounting, and must be
     626             :   // destroyed on main.
     627             :   LogRequestCallback callbackHandle(
     628             :     new nsMainThreadPtrHolder<WebrtcGlobalLoggingCallback>(
     629           0 :       "WebrtcGlobalLoggingCallback", &aLoggingCallback));
     630             : 
     631           0 :   nsAutoCString pattern;
     632           0 :   CopyUTF16toUTF8(aPattern, pattern);
     633             : 
     634           0 :   LogRequest* request = LogRequest::Create(callbackHandle, pattern);
     635             : 
     636           0 :   if (!request) {
     637           0 :     aRv.Throw(NS_ERROR_FAILURE);
     638           0 :     return;
     639             :   }
     640             : 
     641           0 :   if (!WebrtcContentParents::Empty()) {
     642             :   // Pass on the request to any content based PeerConnections.
     643           0 :     for (auto& cp : WebrtcContentParents::GetAll()) {
     644           0 :       request->mContactList.push(cp);
     645             :     }
     646             : 
     647           0 :     auto next = request->GetNextParent();
     648           0 :     if (next) {
     649           0 :       aRv = next->SendGetLogRequest(request->mRequestId, request->mPattern) ?
     650           0 :                 NS_OK : NS_ERROR_FAILURE;
     651           0 :       return;
     652             :     }
     653             :   }
     654             : 
     655           0 :   nsresult rv = RunLogQuery(request->mPattern, nullptr, request->mRequestId);
     656             : 
     657           0 :   if (NS_FAILED(rv)) {
     658           0 :     LogRequest::Delete(request->mRequestId);
     659             :   }
     660             : 
     661           0 :   aRv = rv;
     662           0 :   return;
     663             : }
     664             : 
     665             : static int32_t sLastSetLevel = 0;
     666             : static bool sLastAECDebug = false;
     667             : 
     668             : void
     669           0 : WebrtcGlobalInformation::SetDebugLevel(const GlobalObject& aGlobal, int32_t aLevel)
     670             : {
     671           0 :   if (aLevel) {
     672           0 :     StartWebRtcLog(webrtc::TraceLevel(aLevel));
     673             :   } else {
     674           0 :     StopWebRtcLog();
     675             :   }
     676           0 :   sLastSetLevel = aLevel;
     677             : 
     678           0 :   for (auto& cp : WebrtcContentParents::GetAll()){
     679           0 :     Unused << cp->SendSetDebugMode(aLevel);
     680             :   }
     681           0 : }
     682             : 
     683             : int32_t
     684           0 : WebrtcGlobalInformation::DebugLevel(const GlobalObject& aGlobal)
     685             : {
     686           0 :   return sLastSetLevel;
     687             : }
     688             : 
     689             : void
     690           0 : WebrtcGlobalInformation::SetAecDebug(const GlobalObject& aGlobal, bool aEnable)
     691             : {
     692           0 :   if (aEnable) {
     693           0 :     StartAecLog();
     694             :   } else {
     695           0 :     StopAecLog();
     696             :   }
     697             : 
     698           0 :   sLastAECDebug = aEnable;
     699             : 
     700           0 :   for (auto& cp : WebrtcContentParents::GetAll()){
     701           0 :     Unused << cp->SendSetAecLogging(aEnable);
     702             :   }
     703           0 : }
     704             : 
     705             : bool
     706           0 : WebrtcGlobalInformation::AecDebug(const GlobalObject& aGlobal)
     707             : {
     708           0 :   return sLastAECDebug;
     709             : }
     710             : 
     711             : mozilla::ipc::IPCResult
     712           0 : WebrtcGlobalParent::RecvGetStatsResult(const int& aRequestId,
     713             :                                        nsTArray<RTCStatsReportInternal>&& Stats)
     714             : {
     715           0 :   MOZ_ASSERT(NS_IsMainThread());
     716           0 :   nsresult rv = NS_OK;
     717             : 
     718           0 :   StatsRequest* request = StatsRequest::Get(aRequestId);
     719             : 
     720           0 :   if (!request) {
     721           0 :     CSFLogError(logTag, "Bad RequestId");
     722           0 :     return IPC_FAIL_NO_REASON(this);
     723             :   }
     724             : 
     725           0 :   for (auto&& s : Stats) {
     726           0 :     request->mResult.mReports.Value().AppendElement(s, fallible);
     727             :   }
     728             : 
     729           0 :   auto next = request->GetNextParent();
     730           0 :   if (next) {
     731             :     // There are more content instances to query.
     732           0 :     if (!next->SendGetStatsRequest(request->mRequestId, request->mPcIdFilter)) {
     733           0 :       return IPC_FAIL_NO_REASON(this);
     734             :     }
     735           0 :     return IPC_OK();
     736             :   }
     737             : 
     738             :   // Content queries complete, run chrome instance query if applicable
     739           0 :   PeerConnectionCtx* ctx = GetPeerConnectionCtx();
     740             : 
     741           0 :   if (ctx) {
     742           0 :     rv = RunStatsQuery(ctx->mGetPeerConnections(),
     743           0 :                        request->mPcIdFilter, nullptr, aRequestId);
     744             :   } else {
     745             :     // No instance in the process, return the collections as is
     746           0 :     request->Complete();
     747           0 :     StatsRequest::Delete(aRequestId);
     748             :   }
     749             : 
     750           0 :   if (NS_FAILED(rv)) {
     751           0 :     return IPC_FAIL_NO_REASON(this);
     752             :   }
     753           0 :   return IPC_OK();
     754             : }
     755             : 
     756             : mozilla::ipc::IPCResult
     757           0 : WebrtcGlobalParent::RecvGetLogResult(const int& aRequestId,
     758             :                                      const WebrtcGlobalLog& aLog)
     759             : {
     760           0 :   MOZ_ASSERT(NS_IsMainThread());
     761             : 
     762           0 :   LogRequest* request = LogRequest::Get(aRequestId);
     763             : 
     764           0 :   if (!request) {
     765           0 :     CSFLogError(logTag, "Bad RequestId");
     766           0 :     return IPC_FAIL_NO_REASON(this);
     767             :   }
     768           0 :   request->mResult.AppendElements(aLog, fallible);
     769             : 
     770           0 :   auto next = request->GetNextParent();
     771           0 :   if (next) {
     772             :     // There are more content instances to query.
     773           0 :     if (!next->SendGetLogRequest(request->mRequestId, request->mPattern)) {
     774           0 :       return IPC_FAIL_NO_REASON(this);
     775             :     }
     776           0 :     return IPC_OK();
     777             :   }
     778             : 
     779             :   // Content queries complete, run chrome instance query if applicable
     780           0 :   nsresult rv = RunLogQuery(request->mPattern, nullptr, aRequestId);
     781             : 
     782           0 :   if (NS_FAILED(rv)) {
     783             :     //Unable to get gecko process log. Return what has been collected.
     784           0 :     CSFLogError(logTag, "Unable to extract chrome process log");
     785           0 :     request->Complete();
     786           0 :     LogRequest::Delete(aRequestId);
     787             :   }
     788             : 
     789           0 :   return IPC_OK();
     790             : }
     791             : 
     792             : WebrtcGlobalParent*
     793           0 : WebrtcGlobalParent::Alloc()
     794             : {
     795           0 :   return WebrtcContentParents::Alloc();
     796             : }
     797             : 
     798             : bool
     799           0 : WebrtcGlobalParent::Dealloc(WebrtcGlobalParent * aActor)
     800             : {
     801           0 :   WebrtcContentParents::Dealloc(aActor);
     802           0 :   return true;
     803             : }
     804             : 
     805             : void
     806           0 : WebrtcGlobalParent::ActorDestroy(ActorDestroyReason aWhy)
     807             : {
     808           0 :   mShutdown = true;
     809           0 :   return;
     810             : }
     811             : 
     812             : mozilla::ipc::IPCResult
     813           0 : WebrtcGlobalParent::Recv__delete__()
     814             : {
     815           0 :   return IPC_OK();
     816             : }
     817             : 
     818           0 : MOZ_IMPLICIT WebrtcGlobalParent::WebrtcGlobalParent()
     819           0 :   : mShutdown(false)
     820             : {
     821           0 :   MOZ_COUNT_CTOR(WebrtcGlobalParent);
     822           0 : }
     823             : 
     824           0 : MOZ_IMPLICIT WebrtcGlobalParent::~WebrtcGlobalParent()
     825             : {
     826           0 :   MOZ_COUNT_DTOR(WebrtcGlobalParent);
     827           0 : }
     828             : 
     829             : mozilla::ipc::IPCResult
     830           0 : WebrtcGlobalChild::RecvGetStatsRequest(const int& aRequestId,
     831             :                                        const nsString& aPcIdFilter)
     832             : {
     833           0 :   if (mShutdown) {
     834           0 :     return IPC_OK();
     835             :   }
     836             : 
     837           0 :   PeerConnectionCtx* ctx = GetPeerConnectionCtx();
     838             : 
     839           0 :   if (ctx) {
     840           0 :     nsresult rv = RunStatsQuery(ctx->mGetPeerConnections(),
     841           0 :                                 aPcIdFilter, this, aRequestId);
     842           0 :     if (NS_FAILED(rv)) {
     843           0 :       return IPC_FAIL_NO_REASON(this);
     844             :     }
     845           0 :     return IPC_OK();
     846             :   }
     847             : 
     848           0 :   nsTArray<RTCStatsReportInternal> empty_stats;
     849           0 :   SendGetStatsResult(aRequestId, empty_stats);
     850             : 
     851           0 :   return IPC_OK();
     852             : }
     853             : 
     854             : mozilla::ipc::IPCResult
     855           0 : WebrtcGlobalChild::RecvClearStatsRequest()
     856             : {
     857           0 :   if (mShutdown) {
     858           0 :     return IPC_OK();
     859             :   }
     860             : 
     861           0 :   ClearClosedStats();
     862           0 :   return IPC_OK();
     863             : }
     864             : 
     865             : mozilla::ipc::IPCResult
     866           0 : WebrtcGlobalChild::RecvGetLogRequest(const int& aRequestId,
     867             :                                      const nsCString& aPattern)
     868             : {
     869           0 :   if (mShutdown) {
     870           0 :     return IPC_OK();
     871             :   }
     872             : 
     873             :   nsresult rv;
     874             :   nsCOMPtr<nsIEventTarget> stsThread =
     875           0 :     do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
     876             : 
     877           0 :   if (NS_SUCCEEDED(rv) && stsThread) {
     878             :     // this is a singleton, so we shouldn't need to hold a ref for the
     879             :     // request (and can't just add a ref here anyways)
     880           0 :     rv = RUN_ON_THREAD(stsThread,
     881           0 :                        WrapRunnableNM(&GetLogging_s, this, aRequestId, aPattern.get()),
     882             :                        NS_DISPATCH_NORMAL);
     883             : 
     884           0 :     if (NS_SUCCEEDED(rv)) {
     885           0 :       return IPC_OK();
     886             :     }
     887             :   }
     888             : 
     889           0 :   Sequence<nsString> empty_log;
     890           0 :   SendGetLogResult(aRequestId, empty_log);
     891             : 
     892           0 :   return IPC_OK();
     893             : }
     894             : 
     895             : mozilla::ipc::IPCResult
     896           0 : WebrtcGlobalChild::RecvClearLogRequest()
     897             : {
     898           0 :   if (mShutdown) {
     899           0 :     return IPC_OK();
     900             :   }
     901             : 
     902           0 :   RunLogClear();
     903           0 :   return IPC_OK();
     904             : }
     905             : 
     906             : mozilla::ipc::IPCResult
     907           0 : WebrtcGlobalChild::RecvSetAecLogging(const bool& aEnable)
     908             : {
     909           0 :   if (!mShutdown) {
     910           0 :     if (aEnable) {
     911           0 :       StartAecLog();
     912             :     } else {
     913           0 :       StopAecLog();
     914             :     }
     915             :   }
     916           0 :   return IPC_OK();
     917             : }
     918             : 
     919             : mozilla::ipc::IPCResult
     920           0 : WebrtcGlobalChild::RecvSetDebugMode(const int& aLevel)
     921             : {
     922           0 :   if (!mShutdown) {
     923           0 :     if (aLevel) {
     924           0 :       StartWebRtcLog(webrtc::TraceLevel(aLevel));
     925             :     } else {
     926           0 :       StopWebRtcLog();
     927             :     }
     928             :   }
     929           0 :   return IPC_OK();
     930             : }
     931             : 
     932             : WebrtcGlobalChild*
     933           0 : WebrtcGlobalChild::Create()
     934             : {
     935             :   WebrtcGlobalChild* child =
     936             :     static_cast<WebrtcGlobalChild*>(
     937           0 :       ContentChild::GetSingleton()->SendPWebrtcGlobalConstructor());
     938           0 :   return child;
     939             : }
     940             : 
     941             : void
     942           0 : WebrtcGlobalChild::ActorDestroy(ActorDestroyReason aWhy)
     943             : {
     944           0 :   mShutdown = true;
     945           0 : }
     946             : 
     947           0 : MOZ_IMPLICIT WebrtcGlobalChild::WebrtcGlobalChild()
     948           0 :   : mShutdown(false)
     949             : {
     950           0 :   MOZ_COUNT_CTOR(WebrtcGlobalChild);
     951           0 : }
     952             : 
     953           0 : MOZ_IMPLICIT WebrtcGlobalChild::~WebrtcGlobalChild()
     954             : {
     955           0 :   MOZ_COUNT_DTOR(WebrtcGlobalChild);
     956           0 : }
     957             : 
     958             : struct StreamResult {
     959           0 :   StreamResult() : candidateTypeBitpattern(0), streamSucceeded(false) {}
     960             :   uint32_t candidateTypeBitpattern;
     961             :   bool streamSucceeded;
     962             : };
     963             : 
     964           0 : static uint32_t GetCandidateIpAndTransportMask(const RTCIceCandidateStats *cand) {
     965             : 
     966             :   enum {
     967             :     CANDIDATE_BITMASK_UDP = 1,
     968             :     CANDIDATE_BITMASK_TCP = 1 << 1,
     969             :     CANDIDATE_BITMASK_IPV6 = 1 << 2,
     970             :   };
     971             : 
     972           0 :   uint32_t res = 0;
     973             : 
     974           0 :   nsAutoCString transport;
     975             :   // prefer local transport for local relay candidates
     976           0 :   if (cand->mMozLocalTransport.WasPassed()) {
     977           0 :     transport.Assign(NS_ConvertUTF16toUTF8(cand->mMozLocalTransport.Value()));
     978             :   } else {
     979           0 :     transport.Assign(NS_ConvertUTF16toUTF8(cand->mTransport.Value()));
     980             :   }
     981           0 :   if (transport == kNrIceTransportUdp) {
     982           0 :     res |= CANDIDATE_BITMASK_UDP;
     983           0 :   } else if (transport == kNrIceTransportTcp) {
     984           0 :     res |= CANDIDATE_BITMASK_TCP;
     985             :   }
     986             : 
     987           0 :   if (cand->mIpAddress.Value().FindChar(':') != -1) {
     988           0 :     res |= CANDIDATE_BITMASK_IPV6;
     989             :   }
     990             : 
     991           0 :   return res;
     992             : };
     993             : 
     994           0 : static void StoreLongTermICEStatisticsImpl_m(
     995             :     nsresult result,
     996             :     nsAutoPtr<RTCStatsQuery> query) {
     997             : 
     998             :   using namespace Telemetry;
     999             : 
    1000           0 :   if (NS_FAILED(result) ||
    1001           0 :       !query->error.empty() ||
    1002           0 :       !query->report->mIceCandidateStats.WasPassed()) {
    1003           0 :     return;
    1004             :   }
    1005             : 
    1006           0 :   query->report->mClosed.Construct(true);
    1007             : 
    1008             :   // TODO(bcampen@mozilla.com): Do we need to watch out for cases where the
    1009             :   // components within a stream didn't have the same types of relayed
    1010             :   // candidates? I have a feeling that late trickle could cause this, but right
    1011             :   // now we don't have enough information to detect it (we would need to know
    1012             :   // the ICE component id for each candidate pair and candidate)
    1013             : 
    1014           0 :   std::map<std::string, StreamResult> streamResults;
    1015             : 
    1016             :   // Build list of streams, and whether or not they failed.
    1017           0 :   for (size_t i = 0;
    1018           0 :        i < query->report->mIceCandidatePairStats.Value().Length();
    1019             :        ++i) {
    1020             :     const RTCIceCandidatePairStats &pair =
    1021           0 :       query->report->mIceCandidatePairStats.Value()[i];
    1022             : 
    1023           0 :     if (!pair.mState.WasPassed() || !pair.mTransportId.WasPassed()) {
    1024           0 :       MOZ_CRASH();
    1025             :       continue;
    1026             :     }
    1027             : 
    1028             :     // Note: we use NrIceMediaStream's name for the
    1029             :     // RTCIceCandidatePairStats tranportId
    1030             :     std::string streamId(
    1031           0 :       NS_ConvertUTF16toUTF8(pair.mTransportId.Value()).get());
    1032             : 
    1033           0 :     streamResults[streamId].streamSucceeded |=
    1034           0 :       pair.mState.Value() == RTCStatsIceCandidatePairState::Succeeded;
    1035             :   }
    1036             : 
    1037           0 :   for (size_t i = 0;
    1038           0 :        i < query->report->mIceCandidateStats.Value().Length();
    1039             :        ++i) {
    1040             :     const RTCIceCandidateStats &cand =
    1041           0 :       query->report->mIceCandidateStats.Value()[i];
    1042             : 
    1043           0 :     if (!cand.mType.WasPassed() ||
    1044           0 :         !cand.mCandidateType.WasPassed() ||
    1045           0 :         !cand.mTransport.WasPassed() ||
    1046           0 :         !cand.mIpAddress.WasPassed() ||
    1047           0 :         !cand.mComponentId.WasPassed()) {
    1048             :       // Crash on debug, ignore this candidate otherwise.
    1049           0 :       MOZ_CRASH();
    1050             :       continue;
    1051             :     }
    1052             : 
    1053             :     /* The bitmask after examaning a candidate should look like this:
    1054             :      * REMOTE_GATHERED_HOST_UDP = 1,
    1055             :      * REMOTE_GATHERED_HOST_TCP = 1 << 1,
    1056             :      * REMOTE_GATHERED_HOST_IPV6 = 1 << 2,
    1057             :      * REMOTE_GATHERED_SERVER_REFLEXIVE_UDP = 1 << 3,
    1058             :      * REMOTE_GATHERED_SERVER_REFLEXIVE_TCP = 1 << 4,
    1059             :      * REMOTE_GATHERED_SERVER_REFLEXIVE_IPV6 = 1 << 5,
    1060             :      * REMOTE_GATHERED_TURN_UDP = 1 << 6,
    1061             :      * REMOTE_GATHERED_TURN_TCP = 1 << 7, // dummy place holder
    1062             :      * REMOTE_GATHERED_TURN_IPV6 = 1 << 8,
    1063             :      * REMOTE_GATHERED_PEER_REFLEXIVE_UDP = 1 << 9,
    1064             :      * REMOTE_GATHERED_PEER_REFLEXIVE_TCP = 1 << 10,
    1065             :      * REMOTE_GATHERED_PEER_REFLEXIVE_IPV6 = 1 << 11,
    1066             :      * LOCAL_GATHERED_HOST_UDP = 1 << 16,
    1067             :      * LOCAL_GATHERED_HOST_TCP = 1 << 17,
    1068             :      * LOCAL_GATHERED_HOST_IPV6 = 1 << 18,
    1069             :      * LOCAL_GATHERED_SERVER_REFLEXIVE_UDP = 1 << 19,
    1070             :      * LOCAL_GATHERED_SERVER_REFLEXIVE_TCP = 1 << 20,
    1071             :      * LOCAL_GATHERED_SERVER_REFLEXIVE_IPV6 = 1 << 21,
    1072             :      * LOCAL_GATHERED_TURN_UDP = 1 << 22,
    1073             :      * LOCAL_GATHERED_TURN_TCP = 1 << 23,
    1074             :      * LOCAL_GATHERED_TURN_IPV6 = 1 << 24,
    1075             :      * LOCAL_GATHERED_PEERREFLEXIVE_UDP = 1 << 25,
    1076             :      * LOCAL_GATHERED_PEERREFLEXIVE_TCP = 1 << 26,
    1077             :      * LOCAL_GATHERED_PEERREFLEXIVE_IPV6 = 1 << 27,
    1078             :      *
    1079             :      * This results in following shift values
    1080             :      */
    1081             :     static const uint32_t kLocalShift = 16;
    1082             :     static const uint32_t kSrflxShift = 3;
    1083             :     static const uint32_t kRelayShift = 6;
    1084             :     static const uint32_t kPrflxShift = 9;
    1085             : 
    1086           0 :     uint32_t candBitmask = GetCandidateIpAndTransportMask(&cand);
    1087             : 
    1088             :     // Note: shift values need to result in the above enum table
    1089           0 :     if (cand.mType.Value() == RTCStatsType::Local_candidate) {
    1090           0 :       candBitmask <<= kLocalShift;
    1091             :     }
    1092             : 
    1093           0 :     if (cand.mCandidateType.Value() == RTCStatsIceCandidateType::Serverreflexive) {
    1094           0 :       candBitmask <<= kSrflxShift;
    1095           0 :     } else if (cand.mCandidateType.Value() == RTCStatsIceCandidateType::Relayed) {
    1096           0 :       candBitmask <<= kRelayShift;
    1097           0 :     } else if (cand.mCandidateType.Value() == RTCStatsIceCandidateType::Peerreflexive) {
    1098           0 :       candBitmask <<= kPrflxShift;
    1099             :     }
    1100             : 
    1101             :     // Note: this is not a "component" in the ICE definition, this is really a
    1102             :     // stream ID. This is just the way the stats API is standardized right now.
    1103             :     // Very confusing.
    1104             :     std::string streamId(
    1105           0 :       NS_ConvertUTF16toUTF8(cand.mComponentId.Value()).get());
    1106             : 
    1107           0 :     streamResults[streamId].candidateTypeBitpattern |= candBitmask;
    1108             :   }
    1109             : 
    1110           0 :   for (auto& streamResult : streamResults) {
    1111           0 :     Telemetry::RecordWebrtcIceCandidates(streamResult.second.candidateTypeBitpattern,
    1112           0 :                                          streamResult.second.streamSucceeded);
    1113             :   }
    1114             : 
    1115             :   // Beyond ICE, accumulate telemetry for various PER_CALL settings here.
    1116             : 
    1117           0 :   if (query->report->mOutboundRTPStreamStats.WasPassed()) {
    1118           0 :     auto& array = query->report->mOutboundRTPStreamStats.Value();
    1119           0 :     for (decltype(array.Length()) i = 0; i < array.Length(); i++) {
    1120           0 :       auto& s = array[i];
    1121           0 :       bool isVideo = (s.mId.Value().Find("video") != -1);
    1122           0 :       if (!isVideo || s.mIsRemote) {
    1123           0 :         continue;
    1124             :       }
    1125           0 :       if (s.mBitrateMean.WasPassed()) {
    1126           0 :         Accumulate(WEBRTC_VIDEO_ENCODER_BITRATE_AVG_PER_CALL_KBPS,
    1127           0 :                    uint32_t(s.mBitrateMean.Value() / 1000));
    1128             :       }
    1129           0 :       if (s.mBitrateStdDev.WasPassed()) {
    1130           0 :         Accumulate(WEBRTC_VIDEO_ENCODER_BITRATE_STD_DEV_PER_CALL_KBPS,
    1131           0 :                    uint32_t(s.mBitrateStdDev.Value() / 1000));
    1132             :       }
    1133           0 :       if (s.mFramerateMean.WasPassed()) {
    1134           0 :         Accumulate(WEBRTC_VIDEO_ENCODER_FRAMERATE_AVG_PER_CALL,
    1135           0 :                    uint32_t(s.mFramerateMean.Value()));
    1136             :       }
    1137           0 :       if (s.mFramerateStdDev.WasPassed()) {
    1138           0 :         Accumulate(WEBRTC_VIDEO_ENCODER_FRAMERATE_10X_STD_DEV_PER_CALL,
    1139           0 :                    uint32_t(s.mFramerateStdDev.Value() * 10));
    1140             :       }
    1141           0 :       if (s.mDroppedFrames.WasPassed() && !query->iceStartTime.IsNull()) {
    1142           0 :         double mins = (TimeStamp::Now() - query->iceStartTime).ToSeconds() / 60;
    1143           0 :         if (mins > 0) {
    1144           0 :           Accumulate(WEBRTC_VIDEO_ENCODER_DROPPED_FRAMES_PER_CALL_FPM,
    1145           0 :                      uint32_t(double(s.mDroppedFrames.Value()) / mins));
    1146             :         }
    1147             :       }
    1148             :     }
    1149             :   }
    1150             : 
    1151           0 :   if (query->report->mInboundRTPStreamStats.WasPassed()) {
    1152           0 :     auto& array = query->report->mInboundRTPStreamStats.Value();
    1153           0 :     for (decltype(array.Length()) i = 0; i < array.Length(); i++) {
    1154           0 :       auto& s = array[i];
    1155           0 :       bool isVideo = (s.mId.Value().Find("video") != -1);
    1156           0 :       if (!isVideo || s.mIsRemote) {
    1157           0 :         continue;
    1158             :       }
    1159           0 :       if (s.mBitrateMean.WasPassed()) {
    1160           0 :         Accumulate(WEBRTC_VIDEO_DECODER_BITRATE_AVG_PER_CALL_KBPS,
    1161           0 :                    uint32_t(s.mBitrateMean.Value() / 1000));
    1162             :       }
    1163           0 :       if (s.mBitrateStdDev.WasPassed()) {
    1164           0 :         Accumulate(WEBRTC_VIDEO_DECODER_BITRATE_STD_DEV_PER_CALL_KBPS,
    1165           0 :                    uint32_t(s.mBitrateStdDev.Value() / 1000));
    1166             :       }
    1167           0 :       if (s.mFramerateMean.WasPassed()) {
    1168           0 :         Accumulate(WEBRTC_VIDEO_DECODER_FRAMERATE_AVG_PER_CALL,
    1169           0 :                    uint32_t(s.mFramerateMean.Value()));
    1170             :       }
    1171           0 :       if (s.mFramerateStdDev.WasPassed()) {
    1172           0 :         Accumulate(WEBRTC_VIDEO_DECODER_FRAMERATE_10X_STD_DEV_PER_CALL,
    1173           0 :                    uint32_t(s.mFramerateStdDev.Value() * 10));
    1174             :       }
    1175           0 :       if (s.mDiscardedPackets.WasPassed() && !query->iceStartTime.IsNull()) {
    1176           0 :         double mins = (TimeStamp::Now() - query->iceStartTime).ToSeconds() / 60;
    1177           0 :         if (mins > 0) {
    1178           0 :           Accumulate(WEBRTC_VIDEO_DECODER_DISCARDED_PACKETS_PER_CALL_PPM,
    1179           0 :                      uint32_t(double(s.mDiscardedPackets.Value()) / mins));
    1180             :         }
    1181             :       }
    1182             :     }
    1183             :   }
    1184             : 
    1185             :   // Finally, store the stats
    1186             : 
    1187           0 :   PeerConnectionCtx *ctx = GetPeerConnectionCtx();
    1188           0 :   if (ctx) {
    1189           0 :     ctx->mStatsForClosedPeerConnections.AppendElement(*query->report, fallible);
    1190             :   }
    1191             : }
    1192             : 
    1193           0 : static void GetStatsForLongTermStorage_s(
    1194             :     nsAutoPtr<RTCStatsQuery> query) {
    1195             : 
    1196           0 :   MOZ_ASSERT(query);
    1197             : 
    1198           0 :   nsresult rv = PeerConnectionImpl::ExecuteStatsQuery_s(query.get());
    1199             : 
    1200             :   // Check whether packets were dropped due to rate limiting during
    1201             :   // this call. (These calls must be made on STS)
    1202           0 :   unsigned char rate_limit_bit_pattern = 0;
    1203           0 :   if (!mozilla::nr_socket_short_term_violation_time().IsNull() &&
    1204           0 :       !query->iceStartTime.IsNull() &&
    1205           0 :       mozilla::nr_socket_short_term_violation_time() >= query->iceStartTime) {
    1206           0 :     rate_limit_bit_pattern |= 1;
    1207             :   }
    1208           0 :   if (!mozilla::nr_socket_long_term_violation_time().IsNull() &&
    1209           0 :       !query->iceStartTime.IsNull() &&
    1210           0 :       mozilla::nr_socket_long_term_violation_time() >= query->iceStartTime) {
    1211           0 :     rate_limit_bit_pattern |= 2;
    1212             :   }
    1213             : 
    1214           0 :   if (query->failed) {
    1215           0 :     Telemetry::Accumulate(
    1216             :         Telemetry::WEBRTC_STUN_RATE_LIMIT_EXCEEDED_BY_TYPE_GIVEN_FAILURE,
    1217           0 :         rate_limit_bit_pattern);
    1218             :   } else {
    1219           0 :     Telemetry::Accumulate(
    1220             :         Telemetry::WEBRTC_STUN_RATE_LIMIT_EXCEEDED_BY_TYPE_GIVEN_SUCCESS,
    1221           0 :         rate_limit_bit_pattern);
    1222             :   }
    1223             : 
    1224             :   // Even if Telemetry::Accumulate is threadsafe, we still need to send the
    1225             :   // query back to main, since that is where it must be destroyed.
    1226             :   NS_DispatchToMainThread(
    1227           0 :       WrapRunnableNM(
    1228             :           &StoreLongTermICEStatisticsImpl_m,
    1229             :           rv,
    1230             :           query),
    1231           0 :       NS_DISPATCH_NORMAL);
    1232           0 : }
    1233             : 
    1234           0 : void WebrtcGlobalInformation::StoreLongTermICEStatistics(
    1235             :     PeerConnectionImpl& aPc) {
    1236           0 :   Telemetry::Accumulate(Telemetry::WEBRTC_ICE_FINAL_CONNECTION_STATE,
    1237           0 :                         static_cast<uint32_t>(aPc.IceConnectionState()));
    1238             : 
    1239           0 :   if (aPc.IceConnectionState() == PCImplIceConnectionState::New) {
    1240             :     // ICE has not started; we won't have any remote candidates, so recording
    1241             :     // statistics on gathered candidates is pointless.
    1242           0 :     return;
    1243             :   }
    1244             : 
    1245           0 :   nsAutoPtr<RTCStatsQuery> query(new RTCStatsQuery(true));
    1246             : 
    1247           0 :   nsresult rv = aPc.BuildStatsQuery_m(nullptr, query.get());
    1248             : 
    1249           0 :   NS_ENSURE_SUCCESS_VOID(rv);
    1250             : 
    1251           0 :   RUN_ON_THREAD(aPc.GetSTSThread(),
    1252           0 :                 WrapRunnableNM(&GetStatsForLongTermStorage_s,
    1253             :                                query),
    1254           0 :                 NS_DISPATCH_NORMAL);
    1255             : }
    1256             : 
    1257             : } // namespace dom
    1258           9 : } // namespace mozilla

Generated by: LCOV version 1.13