LCOV - code coverage report
Current view: top level - netwerk/base - NetworkActivityMonitor.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 3 130 2.3 %
Date: 2017-07-14 16:53:18 Functions: 1 21 4.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  *
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "NetworkActivityMonitor.h"
       8             : #include "prmem.h"
       9             : #include "nsIObserverService.h"
      10             : #include "nsPISocketTransportService.h"
      11             : #include "nsSocketTransportService2.h"
      12             : #include "nsThreadUtils.h"
      13             : #include "mozilla/Services.h"
      14             : #include "prerror.h"
      15             : 
      16             : using namespace mozilla::net;
      17             : 
      18             : static PRStatus
      19           0 : nsNetMon_Connect(PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
      20             : {
      21             :   PRStatus ret;
      22             :   PRErrorCode code;
      23           0 :   ret = fd->lower->methods->connect(fd->lower, addr, timeout);
      24           0 :   if (ret == PR_SUCCESS || (code = PR_GetError()) == PR_WOULD_BLOCK_ERROR ||
      25             :       code == PR_IN_PROGRESS_ERROR)
      26           0 :     NetworkActivityMonitor::DataInOut(NetworkActivityMonitor::kUpload);
      27           0 :   return ret;
      28             : }
      29             : 
      30             : static int32_t
      31           0 : nsNetMon_Read(PRFileDesc *fd, void *buf, int32_t len)
      32             : {
      33             :   int32_t ret;
      34           0 :   ret = fd->lower->methods->read(fd->lower, buf, len);
      35           0 :   if (ret >= 0)
      36           0 :     NetworkActivityMonitor::DataInOut(NetworkActivityMonitor::kDownload);
      37           0 :   return ret;
      38             : }
      39             : 
      40             : static int32_t
      41           0 : nsNetMon_Write(PRFileDesc *fd, const void *buf, int32_t len)
      42             : {
      43             :   int32_t ret;
      44           0 :   ret = fd->lower->methods->write(fd->lower, buf, len);
      45           0 :   if (ret > 0)
      46           0 :     NetworkActivityMonitor::DataInOut(NetworkActivityMonitor::kUpload);
      47           0 :   return ret;
      48             : }
      49             : 
      50             : static int32_t
      51           0 : nsNetMon_Writev(PRFileDesc *fd,
      52             :                 const PRIOVec *iov,
      53             :                 int32_t size,
      54             :                 PRIntervalTime timeout)
      55             : {
      56             :   int32_t ret;
      57           0 :   ret = fd->lower->methods->writev(fd->lower, iov, size, timeout);
      58           0 :   if (ret > 0)
      59           0 :     NetworkActivityMonitor::DataInOut(NetworkActivityMonitor::kUpload);
      60           0 :   return ret;
      61             : }
      62             : 
      63             : static int32_t
      64           0 : nsNetMon_Recv(PRFileDesc *fd,
      65             :               void *buf,
      66             :               int32_t amount,
      67             :               int flags,
      68             :               PRIntervalTime timeout)
      69             : {
      70             :   int32_t ret;
      71           0 :   ret = fd->lower->methods->recv(fd->lower, buf, amount, flags, timeout);
      72           0 :   if (ret >= 0)
      73           0 :     NetworkActivityMonitor::DataInOut(NetworkActivityMonitor::kDownload);
      74           0 :   return ret;
      75             : }
      76             : 
      77             : static int32_t
      78           0 : nsNetMon_Send(PRFileDesc *fd,
      79             :               const void *buf,
      80             :               int32_t amount,
      81             :               int flags,
      82             :               PRIntervalTime timeout)
      83             : {
      84             :   int32_t ret;
      85           0 :   ret = fd->lower->methods->send(fd->lower, buf, amount, flags, timeout);
      86           0 :   if (ret > 0)
      87           0 :     NetworkActivityMonitor::DataInOut(NetworkActivityMonitor::kUpload);
      88           0 :   return ret;
      89             : }
      90             : 
      91             : static int32_t
      92           0 : nsNetMon_RecvFrom(PRFileDesc *fd,
      93             :                   void *buf,
      94             :                   int32_t amount,
      95             :                   int flags,
      96             :                   PRNetAddr *addr,
      97             :                   PRIntervalTime timeout)
      98             : {
      99             :   int32_t ret;
     100           0 :   ret = fd->lower->methods->recvfrom(fd->lower,
     101             :                                      buf,
     102             :                                      amount,
     103             :                                      flags,
     104             :                                      addr,
     105           0 :                                      timeout);
     106           0 :   if (ret >= 0)
     107           0 :     NetworkActivityMonitor::DataInOut(NetworkActivityMonitor::kDownload);
     108           0 :   return ret;
     109             : }
     110             : 
     111             : static int32_t
     112           0 : nsNetMon_SendTo(PRFileDesc *fd,
     113             :                 const void *buf,
     114             :                 int32_t amount,
     115             :                 int flags,
     116             :                 const PRNetAddr *addr,
     117             :                 PRIntervalTime timeout)
     118             : {
     119             :   int32_t ret;
     120           0 :   ret = fd->lower->methods->sendto(fd->lower,
     121             :                                    buf,
     122             :                                    amount,
     123             :                                    flags,
     124             :                                    addr,
     125           0 :                                    timeout);
     126           0 :   if (ret > 0)
     127           0 :     NetworkActivityMonitor::DataInOut(NetworkActivityMonitor::kUpload);
     128           0 :   return ret;
     129             : }
     130             : 
     131             : static int32_t
     132           0 : nsNetMon_AcceptRead(PRFileDesc *listenSock,
     133             :                     PRFileDesc **acceptedSock,
     134             :                     PRNetAddr **peerAddr,
     135             :                     void *buf,
     136             :                     int32_t amount,
     137             :                     PRIntervalTime timeout)
     138             : {
     139             :   int32_t ret;
     140           0 :   ret = listenSock->lower->methods->acceptread(listenSock->lower,
     141             :                                                acceptedSock,
     142             :                                                peerAddr,
     143             :                                                buf,
     144             :                                                amount,
     145           0 :                                                timeout);
     146           0 :   if (ret > 0)
     147           0 :     NetworkActivityMonitor::DataInOut(NetworkActivityMonitor::kDownload);
     148           0 :   return ret;
     149             : }
     150             : 
     151             : 
     152           0 : class NotifyNetworkActivity : public mozilla::Runnable {
     153             : public:
     154           0 :   explicit NotifyNetworkActivity(NetworkActivityMonitor::Direction aDirection)
     155           0 :     : mozilla::Runnable("NotifyNetworkActivity")
     156           0 :     , mDirection(aDirection)
     157           0 :   {}
     158           0 :   NS_IMETHOD Run() override
     159             :   {
     160           0 :     MOZ_ASSERT(NS_IsMainThread());
     161             : 
     162           0 :     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     163           0 :     if (!obs)
     164           0 :       return NS_ERROR_FAILURE;
     165             : 
     166           0 :     obs->NotifyObservers(nullptr,
     167           0 :                          mDirection == NetworkActivityMonitor::kUpload
     168             :                            ? NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC
     169             :                            : NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC,
     170           0 :                          nullptr);
     171           0 :     return NS_OK;
     172             :   }
     173             : private:
     174             :   NetworkActivityMonitor::Direction mDirection;
     175             : };
     176             : 
     177             : NetworkActivityMonitor * NetworkActivityMonitor::gInstance = nullptr;
     178             : static PRDescIdentity sNetActivityMonitorLayerIdentity;
     179             : static PRIOMethods sNetActivityMonitorLayerMethods;
     180             : static PRIOMethods *sNetActivityMonitorLayerMethodsPtr = nullptr;
     181             : 
     182           0 : NetworkActivityMonitor::NetworkActivityMonitor()
     183           0 :   : mBlipInterval(PR_INTERVAL_NO_TIMEOUT)
     184             : {
     185           0 :   MOZ_COUNT_CTOR(NetworkActivityMonitor);
     186             : 
     187           0 :   NS_ASSERTION(gInstance==nullptr,
     188             :                "multiple NetworkActivityMonitor instances!");
     189           0 : }
     190             : 
     191           0 : NetworkActivityMonitor::~NetworkActivityMonitor()
     192             : {
     193           0 :   MOZ_COUNT_DTOR(NetworkActivityMonitor);
     194           0 :   gInstance = nullptr;
     195           0 : }
     196             : 
     197             : nsresult
     198           0 : NetworkActivityMonitor::Init(int32_t blipInterval)
     199             : {
     200             :   nsresult rv;
     201             : 
     202           0 :   if (gInstance)
     203           0 :     return NS_ERROR_ALREADY_INITIALIZED;
     204             : 
     205           0 :   NetworkActivityMonitor * mon = new NetworkActivityMonitor();
     206           0 :   rv = mon->Init_Internal(blipInterval);
     207           0 :   if (NS_FAILED(rv)) {
     208           0 :     delete mon;
     209           0 :     return rv;
     210             :   }
     211             : 
     212           0 :   gInstance = mon;
     213           0 :   return NS_OK;
     214             : }
     215             : 
     216             : nsresult
     217           0 : NetworkActivityMonitor::Shutdown()
     218             : {
     219           0 :   if (!gInstance)
     220           0 :     return NS_ERROR_NOT_INITIALIZED;
     221             : 
     222           0 :   delete gInstance;
     223           0 :   return NS_OK;
     224             : }
     225             : 
     226             : nsresult
     227           0 : NetworkActivityMonitor::Init_Internal(int32_t blipInterval)
     228             : {
     229           0 :   if (!sNetActivityMonitorLayerMethodsPtr) {
     230           0 :     sNetActivityMonitorLayerIdentity =
     231           0 :       PR_GetUniqueIdentity("network activity monitor layer");
     232           0 :     sNetActivityMonitorLayerMethods  = *PR_GetDefaultIOMethods();
     233           0 :     sNetActivityMonitorLayerMethods.connect    = nsNetMon_Connect;
     234           0 :     sNetActivityMonitorLayerMethods.read       = nsNetMon_Read;
     235           0 :     sNetActivityMonitorLayerMethods.write      = nsNetMon_Write;
     236           0 :     sNetActivityMonitorLayerMethods.writev     = nsNetMon_Writev;
     237           0 :     sNetActivityMonitorLayerMethods.recv       = nsNetMon_Recv;
     238           0 :     sNetActivityMonitorLayerMethods.send       = nsNetMon_Send;
     239           0 :     sNetActivityMonitorLayerMethods.recvfrom   = nsNetMon_RecvFrom;
     240           0 :     sNetActivityMonitorLayerMethods.sendto     = nsNetMon_SendTo;
     241           0 :     sNetActivityMonitorLayerMethods.acceptread = nsNetMon_AcceptRead;
     242           0 :     sNetActivityMonitorLayerMethodsPtr = &sNetActivityMonitorLayerMethods;
     243             :   }
     244             : 
     245           0 :   mBlipInterval = PR_MillisecondsToInterval(blipInterval);
     246             :   // Set the last notification times to time that has just expired, so any
     247             :   // activity even right now will trigger notification.
     248           0 :   mLastNotificationTime[kUpload] = PR_IntervalNow() - mBlipInterval;
     249           0 :   mLastNotificationTime[kDownload] = mLastNotificationTime[kUpload];
     250             : 
     251           0 :   return NS_OK;
     252             : }
     253             : 
     254             : nsresult
     255           3 : NetworkActivityMonitor::AttachIOLayer(PRFileDesc *fd)
     256             : {
     257           3 :   if (!gInstance)
     258           3 :     return NS_OK;
     259             : 
     260             :   PRFileDesc * layer;
     261             :   PRStatus     status;
     262             : 
     263           0 :   layer = PR_CreateIOLayerStub(sNetActivityMonitorLayerIdentity,
     264           0 :                                sNetActivityMonitorLayerMethodsPtr);
     265           0 :   if (!layer) {
     266           0 :     return NS_ERROR_FAILURE;
     267             :   }
     268             : 
     269           0 :   status = PR_PushIOLayer(fd, PR_NSPR_IO_LAYER, layer);
     270             : 
     271           0 :   if (status == PR_FAILURE) {
     272           0 :     PR_Free(layer); // PR_CreateIOLayerStub() uses PR_Malloc().
     273           0 :     return NS_ERROR_FAILURE;
     274             :   }
     275             : 
     276           0 :   return NS_OK;
     277             : }
     278             : 
     279             : nsresult
     280           0 : NetworkActivityMonitor::DataInOut(Direction direction)
     281             : {
     282           0 :   MOZ_ASSERT(OnSocketThread(), "not on socket thread");
     283             : 
     284           0 :   if (gInstance) {
     285           0 :     PRIntervalTime now = PR_IntervalNow();
     286           0 :     if ((now - gInstance->mLastNotificationTime[direction]) >
     287           0 :         gInstance->mBlipInterval) {
     288           0 :       gInstance->mLastNotificationTime[direction] = now;
     289           0 :       gInstance->PostNotification(direction);
     290             :     }
     291             :   }
     292             : 
     293           0 :   return NS_OK;
     294             : }
     295             : 
     296             : void
     297           0 : NetworkActivityMonitor::PostNotification(Direction direction)
     298             : {
     299           0 :   nsCOMPtr<nsIRunnable> ev = new NotifyNetworkActivity(direction);
     300           0 :   NS_DispatchToMainThread(ev);
     301           0 : }

Generated by: LCOV version 1.13