toolkit/components/statusfilter/nsBrowserStatusFilter.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial