summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authoreustas@chromium.org <eustas@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-24 15:18:19 +0000
committereustas@chromium.org <eustas@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-24 15:18:19 +0000
commitb8015c43fdc2ec814384955288c3771e10b54f17 (patch)
treef1a417a2940d40de9d5fff505b116006541b0741 /net
parent88a907c0bcc93efb850785941986eab829edc654 (diff)
downloadchromium_src-b8015c43fdc2ec814384955288c3771e10b54f17.zip
chromium_src-b8015c43fdc2ec814384955288c3771e10b54f17.tar.gz
chromium_src-b8015c43fdc2ec814384955288c3771e10b54f17.tar.bz2
Implement GetTotalReceivedBytes for http transaction.
BUG=111052 Review URL: https://codereview.chromium.org/99723004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@242433 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/http/http_basic_stream.cc4
-rw-r--r--net/http/http_cache_transaction.cc9
-rw-r--r--net/http/http_cache_transaction.h3
-rw-r--r--net/http/http_cache_unittest.cc112
-rw-r--r--net/http/http_network_transaction.cc20
-rw-r--r--net/http/http_network_transaction.h6
-rw-r--r--net/http/http_network_transaction_unittest.cc52
-rw-r--r--net/http/http_pipelined_connection_impl.cc5
-rw-r--r--net/http/http_transaction.h3
-rw-r--r--net/http/http_transaction_unittest.cc6
-rw-r--r--net/http/http_transaction_unittest.h3
11 files changed, 212 insertions, 11 deletions
diff --git a/net/http/http_basic_stream.cc b/net/http/http_basic_stream.cc
index 87f6469..ee1f46f 100644
--- a/net/http/http_basic_stream.cc
+++ b/net/http/http_basic_stream.cc
@@ -86,7 +86,9 @@ bool HttpBasicStream::IsConnectionReusable() const {
}
int64 HttpBasicStream::GetTotalReceivedBytes() const {
- return parser()->received_bytes();
+ if (parser())
+ return parser()->received_bytes();
+ return 0;
}
bool HttpBasicStream::GetLoadTimingInfo(
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index 88fb53a..95fd4f1 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -214,6 +214,7 @@ HttpCache::Transaction::Transaction(
weak_factory_.GetWeakPtr())),
transaction_pattern_(PATTERN_UNDEFINED),
transaction_delegate_(transaction_delegate),
+ total_received_bytes_(0),
websocket_handshake_stream_base_create_helper_(NULL) {
COMPILE_ASSERT(HttpCache::Transaction::kNumValidationHeaders ==
arraysize(kValidationHeaders),
@@ -465,6 +466,13 @@ bool HttpCache::Transaction::GetFullRequestHeaders(
return false;
}
+int64 HttpCache::Transaction::GetTotalReceivedBytes() const {
+ int64 total_received_bytes = total_received_bytes_;
+ if (network_trans_)
+ total_received_bytes += network_trans_->GetTotalReceivedBytes();
+ return total_received_bytes;
+}
+
void HttpCache::Transaction::DoneReading() {
if (cache_.get() && entry_) {
DCHECK_NE(mode_, UPDATE);
@@ -2387,6 +2395,7 @@ void HttpCache::Transaction::ResetNetworkTransaction() {
LoadTimingInfo load_timing;
if (network_trans_->GetLoadTimingInfo(&load_timing))
old_network_trans_load_timing_.reset(new LoadTimingInfo(load_timing));
+ total_received_bytes_ += network_trans_->GetTotalReceivedBytes();
network_trans_.reset();
}
diff --git a/net/http/http_cache_transaction.h b/net/http/http_cache_transaction.h
index 90c4db5..14c6ad6 100644
--- a/net/http/http_cache_transaction.h
+++ b/net/http/http_cache_transaction.h
@@ -123,6 +123,7 @@ class HttpCache::Transaction : public HttpTransaction {
virtual void StopCaching() OVERRIDE;
virtual bool GetFullRequestHeaders(
HttpRequestHeaders* headers) const OVERRIDE;
+ virtual int64 GetTotalReceivedBytes() const OVERRIDE;
virtual void DoneReading() OVERRIDE;
virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE;
virtual LoadState GetLoadState() const OVERRIDE;
@@ -431,6 +432,8 @@ class HttpCache::Transaction : public HttpTransaction {
HttpTransactionDelegate* transaction_delegate_;
+ int64 total_received_bytes_;
+
// Load timing information for the last network request, if any. Set in the
// 304 and 206 response cases, as the network transaction may be destroyed
// before the caller requests load timing information.
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc
index aa6056a..1c42ba2 100644
--- a/net/http/http_cache_unittest.cc
+++ b/net/http/http_cache_unittest.cc
@@ -182,7 +182,8 @@ void RunTransactionTestWithRequestAndDelegateAndGetTiming(
int num_cache_delegate_actions,
int num_network_delegate_actions,
const net::BoundNetLog& net_log,
- net::LoadTimingInfo* load_timing_info) {
+ net::LoadTimingInfo* load_timing_info,
+ int64* received_bytes) {
net::TestCompletionCallback callback;
// write to the cache
@@ -223,6 +224,9 @@ void RunTransactionTestWithRequestAndDelegateAndGetTiming(
}
ReadAndVerifyTransaction(trans.get(), trans_info);
+
+ if (received_bytes)
+ *received_bytes = trans->GetTotalReceivedBytes();
}
void RunTransactionTestWithRequestAndDelegate(
@@ -234,7 +238,7 @@ void RunTransactionTestWithRequestAndDelegate(
int num_network_delegate_actions) {
RunTransactionTestWithRequestAndDelegateAndGetTiming(
cache, trans_info, request, response_info, num_cache_delegate_actions,
- num_network_delegate_actions, net::BoundNetLog(), NULL);
+ num_network_delegate_actions, net::BoundNetLog(), NULL, NULL);
}
void RunTransactionTestWithRequest(net::HttpCache* cache,
@@ -254,7 +258,7 @@ void RunTransactionTestAndGetTiming(
RunTransactionTestWithRequestAndDelegateAndGetTiming(
cache, trans_info, MockHttpRequest(trans_info), NULL,
kNoDelegateTransactionCheck, kNoDelegateTransactionCheck, log,
- load_timing_info);
+ load_timing_info, NULL);
}
void RunTransactionTestWithDelegate(net::HttpCache* cache,
@@ -268,7 +272,8 @@ void RunTransactionTestWithDelegate(net::HttpCache* cache,
void RunTransactionTest(net::HttpCache* cache,
const MockTransaction& trans_info) {
- RunTransactionTestAndGetTiming(cache, trans_info, net::BoundNetLog(), NULL);
+ RunTransactionTestAndGetTiming(
+ cache, trans_info, net::BoundNetLog(), NULL);
}
void RunTransactionTestWithResponseInfo(net::HttpCache* cache,
@@ -287,7 +292,7 @@ void RunTransactionTestWithResponseInfoAndGetTiming(
RunTransactionTestWithRequestAndDelegateAndGetTiming(
cache, trans_info, MockHttpRequest(trans_info), response,
kNoDelegateTransactionCheck, kNoDelegateTransactionCheck, log,
- load_timing_info);
+ load_timing_info, NULL);
}
void RunTransactionTestWithResponse(net::HttpCache* cache,
@@ -308,7 +313,7 @@ void RunTransactionTestWithResponseAndGetTiming(
RunTransactionTestWithRequestAndDelegateAndGetTiming(
cache, trans_info, MockHttpRequest(trans_info), &response,
kNoDelegateTransactionCheck, kNoDelegateTransactionCheck,
- log, load_timing_info);
+ log, load_timing_info, NULL);
response.headers->GetNormalizedHeaders(response_headers);
}
@@ -6390,3 +6395,98 @@ TEST(HttpCache, SetPriorityNewTransaction) {
RemoveMockTransaction(&kRangeGET_TransactionOK);
}
+
+int64 RunTransactionAndGetReceivedBytes(
+ MockHttpCache& cache,
+ const MockTransaction& trans_info) {
+ int64 received_bytes = -1;
+ RunTransactionTestWithRequestAndDelegateAndGetTiming(
+ cache.http_cache(), trans_info, MockHttpRequest(trans_info), NULL,
+ kNoDelegateTransactionCheck, kNoDelegateTransactionCheck,
+ net::BoundNetLog(), NULL, &received_bytes);
+ return received_bytes;
+}
+
+int64 TransactionSize(MockTransaction& transaction) {
+ return strlen(transaction.status) + strlen(transaction.response_headers) +
+ strlen(transaction.data);
+}
+
+TEST(HttpCache, ReceivedBytesCacheMissAndThenHit) {
+ MockHttpCache cache;
+
+ MockTransaction transaction(kSimpleGET_Transaction);
+ int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
+ EXPECT_EQ(TransactionSize(transaction), received_bytes);
+
+ received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
+ EXPECT_EQ(0, received_bytes);
+}
+
+TEST(HttpCache, ReceivedBytesConditionalRequest304) {
+ MockHttpCache cache;
+
+ ScopedMockTransaction transaction(kETagGET_Transaction);
+ int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
+ EXPECT_EQ(TransactionSize(transaction), received_bytes);
+
+ transaction.load_flags = net::LOAD_VALIDATE_CACHE;
+ transaction.handler = ETagGet_ConditionalRequest_Handler;
+ received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
+ EXPECT_EQ(TransactionSize(transaction), received_bytes);
+}
+
+TEST(HttpCache, ReceivedBytesConditionalRequest200) {
+ MockHttpCache cache;
+
+ MockTransaction transaction(kTypicalGET_Transaction);
+ transaction.request_headers = "Foo: bar\r\n";
+ transaction.response_headers =
+ "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
+ "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
+ "Etag: \"foopy\"\n"
+ "Cache-Control: max-age=0\n"
+ "Vary: Foo\n";
+ AddMockTransaction(&transaction);
+ int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
+ EXPECT_EQ(TransactionSize(transaction), received_bytes);
+
+ RevalidationServer server;
+ transaction.handler = server.Handler;
+ transaction.request_headers = "Foo: none\r\n";
+ received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
+ EXPECT_EQ(TransactionSize(transaction), received_bytes);
+
+ RemoveMockTransaction(&transaction);
+}
+
+TEST(HttpCache, ReceivedBytesRange) {
+ MockHttpCache cache;
+ AddMockTransaction(&kRangeGET_TransactionOK);
+ MockTransaction transaction(kRangeGET_TransactionOK);
+
+ // Read bytes 40-49 from the network.
+ int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
+ int64 range_response_size = TransactionSize(transaction);
+ EXPECT_EQ(range_response_size, received_bytes);
+
+ // Read bytes 40-49 from the cache.
+ received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
+ EXPECT_EQ(0, received_bytes);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Read bytes 30-39 from the network.
+ transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
+ transaction.data = "rg: 30-39 ";
+ received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
+ EXPECT_EQ(range_response_size, received_bytes);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Read bytes 20-29 and 50-59 from the network, bytes 30-49 from the cache.
+ transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
+ transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
+ received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
+ EXPECT_EQ(range_response_size * 2, received_bytes);
+
+ RemoveMockTransaction(&kRangeGET_TransactionOK);
+}
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index d956fb3..322e2e1 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -135,6 +135,7 @@ HttpNetworkTransaction::HttpNetworkTransaction(RequestPriority priority,
fallback_error_code_(ERR_SSL_INAPPROPRIATE_FALLBACK),
request_headers_(),
read_buf_len_(0),
+ total_received_bytes_(0),
next_state_(STATE_NONE),
establishing_tunnel_(false),
websocket_handshake_stream_base_create_helper_(NULL) {
@@ -306,6 +307,7 @@ void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) {
DCHECK(!stream_request_.get());
if (stream_.get()) {
+ total_received_bytes_ += stream_->GetTotalReceivedBytes();
HttpStream* new_stream = NULL;
if (keep_alive && stream_->IsConnectionReusable()) {
// We should call connection_->set_idle_time(), but this doesn't occur
@@ -322,6 +324,8 @@ void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) {
stream_->Close(true);
next_state_ = STATE_CREATE_STREAM;
} else {
+ // Renewed streams shouldn't carry over received bytes.
+ DCHECK_EQ(0, new_stream->GetTotalReceivedBytes());
next_state_ = STATE_INIT_STREAM;
}
stream_.reset(new_stream);
@@ -382,6 +386,13 @@ bool HttpNetworkTransaction::GetFullRequestHeaders(
return true;
}
+int64 HttpNetworkTransaction::GetTotalReceivedBytes() const {
+ int64 total_received_bytes = total_received_bytes_;
+ if (stream_)
+ total_received_bytes += stream_->GetTotalReceivedBytes();
+ return total_received_bytes;
+}
+
const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const {
return ((headers_valid_ && response_.headers.get()) ||
response_.ssl_info.cert.get() || response_.cert_request_info.get())
@@ -448,6 +459,8 @@ void HttpNetworkTransaction::OnStreamReady(const SSLConfig& used_ssl_config,
DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
DCHECK(stream_request_.get());
+ if (stream_)
+ total_received_bytes_ += stream_->GetTotalReceivedBytes();
stream_.reset(stream);
server_ssl_config_ = used_ssl_config;
proxy_info_ = used_proxy_info;
@@ -541,6 +554,8 @@ void HttpNetworkTransaction::OnHttpsProxyTunnelResponse(
response_ = response_info;
server_ssl_config_ = used_ssl_config;
proxy_info_ = used_proxy_info;
+ if (stream_)
+ total_received_bytes_ += stream_->GetTotalReceivedBytes();
stream_.reset(stream);
stream_request_.reset(); // we're done with the stream request
OnIOComplete(ERR_HTTPS_PROXY_TUNNEL_RESPONSE);
@@ -730,6 +745,8 @@ int HttpNetworkTransaction::DoInitStreamComplete(int result) {
result = HandleIOError(result);
// The stream initialization failed, so this stream will never be useful.
+ if (stream_)
+ total_received_bytes_ += stream_->GetTotalReceivedBytes();
stream_.reset();
}
@@ -1248,6 +1265,7 @@ int HttpNetworkTransaction::HandleCertificateRequest(int error) {
// Since we already have a stream, we're being called as part of SSL
// renegotiation.
DCHECK(!stream_request_.get());
+ total_received_bytes_ += stream_->GetTotalReceivedBytes();
stream_->Close(true);
stream_.reset();
}
@@ -1425,6 +1443,8 @@ int HttpNetworkTransaction::HandleIOError(int error) {
void HttpNetworkTransaction::ResetStateForRestart() {
ResetStateForAuthRestart();
+ if (stream_)
+ total_received_bytes_ += stream_->GetTotalReceivedBytes();
stream_.reset();
}
diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h
index 3ae1725..10436b6 100644
--- a/net/http/http_network_transaction.h
+++ b/net/http/http_network_transaction.h
@@ -62,6 +62,7 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
virtual void StopCaching() OVERRIDE {}
virtual bool GetFullRequestHeaders(
HttpRequestHeaders* headers) const OVERRIDE;
+ virtual int64 GetTotalReceivedBytes() const OVERRIDE;
virtual void DoneReading() OVERRIDE {}
virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE;
virtual LoadState GetLoadState() const OVERRIDE;
@@ -254,6 +255,8 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
// Debug helper.
static std::string DescribeState(State state);
+ void SetStream(HttpStreamBase* stream);
+
scoped_refptr<HttpAuthController>
auth_controllers_[HttpAuth::AUTH_NUM_TARGETS];
@@ -306,6 +309,9 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
scoped_refptr<IOBuffer> read_buf_;
int read_buf_len_;
+ // Total number of bytes received on streams for this transaction.
+ int64 total_received_bytes_;
+
// The time the Start method was called.
base::Time start_time_;
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 6df20ac..a0d622a 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -244,6 +244,7 @@ class HttpNetworkTransactionTest
int rv;
std::string status_line;
std::string response_data;
+ int64 totalReceivedBytes;
LoadTimingInfo load_timing_info;
};
@@ -356,6 +357,7 @@ class HttpNetworkTransactionTest
EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']",
response_headers);
+ out.totalReceivedBytes = trans->GetTotalReceivedBytes();
return out;
}
@@ -366,6 +368,13 @@ class HttpNetworkTransactionTest
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);
@@ -584,6 +593,8 @@ TEST_P(HttpNetworkTransactionTest, SimpleGET) {
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);
}
// Response with no status line.
@@ -597,6 +608,8 @@ TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
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);
}
// Allow up to 4 bytes of junk to precede status line.
@@ -610,6 +623,8 @@ TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
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);
}
// Allow up to 4 bytes of junk to precede status line.
@@ -623,6 +638,8 @@ TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
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);
}
// Beyond 4 bytes of slop and it should fail to find a status line.
@@ -636,6 +653,8 @@ TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
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);
}
// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
@@ -653,6 +672,8 @@ TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
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);
}
// Close the connection before enough bytes to have a status line.
@@ -666,15 +687,18 @@ TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
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);
}
// Simulate a 204 response, lacking a Content-Length header, sent over a
// persistent connection. The response should still terminate since a 204
// cannot have a response body.
TEST_P(HttpNetworkTransactionTest, StopsReading204) {
+ char junk[] = "junk";
MockRead data_reads[] = {
MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
- MockRead("junk"), // Should not be read!!
+ MockRead(junk), // Should not be read!!
MockRead(SYNCHRONOUS, OK),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
@@ -682,18 +706,24 @@ TEST_P(HttpNetworkTransactionTest, StopsReading204) {
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);
}
// A simple request using chunked encoding with some extra data after.
// (Like might be seen in a pipelined response.)
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("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
+ MockRead(last_read.data()),
MockRead(SYNCHRONOUS, OK),
};
SimpleGetHelperResult out = SimpleGetHelper(data_reads,
@@ -701,6 +731,9 @@ TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
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);
}
// Next tests deal with http://crbug.com/56344.
@@ -1569,6 +1602,9 @@ TEST_P(HttpNetworkTransactionTest, BasicAuth) {
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()));
@@ -1591,6 +1627,9 @@ TEST_P(HttpNetworkTransactionTest, BasicAuth) {
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);
@@ -1633,6 +1672,9 @@ TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
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);
@@ -1730,6 +1772,12 @@ TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
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 the request-challenge-retry sequence for basic auth, over a keep-alive
diff --git a/net/http/http_pipelined_connection_impl.cc b/net/http/http_pipelined_connection_impl.cc
index 284b254..2ee9c29 100644
--- a/net/http/http_pipelined_connection_impl.cc
+++ b/net/http/http_pipelined_connection_impl.cc
@@ -656,8 +656,9 @@ void HttpPipelinedConnectionImpl::SetConnectionReused(int pipeline_id) {
int64 HttpPipelinedConnectionImpl::GetTotalReceivedBytes(
int pipeline_id) const {
CHECK(ContainsKey(stream_info_map_, pipeline_id));
- CHECK(stream_info_map_.find(pipeline_id)->second.parser.get());
- return stream_info_map_.find(pipeline_id)->second.parser->received_bytes();
+ if (stream_info_map_.find(pipeline_id)->second.parser.get())
+ return stream_info_map_.find(pipeline_id)->second.parser->received_bytes();
+ return 0;
}
bool HttpPipelinedConnectionImpl::GetLoadTimingInfo(
diff --git a/net/http/http_transaction.h b/net/http/http_transaction.h
index 849d03a..3776998 100644
--- a/net/http/http_transaction.h
+++ b/net/http/http_transaction.h
@@ -106,6 +106,9 @@ class NET_EXPORT_PRIVATE HttpTransaction {
// otherwise, returns false and does not modify headers.
virtual bool GetFullRequestHeaders(HttpRequestHeaders* headers) const = 0;
+ // Get the number of bytes received from network.
+ virtual int64 GetTotalReceivedBytes() const = 0;
+
// Called to tell the transaction that we have successfully reached the end
// of the stream. This is equivalent to performing an extra Read() at the end
// that should return 0 bytes. This method should not be called if the
diff --git a/net/http/http_transaction_unittest.cc b/net/http/http_transaction_unittest.cc
index e161eca..ef2923f 100644
--- a/net/http/http_transaction_unittest.cc
+++ b/net/http/http_transaction_unittest.cc
@@ -230,6 +230,7 @@ MockNetworkTransaction::MockNetworkTransaction(
priority_(priority),
websocket_handshake_stream_create_helper_(NULL),
transaction_factory_(factory->AsWeakPtr()),
+ received_bytes_(0),
socket_log_id_(net::NetLog::Source::kInvalidId) {
}
@@ -255,6 +256,7 @@ int MockNetworkTransaction::Start(const net::HttpRequestInfo* request,
std::string resp_status = t->status;
std::string resp_headers = t->response_headers;
std::string resp_data = t->data;
+ received_bytes_ = resp_status.size() + resp_headers.size() + resp_data.size();
if (t->handler)
(t->handler)(request, &resp_status, &resp_headers, &resp_data);
@@ -331,6 +333,10 @@ bool MockNetworkTransaction::GetFullRequestHeaders(
return false;
}
+int64 MockNetworkTransaction::GetTotalReceivedBytes() const {
+ return received_bytes_;
+}
+
void MockNetworkTransaction::DoneReading() {
if (transaction_factory_.get())
transaction_factory_->TransactionDoneReading();
diff --git a/net/http/http_transaction_unittest.h b/net/http/http_transaction_unittest.h
index 3d6bb02..a91ebbd 100644
--- a/net/http/http_transaction_unittest.h
+++ b/net/http/http_transaction_unittest.h
@@ -193,6 +193,8 @@ class MockNetworkTransaction
virtual bool GetFullRequestHeaders(
net::HttpRequestHeaders* headers) const OVERRIDE;
+ virtual int64 GetTotalReceivedBytes() const OVERRIDE;
+
virtual void DoneReading() OVERRIDE;
virtual const net::HttpResponseInfo* GetResponseInfo() const OVERRIDE;
@@ -226,6 +228,7 @@ class MockNetworkTransaction
net::RequestPriority priority_;
CreateHelper* websocket_handshake_stream_create_helper_;
base::WeakPtr<MockNetworkLayer> transaction_factory_;
+ int64 received_bytes_;
// NetLog ID of the fake / non-existent underlying socket used by the
// connection. Requires Start() be passed a BoundNetLog with a real NetLog to