Home | History | Annotate | Download | only in serviceworkers
      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
      3 // found in the LICENSE file.
      4 
      5 #include "config.h"
      6 #include "FetchResponseData.h"
      7 
      8 #include "core/fetch/CrossOriginAccessControl.h"
      9 #include "modules/serviceworkers/FetchHeaderList.h"
     10 #include "public/platform/WebServiceWorkerResponse.h"
     11 
     12 namespace blink {
     13 
     14 FetchResponseData* FetchResponseData::create()
     15 {
     16     // "Unless stated otherwise, a response's url is null, status is 200, status
     17     // message is `OK`, header list is an empty header list, and body is null."
     18     return new FetchResponseData(DefaultType, 200, "OK");
     19 }
     20 
     21 FetchResponseData* FetchResponseData::createNetworkErrorResponse()
     22 {
     23     // "A network error is a response whose status is always 0, status message
     24     // is always the empty byte sequence, header list is aways an empty list,
     25     // and body is always null."
     26     return new FetchResponseData(ErrorType, 0, "");
     27 }
     28 
     29 FetchResponseData* FetchResponseData::createBasicFilteredResponse()
     30 {
     31     // "A basic filtered response is a filtered response whose type is |basic|,
     32     // header list excludes any headers in internal response's header list whose
     33     // name is `Set-Cookie` or `Set-Cookie2`."
     34     FetchResponseData* response = new FetchResponseData(BasicType, m_status, m_statusMessage);
     35     response->m_url = m_url;
     36     for (size_t i = 0; i < m_headerList->size(); ++i) {
     37         const FetchHeaderList::Header* header = m_headerList->list()[i].get();
     38         if (header->first == "set-cookie" || header->first == "set-cookie2")
     39             continue;
     40         response->m_headerList->append(header->first, header->second);
     41     }
     42     response->m_blobDataHandle = m_blobDataHandle;
     43     response->m_internalResponse = this;
     44     return response;
     45 }
     46 
     47 FetchResponseData* FetchResponseData::createCORSFilteredResponse()
     48 {
     49     // "A CORS filtered response is a filtered response whose type is |CORS|,
     50     // header list excludes all headers in internal response's header list,
     51     // except those whose name is either one of `Cache-Control`,
     52     // `Content-Language`, `Content-Type`, `Expires`, `Last-Modified`, and
     53     // `Pragma`, and except those whose name is one of the values resulting from
     54     // parsing `Access-Control-Expose-Headers` in internal response's header
     55     // list."
     56     FetchResponseData* response = new FetchResponseData(CORSType, m_status, m_statusMessage);
     57     response->m_url = m_url;
     58     HTTPHeaderSet accessControlExposeHeaderSet;
     59     String accessControlExposeHeaders;
     60     if (m_headerList->get("access-control-expose-headers", accessControlExposeHeaders))
     61         parseAccessControlExposeHeadersAllowList(accessControlExposeHeaders, accessControlExposeHeaderSet);
     62     for (size_t i = 0; i < m_headerList->size(); ++i) {
     63         const FetchHeaderList::Header* header = m_headerList->list()[i].get();
     64         if (!isOnAccessControlResponseHeaderWhitelist(header->first) && !accessControlExposeHeaderSet.contains(header->first))
     65             continue;
     66         response->m_headerList->append(header->first, header->second);
     67     }
     68     response->m_blobDataHandle = m_blobDataHandle;
     69     response->m_internalResponse = this;
     70     return response;
     71 }
     72 
     73 FetchResponseData* FetchResponseData::createOpaqueFilteredResponse()
     74 {
     75     // "An opaque filtered response is a filtered response whose type is
     76     // |opaque|, status is 0, status message is the empty byte sequence, header
     77     // list is an empty list, and body is null."
     78     FetchResponseData* response = new FetchResponseData(OpaqueType, 0, "");
     79     response->m_internalResponse = this;
     80     return response;
     81 }
     82 
     83 void FetchResponseData::populateWebServiceWorkerResponse(WebServiceWorkerResponse& response)
     84 {
     85     if (m_internalResponse) {
     86         m_internalResponse->populateWebServiceWorkerResponse(response);
     87         return;
     88     }
     89     response.setURL(url());
     90     response.setStatus(status());
     91     response.setStatusText(statusMessage());
     92     for (size_t i = 0; i < headerList()->size(); ++i) {
     93         const FetchHeaderList::Header* header = headerList()->list()[i].get();
     94         response.appendHeader(header->first, header->second);
     95     }
     96     response.setBlobDataHandle(blobDataHandle());
     97 }
     98 
     99 FetchResponseData::FetchResponseData(Type type, unsigned short status, AtomicString statusMessage)
    100     : m_type(type)
    101     , m_status(status)
    102     , m_statusMessage(statusMessage)
    103     , m_headerList(FetchHeaderList::create())
    104 {
    105 }
    106 
    107 void FetchResponseData::trace(Visitor* visitor)
    108 {
    109     visitor->trace(m_headerList);
    110     visitor->trace(m_internalResponse);
    111 }
    112 
    113 } // namespace blink
    114