toolkit/components/statusfilter/nsBrowserStatusFilter.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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/. */
     6 #include "nsBrowserStatusFilter.h"
     7 #include "nsIChannel.h"
     8 #include "nsITimer.h"
     9 #include "nsIServiceManager.h"
    10 #include "nsString.h"
    12 // XXX
    13 // XXX  DO NOT TOUCH THIS CODE UNLESS YOU KNOW WHAT YOU'RE DOING !!!
    14 // XXX
    16 //-----------------------------------------------------------------------------
    17 // nsBrowserStatusFilter <public>
    18 //-----------------------------------------------------------------------------
    20 nsBrowserStatusFilter::nsBrowserStatusFilter()
    21     : mCurProgress(0)
    22     , mMaxProgress(0)
    23     , mStatusIsDirty(true)
    24     , mCurrentPercentage(0)
    25     , mTotalRequests(0)
    26     , mFinishedRequests(0)
    27     , mUseRealProgressFlag(false)
    28     , mDelayedStatus(false)
    29     , mDelayedProgress(false)
    30 {
    31 }
    33 nsBrowserStatusFilter::~nsBrowserStatusFilter()
    34 {
    35     if (mTimer) {
    36         mTimer->Cancel();
    37     }
    38 }
    40 //-----------------------------------------------------------------------------
    41 // nsBrowserStatusFilter::nsISupports
    42 //-----------------------------------------------------------------------------
    44 NS_IMPL_ISUPPORTS(nsBrowserStatusFilter,
    45                   nsIWebProgress,
    46                   nsIWebProgressListener,
    47                   nsIWebProgressListener2,
    48                   nsISupportsWeakReference)
    50 //-----------------------------------------------------------------------------
    51 // nsBrowserStatusFilter::nsIWebProgress
    52 //-----------------------------------------------------------------------------
    54 NS_IMETHODIMP
    55 nsBrowserStatusFilter::AddProgressListener(nsIWebProgressListener *aListener,
    56                                            uint32_t aNotifyMask)
    57 {
    58     mListener = aListener;
    59     return NS_OK;
    60 }
    62 NS_IMETHODIMP
    63 nsBrowserStatusFilter::RemoveProgressListener(nsIWebProgressListener *aListener)
    64 {
    65     if (aListener == mListener)
    66         mListener = nullptr;
    67     return NS_OK;
    68 }
    70 NS_IMETHODIMP
    71 nsBrowserStatusFilter::GetDOMWindow(nsIDOMWindow **aResult)
    72 {
    73     NS_NOTREACHED("nsBrowserStatusFilter::GetDOMWindow");
    74     return NS_ERROR_NOT_IMPLEMENTED;
    75 }
    77 NS_IMETHODIMP
    78 nsBrowserStatusFilter::GetDOMWindowID(uint64_t *aResult)
    79 {
    80     *aResult = 0;
    81     NS_NOTREACHED("nsBrowserStatusFilter::GetDOMWindowID");
    82     return NS_ERROR_NOT_IMPLEMENTED;
    83 }
    85 NS_IMETHODIMP
    86 nsBrowserStatusFilter::GetIsTopLevel(bool *aIsTopLevel)
    87 {
    88     *aIsTopLevel = false;
    89     NS_NOTREACHED("nsBrowserStatusFilter::GetIsTopLevel");
    90     return NS_ERROR_NOT_IMPLEMENTED;
    91 }
    93 NS_IMETHODIMP
    94 nsBrowserStatusFilter::GetIsLoadingDocument(bool *aIsLoadingDocument)
    95 {
    96     NS_NOTREACHED("nsBrowserStatusFilter::GetIsLoadingDocument");
    97     return NS_ERROR_NOT_IMPLEMENTED;
    98 }
   100 NS_IMETHODIMP
   101 nsBrowserStatusFilter::GetLoadType(uint32_t *aLoadType)
   102 {
   103     *aLoadType = 0;
   104     NS_NOTREACHED("nsBrowserStatusFilter::GetLoadType");
   105     return NS_ERROR_NOT_IMPLEMENTED;
   106 }
   108 //-----------------------------------------------------------------------------
   109 // nsBrowserStatusFilter::nsIWebProgressListener
   110 //-----------------------------------------------------------------------------
   112 NS_IMETHODIMP
   113 nsBrowserStatusFilter::OnStateChange(nsIWebProgress *aWebProgress,
   114                                      nsIRequest *aRequest,
   115                                      uint32_t aStateFlags,
   116                                      nsresult aStatus)
   117 {
   118     if (!mListener)
   119         return NS_OK;
   121     if (aStateFlags & STATE_START) {
   122         if (aStateFlags & STATE_IS_NETWORK) {
   123             ResetMembers();
   124         }
   125         if (aStateFlags & STATE_IS_REQUEST) {
   126             ++mTotalRequests;
   128             // if the total requests exceeds 1, then we'll base our progress
   129             // notifications on the percentage of completed requests.
   130             // otherwise, progress for the single request will be reported.
   131             mUseRealProgressFlag = (mTotalRequests == 1);
   132         }
   133     }
   134     else if (aStateFlags & STATE_STOP) {
   135         if (aStateFlags & STATE_IS_REQUEST) {
   136             ++mFinishedRequests;
   137             // Note: Do not return from here. This is necessary so that the
   138             // STATE_STOP can still be relayed to the listener if needed
   139             // (bug 209330)
   140             if (!mUseRealProgressFlag && mTotalRequests)
   141                 OnProgressChange(nullptr, nullptr, 0, 0,
   142                                  mFinishedRequests, mTotalRequests);
   143         }
   144     }
   145     else if (aStateFlags & STATE_TRANSFERRING) {
   146         if (aStateFlags & STATE_IS_REQUEST) {
   147             if (!mUseRealProgressFlag && mTotalRequests)
   148                 return OnProgressChange(nullptr, nullptr, 0, 0,
   149                                         mFinishedRequests, mTotalRequests);
   150         }
   152         // no need to forward this state change
   153         return NS_OK;
   154     } else {
   155         // no need to forward this state change
   156         return NS_OK;
   157     }
   159     // If we're here, we have either STATE_START or STATE_STOP.  The
   160     // listener only cares about these in certain conditions.
   161     bool isLoadingDocument = false;
   162     if ((aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK ||
   163          (aStateFlags & nsIWebProgressListener::STATE_IS_REQUEST &&
   164           mFinishedRequests == mTotalRequests &&
   165           (aWebProgress->GetIsLoadingDocument(&isLoadingDocument),
   166            !isLoadingDocument)))) {
   167         if (mTimer && (aStateFlags & nsIWebProgressListener::STATE_STOP)) {
   168             mTimer->Cancel();
   169             ProcessTimeout();
   170         }
   172         return mListener->OnStateChange(aWebProgress, aRequest, aStateFlags,
   173                                         aStatus);
   174     }
   176     return NS_OK;
   177 }
   179 NS_IMETHODIMP
   180 nsBrowserStatusFilter::OnProgressChange(nsIWebProgress *aWebProgress,
   181                                         nsIRequest *aRequest,
   182                                         int32_t aCurSelfProgress,
   183                                         int32_t aMaxSelfProgress,
   184                                         int32_t aCurTotalProgress,
   185                                         int32_t aMaxTotalProgress)
   186 {
   187     if (!mListener)
   188         return NS_OK;
   190     if (!mUseRealProgressFlag && aRequest)
   191         return NS_OK;
   193     //
   194     // limit frequency of calls to OnProgressChange
   195     //
   197     mCurProgress = (int64_t)aCurTotalProgress;
   198     mMaxProgress = (int64_t)aMaxTotalProgress;
   200     if (mDelayedProgress)
   201         return NS_OK;
   203     if (!mDelayedStatus) {
   204         MaybeSendProgress();
   205         StartDelayTimer();
   206     }
   208     mDelayedProgress = true;
   210     return NS_OK;
   211 }
   213 NS_IMETHODIMP
   214 nsBrowserStatusFilter::OnLocationChange(nsIWebProgress *aWebProgress,
   215                                         nsIRequest *aRequest,
   216                                         nsIURI *aLocation,
   217                                         uint32_t aFlags)
   218 {
   219     if (!mListener)
   220         return NS_OK;
   222     return mListener->OnLocationChange(aWebProgress, aRequest, aLocation,
   223                                        aFlags);
   224 }
   226 NS_IMETHODIMP
   227 nsBrowserStatusFilter::OnStatusChange(nsIWebProgress *aWebProgress,
   228                                       nsIRequest *aRequest,
   229                                       nsresult aStatus,
   230                                       const char16_t *aMessage)
   231 {
   232     if (!mListener)
   233         return NS_OK;
   235     //
   236     // limit frequency of calls to OnStatusChange
   237     //
   238     if (mStatusIsDirty || !mCurrentStatusMsg.Equals(aMessage)) {
   239         mStatusIsDirty = true;
   240         mStatusMsg = aMessage;
   241     }
   243     if (mDelayedStatus)
   244         return NS_OK;
   246     if (!mDelayedProgress) {
   247       MaybeSendStatus();
   248       StartDelayTimer();
   249     }
   251     mDelayedStatus = true;
   253     return NS_OK;
   254 }
   256 NS_IMETHODIMP
   257 nsBrowserStatusFilter::OnSecurityChange(nsIWebProgress *aWebProgress,
   258                                         nsIRequest *aRequest,
   259                                         uint32_t aState)
   260 {
   261     if (!mListener)
   262         return NS_OK;
   264     return mListener->OnSecurityChange(aWebProgress, aRequest, aState);
   265 }
   267 //-----------------------------------------------------------------------------
   268 // nsBrowserStatusFilter::nsIWebProgressListener2
   269 //-----------------------------------------------------------------------------
   270 NS_IMETHODIMP
   271 nsBrowserStatusFilter::OnProgressChange64(nsIWebProgress *aWebProgress,
   272                                           nsIRequest *aRequest,
   273                                           int64_t aCurSelfProgress,
   274                                           int64_t aMaxSelfProgress,
   275                                           int64_t aCurTotalProgress,
   276                                           int64_t aMaxTotalProgress)
   277 {
   278     // XXX truncates 64-bit to 32-bit
   279     return OnProgressChange(aWebProgress, aRequest,
   280                             (int32_t)aCurSelfProgress,
   281                             (int32_t)aMaxSelfProgress,
   282                             (int32_t)aCurTotalProgress,
   283                             (int32_t)aMaxTotalProgress);
   284 }
   286 NS_IMETHODIMP
   287 nsBrowserStatusFilter::OnRefreshAttempted(nsIWebProgress *aWebProgress,
   288                                           nsIURI *aUri,
   289                                           int32_t aDelay,
   290                                           bool aSameUri,
   291                                           bool *allowRefresh)
   292 {
   293     nsCOMPtr<nsIWebProgressListener2> listener =
   294         do_QueryInterface(mListener);
   295     if (!listener) {
   296         *allowRefresh = true;
   297         return NS_OK;
   298     }
   300     return listener->OnRefreshAttempted(aWebProgress, aUri, aDelay, aSameUri,
   301                                         allowRefresh);
   302 }
   304 //-----------------------------------------------------------------------------
   305 // nsBrowserStatusFilter <private>
   306 //-----------------------------------------------------------------------------
   308 void
   309 nsBrowserStatusFilter::ResetMembers()
   310 {
   311     mTotalRequests = 0;
   312     mFinishedRequests = 0;
   313     mUseRealProgressFlag = false;
   314     mMaxProgress = 0;
   315     mCurProgress = 0;
   316     mCurrentPercentage = 0;
   317     mStatusIsDirty = true;
   318 }
   320 void
   321 nsBrowserStatusFilter::MaybeSendProgress() 
   322 {
   323     if (mCurProgress > mMaxProgress || mCurProgress <= 0) 
   324         return;
   326     // check our percentage
   327     int32_t percentage = (int32_t) double(mCurProgress) * 100 / mMaxProgress;
   329     // The progress meter only updates for increases greater than 3 percent
   330     if (percentage > (mCurrentPercentage + 3)) {
   331         mCurrentPercentage = percentage;
   332         // XXX truncates 64-bit to 32-bit
   333         mListener->OnProgressChange(nullptr, nullptr, 0, 0,
   334                                     (int32_t)mCurProgress,
   335                                     (int32_t)mMaxProgress);
   336     }
   337 }
   339 void
   340 nsBrowserStatusFilter::MaybeSendStatus()
   341 {
   342     if (mStatusIsDirty) {
   343         mListener->OnStatusChange(nullptr, nullptr, NS_OK, mStatusMsg.get());
   344         mCurrentStatusMsg = mStatusMsg;
   345         mStatusIsDirty = false;
   346     }
   347 }
   349 nsresult
   350 nsBrowserStatusFilter::StartDelayTimer()
   351 {
   352     NS_ASSERTION(!DelayInEffect(), "delay should not be in effect");
   354     mTimer = do_CreateInstance("@mozilla.org/timer;1");
   355     if (!mTimer)
   356         return NS_ERROR_FAILURE;
   358     return mTimer->InitWithFuncCallback(TimeoutHandler, this, 160, 
   359                                         nsITimer::TYPE_ONE_SHOT);
   360 }
   362 void
   363 nsBrowserStatusFilter::ProcessTimeout()
   364 {
   365     mTimer = nullptr;
   367     if (!mListener)
   368         return;
   370     if (mDelayedStatus) {
   371         mDelayedStatus = false;
   372         MaybeSendStatus();
   373     }
   375     if (mDelayedProgress) {
   376         mDelayedProgress = false;
   377         MaybeSendProgress();
   378     }
   379 }
   381 void
   382 nsBrowserStatusFilter::TimeoutHandler(nsITimer *aTimer, void *aClosure)
   383 {
   384     nsBrowserStatusFilter *self = reinterpret_cast<nsBrowserStatusFilter *>(aClosure);
   385     if (!self) {
   386         NS_ERROR("no self");
   387         return;
   388     }
   390     self->ProcessTimeout();
   391 }

mercurial