| File: | root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/net/OpaqueResponseUtils.h |
| Warning: | line 179, column 5 Value stored to 'rv' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
| 2 | /* vim: set sw=2 ts=8 et tw=80 : */ |
| 3 | |
| 4 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| 7 | |
| 8 | #ifndef mozilla_net_OpaqueResponseUtils_h |
| 9 | #define mozilla_net_OpaqueResponseUtils_h |
| 10 | |
| 11 | #include "ipc/EnumSerializer.h" |
| 12 | #include "mozilla/TimeStamp.h" |
| 13 | #include "nsIContentPolicy.h" |
| 14 | #include "nsIEncodedChannel.h" |
| 15 | #include "nsIStreamListener.h" |
| 16 | #include "nsUnknownDecoder.h" |
| 17 | #include "nsMimeTypes.h" |
| 18 | #include "nsIHttpChannel.h" |
| 19 | |
| 20 | #include "mozilla/Variant.h" |
| 21 | #include "mozilla/Logging.h" |
| 22 | #include "mozilla/glean/NetwerkProtocolHttpMetrics.h" |
| 23 | |
| 24 | #include "nsCOMPtr.h" |
| 25 | #include "nsString.h" |
| 26 | #include "nsTArray.h" |
| 27 | |
| 28 | class nsIContentSniffer; |
| 29 | |
| 30 | namespace mozilla::dom { |
| 31 | class JSValidatorParent; |
| 32 | } |
| 33 | |
| 34 | namespace mozilla::ipc { |
| 35 | class Shmem; |
| 36 | } |
| 37 | |
| 38 | namespace mozilla::net { |
| 39 | |
| 40 | class HttpBaseChannel; |
| 41 | class nsHttpResponseHead; |
| 42 | |
| 43 | enum class OpaqueResponseBlockedReason : uint32_t { |
| 44 | ALLOWED_SAFE_LISTED, |
| 45 | ALLOWED_SAFE_LISTED_SPEC_BREAKING, |
| 46 | BLOCKED_BLOCKLISTED_NEVER_SNIFFED, |
| 47 | BLOCKED_206_AND_BLOCKLISTED, |
| 48 | BLOCKED_NOSNIFF_AND_EITHER_BLOCKLISTED_OR_TEXTPLAIN, |
| 49 | BLOCKED_SHOULD_SNIFF |
| 50 | }; |
| 51 | |
| 52 | using OpaqueResponseBlockedTelemetryReason = glean::orb::BlockReasonLabel; |
| 53 | |
| 54 | enum class OpaqueResponse { Block, Allow, SniffCompressed, Sniff }; |
| 55 | |
| 56 | OpaqueResponseBlockedReason GetOpaqueResponseBlockedReason( |
| 57 | const nsACString& aContentType, uint16_t aStatus, bool aNoSniff); |
| 58 | |
| 59 | OpaqueResponseBlockedReason GetOpaqueResponseBlockedReason( |
| 60 | nsHttpResponseHead& aResponseHead); |
| 61 | |
| 62 | // Returns a tuple of (rangeStart, rangeEnd, rangeTotal) from the input range |
| 63 | // header string if succeed. |
| 64 | Result<std::tuple<int64_t, int64_t, int64_t>, nsresult> |
| 65 | ParseContentRangeHeaderString(const nsAutoCString& aRangeStr); |
| 66 | |
| 67 | bool IsFirstPartialResponse(nsHttpResponseHead& aResponseHead); |
| 68 | |
| 69 | LogModule* GetORBLog(); |
| 70 | |
| 71 | // Helper class to filter data for opaque responses destined for `Window.fetch`. |
| 72 | // See https://fetch.spec.whatwg.org/#concept-filtered-response-opaque. |
| 73 | class OpaqueResponseFilter final : public nsIStreamListener { |
| 74 | public: |
| 75 | NS_DECL_THREADSAFE_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID , void** aInstancePtr) override; virtual MozExternalRefCountType AddRef(void) override; virtual MozExternalRefCountType Release (void) override; using HasThreadSafeRefCnt = std::true_type; protected : ::mozilla::ThreadSafeAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread; public: |
| 76 | NS_DECL_NSIREQUESTOBSERVERvirtual nsresult OnStartRequest(nsIRequest *aRequest) override ; virtual nsresult OnStopRequest(nsIRequest *aRequest, nsresult aStatusCode) override; |
| 77 | NS_DECL_NSISTREAMLISTENERvirtual nsresult OnDataAvailable(nsIRequest *aRequest, nsIInputStream *aInputStream, uint64_t aOffset, uint32_t aCount) override;; |
| 78 | |
| 79 | explicit OpaqueResponseFilter(nsIStreamListener* aNext); |
| 80 | |
| 81 | private: |
| 82 | virtual ~OpaqueResponseFilter() = default; |
| 83 | |
| 84 | nsCOMPtr<nsIStreamListener> mNext; |
| 85 | }; |
| 86 | |
| 87 | class OpaqueResponseBlocker final : public nsIStreamListener { |
| 88 | enum class State { Sniffing, Allowed, Blocked }; |
| 89 | |
| 90 | public: |
| 91 | NS_DECL_THREADSAFE_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID , void** aInstancePtr) override; virtual MozExternalRefCountType AddRef(void) override; virtual MozExternalRefCountType Release (void) override; using HasThreadSafeRefCnt = std::true_type; protected : ::mozilla::ThreadSafeAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread; public: |
| 92 | NS_DECL_NSIREQUESTOBSERVERvirtual nsresult OnStartRequest(nsIRequest *aRequest) override ; virtual nsresult OnStopRequest(nsIRequest *aRequest, nsresult aStatusCode) override; |
| 93 | NS_DECL_NSISTREAMLISTENERvirtual nsresult OnDataAvailable(nsIRequest *aRequest, nsIInputStream *aInputStream, uint64_t aOffset, uint32_t aCount) override;; |
| 94 | |
| 95 | OpaqueResponseBlocker(nsIStreamListener* aNext, HttpBaseChannel* aChannel, |
| 96 | const nsCString& aContentType, bool aNoSniff); |
| 97 | |
| 98 | bool IsSniffing() const; |
| 99 | void AllowResponse(); |
| 100 | void BlockResponse(HttpBaseChannel* aChannel, nsresult aStatus); |
| 101 | void FilterResponse(); |
| 102 | |
| 103 | nsresult EnsureOpaqueResponseIsAllowedAfterSniff(nsIRequest* aRequest); |
| 104 | |
| 105 | OpaqueResponse EnsureOpaqueResponseIsAllowedAfterJavaScriptValidation( |
| 106 | HttpBaseChannel* aChannel, bool aAllow); |
| 107 | |
| 108 | // The four possible results for validation. `JavaScript` and `JSON` are |
| 109 | // self-explanatory. `JavaScript` is the only successful result, in the sense |
| 110 | // that it will allow the opaque response, whereas `JSON` will block. `Other` |
| 111 | // is the case where validation fails, because the response is neither |
| 112 | // `JavaScript` nor `JSON`, but the framework itself works as intended. |
| 113 | // `Failure` implies that something has gone wrong, such as allocation, etc. |
| 114 | enum class ValidatorResult : uint32_t { JavaScript, JSON, Other, Failure }; |
| 115 | |
| 116 | private: |
| 117 | virtual ~OpaqueResponseBlocker() = default; |
| 118 | |
| 119 | nsresult ValidateJavaScript(HttpBaseChannel* aChannel, nsIURI* aURI, |
| 120 | nsILoadInfo* aLoadInfo); |
| 121 | |
| 122 | void ResolveAndProcessData(HttpBaseChannel* aChannel, bool aAllowed, |
| 123 | Maybe<mozilla::ipc::Shmem>& aSharedData); |
| 124 | |
| 125 | void MaybeRunOnStopRequest(HttpBaseChannel* aChannel); |
| 126 | |
| 127 | nsCOMPtr<nsIStreamListener> mNext; |
| 128 | |
| 129 | const nsCString mContentType; |
| 130 | const bool mNoSniff; |
| 131 | bool mShouldFilter = false; |
| 132 | |
| 133 | State mState = State::Sniffing; |
| 134 | nsresult mStatus = NS_OK; |
| 135 | |
| 136 | TimeStamp mStartOfJavaScriptValidation; |
| 137 | |
| 138 | RefPtr<dom::JSValidatorParent> mJSValidator; |
| 139 | |
| 140 | Maybe<nsresult> mPendingOnStopRequestStatus{Nothing()}; |
| 141 | }; |
| 142 | |
| 143 | class nsCompressedAudioVideoImageDetector : public nsUnknownDecoder { |
| 144 | const std::function<void(void*, const uint8_t*, uint32_t)> mCallback; |
| 145 | |
| 146 | public: |
| 147 | nsCompressedAudioVideoImageDetector( |
| 148 | nsIStreamListener* aListener, |
| 149 | std::function<void(void*, const uint8_t*, uint32_t)>&& aCallback) |
| 150 | : nsUnknownDecoder(aListener), mCallback(aCallback) {} |
| 151 | |
| 152 | protected: |
| 153 | virtual void DetermineContentType(nsIRequest* aRequest) override { |
| 154 | nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest); |
| 155 | if (!httpChannel) { |
| 156 | return; |
| 157 | } |
| 158 | |
| 159 | const char* testData = mBuffer; |
| 160 | uint32_t testDataLen = mBufferLen; |
| 161 | // Check if data are compressed. |
| 162 | nsAutoCString decodedData; |
| 163 | |
| 164 | // ConvertEncodedData is always called only on a single thread for each |
| 165 | // instance of an object. |
| 166 | nsresult rv = ConvertEncodedData(aRequest, mBuffer, mBufferLen); |
| 167 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
| 168 | MutexAutoLock lock(mMutex); |
| 169 | decodedData = mDecodedData; |
| 170 | } |
| 171 | if (!decodedData.IsEmpty()) { |
| 172 | testData = decodedData.get(); |
| 173 | testDataLen = std::min<uint32_t>(decodedData.Length(), 512u); |
| 174 | } |
| 175 | |
| 176 | mCallback(httpChannel, (const uint8_t*)testData, testDataLen); |
| 177 | |
| 178 | nsAutoCString contentType; |
| 179 | rv = httpChannel->GetContentType(contentType); |
Value stored to 'rv' is never read | |
| 180 | |
| 181 | MutexAutoLock lock(mMutex); |
| 182 | if (!contentType.IsEmpty()) { |
| 183 | mContentType = contentType; |
| 184 | } else { |
| 185 | mContentType = UNKNOWN_CONTENT_TYPE"application/x-unknown-content-type"; |
| 186 | } |
| 187 | |
| 188 | nsCOMPtr<nsIEncodedChannel> encodedChannel = do_QueryInterface(httpChannel); |
| 189 | if (encodedChannel) { |
| 190 | encodedChannel->SetHasContentDecompressed(true); |
| 191 | } |
| 192 | } |
| 193 | }; |
| 194 | } // namespace mozilla::net |
| 195 | |
| 196 | namespace IPC { |
| 197 | template <> |
| 198 | struct ParamTraits<mozilla::net::OpaqueResponseBlocker::ValidatorResult> |
| 199 | : public ContiguousEnumSerializerInclusive< |
| 200 | mozilla::net::OpaqueResponseBlocker::ValidatorResult, |
| 201 | mozilla::net::OpaqueResponseBlocker::ValidatorResult::JavaScript, |
| 202 | mozilla::net::OpaqueResponseBlocker::ValidatorResult::Failure> {}; |
| 203 | } // namespace IPC |
| 204 | |
| 205 | #endif // mozilla_net_OpaqueResponseUtils_h |