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 : #include "InternalResponse.h"
8 :
9 : #include "mozilla/Assertions.h"
10 : #include "mozilla/dom/InternalHeaders.h"
11 : #include "mozilla/dom/cache/CacheTypes.h"
12 : #include "mozilla/ipc/PBackgroundSharedTypes.h"
13 : #include "mozilla/ipc/IPCStreamUtils.h"
14 : #include "nsIURI.h"
15 : #include "nsStreamUtils.h"
16 :
17 : namespace mozilla {
18 : namespace dom {
19 :
20 2 : InternalResponse::InternalResponse(uint16_t aStatus, const nsACString& aStatusText)
21 : : mType(ResponseType::Default)
22 : , mStatus(aStatus)
23 : , mStatusText(aStatusText)
24 2 : , mHeaders(new InternalHeaders(HeadersGuardEnum::Response))
25 4 : , mBodySize(UNKNOWN_BODY_SIZE)
26 : {
27 2 : }
28 :
29 : already_AddRefed<InternalResponse>
30 0 : InternalResponse::FromIPC(const IPCInternalResponse& aIPCResponse)
31 : {
32 0 : if (aIPCResponse.type() == ResponseType::Error) {
33 0 : return InternalResponse::NetworkError();
34 : }
35 :
36 : RefPtr<InternalResponse> response =
37 0 : new InternalResponse(aIPCResponse.status(),
38 0 : aIPCResponse.statusText());
39 :
40 0 : response->SetURLList(aIPCResponse.urlList());
41 :
42 0 : response->mHeaders = new InternalHeaders(aIPCResponse.headers(),
43 0 : aIPCResponse.headersGuard());
44 :
45 0 : response->InitChannelInfo(aIPCResponse.channelInfo());
46 0 : if (aIPCResponse.principalInfo().type() == mozilla::ipc::OptionalPrincipalInfo::TPrincipalInfo) {
47 0 : UniquePtr<mozilla::ipc::PrincipalInfo> info(new mozilla::ipc::PrincipalInfo(aIPCResponse.principalInfo().get_PrincipalInfo()));
48 0 : response->SetPrincipalInfo(Move(info));
49 : }
50 :
51 0 : nsCOMPtr<nsIInputStream> stream = DeserializeIPCStream(aIPCResponse.body());
52 0 : response->SetBody(stream, aIPCResponse.bodySize());
53 :
54 0 : switch (aIPCResponse.type())
55 : {
56 : case ResponseType::Basic:
57 0 : response = response->BasicResponse();
58 0 : break;
59 : case ResponseType::Cors:
60 0 : response = response->CORSResponse();
61 0 : break;
62 : case ResponseType::Default:
63 0 : break;
64 : case ResponseType::Opaque:
65 0 : response = response->OpaqueResponse();
66 0 : break;
67 : case ResponseType::Opaqueredirect:
68 0 : response = response->OpaqueRedirectResponse();
69 0 : break;
70 : default:
71 0 : MOZ_CRASH("Unexpected ResponseType!");
72 : }
73 0 : MOZ_ASSERT(response);
74 :
75 0 : return response.forget();
76 : }
77 :
78 0 : InternalResponse::~InternalResponse()
79 : {
80 0 : }
81 :
82 : template void
83 : InternalResponse::ToIPC<nsIContentParent>
84 : (IPCInternalResponse* aIPCResponse,
85 : nsIContentParent* aManager,
86 : UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoStream);
87 : template void
88 : InternalResponse::ToIPC<nsIContentChild>
89 : (IPCInternalResponse* aIPCResponse,
90 : nsIContentChild* aManager,
91 : UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoStream);
92 : template void
93 : InternalResponse::ToIPC<mozilla::ipc::PBackgroundParent>
94 : (IPCInternalResponse* aIPCResponse,
95 : mozilla::ipc::PBackgroundParent* aManager,
96 : UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoStream);
97 : template void
98 : InternalResponse::ToIPC<mozilla::ipc::PBackgroundChild>
99 : (IPCInternalResponse* aIPCResponse,
100 : mozilla::ipc::PBackgroundChild* aManager,
101 : UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoStream);
102 :
103 : template<typename M>
104 : void
105 0 : InternalResponse::ToIPC(IPCInternalResponse* aIPCResponse,
106 : M* aManager,
107 : UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoStream)
108 : {
109 0 : MOZ_ASSERT(aIPCResponse);
110 0 : aIPCResponse->type() = mType;
111 0 : aIPCResponse->urlList() = mURLList;
112 0 : aIPCResponse->status() = GetUnfilteredStatus();
113 0 : aIPCResponse->statusText() = GetUnfilteredStatusText();
114 :
115 0 : mHeaders->ToIPC(aIPCResponse->headers(), aIPCResponse->headersGuard());
116 :
117 0 : aIPCResponse->channelInfo() = mChannelInfo.AsIPCChannelInfo();
118 0 : if (mPrincipalInfo) {
119 0 : aIPCResponse->principalInfo() = *mPrincipalInfo;
120 : } else {
121 0 : aIPCResponse->principalInfo() = void_t();
122 : }
123 :
124 0 : nsCOMPtr<nsIInputStream> body;
125 : int64_t bodySize;
126 0 : GetUnfilteredBody(getter_AddRefs(body), &bodySize);
127 :
128 0 : if (body) {
129 0 : aAutoStream.reset(new mozilla::ipc::AutoIPCStream(aIPCResponse->body()));
130 0 : DebugOnly<bool> ok = aAutoStream->Serialize(body, aManager);
131 0 : MOZ_ASSERT(ok);
132 : } else {
133 0 : aIPCResponse->body() = void_t();
134 : }
135 :
136 0 : aIPCResponse->bodySize() = bodySize;
137 0 : }
138 :
139 : already_AddRefed<InternalResponse>
140 0 : InternalResponse::Clone()
141 : {
142 0 : RefPtr<InternalResponse> clone = CreateIncompleteCopy();
143 :
144 0 : clone->mHeaders = new InternalHeaders(*mHeaders);
145 0 : if (mWrappedResponse) {
146 0 : clone->mWrappedResponse = mWrappedResponse->Clone();
147 0 : MOZ_ASSERT(!mBody);
148 0 : return clone.forget();
149 : }
150 :
151 0 : if (!mBody) {
152 0 : return clone.forget();
153 : }
154 :
155 0 : nsCOMPtr<nsIInputStream> clonedBody;
156 0 : nsCOMPtr<nsIInputStream> replacementBody;
157 :
158 0 : nsresult rv = NS_CloneInputStream(mBody, getter_AddRefs(clonedBody),
159 0 : getter_AddRefs(replacementBody));
160 0 : if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; }
161 :
162 0 : clone->mBody.swap(clonedBody);
163 0 : if (replacementBody) {
164 0 : mBody.swap(replacementBody);
165 : }
166 :
167 0 : return clone.forget();
168 : }
169 :
170 : already_AddRefed<InternalResponse>
171 1 : InternalResponse::BasicResponse()
172 : {
173 1 : MOZ_ASSERT(!mWrappedResponse, "Can't BasicResponse a already wrapped response");
174 2 : RefPtr<InternalResponse> basic = CreateIncompleteCopy();
175 1 : basic->mType = ResponseType::Basic;
176 1 : basic->mHeaders = InternalHeaders::BasicHeaders(Headers());
177 1 : basic->mWrappedResponse = this;
178 2 : return basic.forget();
179 : }
180 :
181 : already_AddRefed<InternalResponse>
182 0 : InternalResponse::CORSResponse()
183 : {
184 0 : MOZ_ASSERT(!mWrappedResponse, "Can't CORSResponse a already wrapped response");
185 0 : RefPtr<InternalResponse> cors = CreateIncompleteCopy();
186 0 : cors->mType = ResponseType::Cors;
187 0 : cors->mHeaders = InternalHeaders::CORSHeaders(Headers());
188 0 : cors->mWrappedResponse = this;
189 0 : return cors.forget();
190 : }
191 :
192 : void
193 0 : InternalResponse::SetPrincipalInfo(UniquePtr<mozilla::ipc::PrincipalInfo> aPrincipalInfo)
194 : {
195 0 : mPrincipalInfo = Move(aPrincipalInfo);
196 0 : }
197 :
198 : LoadTainting
199 0 : InternalResponse::GetTainting() const
200 : {
201 0 : switch (mType) {
202 : case ResponseType::Cors:
203 0 : return LoadTainting::CORS;
204 : case ResponseType::Opaque:
205 0 : return LoadTainting::Opaque;
206 : default:
207 0 : return LoadTainting::Basic;
208 : }
209 : }
210 :
211 : already_AddRefed<InternalResponse>
212 0 : InternalResponse::Unfiltered()
213 : {
214 0 : RefPtr<InternalResponse> ref = mWrappedResponse;
215 0 : if (!ref) {
216 0 : ref = this;
217 : }
218 0 : return ref.forget();
219 : }
220 :
221 : already_AddRefed<InternalResponse>
222 0 : InternalResponse::OpaqueResponse()
223 : {
224 0 : MOZ_ASSERT(!mWrappedResponse, "Can't OpaqueResponse a already wrapped response");
225 0 : RefPtr<InternalResponse> response = new InternalResponse(0, EmptyCString());
226 0 : response->mType = ResponseType::Opaque;
227 0 : response->mTerminationReason = mTerminationReason;
228 0 : response->mChannelInfo = mChannelInfo;
229 0 : if (mPrincipalInfo) {
230 0 : response->mPrincipalInfo = MakeUnique<mozilla::ipc::PrincipalInfo>(*mPrincipalInfo);
231 : }
232 0 : response->mWrappedResponse = this;
233 0 : return response.forget();
234 : }
235 :
236 : already_AddRefed<InternalResponse>
237 0 : InternalResponse::OpaqueRedirectResponse()
238 : {
239 0 : MOZ_ASSERT(!mWrappedResponse, "Can't OpaqueRedirectResponse a already wrapped response");
240 0 : MOZ_ASSERT(!mURLList.IsEmpty(), "URLList should not be emtpy for internalResponse");
241 0 : RefPtr<InternalResponse> response = OpaqueResponse();
242 0 : response->mType = ResponseType::Opaqueredirect;
243 0 : response->mURLList = mURLList;
244 0 : return response.forget();
245 : }
246 :
247 : already_AddRefed<InternalResponse>
248 1 : InternalResponse::CreateIncompleteCopy()
249 : {
250 2 : RefPtr<InternalResponse> copy = new InternalResponse(mStatus, mStatusText);
251 1 : copy->mType = mType;
252 1 : copy->mTerminationReason = mTerminationReason;
253 1 : copy->mURLList = mURLList;
254 1 : copy->mChannelInfo = mChannelInfo;
255 1 : if (mPrincipalInfo) {
256 0 : copy->mPrincipalInfo = MakeUnique<mozilla::ipc::PrincipalInfo>(*mPrincipalInfo);
257 : }
258 2 : return copy.forget();
259 : }
260 :
261 : } // namespace dom
262 : } // namespace mozilla
|