#559: M1550498 M1548822 M1540759(partial) M1528481(+WeakPtr for Http2Stream) M1555523 M1552541

This commit is contained in:
Cameron Kaiser 2019-07-04 13:31:06 -07:00
parent fa8b0e6736
commit 4649687068
10 changed files with 74 additions and 47 deletions

View File

@ -2126,11 +2126,13 @@ nsGlobalWindow::WouldReuseInnerWindow(nsIDocument* aNewDocument)
} }
bool equal; bool equal;
if (NS_SUCCEEDED(mDoc->NodePrincipal()->Equals(aNewDocument->NodePrincipal(), if (NS_SUCCEEDED(
&equal)) && BasePrincipal::Cast(mDoc->NodePrincipal())->
equal) { EqualsConsideringDomain(aNewDocument->NodePrincipal(),
&equal))) {
// Return the result. If true (bug 1552541):
// The origin is the same. // The origin is the same.
return true; return equal;
} }
return false; return false;

View File

@ -1673,8 +1673,9 @@ Http2Session::RecvPushPromise(Http2Session *self)
RefPtr<Http2PushTransactionBuffer> transactionBuffer = RefPtr<Http2PushTransactionBuffer> transactionBuffer =
new Http2PushTransactionBuffer(); new Http2PushTransactionBuffer();
transactionBuffer->SetConnection(self); transactionBuffer->SetConnection(self);
Http2PushedStream *pushedStream = nsAutoPtr<Http2PushedStream> pushedStream(
new Http2PushedStream(transactionBuffer, self, associatedStream, promisedID); new Http2PushedStream(transactionBuffer, self, associatedStream, promisedID)
);
rv = pushedStream->ConvertPushHeaders(&self->mDecompressor, rv = pushedStream->ConvertPushHeaders(&self->mDecompressor,
self->mDecompressBuffer, self->mDecompressBuffer,
@ -1683,7 +1684,6 @@ Http2Session::RecvPushPromise(Http2Session *self)
if (rv == NS_ERROR_NOT_IMPLEMENTED) { if (rv == NS_ERROR_NOT_IMPLEMENTED) {
LOG3(("Http2Session::PushPromise Semantics not Implemented\n")); LOG3(("Http2Session::PushPromise Semantics not Implemented\n"));
self->GenerateRstStream(REFUSED_STREAM_ERROR, promisedID); self->GenerateRstStream(REFUSED_STREAM_ERROR, promisedID);
delete pushedStream;
return NS_OK; return NS_OK;
} }
@ -1691,7 +1691,6 @@ Http2Session::RecvPushPromise(Http2Session *self)
// This means the decompression completed ok, but there was a problem with // This means the decompression completed ok, but there was a problem with
// the decoded headers. Reset the stream and go away. // the decoded headers. Reset the stream and go away.
self->GenerateRstStream(PROTOCOL_ERROR, promisedID); self->GenerateRstStream(PROTOCOL_ERROR, promisedID);
delete pushedStream;
return NS_OK; return NS_OK;
} else if (NS_FAILED(rv)) { } else if (NS_FAILED(rv)) {
// This is fatal to the session. // This is fatal to the session.
@ -1699,14 +1698,17 @@ Http2Session::RecvPushPromise(Http2Session *self)
return rv; return rv;
} }
WeakPtr<Http2Stream> pushedWeak = pushedStream.forget();
// Ownership of the pushed stream is by the transaction hash, just as it // Ownership of the pushed stream is by the transaction hash, just as it
// is for a client initiated stream. Errors that aren't fatal to the // is for a client initiated stream. Errors that aren't fatal to the
// whole session must call cleanupStream() after this point in order // whole session must call cleanupStream() after this point in order
// to remove the stream from that hash. // to remove the stream from that hash.
self->mStreamTransactionHash.Put(transactionBuffer, pushedStream); self->mStreamTransactionHash.Put(transactionBuffer, pushedWeak);
self->mPushedStreams.AppendElement(pushedStream); self->mPushedStreams.AppendElement(
static_cast<Http2PushedStream*>(pushedWeak.get()));
if (self->RegisterStreamID(pushedStream, promisedID) == kDeadStreamID) { if (self->RegisterStreamID(pushedWeak, promisedID) == kDeadStreamID) {
LOG3(("Http2Session::RecvPushPromise registerstreamid failed\n")); LOG3(("Http2Session::RecvPushPromise registerstreamid failed\n"));
self->mGoAwayReason = INTERNAL_ERROR; self->mGoAwayReason = INTERNAL_ERROR;
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
@ -1718,23 +1720,24 @@ Http2Session::RecvPushPromise(Http2Session *self)
// Fake the request side of the pushed HTTP transaction. Sets up hash // Fake the request side of the pushed HTTP transaction. Sets up hash
// key and origin // key and origin
uint32_t notUsed; uint32_t notUsed;
pushedStream->ReadSegments(nullptr, 1, &notUsed); pushedWeak->ReadSegments(nullptr, 1, &notUsed);
nsAutoCString key; nsAutoCString key;
if (!pushedStream->GetHashKey(key)) { if (!static_cast<Http2PushedStream*>(pushedWeak.get())->GetHashKey(key)) {
LOG3(("Http2Session::RecvPushPromise one of :authority :scheme :path missing from push\n")); LOG3(("Http2Session::RecvPushPromise one of :authority :scheme :path missing from push\n"));
self->CleanupStream(pushedStream, NS_ERROR_FAILURE, PROTOCOL_ERROR); self->CleanupStream(pushedWeak, NS_ERROR_FAILURE, PROTOCOL_ERROR);
self->ResetDownstreamState(); self->ResetDownstreamState();
return NS_OK; return NS_OK;
} }
// does the pushed origin belong on this connection?
RefPtr<nsStandardURL> associatedURL, pushedURL; RefPtr<nsStandardURL> associatedURL, pushedURL;
rv = Http2Stream::MakeOriginURL(associatedStream->Origin(), associatedURL); rv = Http2Stream::MakeOriginURL(associatedStream->Origin(), associatedURL);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
rv = Http2Stream::MakeOriginURL(pushedStream->Origin(), pushedURL); rv = Http2Stream::MakeOriginURL(pushedWeak->Origin(), pushedURL);
} }
LOG3(("Http2Session::RecvPushPromise %p checking %s == %s", self, LOG3(("Http2Session::RecvPushPromise %p checking %s == %s", self,
associatedStream->Origin().get(), pushedStream->Origin().get())); associatedStream->Origin().get(), pushedWeak->Origin().get()));
bool match = false; bool match = false;
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
rv = associatedURL->Equals(pushedURL, &match); rv = associatedURL->Equals(pushedURL, &match);
@ -1742,36 +1745,38 @@ Http2Session::RecvPushPromise(Http2Session *self)
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
// Fallback to string equality of origins. This won't be guaranteed to be as // Fallback to string equality of origins. This won't be guaranteed to be as
// liberal as we want it to be, but it will at least be safe // liberal as we want it to be, but it will at least be safe
match = associatedStream->Origin().Equals(pushedStream->Origin()); match = associatedStream->Origin().Equals(pushedWeak->Origin());
} }
if (!match) { if (!match) {
LOG3(("Http2Session::RecvPushPromise %p pushed stream mismatched origin " LOG3(("Http2Session::RecvPushPromise %p pushed stream mismatched origin "
"associated origin %s .. pushed origin %s\n", self, "associated origin %s .. pushed origin %s\n", self,
associatedStream->Origin().get(), pushedStream->Origin().get())); associatedStream->Origin().get(), pushedWeak->Origin().get()));
self->CleanupStream(pushedStream, NS_ERROR_FAILURE, REFUSED_STREAM_ERROR); self->CleanupStream(pushedWeak, NS_ERROR_FAILURE, REFUSED_STREAM_ERROR);
self->ResetDownstreamState(); self->ResetDownstreamState();
return NS_OK; return NS_OK;
} }
if (pushedStream->TryOnPush()) { if (static_cast<Http2PushedStream*>(pushedWeak.get())->TryOnPush()) {
LOG3(("Http2Session::RecvPushPromise %p channel implements nsIHttpPushListener " LOG3(("Http2Session::RecvPushPromise %p channel implements nsIHttpPushListener "
"stream %p will not be placed into session cache.\n", self, pushedStream)); "stream %p will not be placed into session cache.\n", self, pushedWeak.get()));
} else { } else {
LOG3(("Http2Session::RecvPushPromise %p place stream into session cache\n", self)); LOG3(("Http2Session::RecvPushPromise %p place stream into session cache\n", self));
if (!cache->RegisterPushedStreamHttp2(key, pushedStream)) { if (!cache->RegisterPushedStreamHttp2(
key, static_cast<Http2PushedStream*>(pushedWeak.get()))) {
// This only happens if they've already pushed us this item.
LOG3(("Http2Session::RecvPushPromise registerPushedStream Failed\n")); LOG3(("Http2Session::RecvPushPromise registerPushedStream Failed\n"));
self->CleanupStream(pushedStream, NS_ERROR_FAILURE, INTERNAL_ERROR); self->CleanupStream(pushedWeak, NS_ERROR_FAILURE, INTERNAL_ERROR);
self->ResetDownstreamState(); self->ResetDownstreamState();
return NS_OK; return NS_OK;
} }
} }
pushedStream->SetHTTPState(Http2Stream::RESERVED_BY_REMOTE); pushedWeak->SetHTTPState(Http2Stream::RESERVED_BY_REMOTE);
static_assert(Http2Stream::kWorstPriority >= 0, static_assert(Http2Stream::kWorstPriority >= 0,
"kWorstPriority out of range"); "kWorstPriority out of range");
uint8_t priorityWeight = (nsISupportsPriority::PRIORITY_LOWEST + 1) - uint8_t priorityWeight = (nsISupportsPriority::PRIORITY_LOWEST + 1) -
(Http2Stream::kWorstPriority - Http2Stream::kNormalPriority); (Http2Stream::kWorstPriority - Http2Stream::kNormalPriority);
pushedStream->SetPriority(Http2Stream::kWorstPriority); pushedWeak->SetPriority(Http2Stream::kWorstPriority);
self->GeneratePriority(promisedID, priorityWeight); self->GeneratePriority(promisedID, priorityWeight);
self->ResetDownstreamState(); self->ResetDownstreamState();
return NS_OK; return NS_OK;

View File

@ -13,6 +13,7 @@
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
#include "nsAHttpTransaction.h" #include "nsAHttpTransaction.h"
#include "nsISupportsPriority.h" #include "nsISupportsPriority.h"
#include "mozilla/WeakPtr.h"
class nsStandardURL; class nsStandardURL;
@ -25,8 +26,10 @@ class Http2Decompressor;
class Http2Stream class Http2Stream
: public nsAHttpSegmentReader : public nsAHttpSegmentReader
, public nsAHttpSegmentWriter , public nsAHttpSegmentWriter
, public SupportsWeakPtr<Http2Stream>
{ {
public: public:
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(Http2Stream)
NS_DECL_NSAHTTPSEGMENTREADER NS_DECL_NSAHTTPSEGMENTREADER
NS_DECL_NSAHTTPSEGMENTWRITER NS_DECL_NSAHTTPSEGMENTWRITER

View File

@ -553,7 +553,14 @@ void
HttpChannelChild::DoOnStartRequest(nsIRequest* aRequest, nsISupports* aContext) HttpChannelChild::DoOnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
{ {
LOG(("HttpChannelChild::DoOnStartRequest [this=%p]\n", this)); LOG(("HttpChannelChild::DoOnStartRequest [this=%p]\n", this));
nsresult rv = mListener->OnStartRequest(aRequest, aContext); nsresult rv;
if (MOZ_LIKELY(mListener)) {
nsCOMPtr<nsIStreamListener> listener(mListener);
rv = listener->OnStartRequest(aRequest, aContext);
} else {
rv = NS_ERROR_UNEXPECTED;
}
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
Cancel(rv); Cancel(rv);
return; return;
@ -817,9 +824,12 @@ HttpChannelChild::DoOnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
if (mCanceled) if (mCanceled)
return; return;
nsresult rv = mListener->OnDataAvailable(aRequest, aContext, aStream, offset, count); if (MOZ_LIKELY(mListener)) {
if (NS_FAILED(rv)) { nsCOMPtr<nsIStreamListener> listener(mListener);
Cancel(rv); nsresult rv = listener->OnDataAvailable(aRequest, aContext, aStream, offset, count);
if (NS_FAILED(rv)) {
Cancel(rv);
}
} }
} }
@ -982,7 +992,10 @@ HttpChannelChild::DoOnStopRequest(nsIRequest* aRequest, nsresult aChannelStatus,
nsChannelClassifier::SetBlockedTrackingContent(this); nsChannelClassifier::SetBlockedTrackingContent(this);
} }
mListener->OnStopRequest(aRequest, aContext, mStatus); if (MOZ_LIKELY(mListener)) {
nsCOMPtr<nsIStreamListener> listener(mListener);
listener->OnStopRequest(aRequest, aContext, mStatus);
}
mListener = 0; mListener = 0;
mListenerContext = 0; mListenerContext = 0;

View File

@ -6008,7 +6008,8 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult st
if (mListener) { if (mListener) {
MOZ_ASSERT(!mOnStartRequestCalled, MOZ_ASSERT(!mOnStartRequestCalled,
"We should not call OnStartRequest twice."); "We should not call OnStartRequest twice.");
mListener->OnStartRequest(this, mListenerContext); nsCOMPtr<nsIStreamListener> listener(mListener);
listener->OnStartRequest(this, mListenerContext);
mOnStartRequestCalled = true; mOnStartRequestCalled = true;
} else { } else {
NS_WARNING("OnStartRequest skipped because of null listener"); NS_WARNING("OnStartRequest skipped because of null listener");

View File

@ -375,8 +375,12 @@ nsHttpConnectionMgr::VerifyTraffic()
nsresult nsresult
nsHttpConnectionMgr::DoShiftReloadConnectionCleanup(nsHttpConnectionInfo *aCI) nsHttpConnectionMgr::DoShiftReloadConnectionCleanup(nsHttpConnectionInfo *aCI)
{ {
RefPtr<nsHttpConnectionInfo> ci;
if (aCI) {
ci = aCI->Clone();
}
return PostEvent(&nsHttpConnectionMgr::OnMsgDoShiftReloadConnectionCleanup, return PostEvent(&nsHttpConnectionMgr::OnMsgDoShiftReloadConnectionCleanup,
0, aCI); 0, ci);
} }
class SpeculativeConnectArgs : public ARefBase class SpeculativeConnectArgs : public ARefBase
@ -505,9 +509,13 @@ nsHttpConnectionMgr::UpdateParam(nsParamName name, uint16_t value)
} }
nsresult nsresult
nsHttpConnectionMgr::ProcessPendingQ(nsHttpConnectionInfo *ci) nsHttpConnectionMgr::ProcessPendingQ(nsHttpConnectionInfo *aCI)
{ {
LOG(("nsHttpConnectionMgr::ProcessPendingQ [ci=%s]\n", ci->HashKey().get())); LOG(("nsHttpConnectionMgr::ProcessPendingQ [ci=%s]\n", aCI->HashKey().get()));
RefPtr<nsHttpConnectionInfo> ci;
if (aCI) {
ci = aCI->Clone();
}
return PostEvent(&nsHttpConnectionMgr::OnMsgProcessPendingQ, 0, ci); return PostEvent(&nsHttpConnectionMgr::OnMsgProcessPendingQ, 0, ci);
} }

View File

@ -2233,7 +2233,7 @@ nsHttpHandler::SpeculativeConnectInternal(nsIURI *aURI,
nsAutoCString username; nsAutoCString username;
aURI->GetUsername(username); aURI->GetUsername(username);
nsHttpConnectionInfo *ci = RefPtr<nsHttpConnectionInfo> ci =
new nsHttpConnectionInfo(host, port, EmptyCString(), username, nullptr, usingSSL); new nsHttpConnectionInfo(host, port, EmptyCString(), username, nullptr, usingSSL);
ci->SetAnonymous(anonymous); ci->SetAnonymous(anonymous);

View File

@ -233,7 +233,8 @@ public:
uint32_t caps = 0) uint32_t caps = 0)
{ {
TickleWifi(callbacks); TickleWifi(callbacks);
return mConnMgr->SpeculativeConnect(ci, callbacks, caps); RefPtr<nsHttpConnectionInfo> clone = ci->Clone();
return mConnMgr->SpeculativeConnect(clone, callbacks, caps);
} }
// Alternate Services Maps are main thread only // Alternate Services Maps are main thread only

View File

@ -3782,12 +3782,9 @@ public class Tokenizer implements Locator {
tokenHandler.characters( tokenHandler.characters(
Tokenizer.LT_SOLIDUS, 0, 2); Tokenizer.LT_SOLIDUS, 0, 2);
emitStrBuf(); emitStrBuf();
if (c == '\u0000') { cstart = pos; // don't drop the
emitReplacementCharacter(buf, pos); // character
} else { reconsume = true;
cstart = pos; // don't drop the
// character
}
state = transition(state, returnState, reconsume, pos); state = transition(state, returnState, reconsume, pos);
continue stateloop; continue stateloop;
} }

View File

@ -2048,11 +2048,8 @@ nsHtml5Tokenizer::stateLoop(int32_t state, char16_t c, int32_t pos, char16_t* bu
default: { default: {
tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2); tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2);
emitStrBuf(); emitStrBuf();
if (c == '\0') { cstart = pos;
emitReplacementCharacter(buf, pos); reconsume = true;
} else {
cstart = pos;
}
state = P::transition(mViewSource, returnState, reconsume, pos); state = P::transition(mViewSource, returnState, reconsume, pos);
NS_HTML5_CONTINUE(stateloop); NS_HTML5_CONTINUE(stateloop);
} }