Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(147)

Side by Side Diff: Source/modules/fetch/FetchResponseData.cpp

Issue 1192913007: Change BodyStreamBuffer to be FetchDataConsumerHandle-based and enable backpressure in Fetch API (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Rebase. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
191 {
192 if (m_internalResponse) {
193 return m_internalResponse->m_blobDataHandle;
194 }
195 return m_blobDataHandle;
196 }
197
198 BodyStreamBuffer* FetchResponseData::internalBuffer() const 128 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 = BodyStreamBuffer::create(createFetchDataConsumerHandleFromWeb Handle(handle1.release()));
249 newResponse->m_buffer = new BodyStreamBuffer(canceller2); 177 newResponse->m_buffer = BodyStreamBuffer::create(createFetchDataConsumer HandleFromWebHandle(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)
299 {
300 ASSERT(!m_buffer);
301 m_blobDataHandle = blobDataHandle;
302 }
303
304 void FetchResponseData::replaceBodyStreamBuffer(BodyStreamBuffer* buffer) 220 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
OLDNEW
« no previous file with comments | « Source/modules/fetch/FetchResponseData.h ('k') | Source/modules/fetch/FetchResponseDataTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698