This source file includes following definitions.
- GetIdleSocketCountInTransportSocketPool
- GetIdleSocketCountInSSLSocketPool
- IsTransportSocketPoolStalled
- GetHeaders
- TestLoadTimingReused
- TestLoadTimingNotReused
- TestLoadTimingReusedWithPac
- TestLoadTimingNotReusedWithPac
- CreateSession
- old_max_pool_sockets_
- SetUp
- TearDown
- GetAlternateProtocolHttpHeader
- SimpleGetHelperForData
- ReadsSize
- observed_before_network_start_
- OnBeforeNetworkStart
- observed_before_network_start
- FillLargeHeadersString
- MockGenerateRandom1
- MockGenerateRandom2
- MockGetHostName
- last_group_name_received
- RequestSocket
- CancelRequest
- ReleaseSocket
- CloseIdleSockets
- IdleSocketCount
- IdleSocketCountInGroup
- GetLoadState
- ConnectionTimeout
- CaptureGroupNameSocketPool
- CaptureGroupNameSocketPool
- CheckBasicServerAuth
- CheckBasicProxyAuth
- CheckDigestServerAuth
- CheckNTLMServerAuth
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- KeepAliveConnectionResendRequestTest
- PreconnectErrorResendRequestTest
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- ConnectStatusHelperWithExpectedStatus
- ConnectStatusHelper
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- SetupSessionForGroupNameTests
- GroupNameTransactionHelper
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- BypassHostCacheOnRefreshHelper
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- callback
- Init
- GetContentLength
- BytesRemaining
- Read
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- GetProxyForURL
- CancelRequest
- GetLoadState
- CancelSetPacScript
- SetPacScript
- resolved
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- GenerateAuthTokenImpl
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- CheckErrorIsPassedBack
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- WRAPPED_TEST_P
- TEST_P
- rules
- Resolve
- ResolveFromCache
- CancelRequest
- GetMockHostResolver
- WRAPPED_TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- priority
- InitializeStream
- SendRequest
- ReadResponseHeaders
- GetResponseInfo
- ReadResponseBody
- Close
- IsResponseBodyComplete
- CanFindEndOfResponse
- IsConnectionReused
- SetConnectionReused
- IsConnectionReusable
- GetTotalReceivedBytes
- GetLoadTimingInfo
- GetSSLInfo
- GetSSLCertRequestInfo
- IsSpdyHttpStream
- Drain
- SetPriority
- websocket_stream_create_helper_
- websocket_stream_create_helper_
- priority
- websocket_stream_create_helper
- FinishStreamRequest
- RestartTunnelWithProxyAuth
- GetLoadState
- SetPriority
- was_npn_negotiated
- protocol_negotiated
- using_spdy
- last_stream_request
- RequestStream
- RequestWebSocketHandshakeStream
- PreconnectStreams
- PipelineInfoToValue
- GetHostMappingRules
- CreateBasicStream
- CreateSpdyStream
- Upgrade
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
#include "net/http/http_network_transaction.h"
#include <math.h>
#include <stdarg.h>
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/json/json_writer.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/test_file_util.h"
#include "net/base/auth.h"
#include "net/base/capturing_net_log.h"
#include "net/base/completion_callback.h"
#include "net/base/load_timing_info.h"
#include "net/base/load_timing_info_test_util.h"
#include "net/base/net_log.h"
#include "net/base/net_log_unittest.h"
#include "net/base/request_priority.h"
#include "net/base/test_completion_callback.h"
#include "net/base/test_data_directory.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_data_stream.h"
#include "net/base/upload_file_element_reader.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/dns/host_cache.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/http_auth_handler_digest.h"
#include "net/http/http_auth_handler_mock.h"
#include "net/http/http_auth_handler_ntlm.h"
#include "net/http/http_basic_stream.h"
#include "net/http/http_network_session.h"
#include "net/http/http_network_session_peer.h"
#include "net/http/http_server_properties_impl.h"
#include "net/http/http_stream.h"
#include "net/http/http_stream_factory.h"
#include "net/http/http_transaction_unittest.h"
#include "net/proxy/proxy_config_service_fixed.h"
#include "net/proxy/proxy_info.h"
#include "net/proxy/proxy_resolver.h"
#include "net/proxy/proxy_service.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/client_socket_pool_manager.h"
#include "net/socket/mock_client_socket_pool_manager.h"
#include "net/socket/next_proto.h"
#include "net/socket/socket_test_util.h"
#include "net/socket/ssl_client_socket.h"
#include "net/spdy/spdy_framer.h"
#include "net/spdy/spdy_session.h"
#include "net/spdy/spdy_session_pool.h"
#include "net/spdy/spdy_test_util_common.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_config_service.h"
#include "net/ssl/ssl_config_service_defaults.h"
#include "net/ssl/ssl_info.h"
#include "net/test/cert_test_util.h"
#include "net/websockets/websocket_handshake_stream_base.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
#include "url/gurl.h"
using base::ASCIIToUTF16;
namespace {
const base::string16 kBar(ASCIIToUTF16("bar"));
const base::string16 kBar2(ASCIIToUTF16("bar2"));
const base::string16 kBar3(ASCIIToUTF16("bar3"));
const base::string16 kBaz(ASCIIToUTF16("baz"));
const base::string16 kFirst(ASCIIToUTF16("first"));
const base::string16 kFoo(ASCIIToUTF16("foo"));
const base::string16 kFoo2(ASCIIToUTF16("foo2"));
const base::string16 kFoo3(ASCIIToUTF16("foo3"));
const base::string16 kFou(ASCIIToUTF16("fou"));
const base::string16 kSecond(ASCIIToUTF16("second"));
const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
int GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession* session) {
return session->GetTransportSocketPool(
net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
}
int GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession* session) {
return session->GetSSLSocketPool(
net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
}
bool IsTransportSocketPoolStalled(net::HttpNetworkSession* session) {
return session->GetTransportSocketPool(
net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IsStalled();
}
bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
if (!params)
return false;
base::ListValue* header_list;
if (!params->GetList("headers", &header_list))
return false;
std::string double_quote_headers;
base::JSONWriter::Write(header_list, &double_quote_headers);
base::ReplaceChars(double_quote_headers, "\"", "'", headers);
return true;
}
void TestLoadTimingReused(const net::LoadTimingInfo& load_timing_info) {
EXPECT_TRUE(load_timing_info.socket_reused);
EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
EXPECT_FALSE(load_timing_info.send_start.is_null());
EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
EXPECT_TRUE(load_timing_info.request_start_time.is_null());
EXPECT_TRUE(load_timing_info.request_start.is_null());
EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
}
void TestLoadTimingNotReused(const net::LoadTimingInfo& load_timing_info,
int connect_timing_flags) {
EXPECT_FALSE(load_timing_info.socket_reused);
EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
connect_timing_flags);
EXPECT_LE(load_timing_info.connect_timing.connect_end,
load_timing_info.send_start);
EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
EXPECT_TRUE(load_timing_info.request_start_time.is_null());
EXPECT_TRUE(load_timing_info.request_start.is_null());
EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
}
void TestLoadTimingReusedWithPac(const net::LoadTimingInfo& load_timing_info) {
EXPECT_TRUE(load_timing_info.socket_reused);
EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
EXPECT_LE(load_timing_info.proxy_resolve_start,
load_timing_info.proxy_resolve_end);
EXPECT_LE(load_timing_info.proxy_resolve_end,
load_timing_info.send_start);
EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
EXPECT_TRUE(load_timing_info.request_start_time.is_null());
EXPECT_TRUE(load_timing_info.request_start.is_null());
EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
}
void TestLoadTimingNotReusedWithPac(const net::LoadTimingInfo& load_timing_info,
int connect_timing_flags) {
EXPECT_FALSE(load_timing_info.socket_reused);
EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
EXPECT_LE(load_timing_info.proxy_resolve_start,
load_timing_info.proxy_resolve_end);
EXPECT_LE(load_timing_info.proxy_resolve_end,
load_timing_info.connect_timing.connect_start);
net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
connect_timing_flags);
EXPECT_LE(load_timing_info.connect_timing.connect_end,
load_timing_info.send_start);
EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
EXPECT_TRUE(load_timing_info.request_start_time.is_null());
EXPECT_TRUE(load_timing_info.request_start.is_null());
EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
}
}
namespace net {
namespace {
HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) {
return SpdySessionDependencies::SpdyCreateSession(session_deps);
}
}
class HttpNetworkTransactionTest
: public PlatformTest,
public ::testing::WithParamInterface<NextProto> {
public:
virtual ~HttpNetworkTransactionTest() {
ClientSocketPoolManager::set_max_sockets_per_pool(
HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
ClientSocketPoolManager::set_max_sockets_per_group(
HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
}
protected:
HttpNetworkTransactionTest()
: spdy_util_(GetParam()),
session_deps_(GetParam()),
old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
HttpNetworkSession::NORMAL_SOCKET_POOL)),
old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
HttpNetworkSession::NORMAL_SOCKET_POOL)) {
}
struct SimpleGetHelperResult {
int rv;
std::string status_line;
std::string response_data;
int64 totalReceivedBytes;
LoadTimingInfo load_timing_info;
};
virtual void SetUp() {
NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
base::MessageLoop::current()->RunUntilIdle();
}
virtual void TearDown() {
NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
base::MessageLoop::current()->RunUntilIdle();
base::MessageLoop::current()->RunUntilIdle();
PlatformTest::TearDown();
NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
base::MessageLoop::current()->RunUntilIdle();
HttpStreamFactory::set_use_alternate_protocols(false);
HttpStreamFactory::SetNextProtos(std::vector<NextProto>());
}
std::string GetAlternateProtocolHttpHeader() {
return
std::string("Alternate-Protocol: 443:") +
AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam())) +
"\r\n\r\n";
}
void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
const MockRead* read_failure);
void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
const MockRead* read_failure,
bool use_spdy);
SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
size_t data_count) {
SimpleGetHelperResult out;
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
for (size_t i = 0; i < data_count; ++i) {
session_deps_.socket_factory->AddSocketDataProvider(data[i]);
}
TestCompletionCallback callback;
EXPECT_TRUE(log.bound().IsLogging());
int rv = trans->Start(&request, callback.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
out.rv = callback.WaitForResult();
EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
if (out.rv != OK)
return out;
const HttpResponseInfo* response = trans->GetResponseInfo();
if (response == NULL || response->headers.get() == NULL) {
out.rv = ERR_UNEXPECTED;
return out;
}
out.status_line = response->headers->GetStatusLine();
EXPECT_EQ("127.0.0.1", response->socket_address.host());
EXPECT_EQ(80, response->socket_address.port());
rv = ReadTransaction(trans.get(), &out.response_data);
EXPECT_EQ(OK, rv);
net::CapturingNetLog::CapturedEntryList entries;
log.GetEntries(&entries);
size_t pos = ExpectLogContainsSomewhere(
entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
NetLog::PHASE_NONE);
ExpectLogContainsSomewhere(
entries, pos,
NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
NetLog::PHASE_NONE);
std::string line;
EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
EXPECT_EQ("GET / HTTP/1.1\r\n", line);
HttpRequestHeaders request_headers;
EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
std::string value;
EXPECT_TRUE(request_headers.GetHeader("Host", &value));
EXPECT_EQ("www.google.com", value);
EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
EXPECT_EQ("keep-alive", value);
std::string response_headers;
EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']",
response_headers);
out.totalReceivedBytes = trans->GetTotalReceivedBytes();
return out;
}
SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
size_t reads_count) {
StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0);
StaticSocketDataProvider* data[] = { &reads };
return SimpleGetHelperForData(data, 1);
}
int64 ReadsSize(MockRead data_reads[], size_t reads_count) {
int64 size = 0;
for (size_t i = 0; i < reads_count; ++i)
size += data_reads[i].data_len;
return size;
}
void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
int expected_status);
void ConnectStatusHelper(const MockRead& status);
void BypassHostCacheOnRefreshHelper(int load_flags);
void CheckErrorIsPassedBack(int error, IoMode mode);
SpdyTestUtil spdy_util_;
SpdySessionDependencies session_deps_;
int old_max_group_sockets_;
int old_max_pool_sockets_;
};
INSTANTIATE_TEST_CASE_P(
NextProto,
HttpNetworkTransactionTest,
testing::Values(kProtoDeprecatedSPDY2,
kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
kProtoHTTP2Draft04));
namespace {
class BeforeNetworkStartHandler {
public:
explicit BeforeNetworkStartHandler(bool defer)
: defer_on_before_network_start_(defer),
observed_before_network_start_(false) {}
void OnBeforeNetworkStart(bool* defer) {
*defer = defer_on_before_network_start_;
observed_before_network_start_ = true;
}
bool observed_before_network_start() const {
return observed_before_network_start_;
}
private:
const bool defer_on_before_network_start_;
bool observed_before_network_start_;
DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler);
};
void FillLargeHeadersString(std::string* str, int size) {
const char* row =
"SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
const int sizeof_row = strlen(row);
const int num_rows = static_cast<int>(
ceil(static_cast<float>(size) / sizeof_row));
const int sizeof_data = num_rows * sizeof_row;
DCHECK(sizeof_data >= size);
str->reserve(sizeof_data);
for (int i = 0; i < num_rows; ++i)
str->append(row, sizeof_row);
}
void MockGenerateRandom1(uint8* output, size_t n) {
static const uint8 bytes[] = {
0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
};
static size_t current_byte = 0;
for (size_t i = 0; i < n; ++i) {
output[i] = bytes[current_byte++];
current_byte %= arraysize(bytes);
}
}
void MockGenerateRandom2(uint8* output, size_t n) {
static const uint8 bytes[] = {
0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
};
static size_t current_byte = 0;
for (size_t i = 0; i < n; ++i) {
output[i] = bytes[current_byte++];
current_byte %= arraysize(bytes);
}
}
std::string MockGetHostName() {
return "WTC-WIN7";
}
template<typename ParentPool>
class CaptureGroupNameSocketPool : public ParentPool {
public:
CaptureGroupNameSocketPool(HostResolver* host_resolver,
CertVerifier* cert_verifier);
const std::string last_group_name_received() const {
return last_group_name_;
}
virtual int RequestSocket(const std::string& group_name,
const void* socket_params,
RequestPriority priority,
ClientSocketHandle* handle,
const CompletionCallback& callback,
const BoundNetLog& net_log) {
last_group_name_ = group_name;
return ERR_IO_PENDING;
}
virtual void CancelRequest(const std::string& group_name,
ClientSocketHandle* handle) {}
virtual void ReleaseSocket(const std::string& group_name,
scoped_ptr<StreamSocket> socket,
int id) {}
virtual void CloseIdleSockets() {}
virtual int IdleSocketCount() const {
return 0;
}
virtual int IdleSocketCountInGroup(const std::string& group_name) const {
return 0;
}
virtual LoadState GetLoadState(const std::string& group_name,
const ClientSocketHandle* handle) const {
return LOAD_STATE_IDLE;
}
virtual base::TimeDelta ConnectionTimeout() const {
return base::TimeDelta();
}
private:
std::string last_group_name_;
};
typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
CaptureGroupNameTransportSocketPool;
typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
CaptureGroupNameHttpProxySocketPool;
typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
CaptureGroupNameSOCKSSocketPool;
typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
CaptureGroupNameSSLSocketPool;
template<typename ParentPool>
CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
HostResolver* host_resolver,
CertVerifier* )
: ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
template<>
CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
HostResolver* host_resolver,
CertVerifier* )
: HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
template <>
CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
HostResolver* host_resolver,
CertVerifier* cert_verifier)
: SSLClientSocketPool(0,
0,
NULL,
host_resolver,
cert_verifier,
NULL,
NULL,
NULL,
std::string(),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL) {}
bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
if (!auth_challenge)
return false;
EXPECT_FALSE(auth_challenge->is_proxy);
EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
EXPECT_EQ("MyRealm1", auth_challenge->realm);
EXPECT_EQ("basic", auth_challenge->scheme);
return true;
}
bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
if (!auth_challenge)
return false;
EXPECT_TRUE(auth_challenge->is_proxy);
EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
EXPECT_EQ("MyRealm1", auth_challenge->realm);
EXPECT_EQ("basic", auth_challenge->scheme);
return true;
}
bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
if (!auth_challenge)
return false;
EXPECT_FALSE(auth_challenge->is_proxy);
EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
EXPECT_EQ("digestive", auth_challenge->realm);
EXPECT_EQ("digest", auth_challenge->scheme);
return true;
}
bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
if (!auth_challenge)
return false;
EXPECT_FALSE(auth_challenge->is_proxy);
EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
EXPECT_EQ(std::string(), auth_challenge->realm);
EXPECT_EQ("ntlm", auth_challenge->scheme);
return true;
}
}
TEST_P(HttpNetworkTransactionTest, Basic) {
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
}
TEST_P(HttpNetworkTransactionTest, SimpleGET) {
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n\r\n"),
MockRead("hello world"),
MockRead(SYNCHRONOUS, OK),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
arraysize(data_reads));
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
EXPECT_EQ("hello world", out.response_data);
int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
EXPECT_EQ(reads_size, out.totalReceivedBytes);
}
TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
MockRead data_reads[] = {
MockRead("hello world"),
MockRead(SYNCHRONOUS, OK),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
arraysize(data_reads));
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
EXPECT_EQ("hello world", out.response_data);
int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
EXPECT_EQ(reads_size, out.totalReceivedBytes);
}
TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
MockRead data_reads[] = {
MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
MockRead(SYNCHRONOUS, OK),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
arraysize(data_reads));
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
EXPECT_EQ("DATA", out.response_data);
int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
EXPECT_EQ(reads_size, out.totalReceivedBytes);
}
TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
MockRead data_reads[] = {
MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
MockRead(SYNCHRONOUS, OK),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
arraysize(data_reads));
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
EXPECT_EQ("DATA", out.response_data);
int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
EXPECT_EQ(reads_size, out.totalReceivedBytes);
}
TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
MockRead data_reads[] = {
MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
MockRead(SYNCHRONOUS, OK),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
arraysize(data_reads));
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
EXPECT_EQ(reads_size, out.totalReceivedBytes);
}
TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
MockRead data_reads[] = {
MockRead("\n"),
MockRead("\n"),
MockRead("Q"),
MockRead("J"),
MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
MockRead(SYNCHRONOUS, OK),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
arraysize(data_reads));
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
EXPECT_EQ("DATA", out.response_data);
int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
EXPECT_EQ(reads_size, out.totalReceivedBytes);
}
TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
MockRead data_reads[] = {
MockRead("HTT"),
MockRead(SYNCHRONOUS, OK),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
arraysize(data_reads));
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
EXPECT_EQ("HTT", out.response_data);
int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
EXPECT_EQ(reads_size, out.totalReceivedBytes);
}
TEST_P(HttpNetworkTransactionTest, StopsReading204) {
char junk[] = "junk";
MockRead data_reads[] = {
MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
MockRead(junk),
MockRead(SYNCHRONOUS, OK),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
arraysize(data_reads));
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
EXPECT_EQ("", out.response_data);
int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
int64 response_size = reads_size - strlen(junk);
EXPECT_EQ(response_size, out.totalReceivedBytes);
}
TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
std::string final_chunk = "0\r\n\r\n";
std::string extra_data = "HTTP/1.1 200 OK\r\n";
std::string last_read = final_chunk + extra_data;
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
MockRead("5\r\nHello\r\n"),
MockRead("1\r\n"),
MockRead(" \r\n"),
MockRead("5\r\nworld\r\n"),
MockRead(last_read.data()),
MockRead(SYNCHRONOUS, OK),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
arraysize(data_reads));
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
EXPECT_EQ("Hello world", out.response_data);
int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
int64 response_size = reads_size - extra_data.size();
EXPECT_EQ(response_size, out.totalReceivedBytes);
}
TEST_P(HttpNetworkTransactionTest,
MultipleContentLengthHeadersNoTransferEncoding) {
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Length: 10\r\n"),
MockRead("Content-Length: 5\r\n\r\n"),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
arraysize(data_reads));
EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
}
TEST_P(HttpNetworkTransactionTest,
DuplicateContentLengthHeadersNoTransferEncoding) {
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Length: 5\r\n"),
MockRead("Content-Length: 5\r\n\r\n"),
MockRead("Hello"),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
arraysize(data_reads));
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
EXPECT_EQ("Hello", out.response_data);
}
TEST_P(HttpNetworkTransactionTest,
ComplexContentLengthHeadersNoTransferEncoding) {
{
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Length: 5\r\n"),
MockRead("Content-Length: 5\r\n"),
MockRead("Content-Length: 5\r\n\r\n"),
MockRead("Hello"),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
arraysize(data_reads));
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
EXPECT_EQ("Hello", out.response_data);
}
{
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Length: 5\r\n"),
MockRead("Content-Length: 5\r\n"),
MockRead("Content-Length: 5\r\n\r\n"),
MockRead("Hello"),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
arraysize(data_reads));
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
EXPECT_EQ("Hello", out.response_data);
}
{
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Length: 10\r\n"),
MockRead("Content-Length: 10\r\n"),
MockRead("Content-Length: 5\r\n\r\n"),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
arraysize(data_reads));
EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
}
}
TEST_P(HttpNetworkTransactionTest,
MultipleContentLengthHeadersTransferEncoding) {
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Length: 666\r\n"),
MockRead("Content-Length: 1337\r\n"),
MockRead("Transfer-Encoding: chunked\r\n\r\n"),
MockRead("5\r\nHello\r\n"),
MockRead("1\r\n"),
MockRead(" \r\n"),
MockRead("5\r\nworld\r\n"),
MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
MockRead(SYNCHRONOUS, OK),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
arraysize(data_reads));
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
EXPECT_EQ("Hello world", out.response_data);
}
TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
MockRead("Content-Length: 5\r\n\r\n"),
MockRead("Hello"),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
arraysize(data_reads));
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
EXPECT_EQ("Hello", out.response_data);
}
TEST_P(HttpNetworkTransactionTest,
TwoIdenticalContentDispositionHeaders) {
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
MockRead("Content-Length: 5\r\n\r\n"),
MockRead("Hello"),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
arraysize(data_reads));
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
EXPECT_EQ("Hello", out.response_data);
}
TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
MockRead("Content-Length: 5\r\n\r\n"),
MockRead("Hello"),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
arraysize(data_reads));
EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
}
TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
MockRead data_reads[] = {
MockRead("HTTP/1.1 302 Redirect\r\n"),
MockRead("Location: http://good.com/\r\n"),
MockRead("Location: http://good.com/\r\n"),
MockRead("Content-Length: 0\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://redirect.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
std::string url;
EXPECT_TRUE(response->headers->IsRedirect(&url));
EXPECT_EQ("http://good.com/", url);
}
TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
MockRead data_reads[] = {
MockRead("HTTP/1.1 302 Redirect\r\n"),
MockRead("Location: http://good.com/\r\n"),
MockRead("Location: http://evil.com/\r\n"),
MockRead("Content-Length: 0\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
arraysize(data_reads));
EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
}
TEST_P(HttpNetworkTransactionTest, Head) {
HttpRequestInfo request;
request.method = "HEAD";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes1[] = {
MockWrite("HEAD / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Content-Length: 0\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.1 404 Not Found\r\n"),
MockRead("Server: Blah\r\n"),
MockRead("Content-Length: 1234\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
TestCompletionCallback callback1;
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers.get() != NULL);
EXPECT_EQ(1234, response->headers->GetContentLength());
EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
std::string server_header;
void* iter = NULL;
bool has_server_header = response->headers->EnumerateHeader(
&iter, "Server", &server_header);
EXPECT_TRUE(has_server_header);
EXPECT_EQ("Blah", server_header);
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(OK, rv);
EXPECT_EQ("", response_data);
}
TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
MockRead("hello"),
MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
MockRead("world"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
const char* const kExpectedResponseData[] = {
"hello", "world"
};
for (int i = 0; i < 2; ++i) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(OK, rv);
EXPECT_EQ(kExpectedResponseData[i], response_data);
}
}
TEST_P(HttpNetworkTransactionTest, Ignores100) {
ScopedVector<UploadElementReader> element_readers;
element_readers.push_back(new UploadBytesElementReader("foo", 3));
UploadDataStream upload_data_stream(element_readers.Pass(), 0);
HttpRequestInfo request;
request.method = "POST";
request.url = GURL("http://www.foo.com/");
request.upload_data_stream = &upload_data_stream;
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockRead data_reads[] = {
MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
MockRead("HTTP/1.0 200 OK\r\n\r\n"),
MockRead("hello world"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(OK, rv);
EXPECT_EQ("hello world", response_data);
}
TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.foo.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockRead data_reads[] = {
MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
"HTTP/1.1 200 OK\r\n\r\n"),
MockRead("hello world"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(OK, rv);
EXPECT_EQ("hello world", response_data);
}
TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
HttpRequestInfo request;
request.method = "POST";
request.url = GURL("http://www.foo.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockRead data_reads[] = {
MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
MockRead(ASYNC, 0),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(OK, rv);
EXPECT_EQ("", response_data);
}
TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
HttpRequestInfo request;
request.method = "POST";
request.url = GURL("http://www.foo.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockRead data_reads[] = {
MockRead(ASYNC, 0),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
}
void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
const MockWrite* write_failure,
const MockRead* read_failure) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.foo.com/");
request.load_flags = 0;
CapturingNetLog net_log;
session_deps_.net_log = &net_log;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
MockWrite data1_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.foo.com\r\n"
"Connection: keep-alive\r\n\r\n"),
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.foo.com\r\n"
"Connection: keep-alive\r\n\r\n")
};
MockRead data1_reads[] = {
MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
MockRead("hello"),
MockRead(ASYNC, OK),
};
if (write_failure) {
ASSERT_FALSE(read_failure);
data1_writes[1] = *write_failure;
} else {
ASSERT_TRUE(read_failure);
data1_reads[2] = *read_failure;
}
StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
data1_writes, arraysize(data1_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
MockRead data2_reads[] = {
MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
MockRead("world"),
MockRead(ASYNC, OK),
};
StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
const char* kExpectedResponseData[] = {
"hello", "world"
};
uint32 first_socket_log_id = NetLog::Source::kInvalidId;
for (int i = 0; i < 2; ++i) {
TestCompletionCallback callback;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
if (i == 0) {
first_socket_log_id = load_timing_info.socket_log_id;
} else {
EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
}
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(OK, rv);
EXPECT_EQ(kExpectedResponseData[i], response_data);
}
}
void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
const MockWrite* write_failure,
const MockRead* read_failure,
bool use_spdy) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.foo.com/");
request.load_flags = 0;
CapturingNetLog net_log;
session_deps_.net_log = &net_log;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
SSLSocketDataProvider ssl1(ASYNC, OK);
SSLSocketDataProvider ssl2(ASYNC, OK);
if (use_spdy) {
ssl1.SetNextProto(GetParam());
ssl2.SetNextProto(GetParam());
}
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
scoped_ptr<SpdyFrame> spdy_response(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> spdy_data(
spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
"Host: www.foo.com\r\n"
"Connection: keep-alive\r\n\r\n";
const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
const char kHttpData[] = "hello";
std::vector<MockRead> data1_reads;
std::vector<MockWrite> data1_writes;
if (write_failure) {
ASSERT_FALSE(read_failure);
data1_writes.push_back(*write_failure);
data1_reads.push_back(MockRead(ASYNC, OK));
} else {
ASSERT_TRUE(read_failure);
if (use_spdy) {
data1_writes.push_back(CreateMockWrite(*spdy_request));
} else {
data1_writes.push_back(MockWrite(kHttpRequest));
}
data1_reads.push_back(*read_failure);
}
StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
&data1_writes[0], data1_writes.size());
session_deps_.socket_factory->AddSocketDataProvider(&data1);
std::vector<MockRead> data2_reads;
std::vector<MockWrite> data2_writes;
if (use_spdy) {
data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
data2_reads.push_back(MockRead(ASYNC, OK, 3));
} else {
data2_writes.push_back(
MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
data2_reads.push_back(
MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
data2_reads.push_back(MockRead(ASYNC, OK, 3));
}
OrderedSocketData data2(&data2_reads[0], data2_reads.size(),
&data2_writes[0], data2_writes.size());
session_deps_.socket_factory->AddSocketDataProvider(&data2);
net::SSLConfig ssl_config;
session->ssl_config_service()->GetSSLConfig(&ssl_config);
if (session->http_stream_factory()->has_next_protos())
ssl_config.next_protos = session->http_stream_factory()->next_protos();
session->http_stream_factory()->PreconnectStreams(
1, request, DEFAULT_PRIORITY, ssl_config, ssl_config);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
TestCompletionCallback callback;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReused(
load_timing_info,
CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(OK, rv);
EXPECT_EQ(kHttpData, response_data);
}
TEST_P(HttpNetworkTransactionTest,
KeepAliveConnectionNotConnectedOnWrite) {
MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
KeepAliveConnectionResendRequestTest(&write_failure, NULL);
}
TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
KeepAliveConnectionResendRequestTest(NULL, &read_failure);
}
TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
MockRead read_failure(SYNCHRONOUS, OK);
KeepAliveConnectionResendRequestTest(NULL, &read_failure);
}
TEST_P(HttpNetworkTransactionTest,
PreconnectErrorNotConnectedOnWrite) {
MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
PreconnectErrorResendRequestTest(&write_failure, NULL, false);
}
TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
PreconnectErrorResendRequestTest(NULL, &read_failure, false);
}
TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
MockRead read_failure(SYNCHRONOUS, OK);
PreconnectErrorResendRequestTest(NULL, &read_failure, false);
}
TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
MockRead read_failure(ASYNC, OK);
PreconnectErrorResendRequestTest(NULL, &read_failure, false);
}
TEST_P(HttpNetworkTransactionTest,
SpdyPreconnectErrorNotConnectedOnWrite) {
MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
PreconnectErrorResendRequestTest(&write_failure, NULL, true);
}
TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
PreconnectErrorResendRequestTest(NULL, &read_failure, true);
}
TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
MockRead read_failure(SYNCHRONOUS, OK);
PreconnectErrorResendRequestTest(NULL, &read_failure, true);
}
TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
MockRead read_failure(ASYNC, OK);
PreconnectErrorResendRequestTest(NULL, &read_failure, true);
}
TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockRead data_reads[] = {
MockRead(ASYNC, ERR_CONNECTION_RESET),
MockRead("HTTP/1.0 200 OK\r\n\r\n"),
MockRead("hello world"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(ERR_CONNECTION_RESET, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
EXPECT_TRUE(response == NULL);
}
TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
MockRead data_reads[] = {
MockRead(SYNCHRONOUS, OK),
MockRead("HTTP/1.0 200 OK\r\n\r\n"),
MockRead("hello world"),
MockRead(SYNCHRONOUS, OK),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
arraysize(data_reads));
EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
}
TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
BeforeNetworkStartHandler net_start_handler(true);
trans->SetBeforeNetworkStartCallback(
base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
base::Unretained(&net_start_handler)));
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Length: 5\r\n\r\n"),
MockRead("hello"),
MockRead(SYNCHRONOUS, 0),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
base::MessageLoop::current()->RunUntilIdle();
EXPECT_TRUE(net_start_handler.observed_before_network_start());
EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
EXPECT_TRUE(trans->GetResponseInfo() == NULL);
trans->ResumeNetworkStart();
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_TRUE(trans->GetResponseInfo() != NULL);
scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
if (rv == ERR_IO_PENDING)
rv = callback.WaitForResult();
EXPECT_EQ(5, rv);
trans.reset();
}
TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
BeforeNetworkStartHandler net_start_handler(true);
trans->SetBeforeNetworkStartCallback(
base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
base::Unretained(&net_start_handler)));
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
base::MessageLoop::current()->RunUntilIdle();
EXPECT_TRUE(net_start_handler.observed_before_network_start());
EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
EXPECT_TRUE(trans->GetResponseInfo() == NULL);
}
TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Connection: keep-alive\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead("hello"),
MockRead(SYNCHRONOUS, 0),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
if (rv == ERR_IO_PENDING)
rv = callback.WaitForResult();
EXPECT_EQ(5, rv);
rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
trans.reset();
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
}
TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Connection: keep-alive\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, 0),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
if (rv == ERR_IO_PENDING)
rv = callback.WaitForResult();
EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
trans.reset();
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
}
TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.foo.com/");
request.load_flags = 0;
CapturingNetLog net_log;
session_deps_.net_log = &net_log;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
MockRead data1_reads[] = {
MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
MockRead("HTTP/1.1 302 Found\r\n"
"Content-Length: 0\r\n\r\n"),
MockRead("HTTP/1.1 302 Found\r\n"
"Content-Length: 5\r\n\r\n"
"hello"),
MockRead("HTTP/1.1 301 Moved Permanently\r\n"
"Content-Length: 0\r\n\r\n"),
MockRead("HTTP/1.1 301 Moved Permanently\r\n"
"Content-Length: 5\r\n\r\n"
"hello"),
MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
MockRead("hello"),
};
StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data1);
MockRead data2_reads[] = {
MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
};
StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
const int kNumUnreadBodies = arraysize(data1_reads) - 2;
std::string response_lines[kNumUnreadBodies];
uint32 first_socket_log_id = NetLog::Source::kInvalidId;
for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
TestCompletionCallback callback;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
if (i == 0) {
TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
first_socket_log_id = load_timing_info.socket_log_id;
} else {
TestLoadTimingReused(load_timing_info);
EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
}
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
response_lines[i] = response->headers->GetStatusLine();
}
const char* const kStatusLines[] = {
"HTTP/1.1 204 No Content",
"HTTP/1.1 205 Reset Content",
"HTTP/1.1 304 Not Modified",
"HTTP/1.1 302 Found",
"HTTP/1.1 302 Found",
"HTTP/1.1 301 Moved Permanently",
"HTTP/1.1 301 Moved Permanently",
};
COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
forgot_to_update_kStatusLines);
for (int i = 0; i < kNumUnreadBodies; ++i)
EXPECT_EQ(kStatusLines[i], response_lines[i]);
TestCompletionCallback callback;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(OK, rv);
EXPECT_EQ("hello", response_data);
}
TEST_P(HttpNetworkTransactionTest, BasicAuth) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
CapturingNetLog log;
session_deps_.net_log = &log;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.0 401 Unauthorized\r\n"),
MockRead("WWW-Authenticate: Basic invalid\r\n"),
MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 10000\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_FAILED),
};
MockWrite data_writes2[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
};
MockRead data_reads2[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
data_writes2, arraysize(data_writes2));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
TestCompletionCallback callback1;
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
LoadTimingInfo load_timing_info1;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(
AuthCredentials(kFoo, kBar), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
LoadTimingInfo load_timing_info2;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
EXPECT_LE(load_timing_info1.receive_headers_end,
load_timing_info2.connect_timing.connect_start);
EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
int64 reads_size2 = ReadsSize(data_reads2, arraysize(data_reads2));
EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(100, response->headers->GetContentLength());
}
TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead("HTTP/1.0 401 Unauthorized\r\n"),
MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 10000\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_FAILED),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(0, rv);
int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
}
TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
CapturingNetLog log;
session_deps_.net_log = &log;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.1 401 Unauthorized\r\n"),
MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 14\r\n\r\n"),
MockRead("Unauthorized\r\n"),
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 5\r\n\r\n"),
MockRead("Hello"),
};
MockRead data_reads2[] = {
MockRead(SYNCHRONOUS, ERR_FAILED),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data1);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
TestCompletionCallback callback1;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
LoadTimingInfo load_timing_info1;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(
AuthCredentials(kFoo, kBar), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
LoadTimingInfo load_timing_info2;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
TestLoadTimingReused(load_timing_info2);
EXPECT_LE(load_timing_info1.receive_headers_end,
load_timing_info2.send_start);
EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(5, response->headers->GetContentLength());
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(OK, rv);
int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
}
TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.1 401 Unauthorized\r\n"),
MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Content-Length: 0\r\n\r\n"),
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 5\r\n\r\n"),
MockRead("hello"),
};
MockRead data_reads2[] = {
MockRead(SYNCHRONOUS, ERR_FAILED),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data1);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
TestCompletionCallback callback1;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(
AuthCredentials(kFoo, kBar), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(5, response->headers->GetContentLength());
}
TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
};
std::string large_body_string("Unauthorized");
large_body_string.append(5 * 1024, ' ');
large_body_string.append("\r\n");
MockRead data_reads1[] = {
MockRead("HTTP/1.1 401 Unauthorized\r\n"),
MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 5134\r\n\r\n"),
MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 5\r\n\r\n"),
MockRead("hello"),
};
MockRead data_reads2[] = {
MockRead(SYNCHRONOUS, ERR_FAILED),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data1);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
TestCompletionCallback callback1;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(
AuthCredentials(kFoo, kBar), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(5, response->headers->GetContentLength());
}
TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.1 401 Unauthorized\r\n"),
MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 14\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
MockRead("Unauthorized\r\n"),
MockRead(SYNCHRONOUS, OK),
};
MockWrite data_writes2[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
};
MockRead data_reads2[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 5\r\n\r\n"),
MockRead("hello"),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
data_writes2, arraysize(data_writes2));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
TestCompletionCallback callback1;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(
AuthCredentials(kFoo, kBar), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(5, response->headers->GetContentLength());
}
TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
session_deps_.proxy_service.reset(
ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
MockWrite data_writes1[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n"
"Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Proxy-Connection: close\r\n\r\n"),
MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 5\r\n\r\n"),
MockRead(SYNCHRONOUS, "hello"),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
SSLSocketDataProvider ssl(ASYNC, OK);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
TestCompletionCallback callback1;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback1.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
net::CapturingNetLog::CapturedEntryList entries;
log.GetEntries(&entries);
size_t pos = ExpectLogContainsSomewhere(
entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
NetLog::PHASE_NONE);
ExpectLogContainsSomewhere(
entries, pos,
NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
NetLog::PHASE_NONE);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_FALSE(response->headers.get() == NULL);
EXPECT_EQ(407, response->headers->response_code());
EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
LoadTimingInfo load_timing_info;
EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(
AuthCredentials(kFoo, kBar), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers->IsKeepAlive());
EXPECT_EQ(200, response->headers->response_code());
EXPECT_EQ(5, response->headers->GetContentLength());
EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReusedWithPac(load_timing_info,
CONNECT_TIMING_HAS_SSL_TIMES);
trans.reset();
session->CloseAllConnections();
}
TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
MockWrite data_writes1[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n"
"Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Content-Length: 10\r\n\r\n"),
MockRead("0123456789"),
MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Content-Length: 10\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
TestCompletionCallback callback1;
int rv = trans->Start(&request, callback1.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
net::CapturingNetLog::CapturedEntryList entries;
log.GetEntries(&entries);
size_t pos = ExpectLogContainsSomewhere(
entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
NetLog::PHASE_NONE);
ExpectLogContainsSomewhere(
entries, pos,
NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
NetLog::PHASE_NONE);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_FALSE(response->headers.get() == NULL);
EXPECT_TRUE(response->headers->IsKeepAlive());
EXPECT_EQ(407, response->headers->response_code());
EXPECT_EQ(10, response->headers->GetContentLength());
EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(
AuthCredentials(kFoo, kBaz), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_FALSE(response->headers.get() == NULL);
EXPECT_TRUE(response->headers->IsKeepAlive());
EXPECT_EQ(407, response->headers->response_code());
EXPECT_EQ(10, response->headers->GetContentLength());
EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
session->CloseAllConnections();
}
TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
MockWrite data_writes[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Content-Length: 10\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers->IsKeepAlive());
EXPECT_EQ(407, response->headers->response_code());
EXPECT_EQ(10, response->headers->GetContentLength());
EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
session->CloseAllConnections();
}
TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Content-Length: 10000\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_FAILED),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
}
TEST_P(HttpNetworkTransactionTest,
HttpsServerRequestsProxyAuthThroughProxy) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
MockWrite data_writes1[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
MockRead("HTTP/1.1 407 Unauthorized\r\n"),
MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
SSLSocketDataProvider ssl(ASYNC, OK);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
TestCompletionCallback callback1;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback1.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
net::CapturingNetLog::CapturedEntryList entries;
log.GetEntries(&entries);
size_t pos = ExpectLogContainsSomewhere(
entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
NetLog::PHASE_NONE);
ExpectLogContainsSomewhere(
entries, pos,
NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
NetLog::PHASE_NONE);
}
TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
HttpRequestInfo request1;
request1.method = "GET";
request1.url = GURL("https://www.google.com/1");
HttpRequestInfo request2;
request2.method = "GET";
request2.url = GURL("https://www.google.com/2");
session_deps_.proxy_service.reset(
ProxyService::CreateFixed("PROXY myproxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
MockWrite data_writes1[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
MockWrite("GET /1 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
MockWrite("GET /2 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Length: 1\r\n\r\n"),
MockRead(SYNCHRONOUS, "1"),
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Length: 2\r\n\r\n"),
MockRead(SYNCHRONOUS, "22"),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
SSLSocketDataProvider ssl(ASYNC, OK);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
TestCompletionCallback callback1;
scoped_ptr<HttpTransaction> trans1(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans1->Start(&request1, callback1.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response1 = trans1->GetResponseInfo();
ASSERT_TRUE(response1 != NULL);
ASSERT_TRUE(response1->headers.get() != NULL);
EXPECT_EQ(1, response1->headers->GetContentLength());
LoadTimingInfo load_timing_info1;
EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
trans1.reset();
TestCompletionCallback callback2;
scoped_ptr<HttpTransaction> trans2(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
rv = trans2->Start(&request2, callback2.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response2 = trans2->GetResponseInfo();
ASSERT_TRUE(response2 != NULL);
ASSERT_TRUE(response2->headers.get() != NULL);
EXPECT_EQ(2, response2->headers->GetContentLength());
LoadTimingInfo load_timing_info2;
EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
TestLoadTimingReused(load_timing_info2);
EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
trans2.reset();
session->CloseAllConnections();
}
TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
HttpRequestInfo request1;
request1.method = "GET";
request1.url = GURL("https://www.google.com/1");
HttpRequestInfo request2;
request2.method = "GET";
request2.url = GURL("https://www.google.com/2");
session_deps_.proxy_service.reset(
ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
MockWrite data_writes1[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
MockWrite("GET /1 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
MockWrite("GET /2 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Length: 1\r\n\r\n"),
MockRead(SYNCHRONOUS, "1"),
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Length: 2\r\n\r\n"),
MockRead(SYNCHRONOUS, "22"),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
SSLSocketDataProvider ssl(ASYNC, OK);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
TestCompletionCallback callback1;
scoped_ptr<HttpTransaction> trans1(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans1->Start(&request1, callback1.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response1 = trans1->GetResponseInfo();
ASSERT_TRUE(response1 != NULL);
ASSERT_TRUE(response1->headers.get() != NULL);
EXPECT_EQ(1, response1->headers->GetContentLength());
LoadTimingInfo load_timing_info1;
EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
TestLoadTimingNotReusedWithPac(load_timing_info1,
CONNECT_TIMING_HAS_SSL_TIMES);
trans1.reset();
TestCompletionCallback callback2;
scoped_ptr<HttpTransaction> trans2(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
rv = trans2->Start(&request2, callback2.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response2 = trans2->GetResponseInfo();
ASSERT_TRUE(response2 != NULL);
ASSERT_TRUE(response2->headers.get() != NULL);
EXPECT_EQ(2, response2->headers->GetContentLength());
LoadTimingInfo load_timing_info2;
EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
TestLoadTimingReusedWithPac(load_timing_info2);
EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
trans2.reset();
session->CloseAllConnections();
}
TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
session_deps_.proxy_service.reset(ProxyService::CreateFixed(
"https://proxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
MockWrite data_writes1[] = {
MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
SSLSocketDataProvider ssl(ASYNC, OK);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
TestCompletionCallback callback1;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback1.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReused(load_timing_info,
CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers->IsKeepAlive());
EXPECT_EQ(200, response->headers->response_code());
EXPECT_EQ(100, response->headers->GetContentLength());
EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
EXPECT_TRUE(response->auth_challenge.get() == NULL);
}
TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
session_deps_.proxy_service.reset(ProxyService::CreateFixed(
"https://proxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<SpdyFrame> req(
spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
MockWrite spdy_writes[] = { CreateMockWrite(*req) };
scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead spdy_reads[] = {
CreateMockRead(*resp),
CreateMockRead(*data),
MockRead(ASYNC, 0, 0),
};
DelayedSocketData spdy_data(
1,
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
TestCompletionCallback callback1;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback1.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReused(load_timing_info,
CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
EXPECT_EQ(kUploadData, response_data);
}
TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
session_deps_.proxy_service.reset(
ProxyService::CreateFixed("https://myproxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<SpdyFrame> req_get(
spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
const char* const kExtraAuthorizationHeaders[] = {
"proxy-authorization", "Basic Zm9vOmJhcg=="
};
scoped_ptr<SpdyFrame> req_get_authorization(
spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
arraysize(kExtraAuthorizationHeaders) / 2,
false,
3,
LOWEST,
false));
MockWrite spdy_writes[] = {
CreateMockWrite(*req_get, 1),
CreateMockWrite(*req_get_authorization, 4),
};
const char* const kExtraAuthenticationHeaders[] = {
"proxy-authenticate", "Basic realm=\"MyRealm1\""
};
scoped_ptr<SpdyFrame> resp_authentication(
spdy_util_.ConstructSpdySynReplyError(
"407 Proxy Authentication Required",
kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
1));
scoped_ptr<SpdyFrame> body_authentication(
spdy_util_.ConstructSpdyBodyFrame(1, true));
scoped_ptr<SpdyFrame> resp_data(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
MockRead spdy_reads[] = {
CreateMockRead(*resp_authentication, 2),
CreateMockRead(*body_authentication, 3),
CreateMockRead(*resp_data, 5),
CreateMockRead(*body_data, 6),
MockRead(ASYNC, 0, 7),
};
OrderedSocketData data(
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
TestCompletionCallback callback1;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback1.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* const response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ(407, response->headers->response_code());
EXPECT_TRUE(response->was_fetched_via_spdy);
EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(
AuthCredentials(kFoo, kBar), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
ASSERT_TRUE(response_restart != NULL);
ASSERT_TRUE(response_restart->headers.get() != NULL);
EXPECT_EQ(200, response_restart->headers->response_code());
EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
}
TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
session_deps_.proxy_service.reset(ProxyService::CreateFixed(
"https://proxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
LOWEST));
const char get[] = "GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n";
scoped_ptr<SpdyFrame> wrapped_get(
spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
scoped_ptr<SpdyFrame> conn_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
const char resp[] = "HTTP/1.1 200 OK\r\n"
"Content-Length: 10\r\n\r\n";
scoped_ptr<SpdyFrame> wrapped_get_resp(
spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
scoped_ptr<SpdyFrame> wrapped_body(
spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
scoped_ptr<SpdyFrame> window_update(
spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
MockWrite spdy_writes[] = {
CreateMockWrite(*connect, 1),
CreateMockWrite(*wrapped_get, 3),
CreateMockWrite(*window_update, 5),
};
MockRead spdy_reads[] = {
CreateMockRead(*conn_resp, 2, ASYNC),
CreateMockRead(*wrapped_get_resp, 4, ASYNC),
CreateMockRead(*wrapped_body, 6, ASYNC),
CreateMockRead(*wrapped_body, 7, ASYNC),
MockRead(ASYNC, 0, 8),
};
OrderedSocketData spdy_data(
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
SSLSocketDataProvider ssl2(ASYNC, OK);
ssl2.was_npn_negotiated = false;
ssl2.protocol_negotiated = kProtoUnknown;
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
TestCompletionCallback callback1;
int rv = trans->Start(&request, callback1.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
EXPECT_EQ("1234567890", response_data);
}
TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
session_deps_.proxy_service.reset(ProxyService::CreateFixed(
"https://proxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
LOWEST));
const char* const kMyUrl = "https://www.google.com/";
scoped_ptr<SpdyFrame> get(
spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
scoped_ptr<SpdyFrame> wrapped_get(
spdy_util_.ConstructWrappedSpdyFrame(get, 1));
scoped_ptr<SpdyFrame> conn_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> get_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> wrapped_get_resp(
spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
scoped_ptr<SpdyFrame> wrapped_body(
spdy_util_.ConstructWrappedSpdyFrame(body, 1));
scoped_ptr<SpdyFrame> window_update_get_resp(
spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
scoped_ptr<SpdyFrame> window_update_body(
spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
MockWrite spdy_writes[] = {
CreateMockWrite(*connect, 1),
CreateMockWrite(*wrapped_get, 3),
CreateMockWrite(*window_update_get_resp, 5),
CreateMockWrite(*window_update_body, 7),
};
MockRead spdy_reads[] = {
CreateMockRead(*conn_resp, 2, ASYNC),
CreateMockRead(*wrapped_get_resp, 4, ASYNC),
CreateMockRead(*wrapped_body, 6, ASYNC),
MockRead(ASYNC, 0, 8),
};
OrderedSocketData spdy_data(
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
SSLSocketDataProvider ssl2(ASYNC, OK);
ssl2.SetNextProto(GetParam());
ssl2.protocol_negotiated = GetParam();
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
TestCompletionCallback callback1;
int rv = trans->Start(&request, callback1.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
EXPECT_EQ(kUploadData, response_data);
}
TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
session_deps_.proxy_service.reset(ProxyService::CreateFixed(
"https://proxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
LOWEST));
scoped_ptr<SpdyFrame> get(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite spdy_writes[] = {
CreateMockWrite(*connect, 1),
CreateMockWrite(*get, 3),
};
scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead spdy_reads[] = {
CreateMockRead(*resp, 2, ASYNC),
MockRead(ASYNC, 0, 4),
};
OrderedSocketData spdy_data(
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
SSLSocketDataProvider ssl2(ASYNC, OK);
ssl2.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
TestCompletionCallback callback1;
int rv = trans->Start(&request, callback1.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
}
TEST_P(HttpNetworkTransactionTest,
HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
session_deps_.proxy_service.reset(ProxyService::CreateFixed(
"https://proxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(
SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
HttpRequestInfo request1;
request1.method = "GET";
request1.url = GURL("https://www.google.com/");
request1.load_flags = 0;
HttpRequestInfo request2;
request2.method = "GET";
request2.url = GURL("https://news.google.com/");
request2.load_flags = 0;
scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
LOWEST));
scoped_ptr<SpdyFrame> conn_resp1(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
const char get1[] = "GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n";
scoped_ptr<SpdyFrame> wrapped_get1(
spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
const char resp1[] = "HTTP/1.1 200 OK\r\n"
"Content-Length: 1\r\n\r\n";
scoped_ptr<SpdyFrame> wrapped_get_resp1(
spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
scoped_ptr<SpdyFrame> wrapped_body1(
spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
scoped_ptr<SpdyFrame> window_update(
spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
const char* const kConnectHeaders2[] = {
spdy_util_.GetMethodKey(), "CONNECT",
spdy_util_.GetPathKey(), "news.google.com:443",
spdy_util_.GetHostKey(), "news.google.com",
spdy_util_.GetVersionKey(), "HTTP/1.1",
};
scoped_ptr<SpdyFrame> connect2(
spdy_util_.ConstructSpdyControlFrame(NULL,
0,
false,
3,
LOWEST,
SYN_STREAM,
CONTROL_FLAG_NONE,
kConnectHeaders2,
arraysize(kConnectHeaders2),
0));
scoped_ptr<SpdyFrame> conn_resp2(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
const char get2[] = "GET / HTTP/1.1\r\n"
"Host: news.google.com\r\n"
"Connection: keep-alive\r\n\r\n";
scoped_ptr<SpdyFrame> wrapped_get2(
spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
const char resp2[] = "HTTP/1.1 200 OK\r\n"
"Content-Length: 2\r\n\r\n";
scoped_ptr<SpdyFrame> wrapped_get_resp2(
spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
scoped_ptr<SpdyFrame> wrapped_body2(
spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
MockWrite spdy_writes[] = {
CreateMockWrite(*connect1, 0),
CreateMockWrite(*wrapped_get1, 2),
CreateMockWrite(*connect2, 5),
CreateMockWrite(*wrapped_get2, 7),
};
MockRead spdy_reads[] = {
CreateMockRead(*conn_resp1, 1, ASYNC),
CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
CreateMockRead(*wrapped_body1, 4, ASYNC),
CreateMockRead(*conn_resp2, 6, ASYNC),
CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
CreateMockRead(*wrapped_body2, 9, ASYNC),
MockRead(ASYNC, 0, 10),
};
DeterministicSocketData spdy_data(
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
SSLSocketDataProvider ssl2(ASYNC, OK);
ssl2.was_npn_negotiated = false;
ssl2.protocol_negotiated = kProtoUnknown;
session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
SSLSocketDataProvider ssl3(ASYNC, OK);
ssl3.was_npn_negotiated = false;
ssl3.protocol_negotiated = kProtoUnknown;
session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl3);
TestCompletionCallback callback;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
spdy_data.RunFor(5);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
scoped_ptr<HttpTransaction> trans2(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
spdy_data.RunFor(5);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
LoadTimingInfo load_timing_info2;
EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
}
TEST_P(HttpNetworkTransactionTest,
HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
session_deps_.proxy_service.reset(ProxyService::CreateFixed(
"https://proxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(
SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
HttpRequestInfo request1;
request1.method = "GET";
request1.url = GURL("https://www.google.com/");
request1.load_flags = 0;
HttpRequestInfo request2;
request2.method = "GET";
request2.url = GURL("https://www.google.com/2");
request2.load_flags = 0;
scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
LOWEST));
scoped_ptr<SpdyFrame> conn_resp1(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
const char get1[] = "GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n";
scoped_ptr<SpdyFrame> wrapped_get1(
spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
const char resp1[] = "HTTP/1.1 200 OK\r\n"
"Content-Length: 1\r\n\r\n";
scoped_ptr<SpdyFrame> wrapped_get_resp1(
spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
scoped_ptr<SpdyFrame> wrapped_body1(
spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
scoped_ptr<SpdyFrame> window_update(
spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
const char get2[] = "GET /2 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n";
scoped_ptr<SpdyFrame> wrapped_get2(
spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
const char resp2[] = "HTTP/1.1 200 OK\r\n"
"Content-Length: 2\r\n\r\n";
scoped_ptr<SpdyFrame> wrapped_get_resp2(
spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
scoped_ptr<SpdyFrame> wrapped_body2(
spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
MockWrite spdy_writes[] = {
CreateMockWrite(*connect1, 0),
CreateMockWrite(*wrapped_get1, 2),
CreateMockWrite(*wrapped_get2, 5),
};
MockRead spdy_reads[] = {
CreateMockRead(*conn_resp1, 1, ASYNC),
CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
CreateMockRead(*wrapped_body1, 4, ASYNC),
CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
CreateMockRead(*wrapped_body2, 7, ASYNC),
MockRead(ASYNC, 0, 8),
};
DeterministicSocketData spdy_data(
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
SSLSocketDataProvider ssl2(ASYNC, OK);
ssl2.was_npn_negotiated = false;
ssl2.protocol_negotiated = kProtoUnknown;
session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
TestCompletionCallback callback;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
spdy_data.RunFor(5);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
trans.reset();
scoped_ptr<HttpTransaction> trans2(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
spdy_data.RunFor(3);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
LoadTimingInfo load_timing_info2;
EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
TestLoadTimingReused(load_timing_info2);
EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
}
TEST_P(HttpNetworkTransactionTest,
HttpsProxySpdyLoadTimingTwoHttpRequests) {
session_deps_.proxy_service.reset(ProxyService::CreateFixed(
"https://proxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(
SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
HttpRequestInfo request1;
request1.method = "GET";
request1.url = GURL("http://www.google.com/");
request1.load_flags = 0;
HttpRequestInfo request2;
request2.method = "GET";
request2.url = GURL("http://news.google.com/");
request2.load_flags = 0;
scoped_ptr<SpdyHeaderBlock> headers(
spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
scoped_ptr<SpdyFrame> get1(spdy_util_.ConstructSpdyControlFrame(
headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
scoped_ptr<SpdyFrame> get_resp1(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> body1(
spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
scoped_ptr<SpdyHeaderBlock> headers2(
spdy_util_.ConstructGetHeaderBlockForProxy("http://news.google.com/"));
scoped_ptr<SpdyFrame> get2(spdy_util_.ConstructSpdyControlFrame(
headers2.Pass(), false, 3, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
scoped_ptr<SpdyFrame> get_resp2(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
scoped_ptr<SpdyFrame> body2(
spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
MockWrite spdy_writes[] = {
CreateMockWrite(*get1, 0),
CreateMockWrite(*get2, 3),
};
MockRead spdy_reads[] = {
CreateMockRead(*get_resp1, 1, ASYNC),
CreateMockRead(*body1, 2, ASYNC),
CreateMockRead(*get_resp2, 4, ASYNC),
CreateMockRead(*body2, 5, ASYNC),
MockRead(ASYNC, 0, 6),
};
DeterministicSocketData spdy_data(
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
TestCompletionCallback callback;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
spdy_data.RunFor(2);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReused(load_timing_info,
CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
EXPECT_EQ(ERR_IO_PENDING, trans->Read(buf.get(), 256, callback.callback()));
spdy_data.RunFor(1);
EXPECT_EQ(1, callback.WaitForResult());
trans.reset();
scoped_ptr<HttpTransaction> trans2(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
spdy_data.RunFor(2);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
LoadTimingInfo load_timing_info2;
EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
TestLoadTimingReused(load_timing_info2);
EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
EXPECT_EQ(ERR_IO_PENDING, trans2->Read(buf.get(), 256, callback.callback()));
spdy_data.RunFor(1);
EXPECT_EQ(2, callback.WaitForResult());
}
TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
session_deps_.proxy_service.reset(
ProxyService::CreateFixed("https://myproxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
MockWrite data_writes1[] = {
MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n"
"Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Proxy-Connection: keep-alive\r\n"),
MockRead("Content-Length: 0\r\n\r\n"),
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
SSLSocketDataProvider ssl(ASYNC, OK);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
TestCompletionCallback callback1;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback1.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReused(load_timing_info,
CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_FALSE(response->headers.get() == NULL);
EXPECT_EQ(407, response->headers->response_code());
EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(
AuthCredentials(kFoo, kBar), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
load_timing_info = LoadTimingInfo();
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingReused(load_timing_info);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers->IsKeepAlive());
EXPECT_EQ(200, response->headers->response_code());
EXPECT_EQ(100, response->headers->GetContentLength());
EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
EXPECT_TRUE(response->auth_challenge.get() == NULL);
}
void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
const MockRead& status, int expected_status) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
MockWrite data_writes[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads[] = {
status,
MockRead("Content-Length: 10\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(expected_status, rv);
}
void HttpNetworkTransactionTest::ConnectStatusHelper(
const MockRead& status) {
ConnectStatusHelperWithExpectedStatus(
status, ERR_TUNNEL_CONNECTION_FAILED);
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
ConnectStatusHelper(
MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
ConnectStatusHelperWithExpectedStatus(
MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
ERR_PROXY_AUTH_UNSUPPORTED);
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
ConnectStatusHelper(
MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
}
TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
}
TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes1[] = {
MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.0 407 Unauthorized\r\n"),
MockRead("Proxy-Authenticate: Basic invalid\r\n"),
MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 10000\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_FAILED),
};
MockWrite data_writes2[] = {
MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n"
"Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
};
MockRead data_reads2[] = {
MockRead("HTTP/1.0 401 Unauthorized\r\n"),
MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 2000\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_FAILED),
};
MockWrite data_writes3[] = {
MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n"
"Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
"Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
};
MockRead data_reads3[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
data_writes2, arraysize(data_writes2));
StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
data_writes3, arraysize(data_writes3));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
session_deps_.socket_factory->AddSocketDataProvider(&data3);
TestCompletionCallback callback1;
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(
AuthCredentials(kFoo, kBar), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
TestCompletionCallback callback3;
rv = trans->RestartWithAuth(
AuthCredentials(kFoo2, kBar2), callback3.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback3.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(100, response->headers->GetContentLength());
}
#if defined(NTLM_PORTABLE)
TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://172.22.68.17/kids/login.aspx");
request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
MockGetHostName);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
MockWrite data_writes1[] = {
MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
"Host: 172.22.68.17\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.1 401 Access Denied\r\n"),
MockRead("WWW-Authenticate: NTLM\r\n"),
MockRead("Connection: close\r\n"),
MockRead("Content-Length: 42\r\n"),
MockRead("Content-Type: text/html\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
};
MockWrite data_writes2[] = {
MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
"Host: 172.22.68.17\r\n"
"Connection: keep-alive\r\n"
"Authorization: NTLM "
"TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
"Host: 172.22.68.17\r\n"
"Connection: keep-alive\r\n"
"Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
"AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
"ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
"Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
"ahlhx5I=\r\n\r\n"),
};
MockRead data_reads2[] = {
MockRead("HTTP/1.1 401 Access Denied\r\n"),
MockRead("WWW-Authenticate: NTLM "
"TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
"AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
"UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
"HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
"AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
"lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
"BtAAAAAAA=\r\n"),
MockRead("Content-Length: 42\r\n"),
MockRead("Content-Type: text/html\r\n\r\n"),
MockRead("You are not authorized to view this page\r\n"),
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=utf-8\r\n"),
MockRead("Content-Length: 13\r\n\r\n"),
MockRead("Please Login\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
data_writes2, arraysize(data_writes2));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
TestCompletionCallback callback1;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_FALSE(trans->IsReadyToRestartForAuth());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_FALSE(response == NULL);
EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_TRUE(trans->IsReadyToRestartForAuth());
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
TestCompletionCallback callback3;
rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback3.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(13, response->headers->GetContentLength());
}
TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://172.22.68.17/kids/login.aspx");
request.load_flags = 0;
HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
MockGetHostName);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
MockWrite data_writes1[] = {
MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
"Host: 172.22.68.17\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.1 401 Access Denied\r\n"),
MockRead("WWW-Authenticate: NTLM\r\n"),
MockRead("Connection: close\r\n"),
MockRead("Content-Length: 42\r\n"),
MockRead("Content-Type: text/html\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
};
MockWrite data_writes2[] = {
MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
"Host: 172.22.68.17\r\n"
"Connection: keep-alive\r\n"
"Authorization: NTLM "
"TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
"Host: 172.22.68.17\r\n"
"Connection: keep-alive\r\n"
"Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
"AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
"ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
"XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
"4Ww7b7E=\r\n\r\n"),
};
MockRead data_reads2[] = {
MockRead("HTTP/1.1 401 Access Denied\r\n"),
MockRead("WWW-Authenticate: NTLM "
"TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
"AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
"UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
"HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
"AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
"lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
"BtAAAAAAA=\r\n"),
MockRead("Content-Length: 42\r\n"),
MockRead("Content-Type: text/html\r\n\r\n"),
MockRead("You are not authorized to view this page\r\n"),
MockRead("HTTP/1.1 401 Access Denied\r\n"),
MockRead("WWW-Authenticate: NTLM\r\n"),
MockRead("Connection: close\r\n"),
MockRead("Content-Length: 42\r\n"),
MockRead("Content-Type: text/html\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
};
MockWrite data_writes3[] = {
MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
"Host: 172.22.68.17\r\n"
"Connection: keep-alive\r\n"
"Authorization: NTLM "
"TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
"Host: 172.22.68.17\r\n"
"Connection: keep-alive\r\n"
"Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
"AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
"ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
"dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
"+4MUm7c=\r\n\r\n"),
};
MockRead data_reads3[] = {
MockRead("HTTP/1.1 401 Access Denied\r\n"),
MockRead("WWW-Authenticate: NTLM "
"TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
"AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
"UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
"HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
"AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
"lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
"BtAAAAAAA=\r\n"),
MockRead("Content-Length: 42\r\n"),
MockRead("Content-Type: text/html\r\n\r\n"),
MockRead("You are not authorized to view this page\r\n"),
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=utf-8\r\n"),
MockRead("Content-Length: 13\r\n\r\n"),
MockRead("Please Login\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
data_writes2, arraysize(data_writes2));
StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
data_writes3, arraysize(data_writes3));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
session_deps_.socket_factory->AddSocketDataProvider(&data3);
TestCompletionCallback callback1;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_FALSE(trans->IsReadyToRestartForAuth());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_TRUE(trans->IsReadyToRestartForAuth());
TestCompletionCallback callback3;
rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback3.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_FALSE(trans->IsReadyToRestartForAuth());
response = trans->GetResponseInfo();
ASSERT_FALSE(response == NULL);
EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
TestCompletionCallback callback4;
rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
callback4.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback4.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_TRUE(trans->IsReadyToRestartForAuth());
TestCompletionCallback callback5;
rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback5.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(13, response->headers->GetContentLength());
}
#endif
TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
std::string large_headers_string;
FillLargeHeadersString(&large_headers_string, 300 * 1024);
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
MockRead("\r\nBODY"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
EXPECT_TRUE(response == NULL);
}
TEST_P(HttpNetworkTransactionTest,
DontRecycleTransportSocketForSSLTunnel) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
MockWrite data_writes1[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.1 404 Not Found\r\n"),
MockRead("Content-Length: 10\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
TestCompletionCallback callback1;
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
EXPECT_TRUE(response == NULL);
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
trans.reset();
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
}
TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
MockRead("lo"),
MockRead(" world"),
MockRead("junk"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers.get() != NULL);
std::string status_line = response->headers->GetStatusLine();
EXPECT_EQ("HTTP/1.1 200 OK", status_line);
EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(OK, rv);
EXPECT_EQ("hello world", response_data);
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
}
TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Length: 11\r\n\r\n"),
MockRead("hello world"),
MockRead(SYNCHRONOUS, OK),
};
SSLSocketDataProvider ssl(ASYNC, OK);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(OK, rv);
EXPECT_EQ("hello world", response_data);
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
}
TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Length: 11\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
MockRead("hello world"),
MockRead(ASYNC, 0, 0)
};
SSLSocketDataProvider ssl(ASYNC, OK);
SSLSocketDataProvider ssl2(ASYNC, OK);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
TestCompletionCallback callback;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(OK, rv);
EXPECT_EQ("hello world", response_data);
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(OK, rv);
EXPECT_EQ("hello world", response_data);
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
}
TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
"tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
"e=17259,18167,19592,19773,19981,20133,20173,20233&"
"rt=prt.2642,ol.2649,xjs.2951");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
MockRead data_reads[] = {
MockRead("HTTP/1.1 204 No Content\r\n"
"Content-Length: 0\r\n"
"Content-Type: text/html\r\n\r\n"),
MockRead("junk"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers.get() != NULL);
std::string status_line = response->headers->GetStatusLine();
EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(OK, rv);
EXPECT_EQ("", response_data);
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
}
TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
ScopedVector<UploadElementReader> element_readers;
element_readers.push_back(new UploadBytesElementReader("foo", 3));
UploadDataStream upload_data_stream(element_readers.Pass(), 0);
HttpRequestInfo request[2];
request[0].method = "GET";
request[0].url = GURL("http://www.google.com/");
request[0].load_flags = 0;
request[1].method = "POST";
request[1].url = GURL("http://www.google.com/login.cgi");
request[1].upload_data_stream = &upload_data_stream;
request[1].load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
MockRead data_reads1[] = {
MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
MockRead("hello world"),
MockRead(SYNCHRONOUS, OK),
};
MockWrite data_writes1[] = {
MockWrite(SYNCHRONOUS, 64),
MockWrite(SYNCHRONOUS, 93),
MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
MockRead data_reads2[] = {
MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
MockRead("welcome"),
MockRead(SYNCHRONOUS, OK),
};
MockWrite data_writes2[] = {
MockWrite(SYNCHRONOUS, 93),
MockWrite(SYNCHRONOUS, 3),
};
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
data_writes2, arraysize(data_writes2));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
const char* kExpectedResponseData[] = {
"hello world", "welcome"
};
for (int i = 0; i < 2; ++i) {
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
TestCompletionCallback callback;
int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(OK, rv);
EXPECT_EQ(kExpectedResponseData[i], response_data);
}
}
TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://foo:b@r@www.google.com/");
request.load_flags = LOAD_NORMAL;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
EXPECT_EQ("b%40r", request.url.password());
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.0 401 Unauthorized\r\n"),
MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Content-Length: 10\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_FAILED),
};
MockWrite data_writes2[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
};
MockRead data_reads2[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
data_writes2, arraysize(data_writes2));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
TestCompletionCallback callback1;
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_TRUE(trans->IsReadyToRestartForAuth());
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_FALSE(trans->IsReadyToRestartForAuth());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(100, response->headers->GetContentLength());
base::MessageLoop::current()->RunUntilIdle();
}
TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://foo:baz@www.google.com/");
request.load_flags = LOAD_NORMAL;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.0 401 Unauthorized\r\n"),
MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Content-Length: 10\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_FAILED),
};
MockWrite data_writes2[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
};
MockRead data_reads2[] = {
MockRead("HTTP/1.0 401 Unauthorized\r\n"),
MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Content-Length: 10\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_FAILED),
};
MockWrite data_writes3[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
};
MockRead data_reads3[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
data_writes2, arraysize(data_writes2));
StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
data_writes3, arraysize(data_writes3));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
session_deps_.socket_factory->AddSocketDataProvider(&data3);
TestCompletionCallback callback1;
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_TRUE(trans->IsReadyToRestartForAuth());
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_FALSE(trans->IsReadyToRestartForAuth());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
TestCompletionCallback callback3;
rv = trans->RestartWithAuth(
AuthCredentials(kFoo, kBar), callback3.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback3.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_FALSE(trans->IsReadyToRestartForAuth());
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(100, response->headers->GetContentLength());
base::MessageLoop::current()->RunUntilIdle();
}
TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://foo:bar@www.google.com/");
request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.0 401 Unauthorized\r\n"),
MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Content-Length: 10\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_FAILED),
};
MockWrite data_writes3[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
};
MockRead data_reads3[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
data_writes3, arraysize(data_writes3));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
session_deps_.socket_factory->AddSocketDataProvider(&data3);
TestCompletionCallback callback1;
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_FALSE(trans->IsReadyToRestartForAuth());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
TestCompletionCallback callback3;
rv = trans->RestartWithAuth(
AuthCredentials(kFoo, kBar), callback3.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback3.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_FALSE(trans->IsReadyToRestartForAuth());
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(100, response->headers->GetContentLength());
base::MessageLoop::current()->RunUntilIdle();
}
TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
{
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/x/y/z");
request.load_flags = 0;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
MockWrite data_writes1[] = {
MockWrite("GET /x/y/z HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.0 401 Unauthorized\r\n"),
MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Content-Length: 10000\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_FAILED),
};
MockWrite data_writes2[] = {
MockWrite("GET /x/y/z HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
};
MockRead data_reads2[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
data_writes2, arraysize(data_writes2));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
TestCompletionCallback callback1;
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(
AuthCredentials(kFoo, kBar), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(100, response->headers->GetContentLength());
}
{
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/x/y/a/b");
request.load_flags = 0;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
MockWrite data_writes1[] = {
MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.0 401 Unauthorized\r\n"),
MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
MockRead("Content-Length: 10000\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_FAILED),
};
MockWrite data_writes2[] = {
MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
};
MockRead data_reads2[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
data_writes2, arraysize(data_writes2));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
TestCompletionCallback callback1;
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->auth_challenge.get());
EXPECT_FALSE(response->auth_challenge->is_proxy);
EXPECT_EQ("www.google.com:80",
response->auth_challenge->challenger.ToString());
EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
EXPECT_EQ("basic", response->auth_challenge->scheme);
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(
AuthCredentials(kFoo2, kBar2), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(100, response->headers->GetContentLength());
}
{
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/x/y/z2");
request.load_flags = 0;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
MockWrite data_writes1[] = {
MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
TestCompletionCallback callback1;
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(100, response->headers->GetContentLength());
}
{
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/x/1");
request.load_flags = 0;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
MockWrite data_writes1[] = {
MockWrite("GET /x/1 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.0 401 Unauthorized\r\n"),
MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Content-Length: 10000\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_FAILED),
};
MockWrite data_writes2[] = {
MockWrite("GET /x/1 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
};
MockRead data_reads2[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
data_writes2, arraysize(data_writes2));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
TestCompletionCallback callback1;
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_TRUE(trans->IsReadyToRestartForAuth());
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_FALSE(trans->IsReadyToRestartForAuth());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(100, response->headers->GetContentLength());
}
{
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/p/q/t");
request.load_flags = 0;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
MockWrite data_writes1[] = {
MockWrite("GET /p/q/t HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.0 401 Unauthorized\r\n"),
MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Content-Length: 10000\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_FAILED),
};
MockWrite data_writes2[] = {
MockWrite("GET /p/q/t HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
};
MockRead data_reads2[] = {
MockRead("HTTP/1.0 401 Unauthorized\r\n"),
MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Content-Length: 10000\r\n\r\n"),
MockRead(SYNCHRONOUS, ERR_FAILED),
};
MockWrite data_writes3[] = {
MockWrite("GET /p/q/t HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
};
MockRead data_reads3[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
data_writes2, arraysize(data_writes2));
StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
data_writes3, arraysize(data_writes3));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
session_deps_.socket_factory->AddSocketDataProvider(&data3);
TestCompletionCallback callback1;
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_TRUE(trans->IsReadyToRestartForAuth());
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_FALSE(trans->IsReadyToRestartForAuth());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
TestCompletionCallback callback3;
rv = trans->RestartWithAuth(
AuthCredentials(kFoo3, kBar3), callback3.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback3.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(100, response->headers->GetContentLength());
}
}
TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
HttpAuthHandlerDigest::Factory* digest_factory =
new HttpAuthHandlerDigest::Factory();
HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
digest_factory->set_nonce_generator(nonce_generator);
session_deps_.http_auth_handler_factory.reset(digest_factory);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
{
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/x/y/z");
request.load_flags = 0;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
MockWrite data_writes1[] = {
MockWrite("GET /x/y/z HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.0 401 Unauthorized\r\n"),
MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
"algorithm=MD5, qop=\"auth\"\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
MockWrite data_writes2[] = {
MockWrite("GET /x/y/z HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Digest username=\"foo\", realm=\"digestive\", "
"nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
"response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
"nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
};
MockRead data_reads2[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
data_writes2, arraysize(data_writes2));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
TestCompletionCallback callback1;
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(
AuthCredentials(kFoo, kBar), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
}
{
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/x/y/a/b");
request.load_flags = 0;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
MockWrite data_writes1[] = {
MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Digest username=\"foo\", realm=\"digestive\", "
"nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
"response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
"nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
TestCompletionCallback callback1;
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
}
}
TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpNetworkTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
trans->read_buf_ = new IOBuffer(15);
trans->read_buf_len_ = 15;
trans->request_headers_.SetHeader("Authorization", "NTLM");
HttpResponseInfo* response = &trans->response_;
response->auth_challenge = new AuthChallengeInfo();
response->ssl_info.cert_status = static_cast<CertStatus>(-1);
response->response_time = base::Time::Now();
response->was_cached = true;
{
HttpRequestInfo request;
std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
std::replace(temp.begin(), temp.end(), '\n', '\0');
scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
request.extra_headers.SetHeader("Foo", "1");
request.extra_headers.SetHeader("bar", "23");
EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
}
trans->ResetStateForRestart();
EXPECT_TRUE(trans->read_buf_.get() == NULL);
EXPECT_EQ(0, trans->read_buf_len_);
EXPECT_TRUE(trans->request_headers_.IsEmpty());
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_TRUE(response->headers.get() == NULL);
EXPECT_FALSE(response->was_cached);
EXPECT_EQ(0U, response->ssl_info.cert_status);
EXPECT_FALSE(response->vary_data.is_valid());
}
TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider ssl_bad_certificate;
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
SSLSocketDataProvider ssl(ASYNC, OK);
session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
session_deps_.socket_factory->AddSocketDataProvider(&data);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
rv = trans->RestartIgnoringLastError(callback.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_EQ(100, response->headers->GetContentLength());
}
TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
MockWrite proxy_writes[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
};
MockRead proxy_reads[] = {
MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
MockRead(SYNCHRONOUS, OK)
};
MockWrite data_writes[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider ssl_bad_certificate(
proxy_reads, arraysize(proxy_reads),
proxy_writes, arraysize(proxy_writes));
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
SSLSocketDataProvider ssl(ASYNC, OK);
session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
session_deps_.socket_factory->AddSocketDataProvider(&data);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
TestCompletionCallback callback;
for (int i = 0; i < 2; i++) {
session_deps_.socket_factory->ResetNextMockIndexes();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
rv = trans->RestartIgnoringLastError(callback.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_EQ(100, response->headers->GetContentLength());
}
}
TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
session_deps_.proxy_service.reset(
ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
CapturingNetLog net_log;
session_deps_.net_log = &net_log;
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
MockWrite data_writes[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
SSLSocketDataProvider proxy_ssl(ASYNC, OK);
SSLSocketDataProvider tunnel_ssl(ASYNC, OK);
session_deps_.socket_factory->AddSocketDataProvider(&data);
session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
TestCompletionCallback callback;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers->IsKeepAlive());
EXPECT_EQ(200, response->headers->response_code());
EXPECT_EQ(100, response->headers->GetContentLength());
EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReusedWithPac(load_timing_info,
CONNECT_TIMING_HAS_SSL_TIMES);
}
TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
session_deps_.proxy_service.reset(
ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
CapturingNetLog net_log;
session_deps_.net_log = &net_log;
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
MockWrite data_writes[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead("HTTP/1.1 302 Redirect\r\n"),
MockRead("Location: http://login.example.com/\r\n"),
MockRead("Content-Length: 0\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
SSLSocketDataProvider proxy_ssl(ASYNC, OK);
session_deps_.socket_factory->AddSocketDataProvider(&data);
session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
TestCompletionCallback callback;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_EQ(302, response->headers->response_code());
std::string url;
EXPECT_TRUE(response->headers->IsRedirect(&url));
EXPECT_EQ("http://login.example.com/", url);
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
EXPECT_FALSE(load_timing_info.socket_reused);
EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
EXPECT_LE(load_timing_info.proxy_resolve_start,
load_timing_info.proxy_resolve_end);
EXPECT_LE(load_timing_info.proxy_resolve_end,
load_timing_info.connect_timing.connect_start);
ExpectConnectTimingHasTimes(
load_timing_info.connect_timing,
CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
EXPECT_TRUE(load_timing_info.send_start.is_null());
EXPECT_TRUE(load_timing_info.send_end.is_null());
EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
}
TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
session_deps_.proxy_service.reset(
ProxyService::CreateFixed("https://proxy:70"));
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
LOWEST));
scoped_ptr<SpdyFrame> goaway(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite data_writes[] = {
CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
CreateMockWrite(*goaway.get(), 3, SYNCHRONOUS),
};
static const char* const kExtraHeaders[] = {
"location",
"http://login.example.com/",
};
scoped_ptr<SpdyFrame> resp(
spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
arraysize(kExtraHeaders)/2, 1));
MockRead data_reads[] = {
CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
MockRead(ASYNC, 0, 2),
};
DelayedSocketData data(
1,
data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
SSLSocketDataProvider proxy_ssl(ASYNC, OK);
proxy_ssl.SetNextProto(GetParam());
session_deps_.socket_factory->AddSocketDataProvider(&data);
session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
TestCompletionCallback callback;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_EQ(302, response->headers->response_code());
std::string url;
EXPECT_TRUE(response->headers->IsRedirect(&url));
EXPECT_EQ("http://login.example.com/", url);
}
TEST_P(HttpNetworkTransactionTest,
ErrorResponseToHttpsConnectViaHttpsProxy) {
session_deps_.proxy_service.reset(
ProxyService::CreateFixed("https://proxy:70"));
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
MockWrite data_writes[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead("HTTP/1.1 404 Not Found\r\n"),
MockRead("Content-Length: 23\r\n\r\n"),
MockRead("The host does not exist"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
SSLSocketDataProvider proxy_ssl(ASYNC, OK);
session_deps_.socket_factory->AddSocketDataProvider(&data);
session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
TestCompletionCallback callback;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
}
TEST_P(HttpNetworkTransactionTest,
ErrorResponseToHttpsConnectViaSpdyProxy) {
session_deps_.proxy_service.reset(
ProxyService::CreateFixed("https://proxy:70"));
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
LOWEST));
scoped_ptr<SpdyFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite data_writes[] = {
CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
};
static const char* const kExtraHeaders[] = {
"location",
"http://login.example.com/",
};
scoped_ptr<SpdyFrame> resp(
spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
arraysize(kExtraHeaders)/2, 1));
scoped_ptr<SpdyFrame> body(
spdy_util_.ConstructSpdyBodyFrame(
1, "The host does not exist", 23, true));
MockRead data_reads[] = {
CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
CreateMockRead(*body.get(), 2, SYNCHRONOUS),
MockRead(ASYNC, 0, 4),
};
DelayedSocketData data(
1,
data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
SSLSocketDataProvider proxy_ssl(ASYNC, OK);
proxy_ssl.SetNextProto(GetParam());
session_deps_.socket_factory->AddSocketDataProvider(&data);
session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
TestCompletionCallback callback;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
}
TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
session_deps_.proxy_service.reset(
ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
LOWEST));
scoped_ptr<SpdyFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
const char* const kAuthCredentials[] = {
"proxy-authorization", "Basic Zm9vOmJhcg==",
};
scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST));
const char get[] = "GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n";
scoped_ptr<SpdyFrame> wrapped_get(
spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
MockWrite spdy_writes[] = {
CreateMockWrite(*req, 1, ASYNC),
CreateMockWrite(*rst, 4, ASYNC),
CreateMockWrite(*connect2, 5),
CreateMockWrite(*wrapped_get, 8),
};
const char* const kAuthChallenge[] = {
spdy_util_.GetStatusKey(), "407 Proxy Authentication Required",
spdy_util_.GetVersionKey(), "HTTP/1.1",
"proxy-authenticate", "Basic realm=\"MyRealm1\"",
};
scoped_ptr<SpdyFrame> conn_auth_resp(
spdy_util_.ConstructSpdyControlFrame(NULL,
0,
false,
1,
LOWEST,
SYN_REPLY,
CONTROL_FLAG_NONE,
kAuthChallenge,
arraysize(kAuthChallenge),
0));
scoped_ptr<SpdyFrame> conn_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
const char resp[] = "HTTP/1.1 200 OK\r\n"
"Content-Length: 5\r\n\r\n";
scoped_ptr<SpdyFrame> wrapped_get_resp(
spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
scoped_ptr<SpdyFrame> wrapped_body(
spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
MockRead spdy_reads[] = {
CreateMockRead(*conn_auth_resp, 2, ASYNC),
CreateMockRead(*conn_resp, 6, ASYNC),
CreateMockRead(*wrapped_get_resp, 9, ASYNC),
CreateMockRead(*wrapped_body, 10, ASYNC),
MockRead(ASYNC, OK, 11),
};
OrderedSocketData spdy_data(
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
SSLSocketDataProvider proxy(ASYNC, OK);
proxy.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
SSLSocketDataProvider server(ASYNC, OK);
session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
TestCompletionCallback callback1;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback1.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
net::CapturingNetLog::CapturedEntryList entries;
log.GetEntries(&entries);
size_t pos = ExpectLogContainsSomewhere(
entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
NetLog::PHASE_NONE);
ExpectLogContainsSomewhere(
entries, pos,
NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
NetLog::PHASE_NONE);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_FALSE(response->headers.get() == NULL);
EXPECT_EQ(407, response->headers->response_code());
EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
EXPECT_TRUE(response->auth_challenge.get() != NULL);
EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers->IsKeepAlive());
EXPECT_EQ(200, response->headers->response_code());
EXPECT_EQ(5, response->headers->GetContentLength());
EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
EXPECT_TRUE(response->auth_challenge.get() == NULL);
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReusedWithPac(load_timing_info,
CONNECT_TIMING_HAS_SSL_TIMES);
trans.reset();
session->CloseAllConnections();
}
TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
HttpRequestInfo request;
HttpRequestInfo push_request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
push_request.method = "GET";
push_request.url = GURL("http://www.another-origin.com/foo.dat");
session_deps_.proxy_service.reset(
ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
session_deps_.trusted_spdy_proxy = "myproxy:70";
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<SpdyFrame> stream1_syn(
spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
MockWrite spdy_writes[] = {
CreateMockWrite(*stream1_syn, 1, ASYNC),
};
scoped_ptr<SpdyFrame>
stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame>
stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
scoped_ptr<SpdyFrame>
stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
0,
2,
1,
"http://www.another-origin.com/foo.dat"));
const char kPushedData[] = "pushed";
scoped_ptr<SpdyFrame> stream2_body(
spdy_util_.ConstructSpdyBodyFrame(
2, kPushedData, strlen(kPushedData), true));
MockRead spdy_reads[] = {
CreateMockRead(*stream1_reply, 2, ASYNC),
CreateMockRead(*stream2_syn, 3, ASYNC),
CreateMockRead(*stream1_body, 4, ASYNC),
CreateMockRead(*stream2_body, 5, ASYNC),
MockRead(ASYNC, ERR_IO_PENDING, 6),
};
OrderedSocketData spdy_data(
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
SSLSocketDataProvider proxy(ASYNC, OK);
proxy.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
scoped_ptr<HttpTransaction> push_trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
rv = push_trans->Start(&push_request, callback.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers->IsKeepAlive());
EXPECT_EQ(200, response->headers->response_code());
EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(OK, rv);
EXPECT_EQ("hello!", response_data);
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReusedWithPac(load_timing_info,
CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
EXPECT_TRUE(push_response->headers.get() != NULL);
EXPECT_EQ(200, push_response->headers->response_code());
rv = ReadTransaction(push_trans.get(), &response_data);
EXPECT_EQ(OK, rv);
EXPECT_EQ("pushed", response_data);
LoadTimingInfo push_load_timing_info;
EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
TestLoadTimingReusedWithPac(push_load_timing_info);
EXPECT_EQ(load_timing_info.socket_log_id,
push_load_timing_info.socket_log_id);
trans.reset();
push_trans.reset();
session->CloseAllConnections();
}
TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
session_deps_.proxy_service.reset(
ProxyService::CreateFixed("https://myproxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
session_deps_.trusted_spdy_proxy = "myproxy:70";
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<SpdyFrame> stream1_syn(
spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
scoped_ptr<SpdyFrame> push_rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
MockWrite spdy_writes[] = {
CreateMockWrite(*stream1_syn, 1, ASYNC),
CreateMockWrite(*push_rst, 4),
};
scoped_ptr<SpdyFrame>
stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame>
stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
scoped_ptr<SpdyFrame>
stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
0,
2,
1,
"https://www.another-origin.com/foo.dat"));
MockRead spdy_reads[] = {
CreateMockRead(*stream1_reply, 2, ASYNC),
CreateMockRead(*stream2_syn, 3, ASYNC),
CreateMockRead(*stream1_body, 5, ASYNC),
MockRead(ASYNC, ERR_IO_PENDING, 6),
};
OrderedSocketData spdy_data(
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
SSLSocketDataProvider proxy(ASYNC, OK);
proxy.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers->IsKeepAlive());
EXPECT_EQ(200, response->headers->response_code());
EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(OK, rv);
EXPECT_EQ("hello!", response_data);
trans.reset();
session->CloseAllConnections();
}
TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
session_deps_.proxy_service.reset(ProxyService::CreateFixed(
"https://proxy:70"));
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
MockWrite bad_cert_writes[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
};
MockRead bad_cert_reads[] = {
MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
MockRead(SYNCHRONOUS, OK)
};
MockWrite good_data_writes[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead good_cert_reads[] = {
MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider ssl_bad_certificate(
bad_cert_reads, arraysize(bad_cert_reads),
bad_cert_writes, arraysize(bad_cert_writes));
StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
good_data_writes, arraysize(good_data_writes));
SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
SSLSocketDataProvider ssl(ASYNC, OK);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
session_deps_.socket_factory->AddSocketDataProvider(&data);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
TestCompletionCallback callback;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
rv = trans->RestartIgnoringLastError(callback.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_EQ(100, response->headers->GetContentLength());
}
TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
"Chromium Ultra Awesome X Edition");
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
}
TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
"Chromium Ultra Awesome X Edition");
session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n"
"User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Proxy-Connection: close\r\n\r\n"),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
}
TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
"http://the.previous.site.com/");
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Referer: http://the.previous.site.com/\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
}
TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
HttpRequestInfo request;
request.method = "POST";
request.url = GURL("http://www.google.com/");
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("POST / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Content-Length: 0\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
}
TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
HttpRequestInfo request;
request.method = "PUT";
request.url = GURL("http://www.google.com/");
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("PUT / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Content-Length: 0\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
}
TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
HttpRequestInfo request;
request.method = "HEAD";
request.url = GURL("http://www.google.com/");
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("HEAD / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Content-Length: 0\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
}
TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = LOAD_BYPASS_CACHE;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Pragma: no-cache\r\n"
"Cache-Control: no-cache\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
}
TEST_P(HttpNetworkTransactionTest,
BuildRequest_CacheControlValidateCache) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = LOAD_VALIDATE_CACHE;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Cache-Control: max-age=0\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
}
TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.extra_headers.SetHeader("FooHeader", "Bar");
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"FooHeader: Bar\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
}
TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.extra_headers.SetHeader("referer", "www.foo.com");
request.extra_headers.SetHeader("hEllo", "Kitty");
request.extra_headers.SetHeader("FoO", "bar");
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"referer: www.foo.com\r\n"
"hEllo: Kitty\r\n"
"FoO: bar\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
}
TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
session_deps_.proxy_service.reset(
ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
CapturingNetLog net_log;
session_deps_.net_log = &net_log;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
MockWrite data_writes[] = {
MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n")
};
MockRead data_reads[] = {
MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
MockRead("Payload"),
MockRead(SYNCHRONOUS, OK)
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReusedWithPac(load_timing_info,
CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
std::string response_text;
rv = ReadTransaction(trans.get(), &response_text);
EXPECT_EQ(OK, rv);
EXPECT_EQ("Payload", response_text);
}
TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
session_deps_.proxy_service.reset(
ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
CapturingNetLog net_log;
session_deps_.net_log = &net_log;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
MockWrite data_writes[] = {
MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
arraysize(write_buffer)),
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n")
};
MockRead data_reads[] = {
MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
arraysize(read_buffer)),
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
MockRead("Payload"),
MockRead(SYNCHRONOUS, OK)
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
SSLSocketDataProvider ssl(ASYNC, OK);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReusedWithPac(load_timing_info,
CONNECT_TIMING_HAS_SSL_TIMES);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
std::string response_text;
rv = ReadTransaction(trans.get(), &response_text);
EXPECT_EQ(OK, rv);
EXPECT_EQ("Payload", response_text);
}
TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
session_deps_.proxy_service.reset(
ProxyService::CreateFixed("socks4://myproxy:1080"));
CapturingNetLog net_log;
session_deps_.net_log = &net_log;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
MockWrite data_writes[] = {
MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n")
};
MockRead data_reads[] = {
MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
MockRead("Payload"),
MockRead(SYNCHRONOUS, OK)
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReused(load_timing_info,
CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
std::string response_text;
rv = ReadTransaction(trans.get(), &response_text);
EXPECT_EQ(OK, rv);
EXPECT_EQ("Payload", response_text);
}
TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
session_deps_.proxy_service.reset(
ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
CapturingNetLog net_log;
session_deps_.net_log = &net_log;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
const char kSOCKS5OkRequest[] = {
0x05,
0x01,
0x00,
0x03,
0x0E,
'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
0x00, 0x50,
};
const char kSOCKS5OkResponse[] =
{ 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
MockWrite data_writes[] = {
MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n")
};
MockRead data_reads[] = {
MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
MockRead("Payload"),
MockRead(SYNCHRONOUS, OK)
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReusedWithPac(load_timing_info,
CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
std::string response_text;
rv = ReadTransaction(trans.get(), &response_text);
EXPECT_EQ(OK, rv);
EXPECT_EQ("Payload", response_text);
}
TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
session_deps_.proxy_service.reset(
ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
CapturingNetLog net_log;
session_deps_.net_log = &net_log;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
const unsigned char kSOCKS5OkRequest[] = {
0x05,
0x01,
0x00,
0x03,
0x0E,
'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
0x01, 0xBB,
};
const char kSOCKS5OkResponse[] =
{ 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
MockWrite data_writes[] = {
MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
arraysize(kSOCKS5OkRequest)),
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n")
};
MockRead data_reads[] = {
MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
MockRead("HTTP/1.0 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
MockRead("Payload"),
MockRead(SYNCHRONOUS, OK)
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
SSLSocketDataProvider ssl(ASYNC, OK);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReusedWithPac(load_timing_info,
CONNECT_TIMING_HAS_SSL_TIMES);
std::string response_text;
rv = ReadTransaction(trans.get(), &response_text);
EXPECT_EQ(OK, rv);
EXPECT_EQ("Payload", response_text);
}
namespace {
struct GroupNameTest {
std::string proxy_server;
std::string url;
std::string expected_group_name;
bool ssl;
};
scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
NextProto next_proto,
SpdySessionDependencies* session_deps_) {
scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_));
base::WeakPtr<HttpServerProperties> http_server_properties =
session->http_server_properties();
http_server_properties->SetAlternateProtocol(
HostPortPair("host.with.alternate", 80), 443,
AlternateProtocolFromNextProto(next_proto));
return session;
}
int GroupNameTransactionHelper(
const std::string& url,
const scoped_refptr<HttpNetworkSession>& session) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL(url);
request.load_flags = 0;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
TestCompletionCallback callback;
return trans->Start(&request, callback.callback(), BoundNetLog());
}
}
TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
const GroupNameTest tests[] = {
{
"",
"http://www.google.com/direct",
"www.google.com:80",
false,
},
{
"",
"http://[2001:1418:13:1::25]/direct",
"[2001:1418:13:1::25]:80",
false,
},
{
"",
"https://www.google.com/direct_ssl",
"ssl/www.google.com:443",
true,
},
{
"",
"https://[2001:1418:13:1::25]/direct",
"ssl/[2001:1418:13:1::25]:443",
true,
},
{
"",
"http://host.with.alternate/direct",
"ssl/host.with.alternate:443",
true,
},
};
HttpStreamFactory::set_use_alternate_protocols(true);
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
session_deps_.proxy_service.reset(
ProxyService::CreateFixed(tests[i].proxy_server));
scoped_refptr<HttpNetworkSession> session(
SetupSessionForGroupNameTests(GetParam(), &session_deps_));
HttpNetworkSessionPeer peer(session);
CaptureGroupNameTransportSocketPool* transport_conn_pool =
new CaptureGroupNameTransportSocketPool(NULL, NULL);
CaptureGroupNameSSLSocketPool* ssl_conn_pool =
new CaptureGroupNameSSLSocketPool(NULL, NULL);
scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
new MockClientSocketPoolManager);
mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
peer.SetClientSocketPoolManager(
mock_pool_manager.PassAs<ClientSocketPoolManager>());
EXPECT_EQ(ERR_IO_PENDING,
GroupNameTransactionHelper(tests[i].url, session));
if (tests[i].ssl)
EXPECT_EQ(tests[i].expected_group_name,
ssl_conn_pool->last_group_name_received());
else
EXPECT_EQ(tests[i].expected_group_name,
transport_conn_pool->last_group_name_received());
}
}
TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
const GroupNameTest tests[] = {
{
"http_proxy",
"http://www.google.com/http_proxy_normal",
"www.google.com:80",
false,
},
{
"http_proxy",
"https://www.google.com/http_connect_ssl",
"ssl/www.google.com:443",
true,
},
{
"http_proxy",
"http://host.with.alternate/direct",
"ssl/host.with.alternate:443",
true,
},
{
"http_proxy",
"ftp://ftp.google.com/http_proxy_normal",
"ftp/ftp.google.com:21",
false,
},
};
HttpStreamFactory::set_use_alternate_protocols(true);
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
session_deps_.proxy_service.reset(
ProxyService::CreateFixed(tests[i].proxy_server));
scoped_refptr<HttpNetworkSession> session(
SetupSessionForGroupNameTests(GetParam(), &session_deps_));
HttpNetworkSessionPeer peer(session);
HostPortPair proxy_host("http_proxy", 80);
CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
CaptureGroupNameSSLSocketPool* ssl_conn_pool =
new CaptureGroupNameSSLSocketPool(NULL, NULL);
scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
new MockClientSocketPoolManager);
mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
peer.SetClientSocketPoolManager(
mock_pool_manager.PassAs<ClientSocketPoolManager>());
EXPECT_EQ(ERR_IO_PENDING,
GroupNameTransactionHelper(tests[i].url, session));
if (tests[i].ssl)
EXPECT_EQ(tests[i].expected_group_name,
ssl_conn_pool->last_group_name_received());
else
EXPECT_EQ(tests[i].expected_group_name,
http_proxy_pool->last_group_name_received());
}
}
TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
const GroupNameTest tests[] = {
{
"socks4://socks_proxy:1080",
"http://www.google.com/socks4_direct",
"socks4/www.google.com:80",
false,
},
{
"socks5://socks_proxy:1080",
"http://www.google.com/socks5_direct",
"socks5/www.google.com:80",
false,
},
{
"socks4://socks_proxy:1080",
"https://www.google.com/socks4_ssl",
"socks4/ssl/www.google.com:443",
true,
},
{
"socks5://socks_proxy:1080",
"https://www.google.com/socks5_ssl",
"socks5/ssl/www.google.com:443",
true,
},
{
"socks4://socks_proxy:1080",
"http://host.with.alternate/direct",
"socks4/ssl/host.with.alternate:443",
true,
},
};
HttpStreamFactory::set_use_alternate_protocols(true);
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
session_deps_.proxy_service.reset(
ProxyService::CreateFixed(tests[i].proxy_server));
scoped_refptr<HttpNetworkSession> session(
SetupSessionForGroupNameTests(GetParam(), &session_deps_));
HttpNetworkSessionPeer peer(session);
HostPortPair proxy_host("socks_proxy", 1080);
CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
CaptureGroupNameSSLSocketPool* ssl_conn_pool =
new CaptureGroupNameSSLSocketPool(NULL, NULL);
scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
new MockClientSocketPoolManager);
mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
peer.SetClientSocketPoolManager(
mock_pool_manager.PassAs<ClientSocketPoolManager>());
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
EXPECT_EQ(ERR_IO_PENDING,
GroupNameTransactionHelper(tests[i].url, session));
if (tests[i].ssl)
EXPECT_EQ(tests[i].expected_group_name,
ssl_conn_pool->last_group_name_received());
else
EXPECT_EQ(tests[i].expected_group_name,
socks_conn_pool->last_group_name_received());
}
}
TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
session_deps_.proxy_service.reset(
ProxyService::CreateFixed("myproxy:70;foobar:80"));
session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
}
void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
int load_flags) {
HttpRequestInfo request;
request.method = "GET";
request.load_flags = load_flags;
request.url = GURL("http://www.google.com/");
session_deps_.host_resolver.reset(new MockCachingHostResolver);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
AddressList addrlist;
TestCompletionCallback callback;
int rv = session_deps_.host_resolver->Resolve(
HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
DEFAULT_PRIORITY,
&addrlist,
callback.callback(),
NULL,
BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
rv = session_deps_.host_resolver->Resolve(
HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
DEFAULT_PRIORITY,
&addrlist,
callback.callback(),
NULL,
BoundNetLog());
ASSERT_EQ(OK, rv);
session_deps_.host_resolver->rules()->AddSimulatedFailure("www.google.com");
MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
rv = trans->Start(&request, callback.callback(), BoundNetLog());
ASSERT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
}
TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
}
TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
}
TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
}
TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.foo.com/");
request.load_flags = 0;
MockWrite write_failure[] = {
MockWrite(ASYNC, ERR_CONNECTION_RESET),
};
StaticSocketDataProvider data(NULL, 0,
write_failure, arraysize(write_failure));
session_deps_.socket_factory->AddSocketDataProvider(&data);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
TestCompletionCallback callback;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(ERR_CONNECTION_RESET, rv);
}
TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.foo.com/");
request.load_flags = 0;
MockRead data_reads[] = {
MockRead("HTTP/1."),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
TestCompletionCallback callback;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(OK, rv);
EXPECT_EQ("", response_data);
}
TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.1 401 Unauthorized\r\n"),
MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 14\r\n\r\n"),
MockRead("Unauth"),
MockRead(ASYNC, ERR_CONNECTION_RESET),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
MockWrite data_writes2[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
};
MockRead data_reads2[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
data_writes2, arraysize(data_writes2));
session_deps_.socket_factory->AddSocketDataProvider(&data2);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
TestCompletionCallback callback1;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(
AuthCredentials(kFoo, kBar), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(100, response->headers->GetContentLength());
}
TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
MockRead proxy_reads[] = {
MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
MockRead(SYNCHRONOUS, OK)
};
StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
SSLSocketDataProvider ssl(ASYNC, OK);
session_deps_.socket_factory->AddSocketDataProvider(&data);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
TestCompletionCallback callback;
session_deps_.socket_factory->ResetNextMockIndexes();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
}
TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
}
TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
base::FilePath temp_file_path;
ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
const uint64 kFakeSize = 100000;
UploadFileElementReader::ScopedOverridingContentLengthForTests
overriding_content_length(kFakeSize);
ScopedVector<UploadElementReader> element_readers;
element_readers.push_back(
new UploadFileElementReader(base::MessageLoopProxy::current().get(),
temp_file_path,
0,
kuint64max,
base::Time()));
UploadDataStream upload_data_stream(element_readers.Pass(), 0);
HttpRequestInfo request;
request.method = "POST";
request.url = GURL("http://www.google.com/upload");
request.upload_data_stream = &upload_data_stream;
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n\r\n"),
MockRead("hello world"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
std::string response_data;
rv = ReadTransaction(trans.get(), &response_data);
EXPECT_EQ(OK, rv);
EXPECT_EQ("hello world", response_data);
base::DeleteFile(temp_file_path, false);
}
TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
base::FilePath temp_file;
ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
std::string temp_file_content("Unreadable file.");
ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
temp_file_content.length()));
ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
ScopedVector<UploadElementReader> element_readers;
element_readers.push_back(
new UploadFileElementReader(base::MessageLoopProxy::current().get(),
temp_file,
0,
kuint64max,
base::Time()));
UploadDataStream upload_data_stream(element_readers.Pass(), 0);
HttpRequestInfo request;
request.method = "POST";
request.url = GURL("http://www.google.com/upload");
request.upload_data_stream = &upload_data_stream;
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
StaticSocketDataProvider data(NULL, 0, NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(ERR_ACCESS_DENIED, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
EXPECT_FALSE(response);
base::DeleteFile(temp_file, false);
}
TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
class FakeUploadElementReader : public UploadElementReader {
public:
FakeUploadElementReader() {}
virtual ~FakeUploadElementReader() {}
const CompletionCallback& callback() const { return callback_; }
virtual int Init(const CompletionCallback& callback) OVERRIDE {
callback_ = callback;
return ERR_IO_PENDING;
}
virtual uint64 GetContentLength() const OVERRIDE { return 0; }
virtual uint64 BytesRemaining() const OVERRIDE { return 0; }
virtual int Read(IOBuffer* buf,
int buf_length,
const CompletionCallback& callback) OVERRIDE {
return ERR_FAILED;
}
private:
CompletionCallback callback_;
};
FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
ScopedVector<UploadElementReader> element_readers;
element_readers.push_back(fake_reader);
UploadDataStream upload_data_stream(element_readers.Pass(), 0);
HttpRequestInfo request;
request.method = "POST";
request.url = GURL("http://www.google.com/upload");
request.upload_data_stream = &upload_data_stream;
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
StaticSocketDataProvider data;
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
base::MessageLoop::current()->RunUntilIdle();
ASSERT_FALSE(fake_reader->callback().is_null());
trans.reset();
fake_reader->callback().Run(OK);
}
TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.1 401 Unauthorized\r\n"
"WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
"\r\n"),
};
MockWrite data_writes2[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic Zmlyc3Q6YmF6\r\n"
"\r\n"),
};
MockRead data_reads2[] = {
MockRead("HTTP/1.1 401 Unauthorized\r\n"
"WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
"\r\n"),
};
MockWrite data_writes3[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
"\r\n"),
};
MockRead data_reads3[] = {
MockRead("HTTP/1.1 401 Unauthorized\r\n"
"WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
"\r\n"),
};
MockWrite data_writes4[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: Basic Zmlyc3Q6YmFy\r\n"
"\r\n"),
};
MockRead data_reads4[] = {
MockRead("HTTP/1.1 200 OK\r\n"
"Content-Type: text/html; charset=iso-8859-1\r\n"
"Content-Length: 5\r\n"
"\r\n"
"hello"),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
data_writes2, arraysize(data_writes2));
StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
data_writes3, arraysize(data_writes3));
StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
data_writes4, arraysize(data_writes4));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
session_deps_.socket_factory->AddSocketDataProvider(&data3);
session_deps_.socket_factory->AddSocketDataProvider(&data4);
TestCompletionCallback callback1;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
const AuthChallengeInfo* challenge = response->auth_challenge.get();
ASSERT_FALSE(challenge == NULL);
EXPECT_FALSE(challenge->is_proxy);
EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
EXPECT_EQ("first_realm", challenge->realm);
EXPECT_EQ("basic", challenge->scheme);
TestCompletionCallback callback2;
rv = trans->RestartWithAuth(
AuthCredentials(kFirst, kBaz), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback2.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
challenge = response->auth_challenge.get();
ASSERT_FALSE(challenge == NULL);
EXPECT_FALSE(challenge->is_proxy);
EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
EXPECT_EQ("second_realm", challenge->realm);
EXPECT_EQ("basic", challenge->scheme);
TestCompletionCallback callback3;
rv = trans->RestartWithAuth(
AuthCredentials(kSecond, kFou), callback3.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback3.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
challenge = response->auth_challenge.get();
ASSERT_FALSE(challenge == NULL);
EXPECT_FALSE(challenge->is_proxy);
EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
EXPECT_EQ("first_realm", challenge->realm);
EXPECT_EQ("basic", challenge->scheme);
TestCompletionCallback callback4;
rv = trans->RestartWithAuth(
AuthCredentials(kFirst, kBar), callback4.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback4.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
}
TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
HttpStreamFactory::SetNextProtos(SpdyNextProtos());
HttpStreamFactory::set_use_alternate_protocols(true);
std::string alternate_protocol_http_header =
GetAlternateProtocolHttpHeader();
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead(alternate_protocol_http_header.c_str()),
MockRead("hello world"),
MockRead(SYNCHRONOUS, OK),
};
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
HostPortPair http_host_port_pair("www.google.com", 80);
HttpServerProperties& http_server_properties =
*session->http_server_properties();
EXPECT_FALSE(
http_server_properties.HasAlternateProtocol(http_host_port_pair));
EXPECT_EQ(OK, callback.WaitForResult());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
EXPECT_FALSE(response->was_fetched_via_spdy);
EXPECT_FALSE(response->was_npn_negotiated);
std::string response_data;
ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
EXPECT_EQ("hello world", response_data);
ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
const PortAlternateProtocolPair alternate =
http_server_properties.GetAlternateProtocol(http_host_port_pair);
PortAlternateProtocolPair expected_alternate;
expected_alternate.port = 443;
expected_alternate.protocol = AlternateProtocolFromNextProto(GetParam());
EXPECT_TRUE(expected_alternate.Equals(alternate));
}
TEST_P(HttpNetworkTransactionTest,
MarkBrokenAlternateProtocolAndFallback) {
HttpStreamFactory::set_use_alternate_protocols(true);
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
StaticSocketDataProvider first_data;
first_data.set_connect_data(mock_connect);
session_deps_.socket_factory->AddSocketDataProvider(&first_data);
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n\r\n"),
MockRead("hello world"),
MockRead(ASYNC, OK),
};
StaticSocketDataProvider second_data(
data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&second_data);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
base::WeakPtr<HttpServerProperties> http_server_properties =
session->http_server_properties();
http_server_properties->SetAlternateProtocol(
HostPortPair::FromURL(request.url),
666 ,
AlternateProtocolFromNextProto(GetParam()));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
EXPECT_EQ("hello world", response_data);
ASSERT_TRUE(http_server_properties->HasAlternateProtocol(
HostPortPair::FromURL(request.url)));
const PortAlternateProtocolPair alternate =
http_server_properties->GetAlternateProtocol(
HostPortPair::FromURL(request.url));
EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
}
TEST_P(HttpNetworkTransactionTest,
AlternateProtocolPortRestrictedBlocked) {
HttpStreamFactory::set_use_alternate_protocols(true);
HttpRequestInfo restricted_port_request;
restricted_port_request.method = "GET";
restricted_port_request.url = GURL("http://www.google.com:1023/");
restricted_port_request.load_flags = 0;
MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
StaticSocketDataProvider first_data;
first_data.set_connect_data(mock_connect);
session_deps_.socket_factory->AddSocketDataProvider(&first_data);
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n\r\n"),
MockRead("hello world"),
MockRead(ASYNC, OK),
};
StaticSocketDataProvider second_data(
data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&second_data);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
base::WeakPtr<HttpServerProperties> http_server_properties =
session->http_server_properties();
const int kUnrestrictedAlternatePort = 1024;
http_server_properties->SetAlternateProtocol(
HostPortPair::FromURL(restricted_port_request.url),
kUnrestrictedAlternatePort,
AlternateProtocolFromNextProto(GetParam()));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
TestCompletionCallback callback;
int rv = trans->Start(
&restricted_port_request,
callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
}
TEST_P(HttpNetworkTransactionTest,
AlternateProtocolPortRestrictedPermitted) {
HttpStreamFactory::set_use_alternate_protocols(true);
session_deps_.enable_user_alternate_protocol_ports = true;
HttpRequestInfo restricted_port_request;
restricted_port_request.method = "GET";
restricted_port_request.url = GURL("http://www.google.com:1023/");
restricted_port_request.load_flags = 0;
MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
StaticSocketDataProvider first_data;
first_data.set_connect_data(mock_connect);
session_deps_.socket_factory->AddSocketDataProvider(&first_data);
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n\r\n"),
MockRead("hello world"),
MockRead(ASYNC, OK),
};
StaticSocketDataProvider second_data(
data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&second_data);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
base::WeakPtr<HttpServerProperties> http_server_properties =
session->http_server_properties();
const int kUnrestrictedAlternatePort = 1024;
http_server_properties->SetAlternateProtocol(
HostPortPair::FromURL(restricted_port_request.url),
kUnrestrictedAlternatePort,
AlternateProtocolFromNextProto(GetParam()));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING, trans->Start(
&restricted_port_request,
callback.callback(), BoundNetLog()));
EXPECT_EQ(OK, callback.WaitForResult());
}
TEST_P(HttpNetworkTransactionTest,
AlternateProtocolPortRestrictedAllowed) {
HttpStreamFactory::set_use_alternate_protocols(true);
HttpRequestInfo restricted_port_request;
restricted_port_request.method = "GET";
restricted_port_request.url = GURL("http://www.google.com:1023/");
restricted_port_request.load_flags = 0;
MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
StaticSocketDataProvider first_data;
first_data.set_connect_data(mock_connect);
session_deps_.socket_factory->AddSocketDataProvider(&first_data);
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n\r\n"),
MockRead("hello world"),
MockRead(ASYNC, OK),
};
StaticSocketDataProvider second_data(
data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&second_data);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
base::WeakPtr<HttpServerProperties> http_server_properties =
session->http_server_properties();
const int kRestrictedAlternatePort = 80;
http_server_properties->SetAlternateProtocol(
HostPortPair::FromURL(restricted_port_request.url),
kRestrictedAlternatePort,
AlternateProtocolFromNextProto(GetParam()));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
TestCompletionCallback callback;
int rv = trans->Start(
&restricted_port_request,
callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
}
TEST_P(HttpNetworkTransactionTest,
AlternateProtocolPortUnrestrictedAllowed1) {
HttpStreamFactory::set_use_alternate_protocols(true);
HttpRequestInfo unrestricted_port_request;
unrestricted_port_request.method = "GET";
unrestricted_port_request.url = GURL("http://www.google.com:1024/");
unrestricted_port_request.load_flags = 0;
MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
StaticSocketDataProvider first_data;
first_data.set_connect_data(mock_connect);
session_deps_.socket_factory->AddSocketDataProvider(&first_data);
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n\r\n"),
MockRead("hello world"),
MockRead(ASYNC, OK),
};
StaticSocketDataProvider second_data(
data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&second_data);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
base::WeakPtr<HttpServerProperties> http_server_properties =
session->http_server_properties();
const int kRestrictedAlternatePort = 80;
http_server_properties->SetAlternateProtocol(
HostPortPair::FromURL(unrestricted_port_request.url),
kRestrictedAlternatePort,
AlternateProtocolFromNextProto(GetParam()));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
TestCompletionCallback callback;
int rv = trans->Start(
&unrestricted_port_request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
}
TEST_P(HttpNetworkTransactionTest,
AlternateProtocolPortUnrestrictedAllowed2) {
HttpStreamFactory::set_use_alternate_protocols(true);
HttpRequestInfo unrestricted_port_request;
unrestricted_port_request.method = "GET";
unrestricted_port_request.url = GURL("http://www.google.com:1024/");
unrestricted_port_request.load_flags = 0;
MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
StaticSocketDataProvider first_data;
first_data.set_connect_data(mock_connect);
session_deps_.socket_factory->AddSocketDataProvider(&first_data);
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n\r\n"),
MockRead("hello world"),
MockRead(ASYNC, OK),
};
StaticSocketDataProvider second_data(
data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&second_data);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
base::WeakPtr<HttpServerProperties> http_server_properties =
session->http_server_properties();
const int kUnrestrictedAlternatePort = 1024;
http_server_properties->SetAlternateProtocol(
HostPortPair::FromURL(unrestricted_port_request.url),
kUnrestrictedAlternatePort,
AlternateProtocolFromNextProto(GetParam()));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
TestCompletionCallback callback;
int rv = trans->Start(
&unrestricted_port_request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
}
TEST_P(HttpNetworkTransactionTest,
AlternateProtocolUnsafeBlocked) {
HttpStreamFactory::set_use_alternate_protocols(true);
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n\r\n"),
MockRead("hello world"),
MockRead(ASYNC, OK),
};
StaticSocketDataProvider data(
data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
base::WeakPtr<HttpServerProperties> http_server_properties =
session->http_server_properties();
const int kUnsafePort = 7;
http_server_properties->SetAlternateProtocol(
HostPortPair::FromURL(request.url),
kUnsafePort,
AlternateProtocolFromNextProto(GetParam()));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
HttpStreamFactory::set_use_alternate_protocols(false);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
EXPECT_EQ("hello world", response_data);
}
TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
HttpStreamFactory::set_use_alternate_protocols(true);
HttpStreamFactory::SetNextProtos(SpdyNextProtos());
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
std::string alternate_protocol_http_header =
GetAlternateProtocolHttpHeader();
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead(alternate_protocol_http_header.c_str()),
MockRead("hello world"),
MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
MockRead(ASYNC, OK)
};
StaticSocketDataProvider first_transaction(
data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
scoped_ptr<SpdyFrame> req(
spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
MockWrite spdy_writes[] = { CreateMockWrite(*req) };
scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead spdy_reads[] = {
CreateMockRead(*resp),
CreateMockRead(*data),
MockRead(ASYNC, 0, 0),
};
DelayedSocketData spdy_data(
1,
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
StaticSocketDataProvider hanging_non_alternate_protocol_socket(
NULL, 0, NULL, 0);
hanging_non_alternate_protocol_socket.set_connect_data(
never_finishing_connect);
session_deps_.socket_factory->AddSocketDataProvider(
&hanging_non_alternate_protocol_socket);
TestCompletionCallback callback;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
EXPECT_EQ("hello world", response_data);
trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
EXPECT_TRUE(response->was_fetched_via_spdy);
EXPECT_TRUE(response->was_npn_negotiated);
ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
EXPECT_EQ("hello!", response_data);
}
TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
HttpStreamFactory::set_use_alternate_protocols(true);
HttpStreamFactory::SetNextProtos(SpdyNextProtos());
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
std::string alternate_protocol_http_header =
GetAlternateProtocolHttpHeader();
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead(alternate_protocol_http_header.c_str()),
MockRead("hello world"),
MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
MockRead(ASYNC, OK),
};
StaticSocketDataProvider first_transaction(
data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
StaticSocketDataProvider hanging_socket(
NULL, 0, NULL, 0);
hanging_socket.set_connect_data(never_finishing_connect);
session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
scoped_ptr<SpdyFrame> req1(
spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
scoped_ptr<SpdyFrame> req2(
spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
MockWrite spdy_writes[] = {
CreateMockWrite(*req1),
CreateMockWrite(*req2),
};
scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
MockRead spdy_reads[] = {
CreateMockRead(*resp1),
CreateMockRead(*data1),
CreateMockRead(*resp2),
CreateMockRead(*data2),
MockRead(ASYNC, 0, 0),
};
DelayedSocketData spdy_data(
2,
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
TestCompletionCallback callback1;
HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback1.WaitForResult());
const HttpResponseInfo* response = trans1.GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
EXPECT_EQ("hello world", response_data);
TestCompletionCallback callback2;
HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
TestCompletionCallback callback3;
HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback2.WaitForResult());
EXPECT_EQ(OK, callback3.WaitForResult());
response = trans2.GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
EXPECT_TRUE(response->was_fetched_via_spdy);
EXPECT_TRUE(response->was_npn_negotiated);
ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
EXPECT_EQ("hello!", response_data);
response = trans3.GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
EXPECT_TRUE(response->was_fetched_via_spdy);
EXPECT_TRUE(response->was_npn_negotiated);
ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
EXPECT_EQ("hello!", response_data);
}
TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
HttpStreamFactory::set_use_alternate_protocols(true);
HttpStreamFactory::SetNextProtos(SpdyNextProtos());
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
std::string alternate_protocol_http_header =
GetAlternateProtocolHttpHeader();
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead(alternate_protocol_http_header.c_str()),
MockRead("hello world"),
MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
MockRead(ASYNC, OK),
};
StaticSocketDataProvider first_transaction(
data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
StaticSocketDataProvider hanging_alternate_protocol_socket(
NULL, 0, NULL, 0);
hanging_alternate_protocol_socket.set_connect_data(
never_finishing_connect);
session_deps_.socket_factory->AddSocketDataProvider(
&hanging_alternate_protocol_socket);
session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
TestCompletionCallback callback;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
EXPECT_EQ("hello world", response_data);
trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
EXPECT_FALSE(response->was_fetched_via_spdy);
EXPECT_FALSE(response->was_npn_negotiated);
ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
EXPECT_EQ("hello world", response_data);
}
class CapturingProxyResolver : public ProxyResolver {
public:
CapturingProxyResolver() : ProxyResolver(false ) {}
virtual ~CapturingProxyResolver() {}
virtual int GetProxyForURL(const GURL& url,
ProxyInfo* results,
const CompletionCallback& callback,
RequestHandle* request,
const BoundNetLog& net_log) OVERRIDE {
ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
HostPortPair("myproxy", 80));
results->UseProxyServer(proxy_server);
resolved_.push_back(url);
return OK;
}
virtual void CancelRequest(RequestHandle request) OVERRIDE {
NOTREACHED();
}
virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
NOTREACHED();
return LOAD_STATE_IDLE;
}
virtual void CancelSetPacScript() OVERRIDE {
NOTREACHED();
}
virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
const CompletionCallback& ) OVERRIDE {
return OK;
}
const std::vector<GURL>& resolved() const { return resolved_; }
private:
std::vector<GURL> resolved_;
DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
};
TEST_P(HttpNetworkTransactionTest,
UseAlternateProtocolForTunneledNpnSpdy) {
HttpStreamFactory::set_use_alternate_protocols(true);
HttpStreamFactory::SetNextProtos(SpdyNextProtos());
ProxyConfig proxy_config;
proxy_config.set_auto_detect(true);
proxy_config.set_pac_url(GURL("http://fooproxyurl"));
CapturingProxyResolver* capturing_proxy_resolver =
new CapturingProxyResolver();
session_deps_.proxy_service.reset(new ProxyService(
new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
NULL));
CapturingNetLog net_log;
session_deps_.net_log = &net_log;
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
std::string alternate_protocol_http_header =
GetAlternateProtocolHttpHeader();
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead(alternate_protocol_http_header.c_str()),
MockRead("hello world"),
MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
MockRead(ASYNC, OK),
};
StaticSocketDataProvider first_transaction(
data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
scoped_ptr<SpdyFrame> req(
spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
MockWrite spdy_writes[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
CreateMockWrite(*req),
};
const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead spdy_reads[] = {
MockRead(ASYNC, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1),
CreateMockRead(*resp.get(), 4),
CreateMockRead(*data.get(), 4),
MockRead(ASYNC, 0, 0, 4),
};
OrderedSocketData spdy_data(
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
StaticSocketDataProvider hanging_non_alternate_protocol_socket(
NULL, 0, NULL, 0);
hanging_non_alternate_protocol_socket.set_connect_data(
never_finishing_connect);
session_deps_.socket_factory->AddSocketDataProvider(
&hanging_non_alternate_protocol_socket);
TestCompletionCallback callback;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
EXPECT_FALSE(response->was_fetched_via_spdy);
EXPECT_FALSE(response->was_npn_negotiated);
std::string response_data;
ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
EXPECT_EQ("hello world", response_data);
trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
EXPECT_TRUE(response->was_fetched_via_spdy);
EXPECT_TRUE(response->was_npn_negotiated);
ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
EXPECT_EQ("hello!", response_data);
ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
EXPECT_EQ("http://www.google.com/",
capturing_proxy_resolver->resolved()[0].spec());
EXPECT_EQ("https://www.google.com/",
capturing_proxy_resolver->resolved()[1].spec());
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReusedWithPac(load_timing_info,
CONNECT_TIMING_HAS_SSL_TIMES);
}
TEST_P(HttpNetworkTransactionTest,
UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
HttpStreamFactory::set_use_alternate_protocols(true);
HttpStreamFactory::SetNextProtos(SpdyNextProtos());
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
std::string alternate_protocol_http_header =
GetAlternateProtocolHttpHeader();
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead(alternate_protocol_http_header.c_str()),
MockRead("hello world"),
MockRead(ASYNC, OK),
};
StaticSocketDataProvider first_transaction(
data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
scoped_ptr<SpdyFrame> req(
spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
MockWrite spdy_writes[] = { CreateMockWrite(*req) };
scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead spdy_reads[] = {
CreateMockRead(*resp),
CreateMockRead(*data),
MockRead(ASYNC, 0, 0),
};
DelayedSocketData spdy_data(
1,
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
TestCompletionCallback callback;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
EXPECT_EQ("hello world", response_data);
HostPortPair host_port_pair("www.google.com", 443);
SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
PRIVACY_MODE_DISABLED);
base::WeakPtr<SpdySession> spdy_session =
CreateSecureSpdySession(session, key, BoundNetLog());
trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
EXPECT_TRUE(response->was_fetched_via_spdy);
EXPECT_TRUE(response->was_npn_negotiated);
ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
EXPECT_EQ("hello!", response_data);
}
TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
static const char kServer[] = "http://www.example.com";
static const char kSecureServer[] = "https://www.example.com";
static const char kProxy[] = "myproxy:70";
const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
enum AuthTiming {
AUTH_NONE,
AUTH_SYNC,
AUTH_ASYNC,
};
const MockWrite kGet(
"GET / HTTP/1.1\r\n"
"Host: www.example.com\r\n"
"Connection: keep-alive\r\n\r\n");
const MockWrite kGetProxy(
"GET http://www.example.com/ HTTP/1.1\r\n"
"Host: www.example.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n");
const MockWrite kGetAuth(
"GET / HTTP/1.1\r\n"
"Host: www.example.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: auth_token\r\n\r\n");
const MockWrite kGetProxyAuth(
"GET http://www.example.com/ HTTP/1.1\r\n"
"Host: www.example.com\r\n"
"Proxy-Connection: keep-alive\r\n"
"Proxy-Authorization: auth_token\r\n\r\n");
const MockWrite kGetAuthThroughProxy(
"GET http://www.example.com/ HTTP/1.1\r\n"
"Host: www.example.com\r\n"
"Proxy-Connection: keep-alive\r\n"
"Authorization: auth_token\r\n\r\n");
const MockWrite kGetAuthWithProxyAuth(
"GET http://www.example.com/ HTTP/1.1\r\n"
"Host: www.example.com\r\n"
"Proxy-Connection: keep-alive\r\n"
"Proxy-Authorization: auth_token\r\n"
"Authorization: auth_token\r\n\r\n");
const MockWrite kConnect(
"CONNECT www.example.com:443 HTTP/1.1\r\n"
"Host: www.example.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n");
const MockWrite kConnectProxyAuth(
"CONNECT www.example.com:443 HTTP/1.1\r\n"
"Host: www.example.com\r\n"
"Proxy-Connection: keep-alive\r\n"
"Proxy-Authorization: auth_token\r\n\r\n");
const MockRead kSuccess(
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html; charset=iso-8859-1\r\n"
"Content-Length: 3\r\n\r\n"
"Yes");
const MockRead kFailure(
"Should not be called.");
const MockRead kServerChallenge(
"HTTP/1.1 401 Unauthorized\r\n"
"WWW-Authenticate: Mock realm=server\r\n"
"Content-Type: text/html; charset=iso-8859-1\r\n"
"Content-Length: 14\r\n\r\n"
"Unauthorized\r\n");
const MockRead kProxyChallenge(
"HTTP/1.1 407 Unauthorized\r\n"
"Proxy-Authenticate: Mock realm=proxy\r\n"
"Proxy-Connection: close\r\n"
"Content-Type: text/html; charset=iso-8859-1\r\n"
"Content-Length: 14\r\n\r\n"
"Unauthorized\r\n");
const MockRead kProxyConnected(
"HTTP/1.1 200 Connection Established\r\n\r\n");
struct TestRound {
TestRound()
: expected_rv(ERR_UNEXPECTED),
extra_write(NULL),
extra_read(NULL) {
}
TestRound(const MockWrite& write_arg, const MockRead& read_arg,
int expected_rv_arg)
: write(write_arg),
read(read_arg),
expected_rv(expected_rv_arg),
extra_write(NULL),
extra_read(NULL) {
}
TestRound(const MockWrite& write_arg, const MockRead& read_arg,
int expected_rv_arg, const MockWrite* extra_write_arg,
const MockRead* extra_read_arg)
: write(write_arg),
read(read_arg),
expected_rv(expected_rv_arg),
extra_write(extra_write_arg),
extra_read(extra_read_arg) {
}
MockWrite write;
MockRead read;
int expected_rv;
const MockWrite* extra_write;
const MockRead* extra_read;
};
static const int kNoSSL = 500;
struct TestConfig {
const char* proxy_url;
AuthTiming proxy_auth_timing;
int proxy_auth_rv;
const char* server_url;
AuthTiming server_auth_timing;
int server_auth_rv;
int num_auth_rounds;
int first_ssl_round;
TestRound rounds[3];
} test_configs[] = {
{ NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
{ TestRound(kGet, kSuccess, OK)}},
{ NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
{ TestRound(kGet, kServerChallenge, OK),
TestRound(kGetAuth, kSuccess, OK)}},
{ NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
{ TestRound(kGet, kServerChallenge, OK),
TestRound(kGetAuth, kFailure, kAuthErr)}},
{ NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
{ TestRound(kGet, kServerChallenge, OK),
TestRound(kGetAuth, kSuccess, OK)}},
{ NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
{ TestRound(kGet, kServerChallenge, OK),
TestRound(kGetAuth, kFailure, kAuthErr)}},
{ kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
{ TestRound(kGetProxy, kSuccess, OK)}},
{ kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
{ TestRound(kGetProxy, kServerChallenge, OK),
TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
{ kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
{ TestRound(kGetProxy, kServerChallenge, OK),
TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
{ kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
{ TestRound(kGetProxy, kServerChallenge, OK),
TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
{ kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
{ TestRound(kGetProxy, kServerChallenge, OK),
TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
{ kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
{ TestRound(kGetProxy, kProxyChallenge, OK),
TestRound(kGetProxyAuth, kSuccess, OK)}},
{ kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
{ TestRound(kGetProxy, kProxyChallenge, OK),
TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
{ kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
{ TestRound(kGetProxy, kProxyChallenge, OK),
TestRound(kGetProxyAuth, kSuccess, OK)}},
{ kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
{ TestRound(kGetProxy, kProxyChallenge, OK),
TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
{ kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
{ TestRound(kGetProxy, kProxyChallenge, OK),
TestRound(kGetProxyAuth, kServerChallenge, OK),
TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
{ kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
{ TestRound(kGetProxy, kProxyChallenge, OK),
TestRound(kGetProxyAuth, kServerChallenge, OK),
TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
{ kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
{ TestRound(kGetProxy, kProxyChallenge, OK),
TestRound(kGetProxyAuth, kServerChallenge, OK),
TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
{ kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
{ TestRound(kGetProxy, kProxyChallenge, OK),
TestRound(kGetProxyAuth, kServerChallenge, OK),
TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
{ kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
{ TestRound(kGetProxy, kProxyChallenge, OK),
TestRound(kGetProxyAuth, kServerChallenge, OK),
TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
{ kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
{ TestRound(kGetProxy, kProxyChallenge, OK),
TestRound(kGetProxyAuth, kServerChallenge, OK),
TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
{ kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
{ TestRound(kGetProxy, kProxyChallenge, OK),
TestRound(kGetProxyAuth, kServerChallenge, OK),
TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
{ kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
{ TestRound(kGetProxy, kProxyChallenge, OK),
TestRound(kGetProxyAuth, kServerChallenge, OK),
TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
{ NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
{ TestRound(kGet, kSuccess, OK)}},
{ NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
{ TestRound(kGet, kServerChallenge, OK),
TestRound(kGetAuth, kSuccess, OK)}},
{ NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
{ TestRound(kGet, kServerChallenge, OK),
TestRound(kGetAuth, kFailure, kAuthErr)}},
{ NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
{ TestRound(kGet, kServerChallenge, OK),
TestRound(kGetAuth, kSuccess, OK)}},
{ NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
{ TestRound(kGet, kServerChallenge, OK),
TestRound(kGetAuth, kFailure, kAuthErr)}},
{ kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
{ TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
{ kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
{ TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
TestRound(kGetAuth, kSuccess, OK)}},
{ kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
{ TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
TestRound(kGetAuth, kFailure, kAuthErr)}},
{ kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
{ TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
TestRound(kGetAuth, kSuccess, OK)}},
{ kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
{ TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
TestRound(kGetAuth, kFailure, kAuthErr)}},
{ kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
{ TestRound(kConnect, kProxyChallenge, OK),
TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
{ kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
{ TestRound(kConnect, kProxyChallenge, OK),
TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
{ kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
{ TestRound(kConnect, kProxyChallenge, OK),
TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
{ kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
{ TestRound(kConnect, kProxyChallenge, OK),
TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
{ kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
{ TestRound(kConnect, kProxyChallenge, OK),
TestRound(kConnectProxyAuth, kProxyConnected, OK,
&kGet, &kServerChallenge),
TestRound(kGetAuth, kSuccess, OK)}},
{ kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
{ TestRound(kConnect, kProxyChallenge, OK),
TestRound(kConnectProxyAuth, kProxyConnected, OK,
&kGet, &kServerChallenge),
TestRound(kGetAuth, kFailure, kAuthErr)}},
{ kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
{ TestRound(kConnect, kProxyChallenge, OK),
TestRound(kConnectProxyAuth, kProxyConnected, OK,
&kGet, &kServerChallenge),
TestRound(kGetAuth, kSuccess, OK)}},
{ kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
{ TestRound(kConnect, kProxyChallenge, OK),
TestRound(kConnectProxyAuth, kProxyConnected, OK,
&kGet, &kServerChallenge),
TestRound(kGetAuth, kFailure, kAuthErr)}},
{ kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
{ TestRound(kConnect, kProxyChallenge, OK),
TestRound(kConnectProxyAuth, kProxyConnected, OK,
&kGet, &kServerChallenge),
TestRound(kGetAuth, kSuccess, OK)}},
{ kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
{ TestRound(kConnect, kProxyChallenge, OK),
TestRound(kConnectProxyAuth, kProxyConnected, OK,
&kGet, &kServerChallenge),
TestRound(kGetAuth, kFailure, kAuthErr)}},
{ kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
{ TestRound(kConnect, kProxyChallenge, OK),
TestRound(kConnectProxyAuth, kProxyConnected, OK,
&kGet, &kServerChallenge),
TestRound(kGetAuth, kSuccess, OK)}},
{ kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
{ TestRound(kConnect, kProxyChallenge, OK),
TestRound(kConnectProxyAuth, kProxyConnected, OK,
&kGet, &kServerChallenge),
TestRound(kGetAuth, kFailure, kAuthErr)}},
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
HttpAuthHandlerMock::Factory* auth_factory(
new HttpAuthHandlerMock::Factory());
session_deps_.http_auth_handler_factory.reset(auth_factory);
const TestConfig& test_config = test_configs[i];
if (test_config.proxy_auth_timing != AUTH_NONE) {
for (int n = 0; n < 2; n++) {
HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
std::string auth_challenge = "Mock realm=proxy";
GURL origin(test_config.proxy_url);
HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
auth_challenge.end());
auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
origin, BoundNetLog());
auth_handler->SetGenerateExpectation(
test_config.proxy_auth_timing == AUTH_ASYNC,
test_config.proxy_auth_rv);
auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
}
}
if (test_config.server_auth_timing != AUTH_NONE) {
HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
std::string auth_challenge = "Mock realm=server";
GURL origin(test_config.server_url);
HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
auth_challenge.end());
auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
origin, BoundNetLog());
auth_handler->SetGenerateExpectation(
test_config.server_auth_timing == AUTH_ASYNC,
test_config.server_auth_rv);
auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
}
if (test_config.proxy_url) {
session_deps_.proxy_service.reset(
ProxyService::CreateFixed(test_config.proxy_url));
} else {
session_deps_.proxy_service.reset(ProxyService::CreateDirect());
}
HttpRequestInfo request;
request.method = "GET";
request.url = GURL(test_config.server_url);
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
for (int round = 0; round < test_config.num_auth_rounds; ++round) {
const TestRound& read_write_round = test_config.rounds[round];
MockRead reads[2];
reads[0] = read_write_round.read;
size_t length_reads = 1;
if (read_write_round.extra_read) {
reads[1] = *read_write_round.extra_read;
length_reads = 2;
}
MockWrite writes[2];
writes[0] = read_write_round.write;
size_t length_writes = 1;
if (read_write_round.extra_write) {
writes[1] = *read_write_round.extra_write;
length_writes = 2;
}
StaticSocketDataProvider data_provider(
reads, length_reads, writes, length_writes);
session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
if (round >= test_config.first_ssl_round)
session_deps_.socket_factory->AddSSLSocketDataProvider(
&ssl_socket_data_provider);
TestCompletionCallback callback;
int rv;
if (round == 0) {
rv = trans.Start(&request, callback.callback(), BoundNetLog());
} else {
rv = trans.RestartWithAuth(
AuthCredentials(kFoo, kBar), callback.callback());
}
if (rv == ERR_IO_PENDING)
rv = callback.WaitForResult();
EXPECT_EQ(read_write_round.expected_rv, rv);
const HttpResponseInfo* response = trans.GetResponseInfo();
if (read_write_round.expected_rv == OK) {
ASSERT_TRUE(response != NULL);
} else {
EXPECT_TRUE(response == NULL);
EXPECT_EQ(round + 1, test_config.num_auth_rounds);
continue;
}
if (round + 1 < test_config.num_auth_rounds) {
EXPECT_FALSE(response->auth_challenge.get() == NULL);
} else {
EXPECT_TRUE(response->auth_challenge.get() == NULL);
}
}
}
}
TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
HttpAuthHandlerMock::Factory* auth_factory(
new HttpAuthHandlerMock::Factory());
session_deps_.http_auth_handler_factory.reset(auth_factory);
session_deps_.proxy_service.reset(ProxyService::CreateDirect());
session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
session_deps_.host_resolver->set_synchronous_mode(true);
HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
auth_handler->set_connection_based(true);
std::string auth_challenge = "Mock realm=server";
GURL origin("http://www.example.com");
HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
auth_challenge.end());
auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
origin, BoundNetLog());
auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
int rv = OK;
const HttpResponseInfo* response = NULL;
HttpRequestInfo request;
request.method = "GET";
request.url = origin;
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
HttpNetworkSessionPeer session_peer(session);
ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
50,
1,
&transport_pool_histograms,
session_deps_.host_resolver.get(),
session_deps_.socket_factory.get(),
session_deps_.net_log);
scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
new MockClientSocketPoolManager);
mock_pool_manager->SetTransportSocketPool(transport_pool);
session_peer.SetClientSocketPoolManager(
mock_pool_manager.PassAs<ClientSocketPoolManager>());
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
TestCompletionCallback callback;
const MockWrite kGet(
"GET / HTTP/1.1\r\n"
"Host: www.example.com\r\n"
"Connection: keep-alive\r\n\r\n");
const MockWrite kGetAuth(
"GET / HTTP/1.1\r\n"
"Host: www.example.com\r\n"
"Connection: keep-alive\r\n"
"Authorization: auth_token\r\n\r\n");
const MockRead kServerChallenge(
"HTTP/1.1 401 Unauthorized\r\n"
"WWW-Authenticate: Mock realm=server\r\n"
"Content-Type: text/html; charset=iso-8859-1\r\n"
"Content-Length: 14\r\n\r\n"
"Unauthorized\r\n");
const MockRead kSuccess(
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html; charset=iso-8859-1\r\n"
"Content-Length: 3\r\n\r\n"
"Yes");
MockWrite writes[] = {
kGet,
kGetAuth,
kGetAuth,
kGetAuth,
kGet,
};
MockRead reads[] = {
kServerChallenge,
kServerChallenge,
kServerChallenge,
kSuccess,
kSuccess,
};
StaticSocketDataProvider data_provider(reads, arraysize(reads),
writes, arraysize(writes));
session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
const char* const kSocketGroup = "www.example.com:80";
auth_handler->SetGenerateExpectation(false, OK);
rv = trans->Start(&request, callback.callback(), BoundNetLog());
if (rv == ERR_IO_PENDING)
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_FALSE(response->auth_challenge.get() == NULL);
EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
scoped_ptr<HttpTransaction> trans_compete(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
TestCompletionCallback callback_compete;
rv = trans_compete->Start(
&request, callback_compete.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
auth_handler->SetGenerateExpectation(false, OK);
rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
if (rv == ERR_IO_PENDING)
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
auth_handler->SetGenerateExpectation(false, OK);
rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
if (rv == ERR_IO_PENDING)
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
auth_handler->SetGenerateExpectation(false, OK);
rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
if (rv == ERR_IO_PENDING)
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
if (rv == ERR_IO_PENDING)
rv = callback.WaitForResult();
EXPECT_EQ(3, rv);
rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
EXPECT_EQ(0, rv);
EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
rv = callback_compete.WaitForResult();
EXPECT_EQ(OK, rv);
rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
if (rv == ERR_IO_PENDING)
rv = callback.WaitForResult();
EXPECT_EQ(3, rv);
rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
EXPECT_EQ(0, rv);
EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
}
TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
HttpStreamFactory::set_use_alternate_protocols(true);
std::vector<NextProto> next_protos;
next_protos.push_back(kProtoHTTP11);
HttpStreamFactory::SetNextProtos(next_protos);
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
std::string alternate_protocol_http_header =
GetAlternateProtocolHttpHeader();
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead(alternate_protocol_http_header.c_str()),
MockRead("hello world"),
MockRead(SYNCHRONOUS, OK),
};
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
ssl.next_proto = "http/1.1";
ssl.protocol_negotiated = kProtoHTTP11;
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
EXPECT_EQ("hello world", response_data);
EXPECT_FALSE(response->was_fetched_via_spdy);
EXPECT_TRUE(response->was_npn_negotiated);
}
TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
HttpStreamFactory::set_use_alternate_protocols(true);
HttpStreamFactory::SetNextProtos(SpdyNextProtos());
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
scoped_ptr<SpdyFrame> req(
spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
MockWrite spdy_writes[] = { CreateMockWrite(*req) };
MockRead spdy_reads[] = {
MockRead(SYNCHRONOUS, 0, 0)
};
DelayedSocketData spdy_data(
0,
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
TestCompletionCallback callback;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
}
class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
public:
explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
virtual ~UrlRecordingHttpAuthHandlerMock() {}
protected:
virtual int GenerateAuthTokenImpl(const AuthCredentials* credentials,
const HttpRequestInfo* request,
const CompletionCallback& callback,
std::string* auth_token) OVERRIDE {
*url_ = request->url;
return HttpAuthHandlerMock::GenerateAuthTokenImpl(
credentials, request, callback, auth_token);
}
private:
GURL* url_;
};
TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
HttpStreamFactory::set_use_alternate_protocols(true);
HttpStreamFactory::SetNextProtos(SpdyNextProtos());
session_deps_.proxy_service.reset(
ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
CapturingNetLog net_log;
session_deps_.net_log = &net_log;
GURL request_url;
{
HttpAuthHandlerMock::Factory* auth_factory =
new HttpAuthHandlerMock::Factory();
UrlRecordingHttpAuthHandlerMock* auth_handler =
new UrlRecordingHttpAuthHandlerMock(&request_url);
auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
auth_factory->set_do_init_from_challenge(true);
session_deps_.http_auth_handler_factory.reset(auth_factory);
}
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com");
request.load_flags = 0;
MockWrite data_writes_1[] = {
MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n"
"\r\n"),
};
MockRead data_reads_1[] = {
MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
MockRead("HTTP/1.1 200 OK\r\n"
"Alternate-Protocol: 443:npn-spdy/2\r\n"
"Proxy-Connection: close\r\n"
"\r\n"),
};
StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
data_writes_1, arraysize(data_writes_1));
scoped_ptr<SpdyFrame> req(
spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
MockWrite data_writes_2[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n"
"\r\n"),
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n"
"Proxy-Authorization: auth_token\r\n"
"\r\n"),
CreateMockWrite(*req),
};
const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
"Proxy-Authenticate: Mock\r\n"
"Proxy-Connection: close\r\n"
"\r\n");
const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
MockRead data_reads_2[] = {
MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
MockRead(ASYNC, kRejectConnectResponse,
arraysize(kRejectConnectResponse) - 1, 1),
MockRead(ASYNC, kAcceptConnectResponse,
arraysize(kAcceptConnectResponse) -1, 4),
CreateMockRead(*resp.get(), 6),
CreateMockRead(*data.get(), 6),
MockRead(ASYNC, 0, 0, 6),
};
OrderedSocketData data_2(
data_reads_2, arraysize(data_reads_2),
data_writes_2, arraysize(data_writes_2));
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
StaticSocketDataProvider hanging_non_alternate_protocol_socket(
NULL, 0, NULL, 0);
hanging_non_alternate_protocol_socket.set_connect_data(
never_finishing_connect);
session_deps_.socket_factory->AddSocketDataProvider(&data_1);
session_deps_.socket_factory->AddSocketDataProvider(&data_2);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
session_deps_.socket_factory->AddSocketDataProvider(
&hanging_non_alternate_protocol_socket);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
TestCompletionCallback callback_1;
scoped_ptr<HttpTransaction> trans_1(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback_1.WaitForResult());
TestCompletionCallback callback_2;
scoped_ptr<HttpTransaction> trans_2(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback_2.WaitForResult());
const HttpResponseInfo* response = trans_2->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_FALSE(response->auth_challenge.get() == NULL);
TestCompletionCallback callback_3;
rv = trans_2->RestartWithAuth(
AuthCredentials(kFoo, kBar), callback_3.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback_3.WaitForResult());
EXPECT_EQ("https", request_url.scheme());
EXPECT_EQ("www.google.com", request_url.host());
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReusedWithPac(load_timing_info,
CONNECT_TIMING_HAS_SSL_TIMES);
}
TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
MockConnect mock_connect(SYNCHRONOUS, OK);
MockRead data_reads[] = {
MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
MockRead(SYNCHRONOUS, "hello world"),
MockRead(SYNCHRONOUS, OK),
};
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
session_deps_.host_resolver->set_synchronous_mode(true);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
data.set_connect_data(mock_connect);
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
CapturingBoundNetLog log;
int rv = trans->Start(&request, callback.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
trans.reset();
base::MessageLoop::current()->RunUntilIdle();
}
TEST_P(HttpNetworkTransactionTest, ProxyGet) {
session_deps_.proxy_service.reset(
ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
MockWrite data_writes1[] = {
MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
TestCompletionCallback callback1;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback1.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers->IsKeepAlive());
EXPECT_EQ(200, response->headers->response_code());
EXPECT_EQ(100, response->headers->GetContentLength());
EXPECT_TRUE(response->was_fetched_via_proxy);
EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReusedWithPac(load_timing_info,
CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
}
TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
session_deps_.proxy_service.reset(
ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
MockWrite data_writes1[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 100\r\n\r\n"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
SSLSocketDataProvider ssl(ASYNC, OK);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
TestCompletionCallback callback1;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback1.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
net::CapturingNetLog::CapturedEntryList entries;
log.GetEntries(&entries);
size_t pos = ExpectLogContainsSomewhere(
entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
NetLog::PHASE_NONE);
ExpectLogContainsSomewhere(
entries, pos,
NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
NetLog::PHASE_NONE);
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
EXPECT_TRUE(response->headers->IsKeepAlive());
EXPECT_EQ(200, response->headers->response_code());
EXPECT_EQ(100, response->headers->GetContentLength());
EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
EXPECT_TRUE(response->was_fetched_via_proxy);
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
TestLoadTimingNotReusedWithPac(load_timing_info,
CONNECT_TIMING_HAS_SSL_TIMES);
}
TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
MockWrite data_writes1[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"),
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads1[] = {
MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
MockRead(ASYNC, 0, 0),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
data_writes1, arraysize(data_writes1));
session_deps_.socket_factory->AddSocketDataProvider(&data1);
SSLSocketDataProvider ssl(ASYNC, OK);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
TestCompletionCallback callback1;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request, callback1.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
net::CapturingNetLog::CapturedEntryList entries;
log.GetEntries(&entries);
size_t pos = ExpectLogContainsSomewhere(
entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
NetLog::PHASE_NONE);
ExpectLogContainsSomewhere(
entries, pos,
NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
NetLog::PHASE_NONE);
}
TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
scoped_ptr<SpdyFrame> req(
spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
MockWrite spdy_writes[] = { CreateMockWrite(*req) };
scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead spdy_reads[] = {
CreateMockRead(*resp),
CreateMockRead(*data),
MockRead(ASYNC, 0, 0),
};
DelayedSocketData spdy_data(
1,
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
HostPortPair host_port_pair("www.google.com", 443);
SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
PRIVACY_MODE_DISABLED);
base::WeakPtr<SpdySession> spdy_session =
CreateInsecureSpdySession(session, key, BoundNetLog());
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
}
void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
int error, IoMode mode) {
net::HttpRequestInfo request_info;
request_info.url = GURL("https://www.example.com/");
request_info.method = "GET";
request_info.load_flags = net::LOAD_NORMAL;
SSLSocketDataProvider ssl_data(mode, OK);
net::MockWrite data_writes[] = {
net::MockWrite(mode, error),
};
net::StaticSocketDataProvider data(NULL, 0,
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
TestCompletionCallback callback;
int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
if (rv == net::ERR_IO_PENDING)
rv = callback.WaitForResult();
ASSERT_EQ(error, rv);
}
TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
static const int kErrors[] = {
ERR_CERT_COMMON_NAME_INVALID,
ERR_CERT_AUTHORITY_INVALID,
ERR_CERT_DATE_INVALID,
};
for (size_t i = 0; i < arraysize(kErrors); i++) {
CheckErrorIsPassedBack(kErrors[i], ASYNC);
CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
}
}
TEST_P(HttpNetworkTransactionTest,
ClientAuthCertCache_Direct_NoFalseStart) {
net::HttpRequestInfo request_info;
request_info.url = GURL("https://www.example.com/");
request_info.method = "GET";
request_info.load_flags = net::LOAD_NORMAL;
scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
cert_request->host_and_port = HostPortPair("www.example.com", 443);
SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
ssl_data1.cert_request_info = cert_request.get();
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data1);
SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
ssl_data2.cert_request_info = cert_request.get();
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
ssl_data3.cert_request_info = cert_request.get();
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data3);
SSLSocketDataProvider ssl_data4(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
ssl_data4.cert_request_info = cert_request.get();
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
net::StaticSocketDataProvider data4(NULL, 0, NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data4);
SSLSocketDataProvider ssl_data5(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
ssl_data5.cert_request_info = cert_request.get();
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
net::StaticSocketDataProvider data5(NULL, 0, NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data5);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
TestCompletionCallback callback;
int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
ASSERT_EQ(net::ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
rv = trans->RestartWithCertificate(NULL, callback.callback());
ASSERT_EQ(net::ERR_IO_PENDING, rv);
scoped_refptr<X509Certificate> client_cert;
ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
HostPortPair("www.example.com", 443), &client_cert));
ASSERT_EQ(NULL, client_cert.get());
rv = callback.WaitForResult();
ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
HostPortPair("www.example.com", 443), &client_cert));
}
TEST_P(HttpNetworkTransactionTest,
ClientAuthCertCache_Direct_FalseStart) {
net::HttpRequestInfo request_info;
request_info.url = GURL("https://www.example.com/");
request_info.method = "GET";
request_info.load_flags = net::LOAD_NORMAL;
scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
cert_request->host_and_port = HostPortPair("www.example.com", 443);
SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
ssl_data1.cert_request_info = cert_request.get();
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data1);
SSLSocketDataProvider ssl_data2(ASYNC, net::OK);
ssl_data2.cert_request_info = cert_request.get();
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
net::MockRead data2_reads[] = {
net::MockRead(ASYNC , net::ERR_SSL_PROTOCOL_ERROR),
};
net::StaticSocketDataProvider data2(
data2_reads, arraysize(data2_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
SSLSocketDataProvider ssl_data3(ASYNC, net::OK);
ssl_data3.cert_request_info = cert_request.get();
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
net::StaticSocketDataProvider data3(
data2_reads, arraysize(data2_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data3);
SSLSocketDataProvider ssl_data4(ASYNC, net::OK);
ssl_data4.cert_request_info = cert_request.get();
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
net::StaticSocketDataProvider data4(
data2_reads, arraysize(data2_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data4);
SSLSocketDataProvider ssl_data5(ASYNC, net::OK);
ssl_data5.cert_request_info = cert_request.get();
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
net::StaticSocketDataProvider data5(
data2_reads, arraysize(data2_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data5);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
TestCompletionCallback callback;
int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
ASSERT_EQ(net::ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
rv = trans->RestartWithCertificate(NULL, callback.callback());
ASSERT_EQ(net::ERR_IO_PENDING, rv);
scoped_refptr<X509Certificate> client_cert;
ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
HostPortPair("www.example.com", 443), &client_cert));
ASSERT_EQ(NULL, client_cert.get());
rv = callback.WaitForResult();
ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
HostPortPair("www.example.com", 443), &client_cert));
}
TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
session_deps_.proxy_service.reset(
ProxyService::CreateFixed("https://proxy:70"));
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
cert_request->host_and_port = HostPortPair("proxy", 70);
SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
ssl_data1.cert_request_info = cert_request.get();
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data1);
SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
ssl_data2.cert_request_info = cert_request.get();
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
#if 0
SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
ssl_data3.cert_request_info = cert_request.get();
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data3);
#endif
net::HttpRequestInfo requests[2];
requests[0].url = GURL("https://www.example.com/");
requests[0].method = "GET";
requests[0].load_flags = net::LOAD_NORMAL;
requests[1].url = GURL("http://www.example.com/");
requests[1].method = "GET";
requests[1].load_flags = net::LOAD_NORMAL;
for (size_t i = 0; i < arraysize(requests); ++i) {
session_deps_.socket_factory->ResetNextMockIndexes();
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpNetworkTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
TestCompletionCallback callback;
int rv = trans->Start(
&requests[i], callback.callback(), net::BoundNetLog());
ASSERT_EQ(net::ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
rv = trans->RestartWithCertificate(NULL, callback.callback());
ASSERT_EQ(net::ERR_IO_PENDING, rv);
scoped_refptr<X509Certificate> client_cert;
ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
HostPortPair("proxy", 70), &client_cert));
ASSERT_EQ(NULL, client_cert.get());
ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
HostPortPair("www.example.com", 443), &client_cert));
rv = callback.WaitForResult();
ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
HostPortPair("proxy", 70), &client_cert));
ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
HostPortPair("www.example.com", 443), &client_cert));
}
}
#define WRAPPED_TEST_P(test_case_name, test_name) \
TEST_P(test_case_name, test_name)
#if defined(OS_WIN)
#define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
#else
#define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
#endif
WRAPPED_TEST_P(HttpNetworkTransactionTest, MAYBE_UseIPConnectionPooling) {
HttpStreamFactory::set_use_alternate_protocols(true);
HttpStreamFactory::SetNextProtos(SpdyNextProtos());
session_deps_.host_resolver.reset(new MockCachingHostResolver());
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
pool_peer.DisableDomainAuthenticationVerification();
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
scoped_ptr<SpdyFrame> host1_req(
spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
scoped_ptr<SpdyFrame> host2_req(
spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
MockWrite spdy_writes[] = {
CreateMockWrite(*host1_req, 1),
CreateMockWrite(*host2_req, 4),
};
scoped_ptr<SpdyFrame> host1_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> host1_resp_body(
spdy_util_.ConstructSpdyBodyFrame(1, true));
scoped_ptr<SpdyFrame> host2_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
scoped_ptr<SpdyFrame> host2_resp_body(
spdy_util_.ConstructSpdyBodyFrame(3, true));
MockRead spdy_reads[] = {
CreateMockRead(*host1_resp, 2),
CreateMockRead(*host1_resp_body, 3),
CreateMockRead(*host2_resp, 5),
CreateMockRead(*host2_resp_body, 6),
MockRead(ASYNC, 0, 7),
};
IPAddressNumber ip;
ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
IPEndPoint peer_addr = IPEndPoint(ip, 443);
MockConnect connect(ASYNC, OK, peer_addr);
OrderedSocketData spdy_data(
connect,
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
TestCompletionCallback callback;
HttpRequestInfo request1;
request1.method = "GET";
request1.url = GURL("https://www.google.com/");
request1.load_flags = 0;
HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
const HttpResponseInfo* response = trans1.GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
EXPECT_EQ("hello!", response_data);
HostPortPair host_port("www.gmail.com", 443);
HostResolver::RequestInfo resolve_info(host_port);
AddressList ignored;
rv = session_deps_.host_resolver->Resolve(resolve_info,
DEFAULT_PRIORITY,
&ignored,
callback.callback(),
NULL,
BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
HttpRequestInfo request2;
request2.method = "GET";
request2.url = GURL("https://www.gmail.com/");
request2.load_flags = 0;
HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
response = trans2.GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
EXPECT_TRUE(response->was_fetched_via_spdy);
EXPECT_TRUE(response->was_npn_negotiated);
ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
EXPECT_EQ("hello!", response_data);
}
#undef MAYBE_UseIPConnectionPooling
TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
HttpStreamFactory::set_use_alternate_protocols(true);
HttpStreamFactory::SetNextProtos(SpdyNextProtos());
session_deps_.host_resolver.reset(new MockCachingHostResolver());
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
pool_peer.DisableDomainAuthenticationVerification();
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
scoped_ptr<SpdyFrame> host1_req(
spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
scoped_ptr<SpdyFrame> host2_req(
spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
MockWrite spdy_writes[] = {
CreateMockWrite(*host1_req, 1),
CreateMockWrite(*host2_req, 4),
};
scoped_ptr<SpdyFrame> host1_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> host1_resp_body(
spdy_util_.ConstructSpdyBodyFrame(1, true));
scoped_ptr<SpdyFrame> host2_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
scoped_ptr<SpdyFrame> host2_resp_body(
spdy_util_.ConstructSpdyBodyFrame(3, true));
MockRead spdy_reads[] = {
CreateMockRead(*host1_resp, 2),
CreateMockRead(*host1_resp_body, 3),
CreateMockRead(*host2_resp, 5),
CreateMockRead(*host2_resp_body, 6),
MockRead(ASYNC, 0, 7),
};
IPAddressNumber ip;
ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
IPEndPoint peer_addr = IPEndPoint(ip, 443);
MockConnect connect(ASYNC, OK, peer_addr);
OrderedSocketData spdy_data(
connect,
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
TestCompletionCallback callback;
HttpRequestInfo request1;
request1.method = "GET";
request1.url = GURL("https://www.google.com/");
request1.load_flags = 0;
HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
const HttpResponseInfo* response = trans1.GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
EXPECT_EQ("hello!", response_data);
HttpRequestInfo request2;
request2.method = "GET";
request2.url = GURL("https://www.gmail.com/");
request2.load_flags = 0;
HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
response = trans2.GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
EXPECT_TRUE(response->was_fetched_via_spdy);
EXPECT_TRUE(response->was_npn_negotiated);
ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
EXPECT_EQ("hello!", response_data);
}
class OneTimeCachingHostResolver : public net::HostResolver {
public:
explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
: host_port_(host_port) {}
virtual ~OneTimeCachingHostResolver() {}
RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
virtual int Resolve(const RequestInfo& info,
RequestPriority priority,
AddressList* addresses,
const CompletionCallback& callback,
RequestHandle* out_req,
const BoundNetLog& net_log) OVERRIDE {
return host_resolver_.Resolve(
info, priority, addresses, callback, out_req, net_log);
}
virtual int ResolveFromCache(const RequestInfo& info,
AddressList* addresses,
const BoundNetLog& net_log) OVERRIDE {
int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
if (rv == OK && info.host_port_pair().Equals(host_port_))
host_resolver_.GetHostCache()->clear();
return rv;
}
virtual void CancelRequest(RequestHandle req) OVERRIDE {
host_resolver_.CancelRequest(req);
}
MockCachingHostResolver* GetMockHostResolver() {
return &host_resolver_;
}
private:
MockCachingHostResolver host_resolver_;
const HostPortPair host_port_;
};
#if defined(OS_WIN)
#define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
#else
#define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
UseIPConnectionPoolingWithHostCacheExpiration
#endif
WRAPPED_TEST_P(HttpNetworkTransactionTest,
MAYBE_UseIPConnectionPoolingWithHostCacheExpiration) {
#if defined(OS_WIN)
return;
#else
HttpStreamFactory::set_use_alternate_protocols(true);
HttpStreamFactory::SetNextProtos(SpdyNextProtos());
OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
HttpNetworkSession::Params params =
SpdySessionDependencies::CreateSessionParams(&session_deps_);
params.host_resolver = &host_resolver;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
pool_peer.DisableDomainAuthenticationVerification();
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
scoped_ptr<SpdyFrame> host1_req(
spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
scoped_ptr<SpdyFrame> host2_req(
spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
MockWrite spdy_writes[] = {
CreateMockWrite(*host1_req, 1),
CreateMockWrite(*host2_req, 4),
};
scoped_ptr<SpdyFrame> host1_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> host1_resp_body(
spdy_util_.ConstructSpdyBodyFrame(1, true));
scoped_ptr<SpdyFrame> host2_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
scoped_ptr<SpdyFrame> host2_resp_body(
spdy_util_.ConstructSpdyBodyFrame(3, true));
MockRead spdy_reads[] = {
CreateMockRead(*host1_resp, 2),
CreateMockRead(*host1_resp_body, 3),
CreateMockRead(*host2_resp, 5),
CreateMockRead(*host2_resp_body, 6),
MockRead(ASYNC, 0, 7),
};
IPAddressNumber ip;
ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
IPEndPoint peer_addr = IPEndPoint(ip, 443);
MockConnect connect(ASYNC, OK, peer_addr);
OrderedSocketData spdy_data(
connect,
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
TestCompletionCallback callback;
HttpRequestInfo request1;
request1.method = "GET";
request1.url = GURL("https://www.google.com/");
request1.load_flags = 0;
HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
const HttpResponseInfo* response = trans1.GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
std::string response_data;
ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
EXPECT_EQ("hello!", response_data);
HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
AddressList ignored;
rv = host_resolver.Resolve(resolve_info,
DEFAULT_PRIORITY,
&ignored,
callback.callback(),
NULL,
BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
HttpRequestInfo request2;
request2.method = "GET";
request2.url = GURL("https://www.gmail.com/");
request2.load_flags = 0;
HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
response = trans2.GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
EXPECT_TRUE(response->was_fetched_via_spdy);
EXPECT_TRUE(response->was_npn_negotiated);
ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
EXPECT_EQ("hello!", response_data);
#endif
}
#undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
TEST_P(HttpNetworkTransactionTest, ReadPipelineEvictionFallback) {
MockRead data_reads1[] = {
MockRead(SYNCHRONOUS, ERR_PIPELINE_EVICTION),
};
MockRead data_reads2[] = {
MockRead("HTTP/1.0 200 OK\r\n\r\n"),
MockRead("hello world"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), NULL, 0);
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), NULL, 0);
StaticSocketDataProvider* data[] = { &data1, &data2 };
SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
EXPECT_EQ("hello world", out.response_data);
}
TEST_P(HttpNetworkTransactionTest, SendPipelineEvictionFallback) {
MockWrite data_writes1[] = {
MockWrite(SYNCHRONOUS, ERR_PIPELINE_EVICTION),
};
MockWrite data_writes2[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads2[] = {
MockRead("HTTP/1.0 200 OK\r\n\r\n"),
MockRead("hello world"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider data1(NULL, 0,
data_writes1, arraysize(data_writes1));
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
data_writes2, arraysize(data_writes2));
StaticSocketDataProvider* data[] = { &data1, &data2 };
SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
EXPECT_EQ(OK, out.rv);
EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
EXPECT_EQ("hello world", out.response_data);
}
TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
const std::string https_url = "https://www.google.com/";
const std::string http_url = "http://www.google.com:443/";
scoped_ptr<SpdyFrame> req1(
spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
MockWrite writes1[] = {
CreateMockWrite(*req1, 0),
};
scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads1[] = {
CreateMockRead(*resp1, 1),
CreateMockRead(*body1, 2),
MockRead(ASYNC, ERR_IO_PENDING, 3)
};
DelayedSocketData data1(
1, reads1, arraysize(reads1),
writes1, arraysize(writes1));
MockConnect connect_data1(ASYNC, OK);
data1.set_connect_data(connect_data1);
MockWrite writes2[] = {
MockWrite(ASYNC, 4,
"GET / HTTP/1.1\r\n"
"Host: www.google.com:443\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead reads2[] = {
MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
MockRead(ASYNC, 6, "hello"),
MockRead(ASYNC, 7, OK),
};
DelayedSocketData data2(
1, reads2, arraysize(reads2),
writes2, arraysize(writes2));
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
session_deps_.socket_factory->AddSocketDataProvider(&data1);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
HttpRequestInfo request1;
request1.method = "GET";
request1.url = GURL(https_url);
request1.load_flags = 0;
HttpNetworkTransaction trans1(LOWEST, session.get());
TestCompletionCallback callback1;
EXPECT_EQ(ERR_IO_PENDING,
trans1.Start(&request1, callback1.callback(), BoundNetLog()));
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(OK, callback1.WaitForResult());
EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
HttpRequestInfo request2;
request2.method = "GET";
request2.url = GURL(http_url);
request2.load_flags = 0;
HttpNetworkTransaction trans2(MEDIUM, session.get());
TestCompletionCallback callback2;
EXPECT_EQ(ERR_IO_PENDING,
trans2.Start(&request2, callback2.callback(), BoundNetLog()));
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(OK, callback2.WaitForResult());
EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
}
TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
const std::string https_url = "https://www.google.com/";
const std::string http_url = "http://www.google.com:443/";
scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
LOWEST));
scoped_ptr<SpdyFrame> req1(
spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
scoped_ptr<SpdyFrame> wrapped_req1(
spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
const char* const headers[] = {
spdy_util_.GetMethodKey(), "GET",
spdy_util_.GetPathKey(), spdy_util_.is_spdy2() ? http_url.c_str() : "/",
spdy_util_.GetHostKey(), "www.google.com:443",
spdy_util_.GetSchemeKey(), "http",
spdy_util_.GetVersionKey(), "HTTP/1.1"
};
scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyControlFrame(
NULL, 0, false, 3, MEDIUM, SYN_STREAM, CONTROL_FLAG_FIN,
headers, arraysize(headers), 0));
MockWrite writes1[] = {
CreateMockWrite(*connect, 0),
CreateMockWrite(*wrapped_req1, 2),
CreateMockWrite(*req2, 5),
};
scoped_ptr<SpdyFrame> conn_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
scoped_ptr<SpdyFrame> wrapped_resp1(
spdy_util_.ConstructWrappedSpdyFrame(resp1, 1));
scoped_ptr<SpdyFrame> wrapped_body1(
spdy_util_.ConstructWrappedSpdyFrame(body1, 1));
scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
MockRead reads1[] = {
CreateMockRead(*conn_resp, 1),
CreateMockRead(*wrapped_resp1, 3),
CreateMockRead(*wrapped_body1, 4),
CreateMockRead(*resp2, 6),
CreateMockRead(*body2, 7),
MockRead(ASYNC, ERR_IO_PENDING, 8)
};
DeterministicSocketData data1(reads1, arraysize(reads1),
writes1, arraysize(writes1));
MockConnect connect_data1(ASYNC, OK);
data1.set_connect_data(connect_data1);
session_deps_.proxy_service.reset(
ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
CapturingNetLog log;
session_deps_.net_log = &log;
SSLSocketDataProvider ssl1(ASYNC, OK);
ssl1.SetNextProto(GetParam());
session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
SSLSocketDataProvider ssl2(ASYNC, OK);
ssl2.SetNextProto(GetParam());
session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1);
scoped_refptr<HttpNetworkSession> session(
SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
HttpRequestInfo request1;
request1.method = "GET";
request1.url = GURL(https_url);
request1.load_flags = 0;
HttpNetworkTransaction trans1(LOWEST, session.get());
TestCompletionCallback callback1;
EXPECT_EQ(ERR_IO_PENDING,
trans1.Start(&request1, callback1.callback(), BoundNetLog()));
base::MessageLoop::current()->RunUntilIdle();
data1.RunFor(4);
EXPECT_EQ(OK, callback1.WaitForResult());
EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
LoadTimingInfo load_timing_info1;
EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
TestLoadTimingNotReusedWithPac(load_timing_info1,
CONNECT_TIMING_HAS_SSL_TIMES);
HttpRequestInfo request2;
request2.method = "GET";
request2.url = GURL(http_url);
request2.load_flags = 0;
HttpNetworkTransaction trans2(MEDIUM, session.get());
TestCompletionCallback callback2;
EXPECT_EQ(ERR_IO_PENDING,
trans2.Start(&request2, callback2.callback(), BoundNetLog()));
base::MessageLoop::current()->RunUntilIdle();
data1.RunFor(3);
EXPECT_EQ(OK, callback2.WaitForResult());
EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
LoadTimingInfo load_timing_info2;
EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
TestLoadTimingReusedWithPac(load_timing_info2);
EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
}
TEST_P(HttpNetworkTransactionTest, UseSpdySessionForHttpWhenForced) {
HttpStreamFactory::set_force_spdy_always(true);
const std::string https_url = "https://www.google.com/";
const std::string http_url = "http://www.google.com:443/";
scoped_ptr<SpdyFrame> req1(
spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
scoped_ptr<SpdyFrame> req2(
spdy_util_.ConstructSpdyGet(http_url.c_str(), false, 3, MEDIUM));
MockWrite writes[] = {
CreateMockWrite(*req1, 1),
CreateMockWrite(*req2, 4),
};
scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
MockRead reads[] = {
CreateMockRead(*resp1, 2),
CreateMockRead(*body1, 3),
CreateMockRead(*resp2, 5),
CreateMockRead(*body2, 6),
MockRead(ASYNC, ERR_IO_PENDING, 7)
};
OrderedSocketData data(reads, arraysize(reads),
writes, arraysize(writes));
SSLSocketDataProvider ssl(ASYNC, OK);
ssl.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
session_deps_.socket_factory->AddSocketDataProvider(&data);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
HttpRequestInfo request1;
request1.method = "GET";
request1.url = GURL(https_url);
request1.load_flags = 0;
HttpNetworkTransaction trans1(LOWEST, session.get());
TestCompletionCallback callback1;
EXPECT_EQ(ERR_IO_PENDING,
trans1.Start(&request1, callback1.callback(), BoundNetLog()));
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(OK, callback1.WaitForResult());
EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
HttpRequestInfo request2;
request2.method = "GET";
request2.url = GURL(http_url);
request2.load_flags = 0;
HttpNetworkTransaction trans2(MEDIUM, session.get());
TestCompletionCallback callback2;
EXPECT_EQ(ERR_IO_PENDING,
trans2.Start(&request2, callback2.callback(), BoundNetLog()));
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(OK, callback2.WaitForResult());
EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
}
TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
const std::string url1 = "http://www.google.com/";
const std::string url2 = "https://mail.google.com/";
const std::string ip_addr = "1.2.3.4";
scoped_ptr<SpdyHeaderBlock> headers(
spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyControlFrame(
headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
MockWrite writes1[] = {
CreateMockWrite(*req1, 0),
};
scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads1[] = {
CreateMockRead(*resp1, 1),
CreateMockRead(*body1, 2),
MockRead(ASYNC, OK, 3)
};
scoped_ptr<DeterministicSocketData> data1(
new DeterministicSocketData(reads1, arraysize(reads1),
writes1, arraysize(writes1)));
IPAddressNumber ip;
ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
IPEndPoint peer_addr = IPEndPoint(ip, 443);
MockConnect connect_data1(ASYNC, OK, peer_addr);
data1->set_connect_data(connect_data1);
scoped_ptr<SpdyFrame> req2(
spdy_util_.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
MockWrite writes2[] = {
CreateMockWrite(*req2, 0),
};
scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads2[] = {
CreateMockRead(*resp2, 1),
CreateMockRead(*body2, 2),
MockRead(ASYNC, OK, 3)
};
scoped_ptr<DeterministicSocketData> data2(
new DeterministicSocketData(reads2, arraysize(reads2),
writes2, arraysize(writes2)));
MockConnect connect_data2(ASYNC, OK);
data2->set_connect_data(connect_data2);
ProxyConfig proxy_config;
proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
CapturingProxyResolver* capturing_proxy_resolver =
new CapturingProxyResolver();
session_deps_.proxy_service.reset(new ProxyService(
new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
NULL));
base::FilePath certs_dir = GetTestCertsDirectory();
scoped_refptr<X509Certificate> server_cert(
ImportCertFromFile(certs_dir, "ok_cert.pem"));
ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert);
SSLSocketDataProvider ssl1(ASYNC, OK);
ssl1.SetNextProto(GetParam());
ssl1.cert = server_cert;
session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
session_deps_.deterministic_socket_factory->AddSocketDataProvider(
data1.get());
SSLSocketDataProvider ssl2(ASYNC, OK);
ssl2.SetNextProto(GetParam());
session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
session_deps_.deterministic_socket_factory->AddSocketDataProvider(
data2.get());
session_deps_.host_resolver.reset(new MockCachingHostResolver());
session_deps_.host_resolver->rules()->AddRule("mail.google.com", ip_addr);
session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
scoped_refptr<HttpNetworkSession> session(
SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
HttpRequestInfo request1;
request1.method = "GET";
request1.url = GURL(url1);
request1.load_flags = 0;
HttpNetworkTransaction trans1(LOWEST, session.get());
TestCompletionCallback callback1;
ASSERT_EQ(ERR_IO_PENDING,
trans1.Start(&request1, callback1.callback(), BoundNetLog()));
data1->RunFor(3);
ASSERT_TRUE(callback1.have_result());
EXPECT_EQ(OK, callback1.WaitForResult());
EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
HttpRequestInfo request2;
request2.method = "GET";
request2.url = GURL(url2);
request2.load_flags = 0;
HttpNetworkTransaction trans2(MEDIUM, session.get());
TestCompletionCallback callback2;
EXPECT_EQ(ERR_IO_PENDING,
trans2.Start(&request2, callback2.callback(), BoundNetLog()));
base::MessageLoop::current()->RunUntilIdle();
data2->RunFor(3);
ASSERT_TRUE(callback2.have_result());
EXPECT_EQ(OK, callback2.WaitForResult());
EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
}
TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
const std::string https_url = "https://www.google.com/";
MockRead reads1[] = {
MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
};
scoped_ptr<DeterministicSocketData> data1(
new DeterministicSocketData(reads1, arraysize(reads1), NULL, 0));
data1->SetStop(1);
scoped_ptr<SpdyFrame> req2(
spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
MockWrite writes2[] = {
CreateMockWrite(*req2, 0),
};
scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads2[] = {
CreateMockRead(*resp2, 1),
CreateMockRead(*body2, 2),
MockRead(ASYNC, OK, 3)
};
scoped_ptr<DeterministicSocketData> data2(
new DeterministicSocketData(reads2, arraysize(reads2),
writes2, arraysize(writes2)));
SSLSocketDataProvider ssl1(ASYNC, OK);
ssl1.SetNextProto(GetParam());
session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
session_deps_.deterministic_socket_factory->AddSocketDataProvider(
data1.get());
SSLSocketDataProvider ssl2(ASYNC, OK);
ssl2.SetNextProto(GetParam());
session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
session_deps_.deterministic_socket_factory->AddSocketDataProvider(
data2.get());
scoped_refptr<HttpNetworkSession> session(
SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
HttpRequestInfo request1;
request1.method = "GET";
request1.url = GURL(https_url);
request1.load_flags = 0;
HttpNetworkTransaction trans1(MEDIUM, session.get());
TestCompletionCallback callback1;
EXPECT_EQ(ERR_IO_PENDING,
trans1.Start(&request1, callback1.callback(), BoundNetLog()));
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
HttpRequestInfo request2;
request2.method = "GET";
request2.url = GURL(https_url);
request2.load_flags = 0;
HttpNetworkTransaction trans2(MEDIUM, session.get());
TestCompletionCallback callback2;
EXPECT_EQ(ERR_IO_PENDING,
trans2.Start(&request2, callback2.callback(), BoundNetLog()));
base::MessageLoop::current()->RunUntilIdle();
data2->RunFor(3);
ASSERT_TRUE(callback2.have_result());
EXPECT_EQ(OK, callback2.WaitForResult());
EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
}
TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
HttpStreamFactory::SetNextProtos(SpdyNextProtos());
ClientSocketPoolManager::set_max_sockets_per_group(
HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
ClientSocketPoolManager::set_max_sockets_per_pool(
HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
SSLSocketDataProvider ssl1(ASYNC, OK);
ssl1.SetNextProto(GetParam());
SSLSocketDataProvider ssl2(ASYNC, OK);
ssl2.SetNextProto(GetParam());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
"https://www.a.com", false, 1, DEFAULT_PRIORITY));
MockWrite spdy1_writes[] = {
CreateMockWrite(*host1_req, 1),
};
scoped_ptr<SpdyFrame> host1_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> host1_resp_body(
spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead spdy1_reads[] = {
CreateMockRead(*host1_resp, 2),
CreateMockRead(*host1_resp_body, 3),
MockRead(ASYNC, ERR_IO_PENDING, 4),
};
scoped_ptr<OrderedSocketData> spdy1_data(
new OrderedSocketData(
spdy1_reads, arraysize(spdy1_reads),
spdy1_writes, arraysize(spdy1_writes)));
session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
scoped_ptr<SpdyFrame> host2_req(spdy_util_.ConstructSpdyGet(
"https://www.b.com", false, 1, DEFAULT_PRIORITY));
MockWrite spdy2_writes[] = {
CreateMockWrite(*host2_req, 1),
};
scoped_ptr<SpdyFrame> host2_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyFrame> host2_resp_body(
spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead spdy2_reads[] = {
CreateMockRead(*host2_resp, 2),
CreateMockRead(*host2_resp_body, 3),
MockRead(ASYNC, ERR_IO_PENDING, 4),
};
scoped_ptr<OrderedSocketData> spdy2_data(
new OrderedSocketData(
spdy2_reads, arraysize(spdy2_reads),
spdy2_writes, arraysize(spdy2_writes)));
session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
MockWrite http_write[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.a.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead http_read[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
MockRead("Content-Length: 6\r\n\r\n"),
MockRead("hello!"),
};
StaticSocketDataProvider http_data(http_read, arraysize(http_read),
http_write, arraysize(http_write));
session_deps_.socket_factory->AddSocketDataProvider(&http_data);
HostPortPair host_port_pair_a("www.a.com", 443);
SpdySessionKey spdy_session_key_a(
host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
EXPECT_FALSE(
HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
TestCompletionCallback callback;
HttpRequestInfo request1;
request1.method = "GET";
request1.url = GURL("https://www.a.com/");
request1.load_flags = 0;
scoped_ptr<HttpNetworkTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
EXPECT_TRUE(response->was_fetched_via_spdy);
EXPECT_TRUE(response->was_npn_negotiated);
std::string response_data;
ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
EXPECT_EQ("hello!", response_data);
trans.reset();
EXPECT_TRUE(
HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
HostPortPair host_port_pair_b("www.b.com", 443);
SpdySessionKey spdy_session_key_b(
host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
EXPECT_FALSE(
HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
HttpRequestInfo request2;
request2.method = "GET";
request2.url = GURL("https://www.b.com/");
request2.load_flags = 0;
trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
rv = trans->Start(&request2, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
EXPECT_TRUE(response->was_fetched_via_spdy);
EXPECT_TRUE(response->was_npn_negotiated);
ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
EXPECT_EQ("hello!", response_data);
EXPECT_FALSE(
HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
EXPECT_TRUE(
HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
HostPortPair host_port_pair_a1("www.a.com", 80);
SpdySessionKey spdy_session_key_a1(
host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
EXPECT_FALSE(
HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
HttpRequestInfo request3;
request3.method = "GET";
request3.url = GURL("http://www.a.com/");
request3.load_flags = 0;
trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
rv = trans->Start(&request3, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
response = trans->GetResponseInfo();
ASSERT_TRUE(response != NULL);
ASSERT_TRUE(response->headers.get() != NULL);
EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
EXPECT_FALSE(response->was_fetched_via_spdy);
EXPECT_FALSE(response->was_npn_negotiated);
ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
EXPECT_EQ("hello!", response_data);
EXPECT_FALSE(
HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
EXPECT_FALSE(
HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
}
TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
StaticSocketDataProvider data;
data.set_connect_data(mock_connect);
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
EXPECT_EQ(NULL, trans->GetResponseInfo());
HttpRequestHeaders request_headers;
trans->GetFullRequestHeaders(&request_headers);
}
TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
StaticSocketDataProvider data;
data.set_connect_data(mock_connect);
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
EXPECT_EQ(NULL, trans->GetResponseInfo());
HttpRequestHeaders request_headers;
trans->GetFullRequestHeaders(&request_headers);
}
TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
};
MockRead data_reads[] = {
MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(ERR_CONNECTION_RESET, rv);
EXPECT_EQ(NULL, trans->GetResponseInfo());
HttpRequestHeaders request_headers;
EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
EXPECT_TRUE(request_headers.HasHeader("Host"));
}
TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite(ASYNC, ERR_CONNECTION_RESET),
};
MockRead data_reads[] = {
MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(ERR_CONNECTION_RESET, rv);
EXPECT_EQ(NULL, trans->GetResponseInfo());
HttpRequestHeaders request_headers;
EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
EXPECT_TRUE(request_headers.HasHeader("Host"));
}
TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(ERR_CONNECTION_RESET, rv);
EXPECT_EQ(NULL, trans->GetResponseInfo());
HttpRequestHeaders request_headers;
EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
EXPECT_TRUE(request_headers.HasHeader("Host"));
}
TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead(ASYNC, ERR_CONNECTION_RESET),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(ERR_CONNECTION_RESET, rv);
EXPECT_EQ(NULL, trans->GetResponseInfo());
HttpRequestHeaders request_headers;
EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
EXPECT_TRUE(request_headers.HasHeader("Host"));
}
TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
request.extra_headers.SetHeader("X-Foo", "bar");
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n"
"X-Foo: bar\r\n\r\n"),
};
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"
"Content-Length: 5\r\n\r\n"
"hello"),
MockRead(ASYNC, ERR_UNEXPECTED),
};
StaticSocketDataProvider data(data_reads, arraysize(data_reads),
data_writes, arraysize(data_writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
HttpRequestHeaders request_headers;
EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
std::string foo;
EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
EXPECT_EQ("bar", foo);
}
namespace {
class FakeStream : public HttpStreamBase,
public base::SupportsWeakPtr<FakeStream> {
public:
explicit FakeStream(RequestPriority priority) : priority_(priority) {}
virtual ~FakeStream() {}
RequestPriority priority() const { return priority_; }
virtual int InitializeStream(const HttpRequestInfo* request_info,
RequestPriority priority,
const BoundNetLog& net_log,
const CompletionCallback& callback) OVERRIDE {
return ERR_IO_PENDING;
}
virtual int SendRequest(const HttpRequestHeaders& request_headers,
HttpResponseInfo* response,
const CompletionCallback& callback) OVERRIDE {
ADD_FAILURE();
return ERR_UNEXPECTED;
}
virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE {
ADD_FAILURE();
return ERR_UNEXPECTED;
}
virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE {
ADD_FAILURE();
return NULL;
}
virtual int ReadResponseBody(IOBuffer* buf, int buf_len,
const CompletionCallback& callback) OVERRIDE {
ADD_FAILURE();
return ERR_UNEXPECTED;
}
virtual void Close(bool not_reusable) OVERRIDE {}
virtual bool IsResponseBodyComplete() const OVERRIDE {
ADD_FAILURE();
return false;
}
virtual bool CanFindEndOfResponse() const OVERRIDE {
return false;
}
virtual bool IsConnectionReused() const OVERRIDE {
ADD_FAILURE();
return false;
}
virtual void SetConnectionReused() OVERRIDE {
ADD_FAILURE();
}
virtual bool IsConnectionReusable() const OVERRIDE {
ADD_FAILURE();
return false;
}
virtual int64 GetTotalReceivedBytes() const OVERRIDE {
ADD_FAILURE();
return 0;
}
virtual bool GetLoadTimingInfo(
LoadTimingInfo* load_timing_info) const OVERRIDE {
ADD_FAILURE();
return false;
}
virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE {
ADD_FAILURE();
}
virtual void GetSSLCertRequestInfo(
SSLCertRequestInfo* cert_request_info) OVERRIDE {
ADD_FAILURE();
}
virtual bool IsSpdyHttpStream() const OVERRIDE {
ADD_FAILURE();
return false;
}
virtual void Drain(HttpNetworkSession* session) OVERRIDE {
ADD_FAILURE();
}
virtual void SetPriority(RequestPriority priority) OVERRIDE {
priority_ = priority;
}
private:
RequestPriority priority_;
DISALLOW_COPY_AND_ASSIGN(FakeStream);
};
class FakeStreamRequest : public HttpStreamRequest,
public base::SupportsWeakPtr<FakeStreamRequest> {
public:
FakeStreamRequest(RequestPriority priority,
HttpStreamRequest::Delegate* delegate)
: priority_(priority),
delegate_(delegate),
websocket_stream_create_helper_(NULL) {}
FakeStreamRequest(RequestPriority priority,
HttpStreamRequest::Delegate* delegate,
WebSocketHandshakeStreamBase::CreateHelper* create_helper)
: priority_(priority),
delegate_(delegate),
websocket_stream_create_helper_(create_helper) {}
virtual ~FakeStreamRequest() {}
RequestPriority priority() const { return priority_; }
const WebSocketHandshakeStreamBase::CreateHelper*
websocket_stream_create_helper() const {
return websocket_stream_create_helper_;
}
base::WeakPtr<FakeStream> FinishStreamRequest() {
FakeStream* fake_stream = new FakeStream(priority_);
base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
return weak_stream;
}
virtual int RestartTunnelWithProxyAuth(
const AuthCredentials& credentials) OVERRIDE {
ADD_FAILURE();
return ERR_UNEXPECTED;
}
virtual LoadState GetLoadState() const OVERRIDE {
ADD_FAILURE();
return LoadState();
}
virtual void SetPriority(RequestPriority priority) OVERRIDE {
priority_ = priority;
}
virtual bool was_npn_negotiated() const OVERRIDE {
return false;
}
virtual NextProto protocol_negotiated() const OVERRIDE {
return kProtoUnknown;
}
virtual bool using_spdy() const OVERRIDE {
return false;
}
private:
RequestPriority priority_;
HttpStreamRequest::Delegate* const delegate_;
WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
};
class FakeStreamFactory : public HttpStreamFactory {
public:
FakeStreamFactory() {}
virtual ~FakeStreamFactory() {}
base::WeakPtr<FakeStreamRequest> last_stream_request() {
return last_stream_request_;
}
virtual HttpStreamRequest* RequestStream(
const HttpRequestInfo& info,
RequestPriority priority,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
HttpStreamRequest::Delegate* delegate,
const BoundNetLog& net_log) OVERRIDE {
FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
last_stream_request_ = fake_request->AsWeakPtr();
return fake_request;
}
virtual HttpStreamRequest* RequestWebSocketHandshakeStream(
const HttpRequestInfo& info,
RequestPriority priority,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
HttpStreamRequest::Delegate* delegate,
WebSocketHandshakeStreamBase::CreateHelper* create_helper,
const BoundNetLog& net_log) OVERRIDE {
FakeStreamRequest* fake_request =
new FakeStreamRequest(priority, delegate, create_helper);
last_stream_request_ = fake_request->AsWeakPtr();
return fake_request;
}
virtual void PreconnectStreams(int num_streams,
const HttpRequestInfo& info,
RequestPriority priority,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config) OVERRIDE {
ADD_FAILURE();
}
virtual base::Value* PipelineInfoToValue() const OVERRIDE {
ADD_FAILURE();
return NULL;
}
virtual const HostMappingRules* GetHostMappingRules() const OVERRIDE {
ADD_FAILURE();
return NULL;
}
private:
base::WeakPtr<FakeStreamRequest> last_stream_request_;
DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
};
class FakeWebSocketStreamCreateHelper :
public WebSocketHandshakeStreamBase::CreateHelper {
public:
virtual WebSocketHandshakeStreamBase* CreateBasicStream(
scoped_ptr<ClientSocketHandle> connection,
bool using_proxy) OVERRIDE {
NOTREACHED();
return NULL;
}
virtual WebSocketHandshakeStreamBase* CreateSpdyStream(
const base::WeakPtr<SpdySession>& session,
bool use_relative_url) OVERRIDE {
NOTREACHED();
return NULL;
};
virtual ~FakeWebSocketStreamCreateHelper() {}
virtual scoped_ptr<WebSocketStream> Upgrade() {
NOTREACHED();
return scoped_ptr<WebSocketStream>();
}
};
}
TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
HttpNetworkSessionPeer peer(session);
FakeStreamFactory* fake_factory = new FakeStreamFactory();
peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
HttpNetworkTransaction trans(LOW, session);
ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
HttpRequestInfo request;
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
trans.Start(&request, callback.callback(), BoundNetLog()));
base::WeakPtr<FakeStreamRequest> fake_request =
fake_factory->last_stream_request();
ASSERT_TRUE(fake_request != NULL);
EXPECT_EQ(LOW, fake_request->priority());
}
TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
HttpNetworkSessionPeer peer(session);
FakeStreamFactory* fake_factory = new FakeStreamFactory();
peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
HttpNetworkTransaction trans(LOW, session);
HttpRequestInfo request;
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
trans.Start(&request, callback.callback(), BoundNetLog()));
base::WeakPtr<FakeStreamRequest> fake_request =
fake_factory->last_stream_request();
ASSERT_TRUE(fake_request != NULL);
EXPECT_EQ(LOW, fake_request->priority());
trans.SetPriority(LOWEST);
ASSERT_TRUE(fake_request != NULL);
EXPECT_EQ(LOWEST, fake_request->priority());
}
TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
HttpNetworkSessionPeer peer(session);
FakeStreamFactory* fake_factory = new FakeStreamFactory();
peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
HttpNetworkTransaction trans(LOW, session);
HttpRequestInfo request;
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
trans.Start(&request, callback.callback(), BoundNetLog()));
base::WeakPtr<FakeStreamRequest> fake_request =
fake_factory->last_stream_request();
ASSERT_TRUE(fake_request != NULL);
base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
ASSERT_TRUE(fake_stream != NULL);
EXPECT_EQ(LOW, fake_stream->priority());
trans.SetPriority(LOWEST);
EXPECT_EQ(LOWEST, fake_stream->priority());
}
TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
std::string test_cases[] = {"ws://www.google.com/", "wss://www.google.com/"};
for (size_t i = 0; i < arraysize(test_cases); ++i) {
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
HttpNetworkSessionPeer peer(session);
FakeStreamFactory* fake_factory = new FakeStreamFactory();
FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
peer.SetHttpStreamFactoryForWebSocket(
scoped_ptr<HttpStreamFactory>(fake_factory));
HttpNetworkTransaction trans(LOW, session);
trans.SetWebSocketHandshakeStreamCreateHelper(
&websocket_stream_create_helper);
HttpRequestInfo request;
TestCompletionCallback callback;
request.method = "GET";
request.url = GURL(test_cases[i]);
EXPECT_EQ(ERR_IO_PENDING,
trans.Start(&request, callback.callback(), BoundNetLog()));
base::WeakPtr<FakeStreamRequest> fake_request =
fake_factory->last_stream_request();
ASSERT_TRUE(fake_request != NULL);
EXPECT_EQ(&websocket_stream_create_helper,
fake_request->websocket_stream_create_helper());
}
}
TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
ClientSocketPoolManager::set_max_sockets_per_group(
HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
ClientSocketPoolManager::set_max_sockets_per_pool(
HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
HttpRequestInfo ssl_request;
ssl_request.method = "GET";
ssl_request.url = GURL("https://www.google.com/");
MockWrite ssl_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead ssl_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Length: 11\r\n\r\n"),
MockRead("hello world"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
ssl_writes, arraysize(ssl_writes));
session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
SSLSocketDataProvider ssl(ASYNC, OK);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
HttpRequestInfo http_request;
http_request.method = "GET";
http_request.url = GURL("http://www.google.com/");
MockWrite http_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead http_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Length: 7\r\n\r\n"),
MockRead("falafel"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
http_writes, arraysize(http_writes));
session_deps_.socket_factory->AddSocketDataProvider(&http_data);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
TestCompletionCallback ssl_callback;
scoped_ptr<HttpTransaction> ssl_trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
ASSERT_EQ(ERR_IO_PENDING,
ssl_trans->Start(&ssl_request, ssl_callback.callback(),
BoundNetLog()));
TestCompletionCallback http_callback;
scoped_ptr<HttpTransaction> http_trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
ASSERT_EQ(ERR_IO_PENDING,
http_trans->Start(&http_request, http_callback.callback(),
BoundNetLog()));
EXPECT_TRUE(IsTransportSocketPoolStalled(session));
ASSERT_EQ(OK, ssl_callback.WaitForResult());
std::string response_data;
ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
EXPECT_EQ("hello world", response_data);
EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session));
ASSERT_FALSE(IsTransportSocketPoolStalled(session));
ASSERT_EQ(OK, http_callback.WaitForResult());
ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
EXPECT_EQ("falafel", response_data);
EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
}
TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
ClientSocketPoolManager::set_max_sockets_per_group(
HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
ClientSocketPoolManager::set_max_sockets_per_pool(
HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
HttpRequestInfo ssl_request;
ssl_request.method = "GET";
ssl_request.url = GURL("https://www.foopy.com/");
StaticSocketDataProvider ssl_data;
session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
SSLSocketDataProvider ssl(ASYNC, OK);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
HttpRequestInfo http_request;
http_request.method = "GET";
http_request.url = GURL("http://www.google.com/");
MockWrite http_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: keep-alive\r\n\r\n"),
};
MockRead http_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Content-Length: 7\r\n\r\n"),
MockRead("falafel"),
MockRead(SYNCHRONOUS, OK),
};
StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
http_writes, arraysize(http_writes));
session_deps_.socket_factory->AddSocketDataProvider(&http_data);
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
net::HttpStreamFactory* http_stream_factory = session->http_stream_factory();
net::SSLConfig ssl_config;
session->ssl_config_service()->GetSSLConfig(&ssl_config);
http_stream_factory->PreconnectStreams(1, ssl_request, DEFAULT_PRIORITY,
ssl_config, ssl_config);
EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session));
TestCompletionCallback http_callback;
scoped_ptr<HttpTransaction> http_trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
ASSERT_EQ(ERR_IO_PENDING,
http_trans->Start(&http_request, http_callback.callback(),
BoundNetLog()));
EXPECT_TRUE(IsTransportSocketPoolStalled(session));
ASSERT_EQ(OK, http_callback.WaitForResult());
std::string response_data;
ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
EXPECT_EQ("falafel", response_data);
EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
}
}