OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 #include "modules/fetch/FetchResponseData.h" | 6 #include "modules/fetch/FetchResponseData.h" |
7 | 7 |
8 #include "core/dom/DOMArrayBuffer.h" | 8 #include "core/dom/DOMArrayBuffer.h" |
9 #include "core/fetch/CrossOriginAccessControl.h" | 9 #include "core/fetch/CrossOriginAccessControl.h" |
10 #include "modules/fetch/BodyStreamBuffer.h" | 10 #include "modules/fetch/BodyStreamBuffer.h" |
| 11 #include "modules/fetch/DataConsumerHandleUtil.h" |
| 12 #include "modules/fetch/DataConsumerTee.h" |
11 #include "modules/fetch/FetchHeaderList.h" | 13 #include "modules/fetch/FetchHeaderList.h" |
12 #include "public/platform/WebServiceWorkerResponse.h" | 14 #include "public/platform/WebServiceWorkerResponse.h" |
13 | 15 |
14 namespace blink { | 16 namespace blink { |
15 | 17 |
16 namespace { | 18 namespace { |
17 | 19 |
18 class BranchCanceller : public BodyStreamBuffer::Canceller { | |
19 public: | |
20 static void create(BodyStreamBuffer* buffer, BranchCanceller** canceller1, B
ranchCanceller** canceller2) | |
21 { | |
22 auto context = new Context(buffer); | |
23 *canceller1 = new BranchCanceller(context, First); | |
24 *canceller2 = new BranchCanceller(context, Second); | |
25 } | |
26 | |
27 void setBuffer(BodyStreamBuffer* buffer) { m_buffer = buffer; } | |
28 | |
29 void cancel() override | |
30 { | |
31 if (m_tag == First) { | |
32 m_context->isFirstCancelled = true; | |
33 } else { | |
34 ASSERT(m_tag == Second); | |
35 m_context->isSecondCancelled = true; | |
36 } | |
37 ASSERT(m_buffer); | |
38 ASSERT(!m_buffer->isClosed()); | |
39 ASSERT(!m_buffer->hasError()); | |
40 m_buffer->close(); | |
41 if (m_context->isFirstCancelled && m_context->isSecondCancelled) | |
42 m_context->buffer->cancel(); | |
43 } | |
44 | |
45 DEFINE_INLINE_VIRTUAL_TRACE() | |
46 { | |
47 visitor->trace(m_context); | |
48 visitor->trace(m_buffer); | |
49 BodyStreamBuffer::Canceller::trace(visitor); | |
50 } | |
51 | |
52 private: | |
53 enum Tag { | |
54 First, | |
55 Second, | |
56 }; | |
57 class Context : public GarbageCollected<Context> { | |
58 public: | |
59 explicit Context(BodyStreamBuffer* buffer) | |
60 : buffer(buffer) | |
61 , isFirstCancelled(false) | |
62 , isSecondCancelled(false) { } | |
63 | |
64 DEFINE_INLINE_VIRTUAL_TRACE() | |
65 { | |
66 visitor->trace(buffer); | |
67 } | |
68 | |
69 Member<BodyStreamBuffer> buffer; | |
70 bool isFirstCancelled; | |
71 bool isSecondCancelled; | |
72 }; | |
73 | |
74 BranchCanceller(Context* context, Tag tag) : m_context(context), m_tag(tag)
{ } | |
75 Member<Context> m_context; | |
76 Member<BodyStreamBuffer> m_buffer; | |
77 Tag m_tag; | |
78 }; | |
79 | |
80 WebServiceWorkerResponseType fetchTypeToWebType(FetchResponseData::Type fetchTyp
e) | 20 WebServiceWorkerResponseType fetchTypeToWebType(FetchResponseData::Type fetchTyp
e) |
81 { | 21 { |
82 WebServiceWorkerResponseType webType = WebServiceWorkerResponseTypeDefault; | 22 WebServiceWorkerResponseType webType = WebServiceWorkerResponseTypeDefault; |
83 switch (fetchType) { | 23 switch (fetchType) { |
84 case FetchResponseData::BasicType: | 24 case FetchResponseData::BasicType: |
85 webType = WebServiceWorkerResponseTypeBasic; | 25 webType = WebServiceWorkerResponseTypeBasic; |
86 break; | 26 break; |
87 case FetchResponseData::CORSType: | 27 case FetchResponseData::CORSType: |
88 webType = WebServiceWorkerResponseTypeCORS; | 28 webType = WebServiceWorkerResponseTypeCORS; |
89 break; | 29 break; |
(...skipping 20 matching lines...) Expand all Loading... |
110 } | 50 } |
111 | 51 |
112 FetchResponseData* FetchResponseData::createNetworkErrorResponse() | 52 FetchResponseData* FetchResponseData::createNetworkErrorResponse() |
113 { | 53 { |
114 // "A network error is a response whose status is always 0, status message | 54 // "A network error is a response whose status is always 0, status message |
115 // is always the empty byte sequence, header list is aways an empty list, | 55 // is always the empty byte sequence, header list is aways an empty list, |
116 // and body is always null." | 56 // and body is always null." |
117 return new FetchResponseData(ErrorType, 0, ""); | 57 return new FetchResponseData(ErrorType, 0, ""); |
118 } | 58 } |
119 | 59 |
120 FetchResponseData* FetchResponseData::createWithBuffer(BodyStreamBuffer* buffer) | 60 FetchResponseData* FetchResponseData::createWithBuffer(BodyStreamBuffer2* buffer
) |
121 { | 61 { |
122 FetchResponseData* response = FetchResponseData::create(); | 62 FetchResponseData* response = FetchResponseData::create(); |
123 response->m_buffer = buffer; | 63 response->m_buffer = buffer; |
124 return response; | 64 return response; |
125 } | 65 } |
126 | 66 |
127 FetchResponseData* FetchResponseData::createBasicFilteredResponse() | 67 FetchResponseData* FetchResponseData::createBasicFilteredResponse() |
128 { | 68 { |
129 // "A basic filtered response is a filtered response whose type is |basic|, | 69 // "A basic filtered response is a filtered response whose type is |basic|, |
130 // header list excludes any headers in internal response's header list whose | 70 // header list excludes any headers in internal response's header list whose |
131 // name is `Set-Cookie` or `Set-Cookie2`." | 71 // name is `Set-Cookie` or `Set-Cookie2`." |
132 FetchResponseData* response = new FetchResponseData(BasicType, m_status, m_s
tatusMessage); | 72 FetchResponseData* response = new FetchResponseData(BasicType, m_status, m_s
tatusMessage); |
133 response->m_url = m_url; | 73 response->m_url = m_url; |
134 for (size_t i = 0; i < m_headerList->size(); ++i) { | 74 for (size_t i = 0; i < m_headerList->size(); ++i) { |
135 const FetchHeaderList::Header* header = m_headerList->list()[i].get(); | 75 const FetchHeaderList::Header* header = m_headerList->list()[i].get(); |
136 if (header->first == "set-cookie" || header->first == "set-cookie2") | 76 if (header->first == "set-cookie" || header->first == "set-cookie2") |
137 continue; | 77 continue; |
138 response->m_headerList->append(header->first, header->second); | 78 response->m_headerList->append(header->first, header->second); |
139 } | 79 } |
140 response->m_blobDataHandle = m_blobDataHandle; | |
141 response->m_buffer = m_buffer; | 80 response->m_buffer = m_buffer; |
142 response->m_mimeType = m_mimeType; | 81 response->m_mimeType = m_mimeType; |
143 response->m_internalResponse = this; | 82 response->m_internalResponse = this; |
144 return response; | 83 return response; |
145 } | 84 } |
146 | 85 |
147 FetchResponseData* FetchResponseData::createCORSFilteredResponse() | 86 FetchResponseData* FetchResponseData::createCORSFilteredResponse() |
148 { | 87 { |
149 // "A CORS filtered response is a filtered response whose type is |CORS|, | 88 // "A CORS filtered response is a filtered response whose type is |CORS|, |
150 // header list excludes all headers in internal response's header list, | 89 // header list excludes all headers in internal response's header list, |
151 // except those whose name is either one of `Cache-Control`, | 90 // except those whose name is either one of `Cache-Control`, |
152 // `Content-Language`, `Content-Type`, `Expires`, `Last-Modified`, and | 91 // `Content-Language`, `Content-Type`, `Expires`, `Last-Modified`, and |
153 // `Pragma`, and except those whose name is one of the values resulting from | 92 // `Pragma`, and except those whose name is one of the values resulting from |
154 // parsing `Access-Control-Expose-Headers` in internal response's header | 93 // parsing `Access-Control-Expose-Headers` in internal response's header |
155 // list." | 94 // list." |
156 FetchResponseData* response = new FetchResponseData(CORSType, m_status, m_st
atusMessage); | 95 FetchResponseData* response = new FetchResponseData(CORSType, m_status, m_st
atusMessage); |
157 response->m_url = m_url; | 96 response->m_url = m_url; |
158 HTTPHeaderSet accessControlExposeHeaderSet; | 97 HTTPHeaderSet accessControlExposeHeaderSet; |
159 String accessControlExposeHeaders; | 98 String accessControlExposeHeaders; |
160 if (m_headerList->get("access-control-expose-headers", accessControlExposeHe
aders)) | 99 if (m_headerList->get("access-control-expose-headers", accessControlExposeHe
aders)) |
161 parseAccessControlExposeHeadersAllowList(accessControlExposeHeaders, acc
essControlExposeHeaderSet); | 100 parseAccessControlExposeHeadersAllowList(accessControlExposeHeaders, acc
essControlExposeHeaderSet); |
162 for (size_t i = 0; i < m_headerList->size(); ++i) { | 101 for (size_t i = 0; i < m_headerList->size(); ++i) { |
163 const FetchHeaderList::Header* header = m_headerList->list()[i].get(); | 102 const FetchHeaderList::Header* header = m_headerList->list()[i].get(); |
164 if (!isOnAccessControlResponseHeaderWhitelist(header->first) && !accessC
ontrolExposeHeaderSet.contains(header->first)) | 103 if (!isOnAccessControlResponseHeaderWhitelist(header->first) && !accessC
ontrolExposeHeaderSet.contains(header->first)) |
165 continue; | 104 continue; |
166 response->m_headerList->append(header->first, header->second); | 105 response->m_headerList->append(header->first, header->second); |
167 } | 106 } |
168 response->m_blobDataHandle = m_blobDataHandle; | |
169 response->m_buffer = m_buffer; | 107 response->m_buffer = m_buffer; |
170 response->m_mimeType = m_mimeType; | 108 response->m_mimeType = m_mimeType; |
171 response->m_internalResponse = this; | 109 response->m_internalResponse = this; |
172 return response; | 110 return response; |
173 } | 111 } |
174 | 112 |
175 FetchResponseData* FetchResponseData::createOpaqueFilteredResponse() | 113 FetchResponseData* FetchResponseData::createOpaqueFilteredResponse() |
176 { | 114 { |
177 // "An opaque filtered response is a filtered response whose type is | 115 // "An opaque filtered response is a filtered response whose type is |
178 // |opaque|, status is 0, status message is the empty byte sequence, header | 116 // |opaque|, status is 0, status message is the empty byte sequence, header |
179 // list is an empty list, and body is null." | 117 // list is an empty list, and body is null." |
180 FetchResponseData* response = new FetchResponseData(OpaqueType, 0, ""); | 118 FetchResponseData* response = new FetchResponseData(OpaqueType, 0, ""); |
181 response->m_internalResponse = this; | 119 response->m_internalResponse = this; |
182 return response; | 120 return response; |
183 } | 121 } |
184 | 122 |
185 String FetchResponseData::mimeType() const | 123 String FetchResponseData::mimeType() const |
186 { | 124 { |
187 return m_mimeType; | 125 return m_mimeType; |
188 } | 126 } |
189 | 127 |
190 PassRefPtr<BlobDataHandle> FetchResponseData::internalBlobDataHandle() const | 128 BodyStreamBuffer2* FetchResponseData::internalBuffer() const |
191 { | |
192 if (m_internalResponse) { | |
193 return m_internalResponse->m_blobDataHandle; | |
194 } | |
195 return m_blobDataHandle; | |
196 } | |
197 | |
198 BodyStreamBuffer* FetchResponseData::internalBuffer() const | |
199 { | 129 { |
200 if (m_internalResponse) { | 130 if (m_internalResponse) { |
201 return m_internalResponse->m_buffer; | 131 return m_internalResponse->m_buffer; |
202 } | 132 } |
203 return m_buffer; | 133 return m_buffer; |
204 } | 134 } |
205 | 135 |
206 String FetchResponseData::internalMIMEType() const | 136 String FetchResponseData::internalMIMEType() const |
207 { | 137 { |
208 if (m_internalResponse) { | 138 if (m_internalResponse) { |
209 return m_internalResponse->mimeType(); | 139 return m_internalResponse->mimeType(); |
210 } | 140 } |
211 return m_mimeType; | 141 return m_mimeType; |
212 } | 142 } |
213 | 143 |
214 FetchResponseData* FetchResponseData::clone() | 144 FetchResponseData* FetchResponseData::clone(ExecutionContext* executionContext) |
215 { | 145 { |
216 FetchResponseData* newResponse = create(); | 146 FetchResponseData* newResponse = create(); |
217 newResponse->m_type = m_type; | 147 newResponse->m_type = m_type; |
218 if (m_terminationReason) { | 148 if (m_terminationReason) { |
219 newResponse->m_terminationReason = adoptPtr(new TerminationReason); | 149 newResponse->m_terminationReason = adoptPtr(new TerminationReason); |
220 *newResponse->m_terminationReason = *m_terminationReason; | 150 *newResponse->m_terminationReason = *m_terminationReason; |
221 } | 151 } |
222 newResponse->m_url = m_url; | 152 newResponse->m_url = m_url; |
223 newResponse->m_status = m_status; | 153 newResponse->m_status = m_status; |
224 newResponse->m_statusMessage = m_statusMessage; | 154 newResponse->m_statusMessage = m_statusMessage; |
225 newResponse->m_headerList = m_headerList->clone(); | 155 newResponse->m_headerList = m_headerList->clone(); |
226 newResponse->m_blobDataHandle = m_blobDataHandle; | |
227 newResponse->m_mimeType = m_mimeType; | 156 newResponse->m_mimeType = m_mimeType; |
228 | 157 |
229 switch (m_type) { | 158 switch (m_type) { |
230 case BasicType: | 159 case BasicType: |
231 case CORSType: | 160 case CORSType: |
232 ASSERT(m_internalResponse); | 161 ASSERT(m_internalResponse); |
233 ASSERT(m_blobDataHandle == m_internalResponse->m_blobDataHandle); | |
234 ASSERT(m_buffer == m_internalResponse->m_buffer); | 162 ASSERT(m_buffer == m_internalResponse->m_buffer); |
235 ASSERT(m_internalResponse->m_type == DefaultType); | 163 ASSERT(m_internalResponse->m_type == DefaultType); |
236 newResponse->m_internalResponse = m_internalResponse->clone(); | 164 newResponse->m_internalResponse = m_internalResponse->clone(executionCon
text); |
237 m_buffer = m_internalResponse->m_buffer; | 165 m_buffer = m_internalResponse->m_buffer; |
238 newResponse->m_buffer = newResponse->m_internalResponse->m_buffer; | 166 newResponse->m_buffer = newResponse->m_internalResponse->m_buffer; |
239 break; | 167 break; |
240 case DefaultType: { | 168 case DefaultType: { |
241 ASSERT(!m_internalResponse); | 169 ASSERT(!m_internalResponse); |
242 if (!m_buffer) | 170 if (!m_buffer) |
243 return newResponse; | 171 return newResponse; |
244 BodyStreamBuffer* original = m_buffer; | 172 |
245 BranchCanceller* canceller1 = nullptr; | 173 OwnPtr<WebDataConsumerHandle> handle1; |
246 BranchCanceller* canceller2 = nullptr; | 174 OwnPtr<WebDataConsumerHandle> handle2; |
247 BranchCanceller::create(original, &canceller1, &canceller2); | 175 DataConsumerTee::create(executionContext, m_buffer->releaseHandle(), &ha
ndle1, &handle2); |
248 m_buffer = new BodyStreamBuffer(canceller1); | 176 m_buffer = BodyStreamBuffer2::create(createFetchDataConsumerHandleFromWe
bHandle(handle1.release())); |
249 newResponse->m_buffer = new BodyStreamBuffer(canceller2); | 177 newResponse->m_buffer = BodyStreamBuffer2::create(createFetchDataConsume
rHandleFromWebHandle(handle2.release())); |
250 canceller1->setBuffer(m_buffer); | |
251 canceller2->setBuffer(newResponse->m_buffer); | |
252 original->startTee(m_buffer, newResponse->m_buffer); | |
253 break; | 178 break; |
254 } | 179 } |
255 case ErrorType: | 180 case ErrorType: |
256 ASSERT(!m_internalResponse); | 181 ASSERT(!m_internalResponse); |
257 ASSERT(!m_blobDataHandle); | |
258 ASSERT(!m_buffer); | 182 ASSERT(!m_buffer); |
259 break; | 183 break; |
260 case OpaqueType: | 184 case OpaqueType: |
261 ASSERT(m_internalResponse); | 185 ASSERT(m_internalResponse); |
262 ASSERT(!m_blobDataHandle); | |
263 ASSERT(!m_buffer); | 186 ASSERT(!m_buffer); |
264 ASSERT(m_internalResponse->m_type == DefaultType); | 187 ASSERT(m_internalResponse->m_type == DefaultType); |
265 newResponse->m_internalResponse = m_internalResponse->clone(); | 188 newResponse->m_internalResponse = m_internalResponse->clone(executionCon
text); |
266 break; | 189 break; |
267 } | 190 } |
268 return newResponse; | 191 return newResponse; |
269 } | 192 } |
270 | 193 |
271 void FetchResponseData::populateWebServiceWorkerResponse(WebServiceWorkerRespons
e& response) | 194 void FetchResponseData::populateWebServiceWorkerResponse(WebServiceWorkerRespons
e& response) |
272 { | 195 { |
273 if (m_internalResponse) { | 196 if (m_internalResponse) { |
274 m_internalResponse->populateWebServiceWorkerResponse(response); | 197 m_internalResponse->populateWebServiceWorkerResponse(response); |
275 response.setResponseType(fetchTypeToWebType(m_type)); | 198 response.setResponseType(fetchTypeToWebType(m_type)); |
276 return; | 199 return; |
277 } | 200 } |
278 | 201 |
279 response.setURL(url()); | 202 response.setURL(url()); |
280 response.setStatus(status()); | 203 response.setStatus(status()); |
281 response.setStatusText(statusMessage()); | 204 response.setStatusText(statusMessage()); |
282 response.setResponseType(fetchTypeToWebType(m_type)); | 205 response.setResponseType(fetchTypeToWebType(m_type)); |
283 for (size_t i = 0; i < headerList()->size(); ++i) { | 206 for (size_t i = 0; i < headerList()->size(); ++i) { |
284 const FetchHeaderList::Header* header = headerList()->list()[i].get(); | 207 const FetchHeaderList::Header* header = headerList()->list()[i].get(); |
285 response.appendHeader(header->first, header->second); | 208 response.appendHeader(header->first, header->second); |
286 } | 209 } |
287 response.setBlobDataHandle(m_blobDataHandle); | |
288 } | 210 } |
289 | 211 |
290 FetchResponseData::FetchResponseData(Type type, unsigned short status, AtomicStr
ing statusMessage) | 212 FetchResponseData::FetchResponseData(Type type, unsigned short status, AtomicStr
ing statusMessage) |
291 : m_type(type) | 213 : m_type(type) |
292 , m_status(status) | 214 , m_status(status) |
293 , m_statusMessage(statusMessage) | 215 , m_statusMessage(statusMessage) |
294 , m_headerList(FetchHeaderList::create()) | 216 , m_headerList(FetchHeaderList::create()) |
295 { | 217 { |
296 } | 218 } |
297 | 219 |
298 void FetchResponseData::setBlobDataHandle(PassRefPtr<BlobDataHandle> blobDataHan
dle) | 220 void FetchResponseData::replaceBodyStreamBuffer(BodyStreamBuffer2* buffer) |
299 { | |
300 ASSERT(!m_buffer); | |
301 m_blobDataHandle = blobDataHandle; | |
302 } | |
303 | |
304 void FetchResponseData::replaceBodyStreamBuffer(BodyStreamBuffer* buffer) | |
305 { | 221 { |
306 if (m_type == BasicType || m_type == CORSType) { | 222 if (m_type == BasicType || m_type == CORSType) { |
307 ASSERT(m_internalResponse); | 223 ASSERT(m_internalResponse); |
308 m_internalResponse->m_blobDataHandle = nullptr; | |
309 m_internalResponse->m_buffer = buffer; | 224 m_internalResponse->m_buffer = buffer; |
310 m_blobDataHandle = nullptr; | |
311 m_buffer = buffer; | 225 m_buffer = buffer; |
312 } else if (m_type == DefaultType) { | 226 } else if (m_type == DefaultType) { |
313 ASSERT(!m_internalResponse); | 227 ASSERT(!m_internalResponse); |
314 m_blobDataHandle = nullptr; | |
315 m_buffer = buffer; | 228 m_buffer = buffer; |
316 } | 229 } |
317 } | 230 } |
318 | 231 |
319 DEFINE_TRACE(FetchResponseData) | 232 DEFINE_TRACE(FetchResponseData) |
320 { | 233 { |
321 visitor->trace(m_headerList); | 234 visitor->trace(m_headerList); |
322 visitor->trace(m_internalResponse); | 235 visitor->trace(m_internalResponse); |
323 visitor->trace(m_buffer); | 236 visitor->trace(m_buffer); |
324 } | 237 } |
325 | 238 |
326 } // namespace blink | 239 } // namespace blink |
OLD | NEW |