| 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 "FetchResponseData.h" | 6 #include "FetchResponseData.h" | 
| 7 | 7 | 
|  | 8 #include "core/dom/DOMArrayBuffer.h" | 
| 8 #include "core/fetch/CrossOriginAccessControl.h" | 9 #include "core/fetch/CrossOriginAccessControl.h" | 
|  | 10 #include "modules/serviceworkers/BodyStreamBuffer.h" | 
| 9 #include "modules/serviceworkers/FetchHeaderList.h" | 11 #include "modules/serviceworkers/FetchHeaderList.h" | 
| 10 #include "public/platform/WebServiceWorkerResponse.h" | 12 #include "public/platform/WebServiceWorkerResponse.h" | 
| 11 | 13 | 
| 12 namespace blink { | 14 namespace blink { | 
| 13 | 15 | 
| 14 namespace { | 16 namespace { | 
| 15 | 17 | 
| 16 WebServiceWorkerResponseType fetchTypeToWebType(FetchResponseData::Type fetchTyp
     e) | 18 WebServiceWorkerResponseType fetchTypeToWebType(FetchResponseData::Type fetchTyp
     e) | 
| 17 { | 19 { | 
| 18     WebServiceWorkerResponseType webType = WebServiceWorkerResponseTypeDefault; | 20     WebServiceWorkerResponseType webType = WebServiceWorkerResponseTypeDefault; | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 29     case FetchResponseData::ErrorType: | 31     case FetchResponseData::ErrorType: | 
| 30         webType = WebServiceWorkerResponseTypeError; | 32         webType = WebServiceWorkerResponseTypeError; | 
| 31         break; | 33         break; | 
| 32     case FetchResponseData::OpaqueType: | 34     case FetchResponseData::OpaqueType: | 
| 33         webType = WebServiceWorkerResponseTypeOpaque; | 35         webType = WebServiceWorkerResponseTypeOpaque; | 
| 34         break; | 36         break; | 
| 35     } | 37     } | 
| 36     return webType; | 38     return webType; | 
| 37 } | 39 } | 
| 38 | 40 | 
|  | 41 class StreamTeePump : public BodyStreamBuffer::Observer { | 
|  | 42 public: | 
|  | 43     StreamTeePump(BodyStreamBuffer* inBuffer, BodyStreamBuffer* outBuffer1, Body
     StreamBuffer* outBuffer2) | 
|  | 44         : m_inBuffer(inBuffer) | 
|  | 45         , m_outBuffer1(outBuffer1) | 
|  | 46         , m_outBuffer2(outBuffer2) | 
|  | 47     { | 
|  | 48     } | 
|  | 49     void onWrite() override | 
|  | 50     { | 
|  | 51         while (RefPtr<DOMArrayBuffer> buf = m_inBuffer->read()) { | 
|  | 52             m_outBuffer1->write(buf); | 
|  | 53             m_outBuffer2->write(buf); | 
|  | 54         } | 
|  | 55     } | 
|  | 56     void onClose() override | 
|  | 57     { | 
|  | 58         m_outBuffer1->close(); | 
|  | 59         m_outBuffer2->close(); | 
|  | 60         cleanup(); | 
|  | 61     } | 
|  | 62     void onError() override | 
|  | 63     { | 
|  | 64         m_outBuffer1->error(m_inBuffer->exception()); | 
|  | 65         m_outBuffer2->error(m_inBuffer->exception()); | 
|  | 66         cleanup(); | 
|  | 67     } | 
|  | 68     void trace(Visitor* visitor) override | 
|  | 69     { | 
|  | 70         BodyStreamBuffer::Observer::trace(visitor); | 
|  | 71         visitor->trace(m_inBuffer); | 
|  | 72         visitor->trace(m_outBuffer1); | 
|  | 73         visitor->trace(m_outBuffer2); | 
|  | 74     } | 
|  | 75     void start() | 
|  | 76     { | 
|  | 77         m_inBuffer->registerObserver(this); | 
|  | 78         onWrite(); | 
|  | 79         if (m_inBuffer->hasError()) | 
|  | 80             return onError(); | 
|  | 81         if (m_inBuffer->isClosed()) | 
|  | 82             return onClose(); | 
|  | 83     } | 
|  | 84 | 
|  | 85 private: | 
|  | 86     void cleanup() | 
|  | 87     { | 
|  | 88         m_inBuffer->unregisterObserver(); | 
|  | 89         m_inBuffer.clear(); | 
|  | 90         m_outBuffer1.clear(); | 
|  | 91         m_outBuffer2.clear(); | 
|  | 92     } | 
|  | 93     Member<BodyStreamBuffer> m_inBuffer; | 
|  | 94     Member<BodyStreamBuffer> m_outBuffer1; | 
|  | 95     Member<BodyStreamBuffer> m_outBuffer2; | 
|  | 96 }; | 
|  | 97 | 
| 39 } // namespace | 98 } // namespace | 
| 40 | 99 | 
| 41 FetchResponseData* FetchResponseData::create() | 100 FetchResponseData* FetchResponseData::create() | 
| 42 { | 101 { | 
| 43     // "Unless stated otherwise, a response's url is null, status is 200, status | 102     // "Unless stated otherwise, a response's url is null, status is 200, status | 
| 44     // message is `OK`, header list is an empty header list, and body is null." | 103     // message is `OK`, header list is an empty header list, and body is null." | 
| 45     return new FetchResponseData(DefaultType, 200, "OK"); | 104     return new FetchResponseData(DefaultType, 200, "OK"); | 
| 46 } | 105 } | 
| 47 | 106 | 
| 48 FetchResponseData* FetchResponseData::createNetworkErrorResponse() | 107 FetchResponseData* FetchResponseData::createNetworkErrorResponse() | 
| 49 { | 108 { | 
| 50     // "A network error is a response whose status is always 0, status message | 109     // "A network error is a response whose status is always 0, status message | 
| 51     // is always the empty byte sequence, header list is aways an empty list, | 110     // is always the empty byte sequence, header list is aways an empty list, | 
| 52     // and body is always null." | 111     // and body is always null." | 
| 53     return new FetchResponseData(ErrorType, 0, ""); | 112     return new FetchResponseData(ErrorType, 0, ""); | 
| 54 } | 113 } | 
| 55 | 114 | 
|  | 115 FetchResponseData* FetchResponseData::createWithBuffer(BodyStreamBuffer* buffer) | 
|  | 116 { | 
|  | 117     FetchResponseData* response = FetchResponseData::create(); | 
|  | 118     response->m_buffer = buffer; | 
|  | 119     return response; | 
|  | 120 } | 
|  | 121 | 
| 56 FetchResponseData* FetchResponseData::createBasicFilteredResponse() | 122 FetchResponseData* FetchResponseData::createBasicFilteredResponse() | 
| 57 { | 123 { | 
| 58     // "A basic filtered response is a filtered response whose type is |basic|, | 124     // "A basic filtered response is a filtered response whose type is |basic|, | 
| 59     // header list excludes any headers in internal response's header list whose | 125     // header list excludes any headers in internal response's header list whose | 
| 60     // name is `Set-Cookie` or `Set-Cookie2`." | 126     // name is `Set-Cookie` or `Set-Cookie2`." | 
| 61     FetchResponseData* response = new FetchResponseData(BasicType, m_status, m_s
     tatusMessage); | 127     FetchResponseData* response = new FetchResponseData(BasicType, m_status, m_s
     tatusMessage); | 
| 62     response->m_url = m_url; | 128     response->m_url = m_url; | 
| 63     for (size_t i = 0; i < m_headerList->size(); ++i) { | 129     for (size_t i = 0; i < m_headerList->size(); ++i) { | 
| 64         const FetchHeaderList::Header* header = m_headerList->list()[i].get(); | 130         const FetchHeaderList::Header* header = m_headerList->list()[i].get(); | 
| 65         if (header->first == "set-cookie" || header->first == "set-cookie2") | 131         if (header->first == "set-cookie" || header->first == "set-cookie2") | 
| 66             continue; | 132             continue; | 
| 67         response->m_headerList->append(header->first, header->second); | 133         response->m_headerList->append(header->first, header->second); | 
| 68     } | 134     } | 
| 69     response->m_blobDataHandle = m_blobDataHandle; | 135     response->m_blobDataHandle = m_blobDataHandle; | 
|  | 136     response->m_buffer = m_buffer; | 
|  | 137     response->m_contentTypeForBuffer = m_contentTypeForBuffer; | 
| 70     response->m_internalResponse = this; | 138     response->m_internalResponse = this; | 
| 71     return response; | 139     return response; | 
| 72 } | 140 } | 
| 73 | 141 | 
| 74 FetchResponseData* FetchResponseData::createCORSFilteredResponse() | 142 FetchResponseData* FetchResponseData::createCORSFilteredResponse() | 
| 75 { | 143 { | 
| 76     // "A CORS filtered response is a filtered response whose type is |CORS|, | 144     // "A CORS filtered response is a filtered response whose type is |CORS|, | 
| 77     // header list excludes all headers in internal response's header list, | 145     // header list excludes all headers in internal response's header list, | 
| 78     // except those whose name is either one of `Cache-Control`, | 146     // except those whose name is either one of `Cache-Control`, | 
| 79     // `Content-Language`, `Content-Type`, `Expires`, `Last-Modified`, and | 147     // `Content-Language`, `Content-Type`, `Expires`, `Last-Modified`, and | 
| 80     // `Pragma`, and except those whose name is one of the values resulting from | 148     // `Pragma`, and except those whose name is one of the values resulting from | 
| 81     // parsing `Access-Control-Expose-Headers` in internal response's header | 149     // parsing `Access-Control-Expose-Headers` in internal response's header | 
| 82     // list." | 150     // list." | 
| 83     FetchResponseData* response = new FetchResponseData(CORSType, m_status, m_st
     atusMessage); | 151     FetchResponseData* response = new FetchResponseData(CORSType, m_status, m_st
     atusMessage); | 
| 84     response->m_url = m_url; | 152     response->m_url = m_url; | 
| 85     HTTPHeaderSet accessControlExposeHeaderSet; | 153     HTTPHeaderSet accessControlExposeHeaderSet; | 
| 86     String accessControlExposeHeaders; | 154     String accessControlExposeHeaders; | 
| 87     if (m_headerList->get("access-control-expose-headers", accessControlExposeHe
     aders)) | 155     if (m_headerList->get("access-control-expose-headers", accessControlExposeHe
     aders)) | 
| 88         parseAccessControlExposeHeadersAllowList(accessControlExposeHeaders, acc
     essControlExposeHeaderSet); | 156         parseAccessControlExposeHeadersAllowList(accessControlExposeHeaders, acc
     essControlExposeHeaderSet); | 
| 89     for (size_t i = 0; i < m_headerList->size(); ++i) { | 157     for (size_t i = 0; i < m_headerList->size(); ++i) { | 
| 90         const FetchHeaderList::Header* header = m_headerList->list()[i].get(); | 158         const FetchHeaderList::Header* header = m_headerList->list()[i].get(); | 
| 91         if (!isOnAccessControlResponseHeaderWhitelist(header->first) && !accessC
     ontrolExposeHeaderSet.contains(header->first)) | 159         if (!isOnAccessControlResponseHeaderWhitelist(header->first) && !accessC
     ontrolExposeHeaderSet.contains(header->first)) | 
| 92             continue; | 160             continue; | 
| 93         response->m_headerList->append(header->first, header->second); | 161         response->m_headerList->append(header->first, header->second); | 
| 94     } | 162     } | 
| 95     response->m_blobDataHandle = m_blobDataHandle; | 163     response->m_blobDataHandle = m_blobDataHandle; | 
|  | 164     response->m_buffer = m_buffer; | 
|  | 165     response->m_contentTypeForBuffer = m_contentTypeForBuffer; | 
| 96     response->m_internalResponse = this; | 166     response->m_internalResponse = this; | 
| 97     return response; | 167     return response; | 
| 98 } | 168 } | 
| 99 | 169 | 
| 100 FetchResponseData* FetchResponseData::createOpaqueFilteredResponse() | 170 FetchResponseData* FetchResponseData::createOpaqueFilteredResponse() | 
| 101 { | 171 { | 
| 102     // "An opaque filtered response is a filtered response whose type is | 172     // "An opaque filtered response is a filtered response whose type is | 
| 103     // |opaque|, status is 0, status message is the empty byte sequence, header | 173     // |opaque|, status is 0, status message is the empty byte sequence, header | 
| 104     // list is an empty list, and body is null." | 174     // list is an empty list, and body is null." | 
| 105     FetchResponseData* response = new FetchResponseData(OpaqueType, 0, ""); | 175     FetchResponseData* response = new FetchResponseData(OpaqueType, 0, ""); | 
| 106     response->m_internalResponse = this; | 176     response->m_internalResponse = this; | 
| 107     return response; | 177     return response; | 
| 108 } | 178 } | 
| 109 | 179 | 
|  | 180 String FetchResponseData::contentType() const | 
|  | 181 { | 
|  | 182     if (m_blobDataHandle) | 
|  | 183         return m_blobDataHandle->type(); | 
|  | 184     return m_contentTypeForBuffer; | 
|  | 185 } | 
|  | 186 | 
|  | 187 PassRefPtr<BlobDataHandle> FetchResponseData::internalBlobDataHandle() const | 
|  | 188 { | 
|  | 189     if (m_internalResponse) { | 
|  | 190         return m_internalResponse->m_blobDataHandle; | 
|  | 191     } | 
|  | 192     return m_blobDataHandle; | 
|  | 193 } | 
|  | 194 | 
|  | 195 BodyStreamBuffer* FetchResponseData::internalBuffer() const | 
|  | 196 { | 
|  | 197     if (m_internalResponse) { | 
|  | 198         return m_internalResponse->m_buffer; | 
|  | 199     } | 
|  | 200     return m_buffer; | 
|  | 201 } | 
|  | 202 | 
|  | 203 String FetchResponseData::internalContentType() const | 
|  | 204 { | 
|  | 205     if (m_internalResponse) { | 
|  | 206         return m_internalResponse->contentType(); | 
|  | 207     } | 
|  | 208     return contentType(); | 
|  | 209 } | 
|  | 210 | 
|  | 211 FetchResponseData* FetchResponseData::clone() | 
|  | 212 { | 
|  | 213     FetchResponseData* newResponse = create(); | 
|  | 214     newResponse->m_type = m_type; | 
|  | 215     if (m_terminationReason) { | 
|  | 216         newResponse->m_terminationReason = adoptPtr(new TerminationReason); | 
|  | 217         *newResponse->m_terminationReason = *m_terminationReason; | 
|  | 218     } | 
|  | 219     newResponse->m_url = m_url; | 
|  | 220     newResponse->m_status = m_status; | 
|  | 221     newResponse->m_statusMessage = m_statusMessage; | 
|  | 222     newResponse->m_headerList = m_headerList->createCopy(); | 
|  | 223     newResponse->m_blobDataHandle = m_blobDataHandle; | 
|  | 224     newResponse->m_contentTypeForBuffer = m_contentTypeForBuffer; | 
|  | 225     if (!m_internalResponse) { | 
|  | 226         if (!m_buffer) | 
|  | 227             return newResponse; | 
|  | 228         BodyStreamBuffer* original = m_buffer; | 
|  | 229         m_buffer = new BodyStreamBuffer(); | 
|  | 230         newResponse->m_buffer = new BodyStreamBuffer(); | 
|  | 231         StreamTeePump* teePump = new StreamTeePump(original, m_buffer, newRespon
     se->m_buffer); | 
|  | 232         teePump->start(); | 
|  | 233         return newResponse; | 
|  | 234     } | 
|  | 235 | 
|  | 236     newResponse->m_internalResponse = m_internalResponse->clone(); | 
|  | 237     if (m_buffer) { | 
|  | 238         m_buffer = m_internalResponse->m_buffer; | 
|  | 239         newResponse->m_buffer = newResponse->m_internalResponse->m_buffer; | 
|  | 240     } | 
|  | 241     return newResponse; | 
|  | 242 } | 
|  | 243 | 
| 110 void FetchResponseData::populateWebServiceWorkerResponse(WebServiceWorkerRespons
     e& response) | 244 void FetchResponseData::populateWebServiceWorkerResponse(WebServiceWorkerRespons
     e& response) | 
| 111 { | 245 { | 
| 112     if (m_internalResponse) { | 246     if (m_internalResponse) { | 
| 113         m_internalResponse->populateWebServiceWorkerResponse(response); | 247         m_internalResponse->populateWebServiceWorkerResponse(response); | 
| 114         response.setResponseType(fetchTypeToWebType(m_type)); | 248         response.setResponseType(fetchTypeToWebType(m_type)); | 
| 115         return; | 249         return; | 
| 116     } | 250     } | 
| 117 | 251 | 
| 118     response.setURL(url()); | 252     response.setURL(url()); | 
| 119     response.setStatus(status()); | 253     response.setStatus(status()); | 
| 120     response.setStatusText(statusMessage()); | 254     response.setStatusText(statusMessage()); | 
| 121     response.setResponseType(fetchTypeToWebType(m_type)); | 255     response.setResponseType(fetchTypeToWebType(m_type)); | 
| 122     for (size_t i = 0; i < headerList()->size(); ++i) { | 256     for (size_t i = 0; i < headerList()->size(); ++i) { | 
| 123         const FetchHeaderList::Header* header = headerList()->list()[i].get(); | 257         const FetchHeaderList::Header* header = headerList()->list()[i].get(); | 
| 124         response.appendHeader(header->first, header->second); | 258         response.appendHeader(header->first, header->second); | 
| 125     } | 259     } | 
| 126     response.setBlobDataHandle(blobDataHandle()); | 260     response.setBlobDataHandle(m_blobDataHandle); | 
| 127 } | 261 } | 
| 128 | 262 | 
| 129 FetchResponseData::FetchResponseData(Type type, unsigned short status, AtomicStr
     ing statusMessage) | 263 FetchResponseData::FetchResponseData(Type type, unsigned short status, AtomicStr
     ing statusMessage) | 
| 130     : m_type(type) | 264     : m_type(type) | 
| 131     , m_status(status) | 265     , m_status(status) | 
| 132     , m_statusMessage(statusMessage) | 266     , m_statusMessage(statusMessage) | 
| 133     , m_headerList(FetchHeaderList::create()) | 267     , m_headerList(FetchHeaderList::create()) | 
| 134 { | 268 { | 
| 135 } | 269 } | 
| 136 | 270 | 
|  | 271 void FetchResponseData::setBlobDataHandle(PassRefPtr<BlobDataHandle> blobDataHan
     dle) | 
|  | 272 { | 
|  | 273     ASSERT(!m_buffer); | 
|  | 274     m_blobDataHandle = blobDataHandle; | 
|  | 275 } | 
|  | 276 | 
| 137 void FetchResponseData::trace(Visitor* visitor) | 277 void FetchResponseData::trace(Visitor* visitor) | 
| 138 { | 278 { | 
| 139     visitor->trace(m_headerList); | 279     visitor->trace(m_headerList); | 
| 140     visitor->trace(m_internalResponse); | 280     visitor->trace(m_internalResponse); | 
|  | 281     visitor->trace(m_buffer); | 
| 141 } | 282 } | 
| 142 | 283 | 
| 143 } // namespace blink | 284 } // namespace blink | 
| OLD | NEW | 
|---|