LCOV - code coverage report
Current view: top level - toolkit/components/statusfilter - nsBrowserStatusFilter.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 115 165 69.7 %
Date: 2017-07-14 16:53:18 Functions: 17 27 63.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "nsBrowserStatusFilter.h"
       7             : #include "mozilla/SystemGroup.h"
       8             : #include "nsIChannel.h"
       9             : #include "nsITimer.h"
      10             : #include "nsIServiceManager.h"
      11             : #include "nsString.h"
      12             : 
      13             : using namespace mozilla;
      14             : 
      15             : //-----------------------------------------------------------------------------
      16             : // nsBrowserStatusFilter <public>
      17             : //-----------------------------------------------------------------------------
      18             : 
      19           2 : nsBrowserStatusFilter::nsBrowserStatusFilter()
      20             :     : mCurProgress(0)
      21             :     , mMaxProgress(0)
      22             :     , mStatusIsDirty(true)
      23             :     , mCurrentPercentage(0)
      24             :     , mTotalRequests(0)
      25             :     , mFinishedRequests(0)
      26             :     , mUseRealProgressFlag(false)
      27             :     , mDelayedStatus(false)
      28           2 :     , mDelayedProgress(false)
      29             : {
      30           2 : }
      31             : 
      32           0 : nsBrowserStatusFilter::~nsBrowserStatusFilter()
      33             : {
      34           0 :     if (mTimer) {
      35           0 :         mTimer->Cancel();
      36             :     }
      37           0 : }
      38             : 
      39             : //-----------------------------------------------------------------------------
      40             : // nsBrowserStatusFilter::nsISupports
      41             : //-----------------------------------------------------------------------------
      42             : 
      43         345 : NS_IMPL_ISUPPORTS(nsBrowserStatusFilter,
      44             :                   nsIWebProgress,
      45             :                   nsIWebProgressListener,
      46             :                   nsIWebProgressListener2,
      47             :                   nsISupportsWeakReference)
      48             : 
      49             : //-----------------------------------------------------------------------------
      50             : // nsBrowserStatusFilter::nsIWebProgress
      51             : //-----------------------------------------------------------------------------
      52             : 
      53             : NS_IMETHODIMP
      54           3 : nsBrowserStatusFilter::AddProgressListener(nsIWebProgressListener *aListener,
      55             :                                            uint32_t aNotifyMask)
      56             : {
      57           3 :     mListener = aListener;
      58           3 :     return NS_OK;
      59             : }
      60             : 
      61             : NS_IMETHODIMP
      62           1 : nsBrowserStatusFilter::RemoveProgressListener(nsIWebProgressListener *aListener)
      63             : {
      64           1 :     if (aListener == mListener)
      65           1 :         mListener = nullptr;
      66           1 :     return NS_OK;
      67             : }
      68             : 
      69             : NS_IMETHODIMP
      70           0 : nsBrowserStatusFilter::GetDOMWindow(mozIDOMWindowProxy **aResult)
      71             : {
      72           0 :     NS_NOTREACHED("nsBrowserStatusFilter::GetDOMWindow");
      73           0 :     return NS_ERROR_NOT_IMPLEMENTED;
      74             : }
      75             : 
      76             : NS_IMETHODIMP
      77           0 : nsBrowserStatusFilter::GetDOMWindowID(uint64_t *aResult)
      78             : {
      79           0 :     *aResult = 0;
      80           0 :     NS_NOTREACHED("nsBrowserStatusFilter::GetDOMWindowID");
      81           0 :     return NS_ERROR_NOT_IMPLEMENTED;
      82             : }
      83             : 
      84             : NS_IMETHODIMP
      85           0 : nsBrowserStatusFilter::GetInnerDOMWindowID(uint64_t *aResult)
      86             : {
      87           0 :     *aResult = 0;
      88           0 :     NS_NOTREACHED("nsBrowserStatusFilter::GetInnerDOMWindowID");
      89           0 :     return NS_ERROR_NOT_IMPLEMENTED;
      90             : }
      91             : 
      92             : NS_IMETHODIMP
      93           0 : nsBrowserStatusFilter::GetIsTopLevel(bool *aIsTopLevel)
      94             : {
      95           0 :     *aIsTopLevel = false;
      96           0 :     NS_NOTREACHED("nsBrowserStatusFilter::GetIsTopLevel");
      97           0 :     return NS_ERROR_NOT_IMPLEMENTED;
      98             : }
      99             : 
     100             : NS_IMETHODIMP
     101           0 : nsBrowserStatusFilter::GetIsLoadingDocument(bool *aIsLoadingDocument)
     102             : {
     103           0 :     NS_NOTREACHED("nsBrowserStatusFilter::GetIsLoadingDocument");
     104           0 :     return NS_ERROR_NOT_IMPLEMENTED;
     105             : }
     106             : 
     107             : NS_IMETHODIMP
     108           0 : nsBrowserStatusFilter::GetLoadType(uint32_t *aLoadType)
     109             : {
     110           0 :     *aLoadType = 0;
     111           0 :     NS_NOTREACHED("nsBrowserStatusFilter::GetLoadType");
     112           0 :     return NS_ERROR_NOT_IMPLEMENTED;
     113             : }
     114             : 
     115             : //-----------------------------------------------------------------------------
     116             : // nsBrowserStatusFilter::nsIWebProgressListener
     117             : //-----------------------------------------------------------------------------
     118             : 
     119             : NS_IMETHODIMP
     120          30 : nsBrowserStatusFilter::OnStateChange(nsIWebProgress *aWebProgress,
     121             :                                      nsIRequest *aRequest,
     122             :                                      uint32_t aStateFlags,
     123             :                                      nsresult aStatus)
     124             : {
     125          30 :     if (!mListener)
     126           0 :         return NS_OK;
     127             : 
     128          30 :     if (aStateFlags & STATE_START) {
     129          11 :         if (aStateFlags & STATE_IS_NETWORK) {
     130           5 :             ResetMembers();
     131             :         }
     132          11 :         if (aStateFlags & STATE_IS_REQUEST) {
     133          11 :             ++mTotalRequests;
     134             : 
     135             :             // if the total requests exceeds 1, then we'll base our progress
     136             :             // notifications on the percentage of completed requests.
     137             :             // otherwise, progress for the single request will be reported.
     138          11 :             mUseRealProgressFlag = (mTotalRequests == 1);
     139             :         }
     140             :     }
     141          19 :     else if (aStateFlags & STATE_STOP) {
     142          14 :         if (aStateFlags & STATE_IS_REQUEST) {
     143           8 :             ++mFinishedRequests;
     144             :             // Note: Do not return from here. This is necessary so that the
     145             :             // STATE_STOP can still be relayed to the listener if needed
     146             :             // (bug 209330)
     147           8 :             if (!mUseRealProgressFlag && mTotalRequests)
     148           7 :                 OnProgressChange(nullptr, nullptr, 0, 0,
     149          14 :                                  mFinishedRequests, mTotalRequests);
     150             :         }
     151             :     }
     152           5 :     else if (aStateFlags & STATE_TRANSFERRING) {
     153           5 :         if (aStateFlags & STATE_IS_REQUEST) {
     154           5 :             if (!mUseRealProgressFlag && mTotalRequests)
     155           5 :                 return OnProgressChange(nullptr, nullptr, 0, 0,
     156          10 :                                         mFinishedRequests, mTotalRequests);
     157             :         }
     158             : 
     159             :         // no need to forward this state change
     160           0 :         return NS_OK;
     161             :     } else {
     162             :         // no need to forward this state change
     163           0 :         return NS_OK;
     164             :     }
     165             : 
     166             :     // If we're here, we have either STATE_START or STATE_STOP.  The
     167             :     // listener only cares about these in certain conditions.
     168          25 :     bool isLoadingDocument = false;
     169          50 :     if ((aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK ||
     170          30 :          (aStateFlags & nsIWebProgressListener::STATE_IS_REQUEST &&
     171          16 :           mFinishedRequests == mTotalRequests &&
     172           4 :           NS_SUCCEEDED(aWebProgress->GetIsLoadingDocument(&isLoadingDocument)) &&
     173           2 :           !isLoadingDocument))) {
     174           9 :         if (mTimer && (aStateFlags & nsIWebProgressListener::STATE_STOP)) {
     175           2 :             mTimer->Cancel();
     176           2 :             ProcessTimeout();
     177             :         }
     178             : 
     179           9 :         return mListener->OnStateChange(aWebProgress, aRequest, aStateFlags,
     180           9 :                                         aStatus);
     181             :     }
     182             : 
     183          16 :     return NS_OK;
     184             : }
     185             : 
     186             : NS_IMETHODIMP
     187          19 : nsBrowserStatusFilter::OnProgressChange(nsIWebProgress *aWebProgress,
     188             :                                         nsIRequest *aRequest,
     189             :                                         int32_t aCurSelfProgress,
     190             :                                         int32_t aMaxSelfProgress,
     191             :                                         int32_t aCurTotalProgress,
     192             :                                         int32_t aMaxTotalProgress)
     193             : {
     194          19 :     if (!mListener)
     195           0 :         return NS_OK;
     196             : 
     197          19 :     if (!mUseRealProgressFlag && aRequest)
     198           5 :         return NS_OK;
     199             : 
     200             :     //
     201             :     // limit frequency of calls to OnProgressChange
     202             :     //
     203             : 
     204          14 :     mCurProgress = (int64_t)aCurTotalProgress;
     205          14 :     mMaxProgress = (int64_t)aMaxTotalProgress;
     206             : 
     207          14 :     if (mDelayedProgress)
     208          10 :         return NS_OK;
     209             : 
     210           4 :     if (!mDelayedStatus) {
     211           0 :         MaybeSendProgress();
     212           0 :         StartDelayTimer();
     213             :     }
     214             : 
     215           4 :     mDelayedProgress = true;
     216             : 
     217           4 :     return NS_OK;
     218             : }
     219             : 
     220             : NS_IMETHODIMP
     221           2 : nsBrowserStatusFilter::OnLocationChange(nsIWebProgress *aWebProgress,
     222             :                                         nsIRequest *aRequest,
     223             :                                         nsIURI *aLocation,
     224             :                                         uint32_t aFlags)
     225             : {
     226           2 :     if (!mListener)
     227           0 :         return NS_OK;
     228             : 
     229           2 :     return mListener->OnLocationChange(aWebProgress, aRequest, aLocation,
     230           2 :                                        aFlags);
     231             : }
     232             : 
     233             : NS_IMETHODIMP
     234          12 : nsBrowserStatusFilter::OnStatusChange(nsIWebProgress *aWebProgress,
     235             :                                       nsIRequest *aRequest,
     236             :                                       nsresult aStatus,
     237             :                                       const char16_t *aMessage)
     238             : {
     239          12 :     if (!mListener)
     240           0 :         return NS_OK;
     241             : 
     242             :     //
     243             :     // limit frequency of calls to OnStatusChange
     244             :     //
     245          12 :     if (mStatusIsDirty || !mCurrentStatusMsg.Equals(aMessage)) {
     246          11 :         mStatusIsDirty = true;
     247          11 :         mStatusMsg = aMessage;
     248             :     }
     249             : 
     250          12 :     if (mDelayedStatus)
     251           8 :         return NS_OK;
     252             : 
     253           4 :     if (!mDelayedProgress) {
     254           4 :       MaybeSendStatus();
     255           4 :       StartDelayTimer();
     256             :     }
     257             : 
     258           4 :     mDelayedStatus = true;
     259             : 
     260           4 :     return NS_OK;
     261             : }
     262             : 
     263             : NS_IMETHODIMP
     264           2 : nsBrowserStatusFilter::OnSecurityChange(nsIWebProgress *aWebProgress,
     265             :                                         nsIRequest *aRequest,
     266             :                                         uint32_t aState)
     267             : {
     268           2 :     if (!mListener)
     269           0 :         return NS_OK;
     270             : 
     271           2 :     return mListener->OnSecurityChange(aWebProgress, aRequest, aState);
     272             : }
     273             : 
     274             : //-----------------------------------------------------------------------------
     275             : // nsBrowserStatusFilter::nsIWebProgressListener2
     276             : //-----------------------------------------------------------------------------
     277             : NS_IMETHODIMP
     278           0 : nsBrowserStatusFilter::OnProgressChange64(nsIWebProgress *aWebProgress,
     279             :                                           nsIRequest *aRequest,
     280             :                                           int64_t aCurSelfProgress,
     281             :                                           int64_t aMaxSelfProgress,
     282             :                                           int64_t aCurTotalProgress,
     283             :                                           int64_t aMaxTotalProgress)
     284             : {
     285             :     // XXX truncates 64-bit to 32-bit
     286           0 :     return OnProgressChange(aWebProgress, aRequest,
     287             :                             (int32_t)aCurSelfProgress,
     288             :                             (int32_t)aMaxSelfProgress,
     289             :                             (int32_t)aCurTotalProgress,
     290           0 :                             (int32_t)aMaxTotalProgress);
     291             : }
     292             : 
     293             : NS_IMETHODIMP
     294           0 : nsBrowserStatusFilter::OnRefreshAttempted(nsIWebProgress *aWebProgress,
     295             :                                           nsIURI *aUri,
     296             :                                           int32_t aDelay,
     297             :                                           bool aSameUri,
     298             :                                           bool *allowRefresh)
     299             : {
     300             :     nsCOMPtr<nsIWebProgressListener2> listener =
     301           0 :         do_QueryInterface(mListener);
     302           0 :     if (!listener) {
     303           0 :         *allowRefresh = true;
     304           0 :         return NS_OK;
     305             :     }
     306             : 
     307           0 :     return listener->OnRefreshAttempted(aWebProgress, aUri, aDelay, aSameUri,
     308           0 :                                         allowRefresh);
     309             : }
     310             : 
     311             : //-----------------------------------------------------------------------------
     312             : // nsBrowserStatusFilter <private>
     313             : //-----------------------------------------------------------------------------
     314             : 
     315             : void
     316           5 : nsBrowserStatusFilter::ResetMembers()
     317             : {
     318           5 :     mTotalRequests = 0;
     319           5 :     mFinishedRequests = 0;
     320           5 :     mUseRealProgressFlag = false;
     321           5 :     mMaxProgress = 0;
     322           5 :     mCurProgress = 0;
     323           5 :     mCurrentPercentage = 0;
     324           5 :     mStatusIsDirty = true;
     325           5 : }
     326             : 
     327             : void
     328           4 : nsBrowserStatusFilter::MaybeSendProgress()
     329             : {
     330           4 :     if (mCurProgress > mMaxProgress || mCurProgress <= 0)
     331           0 :         return;
     332             : 
     333             :     // check our percentage
     334           4 :     int32_t percentage = (int32_t) double(mCurProgress) * 100 / mMaxProgress;
     335             : 
     336             :     // The progress meter only updates for increases greater than 3 percent
     337           4 :     if (percentage > (mCurrentPercentage + 3)) {
     338           4 :         mCurrentPercentage = percentage;
     339             :         // XXX truncates 64-bit to 32-bit
     340          12 :         mListener->OnProgressChange(nullptr, nullptr, 0, 0,
     341           4 :                                     (int32_t)mCurProgress,
     342           8 :                                     (int32_t)mMaxProgress);
     343             :     }
     344             : }
     345             : 
     346             : void
     347           8 : nsBrowserStatusFilter::MaybeSendStatus()
     348             : {
     349           8 :     if (mStatusIsDirty) {
     350           6 :         mListener->OnStatusChange(nullptr, nullptr, NS_OK, mStatusMsg.get());
     351           6 :         mCurrentStatusMsg = mStatusMsg;
     352           6 :         mStatusIsDirty = false;
     353             :     }
     354           8 : }
     355             : 
     356             : nsresult
     357           4 : nsBrowserStatusFilter::StartDelayTimer()
     358             : {
     359           4 :     NS_ASSERTION(!DelayInEffect(), "delay should not be in effect");
     360             : 
     361           4 :     mTimer = do_CreateInstance("@mozilla.org/timer;1");
     362           4 :     if (!mTimer)
     363           0 :         return NS_ERROR_FAILURE;
     364             : 
     365             :     // Use the system group. The browser status filter is always used by chrome
     366             :     // code.
     367           4 :     mTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::Other));
     368           4 :     return mTimer->InitWithNamedFuncCallback(
     369             :         TimeoutHandler, this, 160, nsITimer::TYPE_ONE_SHOT,
     370           4 :         "nsBrowserStatusFilter::TimeoutHandler");
     371             : }
     372             : 
     373             : void
     374           4 : nsBrowserStatusFilter::ProcessTimeout()
     375             : {
     376           4 :     mTimer = nullptr;
     377             : 
     378           4 :     if (!mListener)
     379           0 :         return;
     380             : 
     381           4 :     if (mDelayedStatus) {
     382           4 :         mDelayedStatus = false;
     383           4 :         MaybeSendStatus();
     384             :     }
     385             : 
     386           4 :     if (mDelayedProgress) {
     387           4 :         mDelayedProgress = false;
     388           4 :         MaybeSendProgress();
     389             :     }
     390             : }
     391             : 
     392             : void
     393           2 : nsBrowserStatusFilter::TimeoutHandler(nsITimer *aTimer, void *aClosure)
     394             : {
     395           2 :     nsBrowserStatusFilter *self = reinterpret_cast<nsBrowserStatusFilter *>(aClosure);
     396           2 :     if (!self) {
     397           0 :         NS_ERROR("no self");
     398           0 :         return;
     399             :     }
     400             : 
     401           2 :     self->ProcessTimeout();
     402             : }

Generated by: LCOV version 1.13