mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
Bug 1377208 - Move background h2 stream into background group. r=hurley
This commit is contained in:
parent
af8a2b8fbb
commit
567b0d202a
@ -63,8 +63,9 @@ private:
|
||||
Http2PushedStream::Http2PushedStream(Http2PushTransactionBuffer *aTransaction,
|
||||
Http2Session *aSession,
|
||||
Http2Stream *aAssociatedStream,
|
||||
uint32_t aID)
|
||||
:Http2Stream(aTransaction, aSession, 0)
|
||||
uint32_t aID,
|
||||
uint64_t aCurrentForegroundTabOuterContentWindowId)
|
||||
:Http2Stream(aTransaction, aSession, 0, aCurrentForegroundTabOuterContentWindowId)
|
||||
, mConsumerStream(nullptr)
|
||||
, mAssociatedTransaction(aAssociatedStream->Transaction())
|
||||
, mBufferedPush(aTransaction)
|
||||
|
@ -32,7 +32,8 @@ public:
|
||||
Http2PushedStream(Http2PushTransactionBuffer *aTransaction,
|
||||
Http2Session *aSession,
|
||||
Http2Stream *aAssociatedStream,
|
||||
uint32_t aID);
|
||||
uint32_t aID,
|
||||
uint64_t aCurrentForegroundTabOuterContentWindowId);
|
||||
virtual ~Http2PushedStream() {}
|
||||
|
||||
bool GetPushComplete();
|
||||
|
@ -140,6 +140,8 @@ Http2Session::Http2Session(nsISocketTransport *aSocketTransport, uint32_t versio
|
||||
|
||||
mPingThreshold = gHttpHandler->SpdyPingThreshold();
|
||||
mPreviousPingThreshold = mPingThreshold;
|
||||
mCurrentForegroundTabOuterContentWindowId =
|
||||
gHttpHandler->ConnMgr()->CurrentTopLevelOuterContentWindowId();
|
||||
}
|
||||
|
||||
void
|
||||
@ -418,7 +420,11 @@ Http2Session::AddStream(nsAHttpTransaction *aHttpTransaction,
|
||||
return true;
|
||||
}
|
||||
|
||||
Http2Stream *stream = new Http2Stream(aHttpTransaction, this, aPriority);
|
||||
Http2Stream *stream =
|
||||
new Http2Stream(aHttpTransaction,
|
||||
this,
|
||||
aPriority,
|
||||
mCurrentForegroundTabOuterContentWindowId);
|
||||
|
||||
LOG3(("Http2Session::AddStream session=%p stream=%p serial=%" PRIu64 " "
|
||||
"NextID=0x%X (tentative)", this, stream, mSerial, mNextStreamID));
|
||||
@ -797,14 +803,9 @@ Http2Session::GeneratePriority(uint32_t aID, uint8_t aPriorityWeight)
|
||||
LOG3(("Http2Session::GeneratePriority %p %X %X\n",
|
||||
this, aID, aPriorityWeight));
|
||||
|
||||
uint32_t frameSize = kFrameHeaderBytes + 5;
|
||||
char *packet = EnsureOutputBuffer(frameSize);
|
||||
mOutputQueueUsed += frameSize;
|
||||
char *packet = CreatePriorityFrame(aID, 0, aPriorityWeight);
|
||||
|
||||
CreateFrameHeader(packet, 5, FRAME_TYPE_PRIORITY, 0, aID);
|
||||
NetworkEndian::writeUint32(packet + kFrameHeaderBytes, 0);
|
||||
memcpy(packet + frameSize - 1, &aPriorityWeight, 1);
|
||||
LogIO(this, nullptr, "Generate Priority", packet, frameSize);
|
||||
LogIO(this, nullptr, "Generate Priority", packet, kFrameHeaderBytes + 5);
|
||||
FlushOutputQueue();
|
||||
}
|
||||
|
||||
@ -981,14 +982,38 @@ Http2Session::SendHello()
|
||||
}
|
||||
|
||||
void
|
||||
Http2Session::CreatePriorityNode(uint32_t streamID, uint32_t dependsOn, uint8_t weight,
|
||||
const char *label)
|
||||
Http2Session::SendPriorityFrame(uint32_t streamID,
|
||||
uint32_t dependsOn,
|
||||
uint8_t weight)
|
||||
{
|
||||
char *packet = mOutputQueueBuffer.get() + mOutputQueueUsed;
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
LOG3(("Http2Session::SendPriorityFrame %p Frame 0x%X depends on 0x%X "
|
||||
"weight %d\n", this, streamID, dependsOn, weight));
|
||||
|
||||
char *packet = CreatePriorityFrame(streamID, dependsOn, weight);
|
||||
|
||||
LogIO(this, nullptr, "SendPriorityFrame", packet, kFrameHeaderBytes + 5);
|
||||
FlushOutputQueue();
|
||||
}
|
||||
|
||||
char *
|
||||
Http2Session::CreatePriorityFrame(uint32_t streamID,
|
||||
uint32_t dependsOn,
|
||||
uint8_t weight)
|
||||
{
|
||||
char *packet = EnsureOutputBuffer(kFrameHeaderBytes + 5);
|
||||
CreateFrameHeader(packet, 5, FRAME_TYPE_PRIORITY, 0, streamID);
|
||||
mOutputQueueUsed += kFrameHeaderBytes + 5;
|
||||
NetworkEndian::writeUint32(packet + kFrameHeaderBytes, dependsOn); // depends on
|
||||
packet[kFrameHeaderBytes + 4] = weight; // weight
|
||||
return packet;
|
||||
}
|
||||
|
||||
void
|
||||
Http2Session::CreatePriorityNode(uint32_t streamID, uint32_t dependsOn, uint8_t weight,
|
||||
const char *label)
|
||||
{
|
||||
char *packet = CreatePriorityFrame(streamID, dependsOn, weight);
|
||||
|
||||
LOG3(("Http2Session %p generate Priority Frame 0x%X depends on 0x%X "
|
||||
"weight %d for %s class\n", this, streamID, dependsOn, weight, label));
|
||||
@ -1755,7 +1780,11 @@ Http2Session::RecvPushPromise(Http2Session *self)
|
||||
new Http2PushTransactionBuffer();
|
||||
transactionBuffer->SetConnection(self);
|
||||
Http2PushedStream *pushedStream =
|
||||
new Http2PushedStream(transactionBuffer, self, associatedStream, promisedID);
|
||||
new Http2PushedStream(transactionBuffer,
|
||||
self,
|
||||
associatedStream,
|
||||
promisedID,
|
||||
self->mCurrentForegroundTabOuterContentWindowId);
|
||||
|
||||
rv = pushedStream->ConvertPushHeaders(&self->mDecompressor,
|
||||
self->mDecompressBuffer,
|
||||
@ -4464,5 +4493,17 @@ Http2Session::RealJoinConnection(const nsACString &hostname, int32_t port,
|
||||
return joinedReturn;
|
||||
}
|
||||
|
||||
void
|
||||
Http2Session::TopLevelOuterContentWindowIdChanged(uint64_t windowId)
|
||||
{
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
|
||||
mCurrentForegroundTabOuterContentWindowId = windowId;
|
||||
|
||||
for (auto iter = mStreamTransactionHash.Iter(); !iter.Done(); iter.Next()) {
|
||||
iter.Data()->TopLevelOuterContentWindowIdChanged(windowId);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
@ -258,6 +258,8 @@ public:
|
||||
// For use by an HTTP2Stream
|
||||
void Received421(nsHttpConnectionInfo *ci);
|
||||
|
||||
void SendPriorityFrame(uint32_t streamID, uint32_t dependsOn, uint8_t weight);
|
||||
|
||||
private:
|
||||
|
||||
// These internal states do not correspond to the states of the HTTP/2 specification
|
||||
@ -307,6 +309,7 @@ private:
|
||||
|
||||
MOZ_MUST_USE nsresult SetInputFrameDataStream(uint32_t);
|
||||
void CreatePriorityNode(uint32_t, uint32_t, uint8_t, const char *);
|
||||
char *CreatePriorityFrame(uint32_t, uint32_t, uint8_t);
|
||||
bool VerifyStream(Http2Stream *, uint32_t);
|
||||
void SetNeedsCleanup();
|
||||
|
||||
@ -533,6 +536,8 @@ private:
|
||||
|
||||
nsDataHashtable<nsCStringHashKey, bool> mJoinConnectionCache;
|
||||
|
||||
uint64_t mCurrentForegroundTabOuterContentWindowId;
|
||||
|
||||
class CachePushCheckCallback final : public nsICacheEntryOpenCallback
|
||||
{
|
||||
public:
|
||||
|
@ -38,7 +38,8 @@ namespace net {
|
||||
|
||||
Http2Stream::Http2Stream(nsAHttpTransaction *httpTransaction,
|
||||
Http2Session *session,
|
||||
int32_t priority)
|
||||
int32_t priority,
|
||||
uint64_t windowId)
|
||||
: mStreamID(0)
|
||||
, mSession(session)
|
||||
, mSegmentReader(nullptr)
|
||||
@ -72,6 +73,8 @@ Http2Stream::Http2Stream(nsAHttpTransaction *httpTransaction,
|
||||
, mTotalRead(0)
|
||||
, mPushSource(nullptr)
|
||||
, mAttempting0RTT(false)
|
||||
, mCurrentForegroundTabOuterContentWindowId(windowId)
|
||||
, mTransactionTabId(0)
|
||||
, mIsTunnel(false)
|
||||
, mPlainTextTunnel(false)
|
||||
{
|
||||
@ -100,6 +103,11 @@ Http2Stream::Http2Stream(nsAHttpTransaction *httpTransaction,
|
||||
}
|
||||
MOZ_ASSERT(httpPriority >= 0);
|
||||
SetPriority(static_cast<uint32_t>(httpPriority));
|
||||
|
||||
nsHttpTransaction *trans = mTransaction->QueryHttpTransaction();
|
||||
if (trans) {
|
||||
mTransactionTabId = trans->TopLevelOuterContentWindowId();
|
||||
}
|
||||
}
|
||||
|
||||
Http2Stream::~Http2Stream()
|
||||
@ -1202,6 +1210,40 @@ Http2Stream::SetPriorityDependency(uint32_t newDependency, uint8_t newWeight,
|
||||
exclusive));
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
GetPriorityDependencyFromTransaction(nsHttpTransaction *trans)
|
||||
{
|
||||
MOZ_ASSERT(trans);
|
||||
|
||||
uint32_t classFlags = trans->ClassOfService();
|
||||
|
||||
if (classFlags & nsIClassOfService::UrgentStart) {
|
||||
return Http2Session::kUrgentStartGroupID;
|
||||
}
|
||||
|
||||
if (classFlags & nsIClassOfService::Leader) {
|
||||
return Http2Session::kLeaderGroupID;
|
||||
}
|
||||
|
||||
if (classFlags & nsIClassOfService::Follower) {
|
||||
return Http2Session::kFollowerGroupID;
|
||||
}
|
||||
|
||||
if (classFlags & nsIClassOfService::Speculative) {
|
||||
return Http2Session::kSpeculativeGroupID;
|
||||
}
|
||||
|
||||
if (classFlags & nsIClassOfService::Background) {
|
||||
return Http2Session::kBackgroundGroupID;
|
||||
}
|
||||
|
||||
if (classFlags & nsIClassOfService::Unblocked) {
|
||||
return Http2Session::kOtherGroupID;
|
||||
}
|
||||
|
||||
return Http2Session::kFollowerGroupID; // unmarked followers
|
||||
}
|
||||
|
||||
void
|
||||
Http2Stream::UpdatePriorityDependency()
|
||||
{
|
||||
@ -1230,27 +1272,56 @@ Http2Stream::UpdatePriorityDependency()
|
||||
// spculative bg streams depend on 9
|
||||
// urgent-start streams depend on d
|
||||
|
||||
uint32_t classFlags = trans->ClassOfService();
|
||||
mPriorityDependency = GetPriorityDependencyFromTransaction(trans);
|
||||
|
||||
if (classFlags & nsIClassOfService::Leader) {
|
||||
mPriorityDependency = Http2Session::kLeaderGroupID;
|
||||
} else if (classFlags & nsIClassOfService::Follower) {
|
||||
mPriorityDependency = Http2Session::kFollowerGroupID;
|
||||
} else if (classFlags & nsIClassOfService::Speculative) {
|
||||
mPriorityDependency = Http2Session::kSpeculativeGroupID;
|
||||
} else if (classFlags & nsIClassOfService::Background) {
|
||||
if (mTransactionTabId != mCurrentForegroundTabOuterContentWindowId &&
|
||||
mPriorityDependency != Http2Session::kUrgentStartGroupID) {
|
||||
LOG3(("Http2Stream::UpdatePriorityDependency %p "
|
||||
" depends on background group for trans %p\n",
|
||||
this, trans));
|
||||
mPriorityDependency = Http2Session::kBackgroundGroupID;
|
||||
} else if (classFlags & nsIClassOfService::Unblocked) {
|
||||
mPriorityDependency = Http2Session::kOtherGroupID;
|
||||
} else if (classFlags & nsIClassOfService::UrgentStart) {
|
||||
mPriorityDependency = Http2Session::kUrgentStartGroupID;
|
||||
} else {
|
||||
mPriorityDependency = Http2Session::kFollowerGroupID; // unmarked followers
|
||||
}
|
||||
|
||||
LOG3(("Http2Stream::UpdatePriorityDependency %p "
|
||||
"classFlags %X depends on stream 0x%X\n",
|
||||
this, classFlags, mPriorityDependency));
|
||||
"depends on stream 0x%X\n",
|
||||
this, mPriorityDependency));
|
||||
}
|
||||
|
||||
void
|
||||
Http2Stream::TopLevelOuterContentWindowIdChanged(uint64_t windowId)
|
||||
{
|
||||
LOG3(("Http2Stream::TopLevelOuterContentWindowIdChanged "
|
||||
"%p windowId=%" PRIx64 "\n",
|
||||
this, windowId));
|
||||
|
||||
mCurrentForegroundTabOuterContentWindowId = windowId;
|
||||
|
||||
if (!mSession->UseH2Deps()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Urgent start takes an absolute precedence, so don't
|
||||
// change mPriorityDependency here.
|
||||
if (mPriorityDependency == Http2Session::kUrgentStartGroupID) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mTransactionTabId != mCurrentForegroundTabOuterContentWindowId) {
|
||||
mPriorityDependency = Http2Session::kBackgroundGroupID;
|
||||
LOG3(("Http2Stream::TopLevelOuterContentWindowIdChanged %p "
|
||||
"move into background group.\n", this));
|
||||
} else {
|
||||
nsHttpTransaction *trans = mTransaction->QueryHttpTransaction();
|
||||
if (!trans) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPriorityDependency = GetPriorityDependencyFromTransaction(trans);
|
||||
LOG3(("Http2Stream::TopLevelOuterContentWindowIdChanged %p "
|
||||
"depends on stream 0x%X\n", this, mPriorityDependency));
|
||||
}
|
||||
|
||||
mSession->SendPriorityFrame(mStreamID, mPriorityDependency, mPriorityWeight);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -52,7 +52,7 @@ public:
|
||||
const static int32_t kWorstPriority = kNormalPriority + nsISupportsPriority::PRIORITY_LOWEST;
|
||||
const static int32_t kBestPriority = kNormalPriority + nsISupportsPriority::PRIORITY_HIGHEST;
|
||||
|
||||
Http2Stream(nsAHttpTransaction *, Http2Session *, int32_t);
|
||||
Http2Stream(nsAHttpTransaction *, Http2Session *, int32_t, uint64_t);
|
||||
|
||||
uint32_t StreamID() { return mStreamID; }
|
||||
Http2PushedStream *PushSource() { return mPushSource; }
|
||||
@ -170,6 +170,8 @@ public:
|
||||
|
||||
nsresult GetOriginAttributes(mozilla::OriginAttributes *oa);
|
||||
|
||||
void TopLevelOuterContentWindowIdChanged(uint64_t windowId);
|
||||
|
||||
protected:
|
||||
static void CreatePushHashKey(const nsCString &scheme,
|
||||
const nsCString &hostHeader,
|
||||
@ -347,6 +349,10 @@ private:
|
||||
|
||||
bool mAttempting0RTT;
|
||||
|
||||
uint64_t mCurrentForegroundTabOuterContentWindowId;
|
||||
|
||||
uint64_t mTransactionTabId;
|
||||
|
||||
/// connect tunnels
|
||||
public:
|
||||
bool IsTunnel() { return mIsTunnel; }
|
||||
|
@ -144,6 +144,9 @@ public:
|
||||
|
||||
// nsHttp.h version
|
||||
virtual uint32_t Version() = 0;
|
||||
|
||||
// A notification of the current active tab id change.
|
||||
virtual void TopLevelOuterContentWindowIdChanged(uint64_t windowId) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsAHttpConnection, NS_AHTTPCONNECTION_IID)
|
||||
@ -163,6 +166,7 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsAHttpConnection, NS_AHTTPCONNECTION_IID)
|
||||
MOZ_MUST_USE nsresult PushBack(const char *, uint32_t) override; \
|
||||
already_AddRefed<nsHttpConnection> TakeHttpConnection() override; \
|
||||
already_AddRefed<nsHttpConnection> HttpConnection() override; \
|
||||
void TopLevelOuterContentWindowIdChanged(uint64_t windowId) override; \
|
||||
/* \
|
||||
Thes methods below have automatic definitions that just forward the \
|
||||
function to a lower level connection object \
|
||||
|
@ -3413,6 +3413,47 @@ nsHttpConnectionMgr::ResumeReadOf(nsTArray<RefPtr<nsHttpTransaction>>* transacti
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpConnectionMgr::NotifyConnectionOfWindowIdChange(uint64_t previousWindowId)
|
||||
{
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
|
||||
nsTArray<RefPtr<nsHttpTransaction>> *transactions = nullptr;
|
||||
nsTArray<RefPtr<nsAHttpConnection>> connections;
|
||||
|
||||
auto addConnectionHelper =
|
||||
[&connections](nsTArray<RefPtr<nsHttpTransaction>> *trans) {
|
||||
if (!trans) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto t : *trans) {
|
||||
RefPtr<nsAHttpConnection> conn = t->Connection();
|
||||
if (conn && !connections.Contains(conn)) {
|
||||
connections.AppendElement(conn);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Get unthrottled transactions with the previous and current window id.
|
||||
transactions = mActiveTransactions[false].Get(previousWindowId);
|
||||
addConnectionHelper(transactions);
|
||||
transactions =
|
||||
mActiveTransactions[false].Get(mCurrentTopLevelOuterContentWindowId);
|
||||
addConnectionHelper(transactions);
|
||||
|
||||
// Get throttled transactions with the previous and current window id.
|
||||
transactions = mActiveTransactions[true].Get(previousWindowId);
|
||||
addConnectionHelper(transactions);
|
||||
transactions =
|
||||
mActiveTransactions[true].Get(mCurrentTopLevelOuterContentWindowId);
|
||||
addConnectionHelper(transactions);
|
||||
|
||||
for (auto conn : connections) {
|
||||
conn->TopLevelOuterContentWindowIdChanged(mCurrentTopLevelOuterContentWindowId);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpConnectionMgr::OnMsgUpdateCurrentTopLevelOuterContentWindowId(
|
||||
int32_t aLoading, ARefBase *param)
|
||||
@ -3429,8 +3470,11 @@ nsHttpConnectionMgr::OnMsgUpdateCurrentTopLevelOuterContentWindowId(
|
||||
bool activeTabWasLoading = mActiveTabTransactionsExist;
|
||||
bool activeTabIdChanged = mCurrentTopLevelOuterContentWindowId != winId;
|
||||
|
||||
uint64_t previousWindowId = mCurrentTopLevelOuterContentWindowId;
|
||||
mCurrentTopLevelOuterContentWindowId = winId;
|
||||
|
||||
NotifyConnectionOfWindowIdChange(previousWindowId);
|
||||
|
||||
LOG(("nsHttpConnectionMgr::OnMsgUpdateCurrentTopLevelOuterContentWindowId"
|
||||
" id=%" PRIx64 "\n",
|
||||
mCurrentTopLevelOuterContentWindowId));
|
||||
@ -4898,6 +4942,12 @@ ConnectionHandle::HttpConnection()
|
||||
return rv.forget();
|
||||
}
|
||||
|
||||
void
|
||||
ConnectionHandle::TopLevelOuterContentWindowIdChanged(uint64_t windowId)
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
// nsConnectionEntry
|
||||
|
||||
nsHttpConnectionMgr::
|
||||
|
@ -242,6 +242,11 @@ public:
|
||||
// NOTE: relatively expensive to call, there are two hashtable lookups.
|
||||
bool IsConnEntryUnderPressure(nsHttpConnectionInfo*);
|
||||
|
||||
uint64_t CurrentTopLevelOuterContentWindowId()
|
||||
{
|
||||
return mCurrentTopLevelOuterContentWindowId;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual ~nsHttpConnectionMgr();
|
||||
|
||||
@ -760,6 +765,11 @@ private:
|
||||
nsTArray<RefPtr<PendingTransactionInfo>>*
|
||||
GetTransactionPendingQHelper(nsConnectionEntry *ent, nsAHttpTransaction *trans);
|
||||
|
||||
// When current active tab is changed, this function uses
|
||||
// |previousWindowId| to select background transactions and
|
||||
// mCurrentTopLevelOuterContentWindowId| to select foreground transactions.
|
||||
// Then, it notifies selected transactions' connection of the new active tab id.
|
||||
void NotifyConnectionOfWindowIdChange(uint64_t previousWindowId);
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsHttpConnectionMgr::nsHalfOpenSocket, NS_HALFOPENSOCKET_IID)
|
||||
|
Loading…
Reference in New Issue
Block a user