From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- toolkit/components/statusfilter/moz.build | 11 + .../statusfilter/nsBrowserStatusFilter.cpp | 392 +++++++++++++++++++++ .../statusfilter/nsBrowserStatusFilter.h | 80 +++++ 3 files changed, 483 insertions(+) create mode 100644 toolkit/components/statusfilter/moz.build create mode 100644 toolkit/components/statusfilter/nsBrowserStatusFilter.cpp create mode 100644 toolkit/components/statusfilter/nsBrowserStatusFilter.h (limited to 'toolkit/components/statusfilter') diff --git a/toolkit/components/statusfilter/moz.build b/toolkit/components/statusfilter/moz.build new file mode 100644 index 000000000..68f4810a2 --- /dev/null +++ b/toolkit/components/statusfilter/moz.build @@ -0,0 +1,11 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +SOURCES += [ + 'nsBrowserStatusFilter.cpp', +] + +FINAL_LIBRARY = 'xul' diff --git a/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp b/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp new file mode 100644 index 000000000..f607e01b4 --- /dev/null +++ b/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp @@ -0,0 +1,392 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsBrowserStatusFilter.h" +#include "nsIChannel.h" +#include "nsITimer.h" +#include "nsIServiceManager.h" +#include "nsString.h" + +// XXX +// XXX DO NOT TOUCH THIS CODE UNLESS YOU KNOW WHAT YOU'RE DOING !!! +// XXX + +//----------------------------------------------------------------------------- +// nsBrowserStatusFilter +//----------------------------------------------------------------------------- + +nsBrowserStatusFilter::nsBrowserStatusFilter() + : mCurProgress(0) + , mMaxProgress(0) + , mStatusIsDirty(true) + , mCurrentPercentage(0) + , mTotalRequests(0) + , mFinishedRequests(0) + , mUseRealProgressFlag(false) + , mDelayedStatus(false) + , mDelayedProgress(false) +{ +} + +nsBrowserStatusFilter::~nsBrowserStatusFilter() +{ + if (mTimer) { + mTimer->Cancel(); + } +} + +//----------------------------------------------------------------------------- +// nsBrowserStatusFilter::nsISupports +//----------------------------------------------------------------------------- + +NS_IMPL_ISUPPORTS(nsBrowserStatusFilter, + nsIWebProgress, + nsIWebProgressListener, + nsIWebProgressListener2, + nsISupportsWeakReference) + +//----------------------------------------------------------------------------- +// nsBrowserStatusFilter::nsIWebProgress +//----------------------------------------------------------------------------- + +NS_IMETHODIMP +nsBrowserStatusFilter::AddProgressListener(nsIWebProgressListener *aListener, + uint32_t aNotifyMask) +{ + mListener = aListener; + return NS_OK; +} + +NS_IMETHODIMP +nsBrowserStatusFilter::RemoveProgressListener(nsIWebProgressListener *aListener) +{ + if (aListener == mListener) + mListener = nullptr; + return NS_OK; +} + +NS_IMETHODIMP +nsBrowserStatusFilter::GetDOMWindow(mozIDOMWindowProxy **aResult) +{ + NS_NOTREACHED("nsBrowserStatusFilter::GetDOMWindow"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsBrowserStatusFilter::GetDOMWindowID(uint64_t *aResult) +{ + *aResult = 0; + NS_NOTREACHED("nsBrowserStatusFilter::GetDOMWindowID"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsBrowserStatusFilter::GetIsTopLevel(bool *aIsTopLevel) +{ + *aIsTopLevel = false; + NS_NOTREACHED("nsBrowserStatusFilter::GetIsTopLevel"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsBrowserStatusFilter::GetIsLoadingDocument(bool *aIsLoadingDocument) +{ + NS_NOTREACHED("nsBrowserStatusFilter::GetIsLoadingDocument"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsBrowserStatusFilter::GetLoadType(uint32_t *aLoadType) +{ + *aLoadType = 0; + NS_NOTREACHED("nsBrowserStatusFilter::GetLoadType"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +//----------------------------------------------------------------------------- +// nsBrowserStatusFilter::nsIWebProgressListener +//----------------------------------------------------------------------------- + +NS_IMETHODIMP +nsBrowserStatusFilter::OnStateChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + uint32_t aStateFlags, + nsresult aStatus) +{ + if (!mListener) + return NS_OK; + + if (aStateFlags & STATE_START) { + if (aStateFlags & STATE_IS_NETWORK) { + ResetMembers(); + } + if (aStateFlags & STATE_IS_REQUEST) { + ++mTotalRequests; + + // if the total requests exceeds 1, then we'll base our progress + // notifications on the percentage of completed requests. + // otherwise, progress for the single request will be reported. + mUseRealProgressFlag = (mTotalRequests == 1); + } + } + else if (aStateFlags & STATE_STOP) { + if (aStateFlags & STATE_IS_REQUEST) { + ++mFinishedRequests; + // Note: Do not return from here. This is necessary so that the + // STATE_STOP can still be relayed to the listener if needed + // (bug 209330) + if (!mUseRealProgressFlag && mTotalRequests) + OnProgressChange(nullptr, nullptr, 0, 0, + mFinishedRequests, mTotalRequests); + } + } + else if (aStateFlags & STATE_TRANSFERRING) { + if (aStateFlags & STATE_IS_REQUEST) { + if (!mUseRealProgressFlag && mTotalRequests) + return OnProgressChange(nullptr, nullptr, 0, 0, + mFinishedRequests, mTotalRequests); + } + + // no need to forward this state change + return NS_OK; + } else { + // no need to forward this state change + return NS_OK; + } + + // If we're here, we have either STATE_START or STATE_STOP. The + // listener only cares about these in certain conditions. + bool isLoadingDocument = false; + if ((aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK || + (aStateFlags & nsIWebProgressListener::STATE_IS_REQUEST && + mFinishedRequests == mTotalRequests && + (aWebProgress->GetIsLoadingDocument(&isLoadingDocument), + !isLoadingDocument)))) { + if (mTimer && (aStateFlags & nsIWebProgressListener::STATE_STOP)) { + mTimer->Cancel(); + ProcessTimeout(); + } + + return mListener->OnStateChange(aWebProgress, aRequest, aStateFlags, + aStatus); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsBrowserStatusFilter::OnProgressChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + int32_t aCurSelfProgress, + int32_t aMaxSelfProgress, + int32_t aCurTotalProgress, + int32_t aMaxTotalProgress) +{ + if (!mListener) + return NS_OK; + + if (!mUseRealProgressFlag && aRequest) + return NS_OK; + + // + // limit frequency of calls to OnProgressChange + // + + mCurProgress = (int64_t)aCurTotalProgress; + mMaxProgress = (int64_t)aMaxTotalProgress; + + if (mDelayedProgress) + return NS_OK; + + if (!mDelayedStatus) { + MaybeSendProgress(); + StartDelayTimer(); + } + + mDelayedProgress = true; + + return NS_OK; +} + +NS_IMETHODIMP +nsBrowserStatusFilter::OnLocationChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + nsIURI *aLocation, + uint32_t aFlags) +{ + if (!mListener) + return NS_OK; + + return mListener->OnLocationChange(aWebProgress, aRequest, aLocation, + aFlags); +} + +NS_IMETHODIMP +nsBrowserStatusFilter::OnStatusChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + nsresult aStatus, + const char16_t *aMessage) +{ + if (!mListener) + return NS_OK; + + // + // limit frequency of calls to OnStatusChange + // + if (mStatusIsDirty || !mCurrentStatusMsg.Equals(aMessage)) { + mStatusIsDirty = true; + mStatusMsg = aMessage; + } + + if (mDelayedStatus) + return NS_OK; + + if (!mDelayedProgress) { + MaybeSendStatus(); + StartDelayTimer(); + } + + mDelayedStatus = true; + + return NS_OK; +} + +NS_IMETHODIMP +nsBrowserStatusFilter::OnSecurityChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + uint32_t aState) +{ + if (!mListener) + return NS_OK; + + return mListener->OnSecurityChange(aWebProgress, aRequest, aState); +} + +//----------------------------------------------------------------------------- +// nsBrowserStatusFilter::nsIWebProgressListener2 +//----------------------------------------------------------------------------- +NS_IMETHODIMP +nsBrowserStatusFilter::OnProgressChange64(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + int64_t aCurSelfProgress, + int64_t aMaxSelfProgress, + int64_t aCurTotalProgress, + int64_t aMaxTotalProgress) +{ + // XXX truncates 64-bit to 32-bit + return OnProgressChange(aWebProgress, aRequest, + (int32_t)aCurSelfProgress, + (int32_t)aMaxSelfProgress, + (int32_t)aCurTotalProgress, + (int32_t)aMaxTotalProgress); +} + +NS_IMETHODIMP +nsBrowserStatusFilter::OnRefreshAttempted(nsIWebProgress *aWebProgress, + nsIURI *aUri, + int32_t aDelay, + bool aSameUri, + bool *allowRefresh) +{ + nsCOMPtr listener = + do_QueryInterface(mListener); + if (!listener) { + *allowRefresh = true; + return NS_OK; + } + + return listener->OnRefreshAttempted(aWebProgress, aUri, aDelay, aSameUri, + allowRefresh); +} + +//----------------------------------------------------------------------------- +// nsBrowserStatusFilter +//----------------------------------------------------------------------------- + +void +nsBrowserStatusFilter::ResetMembers() +{ + mTotalRequests = 0; + mFinishedRequests = 0; + mUseRealProgressFlag = false; + mMaxProgress = 0; + mCurProgress = 0; + mCurrentPercentage = 0; + mStatusIsDirty = true; +} + +void +nsBrowserStatusFilter::MaybeSendProgress() +{ + if (mCurProgress > mMaxProgress || mCurProgress <= 0) + return; + + // check our percentage + int32_t percentage = (int32_t) double(mCurProgress) * 100 / mMaxProgress; + + // The progress meter only updates for increases greater than 3 percent + if (percentage > (mCurrentPercentage + 3)) { + mCurrentPercentage = percentage; + // XXX truncates 64-bit to 32-bit + mListener->OnProgressChange(nullptr, nullptr, 0, 0, + (int32_t)mCurProgress, + (int32_t)mMaxProgress); + } +} + +void +nsBrowserStatusFilter::MaybeSendStatus() +{ + if (mStatusIsDirty) { + mListener->OnStatusChange(nullptr, nullptr, NS_OK, mStatusMsg.get()); + mCurrentStatusMsg = mStatusMsg; + mStatusIsDirty = false; + } +} + +nsresult +nsBrowserStatusFilter::StartDelayTimer() +{ + NS_ASSERTION(!DelayInEffect(), "delay should not be in effect"); + + mTimer = do_CreateInstance("@mozilla.org/timer;1"); + if (!mTimer) + return NS_ERROR_FAILURE; + + return mTimer->InitWithNamedFuncCallback( + TimeoutHandler, this, 160, nsITimer::TYPE_ONE_SHOT, + "nsBrowserStatusFilter::TimeoutHandler"); +} + +void +nsBrowserStatusFilter::ProcessTimeout() +{ + mTimer = nullptr; + + if (!mListener) + return; + + if (mDelayedStatus) { + mDelayedStatus = false; + MaybeSendStatus(); + } + + if (mDelayedProgress) { + mDelayedProgress = false; + MaybeSendProgress(); + } +} + +void +nsBrowserStatusFilter::TimeoutHandler(nsITimer *aTimer, void *aClosure) +{ + nsBrowserStatusFilter *self = reinterpret_cast(aClosure); + if (!self) { + NS_ERROR("no self"); + return; + } + + self->ProcessTimeout(); +} diff --git a/toolkit/components/statusfilter/nsBrowserStatusFilter.h b/toolkit/components/statusfilter/nsBrowserStatusFilter.h new file mode 100644 index 000000000..0eb6364fd --- /dev/null +++ b/toolkit/components/statusfilter/nsBrowserStatusFilter.h @@ -0,0 +1,80 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsBrowserStatusFilter_h__ +#define nsBrowserStatusFilter_h__ + +#include "nsIWebProgressListener.h" +#include "nsIWebProgressListener2.h" +#include "nsIWebProgress.h" +#include "nsWeakReference.h" +#include "nsITimer.h" +#include "nsCOMPtr.h" +#include "nsString.h" + +//----------------------------------------------------------------------------- +// nsBrowserStatusFilter - a web progress listener implementation designed to +// sit between nsDocLoader and nsBrowserStatusHandler to filter out and limit +// the frequency of certain events to improve page load performance. +//----------------------------------------------------------------------------- + +class nsBrowserStatusFilter : public nsIWebProgress + , public nsIWebProgressListener2 + , public nsSupportsWeakReference +{ +public: + nsBrowserStatusFilter(); + + NS_DECL_ISUPPORTS + NS_DECL_NSIWEBPROGRESS + NS_DECL_NSIWEBPROGRESSLISTENER + NS_DECL_NSIWEBPROGRESSLISTENER2 + +protected: + virtual ~nsBrowserStatusFilter(); + +private: + nsresult StartDelayTimer(); + void ProcessTimeout(); + void MaybeSendProgress(); + void MaybeSendStatus(); + void ResetMembers(); + bool DelayInEffect() { return mDelayedStatus || mDelayedProgress; } + + static void TimeoutHandler(nsITimer *aTimer, void *aClosure); + +private: + nsCOMPtr mListener; + nsCOMPtr mTimer; + + // delayed values + nsString mStatusMsg; + int64_t mCurProgress; + int64_t mMaxProgress; + + nsString mCurrentStatusMsg; + bool mStatusIsDirty; + int32_t mCurrentPercentage; + + // used to convert OnStart/OnStop notifications into progress notifications + int32_t mTotalRequests; + int32_t mFinishedRequests; + bool mUseRealProgressFlag; + + // indicates whether a timeout is pending + bool mDelayedStatus; + bool mDelayedProgress; +}; + +#define NS_BROWSERSTATUSFILTER_CONTRACTID \ + "@mozilla.org/appshell/component/browser-status-filter;1" +#define NS_BROWSERSTATUSFILTER_CID \ +{ /* 6356aa16-7916-4215-a825-cbc2692ca87a */ \ + 0x6356aa16, \ + 0x7916, \ + 0x4215, \ + {0xa8, 0x25, 0xcb, 0xc2, 0x69, 0x2c, 0xa8, 0x7a} \ +} + +#endif // !nsBrowserStatusFilter_h__ -- cgit v1.2.3