| 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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 |
| OLD | NEW |