summaryrefslogtreecommitdiffstats
path: root/net/http
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2010-11-18 18:32:45 +0000
committerBen Murdoch <benm@google.com>2010-11-18 18:38:07 +0000
commit513209b27ff55e2841eac0e4120199c23acce758 (patch)
treeaeba30bb08c5f47c57003544e378a377c297eee6 /net/http
parent164f7496de0fbee436b385a79ead9e3cb81a50c1 (diff)
downloadexternal_chromium-513209b27ff55e2841eac0e4120199c23acce758.zip
external_chromium-513209b27ff55e2841eac0e4120199c23acce758.tar.gz
external_chromium-513209b27ff55e2841eac0e4120199c23acce758.tar.bz2
Merge Chromium at r65505: Initial merge by git.
Change-Id: I31d8f1d8cd33caaf7f47ffa7350aef42d5fbdb45
Diffstat (limited to 'net/http')
-rw-r--r--net/http/des.cc9
-rw-r--r--net/http/disk_cache_based_ssl_host_info.cc7
-rw-r--r--net/http/disk_cache_based_ssl_host_info.h7
-rw-r--r--net/http/http_auth.h3
-rw-r--r--net/http/http_auth_handler_basic.cc2
-rw-r--r--net/http/http_auth_handler_digest.cc9
-rw-r--r--net/http/http_auth_unittest.cc44
-rw-r--r--net/http/http_basic_stream.cc25
-rw-r--r--net/http/http_basic_stream.h11
-rw-r--r--net/http/http_cache.cc12
-rw-r--r--net/http/http_cache.h6
-rw-r--r--net/http/http_cache_transaction.cc2
-rw-r--r--net/http/http_cache_unittest.cc24
-rw-r--r--net/http/http_chunked_decoder.cc2
-rw-r--r--net/http/http_network_transaction.cc55
-rw-r--r--net/http/http_network_transaction.h3
-rw-r--r--net/http/http_network_transaction_unittest.cc155
-rw-r--r--net/http/http_proxy_client_socket.cc14
-rw-r--r--net/http/http_proxy_client_socket.h1
-rw-r--r--net/http/http_proxy_client_socket_pool_unittest.cc3
-rw-r--r--net/http/http_response_body_drainer_unittest.cc2
-rw-r--r--net/http/http_response_headers.cc28
-rw-r--r--net/http/http_response_headers_unittest.cc80
-rw-r--r--net/http/http_response_info.cc1
-rw-r--r--net/http/http_stream.h5
-rw-r--r--net/http/http_stream_parser.cc19
-rw-r--r--net/http/http_stream_request.cc24
-rw-r--r--net/http/http_transaction_unittest.cc2
-rw-r--r--net/http/http_util.cc25
-rw-r--r--net/http/http_util.h27
-rw-r--r--net/http/http_util_unittest.cc123
31 files changed, 476 insertions, 254 deletions
diff --git a/net/http/des.cc b/net/http/des.cc
index a083149..943f612 100644
--- a/net/http/des.cc
+++ b/net/http/des.cc
@@ -84,7 +84,14 @@ void DESMakeKey(const uint8* raw, uint8* key) {
key[7] = DESSetKeyParity((raw[6] << 1));
}
-#if defined(USE_NSS)
+#if defined(USE_OPENSSL)
+
+void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) {
+ // TODO(joth): When implementing consider splitting up this file by platform.
+ NOTIMPLEMENTED();
+}
+
+#elif defined(USE_NSS)
void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) {
CK_MECHANISM_TYPE cipher_mech = CKM_DES_ECB;
diff --git a/net/http/disk_cache_based_ssl_host_info.cc b/net/http/disk_cache_based_ssl_host_info.cc
index 10b2e15..cd1cac8 100644
--- a/net/http/disk_cache_based_ssl_host_info.cc
+++ b/net/http/disk_cache_based_ssl_host_info.cc
@@ -13,8 +13,11 @@
namespace net {
DiskCacheBasedSSLHostInfo::DiskCacheBasedSSLHostInfo(
- const std::string& hostname, HttpCache* http_cache)
- : callback_(new CancelableCompletionCallback<DiskCacheBasedSSLHostInfo>(
+ const std::string& hostname,
+ const SSLConfig& ssl_config,
+ HttpCache* http_cache)
+ : SSLHostInfo(hostname, ssl_config),
+ callback_(new CancelableCompletionCallback<DiskCacheBasedSSLHostInfo>(
ALLOW_THIS_IN_INITIALIZER_LIST(this),
&DiskCacheBasedSSLHostInfo::DoLoop)),
state_(GET_BACKEND),
diff --git a/net/http/disk_cache_based_ssl_host_info.h b/net/http/disk_cache_based_ssl_host_info.h
index 51a4a91..1d53b90 100644
--- a/net/http/disk_cache_based_ssl_host_info.h
+++ b/net/http/disk_cache_based_ssl_host_info.h
@@ -16,8 +16,9 @@
namespace net {
-class IOBuffer;
class HttpCache;
+class IOBuffer;
+struct SSLConfig;
// DiskCacheBasedSSLHostInfo fetches information about an SSL host from our
// standard disk cache. Since the information is defined to be non-sensitive,
@@ -25,7 +26,9 @@ class HttpCache;
class DiskCacheBasedSSLHostInfo : public SSLHostInfo,
public NonThreadSafe {
public:
- DiskCacheBasedSSLHostInfo(const std::string& hostname, HttpCache* http_cache);
+ DiskCacheBasedSSLHostInfo(const std::string& hostname,
+ const SSLConfig& ssl_config,
+ HttpCache* http_cache);
// Implementation of SSLHostInfo
virtual void Start();
diff --git a/net/http/http_auth.h b/net/http/http_auth.h
index 3611612..0034b1f 100644
--- a/net/http/http_auth.h
+++ b/net/http/http_auth.h
@@ -133,7 +133,8 @@ class HttpAuth {
//
// |headers| must be non-NULL and contain the new HTTP response.
//
- // |target| specifies whether the headers came from a server or proxy.
+ // |target| specifies whether the authentication challenge response came
+ // from a server or a proxy.
//
// |disabled_schemes| are the authentication schemes to ignore.
//
diff --git a/net/http/http_auth_handler_basic.cc b/net/http/http_auth_handler_basic.cc
index 054357a..35b088f 100644
--- a/net/http/http_auth_handler_basic.cc
+++ b/net/http/http_auth_handler_basic.cc
@@ -41,7 +41,7 @@ bool HttpAuthHandlerBasic::ParseChallenge(
std::string realm;
while (parameters.GetNext()) {
if (LowerCaseEqualsASCII(parameters.name(), "realm"))
- realm = parameters.unquoted_value();
+ realm = parameters.value();
}
if (!parameters.valid())
diff --git a/net/http/http_auth_handler_digest.cc b/net/http/http_auth_handler_digest.cc
index f7f178c..82aa9af 100644
--- a/net/http/http_auth_handler_digest.cc
+++ b/net/http/http_auth_handler_digest.cc
@@ -221,7 +221,7 @@ HttpAuth::AuthorizationResult HttpAuthHandlerDigest::HandleAnotherChallenge(
while (parameters.GetNext()) {
if (!LowerCaseEqualsASCII(parameters.name(), "stale"))
continue;
- if (LowerCaseEqualsASCII(parameters.unquoted_value(), "true"))
+ if (LowerCaseEqualsASCII(parameters.value(), "true"))
return HttpAuth::AUTHORIZATION_RESULT_STALE;
}
@@ -266,14 +266,9 @@ bool HttpAuthHandlerDigest::ParseChallenge(
// Loop through all the properties.
while (parameters.GetNext()) {
- if (parameters.value().empty()) {
- DVLOG(1) << "Invalid digest property";
- return false;
- }
-
// FAIL -- couldn't parse a property.
if (!ParseChallengeProperty(parameters.name(),
- parameters.unquoted_value()))
+ parameters.value()))
return false;
}
diff --git a/net/http/http_auth_unittest.cc b/net/http/http_auth_unittest.cc
index 3068135..63ae3b0 100644
--- a/net/http/http_auth_unittest.cc
+++ b/net/http/http_auth_unittest.cc
@@ -149,22 +149,22 @@ TEST(HttpAuthTest, ChooseBestChallenge) {
TEST(HttpAuthTest, HandleChallengeResponse) {
std::string challenge_used;
- const char* kMockChallenge =
+ const char* const kMockChallenge =
"HTTP/1.1 401 Unauthorized\n"
"WWW-Authenticate: Mock token_here\n";
- const char* kBasicChallenge =
+ const char* const kBasicChallenge =
"HTTP/1.1 401 Unauthorized\n"
"WWW-Authenticate: Basic realm=\"happy\"\n";
- const char* kMissingChallenge =
+ const char* const kMissingChallenge =
"HTTP/1.1 401 Unauthorized\n";
- const char* kEmptyChallenge =
+ const char* const kEmptyChallenge =
"HTTP/1.1 401 Unauthorized\n"
"WWW-Authenticate: \n";
- const char* kBasicAndMockChallenges =
+ const char* const kBasicAndMockChallenges =
"HTTP/1.1 401 Unauthorized\n"
"WWW-Authenticate: Basic realm=\"happy\"\n"
"WWW-Authenticate: Mock token_here\n";
- const char* kTwoMockChallenges =
+ const char* const kTwoMockChallenges =
"HTTP/1.1 401 Unauthorized\n"
"WWW-Authenticate: Mock token_a\n"
"WWW-Authenticate: Mock token_b\n";
@@ -249,9 +249,7 @@ TEST(HttpAuthTest, ChallengeTokenizer) {
EXPECT_TRUE(parameters.GetNext());
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("realm"), parameters.name());
- EXPECT_EQ(std::string("foobar"), parameters.unquoted_value());
- EXPECT_EQ(std::string("\"foobar\""), parameters.value());
- EXPECT_TRUE(parameters.value_is_quoted());
+ EXPECT_EQ(std::string("foobar"), parameters.value());
EXPECT_FALSE(parameters.GetNext());
}
@@ -268,8 +266,6 @@ TEST(HttpAuthTest, ChallengeTokenizerNoQuotes) {
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("realm"), parameters.name());
EXPECT_EQ(std::string("foobar@baz.com"), parameters.value());
- EXPECT_EQ(std::string("foobar@baz.com"), parameters.unquoted_value());
- EXPECT_FALSE(parameters.value_is_quoted());
EXPECT_FALSE(parameters.GetNext());
}
@@ -286,8 +282,6 @@ TEST(HttpAuthTest, ChallengeTokenizerMismatchedQuotes) {
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("realm"), parameters.name());
EXPECT_EQ(std::string("foobar@baz.com"), parameters.value());
- EXPECT_EQ(std::string("foobar@baz.com"), parameters.unquoted_value());
- EXPECT_FALSE(parameters.value_is_quoted());
EXPECT_FALSE(parameters.GetNext());
}
@@ -304,7 +298,6 @@ TEST(HttpAuthTest, ChallengeTokenizerMismatchedQuotesNoValue) {
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("realm"), parameters.name());
EXPECT_EQ(std::string(""), parameters.value());
- EXPECT_FALSE(parameters.value_is_quoted());
EXPECT_FALSE(parameters.GetNext());
}
@@ -322,15 +315,13 @@ TEST(HttpAuthTest, ChallengeTokenizerMismatchedQuotesSpaces) {
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("realm"), parameters.name());
EXPECT_EQ(std::string("foo bar"), parameters.value());
- EXPECT_EQ(std::string("foo bar"), parameters.unquoted_value());
- EXPECT_FALSE(parameters.value_is_quoted());
EXPECT_FALSE(parameters.GetNext());
}
// Use multiple name=value properties with mismatching quote marks in the last
// value.
TEST(HttpAuthTest, ChallengeTokenizerMismatchedQuotesMultiple) {
- std::string challenge_str = "Digest qop=, algorithm=md5, realm=\"foo";
+ std::string challenge_str = "Digest qop=auth-int, algorithm=md5, realm=\"foo";
HttpAuth::ChallengeTokenizer challenge(challenge_str.begin(),
challenge_str.end());
HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs();
@@ -340,20 +331,15 @@ TEST(HttpAuthTest, ChallengeTokenizerMismatchedQuotesMultiple) {
EXPECT_TRUE(parameters.GetNext());
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("qop"), parameters.name());
- EXPECT_EQ(std::string(""), parameters.value());
- EXPECT_FALSE(parameters.value_is_quoted());
+ EXPECT_EQ(std::string("auth-int"), parameters.value());
EXPECT_TRUE(parameters.GetNext());
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("algorithm"), parameters.name());
EXPECT_EQ(std::string("md5"), parameters.value());
- EXPECT_EQ(std::string("md5"), parameters.unquoted_value());
- EXPECT_FALSE(parameters.value_is_quoted());
EXPECT_TRUE(parameters.GetNext());
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("realm"), parameters.name());
EXPECT_EQ(std::string("foo"), parameters.value());
- EXPECT_EQ(std::string("foo"), parameters.unquoted_value());
- EXPECT_FALSE(parameters.value_is_quoted());
EXPECT_FALSE(parameters.GetNext());
}
@@ -366,12 +352,8 @@ TEST(HttpAuthTest, ChallengeTokenizerNoValue) {
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("Digest"), challenge.scheme());
- EXPECT_TRUE(parameters.GetNext());
- EXPECT_TRUE(parameters.valid());
- EXPECT_EQ(std::string("qop"), parameters.name());
- EXPECT_EQ(std::string(""), parameters.value());
- EXPECT_FALSE(parameters.value_is_quoted());
EXPECT_FALSE(parameters.GetNext());
+ EXPECT_FALSE(parameters.valid());
}
// Specify multiple properties, comma separated.
@@ -388,18 +370,16 @@ TEST(HttpAuthTest, ChallengeTokenizerMultiple) {
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("algorithm"), parameters.name());
EXPECT_EQ(std::string("md5"), parameters.value());
- EXPECT_FALSE(parameters.value_is_quoted());
EXPECT_TRUE(parameters.GetNext());
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("realm"), parameters.name());
- EXPECT_EQ(std::string("Oblivion"), parameters.unquoted_value());
- EXPECT_TRUE(parameters.value_is_quoted());
+ EXPECT_EQ(std::string("Oblivion"), parameters.value());
EXPECT_TRUE(parameters.GetNext());
EXPECT_TRUE(parameters.valid());
EXPECT_EQ(std::string("qop"), parameters.name());
EXPECT_EQ(std::string("auth-int"), parameters.value());
- EXPECT_FALSE(parameters.value_is_quoted());
EXPECT_FALSE(parameters.GetNext());
+ EXPECT_TRUE(parameters.valid());
}
// Use a challenge which has no property.
diff --git a/net/http/http_basic_stream.cc b/net/http/http_basic_stream.cc
index ecd692b..433b08e 100644
--- a/net/http/http_basic_stream.cc
+++ b/net/http/http_basic_stream.cc
@@ -4,33 +4,48 @@
#include "net/http/http_basic_stream.h"
+#include "base/stringprintf.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_request_info.h"
#include "net/http/http_stream_parser.h"
+#include "net/http/http_util.h"
#include "net/socket/client_socket_handle.h"
namespace net {
-HttpBasicStream::HttpBasicStream(ClientSocketHandle* connection)
+HttpBasicStream::HttpBasicStream(ClientSocketHandle* connection,
+ bool using_proxy)
: read_buf_(new GrowableIOBuffer()),
- connection_(connection) {
+ connection_(connection),
+ using_proxy_(using_proxy),
+ request_info_(NULL) {
}
int HttpBasicStream::InitializeStream(const HttpRequestInfo* request_info,
const BoundNetLog& net_log,
CompletionCallback* callback) {
+ request_info_ = request_info;
parser_.reset(new HttpStreamParser(connection_.get(), request_info,
read_buf_, net_log));
return OK;
}
-int HttpBasicStream::SendRequest(const std::string& headers,
+int HttpBasicStream::SendRequest(const HttpRequestHeaders& headers,
UploadDataStream* request_body,
HttpResponseInfo* response,
CompletionCallback* callback) {
DCHECK(parser_.get());
- return parser_->SendRequest(headers, request_body, response, callback);
+ const std::string path = using_proxy_ ?
+ HttpUtil::SpecForRequest(request_info_->url) :
+ HttpUtil::PathForRequest(request_info_->url);
+ request_line_ = base::StringPrintf("%s %s HTTP/1.1\r\n",
+ request_info_->method.c_str(),
+ path.c_str()) + headers.ToString();
+
+ return parser_->SendRequest(request_line_, request_body, response, callback);
}
HttpBasicStream::~HttpBasicStream() {}
@@ -60,7 +75,7 @@ HttpStream* HttpBasicStream::RenewStreamForAuth() {
DCHECK(IsResponseBodyComplete());
DCHECK(!IsMoreDataBuffered());
parser_.reset();
- return new HttpBasicStream(connection_.release());
+ return new HttpBasicStream(connection_.release(), using_proxy_);
}
bool HttpBasicStream::IsResponseBodyComplete() const {
diff --git a/net/http/http_basic_stream.h b/net/http/http_basic_stream.h
index ffab967..83136c0 100644
--- a/net/http/http_basic_stream.h
+++ b/net/http/http_basic_stream.h
@@ -23,13 +23,14 @@ class ClientSocketHandle;
class GrowableIOBuffer;
class HttpResponseInfo;
struct HttpRequestInfo;
+class HttpRequestHeaders;
class HttpStreamParser;
class IOBuffer;
class UploadDataStream;
class HttpBasicStream : public HttpStream {
public:
- explicit HttpBasicStream(ClientSocketHandle* connection);
+ HttpBasicStream(ClientSocketHandle* connection, bool using_proxy);
virtual ~HttpBasicStream();
// HttpStream methods:
@@ -37,7 +38,7 @@ class HttpBasicStream : public HttpStream {
const BoundNetLog& net_log,
CompletionCallback* callback);
- virtual int SendRequest(const std::string& headers,
+ virtual int SendRequest(const HttpRequestHeaders& headers,
UploadDataStream* request_body,
HttpResponseInfo* response,
CompletionCallback* callback);
@@ -76,6 +77,12 @@ class HttpBasicStream : public HttpStream {
scoped_ptr<ClientSocketHandle> connection_;
+ bool using_proxy_;
+
+ std::string request_line_;
+
+ const HttpRequestInfo* request_info_;
+
DISALLOW_COPY_AND_ASSIGN(HttpBasicStream);
};
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index eca95ef..0372222 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -267,8 +267,9 @@ class HttpCache::SSLHostInfoFactoryAdaptor : public SSLHostInfoFactory {
: http_cache_(http_cache) {
}
- SSLHostInfo* GetForHost(const std::string& hostname) {
- return new DiskCacheBasedSSLHostInfo(hostname, http_cache_);
+ SSLHostInfo* GetForHost(const std::string& hostname,
+ const SSLConfig& ssl_config) {
+ return new DiskCacheBasedSSLHostInfo(hostname, ssl_config, http_cache_);
}
private:
@@ -601,11 +602,10 @@ HttpCache::ActiveEntry* HttpCache::FindActiveEntry(const std::string& key) {
}
HttpCache::ActiveEntry* HttpCache::ActivateEntry(
- const std::string& key,
disk_cache::Entry* disk_entry) {
- DCHECK(!FindActiveEntry(key));
+ DCHECK(!FindActiveEntry(disk_entry->GetKey()));
ActiveEntry* entry = new ActiveEntry(disk_entry);
- active_entries_[key] = entry;
+ active_entries_[disk_entry->GetKey()] = entry;
return entry;
}
@@ -990,7 +990,7 @@ void HttpCache::OnIOComplete(int result, PendingOp* pending_op) {
fail_requests = true;
} else if (item->IsValid()) {
key = pending_op->disk_entry->GetKey();
- entry = ActivateEntry(key, pending_op->disk_entry);
+ entry = ActivateEntry(pending_op->disk_entry);
} else {
// The writer transaction is gone.
if (op == WI_CREATE_ENTRY)
diff --git a/net/http/http_cache.h b/net/http/http_cache.h
index 255d7b6..0ce22e5 100644
--- a/net/http/http_cache.h
+++ b/net/http/http_cache.h
@@ -257,10 +257,8 @@ class HttpCache : public HttpTransactionFactory,
ActiveEntry* FindActiveEntry(const std::string& key);
// Creates a new ActiveEntry and starts tracking it. |disk_entry| is the disk
- // cache entry that corresponds to the desired |key|.
- // TODO(rvargas): remove the |key| argument.
- ActiveEntry* ActivateEntry(const std::string& key,
- disk_cache::Entry* disk_entry);
+ // cache entry.
+ ActiveEntry* ActivateEntry(disk_cache::Entry* disk_entry);
// Deletes an ActiveEntry.
void DeactivateEntry(ActiveEntry* entry);
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index 58288f4..873ccf4 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -1801,7 +1801,7 @@ int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) {
DCHECK_EQ(200, response_.headers->response_code());
}
- scoped_refptr<PickledIOBuffer> data = new PickledIOBuffer();
+ scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer());
response_.Persist(data->pickle(), skip_transient_headers, truncated);
data->Done();
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc
index eec8098..f71cec9 100644
--- a/net/http/http_cache_unittest.cc
+++ b/net/http/http_cache_unittest.cc
@@ -573,7 +573,7 @@ class MockHttpCache {
int size = disk_entry->GetDataSize(0);
TestCompletionCallback cb;
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(size);
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(size));
int rv = disk_entry->ReadData(0, 0, buffer, size, &cb);
rv = cb.GetResult(rv);
EXPECT_EQ(size, rv);
@@ -593,8 +593,8 @@ class MockHttpCache {
&pickle, skip_transient_headers, response_truncated);
TestCompletionCallback cb;
- scoped_refptr<net::WrappedIOBuffer> data = new net::WrappedIOBuffer(
- reinterpret_cast<const char*>(pickle.data()));
+ scoped_refptr<net::WrappedIOBuffer> data(new net::WrappedIOBuffer(
+ reinterpret_cast<const char*>(pickle.data())));
int len = static_cast<int>(pickle.size());
int rv = disk_entry->WriteData(0, 0, data, len, &cb, true);
@@ -951,8 +951,8 @@ const MockTransaction kRangeGET_TransactionOK = {
void Verify206Response(std::string response, int start, int end) {
std::string raw_headers(net::HttpUtil::AssembleRawHeaders(response.data(),
response.size()));
- scoped_refptr<net::HttpResponseHeaders> headers =
- new net::HttpResponseHeaders(raw_headers);
+ scoped_refptr<net::HttpResponseHeaders> headers(
+ new net::HttpResponseHeaders(raw_headers));
ASSERT_EQ(206, headers->response_code());
@@ -1854,7 +1854,7 @@ TEST(HttpCache, SimpleGET_AbandonedCacheRead) {
rv = callback.WaitForResult();
ASSERT_EQ(net::OK, rv);
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(256);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
rv = trans->Read(buf, 256, &callback);
EXPECT_EQ(net::ERR_IO_PENDING, rv);
@@ -3544,7 +3544,7 @@ TEST(HttpCache, RangeGET_Cancel) {
EXPECT_EQ(1, cache.disk_cache()->create_count());
// Make sure that the entry has some data stored.
- scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(10);
+ scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(10));
rv = c->trans->Read(buf, buf->size(), &c->callback);
if (rv == net::ERR_IO_PENDING)
rv = c->callback.WaitForResult();
@@ -3585,7 +3585,7 @@ TEST(HttpCache, RangeGET_Cancel2) {
// Make sure that we revalidate the entry and read from the cache (a single
// read will return while waiting for the network).
- scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(5);
+ scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(5));
rv = c->trans->Read(buf, buf->size(), &c->callback);
EXPECT_EQ(5, c->callback.GetResult(rv));
rv = c->trans->Read(buf, buf->size(), &c->callback);
@@ -3631,7 +3631,7 @@ TEST(HttpCache, RangeGET_Cancel3) {
// Make sure that we revalidate the entry and read from the cache (a single
// read will return while waiting for the network).
- scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(5);
+ scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(5));
rv = c->trans->Read(buf, buf->size(), &c->callback);
EXPECT_EQ(5, c->callback.GetResult(rv));
rv = c->trans->Read(buf, buf->size(), &c->callback);
@@ -4029,7 +4029,7 @@ TEST(HttpCache, DoomOnDestruction2) {
EXPECT_EQ(1, cache.disk_cache()->create_count());
// Make sure that the entry has some data stored.
- scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(10);
+ scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(10));
rv = c->trans->Read(buf, buf->size(), &c->callback);
if (rv == net::ERR_IO_PENDING)
rv = c->callback.WaitForResult();
@@ -4073,7 +4073,7 @@ TEST(HttpCache, DoomOnDestruction3) {
EXPECT_EQ(1, cache.disk_cache()->create_count());
// Make sure that the entry has some data stored.
- scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(10);
+ scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(10));
rv = c->trans->Read(buf, buf->size(), &c->callback);
if (rv == net::ERR_IO_PENDING)
rv = c->callback.WaitForResult();
@@ -4117,7 +4117,7 @@ TEST(HttpCache, Set_Truncated_Flag) {
EXPECT_EQ(1, cache.disk_cache()->create_count());
// Make sure that the entry has some data stored.
- scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(10);
+ scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(10));
rv = c->trans->Read(buf, buf->size(), &c->callback);
if (rv == net::ERR_IO_PENDING)
rv = c->callback.WaitForResult();
diff --git a/net/http/http_chunked_decoder.cc b/net/http/http_chunked_decoder.cc
index 455c9ed..d5b16dd 100644
--- a/net/http/http_chunked_decoder.cc
+++ b/net/http/http_chunked_decoder.cc
@@ -192,7 +192,7 @@ bool HttpChunkedDecoder::ParseChunkSize(const char* start, int len, int* out) {
return false;
int parsed_number;
- bool ok = base::HexStringToInt(std::string(start, len), &parsed_number);
+ bool ok = base::HexStringToInt(start, start + len, &parsed_number);
if (ok && parsed_number >= 0) {
*out = parsed_number;
return true;
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index e0b9c39..bc2d322 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -89,6 +89,7 @@ HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session)
request_(NULL),
headers_valid_(false),
logged_response_time_(false),
+ request_headers_(),
read_buf_len_(0),
next_state_(STATE_NONE),
establishing_tunnel_(false) {
@@ -284,7 +285,7 @@ int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len,
State next_state = STATE_NONE;
- scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
+ scoped_refptr<HttpResponseHeaders> headers(GetResponseHeaders());
if (headers_valid_ && headers.get() && stream_request_.get()) {
// We're trying to read the body of the response but we're still trying
// to establish an SSL tunnel through the proxy. We can't read these
@@ -535,6 +536,8 @@ int HttpNetworkTransaction::DoCreateStreamComplete(int result) {
if (result == OK) {
next_state_ = STATE_INIT_STREAM;
DCHECK(stream_.get());
+ } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
+ result = HandleCertificateRequest(result);
}
// At this point we are done with the stream_request_.
@@ -552,9 +555,6 @@ int HttpNetworkTransaction::DoInitStreamComplete(int result) {
if (result == OK) {
next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
} else {
- if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED)
- result = HandleCertificateRequest(result);
-
if (result < 0)
result = HandleIOError(result);
@@ -624,38 +624,22 @@ int HttpNetworkTransaction::DoSendRequest() {
// This is constructed lazily (instead of within our Start method), so that
// we have proxy info available.
- if (request_headers_.empty() && !response_.was_fetched_via_spdy) {
+ if (request_headers_.IsEmpty()) {
bool using_proxy = (proxy_info_.is_http()|| proxy_info_.is_https()) &&
!is_https_request();
- const std::string path = using_proxy ?
- HttpUtil::SpecForRequest(request_->url) :
- HttpUtil::PathForRequest(request_->url);
- std::string request_line = base::StringPrintf(
- "%s %s HTTP/1.1\r\n", request_->method.c_str(), path.c_str());
-
- HttpRequestHeaders request_headers;
HttpUtil::BuildRequestHeaders(request_, request_body, auth_controllers_,
ShouldApplyServerAuth(),
ShouldApplyProxyAuth(), using_proxy,
- &request_headers);
+ &request_headers_);
if (session_->network_delegate())
- session_->network_delegate()->OnSendHttpRequest(&request_headers);
-
- if (net_log_.IsLoggingAllEvents()) {
- net_log_.AddEvent(
- NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
- new NetLogHttpRequestParameter(request_line, request_headers));
- }
-
- request_headers_ = request_line + request_headers.ToString();
- } else {
- if (net_log_.IsLoggingAllEvents()) {
- net_log_.AddEvent(
- NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
- new NetLogHttpRequestParameter(request_->url.spec(),
- request_->extra_headers));
- }
+ session_->network_delegate()->OnSendHttpRequest(&request_headers_);
+ }
+ if (net_log_.IsLoggingAllEvents()) {
+ net_log_.AddEvent(
+ NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
+ make_scoped_refptr(new NetLogHttpRequestParameter(
+ request_->url.spec(), request_->extra_headers)));
}
headers_valid_ = false;
@@ -748,7 +732,7 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
if (net_log_.IsLoggingAllEvents()) {
net_log_.AddEvent(
NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
- new NetLogHttpResponseParameter(response_.headers));
+ make_scoped_refptr(new NetLogHttpResponseParameter(response_.headers)));
}
if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
@@ -1050,7 +1034,7 @@ void HttpNetworkTransaction::ResetStateForAuthRestart() {
read_buf_ = NULL;
read_buf_len_ = 0;
headers_valid_ = false;
- request_headers_.clear();
+ request_headers_.Clear();
response_ = HttpResponseInfo();
establishing_tunnel_ = false;
}
@@ -1080,7 +1064,7 @@ void HttpNetworkTransaction::ResetConnectionAndRequestForResend() {
// We need to clear request_headers_ because it contains the real request
// headers, but we may need to resend the CONNECT request first to recreate
// the SSL tunnel.
- request_headers_.clear();
+ request_headers_.Clear();
next_state_ = STATE_CREATE_STREAM; // Resend the request.
}
@@ -1094,7 +1078,7 @@ bool HttpNetworkTransaction::ShouldApplyServerAuth() const {
}
int HttpNetworkTransaction::HandleAuthChallenge() {
- scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
+ scoped_refptr<HttpResponseHeaders> headers(GetResponseHeaders());
DCHECK(headers);
int status = headers->response_code();
@@ -1105,6 +1089,11 @@ int HttpNetworkTransaction::HandleAuthChallenge() {
if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct())
return ERR_UNEXPECTED_PROXY_AUTH;
+ // This case can trigger when an HTTPS server responds with a 407 status
+ // code through a non-authenticating proxy.
+ if (!auth_controllers_[target].get())
+ return ERR_UNEXPECTED_PROXY_AUTH;
+
int rv = auth_controllers_[target]->HandleAuthChallenge(
headers, (request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA) != 0, false,
net_log_);
diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h
index ce0c5bd..255fcdf 100644
--- a/net/http/http_network_transaction.h
+++ b/net/http/http_network_transaction.h
@@ -17,6 +17,7 @@
#include "net/base/request_priority.h"
#include "net/base/ssl_config_service.h"
#include "net/http/http_auth.h"
+#include "net/http/http_request_headers.h"
#include "net/http/http_response_info.h"
#include "net/http/http_transaction.h"
#include "net/http/stream_factory.h"
@@ -222,7 +223,7 @@ class HttpNetworkTransaction : public HttpTransaction,
SSLConfig ssl_config_;
- std::string request_headers_;
+ HttpRequestHeaders request_headers_;
// The size in bytes of the buffer we use to drain the response body that
// we want to throw away. The response body is typically a small error
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 2066264..b060d7c 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -460,6 +460,67 @@ TEST_F(HttpNetworkTransactionTest,
}
TEST_F(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_F(HttpNetworkTransactionTest,
+ ComplexContentLengthHeadersNoTransferEncoding) {
+ // More than 2 dupes.
+ {
+ 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);
+ }
+ // HTTP/1.0
+ {
+ 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);
+ }
+ // 2 dupes and one mismatched.
+ {
+ 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_F(HttpNetworkTransactionTest,
MultipleContentLengthHeadersTransferEncoding) {
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
@@ -544,7 +605,7 @@ TEST_F(HttpNetworkTransactionTest, Head) {
TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
@@ -733,7 +794,7 @@ TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
const MockRead& read_failure) {
SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
HttpRequestInfo request;
request.method = "GET";
@@ -850,7 +911,7 @@ TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
// reading the body.
TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
HttpRequestInfo request;
request.method = "GET";
@@ -1707,6 +1768,66 @@ TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
}
+// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
+// through a non-authenticating proxy. The request should fail with
+// ERR_UNEXPECTED_PROXY_AUTH.
+// Note that it is impossible to detect if an HTTP server returns a 407 through
+// a non-authenticating proxy - there is nothing to indicate whether the
+// response came from the proxy or the server, so it is treated as if the proxy
+// issued the challenge.
+TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
+ SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
+ CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
+ 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/");
+
+ // Since we have proxy, should try to establish tunnel.
+ 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(false, OK),
+ };
+
+ StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
+ data_writes1, arraysize(data_writes1));
+ session_deps.socket_factory.AddSocketDataProvider(&data1);
+ SSLSocketDataProvider ssl(true, OK);
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
+
+ TestCompletionCallback callback1;
+
+ scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+
+ int rv = trans->Start(&request, &callback1, log.bound());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback1.WaitForResult();
+ EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
+ size_t pos = ExpectLogContainsSomewhere(
+ log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
+ NetLog::PHASE_NONE);
+ ExpectLogContainsSomewhere(
+ log.entries(), pos,
+ NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
+ NetLog::PHASE_NONE);
+}
// Test a simple get through an HTTPS Proxy.
TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
@@ -3189,7 +3310,7 @@ TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
request[1].load_flags = 0;
SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
// The first socket is used for transaction 1 and the first attempt of
// transaction 2.
@@ -3457,7 +3578,7 @@ TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
// Test that previously tried username/passwords for a realm get re-used.
TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
// Transaction 1: authenticate (foo, bar) on MyRealm1
{
@@ -3850,7 +3971,7 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
// are started with the same nonce.
TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
HttpAuthHandlerDigest::SetFixedCnonce(true);
// Transaction 1: authenticate (foo, bar) on MyRealm1
@@ -3991,7 +4112,7 @@ TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
// Setup some state (which we expect ResetStateForRestart() will clear).
trans->read_buf_ = new IOBuffer(15);
trans->read_buf_len_ = 15;
- trans->request_headers_ = "Authorization: NTLM";
+ trans->request_headers_.SetHeader("Authorization", "NTLM");
// Setup state in response_
HttpResponseInfo* response = &trans->response_;
@@ -4004,7 +4125,7 @@ TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
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);
+ 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));
@@ -4016,7 +4137,7 @@ TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
// Verify that the state that needed to be reset, has been reset.
EXPECT_TRUE(trans->read_buf_.get() == NULL);
EXPECT_EQ(0, trans->read_buf_len_);
- EXPECT_EQ(0U, trans->request_headers_.size());
+ EXPECT_TRUE(trans->request_headers_.IsEmpty());
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_TRUE(response->headers.get() == NULL);
EXPECT_FALSE(response->was_cached);
@@ -5317,7 +5438,7 @@ TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
// Make sure we can handle an error when writing the request.
TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
HttpRequestInfo request;
request.method = "GET";
@@ -5346,7 +5467,7 @@ TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
// Check that a connection closed after the start of the headers finishes ok.
TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
HttpRequestInfo request;
request.method = "GET";
@@ -5388,7 +5509,7 @@ TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
// restart does the right thing.
TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
SessionDependencies session_deps;
- scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
HttpRequestInfo request;
request.method = "GET";
@@ -6412,8 +6533,8 @@ TEST_F(HttpNetworkTransactionTest,
scoped_refptr<SpdySession> spdy_session =
session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
BoundNetLog());
- scoped_refptr<TCPSocketParams> tcp_params =
- new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
+ scoped_refptr<TCPSocketParams> tcp_params(
+ new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false));
scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
EXPECT_EQ(ERR_IO_PENDING,
@@ -6887,7 +7008,7 @@ TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
origin, BoundNetLog());
auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
- scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
int rv = OK;
@@ -7588,8 +7709,8 @@ TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
scoped_refptr<SpdySession> spdy_session =
session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
BoundNetLog());
- scoped_refptr<TCPSocketParams> tcp_params =
- new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
+ scoped_refptr<TCPSocketParams> tcp_params(
+ new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false));
TestCompletionCallback callback;
scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
diff --git a/net/http/http_proxy_client_socket.cc b/net/http/http_proxy_client_socket.cc
index b5ede3d..186b459 100644
--- a/net/http/http_proxy_client_socket.cc
+++ b/net/http/http_proxy_client_socket.cc
@@ -185,6 +185,14 @@ bool HttpProxyClientSocket::WasEverUsed() const {
return false;
}
+bool HttpProxyClientSocket::UsingTCPFastOpen() const {
+ if (transport_.get() && transport_->socket()) {
+ return transport_->socket()->UsingTCPFastOpen();
+ }
+ NOTREACHED();
+ return false;
+}
+
int HttpProxyClientSocket::Read(IOBuffer* buf, int buf_len,
CompletionCallback* callback) {
DCHECK(!user_callback_);
@@ -335,8 +343,8 @@ int HttpProxyClientSocket::DoSendRequest() {
if (net_log_.IsLoggingAllEvents()) {
net_log_.AddEvent(
NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
- new NetLogHttpRequestParameter(
- request_line, request_headers));
+ make_scoped_refptr(new NetLogHttpRequestParameter(
+ request_line, request_headers)));
}
request_headers_ = request_line + request_headers.ToString();
}
@@ -373,7 +381,7 @@ int HttpProxyClientSocket::DoReadHeadersComplete(int result) {
if (net_log_.IsLoggingAllEvents()) {
net_log_.AddEvent(
NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
- new NetLogHttpResponseParameter(response_.headers));
+ make_scoped_refptr(new NetLogHttpResponseParameter(response_.headers)));
}
switch (response_.headers->response_code()) {
diff --git a/net/http/http_proxy_client_socket.h b/net/http/http_proxy_client_socket.h
index 6530285..b42c78b 100644
--- a/net/http/http_proxy_client_socket.h
+++ b/net/http/http_proxy_client_socket.h
@@ -78,6 +78,7 @@ class HttpProxyClientSocket : public ClientSocket {
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
+ virtual bool UsingTCPFastOpen() const;
// Socket methods:
virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc
index e1ca2fe..ae84ecc 100644
--- a/net/http/http_proxy_client_socket_pool_unittest.cc
+++ b/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -244,7 +244,8 @@ TEST_P(HttpProxyClientSocketPoolTest, NeedAuth) {
CreateMockWrite(*rst, 2, true),
};
scoped_ptr<spdy::SpdyFrame> resp(
- ConstructSpdySynReplyError("407 Proxy Authentication Required", 1));
+ ConstructSpdySynReplyError(
+ "407 Proxy Authentication Required", NULL, 0, 1));
MockRead spdy_reads[] = {
CreateMockWrite(*resp, 1, true),
MockRead(true, 0, 3)
diff --git a/net/http/http_response_body_drainer_unittest.cc b/net/http/http_response_body_drainer_unittest.cc
index d57952d..d8c9bb7 100644
--- a/net/http/http_response_body_drainer_unittest.cc
+++ b/net/http/http_response_body_drainer_unittest.cc
@@ -78,7 +78,7 @@ class MockHttpStream : public HttpStream {
CompletionCallback* callback) {
return ERR_UNEXPECTED;
}
- virtual int SendRequest(const std::string& request_headers,
+ virtual int SendRequest(const HttpRequestHeaders& request_headers,
UploadDataStream* request_body,
HttpResponseInfo* response,
CompletionCallback* callback) {
diff --git a/net/http/http_response_headers.cc b/net/http/http_response_headers.cc
index 99c5404..c2d098c 100644
--- a/net/http/http_response_headers.cc
+++ b/net/http/http_response_headers.cc
@@ -484,7 +484,7 @@ bool HttpResponseHeaders::HasHeaderValue(const std::string& name,
while (EnumerateHeader(&iter, name, &temp)) {
if (value.size() == temp.size() &&
std::equal(temp.begin(), temp.end(), value.begin(),
- CaseInsensitiveCompare<char>()))
+ base::CaseInsensitiveCompare<char>()))
return true;
}
return false;
@@ -598,7 +598,7 @@ void HttpResponseHeaders::ParseStatusLine(
raw_headers_.push_back(' ');
raw_headers_.append(code, p);
raw_headers_.push_back(' ');
- base::StringToInt(std::string(code, p), &response_code_);
+ base::StringToInt(code, p, &response_code_);
// Skip whitespace.
while (*p == ' ')
@@ -629,7 +629,7 @@ size_t HttpResponseHeaders::FindHeader(size_t from,
const std::string::const_iterator& name_end = parsed_[i].name_end;
if (static_cast<size_t>(name_end - name_begin) == search.size() &&
std::equal(name_begin, name_end, search.begin(),
- CaseInsensitiveCompare<char>()))
+ base::CaseInsensitiveCompare<char>()))
return i;
}
@@ -973,7 +973,9 @@ bool HttpResponseHeaders::GetMaxAgeValue(TimeDelta* result) const {
value.begin() + kMaxAgePrefixLen,
kMaxAgePrefix)) {
int64 seconds;
- base::StringToInt64(value.substr(kMaxAgePrefixLen), &seconds);
+ base::StringToInt64(value.begin() + kMaxAgePrefixLen,
+ value.end(),
+ &seconds);
*result = TimeDelta::FromSeconds(seconds);
return true;
}
@@ -1148,9 +1150,9 @@ bool HttpResponseHeaders::GetContentRange(int64* first_byte_position,
byte_range_resp_spec.begin() + minus_position;
HttpUtil::TrimLWS(&first_byte_pos_begin, &first_byte_pos_end);
- bool ok = base::StringToInt64(
- std::string(first_byte_pos_begin, first_byte_pos_end),
- first_byte_position);
+ bool ok = base::StringToInt64(first_byte_pos_begin,
+ first_byte_pos_end,
+ first_byte_position);
// Obtain last-byte-pos.
std::string::const_iterator last_byte_pos_begin =
@@ -1159,9 +1161,9 @@ bool HttpResponseHeaders::GetContentRange(int64* first_byte_position,
byte_range_resp_spec.end();
HttpUtil::TrimLWS(&last_byte_pos_begin, &last_byte_pos_end);
- ok &= base::StringToInt64(
- std::string(last_byte_pos_begin, last_byte_pos_end),
- last_byte_position);
+ ok &= base::StringToInt64(last_byte_pos_begin,
+ last_byte_pos_end,
+ last_byte_position);
if (!ok) {
*first_byte_position = *last_byte_position = -1;
return false;
@@ -1184,9 +1186,9 @@ bool HttpResponseHeaders::GetContentRange(int64* first_byte_position,
if (LowerCaseEqualsASCII(instance_length_begin, instance_length_end, "*")) {
return false;
- } else if (!base::StringToInt64(
- std::string(instance_length_begin, instance_length_end),
- instance_length)) {
+ } else if (!base::StringToInt64(instance_length_begin,
+ instance_length_end,
+ instance_length)) {
*instance_length = -1;
return false;
}
diff --git a/net/http/http_response_headers_unittest.cc b/net/http/http_response_headers_unittest.cc
index 18cd1c4..6986723 100644
--- a/net/http/http_response_headers_unittest.cc
+++ b/net/http/http_response_headers_unittest.cc
@@ -51,8 +51,8 @@ void TestCommon(const TestData& test) {
string expected_headers(test.expected_headers);
string headers;
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(raw_headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(raw_headers));
parsed->GetNormalizedHeaders(&headers);
// Transform to readable output format (so it's easier to see diffs).
@@ -281,7 +281,7 @@ TEST(HttpResponseHeadersTest, GetNormalizedHeader) {
"Cache-control: private\n"
"cache-Control: no-store\n";
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed = new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
std::string value;
EXPECT_TRUE(parsed->GetNormalizedHeader("cache-control", &value));
@@ -448,15 +448,15 @@ TEST(HttpResponseHeadersTest, Persist) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
std::string headers = tests[i].raw_headers;
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed1 =
- new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed1(
+ new HttpResponseHeaders(headers));
Pickle pickle;
parsed1->Persist(&pickle, tests[i].options);
void* iter = NULL;
- scoped_refptr<HttpResponseHeaders> parsed2 =
- new HttpResponseHeaders(pickle, &iter);
+ scoped_refptr<HttpResponseHeaders> parsed2(
+ new HttpResponseHeaders(pickle, &iter));
std::string h2;
parsed2->GetNormalizedHeaders(&h2);
@@ -472,7 +472,7 @@ TEST(HttpResponseHeadersTest, EnumerateHeader_Coalesced) {
"Cache-control:private , no-cache=\"set-cookie,server\" \n"
"cache-Control: no-store\n";
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed = new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
void* iter = NULL;
std::string value;
@@ -493,7 +493,7 @@ TEST(HttpResponseHeadersTest, EnumerateHeader_Challenge) {
"WWW-Authenticate:Digest realm=foobar, nonce=x, domain=y\n"
"WWW-Authenticate:Basic realm=quatar\n";
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed = new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
void* iter = NULL;
std::string value;
@@ -512,7 +512,7 @@ TEST(HttpResponseHeadersTest, EnumerateHeader_DateValued) {
"Date: Tue, 07 Aug 2007 23:10:55 GMT\n"
"Last-Modified: Wed, 01 Aug 2007 23:23:45 GMT\n";
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed = new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
std::string value;
EXPECT_TRUE(parsed->EnumerateHeader(NULL, "date", &value));
@@ -656,8 +656,8 @@ TEST(HttpResponseHeadersTest, GetMimeType) {
for (size_t i = 0; i < arraysize(tests); ++i) {
string headers(tests[i].raw_headers);
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(headers));
std::string value;
EXPECT_EQ(tests[i].has_mimetype, parsed->GetMimeType(&value));
@@ -807,8 +807,8 @@ TEST(HttpResponseHeadersTest, RequiresValidation) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string headers(tests[i].headers);
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(headers));
bool requires_validation =
parsed->RequiresValidation(request_time, response_time, current_time);
@@ -871,13 +871,13 @@ TEST(HttpResponseHeadersTest, Update) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string orig_headers(tests[i].orig_headers);
HeadersToRaw(&orig_headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(orig_headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(orig_headers));
string new_headers(tests[i].new_headers);
HeadersToRaw(&new_headers);
- scoped_refptr<HttpResponseHeaders> new_parsed =
- new HttpResponseHeaders(new_headers);
+ scoped_refptr<HttpResponseHeaders> new_parsed(
+ new HttpResponseHeaders(new_headers));
parsed->Update(*new_parsed);
@@ -917,8 +917,8 @@ TEST(HttpResponseHeadersTest, EnumerateHeaderLines) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string headers(tests[i].headers);
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(headers));
string name, value, lines;
@@ -1001,8 +1001,8 @@ TEST(HttpResponseHeadersTest, IsRedirect) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string headers(tests[i].headers);
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(headers));
std::string location;
EXPECT_EQ(parsed->IsRedirect(&location), tests[i].is_redirect);
@@ -1087,8 +1087,8 @@ TEST(HttpResponseHeadersTest, GetContentLength) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string headers(tests[i].headers);
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(headers));
EXPECT_EQ(tests[i].expected_len, parsed->GetContentLength());
}
@@ -1338,8 +1338,8 @@ TEST(HttpResponseHeaders, GetContentRange) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string headers(tests[i].headers);
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(headers));
int64 first_byte_position;
int64 last_byte_position;
@@ -1420,8 +1420,8 @@ TEST(HttpResponseHeadersTest, IsKeepAlive) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string headers(tests[i].headers);
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(headers));
EXPECT_EQ(tests[i].expected_keep_alive, parsed->IsKeepAlive());
}
@@ -1473,8 +1473,8 @@ TEST(HttpResponseHeadersTest, HasStrongValidators) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string headers(tests[i].headers);
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(headers));
EXPECT_EQ(tests[i].expected_result, parsed->HasStrongValidators()) <<
"Failed test case " << i;
@@ -1484,14 +1484,14 @@ TEST(HttpResponseHeadersTest, HasStrongValidators) {
TEST(HttpResponseHeadersTest, GetStatusText) {
std::string headers("HTTP/1.1 404 Not Found");
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed = new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
EXPECT_EQ(std::string("Not Found"), parsed->GetStatusText());
}
TEST(HttpResponseHeadersTest, GetStatusTextMissing) {
std::string headers("HTTP/1.1 404");
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed = new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
// Since the status line gets normalized, we have OK
EXPECT_EQ(std::string("OK"), parsed->GetStatusText());
}
@@ -1499,14 +1499,14 @@ TEST(HttpResponseHeadersTest, GetStatusTextMissing) {
TEST(HttpResponseHeadersTest, GetStatusTextMultiSpace) {
std::string headers("HTTP/1.0 404 Not Found");
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed = new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
EXPECT_EQ(std::string("Not Found"), parsed->GetStatusText());
}
TEST(HttpResponseHeadersTest, GetStatusBadStatusLine) {
std::string headers("Foo bar.");
HeadersToRaw(&headers);
- scoped_refptr<HttpResponseHeaders> parsed = new HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
// The bad status line would have gotten rewritten as
// HTTP/1.0 200 OK.
EXPECT_EQ(std::string("OK"), parsed->GetStatusText());
@@ -1545,8 +1545,8 @@ TEST(HttpResponseHeadersTest, AddHeader) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string orig_headers(tests[i].orig_headers);
HeadersToRaw(&orig_headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(orig_headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(orig_headers));
string new_header(tests[i].new_header);
parsed->AddHeader(new_header);
@@ -1590,8 +1590,8 @@ TEST(HttpResponseHeadersTest, RemoveHeader) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string orig_headers(tests[i].orig_headers);
HeadersToRaw(&orig_headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(orig_headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(orig_headers));
string name(tests[i].to_remove);
parsed->RemoveHeader(name);
@@ -1645,8 +1645,8 @@ TEST(HttpResponseHeadersTest, ReplaceStatus) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
string orig_headers(tests[i].orig_headers);
HeadersToRaw(&orig_headers);
- scoped_refptr<HttpResponseHeaders> parsed =
- new HttpResponseHeaders(orig_headers);
+ scoped_refptr<HttpResponseHeaders> parsed(
+ new HttpResponseHeaders(orig_headers));
string name(tests[i].new_status);
parsed->ReplaceStatusLine(name);
diff --git a/net/http/http_response_info.cc b/net/http/http_response_info.cc
index dc90d1f..00bfb92 100644
--- a/net/http/http_response_info.cc
+++ b/net/http/http_response_info.cc
@@ -182,6 +182,7 @@ void HttpResponseInfo::Persist(Pickle* pickle,
}
if (ssl_info.security_bits != -1)
flags |= RESPONSE_INFO_HAS_SECURITY_BITS;
+ // TODO(wtc): we should persist ssl_info.connection_status.
if (vary_data.is_valid())
flags |= RESPONSE_INFO_HAS_VARY_DATA;
if (response_truncated)
diff --git a/net/http/http_stream.h b/net/http/http_stream.h
index 5aa84e0..16f84cc 100644
--- a/net/http/http_stream.h
+++ b/net/http/http_stream.h
@@ -22,12 +22,13 @@
namespace net {
class BoundNetLog;
+class HttpRequestHeaders;
+struct HttpRequestInfo;
class HttpResponseInfo;
class IOBuffer;
class SSLCertRequestInfo;
class SSLInfo;
class UploadDataStream;
-struct HttpRequestInfo;
class HttpStream {
public:
@@ -45,7 +46,7 @@ class HttpStream {
// synchronously, in which case the result will be passed to the callback
// when available. Returns OK on success. The HttpStream takes ownership
// of the request_body.
- virtual int SendRequest(const std::string& request_headers,
+ virtual int SendRequest(const HttpRequestHeaders& request_headers,
UploadDataStream* request_body,
HttpResponseInfo* response,
CompletionCallback* callback) = 0;
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc
index 0e7610c..d3e4abd 100644
--- a/net/http/http_stream_parser.cc
+++ b/net/http/http_stream_parser.cc
@@ -53,7 +53,7 @@ int HttpStreamParser::SendRequest(const std::string& headers,
DCHECK(response);
response_ = response;
- scoped_refptr<StringIOBuffer> headers_io_buf = new StringIOBuffer(headers);
+ scoped_refptr<StringIOBuffer> headers_io_buf(new StringIOBuffer(headers));
request_headers_ = new DrainableIOBuffer(headers_io_buf,
headers_io_buf->size());
request_body_.reset(request_body);
@@ -510,13 +510,20 @@ int HttpStreamParser::DoParseResponseHeaders(int end_offset) {
void* it = NULL;
const std::string content_length_header("Content-Length");
- std::string ignored_header_value;
+ std::string content_length_value;
if (!headers->HasHeader("Transfer-Encoding") &&
headers->EnumerateHeader(
- &it, content_length_header, &ignored_header_value) &&
- headers->EnumerateHeader(
- &it, content_length_header, &ignored_header_value)) {
- return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH;
+ &it, content_length_header, &content_length_value)) {
+ // Ok, there's no Transfer-Encoding header and there's at least one
+ // Content-Length header. Check if there are any more Content-Length
+ // headers, and if so, make sure they have the same value. Otherwise, it's
+ // a possible response smuggling attack.
+ std::string content_length_value2;
+ while (headers->EnumerateHeader(
+ &it, content_length_header, &content_length_value2)) {
+ if (content_length_value != content_length_value2)
+ return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH;
+ }
}
response_->headers = headers;
diff --git a/net/http/http_stream_request.cc b/net/http/http_stream_request.cc
index 2409d86..71bbdda 100644
--- a/net/http/http_stream_request.cc
+++ b/net/http/http_stream_request.cc
@@ -21,7 +21,6 @@
#include "net/socket/client_socket_pool.h"
#include "net/socket/socks_client_socket_pool.h"
#include "net/socket/ssl_client_socket.h"
-#include "net/socket/ssl_client_socket.h"
#include "net/socket/ssl_client_socket_pool.h"
#include "net/socket/tcp_client_socket_pool.h"
#include "net/spdy/spdy_http_stream.h"
@@ -481,9 +480,9 @@ int HttpStreamRequest::DoInitConnection() {
} else {
ProxyServer proxy_server = proxy_info()->proxy_server();
proxy_host_port.reset(new HostPortPair(proxy_server.host_port_pair()));
- scoped_refptr<TCPSocketParams> proxy_tcp_params =
+ scoped_refptr<TCPSocketParams> proxy_tcp_params(
new TCPSocketParams(*proxy_host_port, request_info().priority,
- request_info().referrer, disable_resolver_cache);
+ request_info().referrer, disable_resolver_cache));
if (proxy_info()->is_http() || proxy_info()->is_https()) {
GURL authentication_url = request_info().url;
@@ -727,8 +726,12 @@ int HttpStreamRequest::DoCreateStream() {
if (connection_->socket() && !connection_->is_reused())
SetSocketMotivation();
+ const ProxyServer& proxy_server = proxy_info()->proxy_server();
+
if (!using_spdy_) {
- stream_.reset(new HttpBasicStream(connection_.release()));
+ bool using_proxy = (proxy_info()->is_http() || proxy_info()->is_https()) &&
+ request_info().url.SchemeIs("http");
+ stream_.reset(new HttpBasicStream(connection_.release(), using_proxy));
return OK;
}
@@ -738,7 +741,6 @@ int HttpStreamRequest::DoCreateStream() {
SpdySessionPool* spdy_pool = session_->spdy_session_pool();
scoped_refptr<SpdySession> spdy_session;
- const ProxyServer& proxy_server = proxy_info()->proxy_server();
HostPortProxyPair pair(endpoint_, proxy_server);
if (spdy_pool->HasSession(pair)) {
// We have a SPDY session to the origin server. This might be a direct
@@ -850,17 +852,17 @@ scoped_refptr<SSLSocketParams> HttpStreamRequest::GenerateSslParams(
if (request_info().load_flags & LOAD_VERIFY_EV_CERT)
ssl_config()->verify_ev_cert = true;
- if (proxy_info()->proxy_server().scheme() == ProxyServer::SCHEME_HTTP ||
- proxy_info()->proxy_server().scheme() == ProxyServer::SCHEME_HTTPS) {
- ssl_config()->mitm_proxies_allowed = true;
- }
+ if (proxy_info()->proxy_server().scheme() == ProxyServer::SCHEME_HTTP ||
+ proxy_info()->proxy_server().scheme() == ProxyServer::SCHEME_HTTPS) {
+ ssl_config()->mitm_proxies_allowed = true;
+ }
- scoped_refptr<SSLSocketParams> ssl_params =
+ scoped_refptr<SSLSocketParams> ssl_params(
new SSLSocketParams(tcp_params, socks_params, http_proxy_params,
proxy_scheme, hostname,
*ssl_config(), load_flags,
force_spdy_always_ && force_spdy_over_ssl_,
- want_spdy_over_npn);
+ want_spdy_over_npn));
return ssl_params;
}
diff --git a/net/http/http_transaction_unittest.cc b/net/http/http_transaction_unittest.cc
index 4d9daa5..518c1f8 100644
--- a/net/http/http_transaction_unittest.cc
+++ b/net/http/http_transaction_unittest.cc
@@ -147,7 +147,7 @@ int ReadTransaction(net::HttpTransaction* trans, std::string* result) {
std::string content;
do {
- scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(256);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
rv = trans->Read(buf, 256, &callback);
if (rv == net::ERR_IO_PENDING)
rv = callback.WaitForResult();
diff --git a/net/http/http_util.cc b/net/http/http_util.cc
index 5c7a4fc..a3d1ec5 100644
--- a/net/http/http_util.cc
+++ b/net/http/http_util.cc
@@ -292,7 +292,7 @@ bool HttpUtil::HasHeader(const std::string& headers, const char* name) {
headers.end(),
name,
name + name_len,
- CaseInsensitiveCompareASCII<char>());
+ base::CaseInsensitiveCompareASCII<char>());
if (it == headers.end())
return false;
@@ -828,12 +828,12 @@ bool HttpUtil::NameValuePairsIterator::GetNext() {
// Scan for the equals sign.
std::string::const_iterator equals = std::find(value_begin_, value_end_, '=');
if (equals == value_end_ || equals == value_begin_)
- return valid_ = false; // Malformed
+ return valid_ = false; // Malformed, no equals sign
// Verify that the equals sign we found wasn't inside of quote marks.
for (std::string::const_iterator it = value_begin_; it != equals; ++it) {
if (HttpUtil::IsQuote(*it))
- return valid_ = false; // Malformed
+ return valid_ = false; // Malformed, quote appears before equals sign
}
name_begin_ = value_begin_;
@@ -843,25 +843,28 @@ bool HttpUtil::NameValuePairsIterator::GetNext() {
TrimLWS(&name_begin_, &name_end_);
TrimLWS(&value_begin_, &value_end_);
value_is_quoted_ = false;
- if (value_begin_ != value_end_ && HttpUtil::IsQuote(*value_begin_)) {
+ unquoted_value_.clear();
+
+ if (value_begin_ == value_end_)
+ return valid_ = false; // Malformed, value is empty
+
+ if (HttpUtil::IsQuote(*value_begin_)) {
// Trim surrounding quotemarks off the value
- if (*value_begin_ != *(value_end_ - 1) || value_begin_ + 1 == value_end_)
+ if (*value_begin_ != *(value_end_ - 1) || value_begin_ + 1 == value_end_) {
// NOTE: This is not as graceful as it sounds:
// * quoted-pairs will no longer be unquoted
// (["\"hello] should give ["hello]).
// * Does not detect when the final quote is escaped
// (["value\"] should give [value"])
++value_begin_; // Gracefully recover from mismatching quotes.
- else
+ } else {
value_is_quoted_ = true;
+ // Do not store iterators into this. See declaration of unquoted_value_.
+ unquoted_value_ = HttpUtil::Unquote(value_begin_, value_end_);
+ }
}
return true;
}
-// If value() has quotemarks, unquote it.
-std::string HttpUtil::NameValuePairsIterator::unquoted_value() const {
- return HttpUtil::Unquote(value_begin_, value_end_);
-}
-
} // namespace net
diff --git a/net/http/http_util.h b/net/http/http_util.h
index f41c4e4..2f5bd85 100644
--- a/net/http/http_util.h
+++ b/net/http/http_util.h
@@ -275,6 +275,9 @@ class HttpUtil {
// Each pair consists of a token (the name), an equals sign, and either a
// token or quoted-string (the value). Arbitrary HTTP LWS is permitted outside
// of and between names, values, and delimiters.
+ //
+ // String iterators returned from this class' methods may be invalidated upon
+ // calls to GetNext() or after the NameValuePairsIterator is destroyed.
class NameValuePairsIterator {
public:
NameValuePairsIterator(std::string::const_iterator begin,
@@ -295,15 +298,16 @@ class HttpUtil {
std::string name() const { return std::string(name_begin_, name_end_); }
// The value of the current name-value pair.
- std::string::const_iterator value_begin() const { return value_begin_; }
- std::string::const_iterator value_end() const { return value_end_; }
- std::string value() const { return std::string(value_begin_, value_end_); }
-
- // If value() has quotemarks, unquote it.
- std::string unquoted_value() const;
-
- // True if the name-value pair's value has quote marks.
- bool value_is_quoted() const { return value_is_quoted_; }
+ std::string::const_iterator value_begin() const {
+ return value_is_quoted_ ? unquoted_value_.begin() : value_begin_;
+ }
+ std::string::const_iterator value_end() const {
+ return value_is_quoted_ ? unquoted_value_.end() : value_end_;
+ }
+ std::string value() const {
+ return value_is_quoted_ ? unquoted_value_ : std::string(value_begin_,
+ value_end_);
+ }
private:
HttpUtil::ValuesIterator props_;
@@ -318,6 +322,11 @@ class HttpUtil {
std::string::const_iterator value_begin_;
std::string::const_iterator value_end_;
+ // Do not store iterators into this string. The NameValuePairsIterator
+ // is copyable/assignable, and if copied the copy's iterators would point
+ // into the original's unquoted_value_ member.
+ std::string unquoted_value_;
+
bool value_is_quoted_;
};
};
diff --git a/net/http/http_util_unittest.cc b/net/http/http_util_unittest.cc
index 4ebbd2e..47242d2 100644
--- a/net/http/http_util_unittest.cc
+++ b/net/http/http_util_unittest.cc
@@ -673,27 +673,48 @@ TEST(HttpUtilTest, ParseRanges) {
}
namespace {
-
-void CheckNameValuePair(HttpUtil::NameValuePairsIterator* parser,
- bool expect_next,
- bool expect_valid,
- std::string expected_name,
- std::string expected_value,
- std::string expected_unquoted_value) {
- ASSERT_EQ(expect_next, parser->GetNext());
+void CheckCurrentNameValuePair(HttpUtil::NameValuePairsIterator* parser,
+ bool expect_valid,
+ std::string expected_name,
+ std::string expected_value) {
ASSERT_EQ(expect_valid, parser->valid());
- if (!expect_next || !expect_valid) {
+ if (!expect_valid) {
return;
}
+
+ // Let's make sure that these never change (i.e., when a quoted value is
+ // unquoted, it should be cached on the first calls and not regenerated
+ // later).
+ std::string::const_iterator first_value_begin = parser->value_begin();
+ std::string::const_iterator first_value_end = parser->value_end();
+
ASSERT_EQ(expected_name, std::string(parser->name_begin(),
parser->name_end()));
ASSERT_EQ(expected_name, parser->name());
ASSERT_EQ(expected_value, std::string(parser->value_begin(),
parser->value_end()));
ASSERT_EQ(expected_value, parser->value());
- ASSERT_EQ(expected_unquoted_value, parser->unquoted_value());
- ASSERT_EQ(expected_value != expected_unquoted_value,
- parser->value_is_quoted());
+
+ // Make sure they didn't/don't change.
+ ASSERT_TRUE(first_value_begin == parser->value_begin());
+ ASSERT_TRUE(first_value_end == parser->value_end());
+}
+
+void CheckNextNameValuePair(HttpUtil::NameValuePairsIterator* parser,
+ bool expect_next,
+ bool expect_valid,
+ std::string expected_name,
+ std::string expected_value) {
+ ASSERT_EQ(expect_next, parser->GetNext());
+ ASSERT_EQ(expect_valid, parser->valid());
+ if (!expect_next || !expect_valid) {
+ return;
+ }
+
+ CheckCurrentNameValuePair(parser,
+ expect_valid,
+ expected_name,
+ expected_value);
}
void CheckInvalidNameValuePair(std::string valid_part,
@@ -731,35 +752,78 @@ void CheckInvalidNameValuePair(std::string valid_part,
} // anonymous namespace
+TEST(HttpUtilTest, NameValuePairsIteratorCopyAndAssign) {
+ std::string data = "alpha='\\'a\\''; beta=\" b \"; cappa='c;'; delta=\"d\"";
+ HttpUtil::NameValuePairsIterator parser_a(data.begin(), data.end(), ';');
+
+ EXPECT_TRUE(parser_a.valid());
+ ASSERT_NO_FATAL_FAILURE(
+ CheckNextNameValuePair(&parser_a, true, true, "alpha", "'a'"));
+
+ HttpUtil::NameValuePairsIterator parser_b(parser_a);
+ // a and b now point to same location
+ ASSERT_NO_FATAL_FAILURE(
+ CheckCurrentNameValuePair(&parser_b, true, "alpha", "'a'"));
+ ASSERT_NO_FATAL_FAILURE(
+ CheckCurrentNameValuePair(&parser_a, true, "alpha", "'a'"));
+
+ // advance a, no effect on b
+ ASSERT_NO_FATAL_FAILURE(
+ CheckNextNameValuePair(&parser_a, true, true, "beta", " b "));
+ ASSERT_NO_FATAL_FAILURE(
+ CheckCurrentNameValuePair(&parser_b, true, "alpha", "'a'"));
+
+ // assign b the current state of a, no effect on a
+ parser_b = parser_a;
+ ASSERT_NO_FATAL_FAILURE(
+ CheckCurrentNameValuePair(&parser_b, true, "beta", " b "));
+ ASSERT_NO_FATAL_FAILURE(
+ CheckCurrentNameValuePair(&parser_a, true, "beta", " b "));
+
+ // advance b, no effect on a
+ ASSERT_NO_FATAL_FAILURE(
+ CheckNextNameValuePair(&parser_b, true, true, "cappa", "c;"));
+ ASSERT_NO_FATAL_FAILURE(
+ CheckCurrentNameValuePair(&parser_a, true, "beta", " b "));
+}
+
TEST(HttpUtilTest, NameValuePairsIteratorEmptyInput) {
std::string data = "";
HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';');
EXPECT_TRUE(parser.valid());
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, false, true, "", "", ""));
+ CheckNextNameValuePair(&parser, false, true, "", ""));
}
TEST(HttpUtilTest, NameValuePairsIterator) {
- std::string data = "alpha=1; beta= 2 ;cappa =' 3 ';"
- "delta= \" 4 \"; e= \" '5'\"; e=6";
+ std::string data = "alpha=1; beta= 2 ;cappa =' 3; ';"
+ "delta= \" \\\"4\\\" \"; e= \" '5'\"; e=6;"
+ "f='\\'\\h\\e\\l\\l\\o\\ \\w\\o\\r\\l\\d\\'';"
+ "g=''; h='hello'";
HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';');
EXPECT_TRUE(parser.valid());
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, true, true, "alpha", "1", "1"));
+ CheckNextNameValuePair(&parser, true, true, "alpha", "1"));
+ ASSERT_NO_FATAL_FAILURE(
+ CheckNextNameValuePair(&parser, true, true, "beta", "2"));
+ ASSERT_NO_FATAL_FAILURE(
+ CheckNextNameValuePair(&parser, true, true, "cappa", " 3; "));
+ ASSERT_NO_FATAL_FAILURE(
+ CheckNextNameValuePair(&parser, true, true, "delta", " \"4\" "));
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, true, true, "beta", "2", "2"));
+ CheckNextNameValuePair(&parser, true, true, "e", " '5'"));
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, true, true, "cappa", "' 3 '", " 3 "));
+ CheckNextNameValuePair(&parser, true, true, "e", "6"));
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, true, true, "delta", "\" 4 \"", " 4 "));
+ CheckNextNameValuePair(&parser, true, true, "f", "'hello world'"));
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, true, true, "e", "\" '5'\"", " '5'"));
+ CheckNextNameValuePair(&parser, true, true, "g", ""));
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, true, true, "e", "6", "6"));
+ CheckNextNameValuePair(&parser, true, true, "h", "hello"));
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, false, true, "", "", ""));
+ CheckNextNameValuePair(&parser, false, true, "", ""));
}
TEST(HttpUtilTest, NameValuePairsIteratorIllegalInputs) {
@@ -768,6 +832,9 @@ TEST(HttpUtilTest, NameValuePairsIteratorIllegalInputs) {
ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", "; 'beta'=2"));
ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("", "'beta'=2"));
+ ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", ";beta="));
+ ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1",
+ ";beta=;cappa=2"));
// According to the spec this is an error, but it doesn't seem appropriate to
// change our behaviour to be less permissive at this time.
@@ -783,13 +850,13 @@ TEST(HttpUtilTest, NameValuePairsIteratorExtraSeparators) {
EXPECT_TRUE(parser.valid());
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, true, true, "alpha", "1", "1"));
+ CheckNextNameValuePair(&parser, true, true, "alpha", "1"));
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, true, true, "beta", "2", "2"));
+ CheckNextNameValuePair(&parser, true, true, "beta", "2"));
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, true, true, "cappa", "3", "3"));
+ CheckNextNameValuePair(&parser, true, true, "cappa", "3"));
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, false, true, "", "", ""));
+ CheckNextNameValuePair(&parser, false, true, "", ""));
}
// See comments on the implementation of NameValuePairsIterator::GetNext
@@ -800,7 +867,7 @@ TEST(HttpUtilTest, NameValuePairsIteratorMissingEndQuote) {
EXPECT_TRUE(parser.valid());
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, true, true, "name", "value", "value"));
+ CheckNextNameValuePair(&parser, true, true, "name", "value"));
ASSERT_NO_FATAL_FAILURE(
- CheckNameValuePair(&parser, false, true, "", "", ""));
+ CheckNextNameValuePair(&parser, false, true, "", ""));
}