示例#1
0
FetchResponseData* FetchResponseData::createCORSFilteredResponse(
    const HTTPHeaderSet& exposedHeaders) const {
  DCHECK_EQ(m_type, DefaultType);
  // "A CORS filtered response is a filtered response whose type is |CORS|,
  // header list excludes all headers in internal response's header list,
  // except those whose name is either one of `Cache-Control`,
  // `Content-Language`, `Content-Type`, `Expires`, `Last-Modified`, and
  // `Pragma`, and except those whose name is one of the values resulting from
  // parsing `Access-Control-Expose-Headers` in internal response's header
  // list."
  FetchResponseData* response =
      new FetchResponseData(CORSType, m_status, m_statusMessage);
  response->setURLList(m_urlList);
  for (size_t i = 0; i < m_headerList->size(); ++i) {
    const FetchHeaderList::Header* header = m_headerList->list()[i].get();
    const String& name = header->first;
    const bool explicitlyExposed = exposedHeaders.contains(name);
    if (isOnAccessControlResponseHeaderWhitelist(name) ||
        (explicitlyExposed &&
         !FetchUtils::isForbiddenResponseHeaderName(name))) {
      if (explicitlyExposed)
        response->m_corsExposedHeaderNames.add(name);
      response->m_headerList->append(name, header->second);
    }
  }
  response->m_buffer = m_buffer;
  response->m_mimeType = m_mimeType;
  response->m_internalResponse = const_cast<FetchResponseData*>(this);
  return response;
}
TEST_F(FetchResponseDataTest, ToWebServiceWorkerDefaultType)
{
    WebServiceWorkerResponse webResponse;
    FetchResponseData* internalResponse = createInternalResponse();

    internalResponse->populateWebServiceWorkerResponse(webResponse);
    EXPECT_EQ(WebServiceWorkerResponseTypeDefault, webResponse.responseType());
    CheckHeaders(webResponse);
}
TEST_F(FetchResponseDataTest, ToWebServiceWorkerOpaqueRedirectType)
{
    WebServiceWorkerResponse webResponse;
    FetchResponseData* internalResponse = createInternalResponse();
    FetchResponseData* opaqueRedirectResponseData = internalResponse->createOpaqueRedirectFilteredResponse();

    opaqueRedirectResponseData->populateWebServiceWorkerResponse(webResponse);
    EXPECT_EQ(WebServiceWorkerResponseTypeOpaqueRedirect, webResponse.responseType());
    CheckHeaders(webResponse);
}
TEST_F(FetchResponseDataTest, ToWebServiceWorkerBasicType)
{
    WebServiceWorkerResponse webResponse;
    FetchResponseData* internalResponse = createInternalResponse();
    FetchResponseData* basicResponseData = internalResponse->createBasicFilteredResponse();

    basicResponseData->populateWebServiceWorkerResponse(webResponse);
    EXPECT_EQ(WebServiceWorkerResponseTypeBasic, webResponse.responseType());
    CheckHeaders(webResponse);
}
TEST_F(FetchResponseDataTest, ToWebServiceWorkerCORSType)
{
    WebServiceWorkerResponse webResponse;
    FetchResponseData* internalResponse = createInternalResponse();
    FetchResponseData* corsResponseData = internalResponse->createCORSFilteredResponse();

    corsResponseData->populateWebServiceWorkerResponse(webResponse);
    EXPECT_EQ(WebServiceWorkerResponseTypeCORS, webResponse.responseType());
    CheckHeaders(webResponse);
}
示例#6
0
void FetchManager::Loader::didFinishLoading(unsigned long, double)
{
    if (!m_resolver->executionContext() || m_resolver->executionContext()->activeDOMObjectsAreStopped())
        return;

    OwnPtr<BlobData> blobData = BlobData::create();
    String filePath = m_response.downloadedFilePath();
    if (!filePath.isEmpty() && m_downloadedBlobLength) {
        blobData->appendFile(filePath);
        blobData->setContentType(m_response.mimeType());
    }
    FetchResponseData* response = FetchResponseData::create();
    response->setStatus(m_response.httpStatusCode());
    response->setStatusMessage(m_response.httpStatusText());
    HTTPHeaderMap::const_iterator end = m_response.httpHeaderFields().end();
    for (HTTPHeaderMap::const_iterator it = m_response.httpHeaderFields().begin(); it != end; ++it) {
        response->headerList()->append(it->key, it->value);
    }
    response->setBlobDataHandle(BlobDataHandle::create(blobData.release(), m_downloadedBlobLength));
    response->setURL(m_request->url());

    switch (m_request->tainting()) {
    case FetchRequestData::BasicTainting:
        response = response->createBasicFilteredResponse();
        break;
    case FetchRequestData::CORSTainting:
        response = response->createCORSFilteredResponse();
        break;
    case FetchRequestData::OpaqueTainting:
        response = response->createOpaqueFilteredResponse();
        break;
    }
    m_resolver->resolve(Response::create(m_resolver->executionContext(), response));
    notifyFinished();
}
示例#7
0
Response* Response::clone(ExceptionState& exceptionState)
{
    if (isBodyLocked() || bodyUsed()) {
        exceptionState.throwTypeError("Response body is already used");
        return nullptr;
    }

    FetchResponseData* response = m_response->clone(executionContext());
    Headers* headers = Headers::create(response->headerList());
    headers->setGuard(m_headers->guard());
    return new Response(executionContext(), response, headers);
}
示例#8
0
FetchResponseData* FetchResponseData::clone(ScriptState* scriptState) {
  FetchResponseData* newResponse = create();
  newResponse->m_type = m_type;
  if (m_terminationReason) {
    newResponse->m_terminationReason = WTF::wrapUnique(new TerminationReason);
    *newResponse->m_terminationReason = *m_terminationReason;
  }
  newResponse->setURLList(m_urlList);
  newResponse->m_status = m_status;
  newResponse->m_statusMessage = m_statusMessage;
  newResponse->m_headerList = m_headerList->clone();
  newResponse->m_mimeType = m_mimeType;
  newResponse->m_responseTime = m_responseTime;
  newResponse->m_cacheStorageCacheName = m_cacheStorageCacheName;
  newResponse->m_corsExposedHeaderNames = m_corsExposedHeaderNames;

  switch (m_type) {
    case BasicType:
    case CORSType:
      ASSERT(m_internalResponse);
      ASSERT(m_buffer == m_internalResponse->m_buffer);
      ASSERT(m_internalResponse->m_type == DefaultType);
      newResponse->m_internalResponse = m_internalResponse->clone(scriptState);
      m_buffer = m_internalResponse->m_buffer;
      newResponse->m_buffer = newResponse->m_internalResponse->m_buffer;
      break;
    case DefaultType: {
      ASSERT(!m_internalResponse);
      if (m_buffer) {
        BodyStreamBuffer* new1 = nullptr;
        BodyStreamBuffer* new2 = nullptr;
        m_buffer->tee(&new1, &new2);
        m_buffer = new1;
        newResponse->m_buffer = new2;
      }
      break;
    }
    case ErrorType:
      ASSERT(!m_internalResponse);
      ASSERT(!m_buffer);
      break;
    case OpaqueType:
    case OpaqueRedirectType:
      ASSERT(m_internalResponse);
      ASSERT(!m_buffer);
      ASSERT(m_internalResponse->m_type == DefaultType);
      newResponse->m_internalResponse = m_internalResponse->clone(scriptState);
      break;
  }
  return newResponse;
}
示例#9
0
FetchResponseData* FetchResponseData::createOpaqueRedirectFilteredResponse()
    const {
  DCHECK_EQ(m_type, DefaultType);
  // "An opaque filtered response is a filtered response whose type is
  // 'opaqueredirect', status is 0, status message is the empty byte sequence,
  // header list is the empty list, body is null, and cache state is 'none'."
  //
  // https://fetch.spec.whatwg.org/#concept-filtered-response-opaque-redirect
  FetchResponseData* response =
      new FetchResponseData(OpaqueRedirectType, 0, "");
  response->setURLList(m_urlList);
  response->m_internalResponse = const_cast<FetchResponseData*>(this);
  return response;
}
TEST_F(FetchResponseDataTest, HeaderList)
{
    FetchResponseData* responseData = createInternalResponse();

    Vector<String> setCookieValues;
    responseData->headerList()->getAll("set-cookie", setCookieValues);
    ASSERT_EQ(1U, setCookieValues.size());
    EXPECT_EQ("foo", setCookieValues[0]);

    Vector<String> barValues;
    responseData->headerList()->getAll("bar", barValues);
    ASSERT_EQ(1U, barValues.size());
    EXPECT_EQ("bar", barValues[0]);

    Vector<String> cacheControlValues;
    responseData->headerList()->getAll("cache-control", cacheControlValues);
    ASSERT_EQ(1U, cacheControlValues.size());
    EXPECT_EQ("no-cache", cacheControlValues[0]);
}
示例#11
0
FetchResponseData* FetchResponseData::createBasicFilteredResponse() const {
  DCHECK_EQ(m_type, DefaultType);
  // "A basic filtered response is a filtered response whose type is |basic|,
  // header list excludes any headers in internal response's header list whose
  // name is `Set-Cookie` or `Set-Cookie2`."
  FetchResponseData* response =
      new FetchResponseData(BasicType, m_status, m_statusMessage);
  response->setURLList(m_urlList);
  for (size_t i = 0; i < m_headerList->size(); ++i) {
    const FetchHeaderList::Header* header = m_headerList->list()[i].get();
    if (FetchUtils::isForbiddenResponseHeaderName(header->first))
      continue;
    response->m_headerList->append(header->first, header->second);
  }
  response->m_buffer = m_buffer;
  response->m_mimeType = m_mimeType;
  response->m_internalResponse = const_cast<FetchResponseData*>(this);
  return response;
}
void FetchManager::Loader::didReceiveResponse(unsigned long, const ResourceResponse& response, PassOwnPtr<WebDataConsumerHandle> handle)
{
    ASSERT(handle);

    m_responseHttpStatusCode = response.httpStatusCode();

    // Recompute the tainting if the request was redirected to a different
    // origin.
    if (!SecurityOrigin::create(response.url())->isSameSchemeHostPort(m_request->origin().get())) {
        switch (m_request->mode()) {
        case WebURLRequest::FetchRequestModeSameOrigin:
            ASSERT_NOT_REACHED();
            break;
        case WebURLRequest::FetchRequestModeNoCORS:
            m_request->setResponseTainting(FetchRequestData::OpaqueTainting);
            break;
        case WebURLRequest::FetchRequestModeCORS:
        case WebURLRequest::FetchRequestModeCORSWithForcedPreflight:
            m_request->setResponseTainting(FetchRequestData::CORSTainting);
            break;
        }
    }
    FetchResponseData* responseData = FetchResponseData::createWithBuffer(BodyStreamBuffer::create(createFetchDataConsumerHandleFromWebHandle(handle)));
    responseData->setStatus(response.httpStatusCode());
    responseData->setStatusMessage(response.httpStatusText());
    for (auto& it : response.httpHeaderFields())
        responseData->headerList()->append(it.key, it.value);
    responseData->setURL(response.url());
    responseData->setMIMEType(response.mimeType());

    FetchResponseData* taintedResponse = responseData;
    switch (m_request->tainting()) {
    case FetchRequestData::BasicTainting:
        taintedResponse = responseData->createBasicFilteredResponse();
        break;
    case FetchRequestData::CORSTainting:
        taintedResponse = responseData->createCORSFilteredResponse();
        break;
    case FetchRequestData::OpaqueTainting:
        taintedResponse = responseData->createOpaqueFilteredResponse();
        break;
    }
    Response* r = Response::create(m_resolver->executionContext(), taintedResponse);
    r->headers()->setGuard(Headers::ImmutableGuard);
    m_resolver->resolve(r);
    m_resolver.clear();
}
TEST_F(FetchResponseDataTest, OpaqueFilterOnResponseWithAccessControlExposeHeaders)
{
    FetchResponseData* internalResponse = createInternalResponse();
    internalResponse->headerList()->append("access-control-expose-headers", "set-cookie, bar");

    FetchResponseData* opaqueResponseData = internalResponse->createOpaqueFilteredResponse();

    EXPECT_FALSE(opaqueResponseData->headerList()->has("set-cookie"));
    EXPECT_FALSE(opaqueResponseData->headerList()->has("bar"));
    EXPECT_FALSE(opaqueResponseData->headerList()->has("cache-control"));
}
TEST_F(FetchResponseDataTest, OpaqueFilter)
{
    FetchResponseData* internalResponse = createInternalResponse();
    FetchResponseData* opaqueResponseData = internalResponse->createOpaqueFilteredResponse();

    EXPECT_FALSE(opaqueResponseData->headerList()->has("set-cookie"));
    EXPECT_FALSE(opaqueResponseData->headerList()->has("bar"));
    EXPECT_FALSE(opaqueResponseData->headerList()->has("cache-control"));
}
示例#15
0
 FetchResponseData* createInternalResponse()
 {
     FetchResponseData* internalResponse = FetchResponseData::create();
     internalResponse->setStatus(200);
     internalResponse->setURL(KURL(ParsedURLString, "http://www.example.com"));
     internalResponse->headerList()->append("set-cookie", "foo");
     internalResponse->headerList()->append("bar", "bar");
     internalResponse->headerList()->append("cache-control", "no-cache");
     return internalResponse;
 }
TEST_F(FetchResponseDataTest, CORSFilter)
{
    FetchResponseData* internalResponse = createInternalResponse();
    FetchResponseData* corsResponseData = internalResponse->createCORSFilteredResponse();

    EXPECT_FALSE(corsResponseData->headerList()->has("set-cookie"));

    EXPECT_FALSE(corsResponseData->headerList()->has("bar"));

    Vector<String> cacheControlValues;
    corsResponseData->headerList()->getAll("cache-control", cacheControlValues);
    ASSERT_EQ(1U, cacheControlValues.size());
    EXPECT_EQ("no-cache", cacheControlValues[0]);
}
TEST_F(FetchResponseDataTest, CORSFilterOnResponseWithAccessControlExposeHeaders)
{
    FetchResponseData* internalResponse = createInternalResponse();
    internalResponse->headerList()->append("access-control-expose-headers", "set-cookie, bar");

    FetchResponseData* corsResponseData = internalResponse->createCORSFilteredResponse();

    EXPECT_FALSE(corsResponseData->headerList()->has("set-cookie"));

    Vector<String> barValues;
    corsResponseData->headerList()->getAll("bar", barValues);
    ASSERT_EQ(1U, barValues.size());
    EXPECT_EQ("bar", barValues[0]);
}