Bug 1127618 - make push caches work in e10s. r=mcmanus r=froydnj

This commit is contained in:
Nicholas Hurley 2015-04-08 14:42:00 +02:00
parent 1bce6dabe8
commit e415496cf8
39 changed files with 575 additions and 206 deletions

View File

@ -0,0 +1,193 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 ;*; */
/* vim: set sw=2 ts=8 et tw=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/. */
#include "nsAutoPtr.h"
#include "nsIObserverService.h"
#include "nsIUUIDGenerator.h"
#include "SchedulingContextService.h"
#include "mozilla/Atomics.h"
#include "mozilla/Services.h"
#include "mozilla/net/PSpdyPush.h"
namespace mozilla {
namespace net {
// nsISchedulingContext
class SchedulingContext final : public nsISchedulingContext
, public nsSupportsWeakReference
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSISCHEDULINGCONTEXT
explicit SchedulingContext(const nsID& id);
private:
virtual ~SchedulingContext() {}
nsID mID;
Atomic<uint32_t> mBlockingTransactionCount;
nsAutoPtr<SpdyPushCache> mSpdyCache;
};
NS_IMPL_ISUPPORTS(SchedulingContext, nsISchedulingContext, nsISupportsWeakReference)
SchedulingContext::SchedulingContext(const nsID& aID)
: mBlockingTransactionCount(0)
{
mID = aID;
}
NS_IMETHODIMP
SchedulingContext::GetBlockingTransactionCount(uint32_t *aBlockingTransactionCount)
{
NS_ENSURE_ARG_POINTER(aBlockingTransactionCount);
*aBlockingTransactionCount = mBlockingTransactionCount;
return NS_OK;
}
NS_IMETHODIMP
SchedulingContext::AddBlockingTransaction()
{
mBlockingTransactionCount++;
return NS_OK;
}
NS_IMETHODIMP
SchedulingContext::RemoveBlockingTransaction(uint32_t *outval)
{
NS_ENSURE_ARG_POINTER(outval);
mBlockingTransactionCount--;
*outval = mBlockingTransactionCount;
return NS_OK;
}
/* [noscript] attribute SpdyPushCachePtr spdyPushCache; */
NS_IMETHODIMP
SchedulingContext::GetSpdyPushCache(mozilla::net::SpdyPushCache **aSpdyPushCache)
{
*aSpdyPushCache = mSpdyCache.get();
return NS_OK;
}
NS_IMETHODIMP
SchedulingContext::SetSpdyPushCache(mozilla::net::SpdyPushCache *aSpdyPushCache)
{
mSpdyCache = aSpdyPushCache;
return NS_OK;
}
/* [noscript] readonly attribute nsID ID; */
NS_IMETHODIMP
SchedulingContext::GetID(nsID *outval)
{
NS_ENSURE_ARG_POINTER(outval);
*outval = mID;
return NS_OK;
}
//nsISchedulingContextService
SchedulingContextService *SchedulingContextService::sSelf = nullptr;
NS_IMPL_ISUPPORTS(SchedulingContextService, nsISchedulingContextService, nsIObserver)
SchedulingContextService::SchedulingContextService()
{
MOZ_ASSERT(!sSelf, "multiple scs instances!");
sSelf = this;
}
SchedulingContextService::~SchedulingContextService()
{
Shutdown();
sSelf = nullptr;
}
nsresult
SchedulingContextService::Init()
{
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (!obs) {
return NS_ERROR_NOT_AVAILABLE;
}
return obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
}
void
SchedulingContextService::Shutdown()
{
mTable.Clear();
}
/* static */ nsresult
SchedulingContextService::Create(nsISupports *aOuter, const nsIID& aIID, void **aResult)
{
if (aOuter != nullptr) {
return NS_ERROR_NO_AGGREGATION;
}
nsRefPtr<SchedulingContextService> svc = new SchedulingContextService();
nsresult rv = svc->Init();
NS_ENSURE_SUCCESS(rv, rv);
return svc->QueryInterface(aIID, aResult);
}
NS_IMETHODIMP
SchedulingContextService::GetSchedulingContext(const nsID& scID, nsISchedulingContext **sc)
{
NS_ENSURE_ARG_POINTER(sc);
*sc = nullptr;
nsWeakPtr weakSC;
nsCOMPtr<nsISchedulingContext> strongSC;
if (mTable.Get(scID, getter_AddRefs(weakSC))) {
strongSC = do_QueryReferent(weakSC);
}
if (!strongSC) {
// Either this wasn't in the table to begin with, or the weak reference has
// expired. Let's make a new one.
strongSC = new SchedulingContext(scID);
weakSC = do_GetWeakReference(strongSC);
if (!weakSC) {
return NS_ERROR_OUT_OF_MEMORY;
}
mTable.Put(scID, weakSC);
}
strongSC.swap(*sc);
return NS_OK;
}
NS_IMETHODIMP
SchedulingContextService::NewSchedulingContextID(nsID *scID)
{
if (!mUUIDGen) {
nsresult rv;
mUUIDGen = do_GetService("@mozilla.org/uuid-generator;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
}
return mUUIDGen->GenerateUUIDInPlace(scID);
}
NS_IMETHODIMP
SchedulingContextService::Observe(nsISupports *subject, const char *topic,
const char16_t *data_unicode)
{
if (!strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, topic)) {
Shutdown();
}
return NS_OK;
}
} // ::mozilla::net
} // ::mozilla

View File

@ -0,0 +1,47 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 ;*; */
/* vim: set sw=2 ts=8 et tw=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 mozilla__net__SchedulingContextService_h
#define mozilla__net__SchedulingContextService_h
#include "nsCOMPtr.h"
#include "nsInterfaceHashtable.h"
#include "nsIObserver.h"
#include "nsISchedulingContext.h"
#include "nsWeakReference.h"
class nsIUUIDGenerator;
namespace mozilla {
namespace net {
class SchedulingContextService final : public nsISchedulingContextService
, public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISCHEDULINGCONTEXTSERVICE
NS_DECL_NSIOBSERVER
SchedulingContextService();
nsresult Init();
void Shutdown();
static nsresult Create(nsISupports *outer, const nsIID& iid, void **result);
private:
virtual ~SchedulingContextService();
static SchedulingContextService *sSelf;
nsInterfaceHashtable<nsIDHashKey, nsIWeakReference> mTable;
nsCOMPtr<nsIUUIDGenerator> mUUIDGen;
};
} // ::mozilla::net
} // ::mozilla
#endif // mozilla__net__SchedulingContextService_h

View File

@ -91,6 +91,7 @@ XPIDL_SOURCES += [
'nsIRequestObserverProxy.idl',
'nsIResponseHeadProvider.idl',
'nsIResumableChannel.idl',
'nsISchedulingContext.idl',
'nsISecretDecoderRing.idl',
'nsISecureBrowserUI.idl',
'nsISecurityEventSink.idl',
@ -237,6 +238,7 @@ UNIFIED_SOURCES += [
'Predictor.cpp',
'ProxyAutoConfig.cpp',
'RedirectChannelRegistrar.cpp',
'SchedulingContextService.cpp',
'StreamingProtocolService.cpp',
'Tickler.cpp',
'TLSServerSocket.cpp',

View File

@ -8,14 +8,14 @@
interface nsISimpleEnumerator;
interface nsIRequestObserver;
interface nsIInterfaceRequestor;
interface nsILoadGroupConnectionInfo;
interface nsISchedulingContext;
typedef unsigned long nsLoadFlags;
/**
* A load group maintains a collection of nsIRequest objects.
*/
[scriptable, uuid(afb57ac2-bce5-4ee3-bb34-385089a9ba5c)]
[scriptable, uuid(ff6a41f9-0bbf-44ca-9c71-f76c1da2b114)]
interface nsILoadGroup : nsIRequest
{
/**
@ -76,10 +76,10 @@ interface nsILoadGroup : nsIRequest
attribute nsIInterfaceRequestor notificationCallbacks;
/**
* Connection information for managing things like js/css
* connection blocking, and per-tab connection grouping
* Context for managing things like js/css connection blocking,
* and per-tab connection grouping.
*/
readonly attribute nsILoadGroupConnectionInfo connectionInfo;
readonly attribute nsID schedulingContextID;
/**
* The set of load flags that will be added to all new requests added to
@ -94,48 +94,3 @@ interface nsILoadGroup : nsIRequest
*/
attribute nsLoadFlags defaultLoadFlags;
};
%{C++
// Forward-declare mozilla::net::SpdyPushCache
namespace mozilla {
namespace net {
class SpdyPushCache;
}
}
%}
[ptr] native SpdyPushCachePtr(mozilla::net::SpdyPushCache);
/**
* Used to maintain state about the connections of a load group and
* how they interact with blocking items like HEAD css/js loads.
*/
[uuid(fdc9659c-b597-4ac0-9c9e-14b04dbb682f)]
interface nsILoadGroupConnectionInfo : nsISupports
{
/**
* Number of active blocking transactions associated with this load group
*/
readonly attribute unsigned long blockingTransactionCount;
/**
* Increase the number of active blocking transactions associated
* with this load group by one.
*/
void addBlockingTransaction();
/**
* Decrease the number of active blocking transactions associated
* with this load group by one. The return value is the number of remaining
* blockers.
*/
unsigned long removeBlockingTransaction();
/* reading this attribute gives out weak pointers to the push
* cache. The nsILoadGroupConnectionInfo implemenation owns the cache
* and will destroy it when overwritten or when the load group
* ends.
*/
[noscript] attribute SpdyPushCachePtr spdyPushCache;
};

View File

@ -0,0 +1,85 @@
/* -*- Mode: C++; tab-width: 4; 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 "nsISupports.idl"
%{C++
// Forward-declare mozilla::net::SpdyPushCache
namespace mozilla {
namespace net {
class SpdyPushCache;
}
}
%}
[ptr] native SpdyPushCachePtr(mozilla::net::SpdyPushCache);
/**
* The nsISchedulingContext is used to maintain state about connections
* that are in some way associated with each other (often by being part
* of the same load group) and how they interact with blocking items like
* HEAD css/js loads.
*
* This used to be known as nsILoadGroupConnectionInfo.
*/
[scriptable, uuid(658e3e6e-8633-4b1a-8d66-fa9f72293e63)]
interface nsISchedulingContext : nsISupports
{
/**
* A unique identifier for this scheduling context
*/
[noscript] readonly attribute nsID ID;
/**
* Number of active blocking transactions associated with this context
*/
readonly attribute unsigned long blockingTransactionCount;
/**
* Increase the number of active blocking transactions associated
* with this context by one.
*/
void addBlockingTransaction();
/**
* Decrease the number of active blocking transactions associated
* with this context by one. The return value is the number of remaining
* blockers.
*/
unsigned long removeBlockingTransaction();
/**
* This gives out a weak pointer to the push cache.
* The nsISchedulingContext implementation owns the cache
* and will destroy it when overwritten or when the context
* ends.
*/
[noscript] attribute SpdyPushCachePtr spdyPushCache;
};
/**
* The nsISchedulingContextService is how anyone gets access to a scheduling
* context when they haven't been explicitly given a strong reference to an
* existing one. It is responsible for creating and handing out strong
* references to nsISchedulingContexts, but only keeps weak references itself.
* The shared scheduling context will go away once no one else is keeping a
* reference to it. If you ask for a scheduling context that has no one else
* holding a reference to it, you'll get a brand new scheduling context. Anyone
* who asks for the same scheduling context while you're holding a reference
* will get a reference to the same scheduling context you have.
*/
[uuid(7fcbf4da-d828-4acc-b144-e5435198f727)]
interface nsISchedulingContextService : nsISupports
{
/**
* Get an existing scheduling context from its ID
*/
nsISchedulingContext getSchedulingContext(in nsIDRef id);
/**
* Create a new scheduling context identifier
*/
nsID newSchedulingContextID();
};

View File

@ -14,13 +14,11 @@
#include "prlog.h"
#include "nsString.h"
#include "nsTArray.h"
#include "mozilla/Atomics.h"
#include "mozilla/Telemetry.h"
#include "nsAutoPtr.h"
#include "mozilla/net/PSpdyPush.h"
#include "nsITimedChannel.h"
#include "nsIInterfaceRequestor.h"
#include "nsIRequestObserver.h"
#include "nsISchedulingContext.h"
#include "CacheObserver.h"
#include "MainThreadUtils.h"
@ -741,12 +739,12 @@ nsLoadGroup::SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks)
}
NS_IMETHODIMP
nsLoadGroup::GetConnectionInfo(nsILoadGroupConnectionInfo **aCI)
nsLoadGroup::GetSchedulingContextID(nsID *aSCID)
{
NS_ENSURE_ARG_POINTER(aCI);
*aCI = mConnectionInfo;
NS_IF_ADDREF(*aCI);
return NS_OK;
if (!mSchedulingContext) {
return NS_ERROR_NOT_AVAILABLE;
}
return mSchedulingContext->GetID(aSCID);
}
////////////////////////////////////////////////////////////////////////////////
@ -1068,68 +1066,6 @@ nsresult nsLoadGroup::MergeLoadFlags(nsIRequest *aRequest, nsLoadFlags& outFlags
return rv;
}
// nsLoadGroupConnectionInfo
class nsLoadGroupConnectionInfo final : public nsILoadGroupConnectionInfo
{
~nsLoadGroupConnectionInfo() {}
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSILOADGROUPCONNECTIONINFO
nsLoadGroupConnectionInfo();
private:
Atomic<uint32_t> mBlockingTransactionCount;
nsAutoPtr<mozilla::net::SpdyPushCache> mSpdyCache;
};
NS_IMPL_ISUPPORTS(nsLoadGroupConnectionInfo, nsILoadGroupConnectionInfo)
nsLoadGroupConnectionInfo::nsLoadGroupConnectionInfo()
: mBlockingTransactionCount(0)
{
}
NS_IMETHODIMP
nsLoadGroupConnectionInfo::GetBlockingTransactionCount(uint32_t *aBlockingTransactionCount)
{
NS_ENSURE_ARG_POINTER(aBlockingTransactionCount);
*aBlockingTransactionCount = mBlockingTransactionCount;
return NS_OK;
}
NS_IMETHODIMP
nsLoadGroupConnectionInfo::AddBlockingTransaction()
{
mBlockingTransactionCount++;
return NS_OK;
}
NS_IMETHODIMP
nsLoadGroupConnectionInfo::RemoveBlockingTransaction(uint32_t *_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
mBlockingTransactionCount--;
*_retval = mBlockingTransactionCount;
return NS_OK;
}
/* [noscript] attribute SpdyPushCachePtr spdyPushCache; */
NS_IMETHODIMP
nsLoadGroupConnectionInfo::GetSpdyPushCache(mozilla::net::SpdyPushCache **aSpdyPushCache)
{
*aSpdyPushCache = mSpdyCache.get();
return NS_OK;
}
NS_IMETHODIMP
nsLoadGroupConnectionInfo::SetSpdyPushCache(mozilla::net::SpdyPushCache *aSpdyPushCache)
{
mSpdyCache = aSpdyPushCache;
return NS_OK;
}
nsresult nsLoadGroup::Init()
{
static const PLDHashTableOps hash_table_ops =
@ -1144,7 +1080,14 @@ nsresult nsLoadGroup::Init()
PL_DHashTableInit(&mRequests, &hash_table_ops,
sizeof(RequestMapEntry));
mConnectionInfo = new nsLoadGroupConnectionInfo();
nsCOMPtr<nsISchedulingContextService> scsvc = do_GetService("@mozilla.org/network/scheduling-context-service;1");
if (scsvc) {
nsID schedulingContextID;
if (NS_SUCCEEDED(scsvc->NewSchedulingContextID(&schedulingContextID))) {
scsvc->GetSchedulingContext(schedulingContextID,
getter_AddRefs(mSchedulingContext));
}
}
return NS_OK;
}

View File

@ -17,7 +17,7 @@
#include "pldhash.h"
#include "mozilla/TimeStamp.h"
class nsILoadGroupConnectionInfo;
class nsISchedulingContext;
class nsITimedChannel;
class nsLoadGroup : public nsILoadGroup,
@ -70,7 +70,7 @@ protected:
nsCOMPtr<nsILoadGroup> mLoadGroup; // load groups can contain load groups
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsILoadGroupConnectionInfo> mConnectionInfo;
nsCOMPtr<nsISchedulingContext> mSchedulingContext;
nsCOMPtr<nsIRequest> mDefaultLoadRequest;
PLDHashTable mRequests;

View File

@ -468,6 +468,17 @@
{ 0xae, 0xcf, 0x05, 0xf8, 0xfa, 0xf0, 0x0c, 0x9b } \
}
// service implementing nsISchedulingContextService
#define NS_SCHEDULINGCONTEXTSERVICE_CONTRACTID \
"@mozilla.org/network/scheduling-context-service;1"
#define NS_SCHEDULINGCONTEXTSERVICE_CID \
{ /* d5499fa7-7ba8-49ff-9e30-1858b99ace69 */ \
0xd5499fa7, \
0x7ba8, \
0x49ff, \
{0x93, 0x30, 0x18, 0x58, 0xb9, 0x9a, 0xce, 0x69} \
}
/******************************************************************************
* netwerk/cache/ classes
*/

View File

@ -132,6 +132,10 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(RedirectChannelRegistrar)
typedef mozilla::net::CacheStorageService CacheStorageService;
NS_GENERIC_FACTORY_CONSTRUCTOR(CacheStorageService)
#include "SchedulingContextService.h"
typedef mozilla::net::SchedulingContextService SchedulingContextService;
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(SchedulingContextService, Init)
///////////////////////////////////////////////////////////////////////////////
extern nsresult
@ -801,6 +805,7 @@ NS_DEFINE_NAMED_CID(NS_SERIALIZATION_HELPER_CID);
NS_DEFINE_NAMED_CID(NS_REDIRECTCHANNELREGISTRAR_CID);
NS_DEFINE_NAMED_CID(NS_CACHE_STORAGE_SERVICE_CID);
NS_DEFINE_NAMED_CID(NS_NETWORKPREDICTOR_CID);
NS_DEFINE_NAMED_CID(NS_SCHEDULINGCONTEXTSERVICE_CID);
static const mozilla::Module::CIDEntry kNeckoCIDs[] = {
{ &kNS_IOSERVICE_CID, false, nullptr, nsIOServiceConstructor },
@ -947,6 +952,7 @@ static const mozilla::Module::CIDEntry kNeckoCIDs[] = {
{ &kNS_REDIRECTCHANNELREGISTRAR_CID, false, nullptr, RedirectChannelRegistrarConstructor },
{ &kNS_CACHE_STORAGE_SERVICE_CID, false, nullptr, CacheStorageServiceConstructor },
{ &kNS_NETWORKPREDICTOR_CID, false, nullptr, mozilla::net::Predictor::Create },
{ &kNS_SCHEDULINGCONTEXTSERVICE_CID, false, nullptr, SchedulingContextServiceConstructor },
{ nullptr }
};
@ -1097,6 +1103,7 @@ static const mozilla::Module::ContractIDEntry kNeckoContracts[] = {
{ NS_CACHE_STORAGE_SERVICE_CONTRACTID, &kNS_CACHE_STORAGE_SERVICE_CID },
{ NS_CACHE_STORAGE_SERVICE_CONTRACTID2, &kNS_CACHE_STORAGE_SERVICE_CID },
{ NS_NETWORKPREDICTOR_CONTRACTID, &kNS_NETWORKPREDICTOR_CID },
{ NS_SCHEDULINGCONTEXTSERVICE_CONTRACTID, &kNS_SCHEDULINGCONTEXTSERVICE_CID },
{ nullptr }
};

View File

@ -58,6 +58,7 @@ struct HttpChannelOpenArgs
uint32_t securityFlags;
uint32_t contentPolicyType;
uint32_t innerWindowID;
nsCString schedulingContextID;
};
struct HttpChannelConnectArgs

View File

@ -77,7 +77,7 @@ Http2PushedStream::Http2PushedStream(Http2PushTransactionBuffer *aTransaction,
mStreamID = aID;
MOZ_ASSERT(!(aID & 1)); // must be even to be a pushed stream
mBufferedPush->SetPushStream(this);
mLoadGroupCI = aAssociatedStream->LoadGroupConnectionInfo();
mSchedulingContext = aAssociatedStream->SchedulingContext();
mLastRead = TimeStamp::Now();
SetPriority(aAssociatedStream->Priority() + 1);
}

View File

@ -13,6 +13,7 @@
#include "mozilla/TimeStamp.h"
#include "nsHttpRequestHead.h"
#include "nsILoadGroup.h"
#include "nsISchedulingContext.h"
#include "nsString.h"
#include "PSpdyPush.h"
@ -42,7 +43,7 @@ public:
nsresult ReadSegments(nsAHttpSegmentReader *, uint32_t, uint32_t *) override;
nsresult WriteSegments(nsAHttpSegmentWriter *, uint32_t, uint32_t *) override;
nsILoadGroupConnectionInfo *LoadGroupConnectionInfo() override { return mLoadGroupCI; };
nsISchedulingContext *SchedulingContext() override { return mSchedulingContext; };
void ConnectPushedStream(Http2Stream *consumer);
bool TryOnPush();
@ -65,7 +66,7 @@ private:
Http2Stream *mConsumerStream; // paired request stream that consumes from
// real http/2 one.. null until a match is made.
nsCOMPtr<nsILoadGroupConnectionInfo> mLoadGroupCI;
nsCOMPtr<nsISchedulingContext> mSchedulingContext;
nsAHttpTransaction *mAssociatedTransaction;

View File

@ -24,7 +24,7 @@
#include "nsHttp.h"
#include "nsHttpHandler.h"
#include "nsHttpConnection.h"
#include "nsILoadGroup.h"
#include "nsISchedulingContext.h"
#include "nsISSLSocketControl.h"
#include "nsISSLStatus.h"
#include "nsISSLStatusProvider.h"
@ -1077,10 +1077,10 @@ Http2Session::CleanupStream(Http2Stream *aStream, nsresult aResult,
Http2PushedStream *pushStream = static_cast<Http2PushedStream *>(aStream);
nsAutoCString hashKey;
pushStream->GetHashKey(hashKey);
nsILoadGroupConnectionInfo *loadGroupCI = aStream->LoadGroupConnectionInfo();
if (loadGroupCI) {
nsISchedulingContext *schedulingContext = aStream->SchedulingContext();
if (schedulingContext) {
SpdyPushCache *cache = nullptr;
loadGroupCI->GetSpdyPushCache(&cache);
schedulingContext->GetSpdyPushCache(&cache);
if (cache) {
Http2PushedStream *trash = cache->RemovePushedStreamHttp2(hashKey);
LOG3(("Http2Session::CleanupStream %p aStream=%p pushStream=%p trash=%p",
@ -1638,12 +1638,12 @@ Http2Session::RecvPushPromise(Http2Session *self)
LOG3(("Http2Session::RecvPushPromise %p lookup associated ID failed.\n", self));
self->GenerateRstStream(PROTOCOL_ERROR, promisedID);
} else {
nsILoadGroupConnectionInfo *loadGroupCI = associatedStream->LoadGroupConnectionInfo();
if (loadGroupCI) {
loadGroupCI->GetSpdyPushCache(&cache);
nsISchedulingContext *schedulingContext = associatedStream->SchedulingContext();
if (schedulingContext) {
schedulingContext->GetSpdyPushCache(&cache);
if (!cache) {
cache = new SpdyPushCache();
if (!cache || NS_FAILED(loadGroupCI->SetSpdyPushCache(cache))) {
if (!cache || NS_FAILED(schedulingContext->SetSpdyPushCache(cache))) {
delete cache;
cache = nullptr;
}
@ -1651,7 +1651,7 @@ Http2Session::RecvPushPromise(Http2Session *self)
}
if (!cache) {
// this is unexpected, but we can handle it just by refusing the push
LOG3(("Http2Session::RecvPushPromise Push Recevied without loadgroup cache\n"));
LOG3(("Http2Session::RecvPushPromise Push Recevied without push cache\n"));
self->GenerateRstStream(REFUSED_STREAM_ERROR, promisedID);
} else {
resetStream = false;

View File

@ -363,10 +363,10 @@ Http2Stream::ParseHttpRequestHeaders(const char *buf,
// check the push cache for GET
if (head->IsGet()) {
// from :scheme, :authority, :path
nsILoadGroupConnectionInfo *loadGroupCI = mTransaction->LoadGroupConnectionInfo();
nsISchedulingContext *schedulingContext = mTransaction->SchedulingContext();
SpdyPushCache *cache = nullptr;
if (loadGroupCI) {
loadGroupCI->GetSpdyPushCache(&cache);
if (schedulingContext) {
schedulingContext->GetSpdyPushCache(&cache);
}
Http2PushedStream *pushedStream = nullptr;
@ -393,8 +393,8 @@ Http2Stream::ParseHttpRequestHeaders(const char *buf,
}
LOG3(("Pushed Stream Lookup "
"session=%p key=%s loadgroupci=%p cache=%p hit=%p\n",
mSession, hashkey.get(), loadGroupCI, cache, pushedStream));
"session=%p key=%s schedulingcontext=%p cache=%p hit=%p\n",
mSession, hashkey.get(), schedulingContext, cache, pushedStream));
if (pushedStream) {
LOG3(("Pushed Stream Match located id=0x%X key=%s\n",

View File

@ -67,9 +67,9 @@ public:
bool HasRegisteredID() { return mStreamID != 0; }
nsAHttpTransaction *Transaction() { return mTransaction; }
virtual nsILoadGroupConnectionInfo *LoadGroupConnectionInfo()
virtual nsISchedulingContext *SchedulingContext()
{
return mTransaction ? mTransaction->LoadGroupConnectionInfo() : nullptr;
return mTransaction ? mTransaction->SchedulingContext() : nullptr;
}
void Close(nsresult reason);

View File

@ -37,6 +37,7 @@
#include "nsPerformance.h"
#include "nsINetworkInterceptController.h"
#include "mozIThirdPartyUtil.h"
#include "nsILoadGroupChild.h"
#include <algorithm>
@ -95,6 +96,7 @@ HttpBaseChannel::HttpBaseChannel()
#endif
mSelfAddr.raw.family = PR_AF_UNSPEC;
mPeerAddr.raw.family = PR_AF_UNSPEC;
mSchedulingContextID.Clear();
}
HttpBaseChannel::~HttpBaseChannel()
@ -1458,6 +1460,21 @@ HttpBaseChannel::RedirectTo(nsIURI *newURI)
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetSchedulingContextID(nsID *aSCID)
{
NS_ENSURE_ARG_POINTER(aSCID);
*aSCID = mSchedulingContextID;
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::SetSchedulingContextID(const nsID aSCID)
{
mSchedulingContextID = aSCID;
return NS_OK;
}
//-----------------------------------------------------------------------------
// HttpBaseChannel::nsIHttpChannelInternal
//-----------------------------------------------------------------------------
@ -2671,6 +2688,35 @@ HttpBaseChannel::GetPerformance()
//------------------------------------------------------------------------------
bool
HttpBaseChannel::EnsureSchedulingContextID()
{
nsID nullID;
nullID.Clear();
if (!mSchedulingContextID.Equals(nullID)) {
// Already have a scheduling context ID, no need to do the rest of this work
return true;
}
// Find the loadgroup at the end of the chain in order
// to make sure all channels derived from the load group
// use the same connection scope.
nsCOMPtr<nsILoadGroupChild> childLoadGroup = do_QueryInterface(mLoadGroup);
if (!childLoadGroup) {
return false;
}
nsCOMPtr<nsILoadGroup> rootLoadGroup;
childLoadGroup->GetRootLoadGroup(getter_AddRefs(rootLoadGroup));
if (!rootLoadGroup) {
return false;
}
// Set the load group connection scope on the transaction
rootLoadGroup->GetSchedulingContextID(&mSchedulingContextID);
return true;
}
} // namespace net
} // namespace mozilla

View File

@ -158,6 +158,8 @@ public:
NS_IMETHOD GetResponseStatusText(nsACString& aValue) override;
NS_IMETHOD GetRequestSucceeded(bool *aValue) override;
NS_IMETHOD RedirectTo(nsIURI *newURI) override;
NS_IMETHOD GetSchedulingContextID(nsID *aSCID) override;
NS_IMETHOD SetSchedulingContextID(const nsID aSCID) override;
// nsIHttpChannelInternal
NS_IMETHOD GetDocumentURI(nsIURI **aDocumentURI) override;
@ -433,6 +435,9 @@ protected:
// The network interface id that's associated with this channel.
nsCString mNetworkInterfaceId;
nsID mSchedulingContextID;
bool EnsureSchedulingContextID();
};
// Share some code while working around C++'s absurd inability to handle casting

View File

@ -1634,6 +1634,11 @@ HttpChannelChild::ContinueAsyncOpen()
propagateLoadInfo(mLoadInfo, openArgs);
EnsureSchedulingContextID();
char scid[NSID_LENGTH];
mSchedulingContextID.ToProvidedString(scid);
openArgs.schedulingContextID().AssignASCII(scid);
// The socket transport in the chrome process now holds a logical ref to us
// until OnStopRequest, or we do a redirect, or we hit an IPDL error.
AddIPDLReference();

View File

@ -110,7 +110,8 @@ HttpChannelParent::Init(const HttpChannelCreationArgs& aArgs)
a.entityID(), a.chooseApplicationCache(),
a.appCacheClientID(), a.allowSpdy(), a.fds(),
a.requestingPrincipalInfo(), a.triggeringPrincipalInfo(),
a.securityFlags(), a.contentPolicyType(), a.innerWindowID());
a.securityFlags(), a.contentPolicyType(), a.innerWindowID(),
a.schedulingContextID());
}
case HttpChannelCreationArgs::THttpChannelConnectArgs:
{
@ -201,7 +202,8 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
const ipc::PrincipalInfo& aTriggeringPrincipalInfo,
const uint32_t& aSecurityFlags,
const uint32_t& aContentPolicyType,
const uint32_t& aInnerWindowID)
const uint32_t& aInnerWindowID,
const nsCString& aSchedulingContextID)
{
nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
if (!uri) {
@ -373,6 +375,10 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
}
}
nsID schedulingContextID;
schedulingContextID.Parse(aSchedulingContextID.BeginReading());
mChannel->SetSchedulingContextID(schedulingContextID);
rv = mChannel->AsyncOpen(mParentListener, nullptr);
if (NS_FAILED(rv))
return SendFailedAsyncOpen(rv);

View File

@ -115,7 +115,8 @@ protected:
const ipc::PrincipalInfo& aTriggeringPrincipalInfo,
const uint32_t& aSecurityFlags,
const uint32_t& aContentPolicyType,
const uint32_t& aInnerWindowID);
const uint32_t& aInnerWindowID,
const nsCString& aSchedulingContextID);
virtual bool RecvSetPriority(const uint16_t& priority) override;
virtual bool RecvSetClassOfService(const uint32_t& cos) override;

View File

@ -205,6 +205,18 @@ NullHttpChannel::RedirectTo(nsIURI *aNewURI)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
NullHttpChannel::GetSchedulingContextID(nsID *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
NullHttpChannel::SetSchedulingContextID(const nsID scID)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//-----------------------------------------------------------------------------
// NullHttpChannel::nsIChannel
//-----------------------------------------------------------------------------

View File

@ -40,7 +40,7 @@ SpdyPushedStream31::SpdyPushedStream31(SpdyPush31TransactionBuffer *aTransaction
LOG3(("SpdyPushedStream31 ctor this=%p id=0x%X\n", this, aID));
mStreamID = aID;
mBufferedPush->SetPushStream(this);
mLoadGroupCI = aAssociatedStream->LoadGroupConnectionInfo();
mSchedulingContext = aAssociatedStream->SchedulingContext();
mLastRead = TimeStamp::Now();
}

View File

@ -11,7 +11,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/TimeStamp.h"
#include "nsHttpRequestHead.h"
#include "nsILoadGroup.h"
#include "nsISchedulingContext.h"
#include "nsString.h"
#include "PSpdyPush.h"
#include "SpdySession31.h"
@ -40,7 +40,7 @@ public:
nsresult ReadSegments(nsAHttpSegmentReader *, uint32_t, uint32_t *);
nsresult WriteSegments(nsAHttpSegmentWriter *, uint32_t, uint32_t *);
nsILoadGroupConnectionInfo *LoadGroupConnectionInfo() { return mLoadGroupCI; };
nsISchedulingContext *SchedulingContext() { return mSchedulingContext; };
void ConnectPushedStream(SpdyStream31 *consumer);
bool DeferCleanupOnSuccess() { return mDeferCleanupOnSuccess; }
@ -58,7 +58,7 @@ private:
SpdyStream31 *mConsumerStream; // paired request stream that consumes from
// real spdy one.. null until a match is made.
nsCOMPtr<nsILoadGroupConnectionInfo> mLoadGroupCI;
nsCOMPtr<nsISchedulingContext> mSchedulingContext;
SpdyPush31TransactionBuffer *mBufferedPush;
TimeStamp mLastRead;

View File

@ -18,7 +18,7 @@
#include "nsHttp.h"
#include "nsHttpHandler.h"
#include "nsHttpConnection.h"
#include "nsILoadGroup.h"
#include "nsISchedulingContext.h"
#include "nsISupportsPriority.h"
#include "prprf.h"
#include "prnetdb.h"
@ -1081,12 +1081,12 @@ SpdySession31::HandleSynStream(SpdySession31 *self)
self->GenerateRstStream(RST_INVALID_STREAM, streamID);
} else {
nsILoadGroupConnectionInfo *loadGroupCI = associatedStream->LoadGroupConnectionInfo();
if (loadGroupCI) {
loadGroupCI->GetSpdyPushCache(&cache);
nsISchedulingContext *schedulingContext = associatedStream->SchedulingContext();
if (schedulingContext) {
schedulingContext->GetSpdyPushCache(&cache);
if (!cache) {
cache = new SpdyPushCache();
if (!cache || NS_FAILED(loadGroupCI->SetSpdyPushCache(cache))) {
if (!cache || NS_FAILED(schedulingContext->SetSpdyPushCache(cache))) {
delete cache;
cache = nullptr;
}
@ -1094,7 +1094,7 @@ SpdySession31::HandleSynStream(SpdySession31 *self)
}
if (!cache) {
// this is unexpected, but we can handle it just be refusing the push
LOG3(("SpdySession31::HandleSynStream Push Recevied without loadgroup cache\n"));
LOG3(("SpdySession31::HandleSynStream Push Recevied without push cache\n"));
self->GenerateRstStream(RST_REFUSED_STREAM, streamID);
}
else {

View File

@ -316,10 +316,10 @@ SpdyStream31::ParseHttpRequestHeaders(const char *buf,
// check the push cache for GET
if (mTransaction->RequestHead()->IsGet()) {
// from :scheme, :host, :path
nsILoadGroupConnectionInfo *loadGroupCI = mTransaction->LoadGroupConnectionInfo();
nsISchedulingContext *schedulingContext = mTransaction->SchedulingContext();
SpdyPushCache *cache = nullptr;
if (loadGroupCI)
loadGroupCI->GetSpdyPushCache(&cache);
if (schedulingContext)
schedulingContext->GetSpdyPushCache(&cache);
SpdyPushedStream31 *pushedStream = nullptr;
// we remove the pushedstream from the push cache so that

View File

@ -42,9 +42,9 @@ public:
bool HasRegisteredID() { return mStreamID != 0; }
nsAHttpTransaction *Transaction() { return mTransaction; }
virtual nsILoadGroupConnectionInfo *LoadGroupConnectionInfo()
virtual nsISchedulingContext *SchedulingContext()
{
return mTransaction ? mTransaction->LoadGroupConnectionInfo() : nullptr;
return mTransaction ? mTransaction->SchedulingContext() : nullptr;
}
void Close(nsresult reason);

View File

@ -12,7 +12,7 @@
class nsIInterfaceRequestor;
class nsIEventTarget;
class nsITransport;
class nsILoadGroupConnectionInfo;
class nsISchedulingContext;
namespace mozilla { namespace net {
@ -145,8 +145,8 @@ public:
// other types
virtual SpdyConnectTransaction *QuerySpdyConnectTransaction() { return nullptr; }
// return the load group connection information associated with the transaction
virtual nsILoadGroupConnectionInfo *LoadGroupConnectionInfo() { return nullptr; }
// return the scheduling context associated with the transaction
virtual nsISchedulingContext *SchedulingContext() { return nullptr; }
// return the connection information associated with the transaction
virtual nsHttpConnectionInfo *ConnectionInfo() = 0;

View File

@ -604,25 +604,27 @@ nsHttpChannel::ContinueHandleAsyncFallback(nsresult rv)
}
void
nsHttpChannel::SetupTransactionLoadGroupInfo()
nsHttpChannel::SetupTransactionSchedulingContext()
{
// Find the loadgroup at the end of the chain in order
// to make sure all channels derived from the load group
// use the same connection scope.
nsCOMPtr<nsILoadGroupChild> childLoadGroup = do_QueryInterface(mLoadGroup);
if (!childLoadGroup)
if (!EnsureSchedulingContextID()) {
return;
}
nsCOMPtr<nsILoadGroup> rootLoadGroup;
childLoadGroup->GetRootLoadGroup(getter_AddRefs(rootLoadGroup));
if (!rootLoadGroup)
nsISchedulingContextService *scsvc =
gHttpHandler->GetSchedulingContextService();
if (!scsvc) {
return;
}
// Set the load group connection scope on the transaction
nsCOMPtr<nsILoadGroupConnectionInfo> ci;
rootLoadGroup->GetConnectionInfo(getter_AddRefs(ci));
if (ci)
mTransaction->SetLoadGroupConnectionInfo(ci);
nsCOMPtr<nsISchedulingContext> sc;
nsresult rv = scsvc->GetSchedulingContext(mSchedulingContextID,
getter_AddRefs(sc));
if (NS_FAILED(rv)) {
return;
}
mTransaction->SetSchedulingContext(sc);
}
static bool
@ -839,7 +841,7 @@ nsHttpChannel::SetupTransaction()
}
mTransaction->SetClassOfService(mClassOfService);
SetupTransactionLoadGroupInfo();
SetupTransactionSchedulingContext();
rv = nsInputStreamPump::Create(getter_AddRefs(mTransactionPump),
responseStream);

View File

@ -231,7 +231,7 @@ private:
nsresult Connect();
void SpeculativeConnect();
nsresult SetupTransaction();
void SetupTransactionLoadGroupInfo();
void SetupTransactionSchedulingContext();
nsresult CallOnStartRequest();
nsresult ProcessResponse();
nsresult ContinueProcessResponse(nsresult);

View File

@ -28,6 +28,7 @@
#include "NullHttpTransaction.h"
#include "nsIDNSRecord.h"
#include "nsITransport.h"
#include "nsISchedulingContext.h"
#include "nsISocketTransportService.h"
#include <algorithm>
#include "Http2Compression.h"
@ -1782,20 +1783,20 @@ nsHttpConnectionMgr::TryDispatchTransaction(nsConnectionEntry *ent,
}
}
// If this is not a blocking transaction and the loadgroup for it is
// If this is not a blocking transaction and the scheduling context for it is
// currently processing one or more blocking transactions then we
// need to just leave it in the queue until those are complete unless it is
// explicitly marked as unblocked.
if (!(caps & NS_HTTP_LOAD_AS_BLOCKING)) {
if (!(caps & NS_HTTP_LOAD_UNBLOCKED)) {
nsILoadGroupConnectionInfo *loadGroupCI = trans->LoadGroupConnectionInfo();
if (loadGroupCI) {
nsISchedulingContext *schedulingContext = trans->SchedulingContext();
if (schedulingContext) {
uint32_t blockers = 0;
if (NS_SUCCEEDED(loadGroupCI->GetBlockingTransactionCount(&blockers)) &&
if (NS_SUCCEEDED(schedulingContext->GetBlockingTransactionCount(&blockers)) &&
blockers) {
// need to wait for blockers to clear
LOG((" blocked by load group: [lgci=%p trans=%p blockers=%d]\n",
loadGroupCI, trans, blockers));
LOG((" blocked by scheduling context: [sc=%p trans=%p blockers=%d]\n",
schedulingContext, trans, blockers));
return NS_ERROR_NOT_AVAILABLE;
}
}

View File

@ -321,6 +321,9 @@ nsHttpHandler::Init()
rv = InitConnectionMgr();
if (NS_FAILED(rv)) return rv;
mSchedulingContextService =
do_GetService("@mozilla.org/network/scheduling-context-service;1");
#ifdef ANDROID
mProductSub.AssignLiteral(MOZILLA_UAVERSION);
#else

View File

@ -25,6 +25,7 @@ class nsICancelable;
class nsICookieService;
class nsIIOService;
class nsIObserverService;
class nsISchedulingContextService;
class nsISiteSecurityService;
class nsIStreamConverterService;
class nsITimer;
@ -337,6 +338,11 @@ public:
void SetCacheSkippedUntil(TimeStamp arg) { mCacheSkippedUntil = arg; }
void ClearCacheSkippedUntil() { mCacheSkippedUntil = TimeStamp(); }
nsISchedulingContextService *GetSchedulingContextService()
{
return mSchedulingContextService.get();
}
private:
virtual ~nsHttpHandler();
@ -540,6 +546,8 @@ private:
// incorrect content lengths or malformed chunked encodings
FrameCheckLevel mEnforceH1Framing;
nsCOMPtr<nsISchedulingContextService> mSchedulingContextService;
private:
// For Rate Pacing Certain Network Events. Only assign this pointer on
// socket thread.

View File

@ -33,6 +33,7 @@
#include "nsIInputStream.h"
#include "nsITransport.h"
#include "nsIOService.h"
#include "nsISchedulingContext.h"
#include <algorithm>
#ifdef MOZ_WIDGET_GONK
@ -1784,10 +1785,10 @@ nsHttpTransaction::CancelPipeline(uint32_t reason)
void
nsHttpTransaction::SetLoadGroupConnectionInfo(nsILoadGroupConnectionInfo *aLoadGroupCI)
nsHttpTransaction::SetSchedulingContext(nsISchedulingContext *aSchedulingContext)
{
LOG(("nsHttpTransaction %p SetLoadGroupConnectionInfo %p\n", this, aLoadGroupCI));
mLoadGroupCI = aLoadGroupCI;
LOG(("nsHttpTransaction %p SetSchedulingContext %p\n", this, aSchedulingContext));
mSchedulingContext = aSchedulingContext;
}
// Called when the transaction marked for blocking is associated with a connection
@ -1802,32 +1803,32 @@ nsHttpTransaction::DispatchedAsBlocking()
LOG(("nsHttpTransaction %p dispatched as blocking\n", this));
if (!mLoadGroupCI)
if (!mSchedulingContext)
return;
LOG(("nsHttpTransaction adding blocking transaction %p from "
"loadgroup %p\n", this, mLoadGroupCI.get()));
"scheduling context %p\n", this, mSchedulingContext.get()));
mLoadGroupCI->AddBlockingTransaction();
mSchedulingContext->AddBlockingTransaction();
mDispatchedAsBlocking = true;
}
void
nsHttpTransaction::RemoveDispatchedAsBlocking()
{
if (!mLoadGroupCI || !mDispatchedAsBlocking)
if (!mSchedulingContext || !mDispatchedAsBlocking)
return;
uint32_t blockers = 0;
nsresult rv = mLoadGroupCI->RemoveBlockingTransaction(&blockers);
nsresult rv = mSchedulingContext->RemoveBlockingTransaction(&blockers);
LOG(("nsHttpTransaction removing blocking transaction %p from "
"loadgroup %p. %d blockers remain.\n", this,
mLoadGroupCI.get(), blockers));
"scheduling context %p. %d blockers remain.\n", this,
mSchedulingContext.get(), blockers));
if (NS_SUCCEEDED(rv) && !blockers) {
LOG(("nsHttpTransaction %p triggering release of blocked channels "
" with loadgroupci=%p\n", this, mLoadGroupCI.get()));
" with scheduling context=%p\n", this, mSchedulingContext.get()));
gHttpHandler->ConnMgr()->ProcessPendingQ();
}
@ -1838,9 +1839,9 @@ void
nsHttpTransaction::ReleaseBlockingTransaction()
{
RemoveDispatchedAsBlocking();
LOG(("nsHttpTransaction %p loadgroupci set to null "
"in ReleaseBlockingTransaction() - was %p\n", this, mLoadGroupCI.get()));
mLoadGroupCI = nullptr;
LOG(("nsHttpTransaction %p scheduling context set to null "
"in ReleaseBlockingTransaction() - was %p\n", this, mSchedulingContext.get()));
mSchedulingContext = nullptr;
}
void

View File

@ -12,7 +12,6 @@
#include "EventTokenBucket.h"
#include "nsCOMPtr.h"
#include "nsThreadUtils.h"
#include "nsILoadGroup.h"
#include "nsIInterfaceRequestor.h"
#include "TimingStruct.h"
#include "Http2Push.h"
@ -28,6 +27,7 @@ class nsIHttpActivityObserver;
class nsIEventTarget;
class nsIInputStream;
class nsIOutputStream;
class nsISchedulingContext;
namespace mozilla { namespace net {
@ -123,9 +123,9 @@ public:
const TimeStamp GetPendingTime() { return mPendingTime; }
bool UsesPipelining() const { return mCaps & NS_HTTP_ALLOW_PIPELINING; }
// overload of nsAHttpTransaction::LoadGroupConnectionInfo()
nsILoadGroupConnectionInfo *LoadGroupConnectionInfo() override { return mLoadGroupCI.get(); }
void SetLoadGroupConnectionInfo(nsILoadGroupConnectionInfo *aLoadGroupCI);
// overload of nsAHttpTransaction::SchedulingContext()
nsISchedulingContext *SchedulingContext() override { return mSchedulingContext.get(); }
void SetSchedulingContext(nsISchedulingContext *aSchedulingContext);
void DispatchedAsBlocking();
void RemoveDispatchedAsBlocking();
@ -217,7 +217,7 @@ private:
nsCOMPtr<nsISupports> mSecurityInfo;
nsCOMPtr<nsIAsyncInputStream> mPipeIn;
nsCOMPtr<nsIAsyncOutputStream> mPipeOut;
nsCOMPtr<nsILoadGroupConnectionInfo> mLoadGroupCI;
nsCOMPtr<nsISchedulingContext> mSchedulingContext;
nsCOMPtr<nsISupports> mChannel;
nsCOMPtr<nsIHttpActivityObserver> mActivityDistributor;

View File

@ -14,7 +14,7 @@ interface nsIHttpHeaderVisitor;
* the inspection of the resulting HTTP response status and headers when they
* become available.
*/
[scriptable, uuid(86ad7e1f-3a64-4e0f-a104-395ebecd7d5c)]
[scriptable, uuid(fdc70825-8ae1-4f81-bd9e-f1fd3f6307ad)]
interface nsIHttpChannel : nsIChannel
{
/**************************************************************************
@ -321,4 +321,9 @@ interface nsIHttpChannel : nsIChannel
* has been opened.
*/
void redirectTo(in nsIURI aNewURI);
/**
* Identifies the scheduling context for this load.
*/
[noscript] attribute nsID schedulingContextID;
};

View File

@ -798,3 +798,16 @@ nsViewSourceChannel::RedirectTo(nsIURI *uri)
mHttpChannel->RedirectTo(uri);
}
NS_IMETHODIMP
nsViewSourceChannel::GetSchedulingContextID(nsID *_retval)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->GetSchedulingContextID(_retval);
}
NS_IMETHODIMP
nsViewSourceChannel::SetSchedulingContextID(const nsID scid)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->SetSchedulingContextID(scid);
}

View File

@ -781,8 +781,9 @@ var tests = [ test_http2_post_big
, test_http2_patch
, test_http2_pushapi_1
, test_http2_continuations
// Add new tests above here - best to add new tests before h1
// streams get too involved
// These next two must always come in this order
// best to add new tests before h1 streams get too involved
, test_http2_h11required_stream
, test_http2_h11required_session
, test_http2_retry_rst

View File

@ -8,6 +8,16 @@
#include "prprf.h"
#include "nsMemory.h"
void nsID::Clear()
{
m0 = 0;
m1 = 0;
m2 = 0;
for (int i = 0; i < 8; ++i) {
m3[i] = 0;
}
}
/**
* Multiplies the_int_var with 16 (0x10) and adds the value of the
* hexadecimal digit the_char. If it fails it returns false from

View File

@ -35,6 +35,11 @@ struct nsID
*/
//@{
/**
* Ensures everything is zeroed out.
*/
void Clear();
/**
* Equivalency method. Compares this nsID with another.
* @return <b>true</b> if they are the same, <b>false</b> if not.