Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef mozilla_dom_InternalResponse_h
8 : #define mozilla_dom_InternalResponse_h
9 :
10 : #include "nsIInputStream.h"
11 : #include "nsISupportsImpl.h"
12 :
13 : #include "mozilla/dom/ResponseBinding.h"
14 : #include "mozilla/dom/ChannelInfo.h"
15 : #include "mozilla/UniquePtr.h"
16 :
17 : namespace mozilla {
18 : namespace ipc {
19 : class PrincipalInfo;
20 : class AutoIPCStream;
21 : } // namespace ipc
22 :
23 : namespace dom {
24 :
25 : class InternalHeaders;
26 : class IPCInternalResponse;
27 :
28 : class InternalResponse final
29 : {
30 : friend class FetchDriver;
31 :
32 : public:
33 6 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InternalResponse)
34 :
35 : InternalResponse(uint16_t aStatus, const nsACString& aStatusText);
36 :
37 : static already_AddRefed<InternalResponse>
38 : FromIPC(const IPCInternalResponse& aIPCResponse);
39 :
40 : template<typename M>
41 : void
42 : ToIPC(IPCInternalResponse* aIPCResponse,
43 : M* aManager,
44 : UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoStream);
45 :
46 : already_AddRefed<InternalResponse> Clone();
47 :
48 : static already_AddRefed<InternalResponse>
49 0 : NetworkError()
50 : {
51 0 : RefPtr<InternalResponse> response = new InternalResponse(0, EmptyCString());
52 0 : ErrorResult result;
53 0 : response->Headers()->SetGuard(HeadersGuardEnum::Immutable, result);
54 0 : MOZ_ASSERT(!result.Failed());
55 0 : response->mType = ResponseType::Error;
56 0 : return response.forget();
57 : }
58 :
59 : already_AddRefed<InternalResponse>
60 : OpaqueResponse();
61 :
62 : already_AddRefed<InternalResponse>
63 : OpaqueRedirectResponse();
64 :
65 : already_AddRefed<InternalResponse>
66 : BasicResponse();
67 :
68 : already_AddRefed<InternalResponse>
69 : CORSResponse();
70 :
71 : ResponseType
72 11 : Type() const
73 : {
74 11 : MOZ_ASSERT_IF(mType == ResponseType::Error, !mWrappedResponse);
75 11 : MOZ_ASSERT_IF(mType == ResponseType::Default, !mWrappedResponse);
76 11 : MOZ_ASSERT_IF(mType == ResponseType::Basic, mWrappedResponse);
77 11 : MOZ_ASSERT_IF(mType == ResponseType::Cors, mWrappedResponse);
78 11 : MOZ_ASSERT_IF(mType == ResponseType::Opaque, mWrappedResponse);
79 11 : MOZ_ASSERT_IF(mType == ResponseType::Opaqueredirect, mWrappedResponse);
80 11 : return mType;
81 : }
82 :
83 : bool
84 1 : IsError() const
85 : {
86 1 : return Type() == ResponseType::Error;
87 : }
88 : // GetUrl should return last fetch URL in response's url list and null if
89 : // response's url list is the empty list.
90 : const nsCString&
91 0 : GetURL() const
92 : {
93 : // Empty urlList when response is a synthetic response.
94 0 : if (mURLList.IsEmpty()) {
95 0 : return EmptyCString();
96 : }
97 0 : return mURLList.LastElement();
98 : }
99 : void
100 0 : GetURLList(nsTArray<nsCString>& aURLList) const
101 : {
102 0 : aURLList.Assign(mURLList);
103 0 : }
104 : const nsCString&
105 0 : GetUnfilteredURL() const
106 : {
107 0 : if (mWrappedResponse) {
108 0 : return mWrappedResponse->GetURL();
109 : }
110 0 : return GetURL();
111 : }
112 : void
113 0 : GetUnfilteredURLList(nsTArray<nsCString>& aURLList) const
114 : {
115 0 : if (mWrappedResponse) {
116 0 : return mWrappedResponse->GetURLList(aURLList);
117 : }
118 :
119 0 : return GetURLList(aURLList);
120 : }
121 :
122 : void
123 1 : SetURLList(const nsTArray<nsCString>& aURLList)
124 : {
125 1 : mURLList.Assign(aURLList);
126 :
127 : #ifdef DEBUG
128 2 : for(uint32_t i = 0; i < mURLList.Length(); ++i) {
129 1 : MOZ_ASSERT(mURLList[i].Find(NS_LITERAL_CSTRING("#")) == kNotFound);
130 : }
131 : #endif
132 1 : }
133 :
134 : uint16_t
135 0 : GetStatus() const
136 : {
137 0 : return mStatus;
138 : }
139 :
140 : uint16_t
141 0 : GetUnfilteredStatus() const
142 : {
143 0 : if (mWrappedResponse) {
144 0 : return mWrappedResponse->GetStatus();
145 : }
146 :
147 0 : return GetStatus();
148 : }
149 :
150 : const nsCString&
151 0 : GetStatusText() const
152 : {
153 0 : return mStatusText;
154 : }
155 :
156 : const nsCString&
157 0 : GetUnfilteredStatusText() const
158 : {
159 0 : if (mWrappedResponse) {
160 0 : return mWrappedResponse->GetStatusText();
161 : }
162 :
163 0 : return GetStatusText();
164 : }
165 :
166 : InternalHeaders*
167 7 : Headers()
168 : {
169 7 : return mHeaders;
170 : }
171 :
172 : InternalHeaders*
173 0 : UnfilteredHeaders()
174 : {
175 0 : if (mWrappedResponse) {
176 0 : return mWrappedResponse->Headers();
177 : };
178 :
179 0 : return Headers();
180 : }
181 :
182 : void
183 2 : GetUnfilteredBody(nsIInputStream** aStream, int64_t* aBodySize = nullptr)
184 : {
185 2 : if (mWrappedResponse) {
186 1 : MOZ_ASSERT(!mBody);
187 1 : return mWrappedResponse->GetBody(aStream, aBodySize);
188 : }
189 2 : nsCOMPtr<nsIInputStream> stream = mBody;
190 1 : stream.forget(aStream);
191 1 : if (aBodySize) {
192 0 : *aBodySize = mBodySize;
193 : }
194 : }
195 :
196 : void
197 2 : GetBody(nsIInputStream** aStream, int64_t* aBodySize = nullptr)
198 : {
199 4 : if (Type() == ResponseType::Opaque ||
200 2 : Type() == ResponseType::Opaqueredirect) {
201 0 : *aStream = nullptr;
202 0 : if (aBodySize) {
203 0 : *aBodySize = UNKNOWN_BODY_SIZE;
204 : }
205 0 : return;
206 : }
207 :
208 2 : return GetUnfilteredBody(aStream, aBodySize);
209 : }
210 :
211 : void
212 1 : SetBody(nsIInputStream* aBody, int64_t aBodySize)
213 : {
214 1 : if (mWrappedResponse) {
215 0 : return mWrappedResponse->SetBody(aBody, aBodySize);
216 : }
217 : // A request's body may not be reset once set.
218 1 : MOZ_ASSERT(!mBody);
219 1 : MOZ_ASSERT(mBodySize == UNKNOWN_BODY_SIZE);
220 : // Check arguments.
221 1 : MOZ_ASSERT(aBodySize == UNKNOWN_BODY_SIZE || aBodySize >= 0);
222 : // If body is not given, then size must be unknown.
223 1 : MOZ_ASSERT_IF(!aBody, aBodySize == UNKNOWN_BODY_SIZE);
224 :
225 1 : mBody = aBody;
226 1 : mBodySize = aBodySize;
227 : }
228 :
229 : void
230 1 : InitChannelInfo(nsIChannel* aChannel)
231 : {
232 1 : mChannelInfo.InitFromChannel(aChannel);
233 1 : }
234 :
235 : void
236 0 : InitChannelInfo(const mozilla::ipc::IPCChannelInfo& aChannelInfo)
237 : {
238 0 : mChannelInfo.InitFromIPCChannelInfo(aChannelInfo);
239 0 : }
240 :
241 : void
242 0 : InitChannelInfo(const ChannelInfo& aChannelInfo)
243 : {
244 0 : mChannelInfo = aChannelInfo;
245 0 : }
246 :
247 : const ChannelInfo&
248 0 : GetChannelInfo() const
249 : {
250 0 : return mChannelInfo;
251 : }
252 :
253 : const UniquePtr<mozilla::ipc::PrincipalInfo>&
254 0 : GetPrincipalInfo() const
255 : {
256 0 : return mPrincipalInfo;
257 : }
258 :
259 : bool
260 0 : IsRedirected() const
261 : {
262 0 : return mURLList.Length() > 1;
263 : }
264 :
265 : // Takes ownership of the principal info.
266 : void
267 : SetPrincipalInfo(UniquePtr<mozilla::ipc::PrincipalInfo> aPrincipalInfo);
268 :
269 : LoadTainting
270 : GetTainting() const;
271 :
272 : already_AddRefed<InternalResponse>
273 : Unfiltered();
274 :
275 : private:
276 : ~InternalResponse();
277 :
278 : explicit InternalResponse(const InternalResponse& aOther) = delete;
279 : InternalResponse& operator=(const InternalResponse&) = delete;
280 :
281 : // Returns an instance of InternalResponse which is a copy of this
282 : // InternalResponse, except headers, body and wrapped response (if any) which
283 : // are left uninitialized. Used for cloning and filtering.
284 : already_AddRefed<InternalResponse> CreateIncompleteCopy();
285 :
286 : ResponseType mType;
287 : nsCString mTerminationReason;
288 : // A response has an associated url list (a list of zero or more fetch URLs).
289 : // Unless stated otherwise, it is the empty list. The current url is the last
290 : // element in mURLlist
291 : nsTArray<nsCString> mURLList;
292 : const uint16_t mStatus;
293 : const nsCString mStatusText;
294 : RefPtr<InternalHeaders> mHeaders;
295 : nsCOMPtr<nsIInputStream> mBody;
296 : int64_t mBodySize;
297 : public:
298 : static const int64_t UNKNOWN_BODY_SIZE = -1;
299 : private:
300 : ChannelInfo mChannelInfo;
301 : UniquePtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
302 :
303 : // For filtered responses.
304 : // Cache, and SW interception should always serialize/access the underlying
305 : // unfiltered headers and when deserializing, create an InternalResponse
306 : // with the unfiltered headers followed by wrapping it.
307 : RefPtr<InternalResponse> mWrappedResponse;
308 : };
309 :
310 : } // namespace dom
311 : } // namespace mozilla
312 :
313 : #endif // mozilla_dom_InternalResponse_h
|