| 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; | 
| 70     response->m_internalResponse = this; | 137     response->m_internalResponse = this; | 
| 71     return response; | 138     return response; | 
| 72 } | 139 } | 
| 73 | 140 | 
| 74 FetchResponseData* FetchResponseData::createCORSFilteredResponse() | 141 FetchResponseData* FetchResponseData::createCORSFilteredResponse() | 
| 75 { | 142 { | 
| 76     // "A CORS filtered response is a filtered response whose type is |CORS|, | 143     // "A CORS filtered response is a filtered response whose type is |CORS|, | 
| 77     // header list excludes all headers in internal response's header list, | 144     // header list excludes all headers in internal response's header list, | 
| 78     // except those whose name is either one of `Cache-Control`, | 145     // except those whose name is either one of `Cache-Control`, | 
| 79     // `Content-Language`, `Content-Type`, `Expires`, `Last-Modified`, and | 146     // `Content-Language`, `Content-Type`, `Expires`, `Last-Modified`, and | 
| 80     // `Pragma`, and except those whose name is one of the values resulting from | 147     // `Pragma`, and except those whose name is one of the values resulting from | 
| 81     // parsing `Access-Control-Expose-Headers` in internal response's header | 148     // parsing `Access-Control-Expose-Headers` in internal response's header | 
| 82     // list." | 149     // list." | 
| 83     FetchResponseData* response = new FetchResponseData(CORSType, m_status, m_st
     atusMessage); | 150     FetchResponseData* response = new FetchResponseData(CORSType, m_status, m_st
     atusMessage); | 
| 84     response->m_url = m_url; | 151     response->m_url = m_url; | 
| 85     HTTPHeaderSet accessControlExposeHeaderSet; | 152     HTTPHeaderSet accessControlExposeHeaderSet; | 
| 86     String accessControlExposeHeaders; | 153     String accessControlExposeHeaders; | 
| 87     if (m_headerList->get("access-control-expose-headers", accessControlExposeHe
     aders)) | 154     if (m_headerList->get("access-control-expose-headers", accessControlExposeHe
     aders)) | 
| 88         parseAccessControlExposeHeadersAllowList(accessControlExposeHeaders, acc
     essControlExposeHeaderSet); | 155         parseAccessControlExposeHeadersAllowList(accessControlExposeHeaders, acc
     essControlExposeHeaderSet); | 
| 89     for (size_t i = 0; i < m_headerList->size(); ++i) { | 156     for (size_t i = 0; i < m_headerList->size(); ++i) { | 
| 90         const FetchHeaderList::Header* header = m_headerList->list()[i].get(); | 157         const FetchHeaderList::Header* header = m_headerList->list()[i].get(); | 
| 91         if (!isOnAccessControlResponseHeaderWhitelist(header->first) && !accessC
     ontrolExposeHeaderSet.contains(header->first)) | 158         if (!isOnAccessControlResponseHeaderWhitelist(header->first) && !accessC
     ontrolExposeHeaderSet.contains(header->first)) | 
| 92             continue; | 159             continue; | 
| 93         response->m_headerList->append(header->first, header->second); | 160         response->m_headerList->append(header->first, header->second); | 
| 94     } | 161     } | 
| 95     response->m_blobDataHandle = m_blobDataHandle; | 162     response->m_blobDataHandle = m_blobDataHandle; | 
|  | 163     response->m_buffer = m_buffer; | 
| 96     response->m_internalResponse = this; | 164     response->m_internalResponse = this; | 
| 97     return response; | 165     return response; | 
| 98 } | 166 } | 
| 99 | 167 | 
| 100 FetchResponseData* FetchResponseData::createOpaqueFilteredResponse() | 168 FetchResponseData* FetchResponseData::createOpaqueFilteredResponse() | 
| 101 { | 169 { | 
| 102     // "An opaque filtered response is a filtered response whose type is | 170     // "An opaque filtered response is a filtered response whose type is | 
| 103     // |opaque|, status is 0, status message is the empty byte sequence, header | 171     // |opaque|, status is 0, status message is the empty byte sequence, header | 
| 104     // list is an empty list, and body is null." | 172     // list is an empty list, and body is null." | 
| 105     FetchResponseData* response = new FetchResponseData(OpaqueType, 0, ""); | 173     FetchResponseData* response = new FetchResponseData(OpaqueType, 0, ""); | 
| 106     response->m_internalResponse = this; | 174     response->m_internalResponse = this; | 
| 107     return response; | 175     return response; | 
| 108 } | 176 } | 
| 109 | 177 | 
|  | 178 PassRefPtr<BlobDataHandle> FetchResponseData::blobDataHandle(bool internal) cons
     t | 
|  | 179 { | 
|  | 180     if (internal && m_internalResponse) { | 
|  | 181         return m_internalResponse->m_blobDataHandle; | 
|  | 182     } | 
|  | 183     return m_blobDataHandle; | 
|  | 184 } | 
|  | 185 | 
|  | 186 BodyStreamBuffer* FetchResponseData::buffer(bool internal) const | 
|  | 187 { | 
|  | 188     if (internal && m_internalResponse) { | 
|  | 189         return m_internalResponse->m_buffer; | 
|  | 190     } | 
|  | 191     return m_buffer; | 
|  | 192 } | 
|  | 193 | 
|  | 194 FetchResponseData* FetchResponseData::clone() | 
|  | 195 { | 
|  | 196     FetchResponseData* newResponse = create(); | 
|  | 197     newResponse->m_type = m_type; | 
|  | 198     if (m_terminationReason) { | 
|  | 199         newResponse->m_terminationReason = adoptPtr(new TerminationReason); | 
|  | 200         *newResponse->m_terminationReason = *m_terminationReason; | 
|  | 201     } | 
|  | 202     newResponse->m_url = m_url; | 
|  | 203     newResponse->m_status = m_status; | 
|  | 204     newResponse->m_statusMessage = m_statusMessage; | 
|  | 205     newResponse->m_headerList = m_headerList->createCopy(); | 
|  | 206     newResponse->m_blobDataHandle = m_blobDataHandle; | 
|  | 207     if (!m_internalResponse) { | 
|  | 208         if (!m_buffer) | 
|  | 209             return newResponse; | 
|  | 210         BodyStreamBuffer* original = m_buffer; | 
|  | 211         m_buffer = new BodyStreamBuffer(original->contentType()); | 
|  | 212         newResponse->m_buffer = new BodyStreamBuffer(original->contentType()); | 
|  | 213         StreamTeePump* teePump = new StreamTeePump(original, m_buffer, newRespon
     se->m_buffer); | 
|  | 214         teePump->start(); | 
|  | 215         return newResponse; | 
|  | 216     } | 
|  | 217 | 
|  | 218     newResponse->m_internalResponse = m_internalResponse->clone(); | 
|  | 219     if (m_buffer) { | 
|  | 220         m_buffer = m_internalResponse->m_buffer; | 
|  | 221         newResponse->m_buffer = newResponse->m_internalResponse->m_buffer; | 
|  | 222     } | 
|  | 223     return newResponse; | 
|  | 224 } | 
|  | 225 | 
| 110 void FetchResponseData::populateWebServiceWorkerResponse(WebServiceWorkerRespons
     e& response) | 226 void FetchResponseData::populateWebServiceWorkerResponse(WebServiceWorkerRespons
     e& response) | 
| 111 { | 227 { | 
| 112     if (m_internalResponse) { | 228     if (m_internalResponse) { | 
| 113         m_internalResponse->populateWebServiceWorkerResponse(response); | 229         m_internalResponse->populateWebServiceWorkerResponse(response); | 
| 114         response.setResponseType(fetchTypeToWebType(m_type)); | 230         response.setResponseType(fetchTypeToWebType(m_type)); | 
| 115         return; | 231         return; | 
| 116     } | 232     } | 
| 117 | 233 | 
| 118     response.setURL(url()); | 234     response.setURL(url()); | 
| 119     response.setStatus(status()); | 235     response.setStatus(status()); | 
| 120     response.setStatusText(statusMessage()); | 236     response.setStatusText(statusMessage()); | 
| 121     response.setResponseType(fetchTypeToWebType(m_type)); | 237     response.setResponseType(fetchTypeToWebType(m_type)); | 
| 122     for (size_t i = 0; i < headerList()->size(); ++i) { | 238     for (size_t i = 0; i < headerList()->size(); ++i) { | 
| 123         const FetchHeaderList::Header* header = headerList()->list()[i].get(); | 239         const FetchHeaderList::Header* header = headerList()->list()[i].get(); | 
| 124         response.appendHeader(header->first, header->second); | 240         response.appendHeader(header->first, header->second); | 
| 125     } | 241     } | 
| 126     response.setBlobDataHandle(blobDataHandle()); | 242     response.setBlobDataHandle(m_blobDataHandle); | 
| 127 } | 243 } | 
| 128 | 244 | 
| 129 FetchResponseData::FetchResponseData(Type type, unsigned short status, AtomicStr
     ing statusMessage) | 245 FetchResponseData::FetchResponseData(Type type, unsigned short status, AtomicStr
     ing statusMessage) | 
| 130     : m_type(type) | 246     : m_type(type) | 
| 131     , m_status(status) | 247     , m_status(status) | 
| 132     , m_statusMessage(statusMessage) | 248     , m_statusMessage(statusMessage) | 
| 133     , m_headerList(FetchHeaderList::create()) | 249     , m_headerList(FetchHeaderList::create()) | 
| 134 { | 250 { | 
| 135 } | 251 } | 
| 136 | 252 | 
|  | 253 void FetchResponseData::setBlobDataHandle(PassRefPtr<BlobDataHandle> blobDataHan
     dle) | 
|  | 254 { | 
|  | 255     ASSERT(!m_buffer); | 
|  | 256     m_blobDataHandle = blobDataHandle; | 
|  | 257 } | 
|  | 258 | 
| 137 void FetchResponseData::trace(Visitor* visitor) | 259 void FetchResponseData::trace(Visitor* visitor) | 
| 138 { | 260 { | 
| 139     visitor->trace(m_headerList); | 261     visitor->trace(m_headerList); | 
| 140     visitor->trace(m_internalResponse); | 262     visitor->trace(m_internalResponse); | 
|  | 263     visitor->trace(m_buffer); | 
| 141 } | 264 } | 
| 142 | 265 | 
| 143 } // namespace blink | 266 } // namespace blink | 
| OLD | NEW | 
|---|