diff options
author | wolfbeast <mcwerewolf@wolfbeast.com> | 2019-12-22 01:23:56 +0100 |
---|---|---|
committer | wolfbeast <mcwerewolf@wolfbeast.com> | 2019-12-22 01:26:49 +0100 |
commit | 54091ecab46c93c2e1b2c689e9179a980beaabe6 (patch) | |
tree | 5cead66d889007e1b06c5dbb8e3d37b2538d0557 /netwerk | |
parent | c1013e9122456b342d65e4eb4c38a7281d8d83d2 (diff) | |
parent | 492624a7106ecbc18994b465ca1dd23fa472bf7e (diff) | |
download | UXP-54091ecab46c93c2e1b2c689e9179a980beaabe6.tar UXP-54091ecab46c93c2e1b2c689e9179a980beaabe6.tar.gz UXP-54091ecab46c93c2e1b2c689e9179a980beaabe6.tar.lz UXP-54091ecab46c93c2e1b2c689e9179a980beaabe6.tar.xz UXP-54091ecab46c93c2e1b2c689e9179a980beaabe6.zip |
Forward to new tree structure.
Diffstat (limited to 'netwerk')
-rw-r--r-- | netwerk/base/ProxyAutoConfig.cpp | 26 | ||||
-rw-r--r-- | netwerk/base/nsIBrowserSearchService.idl | 8 | ||||
-rw-r--r-- | netwerk/base/security-prefs.js | 8 | ||||
-rw-r--r-- | netwerk/build/moz.build | 1 | ||||
-rw-r--r-- | netwerk/protocol/http/Http2Session.cpp | 1 | ||||
-rw-r--r-- | netwerk/protocol/http/HttpBaseChannel.cpp | 2 | ||||
-rw-r--r-- | netwerk/protocol/http/nsCORSListenerProxy.cpp | 3 | ||||
-rw-r--r-- | netwerk/protocol/http/nsHttpChannelAuthProvider.cpp | 15 | ||||
-rw-r--r-- | netwerk/protocol/http/nsHttpChannelAuthProvider.h | 3 | ||||
-rw-r--r-- | netwerk/streamconv/converters/moz.build | 1 | ||||
-rw-r--r-- | netwerk/streamconv/converters/nsHTTPCompressConv.cpp | 735 | ||||
-rw-r--r-- | netwerk/streamconv/converters/nsHTTPCompressConv.h | 136 |
12 files changed, 523 insertions, 416 deletions
diff --git a/netwerk/base/ProxyAutoConfig.cpp b/netwerk/base/ProxyAutoConfig.cpp index 4d7a6c1fd..6a9577669 100644 --- a/netwerk/base/ProxyAutoConfig.cpp +++ b/netwerk/base/ProxyAutoConfig.cpp @@ -271,6 +271,7 @@ public: PACResolver() : mStatus(NS_ERROR_FAILURE) + , mMutex("PACResolver::Mutex") { } @@ -279,9 +280,15 @@ public: nsIDNSRecord *record, nsresult status) override { - if (mTimer) { - mTimer->Cancel(); - mTimer = nullptr; + nsCOMPtr<nsITimer> timer; + { + MutexAutoLock lock(mMutex); + timer.swap(mTimer); + mRequest = nullptr; + } + + if (timer) { + timer->Cancel(); } mRequest = nullptr; @@ -293,9 +300,15 @@ public: // nsITimerCallback NS_IMETHOD Notify(nsITimer *timer) override { - if (mRequest) - mRequest->Cancel(NS_ERROR_NET_TIMEOUT); - mTimer = nullptr; + nsCOMPtr<nsICancelable> request; + { + MutexAutoLock lock(mMutex); + request.swap(mRequest); + mTimer = nullptr; + } + if (request) { + request->Cancel(NS_ERROR_NET_TIMEOUT); + } return NS_OK; } @@ -303,6 +316,7 @@ public: nsCOMPtr<nsICancelable> mRequest; nsCOMPtr<nsIDNSRecord> mResponse; nsCOMPtr<nsITimer> mTimer; + Mutex mMutex; private: ~PACResolver() {} diff --git a/netwerk/base/nsIBrowserSearchService.idl b/netwerk/base/nsIBrowserSearchService.idl index 045973e0c..4ca052e91 100644 --- a/netwerk/base/nsIBrowserSearchService.idl +++ b/netwerk/base/nsIBrowserSearchService.idl @@ -7,7 +7,7 @@ interface nsIURI; interface nsIInputStream; -[scriptable, uuid(5799251f-5b55-4df7-a9e7-0c27812c469a)] +[scriptable, uuid(72599f7a-3712-4b93-90e9-86127006cd68)] interface nsISearchSubmission : nsISupports { /** @@ -20,6 +20,12 @@ interface nsISearchSubmission : nsISupports * The URI to submit a search to. */ readonly attribute nsIURI uri; + + /** + * The POST data associated with a search submission as an + * application/x-www-form-urlencoded string. May be null. + */ + readonly attribute AString postDataString; }; [scriptable, uuid(620bd920-0491-48c8-99a8-d6047e64802d)] diff --git a/netwerk/base/security-prefs.js b/netwerk/base/security-prefs.js index ef78ddccb..702315d43 100644 --- a/netwerk/base/security-prefs.js +++ b/netwerk/base/security-prefs.js @@ -132,6 +132,14 @@ pref("security.cert_pinning.process_headers_from_non_builtin_roots", false); // blacking themselves out by setting a bad pin. (60 days by default) // https://tools.ietf.org/html/rfc7469#section-4.1 pref("security.cert_pinning.max_max_age_seconds", 5184000); +// Controls whether or not HPKP (the HTTP Public Key Pinning header) is enabled. +// If true, the header is processed and collected HPKP information is consulted +// when looking for pinning information. +// If false, the header is not processed and collected HPKP information is not +// consulted when looking for pinning information. Preloaded pins are not +// affected by this preference. +// Default: false +pref("security.cert_pinning.hpkp.enabled", false); // If a request is mixed-content, send an HSTS priming request to attempt to // see if it is available over HTTPS. diff --git a/netwerk/build/moz.build b/netwerk/build/moz.build index b7f658688..6cb47f99e 100644 --- a/netwerk/build/moz.build +++ b/netwerk/build/moz.build @@ -69,4 +69,5 @@ if CONFIG['MOZ_RTSP']: LOCAL_INCLUDES += [ '!/netwerk/dns', + '/modules/brotli/dec', ] diff --git a/netwerk/protocol/http/Http2Session.cpp b/netwerk/protocol/http/Http2Session.cpp index 86e8c74f6..726b39f74 100644 --- a/netwerk/protocol/http/Http2Session.cpp +++ b/netwerk/protocol/http/Http2Session.cpp @@ -2182,6 +2182,7 @@ Http2Session::RecvAltSvc(Http2Session *self) } if (NS_FAILED(self->SetInputFrameDataStream(self->mInputFrameID)) || + !self->mInputFrameDataStream || !self->mInputFrameDataStream->Transaction() || !self->mInputFrameDataStream->Transaction()->RequestHead()) { LOG3(("Http2Session::RecvAltSvc %p got frame w/o origin on invalid stream", self)); diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index 86e177e71..568ef3012 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -897,7 +897,7 @@ public: InterceptFailedOnStop(nsIStreamListener *arg, HttpBaseChannel *chan) : mNext(arg) , mChannel(chan) {} - NS_DECL_ISUPPORTS + NS_DECL_THREADSAFE_ISUPPORTS NS_IMETHOD OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) override { diff --git a/netwerk/protocol/http/nsCORSListenerProxy.cpp b/netwerk/protocol/http/nsCORSListenerProxy.cpp index b9355c82b..70035be28 100644 --- a/netwerk/protocol/http/nsCORSListenerProxy.cpp +++ b/netwerk/protocol/http/nsCORSListenerProxy.cpp @@ -907,6 +907,9 @@ nsCORSListenerProxy::UpdateChannel(nsIChannel* aChannel, NS_ENSURE_SUCCESS(rv, rv); } + // TODO: Bug 1353683 + // consider calling SetBlockedRequest in nsCORSListenerProxy::UpdateChannel + // // Check that the uri is ok to load rv = nsContentUtils::GetSecurityManager()-> CheckLoadURIWithPrincipal(mRequestingPrincipal, uri, diff --git a/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp b/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp index a6681cfc6..1b25afe64 100644 --- a/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp +++ b/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp @@ -96,6 +96,7 @@ uint32_t nsHttpChannelAuthProvider::sAuthAllowPref = SUBRESOURCE_AUTH_DIALOG_ALLOW_ALL; bool nsHttpChannelAuthProvider::sImgCrossOriginAuthAllowPref = false; +bool nsHttpChannelAuthProvider::sConfirmAuthPref = false; void nsHttpChannelAuthProvider::InitializePrefs() @@ -107,6 +108,9 @@ nsHttpChannelAuthProvider::InitializePrefs() mozilla::Preferences::AddBoolVarCache(&sImgCrossOriginAuthAllowPref, "network.auth.subresource-http-img-XO-auth", false); + mozilla::Preferences::AddBoolVarCache(&sConfirmAuthPref, + "network.auth.confirmAuth.enabled", + false); } NS_IMETHODIMP @@ -1450,10 +1454,15 @@ nsHttpChannelAuthProvider::ConfirmAuth(const nsString &bundleKey, bool doYesNoPrompt) { // skip prompting the user if - // 1) we've already prompted the user - // 2) we're not a toplevel channel - // 3) the userpass length is less than the "phishy" threshold + // 1) prompts are disabled by preference + // 2) we've already prompted the user + // 3) we're not a toplevel channel + // 4) the userpass length is less than the "phishy" threshold + if (!sConfirmAuthPref) { + return true; + } + uint32_t loadFlags; nsresult rv = mAuthChannel->GetLoadFlags(&loadFlags); if (NS_FAILED(rv)) diff --git a/netwerk/protocol/http/nsHttpChannelAuthProvider.h b/netwerk/protocol/http/nsHttpChannelAuthProvider.h index 0d6045875..18172e60f 100644 --- a/netwerk/protocol/http/nsHttpChannelAuthProvider.h +++ b/netwerk/protocol/http/nsHttpChannelAuthProvider.h @@ -185,6 +185,9 @@ private: static uint32_t sAuthAllowPref; static bool sImgCrossOriginAuthAllowPref; nsCOMPtr<nsICancelable> mGenerateCredentialsCancelable; + + // Variable holding the preference for anti-spoof auth confirmation prompts. + static bool sConfirmAuthPref; }; } // namespace net diff --git a/netwerk/streamconv/converters/moz.build b/netwerk/streamconv/converters/moz.build index d190843c6..10354357b 100644 --- a/netwerk/streamconv/converters/moz.build +++ b/netwerk/streamconv/converters/moz.build @@ -35,5 +35,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'cocoa': FINAL_LIBRARY = 'xul' LOCAL_INCLUDES += [ + '/modules/brotli/dec', '/netwerk/base', ] diff --git a/netwerk/streamconv/converters/nsHTTPCompressConv.cpp b/netwerk/streamconv/converters/nsHTTPCompressConv.cpp index 37b4b28b0..c35b0dcac 100644 --- a/netwerk/streamconv/converters/nsHTTPCompressConv.cpp +++ b/netwerk/streamconv/converters/nsHTTPCompressConv.cpp @@ -20,7 +20,7 @@ // brotli headers #include "state.h" -#include "decode.h" +#include "brotli/decode.h" namespace mozilla { namespace net { @@ -33,7 +33,8 @@ NS_IMPL_ISUPPORTS(nsHTTPCompressConv, nsIStreamConverter, nsIStreamListener, nsIRequestObserver, - nsICompressConvStats) + nsICompressConvStats, + nsIThreadRetargetableStreamListener) // nsFTPDirListingConv methods nsHTTPCompressConv::nsHTTPCompressConv() @@ -45,11 +46,14 @@ nsHTTPCompressConv::nsHTTPCompressConv() , mCheckHeaderDone(false) , mStreamEnded(false) , mStreamInitialized(false) + , mDummyStreamInitialised(false) + , d_stream{} , mLen(0) , hMode(0) , mSkipCount(0) , mFlags(0) , mDecodedDataLength(0) + , mMutex("nsHTTPCompressConv") { LOG(("nsHttpCompresssConv %p ctor\n", this)); if (NS_IsMainThread()) { @@ -60,8 +64,7 @@ nsHTTPCompressConv::nsHTTPCompressConv() } } -nsHTTPCompressConv::~nsHTTPCompressConv() -{ +nsHTTPCompressConv::~nsHTTPCompressConv() { LOG(("nsHttpCompresssConv %p dtor\n", this)); if (mInpBuffer) { free(mInpBuffer); @@ -74,63 +77,64 @@ nsHTTPCompressConv::~nsHTTPCompressConv() // For some reason we are not getting Z_STREAM_END. But this was also seen // for mozilla bug 198133. Need to handle this case. if (mStreamInitialized && !mStreamEnded) { - inflateEnd (&d_stream); + inflateEnd(&d_stream); } } NS_IMETHODIMP -nsHTTPCompressConv::GetDecodedDataLength(uint64_t *aDecodedDataLength) -{ - *aDecodedDataLength = mDecodedDataLength; - return NS_OK; +nsHTTPCompressConv::GetDecodedDataLength(uint64_t* aDecodedDataLength) { + *aDecodedDataLength = mDecodedDataLength; + return NS_OK; } NS_IMETHODIMP -nsHTTPCompressConv::AsyncConvertData(const char *aFromType, - const char *aToType, - nsIStreamListener *aListener, - nsISupports *aCtxt) -{ - if (!PL_strncasecmp(aFromType, HTTP_COMPRESS_TYPE, sizeof(HTTP_COMPRESS_TYPE)-1) || - !PL_strncasecmp(aFromType, HTTP_X_COMPRESS_TYPE, sizeof(HTTP_X_COMPRESS_TYPE)-1)) { +nsHTTPCompressConv::AsyncConvertData(const char* aFromType, const char* aToType, + nsIStreamListener* aListener, + nsISupports* aCtxt) { + if (!PL_strncasecmp(aFromType, HTTP_COMPRESS_TYPE, sizeof(HTTP_COMPRESS_TYPE) - 1) || + !PL_strncasecmp(aFromType, HTTP_X_COMPRESS_TYPE, sizeof(HTTP_X_COMPRESS_TYPE) - 1)) { mMode = HTTP_COMPRESS_COMPRESS; - } else if (!PL_strncasecmp(aFromType, HTTP_GZIP_TYPE, sizeof(HTTP_GZIP_TYPE)-1) || - !PL_strncasecmp(aFromType, HTTP_X_GZIP_TYPE, sizeof(HTTP_X_GZIP_TYPE)-1)) { + } else if (!PL_strncasecmp(aFromType, HTTP_GZIP_TYPE, sizeof(HTTP_GZIP_TYPE) - 1) || + !PL_strncasecmp(aFromType, HTTP_X_GZIP_TYPE, sizeof(HTTP_X_GZIP_TYPE) - 1)) { mMode = HTTP_COMPRESS_GZIP; - } else if (!PL_strncasecmp(aFromType, HTTP_DEFLATE_TYPE, sizeof(HTTP_DEFLATE_TYPE)-1)) { + } else if (!PL_strncasecmp(aFromType, HTTP_DEFLATE_TYPE, sizeof(HTTP_DEFLATE_TYPE) - 1)) { mMode = HTTP_COMPRESS_DEFLATE; - } else if (!PL_strncasecmp(aFromType, HTTP_BROTLI_TYPE, sizeof(HTTP_BROTLI_TYPE)-1)) { + } else if (!PL_strncasecmp(aFromType, HTTP_BROTLI_TYPE, sizeof(HTTP_BROTLI_TYPE) - 1)) { mMode = HTTP_COMPRESS_BROTLI; } - LOG(("nsHttpCompresssConv %p AsyncConvertData %s %s mode %d\n", - this, aFromType, aToType, mMode)); + LOG(("nsHttpCompresssConv %p AsyncConvertData %s %s mode %d\n", this, + aFromType, aToType, (CompressMode)mMode)); + MutexAutoLock lock(mMutex); // hook ourself up with the receiving listener. mListener = aListener; - mAsyncConvContext = aCtxt; return NS_OK; } NS_IMETHODIMP -nsHTTPCompressConv::OnStartRequest(nsIRequest* request, nsISupports *aContext) -{ +nsHTTPCompressConv::OnStartRequest(nsIRequest* request, nsISupports* aContext) { LOG(("nsHttpCompresssConv %p onstart\n", this)); - return mListener->OnStartRequest(request, aContext); + nsCOMPtr<nsIStreamListener> listener; + { + MutexAutoLock lock(mMutex); + listener = mListener; + } + return listener->OnStartRequest(request, aContext); } NS_IMETHODIMP -nsHTTPCompressConv::OnStopRequest(nsIRequest* request, nsISupports *aContext, - nsresult aStatus) -{ +nsHTTPCompressConv::OnStopRequest(nsIRequest* request, nsISupports* aContext, + nsresult aStatus) { nsresult status = aStatus; - LOG(("nsHttpCompresssConv %p onstop %x\n", this, aStatus)); - + LOG(("nsHttpCompresssConv %p onstop %" PRIx32 "\n", this, + static_cast<uint32_t>(aStatus))); + // Framing integrity is enforced for content-encoding: gzip, but not for // content-encoding: deflate. Note that gzip vs deflate is NOT determined // by content sniffing but only via header. if (!mStreamEnded && NS_SUCCEEDED(status) && - (mFailUncleanStops && (mMode == HTTP_COMPRESS_GZIP)) ) { + (mFailUncleanStops && (mMode == HTTP_COMPRESS_GZIP))) { // This is not a clean end of gzip stream: the transfer is incomplete. status = NS_ERROR_NET_PARTIAL_TRANSFER; LOG(("nsHttpCompresssConv %p onstop partial gzip\n", this)); @@ -144,31 +148,40 @@ nsHTTPCompressConv::OnStopRequest(nsIRequest* request, nsISupports *aContext, if (fpChannel && !isPending) { fpChannel->ForcePending(true); } - if (mBrotli && (mBrotli->mTotalOut == 0) && !BrotliStateIsStreamEnd(&mBrotli->mState)) { + if (mBrotli && (mBrotli->mTotalOut == 0) && !mBrotli->mBrotliStateIsStreamEnd) { status = NS_ERROR_INVALID_CONTENT_ENCODING; } - LOG(("nsHttpCompresssConv %p onstop brotlihandler rv %x\n", this, status)); + LOG(("nsHttpCompresssConv %p onstop brotlihandler rv %" PRIx32 "\n", this, + static_cast<uint32_t>(status))); if (fpChannel && !isPending) { fpChannel->ForcePending(false); } } - return mListener->OnStopRequest(request, aContext, status); -} + nsCOMPtr<nsIStreamListener> listener; + { + MutexAutoLock lock(mMutex); + listener = mListener; + } + return listener->OnStopRequest(request, aContext, status); +} -/* static */ nsresult -nsHTTPCompressConv::BrotliHandler(nsIInputStream *stream, void *closure, const char *dataIn, - uint32_t, uint32_t aAvail, uint32_t *countRead) -{ +/* static */ +nsresult nsHTTPCompressConv::BrotliHandler(nsIInputStream* stream, + void* closure, + const char* dataIn, + uint32_t, + uint32_t aAvail, + uint32_t* countRead) { MOZ_ASSERT(stream); - nsHTTPCompressConv *self = static_cast<nsHTTPCompressConv *>(closure); + nsHTTPCompressConv* self = static_cast<nsHTTPCompressConv*>(closure); *countRead = 0; - const size_t kOutSize = 128 * 1024; // just a chunk size, we call in a loop - uint8_t *outPtr; + const size_t kOutSize = 128 * 1024; // just a chunk size, we call in a loop + uint8_t* outPtr; size_t outSize; size_t avail = aAvail; - BrotliResult res; + BrotliDecoderResult res; if (!self->mBrotli) { *countRead = aAvail; @@ -186,15 +199,21 @@ nsHTTPCompressConv::BrotliHandler(nsIInputStream *stream, void *closure, const c outPtr = outBuffer.get(); // brotli api is documented in brotli/dec/decode.h and brotli/dec/decode.c - LOG(("nsHttpCompresssConv %p brotlihandler decompress %d\n", self, avail)); - res = ::BrotliDecompressStream( - &avail, reinterpret_cast<const unsigned char **>(&dataIn), - &outSize, &outPtr, &self->mBrotli->mTotalOut, &self->mBrotli->mState); + LOG(("nsHttpCompresssConv %p brotlihandler decompress %zu\n", self, avail)); + size_t totalOut = self->mBrotli->mTotalOut; + res = ::BrotliDecoderDecompressStream( + &self->mBrotli->mState, &avail, + reinterpret_cast<const unsigned char**>(&dataIn), &outSize, &outPtr, + &totalOut); outSize = kOutSize - outSize; - LOG(("nsHttpCompresssConv %p brotlihandler decompress rv=%x out=%d\n", - self, res, outSize)); - - if (res == BROTLI_RESULT_ERROR) { + self->mBrotli->mTotalOut = totalOut; + self->mBrotli->mBrotliStateIsStreamEnd = + BrotliDecoderIsFinished(&self->mBrotli->mState); + LOG(("nsHttpCompresssConv %p brotlihandler decompress rv=%" PRIx32 + " out=%zu\n", + self, static_cast<uint32_t>(res), outSize)); + + if (res == BROTLI_DECODER_RESULT_ERROR) { LOG(("nsHttpCompressConv %p marking invalid encoding", self)); self->mBrotli->mStatus = NS_ERROR_INVALID_CONTENT_ENCODING; return self->mBrotli->mStatus; @@ -202,7 +221,7 @@ nsHTTPCompressConv::BrotliHandler(nsIInputStream *stream, void *closure, const c // in 'the current implementation' brotli must consume everything before // asking for more input - if (res == BROTLI_RESULT_NEEDS_MORE_INPUT) { + if (res == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) { MOZ_ASSERT(!avail); if (avail) { LOG(("nsHttpCompressConv %p did not consume all input", self)); @@ -214,22 +233,23 @@ nsHTTPCompressConv::BrotliHandler(nsIInputStream *stream, void *closure, const c nsresult rv = self->do_OnDataAvailable(self->mBrotli->mRequest, self->mBrotli->mContext, self->mBrotli->mSourceOffset, - reinterpret_cast<const char *>(outBuffer.get()), + reinterpret_cast<const char*>(outBuffer.get()), outSize); - LOG(("nsHttpCompressConv %p BrotliHandler ODA rv=%x", self, rv)); + LOG(("nsHttpCompressConv %p BrotliHandler ODA rv=%" PRIx32, self, + static_cast<uint32_t>(rv))); if (NS_FAILED(rv)) { self->mBrotli->mStatus = rv; return self->mBrotli->mStatus; } } - if (res == BROTLI_RESULT_SUCCESS || - res == BROTLI_RESULT_NEEDS_MORE_INPUT) { + if (res == BROTLI_DECODER_RESULT_SUCCESS || + res == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) { *countRead = aAvail; return NS_OK; } - MOZ_ASSERT (res == BROTLI_RESULT_NEEDS_MORE_OUTPUT); - } while (res == BROTLI_RESULT_NEEDS_MORE_OUTPUT); + MOZ_ASSERT(res == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT); + } while (res == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT); self->mBrotli->mStatus = NS_ERROR_UNEXPECTED; return self->mBrotli->mStatus; @@ -237,11 +257,10 @@ nsHTTPCompressConv::BrotliHandler(nsIInputStream *stream, void *closure, const c NS_IMETHODIMP nsHTTPCompressConv::OnDataAvailable(nsIRequest* request, - nsISupports *aContext, - nsIInputStream *iStr, + nsISupports* aContext, + nsIInputStream* iStr, uint64_t aSourceOffset, - uint32_t aCount) -{ + uint32_t aCount) { nsresult rv = NS_ERROR_INVALID_CONTENT_ENCODING; uint32_t streamLen = aCount; LOG(("nsHttpCompressConv %p OnDataAvailable %d", this, aCount)); @@ -260,206 +279,216 @@ nsHTTPCompressConv::OnDataAvailable(nsIRequest* request, } switch (mMode) { - case HTTP_COMPRESS_GZIP: - streamLen = check_header(iStr, streamLen, &rv); + case HTTP_COMPRESS_GZIP: + streamLen = check_header(iStr, streamLen, &rv); - if (rv != NS_OK) { - return rv; - } + if (rv != NS_OK) { + return rv; + } - if (streamLen == 0) { - return NS_OK; - } + if (streamLen == 0) { + return NS_OK; + } - MOZ_FALLTHROUGH; + MOZ_FALLTHROUGH; - case HTTP_COMPRESS_DEFLATE: + case HTTP_COMPRESS_DEFLATE: - if (mInpBuffer != nullptr && streamLen > mInpBufferLen) { - mInpBuffer = (unsigned char *) realloc(mInpBuffer, mInpBufferLen = streamLen); + if (mInpBuffer != nullptr && streamLen > mInpBufferLen) { + unsigned char* originalInpBuffer = mInpBuffer; + if (!(mInpBuffer = (unsigned char*)realloc(originalInpBuffer, mInpBufferLen = streamLen))) { + free(originalInpBuffer); + } + + if (mOutBufferLen < streamLen * 2) { + unsigned char* originalOutBuffer = mOutBuffer; + if (!(mOutBuffer = (unsigned char*)realloc(mOutBuffer, mOutBufferLen = streamLen * 3))) { + free(originalOutBuffer); + } + } - if (mOutBufferLen < streamLen * 2) { - mOutBuffer = (unsigned char *) realloc(mOutBuffer, mOutBufferLen = streamLen * 3); + if (mInpBuffer == nullptr || mOutBuffer == nullptr) { + return NS_ERROR_OUT_OF_MEMORY; + } } - if (mInpBuffer == nullptr || mOutBuffer == nullptr) { - return NS_ERROR_OUT_OF_MEMORY; + if (mInpBuffer == nullptr) { + mInpBuffer = (unsigned char*)malloc(mInpBufferLen = streamLen); } - } - if (mInpBuffer == nullptr) { - mInpBuffer = (unsigned char *) malloc(mInpBufferLen = streamLen); - } + if (mOutBuffer == nullptr) { + mOutBuffer = (unsigned char*)malloc(mOutBufferLen = streamLen * 3); + } - if (mOutBuffer == nullptr) { - mOutBuffer = (unsigned char *) malloc(mOutBufferLen = streamLen * 3); - } + if (mInpBuffer == nullptr || mOutBuffer == nullptr) { + return NS_ERROR_OUT_OF_MEMORY; + } - if (mInpBuffer == nullptr || mOutBuffer == nullptr) { - return NS_ERROR_OUT_OF_MEMORY; - } + uint32_t unused; + iStr->Read((char*)mInpBuffer, streamLen, &unused); - uint32_t unused; - iStr->Read((char *)mInpBuffer, streamLen, &unused); + if (mMode == HTTP_COMPRESS_DEFLATE) { + if (!mStreamInitialized) { + memset(&d_stream, 0, sizeof(d_stream)); - if (mMode == HTTP_COMPRESS_DEFLATE) { - if (!mStreamInitialized) { - memset(&d_stream, 0, sizeof (d_stream)); + if (inflateInit(&d_stream) != Z_OK) { + return NS_ERROR_FAILURE; + } - if (inflateInit(&d_stream) != Z_OK) { - return NS_ERROR_FAILURE; + mStreamInitialized = true; } - - mStreamInitialized = true; - } - d_stream.next_in = mInpBuffer; - d_stream.avail_in = (uInt)streamLen; - - mDummyStreamInitialised = false; - for (;;) { - d_stream.next_out = mOutBuffer; - d_stream.avail_out = (uInt)mOutBufferLen; - - int code = inflate(&d_stream, Z_NO_FLUSH); - unsigned bytesWritten = (uInt)mOutBufferLen - d_stream.avail_out; - - if (code == Z_STREAM_END) { - if (bytesWritten) { - rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char *)mOutBuffer, bytesWritten); - if (NS_FAILED (rv)) { - return rv; + d_stream.next_in = mInpBuffer; + d_stream.avail_in = (uInt)streamLen; + + mDummyStreamInitialised = false; + for (;;) { + d_stream.next_out = mOutBuffer; + d_stream.avail_out = (uInt)mOutBufferLen; + + int code = inflate(&d_stream, Z_NO_FLUSH); + unsigned bytesWritten = (uInt)mOutBufferLen - d_stream.avail_out; + + if (code == Z_STREAM_END) { + if (bytesWritten) { + rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char*)mOutBuffer, bytesWritten); + if (NS_FAILED(rv)) { + return rv; + } } - } - inflateEnd(&d_stream); - mStreamEnded = true; - break; - } else if (code == Z_OK) { - if (bytesWritten) { - rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char *)mOutBuffer, bytesWritten); - if (NS_FAILED (rv)) { - return rv; + inflateEnd(&d_stream); + mStreamEnded = true; + break; + } else if (code == Z_OK) { + if (bytesWritten) { + rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char*)mOutBuffer, bytesWritten); + if (NS_FAILED(rv)) { + return rv; + } } - } - } else if (code == Z_BUF_ERROR) { - if (bytesWritten) { - rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char *)mOutBuffer, bytesWritten); - if (NS_FAILED (rv)) { - return rv; + } else if (code == Z_BUF_ERROR) { + if (bytesWritten) { + rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char*)mOutBuffer, bytesWritten); + if (NS_FAILED(rv)) { + return rv; + } } - } - break; - } else if (code == Z_DATA_ERROR) { - // some servers (notably Apache with mod_deflate) don't generate zlib headers - // insert a dummy header and try again - static char dummy_head[2] = - { - 0x8 + 0x7 * 0x10, - (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF, + break; + } else if (code == Z_DATA_ERROR) { + // some servers (notably Apache with mod_deflate) don't generate + // zlib headers insert a dummy header and try again + static char dummy_head[2] = { + 0x8 + 0x7 * 0x10, + (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF, }; - inflateReset(&d_stream); - d_stream.next_in = (Bytef*) dummy_head; - d_stream.avail_in = sizeof(dummy_head); + inflateReset(&d_stream); + d_stream.next_in = (Bytef*)dummy_head; + d_stream.avail_in = sizeof(dummy_head); - code = inflate(&d_stream, Z_NO_FLUSH); - if (code != Z_OK) { - return NS_ERROR_FAILURE; - } + code = inflate(&d_stream, Z_NO_FLUSH); + if (code != Z_OK) { + return NS_ERROR_FAILURE; + } - // stop an endless loop caused by non-deflate data being labelled as deflate - if (mDummyStreamInitialised) { - NS_WARNING("endless loop detected" - " - invalid deflate"); + // stop an endless loop caused by non-deflate data being labelled as + // deflate + if (mDummyStreamInitialised) { + NS_WARNING( + "endless loop detected" + " - invalid deflate"); + return NS_ERROR_INVALID_CONTENT_ENCODING; + } + mDummyStreamInitialised = true; + // reset stream pointers to our original data + d_stream.next_in = mInpBuffer; + d_stream.avail_in = (uInt)streamLen; + } else { return NS_ERROR_INVALID_CONTENT_ENCODING; } - mDummyStreamInitialised = true; - // reset stream pointers to our original data - d_stream.next_in = mInpBuffer; - d_stream.avail_in = (uInt)streamLen; - } else { - return NS_ERROR_INVALID_CONTENT_ENCODING; - } - } /* for */ - } else { - if (!mStreamInitialized) { - memset(&d_stream, 0, sizeof (d_stream)); + } /* for */ + } else { + if (!mStreamInitialized) { + memset(&d_stream, 0, sizeof(d_stream)); - if (inflateInit2(&d_stream, -MAX_WBITS) != Z_OK) { - return NS_ERROR_FAILURE; - } + if (inflateInit2(&d_stream, -MAX_WBITS) != Z_OK) { + return NS_ERROR_FAILURE; + } - mStreamInitialized = true; - } + mStreamInitialized = true; + } - d_stream.next_in = mInpBuffer; - d_stream.avail_in = (uInt)streamLen; + d_stream.next_in = mInpBuffer; + d_stream.avail_in = (uInt)streamLen; - for (;;) { - d_stream.next_out = mOutBuffer; - d_stream.avail_out = (uInt)mOutBufferLen; + for (;;) { + d_stream.next_out = mOutBuffer; + d_stream.avail_out = (uInt)mOutBufferLen; - int code = inflate (&d_stream, Z_NO_FLUSH); - unsigned bytesWritten = (uInt)mOutBufferLen - d_stream.avail_out; + int code = inflate(&d_stream, Z_NO_FLUSH); + unsigned bytesWritten = (uInt)mOutBufferLen - d_stream.avail_out; - if (code == Z_STREAM_END) { - if (bytesWritten) { - rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char *)mOutBuffer, bytesWritten); - if (NS_FAILED (rv)) { - return rv; + if (code == Z_STREAM_END) { + if (bytesWritten) { + rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char*)mOutBuffer, bytesWritten); + if (NS_FAILED(rv)) { + return rv; + } } - } - inflateEnd(&d_stream); - mStreamEnded = true; - break; - } else if (code == Z_OK) { - if (bytesWritten) { - rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char *)mOutBuffer, bytesWritten); - if (NS_FAILED (rv)) { - return rv; + inflateEnd(&d_stream); + mStreamEnded = true; + break; + } else if (code == Z_OK) { + if (bytesWritten) { + rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char*)mOutBuffer, bytesWritten); + if (NS_FAILED(rv)) { + return rv; + } } - } - } else if (code == Z_BUF_ERROR) { - if (bytesWritten) { - rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char *)mOutBuffer, bytesWritten); - if (NS_FAILED (rv)) { - return rv; + } else if (code == Z_BUF_ERROR) { + if (bytesWritten) { + rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char*)mOutBuffer, bytesWritten); + if (NS_FAILED(rv)) { + return rv; + } } + break; + } else { + return NS_ERROR_INVALID_CONTENT_ENCODING; } - break; - } else { - return NS_ERROR_INVALID_CONTENT_ENCODING; - } - } /* for */ - } /* gzip */ - break; + } /* for */ + } /* gzip */ + break; - case HTTP_COMPRESS_BROTLI: - { - if (!mBrotli) { - mBrotli = new BrotliWrapper(); - } + case HTTP_COMPRESS_BROTLI: { + if (!mBrotli) { + mBrotli = new BrotliWrapper(); + } - mBrotli->mRequest = request; - mBrotli->mContext = aContext; - mBrotli->mSourceOffset = aSourceOffset; + mBrotli->mRequest = request; + mBrotli->mContext = nullptr; + mBrotli->mSourceOffset = aSourceOffset; - uint32_t countRead; - rv = iStr->ReadSegments(BrotliHandler, this, streamLen, &countRead); - if (NS_SUCCEEDED(rv)) { - rv = mBrotli->mStatus; - } - if (NS_FAILED(rv)) { - return rv; - } - } - break; + uint32_t countRead; + rv = iStr->ReadSegments(BrotliHandler, this, streamLen, &countRead); + if (NS_SUCCEEDED(rv)) { + rv = mBrotli->mStatus; + } + if (NS_FAILED(rv)) { + return rv; + } + } break; - default: - rv = mListener->OnDataAvailable(request, aContext, iStr, aSourceOffset, aCount); - if (NS_FAILED (rv)) { - return rv; - } + default: + nsCOMPtr<nsIStreamListener> listener; + { + MutexAutoLock lock(mMutex); + listener = mListener; + } + rv = listener->OnDataAvailable(request, aContext, iStr, aSourceOffset, aCount); + if (NS_FAILED(rv)) { + return rv; + } } /* switch */ return NS_OK; @@ -468,20 +497,19 @@ nsHTTPCompressConv::OnDataAvailable(nsIRequest* request, // XXX/ruslan: need to implement this too NS_IMETHODIMP -nsHTTPCompressConv::Convert(nsIInputStream *aFromStream, - const char *aFromType, - const char *aToType, - nsISupports *aCtxt, - nsIInputStream **_retval) -{ +nsHTTPCompressConv::Convert(nsIInputStream* aFromStream, + const char* aFromType, + const char* aToType, + nsISupports* aCtxt, + nsIInputStream** _retval) { return NS_ERROR_NOT_IMPLEMENTED; } -nsresult -nsHTTPCompressConv::do_OnDataAvailable(nsIRequest* request, - nsISupports *context, uint64_t offset, - const char *buffer, uint32_t count) -{ +nsresult nsHTTPCompressConv::do_OnDataAvailable(nsIRequest* request, + nsISupports* context, + uint64_t offset, + const char* buffer, + uint32_t count) { if (!mStream) { mStream = do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID); NS_ENSURE_STATE(mStream); @@ -489,8 +517,12 @@ nsHTTPCompressConv::do_OnDataAvailable(nsIRequest* request, mStream->ShareData(buffer, count); - nsresult rv = mListener->OnDataAvailable(request, context, mStream, - offset, count); + nsCOMPtr<nsIStreamListener> listener; + { + MutexAutoLock lock(mMutex); + listener = mListener; + } + nsresult rv = listener->OnDataAvailable(request, context, mStream, offset, count); // Make sure the stream no longer references |buffer| in case our listener // is crazy enough to try to read from |mStream| after ODA. @@ -500,19 +532,27 @@ nsHTTPCompressConv::do_OnDataAvailable(nsIRequest* request, return rv; } -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ -#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define RESERVED 0xE0 /* bits 5..7: reserved */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ static unsigned gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ -uint32_t -nsHTTPCompressConv::check_header(nsIInputStream *iStr, uint32_t streamLen, nsresult *rs) -{ - enum { GZIP_INIT = 0, GZIP_OS, GZIP_EXTRA0, GZIP_EXTRA1, GZIP_EXTRA2, GZIP_ORIG, GZIP_COMMENT, GZIP_CRC }; +uint32_t nsHTTPCompressConv::check_header(nsIInputStream* iStr, + uint32_t streamLen, nsresult* rs) { + enum { + GZIP_INIT = 0, + GZIP_OS, + GZIP_EXTRA0, + GZIP_EXTRA1, + GZIP_EXTRA2, + GZIP_ORIG, + GZIP_COMMENT, + GZIP_CRC + }; char c; *rs = NS_OK; @@ -523,134 +563,147 @@ nsHTTPCompressConv::check_header(nsIInputStream *iStr, uint32_t streamLen, nsres while (streamLen) { switch (hMode) { - case GZIP_INIT: - uint32_t unused; - iStr->Read(&c, 1, &unused); - streamLen--; - - if (mSkipCount == 0 && ((unsigned)c & 0377) != gz_magic[0]) { - *rs = NS_ERROR_INVALID_CONTENT_ENCODING; - return 0; - } - - if (mSkipCount == 1 && ((unsigned)c & 0377) != gz_magic[1]) { - *rs = NS_ERROR_INVALID_CONTENT_ENCODING; - return 0; - } + case GZIP_INIT: + uint32_t unused; + iStr->Read(&c, 1, &unused); + streamLen--; - if (mSkipCount == 2 && ((unsigned)c & 0377) != Z_DEFLATED) { - *rs = NS_ERROR_INVALID_CONTENT_ENCODING; - return 0; - } + if (mSkipCount == 0 && ((unsigned)c & 0377) != gz_magic[0]) { + *rs = NS_ERROR_INVALID_CONTENT_ENCODING; + return 0; + } - mSkipCount++; - if (mSkipCount == 4) { - mFlags = (unsigned) c & 0377; - if (mFlags & RESERVED) { + if (mSkipCount == 1 && ((unsigned)c & 0377) != gz_magic[1]) { *rs = NS_ERROR_INVALID_CONTENT_ENCODING; return 0; } - hMode = GZIP_OS; - mSkipCount = 0; - } - break; - case GZIP_OS: - iStr->Read(&c, 1, &unused); - streamLen--; - mSkipCount++; + if (mSkipCount == 2 && ((unsigned)c & 0377) != Z_DEFLATED) { + *rs = NS_ERROR_INVALID_CONTENT_ENCODING; + return 0; + } - if (mSkipCount == 6) { - hMode = GZIP_EXTRA0; - } - break; + mSkipCount++; + if (mSkipCount == 4) { + mFlags = (unsigned)c & 0377; + if (mFlags & RESERVED) { + *rs = NS_ERROR_INVALID_CONTENT_ENCODING; + return 0; + } + hMode = GZIP_OS; + mSkipCount = 0; + } + break; - case GZIP_EXTRA0: - if (mFlags & EXTRA_FIELD) { + case GZIP_OS: iStr->Read(&c, 1, &unused); streamLen--; - mLen = (uInt) c & 0377; - hMode = GZIP_EXTRA1; - } else { - hMode = GZIP_ORIG; - } - break; + mSkipCount++; - case GZIP_EXTRA1: - iStr->Read(&c, 1, &unused); - streamLen--; - mLen |= ((uInt) c & 0377) << 8; - mSkipCount = 0; - hMode = GZIP_EXTRA2; - break; + if (mSkipCount == 6) { + hMode = GZIP_EXTRA0; + } + break; + + case GZIP_EXTRA0: + if (mFlags & EXTRA_FIELD) { + iStr->Read(&c, 1, &unused); + streamLen--; + mLen = (uInt)c & 0377; + hMode = GZIP_EXTRA1; + } else { + hMode = GZIP_ORIG; + } + break; - case GZIP_EXTRA2: - if (mSkipCount == mLen) { - hMode = GZIP_ORIG; - } else { + case GZIP_EXTRA1: iStr->Read(&c, 1, &unused); streamLen--; - mSkipCount++; - } - break; + mLen |= ((uInt)c & 0377) << 8; + mSkipCount = 0; + hMode = GZIP_EXTRA2; + break; - case GZIP_ORIG: - if (mFlags & ORIG_NAME) { - iStr->Read(&c, 1, &unused); - streamLen--; - if (c == 0) - hMode = GZIP_COMMENT; - } else { - hMode = GZIP_COMMENT; - } - break; + case GZIP_EXTRA2: + if (mSkipCount == mLen) { + hMode = GZIP_ORIG; + } else { + iStr->Read(&c, 1, &unused); + streamLen--; + mSkipCount++; + } + break; - case GZIP_COMMENT: - if (mFlags & COMMENT) { - iStr->Read(&c, 1, &unused); - streamLen--; - if (c == 0) { + case GZIP_ORIG: + if (mFlags & ORIG_NAME) { + iStr->Read(&c, 1, &unused); + streamLen--; + if (c == 0) hMode = GZIP_COMMENT; + } else { + hMode = GZIP_COMMENT; + } + break; + + case GZIP_COMMENT: + if (mFlags & COMMENT) { + iStr->Read(&c, 1, &unused); + streamLen--; + if (c == 0) { + hMode = GZIP_CRC; + mSkipCount = 0; + } + } else { hMode = GZIP_CRC; mSkipCount = 0; } - } else { - hMode = GZIP_CRC; - mSkipCount = 0; - } - break; - - case GZIP_CRC: - if (mFlags & HEAD_CRC) { - iStr->Read(&c, 1, &unused); - streamLen--; - mSkipCount++; - if (mSkipCount == 2) { + break; + + case GZIP_CRC: + if (mFlags & HEAD_CRC) { + iStr->Read(&c, 1, &unused); + streamLen--; + mSkipCount++; + if (mSkipCount == 2) { + mCheckHeaderDone = true; + return streamLen; + } + } else { mCheckHeaderDone = true; return streamLen; } - } else { - mCheckHeaderDone = true; - return streamLen; - } - break; + break; } } return streamLen; } -} // namespace net -} // namespace mozilla +NS_IMETHODIMP +nsHTTPCompressConv::CheckListenerChain() { + nsCOMPtr<nsIThreadRetargetableStreamListener> listener; + { + MutexAutoLock lock(mMutex); + listener = do_QueryInterface(mListener); + } -nsresult -NS_NewHTTPCompressConv(mozilla::net::nsHTTPCompressConv **aHTTPCompressConv) -{ - NS_PRECONDITION(aHTTPCompressConv != nullptr, "null ptr"); + if (!listener) { + return NS_ERROR_NO_INTERFACE; + } + + return listener->CheckListenerChain(); +} + +} // namespace net +} // namespace mozilla + +nsresult NS_NewHTTPCompressConv( + mozilla::net::nsHTTPCompressConv** aHTTPCompressConv) { + MOZ_ASSERT(aHTTPCompressConv != nullptr, "null ptr"); if (!aHTTPCompressConv) { return NS_ERROR_NULL_POINTER; } RefPtr<mozilla::net::nsHTTPCompressConv> outVal = - new mozilla::net::nsHTTPCompressConv(); + new mozilla::net::nsHTTPCompressConv(); if (!outVal) { return NS_ERROR_OUT_OF_MEMORY; } diff --git a/netwerk/streamconv/converters/nsHTTPCompressConv.h b/netwerk/streamconv/converters/nsHTTPCompressConv.h index 38889a8f7..6721a1e34 100644 --- a/netwerk/streamconv/converters/nsHTTPCompressConv.h +++ b/netwerk/streamconv/converters/nsHTTPCompressConv.h @@ -4,13 +4,16 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined (__nsHTTPCompressConv__h__) -#define __nsHTTPCompressConv__h__ 1 +#if !defined(__nsHTTPCompressConv__h__) +#define __nsHTTPCompressConv__h__ 1 #include "nsIStreamConverter.h" #include "nsICompressConvStats.h" +#include "nsIThreadRetargetableStreamListener.h" #include "nsCOMPtr.h" #include "nsAutoPtr.h" +#include "mozilla/Atomics.h" +#include "mozilla/Mutex.h" #include "zlib.h" @@ -30,20 +33,19 @@ class nsIStringInputStream; {0xab, 0xf4, 0x07, 0x98, 0x61, 0x51, 0x02, 0x2d} \ } - -#define HTTP_DEFLATE_TYPE "deflate" -#define HTTP_GZIP_TYPE "gzip" -#define HTTP_X_GZIP_TYPE "x-gzip" -#define HTTP_COMPRESS_TYPE "compress" -#define HTTP_X_COMPRESS_TYPE "x-compress" -#define HTTP_BROTLI_TYPE "br" -#define HTTP_IDENTITY_TYPE "identity" -#define HTTP_UNCOMPRESSED_TYPE "uncompressed" +#define HTTP_DEFLATE_TYPE "deflate" +#define HTTP_GZIP_TYPE "gzip" +#define HTTP_X_GZIP_TYPE "x-gzip" +#define HTTP_COMPRESS_TYPE "compress" +#define HTTP_X_COMPRESS_TYPE "x-compress" +#define HTTP_BROTLI_TYPE "br" +#define HTTP_IDENTITY_TYPE "identity" +#define HTTP_UNCOMPRESSED_TYPE "uncompressed" namespace mozilla { namespace net { -typedef enum { +typedef enum { HTTP_COMPRESS_GZIP, HTTP_COMPRESS_DEFLATE, HTTP_COMPRESS_COMPRESS, @@ -51,82 +53,88 @@ typedef enum { HTTP_COMPRESS_IDENTITY } CompressMode; -class BrotliWrapper -{ +class BrotliWrapper { public: BrotliWrapper() - : mTotalOut(0) - , mStatus(NS_OK) - { - BrotliStateInit(&mState); - } - ~BrotliWrapper() - { - BrotliStateCleanup(&mState); + : mTotalOut(0), + mStatus(NS_OK), + mBrotliStateIsStreamEnd(false), + mRequest(nullptr), + mContext(nullptr), + mSourceOffset(0) { + BrotliDecoderStateInit(&mState, 0, 0, 0); } + ~BrotliWrapper() { BrotliDecoderStateCleanup(&mState); } - BrotliState mState; - size_t mTotalOut; - nsresult mStatus; + BrotliDecoderState mState; + Atomic<size_t, Relaxed> mTotalOut; + nsresult mStatus; + Atomic<bool, Relaxed> mBrotliStateIsStreamEnd; - nsIRequest *mRequest; - nsISupports *mContext; - uint64_t mSourceOffset; + nsIRequest* mRequest; + nsISupports* mContext; + uint64_t mSourceOffset; }; -class nsHTTPCompressConv - : public nsIStreamConverter - , public nsICompressConvStats -{ - public: +class nsHTTPCompressConv : public nsIStreamConverter, + public nsICompressConvStats, + public nsIThreadRetargetableStreamListener { +public: // nsISupports methods - NS_DECL_THREADSAFE_ISUPPORTS - NS_DECL_NSIREQUESTOBSERVER - NS_DECL_NSISTREAMLISTENER - NS_DECL_NSICOMPRESSCONVSTATS + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSIREQUESTOBSERVER + NS_DECL_NSISTREAMLISTENER + NS_DECL_NSICOMPRESSCONVSTATS + NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER // nsIStreamConverter methods - NS_DECL_NSISTREAMCONVERTER + NS_DECL_NSISTREAMCONVERTER - nsHTTPCompressConv (); + nsHTTPCompressConv(); private: - virtual ~nsHTTPCompressConv (); + virtual ~nsHTTPCompressConv(); + + nsCOMPtr<nsIStreamListener> mListener; // this guy gets the converted data via his OnDataAvailable () + Atomic<CompressMode, Relaxed> mMode; - nsCOMPtr<nsIStreamListener> mListener; // this guy gets the converted data via his OnDataAvailable () - CompressMode mMode; + unsigned char* mOutBuffer; + unsigned char* mInpBuffer; - unsigned char *mOutBuffer; - unsigned char *mInpBuffer; + uint32_t mOutBufferLen; + uint32_t mInpBufferLen; - uint32_t mOutBufferLen; - uint32_t mInpBufferLen; + nsAutoPtr<BrotliWrapper> mBrotli; - nsAutoPtr<BrotliWrapper> mBrotli; + nsCOMPtr<nsIStringInputStream> mStream; - nsCOMPtr<nsISupports> mAsyncConvContext; - nsCOMPtr<nsIStringInputStream> mStream; + static nsresult BrotliHandler(nsIInputStream* stream, + void* closure, + const char* dataIn, + uint32_t, + uint32_t avail, + uint32_t* countRead); - static nsresult - BrotliHandler(nsIInputStream *stream, void *closure, const char *dataIn, - uint32_t, uint32_t avail, uint32_t *countRead); + nsresult do_OnDataAvailable(nsIRequest* request, + nsISupports* aContext, + uint64_t aSourceOffset, + const char* buffer, + uint32_t aCount); - nsresult do_OnDataAvailable (nsIRequest *request, nsISupports *aContext, - uint64_t aSourceOffset, const char *buffer, - uint32_t aCount); + bool mCheckHeaderDone; + Atomic<bool> mStreamEnded; + bool mStreamInitialized; + bool mDummyStreamInitialised; + bool mFailUncleanStops; - bool mCheckHeaderDone; - bool mStreamEnded; - bool mStreamInitialized; - bool mDummyStreamInitialised; - bool mFailUncleanStops; + z_stream d_stream; + unsigned mLen, hMode, mSkipCount, mFlags; - z_stream d_stream; - unsigned mLen, hMode, mSkipCount, mFlags; + uint32_t check_header(nsIInputStream* iStr, uint32_t streamLen, nsresult* rv); - uint32_t check_header (nsIInputStream *iStr, uint32_t streamLen, nsresult *rv); + Atomic<uint32_t, Relaxed> mDecodedDataLength; - uint32_t mDecodedDataLength; + mutable mozilla::Mutex mMutex; }; } // namespace net |