mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-13 19:41:49 +00:00
Bug 1365306 - Remove net::ThrottlingService, don't suspend/resume download channels on page load. r=hurley
This commit is contained in:
parent
56b8e8c07e
commit
5f3173e90f
@ -7609,10 +7609,6 @@ nsresult
|
||||
nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
|
||||
nsIChannel* aChannel, nsresult aStatus)
|
||||
{
|
||||
// We can release any pressure we may have had on the throttling service and
|
||||
// let background channels continue.
|
||||
mThrottler.reset();
|
||||
|
||||
if (!aChannel) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
@ -10799,16 +10795,6 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||
net::PredictorPredict(aURI, nullptr,
|
||||
nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr);
|
||||
|
||||
// Increase pressure on the throttling service so background channels will be
|
||||
// appropriately de-prioritized. We need to explicitly check for http[s] here
|
||||
// so that we don't throttle while loading, say, about:blank.
|
||||
bool isHTTP, isHTTPS;
|
||||
aURI->SchemeIs("http", &isHTTP);
|
||||
aURI->SchemeIs("https", &isHTTPS);
|
||||
if (isHTTP || isHTTPS) {
|
||||
mThrottler.reset(new mozilla::net::Throttler());
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRequest> req;
|
||||
rv = DoURILoad(aURI, aOriginalURI, aLoadReplace, aReferrer,
|
||||
!(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER),
|
||||
|
@ -60,7 +60,6 @@
|
||||
#include "nsRect.h"
|
||||
#include "Units.h"
|
||||
#include "nsIDeprecationWarner.h"
|
||||
#include "nsIThrottlingService.h"
|
||||
|
||||
namespace mozilla {
|
||||
enum class TaskCategory;
|
||||
@ -1101,9 +1100,6 @@ public:
|
||||
InterfaceRequestorProxy() {}
|
||||
nsWeakPtr mWeakPtr;
|
||||
};
|
||||
|
||||
private:
|
||||
mozilla::UniquePtr<mozilla::net::Throttler> mThrottler;
|
||||
};
|
||||
|
||||
#endif /* nsDocShell_h__ */
|
||||
|
@ -1,440 +0,0 @@
|
||||
/* vim: set ts=2 sts=2 et sw=2: */
|
||||
/* 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/. */
|
||||
|
||||
|
||||
// Things to think about
|
||||
// * do we need to be multithreaded, or is mt-only ok?
|
||||
|
||||
#include "ThrottlingService.h"
|
||||
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIObserverService.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
#include "mozilla/net/NeckoChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net{
|
||||
|
||||
static const char kEnabledPref[] = "network.throttle.enable";
|
||||
static const bool kDefaultEnabled = true;
|
||||
|
||||
// During a page load presure, every channel that is marked as Throttleable
|
||||
// is being periodically suspended and resumed for the suspend-for and
|
||||
// resume-for intervals respectively. This gives more bandwidth to other
|
||||
// more priority responses.
|
||||
|
||||
static const char kSuspendPeriodPref[] = "network.throttle.suspend-for";
|
||||
static const uint32_t kDefaultSuspendPeriod = 3000;
|
||||
static const char kResumePeriodPref[] = "network.throttle.resume-for";
|
||||
static const uint32_t kDefaultResumePeriod = 200;
|
||||
|
||||
NS_IMPL_ISUPPORTS(ThrottlingService, nsIThrottlingService, nsIObserver, nsITimerCallback)
|
||||
|
||||
ThrottlingService::ThrottlingService()
|
||||
:mEnabled(kDefaultEnabled)
|
||||
,mInitCalled(false)
|
||||
,mSuspended(false)
|
||||
,mPressureCount(0)
|
||||
,mSuspendPeriod(kDefaultSuspendPeriod)
|
||||
,mResumePeriod(kDefaultResumePeriod)
|
||||
,mIteratingHash(false)
|
||||
{
|
||||
}
|
||||
|
||||
ThrottlingService::~ThrottlingService()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
ThrottlingService::Init()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mInitCalled);
|
||||
|
||||
mInitCalled = true;
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (!obs) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsresult rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mEnabled = Preferences::GetBool(kEnabledPref, kDefaultEnabled);
|
||||
rv = Preferences::AddStrongObserver(this, kEnabledPref);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
Preferences::AddUintVarCache(&mSuspendPeriod, kSuspendPeriodPref, kDefaultSuspendPeriod);
|
||||
Preferences::AddUintVarCache(&mResumePeriod, kResumePeriodPref, kDefaultResumePeriod);
|
||||
|
||||
mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ThrottlingService::Shutdown()
|
||||
{
|
||||
if (!mInitCalled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mTimer) {
|
||||
mTimer->Cancel();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
||||
}
|
||||
|
||||
Preferences::RemoveObserver(this, kEnabledPref);
|
||||
|
||||
MaybeResumeAll();
|
||||
mChannelHash.Clear();
|
||||
}
|
||||
|
||||
nsresult
|
||||
ThrottlingService::Create(nsISupports *outer, const nsIID& iid, void **result)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (outer != nullptr) {
|
||||
return NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
|
||||
RefPtr<ThrottlingService> svc = new ThrottlingService();
|
||||
if (!IsNeckoChild()) {
|
||||
// We only need to do any work on the parent, so only bother initializing
|
||||
// there. Child-side, we'll just error out since we only deal with parent
|
||||
// channels.)
|
||||
nsresult rv = svc->Init();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return svc->QueryInterface(iid, result);
|
||||
}
|
||||
|
||||
// nsIThrottlingService
|
||||
|
||||
nsresult
|
||||
ThrottlingService::AddChannel(nsIHttpChannel *channel)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// We don't check mEnabled, because we always want to put channels in the hash
|
||||
// to avoid potential inconsistencies in the case where the user changes the
|
||||
// enabled pref at run-time.
|
||||
|
||||
if (IsNeckoChild()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
uint64_t key;
|
||||
nsresult rv = channel->GetChannelId(&key);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mChannelHash.Get(key, nullptr)) {
|
||||
// We already have this channel under our control, not adding it again.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!mIteratingHash) {
|
||||
// This should be the common case, and as such is easy to handle
|
||||
mChannelHash.Put(key, channel);
|
||||
|
||||
if (mSuspended) {
|
||||
channel->Suspend();
|
||||
}
|
||||
} else {
|
||||
// This gets tricky - we've somehow re-entrantly gotten here through the
|
||||
// hash iteration in one of MaybeSuspendAll or MaybeResumeAll. Keep track
|
||||
// of the fact that this add came in now, and once we're done iterating, we
|
||||
// can add this into the hash. This avoids unexpectedly modifying the hash
|
||||
// while it's being iterated over, which could lead to inconsistencies.
|
||||
mChannelsToAddRemove.AppendElement(channel);
|
||||
mChannelIsAdd.AppendElement(true);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ThrottlingService::RemoveChannel(nsIHttpChannel *channel)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Just like above, don't worry about mEnabled to avoid inconsistencies when
|
||||
// the pref changes at run-time
|
||||
|
||||
if (IsNeckoChild()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
uint64_t key;
|
||||
nsresult rv = channel->GetChannelId(&key);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mChannelHash.Get(key, nullptr)) {
|
||||
// TODO - warn?
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
if (!mIteratingHash) {
|
||||
// This should be the common case, and easy to handle.
|
||||
mChannelHash.Remove(key);
|
||||
|
||||
if (mSuspended) {
|
||||
// This channel is no longer under our control for suspend/resume, but
|
||||
// we've suspended it. Time to let it go.
|
||||
channel->Resume();
|
||||
}
|
||||
} else {
|
||||
// This gets tricky - we've somehow re-entrantly gotten here through the
|
||||
// hash iteration in one of MaybeSuspendAll or MaybeResumeAll. Keep track
|
||||
// of the fact that this add came in now, and once we're done iterating, we
|
||||
// can add this into the hash. This avoids unexpectedly modifying the hash
|
||||
// while it's being iterated over, which could lead to inconsistencies.
|
||||
mChannelsToAddRemove.AppendElement(channel);
|
||||
mChannelIsAdd.AppendElement(false);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ThrottlingService::IncreasePressure()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Just like add/removing channels, we don't check mEnabled here in order to
|
||||
// avoid inconsistencies that could occur if the pref is flipped at runtime
|
||||
|
||||
if (IsNeckoChild()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
if (mPressureCount++ == 0) {
|
||||
MOZ_ASSERT(!mSuspended, "Suspended with 0 pressure?");
|
||||
MaybeSuspendAll();
|
||||
if (mSuspended) {
|
||||
// MaybeSuspendAll() may not actually suspend things, and we only want to
|
||||
// bother setting a timer to resume if we actually suspended.
|
||||
mTimer->InitWithCallback(this, mSuspendPeriod, nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ThrottlingService::DecreasePressure()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Just like add/removing channels, we don't check mEnabled here in order to
|
||||
// avoid inconsistencies that could occur if the pref is flipped at runtime
|
||||
|
||||
if (IsNeckoChild()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mPressureCount > 0, "Unbalanced throttle pressure");
|
||||
|
||||
if (--mPressureCount == 0) {
|
||||
MaybeResumeAll();
|
||||
mTimer->Cancel();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIObserver
|
||||
|
||||
nsresult
|
||||
ThrottlingService::Observe(nsISupports *subject, const char *topic,
|
||||
const char16_t *data_unicode)
|
||||
{
|
||||
MOZ_ASSERT(!IsNeckoChild());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, topic)) {
|
||||
Shutdown();
|
||||
} else if (!strcmp("nsPref:changed", topic)) {
|
||||
mEnabled = Preferences::GetBool(kEnabledPref, mEnabled);
|
||||
if (mEnabled && mPressureCount) {
|
||||
// We weren't enabled, but we are now, AND we're under pressure. Go ahead
|
||||
// and suspend things.
|
||||
MaybeSuspendAll();
|
||||
if (mSuspended) {
|
||||
mTimer->InitWithCallback(this, mSuspendPeriod, nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
} else if (!mEnabled) {
|
||||
// We were enabled, but we aren't any longer. Make sure we aren't
|
||||
// suspending channels and that we don't have any timer that wants to
|
||||
// change things unexpectedly.
|
||||
mTimer->Cancel();
|
||||
MaybeResumeAll();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsITimerCallback
|
||||
|
||||
nsresult
|
||||
ThrottlingService::Notify(nsITimer *timer)
|
||||
{
|
||||
MOZ_ASSERT(!IsNeckoChild());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(timer == mTimer);
|
||||
|
||||
if (mSuspended) {
|
||||
MaybeResumeAll();
|
||||
// Always try to resume if we were suspended, but only time-limit the
|
||||
// resumption if we're under pressure and we're enabled. If either of those
|
||||
// conditions is false, it doesn't make any sense to set a timer to suspend
|
||||
// things when we don't want to be suspended anyway.
|
||||
if (mPressureCount && mEnabled) {
|
||||
mTimer->InitWithCallback(this, mResumePeriod, nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
} else if (mPressureCount) {
|
||||
MaybeSuspendAll();
|
||||
if (mSuspended) {
|
||||
// MaybeSuspendAll() may not actually suspend, and it only makes sense to
|
||||
// set a timer to resume if we actually suspended the channels.
|
||||
mTimer->InitWithCallback(this, mSuspendPeriod, nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Internal methods
|
||||
|
||||
void
|
||||
ThrottlingService::MaybeSuspendAll()
|
||||
{
|
||||
MOZ_ASSERT(!IsNeckoChild());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mEnabled) {
|
||||
// We don't actually suspend when disabled, even though it's possible we get
|
||||
// called in that state in order to avoid inconsistencies in the hash and
|
||||
// the count if the pref changes at runtime.
|
||||
return;
|
||||
}
|
||||
|
||||
if (mSuspended) {
|
||||
// Already suspended, nothing to do!
|
||||
return;
|
||||
}
|
||||
mSuspended = true;
|
||||
|
||||
IterateHash([](ChannelHash::Iterator &iter) -> void {
|
||||
const nsCOMPtr<nsIHttpChannel> channel = iter.UserData();
|
||||
channel->Suspend();
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
ThrottlingService::MaybeResumeAll()
|
||||
{
|
||||
MOZ_ASSERT(!IsNeckoChild());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mSuspended) {
|
||||
// Already resumed, nothing to do!
|
||||
return;
|
||||
}
|
||||
mSuspended = false;
|
||||
|
||||
IterateHash([](ChannelHash::Iterator &iter) -> void {
|
||||
const nsCOMPtr<nsIHttpChannel> channel = iter.UserData();
|
||||
channel->Resume();
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
ThrottlingService::IterateHash(void (* callback)(ChannelHash::Iterator &iter))
|
||||
{
|
||||
MOZ_ASSERT(!mIteratingHash);
|
||||
mIteratingHash = true;
|
||||
for (ChannelHash::Iterator iter = mChannelHash.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
callback(iter);
|
||||
}
|
||||
mIteratingHash = false;
|
||||
HandleExtraAddRemove();
|
||||
}
|
||||
|
||||
void
|
||||
ThrottlingService::HandleExtraAddRemove()
|
||||
{
|
||||
MOZ_ASSERT(!mIteratingHash);
|
||||
MOZ_ASSERT(mChannelsToAddRemove.Length() == mChannelIsAdd.Length());
|
||||
|
||||
nsCOMArray<nsIHttpChannel> channelsToAddRemove;
|
||||
channelsToAddRemove.SwapElements(mChannelsToAddRemove);
|
||||
|
||||
nsTArray<bool> channelIsAdd;
|
||||
channelIsAdd.SwapElements(mChannelIsAdd);
|
||||
|
||||
for (size_t i = 0; i < channelsToAddRemove.Length(); ++i) {
|
||||
if (channelIsAdd[i]) {
|
||||
AddChannel(channelsToAddRemove[i]);
|
||||
} else {
|
||||
RemoveChannel(channelsToAddRemove[i]);
|
||||
}
|
||||
}
|
||||
|
||||
channelsToAddRemove.Clear();
|
||||
channelIsAdd.Clear();
|
||||
}
|
||||
|
||||
// The publicly available way to throttle things
|
||||
|
||||
Throttler::Throttler()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (IsNeckoChild()) {
|
||||
if (gNeckoChild) {
|
||||
// The child object may have already gone away, so we need to guard
|
||||
// guard against deref'ing a nullptr here. If that's what happened, then
|
||||
// our pageload won't be continuing anyway, so what we do is pretty much
|
||||
// irrelevant.
|
||||
gNeckoChild->SendIncreaseThrottlePressure();
|
||||
}
|
||||
} else {
|
||||
mThrottlingService = do_GetService("@mozilla.org/network/throttling-service;1");
|
||||
mThrottlingService->IncreasePressure();
|
||||
}
|
||||
}
|
||||
|
||||
Throttler::~Throttler()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (IsNeckoChild()) {
|
||||
if (gNeckoChild) {
|
||||
// The child object may have already gone away, so we need to guard
|
||||
// guard against deref'ing a nullptr here. If that's what happened, then
|
||||
// NeckoParent::ActorDestroy will take care of releasing the pressure we
|
||||
// created.
|
||||
gNeckoChild->SendDecreaseThrottlePressure();
|
||||
}
|
||||
} else {
|
||||
MOZ_RELEASE_ASSERT(mThrottlingService);
|
||||
mThrottlingService->DecreasePressure();
|
||||
mThrottlingService = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
/* vim: set ts=2 sts=2 et sw=2: */
|
||||
/* 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 mozilla__net__ThrottlingService_h
|
||||
#define mozilla__net__ThrottlingService_h
|
||||
|
||||
#include "nsIThrottlingService.h"
|
||||
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsITimer.h"
|
||||
|
||||
class nsIHttpChannel;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class ThrottlingService : public nsIThrottlingService
|
||||
, public nsIObserver
|
||||
, public nsITimerCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSITHROTTLINGSERVICE
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
|
||||
ThrottlingService();
|
||||
|
||||
nsresult Init();
|
||||
void Shutdown();
|
||||
static nsresult Create(nsISupports *outer, const nsIID& iid, void **result);
|
||||
|
||||
private:
|
||||
virtual ~ThrottlingService();
|
||||
|
||||
void MaybeSuspendAll();
|
||||
void MaybeResumeAll();
|
||||
|
||||
void HandleExtraAddRemove();
|
||||
|
||||
bool mEnabled;
|
||||
bool mInitCalled;
|
||||
bool mSuspended;
|
||||
uint32_t mPressureCount;
|
||||
uint32_t mSuspendPeriod; // How long we should Suspend() channels for
|
||||
uint32_t mResumePeriod; // How long we should Resume() channels for
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
typedef nsInterfaceHashtable<nsUint64HashKey, nsIHttpChannel> ChannelHash;
|
||||
ChannelHash mChannelHash;
|
||||
|
||||
// Used to avoid inconsistencies in the hash and the suspend/resume count of
|
||||
// channels. See comments in AddChannel and RemoveChannel for details.
|
||||
void IterateHash(void (* callback)(ChannelHash::Iterator &iter));
|
||||
bool mIteratingHash;
|
||||
nsCOMArray<nsIHttpChannel> mChannelsToAddRemove;
|
||||
nsTArray<bool> mChannelIsAdd;
|
||||
};
|
||||
|
||||
} // ::mozilla::net
|
||||
} // ::mozilla
|
||||
|
||||
#endif // mozilla__net__ThrottlingService_h
|
@ -117,7 +117,6 @@ XPIDL_SOURCES += [
|
||||
'nsIThreadRetargetableRequest.idl',
|
||||
'nsIThreadRetargetableStreamListener.idl',
|
||||
'nsIThrottledInputChannel.idl',
|
||||
'nsIThrottlingService.idl',
|
||||
'nsITimedChannel.idl',
|
||||
'nsITLSServerSocket.idl',
|
||||
'nsITraceableChannel.idl',
|
||||
@ -250,7 +249,6 @@ UNIFIED_SOURCES += [
|
||||
'StreamingProtocolService.cpp',
|
||||
'TCPFastOpenLayer.cpp',
|
||||
'ThrottleQueue.cpp',
|
||||
'ThrottlingService.cpp',
|
||||
'Tickler.cpp',
|
||||
'TLSServerSocket.cpp',
|
||||
]
|
||||
|
@ -1,37 +0,0 @@
|
||||
/* vim: set ts=2 sts=2 et sw=2: */
|
||||
/* 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 "nsISupports.idl"
|
||||
|
||||
interface nsIHttpChannel;
|
||||
|
||||
[builtinclass, uuid(c755ef98-b749-4f30-a658-1e6110013a66)]
|
||||
interface nsIThrottlingService : nsISupports
|
||||
{
|
||||
void addChannel(in nsIHttpChannel channel);
|
||||
void removeChannel(in nsIHttpChannel channel);
|
||||
|
||||
/* Don't call these directly, use mozilla::net::Throttler instead! */
|
||||
void increasePressure();
|
||||
void decreasePressure();
|
||||
};
|
||||
|
||||
%{C++
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class Throttler
|
||||
{
|
||||
public:
|
||||
Throttler();
|
||||
~Throttler();
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIThrottlingService> mThrottlingService;
|
||||
};
|
||||
|
||||
} // ::mozilla::net
|
||||
} // ::mozilla
|
||||
%}
|
@ -494,17 +494,6 @@
|
||||
{0x93, 0x30, 0x18, 0x58, 0xb9, 0x9a, 0xce, 0x69} \
|
||||
}
|
||||
|
||||
// service implementing nsIThrottlingService
|
||||
#define NS_THROTTLINGSERVICE_CONTRACTID \
|
||||
"@mozilla.org/network/throttling-service;1"
|
||||
#define NS_THROTTLINGSERVICE_CID \
|
||||
{ /* c1c48f2b-cb9c-415e-b4f9-5e4c3476ca86 */ \
|
||||
0xc1c48f2b, \
|
||||
0xcb9c, \
|
||||
0x415e, \
|
||||
{0xb4, 0xf9, 0x5e, 0x4c, 0x34, 0x76, 0xca, 0x86} \
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* netwerk/cache/ classes
|
||||
*/
|
||||
|
@ -38,7 +38,6 @@
|
||||
#include "nsCategoryCache.h"
|
||||
#include "nsIContentSniffer.h"
|
||||
#include "Predictor.h"
|
||||
#include "ThrottlingService.h"
|
||||
#include "nsIThreadPool.h"
|
||||
#include "mozilla/net/NeckoChild.h"
|
||||
|
||||
@ -875,7 +874,6 @@ NS_DEFINE_NAMED_CID(NS_REQUESTCONTEXTSERVICE_CID);
|
||||
#ifdef BUILD_NETWORK_INFO_SERVICE
|
||||
NS_DEFINE_NAMED_CID(NETWORKINFOSERVICE_CID);
|
||||
#endif // BUILD_NETWORK_INFO_SERVICE
|
||||
NS_DEFINE_NAMED_CID(NS_THROTTLINGSERVICE_CID);
|
||||
|
||||
static const mozilla::Module::CIDEntry kNeckoCIDs[] = {
|
||||
{ &kNS_IOSERVICE_CID, false, nullptr, nsIOServiceConstructor },
|
||||
@ -1029,7 +1027,6 @@ static const mozilla::Module::CIDEntry kNeckoCIDs[] = {
|
||||
#ifdef BUILD_NETWORK_INFO_SERVICE
|
||||
{ &kNETWORKINFOSERVICE_CID, false, nullptr, nsNetworkInfoServiceConstructor },
|
||||
#endif
|
||||
{ &kNS_THROTTLINGSERVICE_CID, false, nullptr, mozilla::net::ThrottlingService::Create },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
@ -1188,7 +1185,6 @@ static const mozilla::Module::ContractIDEntry kNeckoContracts[] = {
|
||||
#ifdef BUILD_NETWORK_INFO_SERVICE
|
||||
{ NETWORKINFOSERVICE_CONTRACT_ID, &kNETWORKINFOSERVICE_CID },
|
||||
#endif
|
||||
{ NS_THROTTLINGSERVICE_CONTRACTID, &kNS_THROTTLINGSERVICE_CID },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
|
@ -48,7 +48,6 @@
|
||||
#include "nsINetworkPredictor.h"
|
||||
#include "nsINetworkPredictorVerifier.h"
|
||||
#include "nsISpeculativeConnect.h"
|
||||
#include "nsIThrottlingService.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
using mozilla::OriginAttributes;
|
||||
@ -946,23 +945,6 @@ NeckoParent::RecvRemoveRequestContext(const uint64_t& rcid)
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
NeckoParent::RecvIncreaseThrottlePressure()
|
||||
{
|
||||
mThrottlers.AppendElement(mozilla::UniquePtr<mozilla::net::Throttler>(new mozilla::net::Throttler));
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
NeckoParent::RecvDecreaseThrottlePressure()
|
||||
{
|
||||
MOZ_ASSERT(!mThrottlers.IsEmpty());
|
||||
// We do this because we don't actually care which throttler gets removed,
|
||||
// just that one of them does.
|
||||
mThrottlers.RemoveElementAt(0);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
NeckoParent::RecvNotifyCurrentTopLevelOuterContentWindowId(const uint64_t& aWindowId)
|
||||
{
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "mozilla/net/NeckoCommon.h"
|
||||
#include "nsIAuthPrompt2.h"
|
||||
#include "nsINetworkPredictor.h"
|
||||
#include "nsIThrottlingService.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
#ifndef mozilla_net_NeckoParent_h
|
||||
@ -236,14 +235,7 @@ protected:
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvRemoveRequestContext(const uint64_t& rcid) override;
|
||||
|
||||
/* Throttler messages */
|
||||
virtual mozilla::ipc::IPCResult RecvIncreaseThrottlePressure() override;
|
||||
virtual mozilla::ipc::IPCResult RecvDecreaseThrottlePressure() override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvNotifyCurrentTopLevelOuterContentWindowId(const uint64_t& aWindowId) override;
|
||||
private:
|
||||
nsTArray<mozilla::UniquePtr<mozilla::net::Throttler>> mThrottlers;
|
||||
virtual mozilla::ipc::IPCResult RecvNotifyCurrentTopLevelOuterContentWindowId(const uint64_t& aWindowId) override;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
|
@ -125,12 +125,6 @@ parent:
|
||||
|
||||
async PStunAddrsRequest();
|
||||
|
||||
/**
|
||||
* Throttling of channels
|
||||
*/
|
||||
async IncreaseThrottlePressure();
|
||||
async DecreaseThrottlePressure();
|
||||
|
||||
prio(high) async NotifyCurrentTopLevelOuterContentWindowId(uint64_t windowId);
|
||||
|
||||
child:
|
||||
|
@ -4248,11 +4248,5 @@ Http2Session::RealJoinConnection(const nsACString &hostname, int32_t port,
|
||||
return joinedReturn;
|
||||
}
|
||||
|
||||
void
|
||||
Http2Session::ThrottleResponse(bool aThrottle)
|
||||
{
|
||||
// Response throttling on an h2 connection will be implemented later.
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
@ -52,7 +52,6 @@ public:
|
||||
uint32_t SpdyVersion() override;
|
||||
bool TestJoinConnection(const nsACString &hostname, int32_t port) override;
|
||||
bool JoinConnection(const nsACString &hostname, int32_t port) override;
|
||||
void ThrottleResponse(bool aThrottle) override;
|
||||
|
||||
// When the connection is active this is called up to once every 1 second
|
||||
// return the interval (in seconds) that the connection next wants to
|
||||
|
@ -62,7 +62,6 @@
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "nsICacheInfoChannel.h"
|
||||
#include "nsIDOMWindowUtils.h"
|
||||
#include "nsIThrottlingService.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include "HttpBaseChannel.h"
|
||||
@ -3071,13 +3070,6 @@ HttpBaseChannel::ReleaseListeners()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Should only be called on the main thread.");
|
||||
|
||||
if (mClassOfService & nsIClassOfService::Throttleable) {
|
||||
nsIThrottlingService *throttler = gHttpHandler->GetThrottlingService();
|
||||
if (throttler) {
|
||||
throttler->RemoveChannel(this);
|
||||
}
|
||||
}
|
||||
|
||||
mListener = nullptr;
|
||||
mListenerContext = nullptr;
|
||||
mCallbacks = nullptr;
|
||||
|
@ -146,14 +146,6 @@ public:
|
||||
|
||||
// nsHttp.h version
|
||||
virtual uint32_t Version() = 0;
|
||||
|
||||
// Throttling control, can be called only on the socket thread. HTTP/1
|
||||
// implementation effects whether we AsyncWait on the socket input stream
|
||||
// after reading data. This doesn't have a counter-like logic, hence
|
||||
// calling it with aThrottle = false will re-enable read from the socket
|
||||
// immediately. Calling more than once with the same argument value has
|
||||
// no effect.
|
||||
virtual void ThrottleResponse(bool aThrottle) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsAHttpConnection, NS_AHTTPCONNECTION_IID)
|
||||
|
@ -107,7 +107,6 @@
|
||||
#include "HSTSPrimerListener.h"
|
||||
#include "CacheStorageService.h"
|
||||
#include "HttpChannelParent.h"
|
||||
#include "nsIThrottlingService.h"
|
||||
#include "nsIBufferedStreams.h"
|
||||
#include "nsIFileStreams.h"
|
||||
#include "nsIMIMEInputStream.h"
|
||||
@ -711,7 +710,7 @@ nsHttpChannel::ContinueConnect()
|
||||
while (suspendCount--)
|
||||
mTransactionPump->Suspend();
|
||||
|
||||
if (mSuspendCount && mClassOfService & nsIClassOfService::Throttleable) {
|
||||
if (mClassOfService & nsIClassOfService::Throttleable) {
|
||||
gHttpHandler->ThrottleTransaction(mTransaction, true);
|
||||
}
|
||||
|
||||
@ -6627,18 +6626,9 @@ nsHttpChannel::OnClassOfServiceUpdated()
|
||||
{
|
||||
bool throttleable = !!(mClassOfService & nsIClassOfService::Throttleable);
|
||||
|
||||
if (mSuspendCount && mTransaction) {
|
||||
if (mTransaction) {
|
||||
gHttpHandler->ThrottleTransaction(mTransaction, throttleable);
|
||||
}
|
||||
|
||||
nsIThrottlingService *throttler = gHttpHandler->GetThrottlingService();
|
||||
if (throttler) {
|
||||
if (throttleable) {
|
||||
throttler->AddChannel(this);
|
||||
} else {
|
||||
throttler->RemoveChannel(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -86,8 +86,6 @@ nsHttpConnection::nsHttpConnection()
|
||||
, mContentBytesWritten0RTT(0)
|
||||
, mEarlyDataNegotiated(false)
|
||||
, mDid0RTTSpdy(false)
|
||||
, mResponseThrottled(false)
|
||||
, mResumeRecvOnUnthrottle(false)
|
||||
, mFastOpen(false)
|
||||
, mFastOpenStatus(TFO_NOT_TRIED)
|
||||
, mForceSendDuringFastOpenPending(false)
|
||||
@ -1471,22 +1469,6 @@ nsHttpConnection::ResumeRecv()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// mResponseThrottled is an indication from above layers to stop reading
|
||||
// the socket.
|
||||
if (mResponseThrottled) {
|
||||
mResumeRecvOnUnthrottle = true;
|
||||
|
||||
if (mSocketIn) {
|
||||
LOG((" throttled, waiting for closure only"));
|
||||
return mSocketIn->AsyncWait(this,
|
||||
nsIAsyncInputStream::WAIT_CLOSURE_ONLY,
|
||||
0, nullptr);
|
||||
}
|
||||
LOG((" throttled, and no socket input stream"));
|
||||
NS_NOTREACHED("no socket input stream");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// the mLastReadTime timestamp is used for finding slowish readers
|
||||
// and can be pretty sensitive. For that reason we actually reset it
|
||||
// when we ask to read (resume recv()) so that when we get called back
|
||||
@ -2165,32 +2147,6 @@ nsHttpConnection::DisableTCPKeepalives()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsHttpConnection::ThrottleResponse(bool aThrottle)
|
||||
{
|
||||
LOG(("nsHttpConnection::ThrottleResponse this=%p, throttle=%d", this, aThrottle));
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
|
||||
if (aThrottle) {
|
||||
mResponseThrottled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
mResponseThrottled = false;
|
||||
|
||||
if (!mResumeRecvOnUnthrottle) {
|
||||
// We didn't get to the point when ResumeRecv was called
|
||||
// during the throttle period, nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
mResumeRecvOnUnthrottle = false;
|
||||
|
||||
nsresult rv = ResumeRecv();
|
||||
if (NS_FAILED(rv)) {
|
||||
CloseTransaction(mTransaction, rv);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpConnection::nsISupports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -231,8 +231,6 @@ public:
|
||||
bool TestJoinConnection(const nsACString &hostname, int32_t port);
|
||||
bool JoinConnection(const nsACString &hostname, int32_t port);
|
||||
|
||||
void ThrottleResponse(bool aThrottle);
|
||||
|
||||
void SetFastOpenStatus(uint8_t tfoStatus) {
|
||||
mFastOpenStatus = tfoStatus;
|
||||
}
|
||||
@ -396,13 +394,6 @@ private:
|
||||
nsCString mEarlyNegotiatedALPN;
|
||||
bool mDid0RTTSpdy;
|
||||
|
||||
// Reflects throttling request, effects if we resume read from the socket.
|
||||
// Accessed only on the socket thread.
|
||||
bool mResponseThrottled;
|
||||
// A read from the socket was requested while we where throttled, means
|
||||
// to ResumeRecv() when untrottled again. Only accessed on the socket thread.
|
||||
bool mResumeRecvOnUnthrottle;
|
||||
|
||||
bool mFastOpen;
|
||||
uint8_t mFastOpenStatus;
|
||||
|
||||
|
@ -1640,7 +1640,6 @@ class ConnectionHandle : public nsAHttpConnection
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSAHTTPCONNECTION(mConn)
|
||||
virtual void ThrottleResponse(bool aThrottle) override;
|
||||
|
||||
explicit ConnectionHandle(nsHttpConnection *conn) : mConn(conn) { }
|
||||
void Reset() { mConn = nullptr; }
|
||||
@ -1655,13 +1654,6 @@ nsHttpConnectionMgr::MakeConnectionHandle(nsHttpConnection *aWrapped)
|
||||
return new ConnectionHandle(aWrapped);
|
||||
}
|
||||
|
||||
void ConnectionHandle::ThrottleResponse(bool aThrottle)
|
||||
{
|
||||
if (mConn) {
|
||||
mConn->ThrottleResponse(aThrottle);
|
||||
}
|
||||
}
|
||||
|
||||
ConnectionHandle::~ConnectionHandle()
|
||||
{
|
||||
if (mConn) {
|
||||
|
@ -53,7 +53,6 @@
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsSocketTransportService2.h"
|
||||
#include "nsIOService.h"
|
||||
#include "nsIThrottlingService.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
@ -715,17 +714,6 @@ nsHttpHandler::GetIOService(nsIIOService** result)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIThrottlingService *
|
||||
nsHttpHandler::GetThrottlingService()
|
||||
{
|
||||
if (!mThrottlingService) {
|
||||
nsCOMPtr<nsIThrottlingService> service = do_GetService(NS_THROTTLINGSERVICE_CONTRACTID);
|
||||
mThrottlingService = new nsMainThreadPtrHolder<nsIThrottlingService>(service);
|
||||
}
|
||||
|
||||
return mThrottlingService;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
nsHttpHandler::Get32BitsOfPseudoRandom()
|
||||
{
|
||||
|
@ -27,7 +27,6 @@ class nsIIOService;
|
||||
class nsIRequestContextService;
|
||||
class nsISiteSecurityService;
|
||||
class nsIStreamConverterService;
|
||||
class nsIThrottlingService;
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
@ -296,7 +295,6 @@ public:
|
||||
MOZ_MUST_USE nsresult GetIOService(nsIIOService** service);
|
||||
nsICookieService * GetCookieService(); // not addrefed
|
||||
nsISiteSecurityService * GetSSService();
|
||||
nsIThrottlingService * GetThrottlingService();
|
||||
|
||||
// callable from socket thread only
|
||||
uint32_t Get32BitsOfPseudoRandom();
|
||||
@ -412,7 +410,6 @@ private:
|
||||
nsMainThreadPtrHandle<nsIStreamConverterService> mStreamConvSvc;
|
||||
nsMainThreadPtrHandle<nsICookieService> mCookieService;
|
||||
nsMainThreadPtrHandle<nsISiteSecurityService> mSSService;
|
||||
nsMainThreadPtrHandle<nsIThrottlingService> mThrottlingService;
|
||||
|
||||
// the authentication credentials cache
|
||||
nsHttpAuthCache mAuthCache;
|
||||
|
@ -159,12 +159,7 @@ void nsHttpTransaction::ThrottleResponse(bool aThrottle)
|
||||
{
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
|
||||
// Just in case we suspend, get a connection, release a connection, get another connection.
|
||||
mThrottleResponse = aThrottle;
|
||||
|
||||
if (mConnection) {
|
||||
mConnection->ThrottleResponse(aThrottle);
|
||||
}
|
||||
}
|
||||
|
||||
nsHttpTransaction::~nsHttpTransaction()
|
||||
@ -479,10 +474,6 @@ nsHttpTransaction::SetConnection(nsAHttpConnection *conn)
|
||||
MutexAutoLock lock(mLock);
|
||||
mConnection = conn;
|
||||
}
|
||||
|
||||
if (conn && mThrottleResponse) {
|
||||
gHttpHandler->ThrottleTransaction(this, true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -313,6 +313,7 @@ private:
|
||||
Atomic<bool, ReleaseAcquire> mResponseIsComplete;
|
||||
|
||||
// If true, this transaction was asked to stop receiving the response.
|
||||
// NOTE: this flag is currently unused. A useful remnant of an old throttling algorithm.
|
||||
bool mThrottleResponse;
|
||||
|
||||
// state flags, all logically boolean, but not packed together into a
|
||||
@ -377,8 +378,8 @@ public:
|
||||
// but later can be dispatched via spdy (not subject to rate pacing).
|
||||
void CancelPacing(nsresult reason);
|
||||
|
||||
// Forwards to the connection's ThrottleResponse. If there is no connection
|
||||
// at the time, we set a flag to do it on connection assignment.
|
||||
// Called only on the socket thread. Updates the flag whether the transaction
|
||||
// should make the underlying connection or session stop reading from the socket.
|
||||
void ThrottleResponse(bool aThrottle);
|
||||
|
||||
private:
|
||||
|
Loading…
x
Reference in New Issue
Block a user