File: | var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/mozilla/net/OpaqueResponseUtils.h |
Warning: | line 190, 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 | |
23 | #include "nsCOMPtr.h" |
24 | #include "nsString.h" |
25 | #include "nsTArray.h" |
26 | |
27 | class nsIContentSniffer; |
28 | |
29 | namespace mozilla::dom { |
30 | class JSValidatorParent; |
31 | } |
32 | |
33 | namespace mozilla::ipc { |
34 | class Shmem; |
35 | } |
36 | |
37 | namespace mozilla::net { |
38 | |
39 | class HttpBaseChannel; |
40 | class nsHttpResponseHead; |
41 | |
42 | enum class OpaqueResponseBlockedReason : uint32_t { |
43 | ALLOWED_SAFE_LISTED, |
44 | ALLOWED_SAFE_LISTED_SPEC_BREAKING, |
45 | BLOCKED_BLOCKLISTED_NEVER_SNIFFED, |
46 | BLOCKED_206_AND_BLOCKLISTED, |
47 | BLOCKED_NOSNIFF_AND_EITHER_BLOCKLISTED_OR_TEXTPLAIN, |
48 | BLOCKED_SHOULD_SNIFF |
49 | }; |
50 | |
51 | enum class OpaqueResponseBlockedTelemetryReason : uint32_t { |
52 | MIME_NEVER_SNIFFED, |
53 | RESP_206_BLCLISTED, |
54 | NOSNIFF_BLC_OR_TEXTP, |
55 | RESP_206_NO_FIRST, |
56 | AFTER_SNIFF_MEDIA, |
57 | AFTER_SNIFF_NOSNIFF, |
58 | AFTER_SNIFF_STA_CODE, |
59 | AFTER_SNIFF_CT_FAIL, |
60 | MEDIA_NOT_INITIAL, |
61 | MEDIA_INCORRECT_RESP, |
62 | JS_VALIDATION_FAILED |
63 | }; |
64 | |
65 | enum class OpaqueResponse { Block, Allow, SniffCompressed, Sniff }; |
66 | |
67 | OpaqueResponseBlockedReason GetOpaqueResponseBlockedReason( |
68 | const nsACString& aContentType, uint16_t aStatus, bool aNoSniff); |
69 | |
70 | OpaqueResponseBlockedReason GetOpaqueResponseBlockedReason( |
71 | nsHttpResponseHead& aResponseHead); |
72 | |
73 | // Returns a tuple of (rangeStart, rangeEnd, rangeTotal) from the input range |
74 | // header string if succeed. |
75 | Result<std::tuple<int64_t, int64_t, int64_t>, nsresult> |
76 | ParseContentRangeHeaderString(const nsAutoCString& aRangeStr); |
77 | |
78 | bool IsFirstPartialResponse(nsHttpResponseHead& aResponseHead); |
79 | |
80 | LogModule* GetORBLog(); |
81 | |
82 | // Helper class to filter data for opaque responses destined for `Window.fetch`. |
83 | // See https://fetch.spec.whatwg.org/#concept-filtered-response-opaque. |
84 | class OpaqueResponseFilter final : public nsIStreamListener { |
85 | public: |
86 | 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: |
87 | NS_DECL_NSIREQUESTOBSERVERvirtual nsresult OnStartRequest(nsIRequest *aRequest) override ; virtual nsresult OnStopRequest(nsIRequest *aRequest, nsresult aStatusCode) override; |
88 | NS_DECL_NSISTREAMLISTENERvirtual nsresult OnDataAvailable(nsIRequest *aRequest, nsIInputStream *aInputStream, uint64_t aOffset, uint32_t aCount) override;; |
89 | |
90 | explicit OpaqueResponseFilter(nsIStreamListener* aNext); |
91 | |
92 | private: |
93 | virtual ~OpaqueResponseFilter() = default; |
94 | |
95 | nsCOMPtr<nsIStreamListener> mNext; |
96 | }; |
97 | |
98 | class OpaqueResponseBlocker final : public nsIStreamListener { |
99 | enum class State { Sniffing, Allowed, Blocked }; |
100 | |
101 | public: |
102 | 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: |
103 | NS_DECL_NSIREQUESTOBSERVERvirtual nsresult OnStartRequest(nsIRequest *aRequest) override ; virtual nsresult OnStopRequest(nsIRequest *aRequest, nsresult aStatusCode) override; |
104 | NS_DECL_NSISTREAMLISTENERvirtual nsresult OnDataAvailable(nsIRequest *aRequest, nsIInputStream *aInputStream, uint64_t aOffset, uint32_t aCount) override;; |
105 | |
106 | OpaqueResponseBlocker(nsIStreamListener* aNext, HttpBaseChannel* aChannel, |
107 | const nsCString& aContentType, bool aNoSniff); |
108 | |
109 | bool IsSniffing() const; |
110 | void AllowResponse(); |
111 | void BlockResponse(HttpBaseChannel* aChannel, nsresult aStatus); |
112 | void FilterResponse(); |
113 | |
114 | nsresult EnsureOpaqueResponseIsAllowedAfterSniff(nsIRequest* aRequest); |
115 | |
116 | OpaqueResponse EnsureOpaqueResponseIsAllowedAfterJavaScriptValidation( |
117 | HttpBaseChannel* aChannel, bool aAllow); |
118 | |
119 | // The four possible results for validation. `JavaScript` and `JSON` are |
120 | // self-explanatory. `JavaScript` is the only successful result, in the sense |
121 | // that it will allow the opaque response, whereas `JSON` will block. `Other` |
122 | // is the case where validation fails, because the response is neither |
123 | // `JavaScript` nor `JSON`, but the framework itself works as intended. |
124 | // `Failure` implies that something has gone wrong, such as allocation, etc. |
125 | enum class ValidatorResult : uint32_t { JavaScript, JSON, Other, Failure }; |
126 | |
127 | private: |
128 | virtual ~OpaqueResponseBlocker() = default; |
129 | |
130 | nsresult ValidateJavaScript(HttpBaseChannel* aChannel, nsIURI* aURI, |
131 | nsILoadInfo* aLoadInfo); |
132 | |
133 | void ResolveAndProcessData(HttpBaseChannel* aChannel, bool aAllowed, |
134 | Maybe<mozilla::ipc::Shmem>& aSharedData); |
135 | |
136 | void MaybeRunOnStopRequest(HttpBaseChannel* aChannel); |
137 | |
138 | nsCOMPtr<nsIStreamListener> mNext; |
139 | |
140 | const nsCString mContentType; |
141 | const bool mNoSniff; |
142 | bool mShouldFilter = false; |
143 | |
144 | State mState = State::Sniffing; |
145 | nsresult mStatus = NS_OK; |
146 | |
147 | TimeStamp mStartOfJavaScriptValidation; |
148 | |
149 | RefPtr<dom::JSValidatorParent> mJSValidator; |
150 | |
151 | Maybe<nsresult> mPendingOnStopRequestStatus{Nothing()}; |
152 | }; |
153 | |
154 | class nsCompressedAudioVideoImageDetector : public nsUnknownDecoder { |
155 | const std::function<void(void*, const uint8_t*, uint32_t)> mCallback; |
156 | |
157 | public: |
158 | nsCompressedAudioVideoImageDetector( |
159 | nsIStreamListener* aListener, |
160 | std::function<void(void*, const uint8_t*, uint32_t)>&& aCallback) |
161 | : nsUnknownDecoder(aListener), mCallback(aCallback) {} |
162 | |
163 | protected: |
164 | virtual void DetermineContentType(nsIRequest* aRequest) override { |
165 | nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest); |
166 | if (!httpChannel) { |
167 | return; |
168 | } |
169 | |
170 | const char* testData = mBuffer; |
171 | uint32_t testDataLen = mBufferLen; |
172 | // Check if data are compressed. |
173 | nsAutoCString decodedData; |
174 | |
175 | // ConvertEncodedData is always called only on a single thread for each |
176 | // instance of an object. |
177 | nsresult rv = ConvertEncodedData(aRequest, mBuffer, mBufferLen); |
178 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
179 | MutexAutoLock lock(mMutex); |
180 | decodedData = mDecodedData; |
181 | } |
182 | if (!decodedData.IsEmpty()) { |
183 | testData = decodedData.get(); |
184 | testDataLen = std::min<uint32_t>(decodedData.Length(), 512u); |
185 | } |
186 | |
187 | mCallback(httpChannel, (const uint8_t*)testData, testDataLen); |
188 | |
189 | nsAutoCString contentType; |
190 | rv = httpChannel->GetContentType(contentType); |
Value stored to 'rv' is never read | |
191 | |
192 | MutexAutoLock lock(mMutex); |
193 | if (!contentType.IsEmpty()) { |
194 | mContentType = contentType; |
195 | } else { |
196 | mContentType = UNKNOWN_CONTENT_TYPE"application/x-unknown-content-type"; |
197 | } |
198 | |
199 | nsCOMPtr<nsIEncodedChannel> encodedChannel = do_QueryInterface(httpChannel); |
200 | if (encodedChannel) { |
201 | encodedChannel->SetHasContentDecompressed(true); |
202 | } |
203 | } |
204 | }; |
205 | } // namespace mozilla::net |
206 | |
207 | namespace IPC { |
208 | template <> |
209 | struct ParamTraits<mozilla::net::OpaqueResponseBlocker::ValidatorResult> |
210 | : public ContiguousEnumSerializerInclusive< |
211 | mozilla::net::OpaqueResponseBlocker::ValidatorResult, |
212 | mozilla::net::OpaqueResponseBlocker::ValidatorResult::JavaScript, |
213 | mozilla::net::OpaqueResponseBlocker::ValidatorResult::Failure> {}; |
214 | } // namespace IPC |
215 | |
216 | #endif // mozilla_net_OpaqueResponseUtils_h |