diff options
author | wicknix <39230578+wicknix@users.noreply.github.com> | 2019-04-15 18:58:07 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-15 18:58:07 -0500 |
commit | 5a1843c9f9e323627f9c35529e6a8c853d4dbb0d (patch) | |
tree | 62de3cd7cb8a6f75e568863bb73ca2deb80d87a9 /netwerk/protocol/http | |
parent | 065f6f9e5ebc1ed6cfaadaf7851b6021fa94a013 (diff) | |
parent | 095ea556855b38138e39e713f482eb440f7da9b2 (diff) | |
download | UXP-5a1843c9f9e323627f9c35529e6a8c853d4dbb0d.tar UXP-5a1843c9f9e323627f9c35529e6a8c853d4dbb0d.tar.gz UXP-5a1843c9f9e323627f9c35529e6a8c853d4dbb0d.tar.lz UXP-5a1843c9f9e323627f9c35529e6a8c853d4dbb0d.tar.xz UXP-5a1843c9f9e323627f9c35529e6a8c853d4dbb0d.zip |
Merge pull request #1 from MoonchildProductions/master
keep up with mc
Diffstat (limited to 'netwerk/protocol/http')
28 files changed, 453 insertions, 631 deletions
diff --git a/netwerk/protocol/http/ASpdySession.cpp b/netwerk/protocol/http/ASpdySession.cpp index f22c326d1..d5d98804d 100644 --- a/netwerk/protocol/http/ASpdySession.cpp +++ b/netwerk/protocol/http/ASpdySession.cpp @@ -45,8 +45,6 @@ ASpdySession::NewSpdySession(uint32_t version, // from a list provided in the SERVER HELLO filtered by our acceptable // versions, so there is no risk of the server ignoring our prefs. - Telemetry::Accumulate(Telemetry::SPDY_VERSION2, version); - return new Http2Session(aTransport, version, attemptingEarlyData); } diff --git a/netwerk/protocol/http/AlternateServices.cpp b/netwerk/protocol/http/AlternateServices.cpp index b3e6babe3..ee2fa9331 100644 --- a/netwerk/protocol/http/AlternateServices.cpp +++ b/netwerk/protocol/http/AlternateServices.cpp @@ -654,8 +654,13 @@ private: { nsID channelId; nsLoadFlags flags; + + nsContentPolicyType contentPolicyType = + loadInfo ? loadInfo->GetExternalContentPolicyType() + : nsIContentPolicy::TYPE_OTHER; + if (NS_FAILED(gHttpHandler->NewChannelId(&channelId)) || - NS_FAILED(chan->Init(uri, caps, nullptr, 0, nullptr, channelId)) || + NS_FAILED(chan->Init(uri, caps, nullptr, 0, nullptr, channelId, contentPolicyType)) || NS_FAILED(chan->SetAllowAltSvc(false)) || NS_FAILED(chan->SetRedirectMode(nsIHttpChannelInternal::REDIRECT_MODE_ERROR)) || NS_FAILED(chan->SetLoadInfo(loadInfo)) || diff --git a/netwerk/protocol/http/Http2Compression.cpp b/netwerk/protocol/http/Http2Compression.cpp index 1b4603e1a..9206f8b4c 100644 --- a/netwerk/protocol/http/Http2Compression.cpp +++ b/netwerk/protocol/http/Http2Compression.cpp @@ -292,12 +292,6 @@ Http2BaseCompressor::Http2BaseCompressor() Http2BaseCompressor::~Http2BaseCompressor() { - if (mPeakSize) { - Telemetry::Accumulate(mPeakSizeID, mPeakSize); - } - if (mPeakCount) { - Telemetry::Accumulate(mPeakCountID, mPeakCount); - } UnregisterStrongMemoryReporter(mDynamicReporter); mDynamicReporter->mCompressor = nullptr; mDynamicReporter = nullptr; @@ -336,16 +330,6 @@ Http2BaseCompressor::MakeRoom(uint32_t amount, const char *direction) bytesEvicted += mHeaderTable[index]->Size(); mHeaderTable.RemoveElement(); } - - if (!strcmp(direction, "decompressor")) { - Telemetry::Accumulate(Telemetry::HPACK_ELEMENTS_EVICTED_DECOMPRESSOR, countEvicted); - Telemetry::Accumulate(Telemetry::HPACK_BYTES_EVICTED_DECOMPRESSOR, bytesEvicted); - Telemetry::Accumulate(Telemetry::HPACK_BYTES_EVICTED_RATIO_DECOMPRESSOR, (uint32_t)((100.0 * (double)bytesEvicted) / (double)amount)); - } else { - Telemetry::Accumulate(Telemetry::HPACK_ELEMENTS_EVICTED_COMPRESSOR, countEvicted); - Telemetry::Accumulate(Telemetry::HPACK_BYTES_EVICTED_COMPRESSOR, bytesEvicted); - Telemetry::Accumulate(Telemetry::HPACK_BYTES_EVICTED_RATIO_COMPRESSOR, (uint32_t)((100.0 * (double)bytesEvicted) / (double)amount)); - } } void @@ -418,7 +402,7 @@ Http2Decompressor::DecodeHeaderBlock(const uint8_t *data, uint32_t datalen, nsresult rv = NS_OK; nsresult softfail_rv = NS_OK; - while (NS_SUCCEEDED(rv) && (mOffset < datalen)) { + while (NS_SUCCEEDED(rv) && (mOffset < mDataLen)) { bool modifiesTable = true; if (mData[mOffset] & 0x80) { rv = DoIndexed(); @@ -700,6 +684,11 @@ nsresult Http2Decompressor::DecodeFinalHuffmanCharacter(const HuffmanIncomingTable *table, uint8_t &c, uint8_t &bitsLeft) { + MOZ_ASSERT(mOffset <= mDataLen); + if (mOffset > mDataLen) { + NS_WARNING("DecodeFinalHuffmanCharacter trying to read beyond end of buffer"); + return NS_ERROR_FAILURE; + } uint8_t mask = (1 << bitsLeft) - 1; uint8_t idx = mData[mOffset - 1] & mask; idx <<= (8 - bitsLeft); @@ -737,6 +726,7 @@ Http2Decompressor::DecodeFinalHuffmanCharacter(const HuffmanIncomingTable *table uint8_t Http2Decompressor::ExtractByte(uint8_t bitsLeft, uint32_t &bytesConsumed) { + MOZ_DIAGNOSTIC_ASSERT(mOffset < mDataLen); uint8_t rv; if (bitsLeft) { @@ -766,8 +756,8 @@ Http2Decompressor::DecodeHuffmanCharacter(const HuffmanIncomingTable *table, uint8_t idx = ExtractByte(bitsLeft, bytesConsumed); if (table->IndexHasANextTable(idx)) { - if (bytesConsumed >= mDataLen) { - if (!bitsLeft || (bytesConsumed > mDataLen)) { + if (mOffset >= mDataLen) { + if (!bitsLeft || (mOffset > mDataLen)) { // TODO - does this get me into trouble in the new world? // No info left in input to try to consume, we're done LOG(("DecodeHuffmanCharacter all out of bits to consume, can't chain")); @@ -908,6 +898,13 @@ Http2Decompressor::DoLiteralInternal(nsACString &name, nsACString &value, return rv; } + // sanity check + if (mOffset >= mDataLen) { + NS_WARNING("Http2 Decompressor ran out of data"); + // This is session-fatal + return NS_ERROR_FAILURE; + } + bool isHuffmanEncoded; if (!index) { @@ -935,6 +932,13 @@ Http2Decompressor::DoLiteralInternal(nsACString &name, nsACString &value, return rv; } + // sanity check + if (mOffset >= mDataLen) { + NS_WARNING("Http2 Decompressor ran out of data"); + // This is session-fatal + return NS_ERROR_FAILURE; + } + // now the value uint32_t valueLen; isHuffmanEncoded = mData[mOffset] & (1 << 7); diff --git a/netwerk/protocol/http/Http2Session.cpp b/netwerk/protocol/http/Http2Session.cpp index 4f350af83..4a178f091 100644 --- a/netwerk/protocol/http/Http2Session.cpp +++ b/netwerk/protocol/http/Http2Session.cpp @@ -168,13 +168,6 @@ Http2Session::~Http2Session() this, mDownstreamState)); Shutdown(); - - Telemetry::Accumulate(Telemetry::SPDY_PARALLEL_STREAMS, mConcurrentHighWater); - Telemetry::Accumulate(Telemetry::SPDY_REQUEST_PER_CONN, (mNextStreamID - 1) / 2); - Telemetry::Accumulate(Telemetry::SPDY_SERVER_INITIATED_STREAMS, - mServerPushedResources); - Telemetry::Accumulate(Telemetry::SPDY_GOAWAY_LOCAL, mClientGoAwayReason); - Telemetry::Accumulate(Telemetry::SPDY_GOAWAY_PEER, mPeerGoAwayReason); } void @@ -1508,13 +1501,11 @@ Http2Session::RecvSettings(Http2Session *self) case SETTINGS_TYPE_MAX_CONCURRENT: self->mMaxConcurrent = value; - Telemetry::Accumulate(Telemetry::SPDY_SETTINGS_MAX_STREAMS, value); self->ProcessPending(); break; case SETTINGS_TYPE_INITIAL_WINDOW: { - Telemetry::Accumulate(Telemetry::SPDY_SETTINGS_IW, value >> 10); int32_t delta = value - self->mServerInitialStreamWindow; self->mServerInitialStreamWindow = value; @@ -2494,8 +2485,6 @@ Http2Session::ReadyToProcessDataFrame(enum internalStateType newState) newState == DISCARDING_DATA_FRAME_PADDING); ChangeDownstreamState(newState); - Telemetry::Accumulate(Telemetry::SPDY_CHUNK_RECVD, - mInputFrameDataSize >> 10); mLastDataReadEpoch = mLastReadEpoch; if (!mInputFrameID) { diff --git a/netwerk/protocol/http/Http2Stream.cpp b/netwerk/protocol/http/Http2Stream.cpp index 7a8f96855..581ebe016 100644 --- a/netwerk/protocol/http/Http2Stream.cpp +++ b/netwerk/protocol/http/Http2Stream.cpp @@ -21,7 +21,6 @@ #include "Http2Push.h" #include "TunnelUtils.h" -#include "mozilla/Telemetry.h" #include "nsAlgorithm.h" #include "nsHttp.h" #include "nsHttpHandler.h" @@ -658,16 +657,7 @@ Http2Stream::GenerateOpen() outputOffset += frameLen; } - Telemetry::Accumulate(Telemetry::SPDY_SYN_SIZE, compressedData.Length()); - - // The size of the input headers is approximate - uint32_t ratio = - compressedData.Length() * 100 / - (11 + requestURI.Length() + - mFlatHttpRequestHeaders.Length()); - mFlatHttpRequestHeaders.Truncate(); - Telemetry::Accumulate(Telemetry::SPDY_SYN_RATIO, ratio); return NS_OK; } @@ -984,7 +974,7 @@ Http2Stream::GenerateDataFrameHeader(uint32_t dataLength, bool lastFrame) } // ConvertResponseHeaders is used to convert the response headers -// into HTTP/1 format and report some telemetry +// into HTTP/1 format nsresult Http2Stream::ConvertResponseHeaders(Http2Decompressor *decompressor, nsACString &aHeadersIn, @@ -1025,13 +1015,6 @@ Http2Stream::ConvertResponseHeaders(Http2Decompressor *decompressor, return NS_ERROR_ILLEGAL_VALUE; } - if (aHeadersIn.Length() && aHeadersOut.Length()) { - Telemetry::Accumulate(Telemetry::SPDY_SYN_REPLY_SIZE, aHeadersIn.Length()); - uint32_t ratio = - aHeadersIn.Length() * 100 / aHeadersOut.Length(); - Telemetry::Accumulate(Telemetry::SPDY_SYN_REPLY_RATIO, ratio); - } - // The decoding went ok. Now we can customize and clean up. aHeadersIn.Truncate(); @@ -1047,7 +1030,7 @@ Http2Stream::ConvertResponseHeaders(Http2Decompressor *decompressor, } // ConvertPushHeaders is used to convert the pushed request headers -// into HTTP/1 format and report some telemetry +// into HTTP/1 format nsresult Http2Stream::ConvertPushHeaders(Http2Decompressor *decompressor, nsACString &aHeadersIn, diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index d161f9a43..86e177e71 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -49,7 +49,6 @@ #include "LoadInfo.h" #include "nsNullPrincipal.h" #include "nsISSLSocketControl.h" -#include "mozilla/Telemetry.h" #include "nsIURL.h" #include "nsIConsoleService.h" #include "mozilla/BinarySearch.h" @@ -152,7 +151,8 @@ HttpBaseChannel::Init(nsIURI *aURI, nsProxyInfo *aProxyInfo, uint32_t aProxyResolveFlags, nsIURI *aProxyURI, - const nsID& aChannelId) + const nsID& aChannelId, + nsContentPolicyType aContentPolicyType) { LOG(("HttpBaseChannel::Init [this=%p]\n", this)); @@ -201,7 +201,7 @@ HttpBaseChannel::Init(nsIURI *aURI, rv = mRequestHead.SetHeader(nsHttp::Host, hostLine); if (NS_FAILED(rv)) return rv; - rv = gHttpHandler->AddStandardRequestHeaders(&mRequestHead, isHTTPS); + rv = gHttpHandler->AddStandardRequestHeaders(&mRequestHead, isHTTPS, aContentPolicyType); if (NS_FAILED(rv)) return rv; nsAutoCString type; @@ -997,17 +997,6 @@ HttpBaseChannel::DoApplyContentConversions(nsIStreamListener* aNextListener, } LOG(("converter removed '%s' content-encoding\n", val)); - if (gHttpHandler->IsTelemetryEnabled()) { - int mode = 0; - if (from.Equals("gzip") || from.Equals("x-gzip")) { - mode = 1; - } else if (from.Equals("deflate") || from.Equals("x-deflate")) { - mode = 2; - } else if (from.Equals("br")) { - mode = 3; - } - Telemetry::Accumulate(Telemetry::HTTP_CONTENT_ENCODING, mode); - } nextListener = converter; } else { @@ -1667,13 +1656,7 @@ HttpBaseChannel::SetRequestHeader(const nsACString& aHeader, return NS_ERROR_INVALID_ARG; } - nsHttpAtom atom = nsHttp::ResolveAtom(flatHeader.get()); - if (!atom) { - NS_WARNING("failed to resolve atom"); - return NS_ERROR_NOT_AVAILABLE; - } - - return mRequestHead.SetHeader(atom, flatValue, aMerge); + return mRequestHead.SetHeader(aHeader, flatValue, aMerge); } NS_IMETHODIMP @@ -1690,13 +1673,7 @@ HttpBaseChannel::SetEmptyRequestHeader(const nsACString& aHeader) return NS_ERROR_INVALID_ARG; } - nsHttpAtom atom = nsHttp::ResolveAtom(flatHeader.get()); - if (!atom) { - NS_WARNING("failed to resolve atom"); - return NS_ERROR_NOT_AVAILABLE; - } - - return mRequestHead.SetEmptyHeader(atom); + return mRequestHead.SetEmptyHeader(aHeader); } NS_IMETHODIMP @@ -1752,7 +1729,7 @@ HttpBaseChannel::SetResponseHeader(const nsACString& header, mResponseHeadersModified = true; - return mResponseHead->SetHeader(atom, value, merge); + return mResponseHead->SetHeader(header, value, merge); } NS_IMETHODIMP @@ -3690,14 +3667,17 @@ HttpBaseChannel::GetPerformance() return nullptr; } - // We only add to the document's performance object if it has the same - // principal as the one triggering the load. This is to prevent navigations - // triggered _by_ the iframe from showing up in the parent document's - // performance entries if they have different origins. if (!mLoadInfo->TriggeringPrincipal()->Equals(loadingDocument->NodePrincipal())) { return nullptr; } + if (mLoadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_SUBDOCUMENT && + !mLoadInfo->GetIsFromProcessingFrameAttributes()) { + // We only report loads caused by processing the attributes of the + // browsing context container. + return nullptr; + } + nsCOMPtr<nsPIDOMWindowInner> innerWindow = loadingDocument->GetInnerWindow(); if (!innerWindow) { return nullptr; diff --git a/netwerk/protocol/http/HttpBaseChannel.h b/netwerk/protocol/http/HttpBaseChannel.h index 9aa696a70..8def0f23c 100644 --- a/netwerk/protocol/http/HttpBaseChannel.h +++ b/netwerk/protocol/http/HttpBaseChannel.h @@ -99,7 +99,8 @@ public: virtual nsresult Init(nsIURI *aURI, uint32_t aCaps, nsProxyInfo *aProxyInfo, uint32_t aProxyResolveFlags, nsIURI *aProxyURI, - const nsID& aChannelId); + const nsID& aChannelId, + nsContentPolicyType aContentPolicyType); // nsIRequest NS_IMETHOD GetName(nsACString& aName) override; diff --git a/netwerk/protocol/http/PHttpChannelParams.h b/netwerk/protocol/http/PHttpChannelParams.h index 4df5c7832..b04f57306 100644 --- a/netwerk/protocol/http/PHttpChannelParams.h +++ b/netwerk/protocol/http/PHttpChannelParams.h @@ -98,7 +98,11 @@ struct ParamTraits<mozilla::net::nsHttpHeaderArray::nsEntry> static void Write(Message* aMsg, const paramType& aParam) { - WriteParam(aMsg, aParam.header); + if (aParam.headerNameOriginal.IsEmpty()) { + WriteParam(aMsg, aParam.header); + } else { + WriteParam(aMsg, aParam.headerNameOriginal); + } WriteParam(aMsg, aParam.value); switch (aParam.variety) { case mozilla::net::nsHttpHeaderArray::eVarietyUnknown: @@ -124,11 +128,18 @@ struct ParamTraits<mozilla::net::nsHttpHeaderArray::nsEntry> static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult) { uint8_t variety; - if (!ReadParam(aMsg, aIter, &aResult->header) || + nsAutoCString header; + if (!ReadParam(aMsg, aIter, &header) || !ReadParam(aMsg, aIter, &aResult->value) || !ReadParam(aMsg, aIter, &variety)) return false; + mozilla::net::nsHttpAtom atom = mozilla::net::nsHttp::ResolveAtom(header); + aResult->header = atom; + if (!header.Equals(atom.get())) { + aResult->headerNameOriginal = header; + } + switch (variety) { case 0: aResult->variety = mozilla::net::nsHttpHeaderArray::eVarietyUnknown; diff --git a/netwerk/protocol/http/TunnelUtils.cpp b/netwerk/protocol/http/TunnelUtils.cpp index 4cc24a07f..6880e0187 100644 --- a/netwerk/protocol/http/TunnelUtils.cpp +++ b/netwerk/protocol/http/TunnelUtils.cpp @@ -23,6 +23,7 @@ #include "nsNetCID.h" #include "nsServiceManagerUtils.h" #include "nsComponentManagerUtils.h" +#include "nsSocketTransport2.h" namespace mozilla { namespace net { @@ -42,6 +43,7 @@ TLSFilterTransaction::TLSFilterTransaction(nsAHttpTransaction *aWrapped, , mSegmentReader(aReader) , mSegmentWriter(aWriter) , mForce(false) + , mReadSegmentReturnValue(NS_OK) , mNudgeCounter(0) { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); @@ -130,6 +132,19 @@ TLSFilterTransaction::Close(nsresult aReason) } mTransaction->Close(aReason); mTransaction = nullptr; + + RefPtr<NullHttpTransaction> baseTrans(do_QueryReferent(mWeakTrans)); + SpdyConnectTransaction *trans = baseTrans + ? baseTrans->QuerySpdyConnectTransaction() + : nullptr; + + LOG(("TLSFilterTransaction::Close %p aReason=%" PRIx32 " trans=%p\n", + this, static_cast<uint32_t>(aReason), trans)); + + if (trans) { + trans->Close(aReason); + trans = nullptr; + } } nsresult @@ -140,7 +155,7 @@ TLSFilterTransaction::OnReadSegment(const char *aData, LOG(("TLSFilterTransaction %p OnReadSegment %d (buffered %d)\n", this, aCount, mEncryptedTextUsed)); - mReadSegmentBlocked = false; + mReadSegmentReturnValue = NS_OK; MOZ_ASSERT(mSegmentReader); if (!mSecInfo) { return NS_ERROR_FAILURE; @@ -188,10 +203,12 @@ TLSFilterTransaction::OnReadSegment(const char *aData, return NS_OK; } // mTransaction ReadSegments actually obscures this code, so - // keep it in a member var for this::ReadSegments to insepct. Similar + // keep it in a member var for this::ReadSegments to inspect. Similar // to nsHttpConnection::mSocketOutCondition - mReadSegmentBlocked = (PR_GetError() == PR_WOULD_BLOCK_ERROR); - return mReadSegmentBlocked ? NS_BASE_STREAM_WOULD_BLOCK : NS_ERROR_FAILURE; + PRErrorCode code = PR_GetError(); + mReadSegmentReturnValue = ErrorAccordingToNSPR(code); + + return mReadSegmentReturnValue; } aCount -= written; aData += written; @@ -273,10 +290,18 @@ TLSFilterTransaction::OnWriteSegment(char *aData, mFilterReadCode = NS_OK; int32_t bytesRead = PR_Read(mFD, aData, aCount); if (bytesRead == -1) { - if (PR_GetError() == PR_WOULD_BLOCK_ERROR) { + PRErrorCode code = PR_GetError(); + if (code == PR_WOULD_BLOCK_ERROR) { return NS_BASE_STREAM_WOULD_BLOCK; } - return NS_ERROR_FAILURE; + // If reading from the socket succeeded (NS_SUCCEEDED(mFilterReadCode)), + // but the nss layer encountered an error remember the error. + if (NS_SUCCEEDED(mFilterReadCode)) { + mFilterReadCode = ErrorAccordingToNSPR(code); + LOG(("TLSFilterTransaction::OnWriteSegment %p nss error %" PRIx32 ".\n", + this, static_cast<uint32_t>(mFilterReadCode))); + } + return mFilterReadCode; } *outCountRead = bytesRead; @@ -303,7 +328,7 @@ TLSFilterTransaction::FilterInput(char *aBuf, int32_t aAmount) if (NS_SUCCEEDED(mFilterReadCode) && outCountRead) { LOG(("TLSFilterTransaction::FilterInput rv=%x read=%d input from net " "1 layer stripped, 1 still on\n", mFilterReadCode, outCountRead)); - if (mReadSegmentBlocked) { + if (mReadSegmentReturnValue == NS_BASE_STREAM_WOULD_BLOCK) { mNudgeCounter = 0; } } @@ -325,19 +350,18 @@ TLSFilterTransaction::ReadSegments(nsAHttpSegmentReader *aReader, return NS_ERROR_UNEXPECTED; } - mReadSegmentBlocked = false; + mReadSegmentReturnValue = NS_OK; mSegmentReader = aReader; nsresult rv = mTransaction->ReadSegments(this, aCount, outCountRead); LOG(("TLSFilterTransaction %p called trans->ReadSegments rv=%x %d\n", this, rv, *outCountRead)); - if (NS_SUCCEEDED(rv) && mReadSegmentBlocked) { - rv = NS_BASE_STREAM_WOULD_BLOCK; + if (NS_SUCCEEDED(rv) && (mReadSegmentReturnValue == NS_BASE_STREAM_WOULD_BLOCK)) { LOG(("TLSFilterTransaction %p read segment blocked found rv=%x\n", - this, rv)); + this, static_cast<uint32_t>(rv))); Connection()->ForceSend(); } - return rv; + return NS_SUCCEEDED(rv) ? mReadSegmentReturnValue : rv; } nsresult @@ -442,7 +466,10 @@ TLSFilterTransaction::Notify(nsITimer *timer) if (timer != mTimer) { return NS_ERROR_UNEXPECTED; } - StartTimerCallback(); + nsresult rv = StartTimerCallback(); + if (NS_FAILED(rv)) { + Close(rv); + } return NS_OK; } @@ -456,7 +483,7 @@ TLSFilterTransaction::StartTimerCallback() // This class can be called re-entrantly, so cleanup m* before ->on() RefPtr<NudgeTunnelCallback> cb(mNudgeCallback); mNudgeCallback = nullptr; - cb->OnTunnelNudged(this); + return cb->OnTunnelNudged(this); } return NS_OK; } @@ -675,10 +702,12 @@ TLSFilterTransaction::TakeSubTransactions( } nsresult -TLSFilterTransaction::SetProxiedTransaction(nsAHttpTransaction *aTrans) +TLSFilterTransaction::SetProxiedTransaction(nsAHttpTransaction *aTrans, + nsAHttpTransaction *aSpdyConnectTransaction) { - LOG(("TLSFilterTransaction::SetProxiedTransaction [this=%p] aTrans=%p\n", - this, aTrans)); + LOG(("TLSFilterTransaction::SetProxiedTransaction [this=%p] aTrans=%p, " + "aSpdyConnectTransaction=%p\n", + this, aTrans, aSpdyConnectTransaction)); mTransaction = aTrans; nsCOMPtr<nsIInterfaceRequestor> callbacks; @@ -688,6 +717,8 @@ TLSFilterTransaction::SetProxiedTransaction(nsAHttpTransaction *aTrans) secCtrl->SetNotificationCallbacks(callbacks); } + mWeakTrans = do_GetWeakReference(aSpdyConnectTransaction); + return NS_OK; } @@ -1075,7 +1106,7 @@ SpdyConnectTransaction::MapStreamToHttpConnection(nsISocketTransport *aTransport if (mForcePlainText) { mTunneledConn->ForcePlainText(); } else { - mTunneledConn->SetupSecondaryTLS(); + mTunneledConn->SetupSecondaryTLS(this); mTunneledConn->SetInSpdyTunnel(true); } diff --git a/netwerk/protocol/http/TunnelUtils.h b/netwerk/protocol/http/TunnelUtils.h index 20cfaf7ee..4a003082e 100644 --- a/netwerk/protocol/http/TunnelUtils.h +++ b/netwerk/protocol/http/TunnelUtils.h @@ -93,10 +93,11 @@ class TLSFilterTransaction; class NudgeTunnelCallback : public nsISupports { public: - virtual void OnTunnelNudged(TLSFilterTransaction *) = 0; + virtual nsresult OnTunnelNudged(TLSFilterTransaction *) = 0; }; -#define NS_DECL_NUDGETUNNELCALLBACK void OnTunnelNudged(TLSFilterTransaction *) override; +#define NS_DECL_NUDGETUNNELCALLBACK \ + nsresult OnTunnelNudged(TLSFilterTransaction *) override; class TLSFilterTransaction final : public nsAHttpTransaction @@ -121,7 +122,8 @@ public: nsresult CommitToSegmentSize(uint32_t size, bool forceCommitment) override; nsresult GetTransactionSecurityInfo(nsISupports **) override; nsresult NudgeTunnel(NudgeTunnelCallback *callback); - nsresult SetProxiedTransaction(nsAHttpTransaction *aTrans); + MOZ_MUST_USE nsresult SetProxiedTransaction(nsAHttpTransaction *aTrans, + nsAHttpTransaction *aSpdyConnectTransaction = nullptr); void newIODriver(nsIAsyncInputStream *aSocketIn, nsIAsyncOutputStream *aSocketOut, nsIAsyncInputStream **outSocketIn, @@ -153,6 +155,7 @@ private: private: RefPtr<nsAHttpTransaction> mTransaction; + nsWeakPtr mWeakTrans; // SpdyConnectTransaction * nsCOMPtr<nsISupports> mSecInfo; nsCOMPtr<nsITimer> mTimer; RefPtr<NudgeTunnelCallback> mNudgeCallback; @@ -168,7 +171,7 @@ private: nsresult mFilterReadCode; bool mForce; - bool mReadSegmentBlocked; + nsresult mReadSegmentReturnValue; uint32_t mNudgeCounter; }; diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index d7247eeab..481df5ff0 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -83,7 +83,6 @@ #include "nsCRT.h" #include "CacheObserver.h" #include "mozilla/dom/Performance.h" -#include "mozilla/Telemetry.h" #include "AlternateServices.h" #include "InterceptedChannel.h" #include "nsIHttpPushListener.h" @@ -123,30 +122,6 @@ static NS_DEFINE_CID(kStreamListenerTeeCID, NS_STREAMLISTENERTEE_CID); static NS_DEFINE_CID(kStreamTransportServiceCID, NS_STREAMTRANSPORTSERVICE_CID); -enum CacheDisposition { - kCacheHit = 1, - kCacheHitViaReval = 2, - kCacheMissedViaReval = 3, - kCacheMissed = 4 -}; - -void -AccumulateCacheHitTelemetry(CacheDisposition hitOrMiss) -{ - if (!CacheObserver::UseNewCache()) { - Telemetry::Accumulate(Telemetry::HTTP_CACHE_DISPOSITION_2, hitOrMiss); - } - else { - Telemetry::Accumulate(Telemetry::HTTP_CACHE_DISPOSITION_2_V2, hitOrMiss); - - int32_t experiment = CacheObserver::HalfLifeExperiment(); - if (experiment > 0 && hitOrMiss == kCacheMissed) { - Telemetry::Accumulate(Telemetry::HTTP_CACHE_MISS_HALFLIFE_EXPERIMENT_2, - experiment - 1); - } - } -} - // Computes and returns a SHA1 hash of the input buffer. The input buffer // must be a null-terminated string. nsresult @@ -324,11 +299,15 @@ nsHttpChannel::nsHttpChannel() , mPushedStream(nullptr) , mLocalBlocklist(false) , mWarningReporter(nullptr) + , mSendUpgradeRequest(false) , mDidReval(false) { LOG(("Creating nsHttpChannel [this=%p]\n", this)); mChannelCreationTime = PR_Now(); mChannelCreationTimestamp = TimeStamp::Now(); + + mSendUpgradeRequest = + Preferences::GetBool("network.http.upgrade-insecure-requests", false); } nsHttpChannel::~nsHttpChannel() @@ -345,10 +324,16 @@ nsHttpChannel::Init(nsIURI *uri, nsProxyInfo *proxyInfo, uint32_t proxyResolveFlags, nsIURI *proxyURI, - const nsID& channelId) -{ - nsresult rv = HttpBaseChannel::Init(uri, caps, proxyInfo, - proxyResolveFlags, proxyURI, channelId); + const nsID& channelId, + nsContentPolicyType aContentPolicyType) +{ + nsresult rv = HttpBaseChannel::Init(uri, + caps, + proxyInfo, + proxyResolveFlags, + proxyURI, + channelId, + aContentPolicyType); if (NS_FAILED(rv)) return rv; @@ -388,8 +373,9 @@ nsHttpChannel::Connect() mLoadInfo->GetExternalContentPolicyType() : nsIContentPolicy::TYPE_OTHER; - if (type == nsIContentPolicy::TYPE_DOCUMENT || - type == nsIContentPolicy::TYPE_SUBDOCUMENT) { + if (mSendUpgradeRequest && + (type == nsIContentPolicy::TYPE_DOCUMENT || + type == nsIContentPolicy::TYPE_SUBDOCUMENT)) { rv = SetRequestHeader(NS_LITERAL_CSTRING("Upgrade-Insecure-Requests"), NS_LITERAL_CSTRING("1"), false); NS_ENSURE_SUCCESS(rv, rv); @@ -500,11 +486,6 @@ nsHttpChannel::ContinueConnect() event->Revoke(); } - // Don't accumulate the cache hit telemetry for intercepted channels. - if (mInterceptCache != INTERCEPTED) { - AccumulateCacheHitTelemetry(kCacheHit); - } - return rv; } else if (mLoadFlags & LOAD_ONLY_FROM_CACHE) { @@ -1091,10 +1072,8 @@ ProcessXCTO(nsIURI* aURI, nsHttpResponseHead* aResponseHead, nsILoadInfo* aLoadI if (aLoadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_IMAGE) { if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("image/"))) { - Accumulate(Telemetry::XCTO_NOSNIFF_BLOCK_IMAGE, 0); return NS_OK; } - Accumulate(Telemetry::XCTO_NOSNIFF_BLOCK_IMAGE, 1); // Instead of consulting Preferences::GetBool() all the time we // can cache the result to speed things up. static bool sXCTONosniffBlockImages = false; @@ -1141,26 +1120,21 @@ EnsureMIMEOfScript(nsIURI* aURI, nsHttpResponseHead* aResponseHead, nsILoadInfo* if (nsContentUtils::IsJavascriptMIMEType(typeString)) { // script load has type script - Telemetry::Accumulate(Telemetry::SCRIPT_BLOCK_INCORRECT_MIME, 1); return NS_OK; } bool block = false; if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("image/"))) { // script load has type image - Telemetry::Accumulate(Telemetry::SCRIPT_BLOCK_INCORRECT_MIME, 2); block = true; } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("audio/"))) { // script load has type audio - Telemetry::Accumulate(Telemetry::SCRIPT_BLOCK_INCORRECT_MIME, 3); block = true; } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("video/"))) { // script load has type video - Telemetry::Accumulate(Telemetry::SCRIPT_BLOCK_INCORRECT_MIME, 4); block = true; } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/csv"))) { // script load has type text/csv - Telemetry::Accumulate(Telemetry::SCRIPT_BLOCK_INCORRECT_MIME, 6); block = true; } @@ -1186,42 +1160,35 @@ EnsureMIMEOfScript(nsIURI* aURI, nsHttpResponseHead* aResponseHead, nsILoadInfo* if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/plain"))) { // script load has type text/plain - Telemetry::Accumulate(Telemetry::SCRIPT_BLOCK_INCORRECT_MIME, 5); return NS_OK; } if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/xml"))) { // script load has type text/xml - Telemetry::Accumulate(Telemetry::SCRIPT_BLOCK_INCORRECT_MIME, 7); return NS_OK; } if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("application/octet-stream"))) { // script load has type application/octet-stream - Telemetry::Accumulate(Telemetry::SCRIPT_BLOCK_INCORRECT_MIME, 8); return NS_OK; } if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("application/xml"))) { // script load has type application/xml - Telemetry::Accumulate(Telemetry::SCRIPT_BLOCK_INCORRECT_MIME, 9); return NS_OK; } if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/html"))) { // script load has type text/html - Telemetry::Accumulate(Telemetry::SCRIPT_BLOCK_INCORRECT_MIME, 10); return NS_OK; } if (contentType.IsEmpty()) { // script load has no type - Telemetry::Accumulate(Telemetry::SCRIPT_BLOCK_INCORRECT_MIME, 11); return NS_OK; } // script load has unknown type - Telemetry::Accumulate(Telemetry::SCRIPT_BLOCK_INCORRECT_MIME, 0); return NS_OK; } @@ -1867,65 +1834,6 @@ nsHttpChannel::ProcessResponse() LOG(("nsHttpChannel::ProcessResponse [this=%p httpStatus=%u]\n", this, httpStatus)); - // do some telemetry - if (gHttpHandler->IsTelemetryEnabled()) { - // Gather data on whether the transaction and page (if this is - // the initial page load) is being loaded with SSL. - Telemetry::Accumulate(Telemetry::HTTP_TRANSACTION_IS_SSL, - mConnectionInfo->EndToEndSSL()); - if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) { - Telemetry::Accumulate(Telemetry::HTTP_PAGELOAD_IS_SSL, - mConnectionInfo->EndToEndSSL()); - } - - // how often do we see something like Alternate-Protocol: "443:quic,p=1" - nsAutoCString alt_protocol; - mResponseHead->GetHeader(nsHttp::Alternate_Protocol, alt_protocol); - bool saw_quic = (!alt_protocol.IsEmpty() && - PL_strstr(alt_protocol.get(), "quic")) ? 1 : 0; - Telemetry::Accumulate(Telemetry::HTTP_SAW_QUIC_ALT_PROTOCOL, saw_quic); - - // Gather data on how many URLS get redirected - switch (httpStatus) { - case 200: - Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 0); - break; - case 301: - Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 1); - break; - case 302: - Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 2); - break; - case 304: - Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 3); - break; - case 307: - Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 4); - break; - case 308: - Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 5); - break; - case 400: - Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 6); - break; - case 401: - Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 7); - break; - case 403: - Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 8); - break; - case 404: - Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 9); - break; - case 500: - Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 10); - break; - default: - Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 11); - break; - } - } - // Let the predictor know whether this was a cacheable response or not so // that it knows whether or not to possibly prefetch this resource in the // future. @@ -2193,33 +2101,6 @@ nsHttpChannel::ContinueProcessResponse2(nsresult rv) break; } - if (gHttpHandler->IsTelemetryEnabled()) { - CacheDisposition cacheDisposition; - if (!mDidReval) { - cacheDisposition = kCacheMissed; - } else if (successfulReval) { - cacheDisposition = kCacheHitViaReval; - } else { - cacheDisposition = kCacheMissedViaReval; - } - AccumulateCacheHitTelemetry(cacheDisposition); - - Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_VERSION, - mResponseHead->Version()); - - if (mResponseHead->Version() == NS_HTTP_VERSION_0_9) { - // DefaultPortTopLevel = 0, DefaultPortSubResource = 1, - // NonDefaultPortTopLevel = 2, NonDefaultPortSubResource = 3 - uint32_t v09Info = 0; - if (!(mLoadFlags & LOAD_INITIAL_DOCUMENT_URI)) { - v09Info += 1; - } - if (mConnectionInfo->OriginPort() != mConnectionInfo->DefaultPort()) { - v09Info += 2; - } - Telemetry::Accumulate(Telemetry::HTTP_09_INFO, v09Info); - } - } return rv; } @@ -3212,7 +3093,6 @@ nsHttpChannel::ProcessNotModified() PipelineFeedbackInfo(mConnectionInfo, nsHttpConnectionMgr::RedCorruptedContent, nullptr, 0); - Telemetry::Accumulate(Telemetry::CACHE_LM_INCONSISTENT, true); } // merge any new headers with the cached response headers @@ -3866,8 +3746,6 @@ nsHttpChannel::OnCacheEntryCheck(nsICacheEntry* entry, nsIApplicationCache* appC (!mCachedResponseHead->ExpiresInPast() || !mCachedResponseHead->MustValidateIfExpired())) { LOG(("NOT validating based on isForcedValid being true.\n")); - Telemetry::AutoCounter<Telemetry::PREDICTOR_TOTAL_PREFETCHES_USED> used; - ++used; doValidation = false; } // If the LOAD_FROM_CACHE flag is set, any cached data can simply be used @@ -4222,11 +4100,6 @@ nsHttpChannel::OnNormalCacheEntryAvailable(nsICacheEntry *aEntry, if (NS_SUCCEEDED(aEntryStatus)) { mCacheEntry = aEntry; mCacheEntryIsWriteOnly = aNew; - - if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) { - Telemetry::Accumulate(Telemetry::HTTP_OFFLINE_CACHE_DOCUMENT_LOAD, - false); - } } return NS_OK; @@ -5897,17 +5770,13 @@ nsHttpChannel::BeginConnect() LOG(("nsHttpChannel %p Using connection info from altsvc mapping", this)); mapping->GetConnectionInfo(getter_AddRefs(mConnectionInfo), proxyInfo, originAttributes); - Telemetry::Accumulate(Telemetry::HTTP_TRANSACTION_USE_ALTSVC, true); - Telemetry::Accumulate(Telemetry::HTTP_TRANSACTION_USE_ALTSVC_OE, !isHttps); } else if (mConnectionInfo) { LOG(("nsHttpChannel %p Using channel supplied connection info", this)); - Telemetry::Accumulate(Telemetry::HTTP_TRANSACTION_USE_ALTSVC, false); } else { LOG(("nsHttpChannel %p Using default connection info", this)); mConnectionInfo = new nsHttpConnectionInfo(host, port, EmptyCString(), mUsername, proxyInfo, originAttributes, isHttps); - Telemetry::Accumulate(Telemetry::HTTP_TRANSACTION_USE_ALTSVC, false); } // Set network interface id only when it's not empty to avoid @@ -6637,8 +6506,6 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult st if (mTimingEnabled && request == mCachePump) { mCacheReadEnd = TimeStamp::Now(); - - ReportNetVSCacheTelemetry(); } // allow content to be cached if it was loaded successfully (bug #482935) @@ -6829,7 +6696,6 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult st chanDisposition = static_cast<ChannelDisposition>(chanDisposition + kHttpsCanceled); } LOG((" nsHttpChannel::OnStopRequest ChannelDisposition %d\n", chanDisposition)); - Telemetry::Accumulate(Telemetry::HTTP_CHANNEL_DISPOSITION, chanDisposition); // if needed, check cache entry has all data we expect if (mCacheEntry && mCachePump && @@ -8196,134 +8062,5 @@ nsHttpChannel::SetDoNotTrack() } } - -void -nsHttpChannel::ReportNetVSCacheTelemetry() -{ - nsresult rv; - if (!mCacheEntry) { - return; - } - - // We only report telemetry if the entry is persistent (on disk) - bool persistent; - rv = mCacheEntry->GetPersistent(&persistent); - if (NS_FAILED(rv) || !persistent) { - return; - } - - nsXPIDLCString tmpStr; - rv = mCacheEntry->GetMetaDataElement("net-response-time-onstart", - getter_Copies(tmpStr)); - if (NS_FAILED(rv)) { - return; - } - uint64_t onStartNetTime = tmpStr.ToInteger64(&rv); - if (NS_FAILED(rv)) { - return; - } - - tmpStr.Truncate(); - rv = mCacheEntry->GetMetaDataElement("net-response-time-onstop", - getter_Copies(tmpStr)); - if (NS_FAILED(rv)) { - return; - } - uint64_t onStopNetTime = tmpStr.ToInteger64(&rv); - if (NS_FAILED(rv)) { - return; - } - - uint64_t onStartCacheTime = (mOnStartRequestTimestamp - mAsyncOpenTime).ToMilliseconds(); - int64_t onStartDiff = onStartNetTime - onStartCacheTime; - onStartDiff += 500; // We offset the difference by 500 ms to report positive values in telemetry - - uint64_t onStopCacheTime = (mCacheReadEnd - mAsyncOpenTime).ToMilliseconds(); - int64_t onStopDiff = onStopNetTime - onStopCacheTime; - onStopDiff += 500; // We offset the difference by 500 ms - - if (mDidReval) { - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_REVALIDATED, onStartDiff); - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_REVALIDATED, onStopDiff); - } else { - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_NOTREVALIDATED, onStartDiff); - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_NOTREVALIDATED, onStopDiff); - } - - if (mDidReval) { - // We don't report revalidated probes as the data would be skewed. - return; - } - - uint32_t diskStorageSizeK = 0; - rv = mCacheEntry->GetDiskStorageSizeInKB(&diskStorageSizeK); - if (NS_FAILED(rv)) { - return; - } - - nsAutoCString contentType; - if (mResponseHead && mResponseHead->HasContentType()) { - mResponseHead->ContentType(contentType); - } - bool isImage = StringBeginsWith(contentType, NS_LITERAL_CSTRING("image/")); - if (isImage) { - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_ISIMG, onStartDiff); - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_ISIMG, onStopDiff); - } else { - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_NOTIMG, onStartDiff); - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_NOTIMG, onStopDiff); - } - - if (mCacheOpenWithPriority) { - if (mCacheQueueSizeWhenOpen < 5) { - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_QSMALL_HIGHPRI, onStartDiff); - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_QSMALL_HIGHPRI, onStopDiff); - } else if (mCacheQueueSizeWhenOpen < 10) { - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_QMED_HIGHPRI, onStartDiff); - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_QMED_HIGHPRI, onStopDiff); - } else { - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_QBIG_HIGHPRI, onStartDiff); - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_QBIG_HIGHPRI, onStopDiff); - } - } else { // The limits are higher for normal priority cache queues - if (mCacheQueueSizeWhenOpen < 10) { - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_QSMALL_NORMALPRI, onStartDiff); - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_QSMALL_NORMALPRI, onStopDiff); - } else if (mCacheQueueSizeWhenOpen < 50) { - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_QMED_NORMALPRI, onStartDiff); - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_QMED_NORMALPRI, onStopDiff); - } else { - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_QBIG_NORMALPRI, onStartDiff); - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_QBIG_NORMALPRI, onStopDiff); - } - } - - if (diskStorageSizeK < 32) { - if (mCacheOpenWithPriority) { - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_SMALL_HIGHPRI, onStartDiff); - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_SMALL_HIGHPRI, onStopDiff); - } else { - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_SMALL_NORMALPRI, onStartDiff); - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_SMALL_NORMALPRI, onStopDiff); - } - } else if (diskStorageSizeK < 256) { - if (mCacheOpenWithPriority) { - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_MED_HIGHPRI, onStartDiff); - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_MED_HIGHPRI, onStopDiff); - } else { - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_MED_NORMALPRI, onStartDiff); - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_MED_NORMALPRI, onStopDiff); - } - } else { - if (mCacheOpenWithPriority) { - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_LARGE_HIGHPRI, onStartDiff); - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_LARGE_HIGHPRI, onStopDiff); - } else { - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_LARGE_NORMALPRI, onStartDiff); - Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_LARGE_NORMALPRI, onStopDiff); - } - } -} - } // namespace net } // namespace mozilla diff --git a/netwerk/protocol/http/nsHttpChannel.h b/netwerk/protocol/http/nsHttpChannel.h index 2e24d6e81..0038e1f71 100644 --- a/netwerk/protocol/http/nsHttpChannel.h +++ b/netwerk/protocol/http/nsHttpChannel.h @@ -123,7 +123,8 @@ public: virtual nsresult Init(nsIURI *aURI, uint32_t aCaps, nsProxyInfo *aProxyInfo, uint32_t aProxyResolveFlags, nsIURI *aProxyURI, - const nsID& aChannelId) override; + const nsID& aChannelId, + nsContentPolicyType aContentPolicyType) override; nsresult OnPush(const nsACString &uri, Http2PushedStream *pushedStream); @@ -431,9 +432,6 @@ private: rv == NS_ERROR_MALFORMED_URI; } - // Report net vs cache time telemetry - void ReportNetVSCacheTelemetry(); - // Create a aggregate set of the current notification callbacks // and ensure the transaction is updated to use it. void UpdateAggregateCallbacks(); @@ -597,6 +595,10 @@ private: HttpChannelSecurityWarningReporter* mWarningReporter; RefPtr<ADivertableParentChannel> mParentChannel; + + // Whether we send opportunistic encryption requests. + bool mSendUpgradeRequest; + protected: virtual void DoNotifyListenerCleanup() override; diff --git a/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp b/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp index d04f47ddc..0e7eb55c3 100644 --- a/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp +++ b/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp @@ -867,24 +867,6 @@ nsHttpChannelAuthProvider::GetCredentialsForChallenge(const char *challenge, else if (authFlags & nsIHttpAuthenticator::IDENTITY_ENCRYPTED) level = nsIAuthPrompt2::LEVEL_PW_ENCRYPTED; - // Collect statistics on how frequently the various types of HTTP - // authentication are used over SSL and non-SSL connections. - if (gHttpHandler->IsTelemetryEnabled()) { - if (NS_LITERAL_CSTRING("basic").LowerCaseEqualsASCII(authType)) { - Telemetry::Accumulate(Telemetry::HTTP_AUTH_TYPE_STATS, - UsingSSL() ? HTTP_AUTH_BASIC_SECURE : HTTP_AUTH_BASIC_INSECURE); - } else if (NS_LITERAL_CSTRING("digest").LowerCaseEqualsASCII(authType)) { - Telemetry::Accumulate(Telemetry::HTTP_AUTH_TYPE_STATS, - UsingSSL() ? HTTP_AUTH_DIGEST_SECURE : HTTP_AUTH_DIGEST_INSECURE); - } else if (NS_LITERAL_CSTRING("ntlm").LowerCaseEqualsASCII(authType)) { - Telemetry::Accumulate(Telemetry::HTTP_AUTH_TYPE_STATS, - UsingSSL() ? HTTP_AUTH_NTLM_SECURE : HTTP_AUTH_NTLM_INSECURE); - } else if (NS_LITERAL_CSTRING("negotiate").LowerCaseEqualsASCII(authType)) { - Telemetry::Accumulate(Telemetry::HTTP_AUTH_TYPE_STATS, - UsingSSL() ? HTTP_AUTH_NEGOTIATE_SECURE : HTTP_AUTH_NEGOTIATE_INSECURE); - } - } - // Depending on the pref setting, the authentication dialog may be // blocked for all sub-resources, blocked for cross-origin // sub-resources, or always allowed for sub-resources. @@ -991,22 +973,6 @@ nsHttpChannelAuthProvider::BlockPrompt() } } - if (gHttpHandler->IsTelemetryEnabled()) { - if (topDoc) { - Telemetry::Accumulate(Telemetry::HTTP_AUTH_DIALOG_STATS, - HTTP_AUTH_DIALOG_TOP_LEVEL_DOC); - } else if (xhr) { - Telemetry::Accumulate(Telemetry::HTTP_AUTH_DIALOG_STATS, - HTTP_AUTH_DIALOG_XHR); - } else if (!mCrossOrigin) { - Telemetry::Accumulate(Telemetry::HTTP_AUTH_DIALOG_STATS, - HTTP_AUTH_DIALOG_SAME_ORIGIN_SUBRESOURCE); - } else { - Telemetry::Accumulate(Telemetry::HTTP_AUTH_DIALOG_STATS, - HTTP_AUTH_DIALOG_CROSS_ORIGIN_SUBRESOURCE); - } - } - switch (sAuthAllowPref) { case SUBRESOURCE_AUTH_DIALOG_DISALLOW_ALL: // Do not open the http-authentication credentials dialog for diff --git a/netwerk/protocol/http/nsHttpConnection.cpp b/netwerk/protocol/http/nsHttpConnection.cpp index c4564cd8b..505d849c0 100644 --- a/netwerk/protocol/http/nsHttpConnection.cpp +++ b/netwerk/protocol/http/nsHttpConnection.cpp @@ -19,7 +19,6 @@ #include "ASpdySession.h" #include "mozilla/ChaosMode.h" -#include "mozilla/Telemetry.h" #include "nsHttpConnection.h" #include "nsHttpHandler.h" #include "nsHttpPipeline.h" @@ -105,18 +104,12 @@ nsHttpConnection::~nsHttpConnection() if (!mEverUsedSpdy) { LOG(("nsHttpConnection %p performed %d HTTP/1.x transactions\n", this, mHttp1xTransactionCount)); - Telemetry::Accumulate(Telemetry::HTTP_REQUEST_PER_CONN, - mHttp1xTransactionCount); } if (mTotalBytesRead) { uint32_t totalKBRead = static_cast<uint32_t>(mTotalBytesRead >> 10); LOG(("nsHttpConnection %p read %dkb on connection spdy=%d\n", this, totalKBRead, mEverUsedSpdy)); - Telemetry::Accumulate(mEverUsedSpdy ? - Telemetry::SPDY_KBREAD_PER_CONN : - Telemetry::HTTP_KBREAD_PER_CONN, - totalKBRead); } if (mForceSendTimer) { mForceSendTimer->Cancel(); @@ -482,21 +475,6 @@ nsHttpConnection::EnsureNPNComplete(nsresult &aOut0RTTWriteHandshakeValue, int16_t tlsVersion; ssl->GetSSLVersionUsed(&tlsVersion); - // Send the 0RTT telemetry only for tls1.3 - if (tlsVersion > nsISSLSocketControl::TLS_VERSION_1_2) { - Telemetry::Accumulate(Telemetry::TLS_EARLY_DATA_NEGOTIATED, - (!mEarlyDataNegotiated) ? TLS_EARLY_DATA_NOT_AVAILABLE - : ((mWaitingFor0RTTResponse) ? TLS_EARLY_DATA_AVAILABLE_AND_USED - : TLS_EARLY_DATA_AVAILABLE_BUT_NOT_USED)); - if (mWaitingFor0RTTResponse) { - Telemetry::Accumulate(Telemetry::TLS_EARLY_DATA_ACCEPTED, - earlyDataAccepted); - } - if (earlyDataAccepted) { - Telemetry::Accumulate(Telemetry::TLS_EARLY_DATA_BYTES_WRITTEN, - mContentBytesWritten0RTT); - } - } mWaitingFor0RTTResponse = false; if (!earlyDataAccepted) { @@ -518,8 +496,6 @@ nsHttpConnection::EnsureNPNComplete(nsresult &aOut0RTTWriteHandshakeValue, StartSpdy(mSpdySession->SpdyVersion()); } } - - Telemetry::Accumulate(Telemetry::SPDY_NPN_CONNECT, UsingSpdy()); } npnComplete: @@ -559,16 +535,16 @@ npnComplete: return true; } -void +nsresult nsHttpConnection::OnTunnelNudged(TLSFilterTransaction *trans) { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); LOG(("nsHttpConnection::OnTunnelNudged %p\n", this)); if (trans != mTLSFilter) { - return; + return NS_OK; } LOG(("nsHttpConnection::OnTunnelNudged %p Calling OnSocketWritable\n", this)); - OnSocketWritable(); + return OnSocketWritable(); } // called on the socket thread @@ -663,7 +639,9 @@ nsHttpConnection::Activate(nsAHttpTransaction *trans, uint32_t caps, int32_t pri } if (mTLSFilter) { - mTLSFilter->SetProxiedTransaction(trans); + RefPtr<NullHttpTransaction> baseTrans(do_QueryReferent(mWeakTrans)); + rv = mTLSFilter->SetProxiedTransaction(trans, baseTrans); + NS_ENSURE_SUCCESS(rv, rv); mTransaction = mTLSFilter; } @@ -2003,7 +1981,7 @@ nsHttpConnection::OnSocketReadable() // negotiation are known (which is determined from the write path). // If the server speaks SPDY it is likely the readable data here is // a spdy settings frame and without NPN it would be misinterpreted - // as HTTP/* + // as HTTP LOG(("nsHttpConnection::OnSocketReadable %p return due to inactive " "tunnel setup but incomplete NPN state\n", this)); @@ -2043,12 +2021,14 @@ nsHttpConnection::OnSocketReadable() } void -nsHttpConnection::SetupSecondaryTLS() +nsHttpConnection::SetupSecondaryTLS(nsAHttpTransaction *aSpdyConnectTransaction) { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); MOZ_ASSERT(!mTLSFilter); - LOG(("nsHttpConnection %p SetupSecondaryTLS %s %d\n", - this, mConnInfo->Origin(), mConnInfo->OriginPort())); + LOG(("nsHttpConnection %p SetupSecondaryTLS %s %d " + "aSpdyConnectTransaction=%p\n", + this, mConnInfo->Origin(), mConnInfo->OriginPort(), + aSpdyConnectTransaction)); nsHttpConnectionInfo *ci = nullptr; if (mTransaction) { @@ -2065,6 +2045,7 @@ nsHttpConnection::SetupSecondaryTLS() if (mTransaction) { mTransaction = mTLSFilter; } + mWeakTrans = do_GetWeakReference(aSpdyConnectTransaction); } void diff --git a/netwerk/protocol/http/nsHttpConnection.h b/netwerk/protocol/http/nsHttpConnection.h index 08eea1de2..ce7523eb5 100644 --- a/netwerk/protocol/http/nsHttpConnection.h +++ b/netwerk/protocol/http/nsHttpConnection.h @@ -202,7 +202,7 @@ public: static nsresult MakeConnectString(nsAHttpTransaction *trans, nsHttpRequestHead *request, nsACString &result); - void SetupSecondaryTLS(); + void SetupSecondaryTLS(nsAHttpTransaction *aSpdyConnectTransaction = nullptr); void SetInSpdyTunnel(bool arg); // Check active connections for traffic (or not). SPDY connections send a @@ -281,6 +281,7 @@ private: // transaction is open, otherwise it is null. RefPtr<nsAHttpTransaction> mTransaction; RefPtr<TLSFilterTransaction> mTLSFilter; + nsWeakPtr mWeakTrans; // SpdyConnectTransaction * RefPtr<nsHttpHandler> mHttpHandler; // keep gHttpHandler alive diff --git a/netwerk/protocol/http/nsHttpConnectionInfo.cpp b/netwerk/protocol/http/nsHttpConnectionInfo.cpp index e965fd1cc..93a40843c 100644 --- a/netwerk/protocol/http/nsHttpConnectionInfo.cpp +++ b/netwerk/protocol/http/nsHttpConnectionInfo.cpp @@ -15,32 +15,26 @@ #include "nsHttpConnectionInfo.h" #include "mozilla/net/DNS.h" -#include "prnetdb.h" -#include "nsICryptoHash.h" #include "nsComponentManagerUtils.h" +#include "nsICryptoHash.h" #include "nsIProtocolProxyService.h" +#include "nsNetCID.h" +#include "prnetdb.h" static nsresult SHA256(const char* aPlainText, nsAutoCString& aResult) { - static nsICryptoHash* hasher = nullptr; nsresult rv; - if (!hasher) { - rv = CallCreateInstance("@mozilla.org/security/hash;1", &hasher); - if (NS_FAILED(rv)) { - LOG(("nsHttpDigestAuth: no crypto hash!\n")); - return rv; - } + nsCOMPtr<nsICryptoHash> hasher = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv); + if (NS_FAILED(rv)) { + LOG(("nsHttpDigestAuth: no crypto hash!\n")); + return rv; } - rv = hasher->Init(nsICryptoHash::SHA256); NS_ENSURE_SUCCESS(rv, rv); - rv = hasher->Update((unsigned char*) aPlainText, strlen(aPlainText)); NS_ENSURE_SUCCESS(rv, rv); - - rv = hasher->Finish(false, aResult); - return rv; + return hasher->Finish(false, aResult); } namespace mozilla { diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp index 9271b49af..907f33436 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp +++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp @@ -23,7 +23,6 @@ #include "mozilla/net/DNS.h" #include "nsISocketTransport.h" #include "nsISSLSocketControl.h" -#include "mozilla/Telemetry.h" #include "mozilla/net/DashboardTypes.h" #include "NullHttpTransaction.h" #include "nsIDNSRecord.h" @@ -36,8 +35,6 @@ #include "mozilla/Unused.h" #include "nsIURI.h" -#include "mozilla/Telemetry.h" - namespace mozilla { namespace net { @@ -847,7 +844,6 @@ nsHttpConnectionMgr::GetSpdyPreferredEnt(nsConnectionEntry *aOriginalEntry) "with %s connections. rv=%x isJoined=%d", preferred->mConnInfo->Origin(), aOriginalEntry->mConnInfo->Origin(), rv, isJoined)); - Telemetry::Accumulate(Telemetry::SPDY_NPN_JOIN, false); return nullptr; } @@ -857,7 +853,6 @@ nsHttpConnectionMgr::GetSpdyPreferredEnt(nsConnectionEntry *aOriginalEntry) "so %s will be coalesced with %s", preferred->mConnInfo->Origin(), aOriginalEntry->mConnInfo->Origin(), aOriginalEntry->mConnInfo->Origin(), preferred->mConnInfo->Origin())); - Telemetry::Accumulate(Telemetry::SPDY_NPN_JOIN, true); return preferred; } @@ -1189,14 +1184,6 @@ nsHttpConnectionMgr::MakeNewConnection(nsConnectionEntry *ent, transport->SetConnectionFlags(flags); } - Telemetry::AutoCounter<Telemetry::HTTPCONNMGR_USED_SPECULATIVE_CONN> usedSpeculativeConn; - ++usedSpeculativeConn; - - if (ent->mHalfOpens[i]->IsFromPredictor()) { - Telemetry::AutoCounter<Telemetry::PREDICTOR_TOTAL_PRECONNECTS_USED> totalPreconnectsUsed; - ++totalPreconnectsUsed; - } - // return OK because we have essentially opened a new connection // by converting a speculative half-open to general use return NS_OK; @@ -1390,14 +1377,6 @@ nsHttpConnectionMgr::AddToShortestPipeline(nsConnectionEntry *ent, ent->SetYellowConnection(bestConn); if (!trans->GetPendingTime().IsNull()) { - if (trans->UsesPipelining()) - AccumulateTimeDelta( - Telemetry::TRANSACTION_WAIT_TIME_HTTP_PIPELINES, - trans->GetPendingTime(), TimeStamp::Now()); - else - AccumulateTimeDelta( - Telemetry::TRANSACTION_WAIT_TIME_HTTP, - trans->GetPendingTime(), TimeStamp::Now()); trans->SetPendingTime(false); } return true; @@ -1680,8 +1659,6 @@ nsHttpConnectionMgr::DispatchTransaction(nsConnectionEntry *ent, rv = conn->Activate(trans, caps, priority); MOZ_ASSERT(NS_SUCCEEDED(rv), "SPDY Cannot Fail Dispatch"); if (NS_SUCCEEDED(rv) && !trans->GetPendingTime().IsNull()) { - AccumulateTimeDelta(Telemetry::TRANSACTION_WAIT_TIME_SPDY, - trans->GetPendingTime(), TimeStamp::Now()); trans->SetPendingTime(false); } return rv; @@ -1698,12 +1675,6 @@ nsHttpConnectionMgr::DispatchTransaction(nsConnectionEntry *ent, rv = DispatchAbstractTransaction(ent, trans, caps, conn, priority); if (NS_SUCCEEDED(rv) && !trans->GetPendingTime().IsNull()) { - if (trans->UsesPipelining()) - AccumulateTimeDelta(Telemetry::TRANSACTION_WAIT_TIME_HTTP_PIPELINES, - trans->GetPendingTime(), TimeStamp::Now()); - else - AccumulateTimeDelta(Telemetry::TRANSACTION_WAIT_TIME_HTTP, - trans->GetPendingTime(), TimeStamp::Now()); trans->SetPendingTime(false); } return rv; @@ -1832,21 +1803,6 @@ nsHttpConnectionMgr::BuildPipeline(nsConnectionEntry *ent, return NS_OK; } -void -nsHttpConnectionMgr::ReportProxyTelemetry(nsConnectionEntry *ent) -{ - enum { PROXY_NONE = 1, PROXY_HTTP = 2, PROXY_SOCKS = 3, PROXY_HTTPS = 4 }; - - if (!ent->mConnInfo->UsingProxy()) - Telemetry::Accumulate(Telemetry::HTTP_PROXY_TYPE, PROXY_NONE); - else if (ent->mConnInfo->UsingHttpsProxy()) - Telemetry::Accumulate(Telemetry::HTTP_PROXY_TYPE, PROXY_HTTPS); - else if (ent->mConnInfo->UsingHttpProxy()) - Telemetry::Accumulate(Telemetry::HTTP_PROXY_TYPE, PROXY_HTTP); - else - Telemetry::Accumulate(Telemetry::HTTP_PROXY_TYPE, PROXY_SOCKS); -} - nsresult nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans) { @@ -1890,8 +1846,6 @@ nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans) ent = preferredEntry; } - ReportProxyTelemetry(ent); - // Check if the transaction already has a sticky reference to a connection. // If so, then we can just use it directly by transferring its reference // to the new connection variable instead of searching for a new one @@ -1988,13 +1942,9 @@ nsHttpConnectionMgr::CreateTransport(nsConnectionEntry *ent, if (speculative) { sock->SetSpeculative(true); sock->SetAllow1918(allow1918); - Telemetry::AutoCounter<Telemetry::HTTPCONNMGR_TOTAL_SPECULATIVE_CONN> totalSpeculativeConn; - ++totalSpeculativeConn; if (isFromPredictor) { sock->SetIsFromPredictor(true); - Telemetry::AutoCounter<Telemetry::PREDICTOR_TOTAL_PRECONNECTS_CREATED> totalPreconnectsCreated; - ++totalPreconnectsCreated; } } @@ -3107,8 +3057,6 @@ nsHalfOpenSocket::SetupStreams(nsISocketTransport **transport, rv = socketTransport->SetSecurityCallbacks(this); NS_ENSURE_SUCCESS(rv, rv); - Telemetry::Accumulate(Telemetry::HTTP_CONNECTION_ENTRY_CACHE_HIT_1, - mEnt->mUsedForConnection); mEnt->mUsedForConnection = true; nsCOMPtr<nsIOutputStream> sout; @@ -3908,16 +3856,6 @@ nsConnectionEntry::RemoveHalfOpen(nsHalfOpenSocket *halfOpen) // will result in it not being present in the halfopen table. That's expected. if (mHalfOpens.RemoveElement(halfOpen)) { - if (halfOpen->IsSpeculative()) { - Telemetry::AutoCounter<Telemetry::HTTPCONNMGR_UNUSED_SPECULATIVE_CONN> unusedSpeculativeConn; - ++unusedSpeculativeConn; - - if (halfOpen->IsFromPredictor()) { - Telemetry::AutoCounter<Telemetry::PREDICTOR_TOTAL_PRECONNECTS_UNUSED> totalPreconnectsUnused; - ++totalPreconnectsUnused; - } - } - MOZ_ASSERT(gHttpHandler->ConnMgr()->mNumHalfOpenConns); if (gHttpHandler->ConnMgr()->mNumHalfOpenConns) { // just in case gHttpHandler->ConnMgr()->mNumHalfOpenConns--; diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.h b/netwerk/protocol/http/nsHttpConnectionMgr.h index 7ca2a2b28..a2c88c402 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.h +++ b/netwerk/protocol/http/nsHttpConnectionMgr.h @@ -529,7 +529,6 @@ private: nsresult ProcessNewTransaction(nsHttpTransaction *); nsresult EnsureSocketThreadTarget(); void ClosePersistentConnections(nsConnectionEntry *ent); - void ReportProxyTelemetry(nsConnectionEntry *ent); nsresult CreateTransport(nsConnectionEntry *, nsAHttpTransaction *, uint32_t, bool, bool, bool); void AddActiveConn(nsHttpConnection *, nsConnectionEntry *); diff --git a/netwerk/protocol/http/nsHttpHandler.cpp b/netwerk/protocol/http/nsHttpHandler.cpp index f9bcc391d..0f4c94202 100644 --- a/netwerk/protocol/http/nsHttpHandler.cpp +++ b/netwerk/protocol/http/nsHttpHandler.cpp @@ -58,7 +58,6 @@ #include "mozilla/net/NeckoChild.h" #include "mozilla/net/NeckoParent.h" #include "mozilla/ipc/URIUtils.h" -#include "mozilla/Telemetry.h" #include "mozilla/Unused.h" #include "mozilla/BasePrincipal.h" @@ -91,7 +90,6 @@ #define BROWSER_PREF_PREFIX "browser.cache." #define DONOTTRACK_HEADER_ENABLED "privacy.donottrackheader.enabled" #define H2MANDATORY_SUITE "security.ssl3.ecdhe_rsa_aes_128_gcm_sha256" -#define TELEMETRY_ENABLED "toolkit.telemetry.enabled" #define ALLOW_EXPERIMENTS "network.allow-experiments" #define SAFE_HINT_HEADER_VALUE "safeHint.enabled" #define SECURITY_PREFIX "security." @@ -203,13 +201,13 @@ nsHttpHandler::nsHttpHandler() , mCompatFirefoxEnabled(false) , mCompatFirefoxVersion("52.9") , mUserAgentIsDirty(true) + , mAcceptLanguagesIsDirty(true) , mPromptTempRedirect(true) , mEnablePersistentHttpsCaching(false) , mDoNotTrackEnabled(false) , mSafeHintEnabled(false) , mParentalControlEnabled(false) , mHandlerActive(false) - , mTelemetryEnabled(false) , mAllowExperiments(true) , mDebugObservations(false) , mEnableSpdy(false) @@ -305,7 +303,6 @@ nsHttpHandler::Init() prefBranch->AddObserver(INTL_ACCEPT_LANGUAGES, this, true); prefBranch->AddObserver(BROWSER_PREF("disk_cache_ssl"), this, true); prefBranch->AddObserver(DONOTTRACK_HEADER_ENABLED, this, true); - prefBranch->AddObserver(TELEMETRY_ENABLED, this, true); prefBranch->AddObserver(H2MANDATORY_SUITE, this, true); prefBranch->AddObserver(HTTP_PREF("tcp_keepalive.short_lived_connections"), this, true); prefBranch->AddObserver(HTTP_PREF("tcp_keepalive.long_lived_connections"), this, true); @@ -419,6 +416,7 @@ nsHttpHandler::Init() obsService->AddObserver(this, "browser:purge-session-history", true); obsService->AddObserver(this, NS_NETWORK_LINK_TOPIC, true); obsService->AddObserver(this, "application-background", true); + obsService->AddObserver(this, "string-bundles-have-flushed", true); } MakeNewRequestTokenBucket(); @@ -470,7 +468,9 @@ nsHttpHandler::InitConnectionMgr() } nsresult -nsHttpHandler::AddStandardRequestHeaders(nsHttpRequestHead *request, bool isSecure) +nsHttpHandler::AddStandardRequestHeaders(nsHttpRequestHead *request, + bool isSecure, + nsContentPolicyType aContentPolicyType) { nsresult rv; @@ -483,14 +483,32 @@ nsHttpHandler::AddStandardRequestHeaders(nsHttpRequestHead *request, bool isSecu // Add the "Accept" header. Note, this is set as an override because the // service worker expects to see it. The other "default" headers are // hidden from service worker interception. - rv = request->SetHeader(nsHttp::Accept, mAccept, + nsAutoCString accept; + if (aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT || + aContentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT) { + accept.Assign(mAcceptNavigation); + } else if (aContentPolicyType == nsIContentPolicy::TYPE_IMAGE || + aContentPolicyType == nsIContentPolicy::TYPE_IMAGESET) { + accept.Assign(mAcceptImage); + } else if (aContentPolicyType == nsIContentPolicy::TYPE_STYLESHEET) { + accept.Assign(mAcceptStyle); + } else { + accept.Assign(mAcceptDefault); + } + + rv = request->SetHeader(nsHttp::Accept, accept, false, nsHttpHeaderArray::eVarietyRequestOverride); if (NS_FAILED(rv)) return rv; // Add the "Accept-Language" header. This header is also exposed to the // service worker. + if (mAcceptLanguagesIsDirty) { + rv = SetAcceptLanguages(); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + } + + // Add the "Accept-Language" header if (!mAcceptLanguages.IsEmpty()) { - // Add the "Accept-Language" header rv = request->SetHeader(nsHttp::Accept_Language, mAcceptLanguages, false, nsHttpHeaderArray::eVarietyRequestOverride); @@ -1265,12 +1283,36 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref) mQoSBits = (uint8_t) clamped(val, 0, 0xff); } + if (PREF_CHANGED(HTTP_PREF("accept.navigation"))) { + nsXPIDLCString accept; + rv = prefs->GetCharPref(HTTP_PREF("accept.navigation"), + getter_Copies(accept)); + if (NS_SUCCEEDED(rv)) + SetAccept(accept, ACCEPT_NAVIGATION); + } + + if (PREF_CHANGED(HTTP_PREF("accept.image"))) { + nsXPIDLCString accept; + rv = prefs->GetCharPref(HTTP_PREF("accept.image"), + getter_Copies(accept)); + if (NS_SUCCEEDED(rv)) + SetAccept(accept, ACCEPT_IMAGE); + } + + if (PREF_CHANGED(HTTP_PREF("accept.style"))) { + nsXPIDLCString accept; + rv = prefs->GetCharPref(HTTP_PREF("accept.style"), + getter_Copies(accept)); + if (NS_SUCCEEDED(rv)) + SetAccept(accept, ACCEPT_STYLE); + } + if (PREF_CHANGED(HTTP_PREF("accept.default"))) { nsXPIDLCString accept; rv = prefs->GetCharPref(HTTP_PREF("accept.default"), getter_Copies(accept)); if (NS_SUCCEEDED(rv)) - SetAccept(accept); + SetAccept(accept, ACCEPT_DEFAULT); } if (PREF_CHANGED(HTTP_PREF("accept-encoding"))) { @@ -1511,16 +1553,10 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref) // if (PREF_CHANGED(INTL_ACCEPT_LANGUAGES)) { - nsCOMPtr<nsIPrefLocalizedString> pls; - prefs->GetComplexValue(INTL_ACCEPT_LANGUAGES, - NS_GET_IID(nsIPrefLocalizedString), - getter_AddRefs(pls)); - if (pls) { - nsXPIDLString uval; - pls->ToString(getter_Copies(uval)); - if (uval) - SetAcceptLanguages(NS_ConvertUTF16toUTF8(uval).get()); - } + // We don't want to set the new accept languages here since + // this pref is a complex type and it may be racy with flushing + // string resources. + mAcceptLanguagesIsDirty = true; } // @@ -1547,19 +1583,6 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref) // includes telemetry and allow-experiments because of the abtest profile bool requestTokenBucketUpdated = false; - // - // Telemetry - // - - if (PREF_CHANGED(TELEMETRY_ENABLED)) { - cVar = false; - requestTokenBucketUpdated = true; - rv = prefs->GetBoolPref(TELEMETRY_ENABLED, &cVar); - if (NS_SUCCEEDED(rv)) { - mTelemetryEnabled = cVar; - } - } - // "security.ssl3.ecdhe_rsa_aes_128_gcm_sha256" is the required h2 interop // suite. @@ -1897,19 +1920,37 @@ PrepareAcceptLanguages(const char *i_AcceptLanguages, nsACString &o_AcceptLangua } nsresult -nsHttpHandler::SetAcceptLanguages(const char *aAcceptLanguages) +nsHttpHandler::SetAcceptLanguages() { + mAcceptLanguagesIsDirty = false; + + const nsAdoptingCString& acceptLanguages = + Preferences::GetLocalizedCString(INTL_ACCEPT_LANGUAGES); + nsAutoCString buf; - nsresult rv = PrepareAcceptLanguages(aAcceptLanguages, buf); - if (NS_SUCCEEDED(rv)) + nsresult rv = PrepareAcceptLanguages(acceptLanguages.get(), buf); + if (NS_SUCCEEDED(rv)) { mAcceptLanguages.Assign(buf); + } return rv; } nsresult -nsHttpHandler::SetAccept(const char *aAccept) +nsHttpHandler::SetAccept(const char *aAccept, AcceptType aType) { - mAccept = aAccept; + switch (aType) { + case ACCEPT_NAVIGATION: + mAcceptNavigation = aAccept; + break; + case ACCEPT_IMAGE: + mAcceptImage = aAccept; + break; + case ACCEPT_STYLE: + mAcceptStyle = aAccept; + break; + case ACCEPT_DEFAULT: + mAcceptDefault = aAccept; + } return NS_OK; } @@ -2067,7 +2108,11 @@ nsHttpHandler::NewProxiedChannel2(nsIURI *uri, rv = NewChannelId(&channelId); NS_ENSURE_SUCCESS(rv, rv); - rv = httpChannel->Init(uri, caps, proxyInfo, proxyResolveFlags, proxyURI, channelId); + nsContentPolicyType contentPolicyType = + aLoadInfo ? aLoadInfo->GetExternalContentPolicyType() + : nsIContentPolicy::TYPE_OTHER; + + rv = httpChannel->Init(uri, caps, proxyInfo, proxyResolveFlags, proxyURI, channelId, contentPolicyType); if (NS_FAILED(rv)) return rv; @@ -2175,11 +2220,6 @@ nsHttpHandler::Observe(nsISupports *subject, // depend on this value. mSessionStartTime = NowInSeconds(); - if (!mDoNotTrackEnabled) { - Telemetry::Accumulate(Telemetry::DNT_USAGE, 2); - } else { - Telemetry::Accumulate(Telemetry::DNT_USAGE, 1); - } } else if (!strcmp(topic, "profile-change-net-restore")) { // initialize connection manager InitConnectionMgr(); @@ -2233,6 +2273,8 @@ nsHttpHandler::Observe(nsISupports *subject, if (mConnMgr) { mConnMgr->DoShiftReloadConnectionCleanup(nullptr); } + } else if (!strcmp(topic, "string-bundles-have-flushed")) { + mAcceptLanguagesIsDirty = true; } return NS_OK; diff --git a/netwerk/protocol/http/nsHttpHandler.h b/netwerk/protocol/http/nsHttpHandler.h index 0904af893..67b9ebe0e 100644 --- a/netwerk/protocol/http/nsHttpHandler.h +++ b/netwerk/protocol/http/nsHttpHandler.h @@ -15,6 +15,7 @@ #include "nsCOMPtr.h" #include "nsWeakReference.h" +#include "nsIContentPolicy.h" #include "nsIHttpProtocolHandler.h" #include "nsIObserver.h" #include "nsISpeculativeConnect.h" @@ -50,6 +51,14 @@ enum FrameCheckLevel { FRAMECHECK_STRICT }; +// Fetch spec different http Accept types +enum AcceptType { + ACCEPT_NAVIGATION, + ACCEPT_IMAGE, + ACCEPT_STYLE, + ACCEPT_DEFAULT, +}; + //----------------------------------------------------------------------------- // nsHttpHandler - protocol handler for HTTP and HTTPS //----------------------------------------------------------------------------- @@ -70,7 +79,7 @@ public: nsHttpHandler(); nsresult Init(); - nsresult AddStandardRequestHeaders(nsHttpRequestHead *, bool isSecure); + nsresult AddStandardRequestHeaders(nsHttpRequestHead *, bool isSecure, nsContentPolicyType aContentPolicyType); nsresult AddConnectionHeader(nsHttpRequestHead *, uint32_t capabilities); bool IsAcceptableEncoding(const char *encoding, bool isSecure); @@ -105,8 +114,10 @@ public: bool EnforceAssocReq() { return mEnforceAssocReq; } bool IsPersistentHttpsCachingEnabled() { return mEnablePersistentHttpsCaching; } - bool IsTelemetryEnabled() { return mTelemetryEnabled; } - bool AllowExperiments() { return mTelemetryEnabled && mAllowExperiments; } + + // Since telemetry has been removed, experiments should also not be allowed. + // Making this function return `false` for now, it will be cleaned up later. + bool AllowExperiments() { return false; } bool IsSpdyEnabled() { return mEnableSpdy; } bool IsHttp2Enabled() { return mHttp2Enabled; } @@ -383,8 +394,8 @@ private: void InitUserAgentComponents(); void PrefsChanged(nsIPrefBranch *prefs, const char *pref); - nsresult SetAccept(const char *); - nsresult SetAcceptLanguages(const char *); + nsresult SetAccept(const char *, AcceptType aType); + nsresult SetAcceptLanguages(); nsresult SetAcceptEncodings(const char *, bool mIsSecure); nsresult InitConnectionMgr(); @@ -392,8 +403,8 @@ private: void NotifyObservers(nsIHttpChannel *chan, const char *event); static void TimerCallback(nsITimer * aTimer, void * aClosure); + private: - // cached services nsMainThreadPtrHandle<nsIIOService> mIOService; nsMainThreadPtrHandle<nsIStreamConverterService> mStreamConvSvc; @@ -458,7 +469,10 @@ private: bool mPipeliningOverSSL; bool mEnforceAssocReq; - nsCString mAccept; + nsCString mAcceptNavigation; + nsCString mAcceptImage; + nsCString mAcceptStyle; + nsCString mAcceptDefault; nsCString mAcceptLanguages; nsCString mHttpAcceptEncodings; nsCString mHttpsAcceptEncodings; @@ -491,6 +505,7 @@ private: nsCString mUserAgent; nsXPIDLCString mUserAgentOverride; bool mUserAgentIsDirty; // true if mUserAgent should be rebuilt + bool mAcceptLanguagesIsDirty; bool mPromptTempRedirect; @@ -508,9 +523,6 @@ private: // true in between init and shutdown states Atomic<bool, Relaxed> mHandlerActive; - // Whether telemetry is reported or not - uint32_t mTelemetryEnabled : 1; - // The value of network.allow-experiments uint32_t mAllowExperiments : 1; diff --git a/netwerk/protocol/http/nsHttpHeaderArray.cpp b/netwerk/protocol/http/nsHttpHeaderArray.cpp index 670300dea..1030bc91e 100644 --- a/netwerk/protocol/http/nsHttpHeaderArray.cpp +++ b/netwerk/protocol/http/nsHttpHeaderArray.cpp @@ -18,12 +18,37 @@ namespace net { //----------------------------------------------------------------------------- // nsHttpHeaderArray <public> //----------------------------------------------------------------------------- + +nsresult +nsHttpHeaderArray::SetHeader(const nsACString &headerName, + const nsACString &value, + bool merge, + nsHttpHeaderArray::HeaderVariety variety) +{ + nsHttpAtom header = nsHttp::ResolveAtom(PromiseFlatCString(headerName).get()); + if (!header) { + NS_WARNING("failed to resolve atom"); + return NS_ERROR_NOT_AVAILABLE; + } + return SetHeader(header, headerName, value, merge, variety); +} + nsresult nsHttpHeaderArray::SetHeader(nsHttpAtom header, const nsACString &value, bool merge, nsHttpHeaderArray::HeaderVariety variety) { + return SetHeader(header, EmptyCString(), value, merge, variety); +} + +nsresult +nsHttpHeaderArray::SetHeader(nsHttpAtom header, + const nsACString &headerName, + const nsACString &value, + bool merge, + nsHttpHeaderArray::HeaderVariety variety) +{ MOZ_ASSERT((variety == eVarietyResponse) || (variety == eVarietyRequestDefault) || (variety == eVarietyRequestOverride), @@ -51,7 +76,7 @@ nsHttpHeaderArray::SetHeader(nsHttpAtom header, MOZ_ASSERT(!entry || variety != eVarietyRequestDefault, "Cannot set default entry which overrides existing entry!"); if (!entry) { - return SetHeader_internal(header, value, variety); + return SetHeader_internal(header, headerName, value, variety); } else if (merge && !IsSingletonHeader(header)) { return MergeHeader(header, entry, value, variety); } else { @@ -59,7 +84,7 @@ nsHttpHeaderArray::SetHeader(nsHttpAtom header, if (entry->variety == eVarietyResponseNetOriginalAndResponse) { MOZ_ASSERT(variety == eVarietyResponse); entry->variety = eVarietyResponseNetOriginal; - return SetHeader_internal(header, value, variety); + return SetHeader_internal(header, headerName, value, variety); } else { entry->value = value; entry->variety = variety; @@ -71,6 +96,7 @@ nsHttpHeaderArray::SetHeader(nsHttpAtom header, nsresult nsHttpHeaderArray::SetHeader_internal(nsHttpAtom header, + const nsACString &headerName, const nsACString &value, nsHttpHeaderArray::HeaderVariety variety) { @@ -79,14 +105,26 @@ nsHttpHeaderArray::SetHeader_internal(nsHttpAtom header, return NS_ERROR_OUT_OF_MEMORY; } entry->header = header; + // Only save original form of a header if it is different than the header + // atom string. + if (!headerName.Equals(header.get())) { + entry->headerNameOriginal = headerName; + } entry->value = value; entry->variety = variety; return NS_OK; } nsresult -nsHttpHeaderArray::SetEmptyHeader(nsHttpAtom header, HeaderVariety variety) +nsHttpHeaderArray::SetEmptyHeader(const nsACString &headerName, + HeaderVariety variety) { + nsHttpAtom header = nsHttp::ResolveAtom(PromiseFlatCString(headerName).get()); + if (!header) { + NS_WARNING("failed to resolve atom"); + return NS_ERROR_NOT_AVAILABLE; + } + MOZ_ASSERT((variety == eVarietyResponse) || (variety == eVarietyRequestDefault) || (variety == eVarietyRequestOverride), @@ -104,11 +142,12 @@ nsHttpHeaderArray::SetEmptyHeader(nsHttpAtom header, HeaderVariety variety) entry->variety = eVarietyResponseNetOriginal; } - return SetHeader_internal(header, EmptyCString(), variety); + return SetHeader_internal(header, headerName, EmptyCString(), variety); } nsresult nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header, + const nsACString &headerNameOriginal, const nsACString &value, bool response) { @@ -125,7 +164,7 @@ nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header, LOG(("Ignoring Empty Header: %s\n", header.get())); if (response) { // Set header as original but not as response header. - return SetHeader_internal(header, value, + return SetHeader_internal(header, headerNameOriginal, value, eVarietyResponseNetOriginal); } return NS_OK; // ignore empty headers by default @@ -135,7 +174,7 @@ nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header, if (response) { variety = eVarietyResponseNetOriginalAndResponse; } - return SetHeader_internal(header, value, variety); + return SetHeader_internal(header, headerNameOriginal, value, variety); } else if (!IsSingletonHeader(header)) { HeaderVariety variety = eVarietyRequestOverride; @@ -147,7 +186,7 @@ nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header, return rv; } if (response) { - rv = SetHeader_internal(header, value, + rv = SetHeader_internal(header, headerNameOriginal, value, eVarietyResponseNetOriginal); } return rv; @@ -164,7 +203,7 @@ nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header, } if (response) { - return SetHeader_internal(header, value, + return SetHeader_internal(header, headerNameOriginal, value, eVarietyResponseNetOriginal); } } @@ -174,6 +213,7 @@ nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header, nsresult nsHttpHeaderArray::SetResponseHeaderFromCache(nsHttpAtom header, + const nsACString &headerNameOriginal, const nsACString &value, nsHttpHeaderArray::HeaderVariety variety) { @@ -183,7 +223,7 @@ nsHttpHeaderArray::SetResponseHeaderFromCache(nsHttpAtom header, "eVarietyResponseNetOriginal"); if (variety == eVarietyResponseNetOriginal) { - return SetHeader_internal(header, value, + return SetHeader_internal(header, headerNameOriginal, value, eVarietyResponseNetOriginal); } else { nsTArray<nsEntry>::index_type index = 0; @@ -203,7 +243,8 @@ nsHttpHeaderArray::SetResponseHeaderFromCache(nsHttpAtom header, } } while (index != mHeaders.NoIndex); // If we are here, we have not found an entry so add a new one. - return SetHeader_internal(header, value, eVarietyResponse); + return SetHeader_internal(header, headerNameOriginal, value, + eVarietyResponse); } } @@ -260,8 +301,16 @@ nsHttpHeaderArray::GetOriginalHeader(nsHttpAtom aHeader, if (entry.variety == eVarietyResponse) { continue; } + + nsAutoCString hdr; + if (entry.headerNameOriginal.IsEmpty()) { + hdr = nsDependentCString(entry.header); + } else { + hdr = entry.headerNameOriginal; + } + rv = NS_OK; - if (NS_FAILED(aVisitor->VisitHeader(nsDependentCString(entry.header), + if (NS_FAILED(aVisitor->VisitHeader(hdr, entry.value))) { break; } @@ -298,8 +347,14 @@ nsHttpHeaderArray::VisitHeaders(nsIHttpHeaderVisitor *visitor, nsHttpHeaderArray } else if (filter == eFilterResponseOriginal && entry.variety == eVarietyResponse) { continue; } - rv = visitor->VisitHeader( - nsDependentCString(entry.header), entry.value); + + nsAutoCString hdr; + if (entry.headerNameOriginal.IsEmpty()) { + hdr = nsDependentCString(entry.header); + } else { + hdr = entry.headerNameOriginal; + } + rv = visitor->VisitHeader(hdr, entry.value); if NS_FAILED(rv) { return rv; } @@ -310,6 +365,7 @@ nsHttpHeaderArray::VisitHeaders(nsIHttpHeaderVisitor *visitor, nsHttpHeaderArray /*static*/ nsresult nsHttpHeaderArray::ParseHeaderLine(const nsACString& line, nsHttpAtom *hdr, + nsACString *headerName, nsACString *val) { // @@ -360,6 +416,7 @@ nsHttpHeaderArray::ParseHeaderLine(const nsACString& line, // assign return values if (hdr) *hdr = atom; if (val) val->Assign(p, p2 - p + 1); + if (headerName) headerName->Assign(sub); return NS_OK; } @@ -397,7 +454,11 @@ nsHttpHeaderArray::Flatten(nsACString &buf, bool pruneProxyHeaders, continue; } - buf.Append(entry.header); + if (entry.headerNameOriginal.IsEmpty()) { + buf.Append(entry.header); + } else { + buf.Append(entry.headerNameOriginal); + } buf.AppendLiteral(": "); buf.Append(entry.value); buf.AppendLiteral("\r\n"); @@ -415,7 +476,11 @@ nsHttpHeaderArray::FlattenOriginalHeader(nsACString &buf) continue; } - buf.Append(entry.header); + if (entry.headerNameOriginal.IsEmpty()) { + buf.Append(entry.header); + } else { + buf.Append(entry.headerNameOriginal); + } buf.AppendLiteral(": "); buf.Append(entry.value); buf.AppendLiteral("\r\n"); @@ -423,11 +488,13 @@ nsHttpHeaderArray::FlattenOriginalHeader(nsACString &buf) } const char * -nsHttpHeaderArray::PeekHeaderAt(uint32_t index, nsHttpAtom &header) const +nsHttpHeaderArray::PeekHeaderAt(uint32_t index, nsHttpAtom &header, + nsACString &headerNameOriginal) const { const nsEntry &entry = mHeaders[index]; header = entry.header; + headerNameOriginal = entry.headerNameOriginal; return entry.value.get(); } diff --git a/netwerk/protocol/http/nsHttpHeaderArray.h b/netwerk/protocol/http/nsHttpHeaderArray.h index 91b91f04a..3ffdfa814 100644 --- a/netwerk/protocol/http/nsHttpHeaderArray.h +++ b/netwerk/protocol/http/nsHttpHeaderArray.h @@ -49,19 +49,30 @@ public: }; // Used by internal setters: to set header from network use SetHeaderFromNet + nsresult SetHeader(const nsACString &headerName, + const nsACString &value, + bool merge, HeaderVariety variety); nsresult SetHeader(nsHttpAtom header, const nsACString &value, bool merge, HeaderVariety variety); + nsresult SetHeader(nsHttpAtom header, + const nsACString &headerName, + const nsACString &value, + bool merge, HeaderVariety variety); // Used by internal setters to set an empty header - nsresult SetEmptyHeader(nsHttpAtom header, HeaderVariety variety); + nsresult SetEmptyHeader(const nsACString &headerName, HeaderVariety variety); // Merges supported headers. For other duplicate values, determines if error // needs to be thrown or 1st value kept. // For the response header we keep the original headers as well. - nsresult SetHeaderFromNet(nsHttpAtom header, const nsACString &value, + nsresult SetHeaderFromNet(nsHttpAtom header, + const nsACString &headerNameOriginal, + const nsACString &value, bool response); - nsresult SetResponseHeaderFromCache(nsHttpAtom header, const nsACString &value, + nsresult SetResponseHeaderFromCache(nsHttpAtom header, + const nsACString &headerNameOriginal, + const nsACString &value, HeaderVariety variety); nsresult GetHeader(nsHttpAtom header, nsACString &value) const; @@ -97,15 +108,17 @@ public: // parse a header line, return the header atom and a pointer to the // header value (the substring of the header line -- do not free). static nsresult ParseHeaderLine(const nsACString& line, - nsHttpAtom *header=nullptr, - nsACString* value=nullptr); + nsHttpAtom *header = nullptr, + nsACString *headerNameOriginal = nullptr, + nsACString *value = nullptr); void Flatten(nsACString &, bool pruneProxyHeaders, bool pruneTransients); void FlattenOriginalHeader(nsACString &); uint32_t Count() const { return mHeaders.Length(); } - const char *PeekHeaderAt(uint32_t i, nsHttpAtom &header) const; + const char *PeekHeaderAt(uint32_t i, nsHttpAtom &header, + nsACString &headerNameOriginal) const; void Clear(); @@ -113,6 +126,7 @@ public: struct nsEntry { nsHttpAtom header; + nsCString headerNameOriginal; nsCString value; HeaderVariety variety = eVarietyUnknown; @@ -140,7 +154,9 @@ private: int32_t LookupEntry(nsHttpAtom header, nsEntry **); nsresult MergeHeader(nsHttpAtom header, nsEntry *entry, const nsACString &value, HeaderVariety variety); - nsresult SetHeader_internal(nsHttpAtom header, const nsACString &value, + nsresult SetHeader_internal(nsHttpAtom header, + const nsACString &headerName, + const nsACString &value, HeaderVariety variety); // Header cannot be merged: only one value possible @@ -257,7 +273,11 @@ nsHttpHeaderArray::MergeHeader(nsHttpAtom header, if (entry->variety == eVarietyResponseNetOriginalAndResponse) { MOZ_ASSERT(variety == eVarietyResponse); entry->variety = eVarietyResponseNetOriginal; - nsresult rv = SetHeader_internal(header, newValue, eVarietyResponse); + // Copy entry->headerNameOriginal because in SetHeader_internal we are going + // to a new one and a realocation can happen. + nsCString headerNameOriginal = entry->headerNameOriginal; + nsresult rv = SetHeader_internal(header, headerNameOriginal, + newValue, eVarietyResponse); if (NS_FAILED(rv)) { return rv; } diff --git a/netwerk/protocol/http/nsHttpPipeline.cpp b/netwerk/protocol/http/nsHttpPipeline.cpp index 293de8e39..4f5777244 100644 --- a/netwerk/protocol/http/nsHttpPipeline.cpp +++ b/netwerk/protocol/http/nsHttpPipeline.cpp @@ -291,6 +291,11 @@ nsHttpPipeline::PushBack(const char *data, uint32_t length) MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); MOZ_ASSERT(mPushBackLen == 0, "push back buffer already has data!"); + // Some bad behaving proxies may yank the connection out from under us. + // Check if we still have a connection to work with. + if (!mConnection) + return NS_ERROR_FAILURE; + // If we have no chance for a pipeline (e.g. due to an Upgrade) // then push this data down to original connection if (!mConnection->IsPersistent()) diff --git a/netwerk/protocol/http/nsHttpRequestHead.cpp b/netwerk/protocol/http/nsHttpRequestHead.cpp index 094a79457..b366a8d54 100644 --- a/netwerk/protocol/http/nsHttpRequestHead.cpp +++ b/netwerk/protocol/http/nsHttpRequestHead.cpp @@ -131,6 +131,20 @@ nsHttpRequestHead::Origin(nsACString &aOrigin) } nsresult +nsHttpRequestHead::SetHeader(const nsACString &h, const nsACString &v, + bool m /*= false*/) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + + if (mInVisitHeaders) { + return NS_ERROR_FAILURE; + } + + return mHeaders.SetHeader(h, v, m, + nsHttpHeaderArray::eVarietyRequestOverride); +} + +nsresult nsHttpRequestHead::SetHeader(nsHttpAtom h, const nsACString &v, bool m /*= false*/) { @@ -158,7 +172,7 @@ nsHttpRequestHead::SetHeader(nsHttpAtom h, const nsACString &v, bool m, } nsresult -nsHttpRequestHead::SetEmptyHeader(nsHttpAtom h) +nsHttpRequestHead::SetEmptyHeader(const nsACString &h) { ReentrantMonitorAutoEnter mon(mReentrantMonitor); @@ -253,6 +267,7 @@ nsHttpRequestHead::ParseHeaderSet(const char *buffer) { ReentrantMonitorAutoEnter mon(mReentrantMonitor); nsHttpAtom hdr; + nsAutoCString headerNameOriginal; nsAutoCString val; while (buffer) { const char *eof = strchr(buffer, '\r'); @@ -262,9 +277,13 @@ nsHttpRequestHead::ParseHeaderSet(const char *buffer) if (NS_SUCCEEDED(nsHttpHeaderArray::ParseHeaderLine( nsDependentCSubstring(buffer, eof - buffer), &hdr, + &headerNameOriginal, &val))) { - mHeaders.SetHeaderFromNet(hdr, val, false); + mHeaders.SetHeaderFromNet(hdr, + headerNameOriginal, + val, + false); } buffer = eof + 1; if (*buffer == '\n') { diff --git a/netwerk/protocol/http/nsHttpRequestHead.h b/netwerk/protocol/http/nsHttpRequestHead.h index 415968083..b7020d33a 100644 --- a/netwerk/protocol/http/nsHttpRequestHead.h +++ b/netwerk/protocol/http/nsHttpRequestHead.h @@ -57,10 +57,12 @@ public: int32_t port); void Origin(nsACString &aOrigin); + nsresult SetHeader(const nsACString &h, const nsACString &v, + bool m=false); nsresult SetHeader(nsHttpAtom h, const nsACString &v, bool m=false); nsresult SetHeader(nsHttpAtom h, const nsACString &v, bool m, nsHttpHeaderArray::HeaderVariety variety); - nsresult SetEmptyHeader(nsHttpAtom h); + nsresult SetEmptyHeader(const nsACString &h); nsresult GetHeader(nsHttpAtom h, nsACString &v); nsresult ClearHeader(nsHttpAtom h); diff --git a/netwerk/protocol/http/nsHttpResponseHead.cpp b/netwerk/protocol/http/nsHttpResponseHead.cpp index 6d384c488..fa6430b82 100644 --- a/netwerk/protocol/http/nsHttpResponseHead.cpp +++ b/netwerk/protocol/http/nsHttpResponseHead.cpp @@ -137,6 +137,26 @@ nsHttpResponseHead::Immutable() } nsresult +nsHttpResponseHead::SetHeader(const nsACString &hdr, + const nsACString &val, + bool merge) +{ + ReentrantMonitorAutoEnter monitor(mReentrantMonitor); + + if (mInVisitHeaders) { + return NS_ERROR_FAILURE; + } + + nsHttpAtom atom = nsHttp::ResolveAtom(PromiseFlatCString(hdr).get()); + if (!atom) { + NS_WARNING("failed to resolve atom"); + return NS_ERROR_NOT_AVAILABLE; + } + + return SetHeader_locked(atom, hdr, val, merge); +} + +nsresult nsHttpResponseHead::SetHeader(nsHttpAtom hdr, const nsACString &val, bool merge) @@ -147,24 +167,25 @@ nsHttpResponseHead::SetHeader(nsHttpAtom hdr, return NS_ERROR_FAILURE; } - return SetHeader_locked(hdr, val, merge); + return SetHeader_locked(hdr, EmptyCString(), val, merge); } nsresult -nsHttpResponseHead::SetHeader_locked(nsHttpAtom hdr, +nsHttpResponseHead::SetHeader_locked(nsHttpAtom atom, + const nsACString &hdr, const nsACString &val, bool merge) { - nsresult rv = mHeaders.SetHeader(hdr, val, merge, + nsresult rv = mHeaders.SetHeader(atom, hdr, val, merge, nsHttpHeaderArray::eVarietyResponse); if (NS_FAILED(rv)) return rv; // respond to changes in these headers. we need to reparse the entire // header since the change may have merged in additional values. - if (hdr == nsHttp::Cache_Control) - ParseCacheControl(mHeaders.PeekHeader(hdr)); - else if (hdr == nsHttp::Pragma) - ParsePragma(mHeaders.PeekHeader(hdr)); + if (atom == nsHttp::Cache_Control) + ParseCacheControl(mHeaders.PeekHeader(atom)); + else if (atom == nsHttp::Pragma) + ParsePragma(mHeaders.PeekHeader(atom)); return NS_OK; } @@ -316,6 +337,7 @@ nsHttpResponseHead::ParseCachedOriginalHeaders(char *block) char *p = block; nsHttpAtom hdr = {0}; + nsAutoCString headerNameOriginal; nsAutoCString val; nsresult rv; @@ -331,12 +353,13 @@ nsHttpResponseHead::ParseCachedOriginalHeaders(char *block) *p = 0; if (NS_FAILED(nsHttpHeaderArray::ParseHeaderLine( - nsDependentCString(block, p - block), &hdr, &val))) { + nsDependentCString(block, p - block), &hdr, &headerNameOriginal, &val))) { return NS_OK; } rv = mHeaders.SetResponseHeaderFromCache(hdr, + headerNameOriginal, val, nsHttpHeaderArray::eVarietyResponseNetOriginal); @@ -567,18 +590,21 @@ nsresult nsHttpResponseHead::ParseHeaderLine_locked(const nsACString &line, bool originalFromNetHeaders) { nsHttpAtom hdr = {0}; + nsAutoCString headerNameOriginal; nsAutoCString val; - if (NS_FAILED(nsHttpHeaderArray::ParseHeaderLine(line, &hdr, &val))) { + if (NS_FAILED(nsHttpHeaderArray::ParseHeaderLine(line, &hdr, &headerNameOriginal, &val))) { return NS_OK; } nsresult rv; if (originalFromNetHeaders) { rv = mHeaders.SetHeaderFromNet(hdr, + headerNameOriginal, val, true); } else { rv = mHeaders.SetResponseHeaderFromCache(hdr, + headerNameOriginal, val, nsHttpHeaderArray::eVarietyResponse); } @@ -856,7 +882,8 @@ nsHttpResponseHead::UpdateHeaders(nsHttpResponseHead *aOther) uint32_t i, count = aOther->mHeaders.Count(); for (i=0; i<count; ++i) { nsHttpAtom header; - const char *val = aOther->mHeaders.PeekHeaderAt(i, header); + nsAutoCString headerNameOriginal; + const char *val = aOther->mHeaders.PeekHeaderAt(i, header, headerNameOriginal); if (!val) { continue; @@ -890,7 +917,8 @@ nsHttpResponseHead::UpdateHeaders(nsHttpResponseHead *aOther) LOG(("new response header [%s: %s]\n", header.get(), val)); // overwrite the current header value with the new value... - SetHeader_locked(header, nsDependentCString(val)); + SetHeader_locked(header, headerNameOriginal, + nsDependentCString(val)); } } diff --git a/netwerk/protocol/http/nsHttpResponseHead.h b/netwerk/protocol/http/nsHttpResponseHead.h index 0a912f4b4..8b51386ea 100644 --- a/netwerk/protocol/http/nsHttpResponseHead.h +++ b/netwerk/protocol/http/nsHttpResponseHead.h @@ -65,6 +65,8 @@ public: */ int64_t TotalEntitySize(); + nsresult SetHeader(const nsACString &h, const nsACString &v, + bool m=false); nsresult SetHeader(nsHttpAtom h, const nsACString &v, bool m=false); nsresult GetHeader(nsHttpAtom h, nsACString &v); void ClearHeader(nsHttpAtom h); @@ -137,8 +139,8 @@ public: bool HasContentType(); bool HasContentCharset(); private: - nsresult SetHeader_locked(nsHttpAtom h, const nsACString &v, - bool m=false); + nsresult SetHeader_locked(nsHttpAtom atom, const nsACString &h, + const nsACString &v, bool m=false); void AssignDefaultStatusText(); void ParseVersion(const char *); void ParseCacheControl(const char *); diff --git a/netwerk/protocol/http/nsHttpTransaction.cpp b/netwerk/protocol/http/nsHttpTransaction.cpp index 8d837d172..76e0a4ad9 100644 --- a/netwerk/protocol/http/nsHttpTransaction.cpp +++ b/netwerk/protocol/http/nsHttpTransaction.cpp @@ -1164,7 +1164,9 @@ nsHttpTransaction::Close(nsresult reason) } // closing this pipe triggers the channel's OnStopRequest method. - mPipeOut->CloseWithStatus(reason); + if (mPipeOut) { + mPipeOut->CloseWithStatus(reason); + } #ifdef WIN32 // bug 1153929 MOZ_DIAGNOSTIC_ASSERT(mPipeOut); |