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 |