1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,391 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsBrowserStatusFilter.h" 1.10 +#include "nsIChannel.h" 1.11 +#include "nsITimer.h" 1.12 +#include "nsIServiceManager.h" 1.13 +#include "nsString.h" 1.14 + 1.15 +// XXX 1.16 +// XXX DO NOT TOUCH THIS CODE UNLESS YOU KNOW WHAT YOU'RE DOING !!! 1.17 +// XXX 1.18 + 1.19 +//----------------------------------------------------------------------------- 1.20 +// nsBrowserStatusFilter <public> 1.21 +//----------------------------------------------------------------------------- 1.22 + 1.23 +nsBrowserStatusFilter::nsBrowserStatusFilter() 1.24 + : mCurProgress(0) 1.25 + , mMaxProgress(0) 1.26 + , mStatusIsDirty(true) 1.27 + , mCurrentPercentage(0) 1.28 + , mTotalRequests(0) 1.29 + , mFinishedRequests(0) 1.30 + , mUseRealProgressFlag(false) 1.31 + , mDelayedStatus(false) 1.32 + , mDelayedProgress(false) 1.33 +{ 1.34 +} 1.35 + 1.36 +nsBrowserStatusFilter::~nsBrowserStatusFilter() 1.37 +{ 1.38 + if (mTimer) { 1.39 + mTimer->Cancel(); 1.40 + } 1.41 +} 1.42 + 1.43 +//----------------------------------------------------------------------------- 1.44 +// nsBrowserStatusFilter::nsISupports 1.45 +//----------------------------------------------------------------------------- 1.46 + 1.47 +NS_IMPL_ISUPPORTS(nsBrowserStatusFilter, 1.48 + nsIWebProgress, 1.49 + nsIWebProgressListener, 1.50 + nsIWebProgressListener2, 1.51 + nsISupportsWeakReference) 1.52 + 1.53 +//----------------------------------------------------------------------------- 1.54 +// nsBrowserStatusFilter::nsIWebProgress 1.55 +//----------------------------------------------------------------------------- 1.56 + 1.57 +NS_IMETHODIMP 1.58 +nsBrowserStatusFilter::AddProgressListener(nsIWebProgressListener *aListener, 1.59 + uint32_t aNotifyMask) 1.60 +{ 1.61 + mListener = aListener; 1.62 + return NS_OK; 1.63 +} 1.64 + 1.65 +NS_IMETHODIMP 1.66 +nsBrowserStatusFilter::RemoveProgressListener(nsIWebProgressListener *aListener) 1.67 +{ 1.68 + if (aListener == mListener) 1.69 + mListener = nullptr; 1.70 + return NS_OK; 1.71 +} 1.72 + 1.73 +NS_IMETHODIMP 1.74 +nsBrowserStatusFilter::GetDOMWindow(nsIDOMWindow **aResult) 1.75 +{ 1.76 + NS_NOTREACHED("nsBrowserStatusFilter::GetDOMWindow"); 1.77 + return NS_ERROR_NOT_IMPLEMENTED; 1.78 +} 1.79 + 1.80 +NS_IMETHODIMP 1.81 +nsBrowserStatusFilter::GetDOMWindowID(uint64_t *aResult) 1.82 +{ 1.83 + *aResult = 0; 1.84 + NS_NOTREACHED("nsBrowserStatusFilter::GetDOMWindowID"); 1.85 + return NS_ERROR_NOT_IMPLEMENTED; 1.86 +} 1.87 + 1.88 +NS_IMETHODIMP 1.89 +nsBrowserStatusFilter::GetIsTopLevel(bool *aIsTopLevel) 1.90 +{ 1.91 + *aIsTopLevel = false; 1.92 + NS_NOTREACHED("nsBrowserStatusFilter::GetIsTopLevel"); 1.93 + return NS_ERROR_NOT_IMPLEMENTED; 1.94 +} 1.95 + 1.96 +NS_IMETHODIMP 1.97 +nsBrowserStatusFilter::GetIsLoadingDocument(bool *aIsLoadingDocument) 1.98 +{ 1.99 + NS_NOTREACHED("nsBrowserStatusFilter::GetIsLoadingDocument"); 1.100 + return NS_ERROR_NOT_IMPLEMENTED; 1.101 +} 1.102 + 1.103 +NS_IMETHODIMP 1.104 +nsBrowserStatusFilter::GetLoadType(uint32_t *aLoadType) 1.105 +{ 1.106 + *aLoadType = 0; 1.107 + NS_NOTREACHED("nsBrowserStatusFilter::GetLoadType"); 1.108 + return NS_ERROR_NOT_IMPLEMENTED; 1.109 +} 1.110 + 1.111 +//----------------------------------------------------------------------------- 1.112 +// nsBrowserStatusFilter::nsIWebProgressListener 1.113 +//----------------------------------------------------------------------------- 1.114 + 1.115 +NS_IMETHODIMP 1.116 +nsBrowserStatusFilter::OnStateChange(nsIWebProgress *aWebProgress, 1.117 + nsIRequest *aRequest, 1.118 + uint32_t aStateFlags, 1.119 + nsresult aStatus) 1.120 +{ 1.121 + if (!mListener) 1.122 + return NS_OK; 1.123 + 1.124 + if (aStateFlags & STATE_START) { 1.125 + if (aStateFlags & STATE_IS_NETWORK) { 1.126 + ResetMembers(); 1.127 + } 1.128 + if (aStateFlags & STATE_IS_REQUEST) { 1.129 + ++mTotalRequests; 1.130 + 1.131 + // if the total requests exceeds 1, then we'll base our progress 1.132 + // notifications on the percentage of completed requests. 1.133 + // otherwise, progress for the single request will be reported. 1.134 + mUseRealProgressFlag = (mTotalRequests == 1); 1.135 + } 1.136 + } 1.137 + else if (aStateFlags & STATE_STOP) { 1.138 + if (aStateFlags & STATE_IS_REQUEST) { 1.139 + ++mFinishedRequests; 1.140 + // Note: Do not return from here. This is necessary so that the 1.141 + // STATE_STOP can still be relayed to the listener if needed 1.142 + // (bug 209330) 1.143 + if (!mUseRealProgressFlag && mTotalRequests) 1.144 + OnProgressChange(nullptr, nullptr, 0, 0, 1.145 + mFinishedRequests, mTotalRequests); 1.146 + } 1.147 + } 1.148 + else if (aStateFlags & STATE_TRANSFERRING) { 1.149 + if (aStateFlags & STATE_IS_REQUEST) { 1.150 + if (!mUseRealProgressFlag && mTotalRequests) 1.151 + return OnProgressChange(nullptr, nullptr, 0, 0, 1.152 + mFinishedRequests, mTotalRequests); 1.153 + } 1.154 + 1.155 + // no need to forward this state change 1.156 + return NS_OK; 1.157 + } else { 1.158 + // no need to forward this state change 1.159 + return NS_OK; 1.160 + } 1.161 + 1.162 + // If we're here, we have either STATE_START or STATE_STOP. The 1.163 + // listener only cares about these in certain conditions. 1.164 + bool isLoadingDocument = false; 1.165 + if ((aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK || 1.166 + (aStateFlags & nsIWebProgressListener::STATE_IS_REQUEST && 1.167 + mFinishedRequests == mTotalRequests && 1.168 + (aWebProgress->GetIsLoadingDocument(&isLoadingDocument), 1.169 + !isLoadingDocument)))) { 1.170 + if (mTimer && (aStateFlags & nsIWebProgressListener::STATE_STOP)) { 1.171 + mTimer->Cancel(); 1.172 + ProcessTimeout(); 1.173 + } 1.174 + 1.175 + return mListener->OnStateChange(aWebProgress, aRequest, aStateFlags, 1.176 + aStatus); 1.177 + } 1.178 + 1.179 + return NS_OK; 1.180 +} 1.181 + 1.182 +NS_IMETHODIMP 1.183 +nsBrowserStatusFilter::OnProgressChange(nsIWebProgress *aWebProgress, 1.184 + nsIRequest *aRequest, 1.185 + int32_t aCurSelfProgress, 1.186 + int32_t aMaxSelfProgress, 1.187 + int32_t aCurTotalProgress, 1.188 + int32_t aMaxTotalProgress) 1.189 +{ 1.190 + if (!mListener) 1.191 + return NS_OK; 1.192 + 1.193 + if (!mUseRealProgressFlag && aRequest) 1.194 + return NS_OK; 1.195 + 1.196 + // 1.197 + // limit frequency of calls to OnProgressChange 1.198 + // 1.199 + 1.200 + mCurProgress = (int64_t)aCurTotalProgress; 1.201 + mMaxProgress = (int64_t)aMaxTotalProgress; 1.202 + 1.203 + if (mDelayedProgress) 1.204 + return NS_OK; 1.205 + 1.206 + if (!mDelayedStatus) { 1.207 + MaybeSendProgress(); 1.208 + StartDelayTimer(); 1.209 + } 1.210 + 1.211 + mDelayedProgress = true; 1.212 + 1.213 + return NS_OK; 1.214 +} 1.215 + 1.216 +NS_IMETHODIMP 1.217 +nsBrowserStatusFilter::OnLocationChange(nsIWebProgress *aWebProgress, 1.218 + nsIRequest *aRequest, 1.219 + nsIURI *aLocation, 1.220 + uint32_t aFlags) 1.221 +{ 1.222 + if (!mListener) 1.223 + return NS_OK; 1.224 + 1.225 + return mListener->OnLocationChange(aWebProgress, aRequest, aLocation, 1.226 + aFlags); 1.227 +} 1.228 + 1.229 +NS_IMETHODIMP 1.230 +nsBrowserStatusFilter::OnStatusChange(nsIWebProgress *aWebProgress, 1.231 + nsIRequest *aRequest, 1.232 + nsresult aStatus, 1.233 + const char16_t *aMessage) 1.234 +{ 1.235 + if (!mListener) 1.236 + return NS_OK; 1.237 + 1.238 + // 1.239 + // limit frequency of calls to OnStatusChange 1.240 + // 1.241 + if (mStatusIsDirty || !mCurrentStatusMsg.Equals(aMessage)) { 1.242 + mStatusIsDirty = true; 1.243 + mStatusMsg = aMessage; 1.244 + } 1.245 + 1.246 + if (mDelayedStatus) 1.247 + return NS_OK; 1.248 + 1.249 + if (!mDelayedProgress) { 1.250 + MaybeSendStatus(); 1.251 + StartDelayTimer(); 1.252 + } 1.253 + 1.254 + mDelayedStatus = true; 1.255 + 1.256 + return NS_OK; 1.257 +} 1.258 + 1.259 +NS_IMETHODIMP 1.260 +nsBrowserStatusFilter::OnSecurityChange(nsIWebProgress *aWebProgress, 1.261 + nsIRequest *aRequest, 1.262 + uint32_t aState) 1.263 +{ 1.264 + if (!mListener) 1.265 + return NS_OK; 1.266 + 1.267 + return mListener->OnSecurityChange(aWebProgress, aRequest, aState); 1.268 +} 1.269 + 1.270 +//----------------------------------------------------------------------------- 1.271 +// nsBrowserStatusFilter::nsIWebProgressListener2 1.272 +//----------------------------------------------------------------------------- 1.273 +NS_IMETHODIMP 1.274 +nsBrowserStatusFilter::OnProgressChange64(nsIWebProgress *aWebProgress, 1.275 + nsIRequest *aRequest, 1.276 + int64_t aCurSelfProgress, 1.277 + int64_t aMaxSelfProgress, 1.278 + int64_t aCurTotalProgress, 1.279 + int64_t aMaxTotalProgress) 1.280 +{ 1.281 + // XXX truncates 64-bit to 32-bit 1.282 + return OnProgressChange(aWebProgress, aRequest, 1.283 + (int32_t)aCurSelfProgress, 1.284 + (int32_t)aMaxSelfProgress, 1.285 + (int32_t)aCurTotalProgress, 1.286 + (int32_t)aMaxTotalProgress); 1.287 +} 1.288 + 1.289 +NS_IMETHODIMP 1.290 +nsBrowserStatusFilter::OnRefreshAttempted(nsIWebProgress *aWebProgress, 1.291 + nsIURI *aUri, 1.292 + int32_t aDelay, 1.293 + bool aSameUri, 1.294 + bool *allowRefresh) 1.295 +{ 1.296 + nsCOMPtr<nsIWebProgressListener2> listener = 1.297 + do_QueryInterface(mListener); 1.298 + if (!listener) { 1.299 + *allowRefresh = true; 1.300 + return NS_OK; 1.301 + } 1.302 + 1.303 + return listener->OnRefreshAttempted(aWebProgress, aUri, aDelay, aSameUri, 1.304 + allowRefresh); 1.305 +} 1.306 + 1.307 +//----------------------------------------------------------------------------- 1.308 +// nsBrowserStatusFilter <private> 1.309 +//----------------------------------------------------------------------------- 1.310 + 1.311 +void 1.312 +nsBrowserStatusFilter::ResetMembers() 1.313 +{ 1.314 + mTotalRequests = 0; 1.315 + mFinishedRequests = 0; 1.316 + mUseRealProgressFlag = false; 1.317 + mMaxProgress = 0; 1.318 + mCurProgress = 0; 1.319 + mCurrentPercentage = 0; 1.320 + mStatusIsDirty = true; 1.321 +} 1.322 + 1.323 +void 1.324 +nsBrowserStatusFilter::MaybeSendProgress() 1.325 +{ 1.326 + if (mCurProgress > mMaxProgress || mCurProgress <= 0) 1.327 + return; 1.328 + 1.329 + // check our percentage 1.330 + int32_t percentage = (int32_t) double(mCurProgress) * 100 / mMaxProgress; 1.331 + 1.332 + // The progress meter only updates for increases greater than 3 percent 1.333 + if (percentage > (mCurrentPercentage + 3)) { 1.334 + mCurrentPercentage = percentage; 1.335 + // XXX truncates 64-bit to 32-bit 1.336 + mListener->OnProgressChange(nullptr, nullptr, 0, 0, 1.337 + (int32_t)mCurProgress, 1.338 + (int32_t)mMaxProgress); 1.339 + } 1.340 +} 1.341 + 1.342 +void 1.343 +nsBrowserStatusFilter::MaybeSendStatus() 1.344 +{ 1.345 + if (mStatusIsDirty) { 1.346 + mListener->OnStatusChange(nullptr, nullptr, NS_OK, mStatusMsg.get()); 1.347 + mCurrentStatusMsg = mStatusMsg; 1.348 + mStatusIsDirty = false; 1.349 + } 1.350 +} 1.351 + 1.352 +nsresult 1.353 +nsBrowserStatusFilter::StartDelayTimer() 1.354 +{ 1.355 + NS_ASSERTION(!DelayInEffect(), "delay should not be in effect"); 1.356 + 1.357 + mTimer = do_CreateInstance("@mozilla.org/timer;1"); 1.358 + if (!mTimer) 1.359 + return NS_ERROR_FAILURE; 1.360 + 1.361 + return mTimer->InitWithFuncCallback(TimeoutHandler, this, 160, 1.362 + nsITimer::TYPE_ONE_SHOT); 1.363 +} 1.364 + 1.365 +void 1.366 +nsBrowserStatusFilter::ProcessTimeout() 1.367 +{ 1.368 + mTimer = nullptr; 1.369 + 1.370 + if (!mListener) 1.371 + return; 1.372 + 1.373 + if (mDelayedStatus) { 1.374 + mDelayedStatus = false; 1.375 + MaybeSendStatus(); 1.376 + } 1.377 + 1.378 + if (mDelayedProgress) { 1.379 + mDelayedProgress = false; 1.380 + MaybeSendProgress(); 1.381 + } 1.382 +} 1.383 + 1.384 +void 1.385 +nsBrowserStatusFilter::TimeoutHandler(nsITimer *aTimer, void *aClosure) 1.386 +{ 1.387 + nsBrowserStatusFilter *self = reinterpret_cast<nsBrowserStatusFilter *>(aClosure); 1.388 + if (!self) { 1.389 + NS_ERROR("no self"); 1.390 + return; 1.391 + } 1.392 + 1.393 + self->ProcessTimeout(); 1.394 +}