blob: 4d79646b8b4888aedc6a279f347ac744feda7d4e [file]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "modules/fetch/Response.h"
#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/ScriptState.h"
#include "bindings/core/v8/V8BindingForTesting.h"
#include "core/dom/Document.h"
#include "core/frame/Frame.h"
#include "core/testing/DummyPageHolder.h"
#include "modules/fetch/BodyStreamBuffer.h"
#include "modules/fetch/BytesConsumer.h"
#include "modules/fetch/BytesConsumerTestUtil.h"
#include "modules/fetch/DataConsumerHandleTestUtil.h"
#include "modules/fetch/FetchResponseData.h"
#include "platform/blob/BlobData.h"
#include "platform/testing/UnitTestHelpers.h"
#include "public/platform/modules/serviceworker/WebServiceWorkerResponse.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "wtf/PtrUtil.h"
#include "wtf/Vector.h"
#include <memory>
namespace blink {
namespace {
std::unique_ptr<WebServiceWorkerResponse> createTestWebServiceWorkerResponse() {
const KURL url(ParsedURLString, "http://www.webresponse.com/");
const unsigned short status = 200;
const String statusText = "the best status text";
struct {
const char* key;
const char* value;
} headers[] = {{"cache-control", "no-cache"},
{"set-cookie", "foop"},
{"foo", "bar"},
{0, 0}};
Vector<WebURL> urlList;
urlList.push_back(url);
std::unique_ptr<WebServiceWorkerResponse> webResponse =
WTF::makeUnique<WebServiceWorkerResponse>();
webResponse->setURLList(urlList);
webResponse->setStatus(status);
webResponse->setStatusText(statusText);
webResponse->setResponseType(WebServiceWorkerResponseTypeDefault);
for (int i = 0; headers[i].key; ++i)
webResponse->setHeader(WebString::fromUTF8(headers[i].key),
WebString::fromUTF8(headers[i].value));
return webResponse;
}
TEST(ServiceWorkerResponseTest, FromFetchResponseData) {
std::unique_ptr<DummyPageHolder> page =
DummyPageHolder::create(IntSize(1, 1));
const KURL url(ParsedURLString, "http://www.response.com");
FetchResponseData* fetchResponseData = FetchResponseData::create();
Vector<KURL> urlList;
urlList.push_back(url);
fetchResponseData->setURLList(urlList);
Response* response = Response::create(&page->document(), fetchResponseData);
ASSERT(response);
EXPECT_EQ(url, response->url());
}
TEST(ServiceWorkerResponseTest, FromWebServiceWorkerResponse) {
V8TestingScope scope;
std::unique_ptr<WebServiceWorkerResponse> webResponse =
createTestWebServiceWorkerResponse();
Response* response = Response::create(scope.getScriptState(), *webResponse);
ASSERT(response);
ASSERT_EQ(1u, webResponse->urlList().size());
EXPECT_EQ(webResponse->urlList()[0], response->url());
EXPECT_EQ(webResponse->status(), response->status());
EXPECT_STREQ(webResponse->statusText().utf8().c_str(),
response->statusText().utf8().data());
Headers* responseHeaders = response->headers();
WebVector<WebString> keys = webResponse->getHeaderKeys();
EXPECT_EQ(keys.size(), responseHeaders->headerList()->size());
for (size_t i = 0, max = keys.size(); i < max; ++i) {
WebString key = keys[i];
DummyExceptionStateForTesting exceptionState;
EXPECT_STREQ(webResponse->getHeader(key).utf8().c_str(),
responseHeaders->get(key, exceptionState).utf8().data());
EXPECT_FALSE(exceptionState.hadException());
}
}
TEST(ServiceWorkerResponseTest, FromWebServiceWorkerResponseDefault) {
V8TestingScope scope;
std::unique_ptr<WebServiceWorkerResponse> webResponse =
createTestWebServiceWorkerResponse();
webResponse->setResponseType(WebServiceWorkerResponseTypeDefault);
Response* response = Response::create(scope.getScriptState(), *webResponse);
Headers* responseHeaders = response->headers();
DummyExceptionStateForTesting exceptionState;
EXPECT_STREQ(
"foop", responseHeaders->get("set-cookie", exceptionState).utf8().data());
EXPECT_STREQ("bar",
responseHeaders->get("foo", exceptionState).utf8().data());
EXPECT_STREQ(
"no-cache",
responseHeaders->get("cache-control", exceptionState).utf8().data());
EXPECT_FALSE(exceptionState.hadException());
}
TEST(ServiceWorkerResponseTest, FromWebServiceWorkerResponseBasic) {
V8TestingScope scope;
std::unique_ptr<WebServiceWorkerResponse> webResponse =
createTestWebServiceWorkerResponse();
webResponse->setResponseType(WebServiceWorkerResponseTypeBasic);
Response* response = Response::create(scope.getScriptState(), *webResponse);
Headers* responseHeaders = response->headers();
DummyExceptionStateForTesting exceptionState;
EXPECT_STREQ(
"", responseHeaders->get("set-cookie", exceptionState).utf8().data());
EXPECT_STREQ("bar",
responseHeaders->get("foo", exceptionState).utf8().data());
EXPECT_STREQ(
"no-cache",
responseHeaders->get("cache-control", exceptionState).utf8().data());
EXPECT_FALSE(exceptionState.hadException());
}
TEST(ServiceWorkerResponseTest, FromWebServiceWorkerResponseCORS) {
V8TestingScope scope;
std::unique_ptr<WebServiceWorkerResponse> webResponse =
createTestWebServiceWorkerResponse();
webResponse->setResponseType(WebServiceWorkerResponseTypeCORS);
Response* response = Response::create(scope.getScriptState(), *webResponse);
Headers* responseHeaders = response->headers();
DummyExceptionStateForTesting exceptionState;
EXPECT_STREQ(
"", responseHeaders->get("set-cookie", exceptionState).utf8().data());
EXPECT_STREQ("", responseHeaders->get("foo", exceptionState).utf8().data());
EXPECT_STREQ(
"no-cache",
responseHeaders->get("cache-control", exceptionState).utf8().data());
EXPECT_FALSE(exceptionState.hadException());
}
TEST(ServiceWorkerResponseTest, FromWebServiceWorkerResponseOpaque) {
V8TestingScope scope;
std::unique_ptr<WebServiceWorkerResponse> webResponse =
createTestWebServiceWorkerResponse();
webResponse->setResponseType(WebServiceWorkerResponseTypeOpaque);
Response* response = Response::create(scope.getScriptState(), *webResponse);
Headers* responseHeaders = response->headers();
DummyExceptionStateForTesting exceptionState;
EXPECT_STREQ(
"", responseHeaders->get("set-cookie", exceptionState).utf8().data());
EXPECT_STREQ("", responseHeaders->get("foo", exceptionState).utf8().data());
EXPECT_STREQ(
"", responseHeaders->get("cache-control", exceptionState).utf8().data());
EXPECT_FALSE(exceptionState.hadException());
}
void checkResponseStream(ScriptState* scriptState,
Response* response,
bool checkResponseBodyStreamBuffer) {
BodyStreamBuffer* originalInternal = response->internalBodyBuffer();
if (checkResponseBodyStreamBuffer) {
EXPECT_EQ(response->bodyBuffer(), originalInternal);
} else {
EXPECT_FALSE(response->bodyBuffer());
}
DummyExceptionStateForTesting exceptionState;
Response* clonedResponse = response->clone(scriptState, exceptionState);
EXPECT_FALSE(exceptionState.hadException());
if (!response->internalBodyBuffer())
FAIL() << "internalBodyBuffer() must not be null.";
if (!clonedResponse->internalBodyBuffer())
FAIL() << "internalBodyBuffer() must not be null.";
EXPECT_TRUE(response->internalBodyBuffer());
EXPECT_TRUE(clonedResponse->internalBodyBuffer());
EXPECT_TRUE(response->internalBodyBuffer());
EXPECT_TRUE(clonedResponse->internalBodyBuffer());
EXPECT_NE(response->internalBodyBuffer(), originalInternal);
EXPECT_NE(clonedResponse->internalBodyBuffer(), originalInternal);
EXPECT_NE(response->internalBodyBuffer(),
clonedResponse->internalBodyBuffer());
if (checkResponseBodyStreamBuffer) {
EXPECT_EQ(response->bodyBuffer(), response->internalBodyBuffer());
EXPECT_EQ(clonedResponse->bodyBuffer(),
clonedResponse->internalBodyBuffer());
} else {
EXPECT_FALSE(response->bodyBuffer());
EXPECT_FALSE(clonedResponse->bodyBuffer());
}
BytesConsumerTestUtil::MockFetchDataLoaderClient* client1 =
new BytesConsumerTestUtil::MockFetchDataLoaderClient();
BytesConsumerTestUtil::MockFetchDataLoaderClient* client2 =
new BytesConsumerTestUtil::MockFetchDataLoaderClient();
EXPECT_CALL(*client1, didFetchDataLoadedString(String("Hello, world")));
EXPECT_CALL(*client2, didFetchDataLoadedString(String("Hello, world")));
response->internalBodyBuffer()->startLoading(
FetchDataLoader::createLoaderAsString(), client1);
clonedResponse->internalBodyBuffer()->startLoading(
FetchDataLoader::createLoaderAsString(), client2);
blink::testing::runPendingTasks();
}
BodyStreamBuffer* createHelloWorldBuffer(ScriptState* scriptState) {
using Command = BytesConsumerTestUtil::Command;
BytesConsumerTestUtil::ReplayingBytesConsumer* src =
new BytesConsumerTestUtil::ReplayingBytesConsumer(
scriptState->getExecutionContext());
src->add(Command(Command::Data, "Hello, "));
src->add(Command(Command::Data, "world"));
src->add(Command(Command::Done));
return new BodyStreamBuffer(scriptState, src);
}
TEST(ServiceWorkerResponseTest, BodyStreamBufferCloneDefault) {
V8TestingScope scope;
BodyStreamBuffer* buffer = createHelloWorldBuffer(scope.getScriptState());
FetchResponseData* fetchResponseData =
FetchResponseData::createWithBuffer(buffer);
Vector<KURL> urlList;
urlList.push_back(KURL(ParsedURLString, "http://www.response.com"));
fetchResponseData->setURLList(urlList);
Response* response =
Response::create(scope.getExecutionContext(), fetchResponseData);
EXPECT_EQ(response->internalBodyBuffer(), buffer);
checkResponseStream(scope.getScriptState(), response, true);
}
TEST(ServiceWorkerResponseTest, BodyStreamBufferCloneBasic) {
V8TestingScope scope;
BodyStreamBuffer* buffer = createHelloWorldBuffer(scope.getScriptState());
FetchResponseData* fetchResponseData =
FetchResponseData::createWithBuffer(buffer);
Vector<KURL> urlList;
urlList.push_back(KURL(ParsedURLString, "http://www.response.com"));
fetchResponseData->setURLList(urlList);
fetchResponseData = fetchResponseData->createBasicFilteredResponse();
Response* response =
Response::create(scope.getExecutionContext(), fetchResponseData);
EXPECT_EQ(response->internalBodyBuffer(), buffer);
checkResponseStream(scope.getScriptState(), response, true);
}
TEST(ServiceWorkerResponseTest, BodyStreamBufferCloneCORS) {
V8TestingScope scope;
BodyStreamBuffer* buffer = createHelloWorldBuffer(scope.getScriptState());
FetchResponseData* fetchResponseData =
FetchResponseData::createWithBuffer(buffer);
Vector<KURL> urlList;
urlList.push_back(KURL(ParsedURLString, "http://www.response.com"));
fetchResponseData->setURLList(urlList);
fetchResponseData = fetchResponseData->createCORSFilteredResponse();
Response* response =
Response::create(scope.getExecutionContext(), fetchResponseData);
EXPECT_EQ(response->internalBodyBuffer(), buffer);
checkResponseStream(scope.getScriptState(), response, true);
}
TEST(ServiceWorkerResponseTest, BodyStreamBufferCloneOpaque) {
V8TestingScope scope;
BodyStreamBuffer* buffer = createHelloWorldBuffer(scope.getScriptState());
FetchResponseData* fetchResponseData =
FetchResponseData::createWithBuffer(buffer);
Vector<KURL> urlList;
urlList.push_back(KURL(ParsedURLString, "http://www.response.com"));
fetchResponseData->setURLList(urlList);
fetchResponseData = fetchResponseData->createOpaqueFilteredResponse();
Response* response =
Response::create(scope.getExecutionContext(), fetchResponseData);
EXPECT_EQ(response->internalBodyBuffer(), buffer);
checkResponseStream(scope.getScriptState(), response, false);
}
TEST(ServiceWorkerResponseTest, BodyStreamBufferCloneError) {
V8TestingScope scope;
BodyStreamBuffer* buffer = new BodyStreamBuffer(
scope.getScriptState(),
BytesConsumer::createErrored(BytesConsumer::Error()));
FetchResponseData* fetchResponseData =
FetchResponseData::createWithBuffer(buffer);
Vector<KURL> urlList;
urlList.push_back(KURL(ParsedURLString, "http://www.response.com"));
fetchResponseData->setURLList(urlList);
Response* response =
Response::create(scope.getExecutionContext(), fetchResponseData);
DummyExceptionStateForTesting exceptionState;
Response* clonedResponse =
response->clone(scope.getScriptState(), exceptionState);
EXPECT_FALSE(exceptionState.hadException());
BytesConsumerTestUtil::MockFetchDataLoaderClient* client1 =
new BytesConsumerTestUtil::MockFetchDataLoaderClient();
BytesConsumerTestUtil::MockFetchDataLoaderClient* client2 =
new BytesConsumerTestUtil::MockFetchDataLoaderClient();
EXPECT_CALL(*client1, didFetchDataLoadFailed());
EXPECT_CALL(*client2, didFetchDataLoadFailed());
response->internalBodyBuffer()->startLoading(
FetchDataLoader::createLoaderAsString(), client1);
clonedResponse->internalBodyBuffer()->startLoading(
FetchDataLoader::createLoaderAsString(), client2);
blink::testing::runPendingTasks();
}
} // namespace
} // namespace blink