diff options
author | Andras Becsi <andras.becsi@digia.com> | 2014-03-18 13:16:26 +0100 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-03-20 15:55:39 +0100 |
commit | 3f0f86b0caed75241fa71c95a5d73bc0164348c5 (patch) | |
tree | 92b9fb00f2e9e90b0be2262093876d4f43b6cd13 /chromium/net/http | |
parent | e90d7c4b152c56919d963987e2503f9909a666d2 (diff) | |
download | qtwebengine-chromium-3f0f86b0caed75241fa71c95a5d73bc0164348c5.tar.gz |
Update to new stable branch 1750
This also includes an updated ninja and chromium dependencies
needed on Windows.
Change-Id: Icd597d80ed3fa4425933c9f1334c3c2e31291c42
Reviewed-by: Zoltan Arvai <zarvai@inf.u-szeged.hu>
Reviewed-by: Zeno Albisser <zeno.albisser@digia.com>
Diffstat (limited to 'chromium/net/http')
93 files changed, 3545 insertions, 1533 deletions
diff --git a/chromium/net/http/http_auth_cache.cc b/chromium/net/http/http_auth_cache.cc index 1c8c03fbb25..63bad076df1 100644 --- a/chromium/net/http/http_auth_cache.cc +++ b/chromium/net/http/http_auth_cache.cc @@ -43,7 +43,8 @@ bool IsEnclosingPath(const std::string& container, const std::string& path) { void CheckOriginIsValid(const GURL& origin) { DCHECK(origin.is_valid()); // Note that the scheme may be FTP when we're using a HTTP proxy. - DCHECK(origin.SchemeIsHTTPOrHTTPS() || origin.SchemeIs("ftp")); + DCHECK(origin.SchemeIsHTTPOrHTTPS() || origin.SchemeIs("ftp") || + origin.SchemeIsWSOrWSS()); DCHECK(origin.GetOrigin() == origin); } diff --git a/chromium/net/http/http_auth_gssapi_posix.cc b/chromium/net/http/http_auth_gssapi_posix.cc index 4d7bf074061..41cbcdbcdc0 100644 --- a/chromium/net/http/http_auth_gssapi_posix.cc +++ b/chromium/net/http/http_auth_gssapi_posix.cc @@ -715,7 +715,7 @@ HttpAuth::AuthorizationResult HttpAuthGSSAPI::ParseChallenge( } int HttpAuthGSSAPI::GenerateAuthToken(const AuthCredentials* credentials, - const std::wstring& spn, + const std::string& spn, std::string* auth_token) { DCHECK(auth_token); @@ -734,11 +734,7 @@ int HttpAuthGSSAPI::GenerateAuthToken(const AuthCredentials* credentials, std::string encode_input(static_cast<char*>(output_token.value), output_token.length); std::string encode_output; - bool base64_rv = base::Base64Encode(encode_input, &encode_output); - if (!base64_rv) { - LOG(ERROR) << "Base64 encoding of auth token failed."; - return ERR_ENCODING_CONVERSION_FAILED; - } + base::Base64Encode(encode_input, &encode_output); *auth_token = scheme_ + " " + encode_output; return OK; } @@ -837,12 +833,12 @@ int MapInitSecContextStatusToError(OM_uint32 major_status) { } -int HttpAuthGSSAPI::GetNextSecurityToken(const std::wstring& spn, +int HttpAuthGSSAPI::GetNextSecurityToken(const std::string& spn, gss_buffer_t in_token, gss_buffer_t out_token) { // Create a name for the principal // TODO(cbentzel): Just do this on the first pass? - std::string spn_principal = WideToASCII(spn); + std::string spn_principal = spn; gss_buffer_desc spn_buffer = GSS_C_EMPTY_BUFFER; spn_buffer.value = const_cast<char*>(spn_principal.c_str()); spn_buffer.length = spn_principal.size() + 1; diff --git a/chromium/net/http/http_auth_gssapi_posix.h b/chromium/net/http/http_auth_gssapi_posix.h index afa50a02c9f..db603f65da8 100644 --- a/chromium/net/http/http_auth_gssapi_posix.h +++ b/chromium/net/http/http_auth_gssapi_posix.h @@ -251,7 +251,7 @@ class NET_EXPORT_PRIVATE HttpAuthGSSAPI { // obtained using |*credentials|. If |credentials| is NULL, the default // credentials are used instead. int GenerateAuthToken(const AuthCredentials* credentials, - const std::wstring& spn, + const std::string& spn, std::string* auth_token); // Delegation is allowed on the Kerberos ticket. This allows certain servers @@ -260,7 +260,7 @@ class NET_EXPORT_PRIVATE HttpAuthGSSAPI { void Delegate(); private: - int GetNextSecurityToken(const std::wstring& spn, + int GetNextSecurityToken(const std::string& spn, gss_buffer_t in_token, gss_buffer_t out_token); diff --git a/chromium/net/http/http_auth_gssapi_posix_unittest.cc b/chromium/net/http/http_auth_gssapi_posix_unittest.cc index 1c3d12b6c29..48d17a3ad64 100644 --- a/chromium/net/http/http_auth_gssapi_posix_unittest.cc +++ b/chromium/net/http/http_auth_gssapi_posix_unittest.cc @@ -202,7 +202,7 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_TwoRounds) { // Generate an auth token and create another thing. EstablishInitialContext(&mock_library); std::string auth_token; - EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, L"HTTP/intranet.google.com", + EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, "HTTP/intranet.google.com", &auth_token)); std::string second_challenge_text = "Negotiate Zm9vYmFy"; @@ -239,7 +239,7 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_MissingTokenSecondRound) { EstablishInitialContext(&mock_library); std::string auth_token; - EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, L"HTTP/intranet.google.com", + EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, "HTTP/intranet.google.com", &auth_token)); std::string second_challenge_text = "Negotiate"; HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(), @@ -262,7 +262,7 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_NonBase64EncodedToken) { EstablishInitialContext(&mock_library); std::string auth_token; - EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, L"HTTP/intranet.google.com", + EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, "HTTP/intranet.google.com", &auth_token)); std::string second_challenge_text = "Negotiate =happyjoy="; HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(), diff --git a/chromium/net/http/http_auth_handler_basic.cc b/chromium/net/http/http_auth_handler_basic.cc index af5f188b156..e445c93100c 100644 --- a/chromium/net/http/http_auth_handler_basic.cc +++ b/chromium/net/http/http_auth_handler_basic.cc @@ -91,13 +91,9 @@ int HttpAuthHandlerBasic::GenerateAuthTokenImpl( DCHECK(credentials); // TODO(eroman): is this the right encoding of username/password? std::string base64_username_password; - if (!base::Base64Encode( - UTF16ToUTF8(credentials->username()) + ":" + - UTF16ToUTF8(credentials->password()), - &base64_username_password)) { - LOG(ERROR) << "Unexpected problem Base64 encoding."; - return ERR_UNEXPECTED; - } + base::Base64Encode(UTF16ToUTF8(credentials->username()) + ":" + + UTF16ToUTF8(credentials->password()), + &base64_username_password); *auth_token = "Basic " + base64_username_password; return OK; } diff --git a/chromium/net/http/http_auth_handler_digest.cc b/chromium/net/http/http_auth_handler_digest.cc index 904430ecb40..a8e301a02e8 100644 --- a/chromium/net/http/http_auth_handler_digest.cc +++ b/chromium/net/http/http_auth_handler_digest.cc @@ -18,6 +18,7 @@ #include "net/http/http_auth.h" #include "net/http/http_request_info.h" #include "net/http/http_util.h" +#include "url/gurl.h" namespace net { @@ -304,7 +305,7 @@ void HttpAuthHandlerDigest::GetRequestMethodAndPath( const GURL& url = request->url; if (target_ == HttpAuth::AUTH_PROXY && - (url.SchemeIs("https") || url.SchemeIs("ws") || url.SchemeIs("wss"))) { + (url.SchemeIs("https") || url.SchemeIsWSOrWSS())) { *method = "CONNECT"; *path = GetHostAndPort(url); } else { diff --git a/chromium/net/http/http_auth_handler_negotiate.cc b/chromium/net/http/http_auth_handler_negotiate.cc index 13b106925b7..788b06750b6 100644 --- a/chromium/net/http/http_auth_handler_negotiate.cc +++ b/chromium/net/http/http_auth_handler_negotiate.cc @@ -7,9 +7,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/logging.h" -#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" #include "net/base/address_family.h" #include "net/base/net_errors.h" #include "net/dns/host_resolver.h" @@ -114,7 +112,7 @@ HttpAuthHandlerNegotiate::HttpAuthHandlerNegotiate( HttpAuthHandlerNegotiate::~HttpAuthHandlerNegotiate() { } -std::wstring HttpAuthHandlerNegotiate::CreateSPN( +std::string HttpAuthHandlerNegotiate::CreateSPN( const AddressList& address_list, const GURL& origin) { // Kerberos Web Server SPNs are in the form HTTP/<host>:<port> through SSPI, // and in the form HTTP@<host>:<port> through GSSAPI @@ -155,11 +153,10 @@ std::wstring HttpAuthHandlerNegotiate::CreateSPN( static const char kSpnSeparator = '@'; #endif if (port != 80 && port != 443 && use_port_) { - return ASCIIToWide(base::StringPrintf("HTTP%c%s:%d", kSpnSeparator, - server.c_str(), port)); + return base::StringPrintf("HTTP%c%s:%d", kSpnSeparator, server.c_str(), + port); } else { - return ASCIIToWide(base::StringPrintf("HTTP%c%s", kSpnSeparator, - server.c_str())); + return base::StringPrintf("HTTP%c%s", kSpnSeparator, server.c_str()); } } diff --git a/chromium/net/http/http_auth_handler_negotiate.h b/chromium/net/http/http_auth_handler_negotiate.h index 6fd7aa9a068..d028178ed51 100644 --- a/chromium/net/http/http_auth_handler_negotiate.h +++ b/chromium/net/http/http_auth_handler_negotiate.h @@ -102,8 +102,8 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNegotiate : public HttpAuthHandler { virtual ~HttpAuthHandlerNegotiate(); // These are public for unit tests - std::wstring CreateSPN(const AddressList& address_list, const GURL& orign); - const std::wstring& spn() const { return spn_; } + std::string CreateSPN(const AddressList& address_list, const GURL& orign); + const std::string& spn() const { return spn_; } // HttpAuthHandler: virtual HttpAuth::AuthorizationResult HandleAnotherChallenge( @@ -152,7 +152,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNegotiate : public HttpAuthHandler { bool already_called_; bool has_credentials_; AuthCredentials credentials_; - std::wstring spn_; + std::string spn_; // Things which vary each round. CompletionCallback callback_; diff --git a/chromium/net/http/http_auth_handler_negotiate_unittest.cc b/chromium/net/http/http_auth_handler_negotiate_unittest.cc index 809f58e1fcc..64521a6177f 100644 --- a/chromium/net/http/http_auth_handler_negotiate_unittest.cc +++ b/chromium/net/http/http_auth_handler_negotiate_unittest.cc @@ -226,9 +226,9 @@ TEST_F(HttpAuthHandlerNegotiateTest, DisableCname) { EXPECT_EQ(OK, auth_handler->GenerateAuthToken(NULL, &request_info, callback.callback(), &token)); #if defined(OS_WIN) - EXPECT_EQ(L"HTTP/alias", auth_handler->spn()); + EXPECT_EQ("HTTP/alias", auth_handler->spn()); #elif defined(OS_POSIX) - EXPECT_EQ(L"HTTP@alias", auth_handler->spn()); + EXPECT_EQ("HTTP@alias", auth_handler->spn()); #endif } @@ -244,9 +244,9 @@ TEST_F(HttpAuthHandlerNegotiateTest, DisableCnameStandardPort) { EXPECT_EQ(OK, auth_handler->GenerateAuthToken(NULL, &request_info, callback.callback(), &token)); #if defined(OS_WIN) - EXPECT_EQ(L"HTTP/alias", auth_handler->spn()); + EXPECT_EQ("HTTP/alias", auth_handler->spn()); #elif defined(OS_POSIX) - EXPECT_EQ(L"HTTP@alias", auth_handler->spn()); + EXPECT_EQ("HTTP@alias", auth_handler->spn()); #endif } @@ -262,9 +262,9 @@ TEST_F(HttpAuthHandlerNegotiateTest, DisableCnameNonstandardPort) { EXPECT_EQ(OK, auth_handler->GenerateAuthToken(NULL, &request_info, callback.callback(), &token)); #if defined(OS_WIN) - EXPECT_EQ(L"HTTP/alias:500", auth_handler->spn()); + EXPECT_EQ("HTTP/alias:500", auth_handler->spn()); #elif defined(OS_POSIX) - EXPECT_EQ(L"HTTP@alias:500", auth_handler->spn()); + EXPECT_EQ("HTTP@alias:500", auth_handler->spn()); #endif } @@ -280,9 +280,9 @@ TEST_F(HttpAuthHandlerNegotiateTest, CnameSync) { EXPECT_EQ(OK, auth_handler->GenerateAuthToken(NULL, &request_info, callback.callback(), &token)); #if defined(OS_WIN) - EXPECT_EQ(L"HTTP/canonical.example.com", auth_handler->spn()); + EXPECT_EQ("HTTP/canonical.example.com", auth_handler->spn()); #elif defined(OS_POSIX) - EXPECT_EQ(L"HTTP@canonical.example.com", auth_handler->spn()); + EXPECT_EQ("HTTP@canonical.example.com", auth_handler->spn()); #endif } @@ -299,9 +299,9 @@ TEST_F(HttpAuthHandlerNegotiateTest, CnameAsync) { NULL, &request_info, callback.callback(), &token)); EXPECT_EQ(OK, callback.WaitForResult()); #if defined(OS_WIN) - EXPECT_EQ(L"HTTP/canonical.example.com", auth_handler->spn()); + EXPECT_EQ("HTTP/canonical.example.com", auth_handler->spn()); #elif defined(OS_POSIX) - EXPECT_EQ(L"HTTP@canonical.example.com", auth_handler->spn()); + EXPECT_EQ("HTTP@canonical.example.com", auth_handler->spn()); #endif } diff --git a/chromium/net/http/http_auth_handler_ntlm.cc b/chromium/net/http/http_auth_handler_ntlm.cc index 4c04234e22e..922800c71e1 100644 --- a/chromium/net/http/http_auth_handler_ntlm.cc +++ b/chromium/net/http/http_auth_handler_ntlm.cc @@ -89,13 +89,9 @@ int HttpAuthHandlerNTLM::GenerateAuthTokenImpl( // Base64 encode data in output buffer and prepend "NTLM ". std::string encode_input(static_cast<char*>(out_buf), out_buf_len); std::string encode_output; - bool base64_rv = base::Base64Encode(encode_input, &encode_output); + base::Base64Encode(encode_input, &encode_output); // OK, we are done with |out_buf| free(out_buf); - if (!base64_rv) { - LOG(ERROR) << "Unexpected problem Base64 encoding."; - return ERR_UNEXPECTED; - } *auth_token = std::string("NTLM ") + encode_output; return OK; #endif @@ -136,11 +132,11 @@ HttpAuth::AuthorizationResult HttpAuthHandlerNTLM::ParseChallenge( } // static -std::wstring HttpAuthHandlerNTLM::CreateSPN(const GURL& origin) { +std::string HttpAuthHandlerNTLM::CreateSPN(const GURL& origin) { // The service principal name of the destination server. See // http://msdn.microsoft.com/en-us/library/ms677949%28VS.85%29.aspx - std::wstring target(L"HTTP/"); - target.append(ASCIIToWide(GetHostAndPort(origin))); + std::string target("HTTP/"); + target.append(GetHostAndPort(origin)); return target; } diff --git a/chromium/net/http/http_auth_handler_ntlm.h b/chromium/net/http/http_auth_handler_ntlm.h index 971dd1fc06f..98bd362d543 100644 --- a/chromium/net/http/http_auth_handler_ntlm.h +++ b/chromium/net/http/http_auth_handler_ntlm.h @@ -145,7 +145,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNTLM : public HttpAuthHandler { uint32* out_token_len); // Create an NTLM SPN to identify the |origin| server. - static std::wstring CreateSPN(const GURL& origin); + static std::string CreateSPN(const GURL& origin); #if defined(NTLM_SSPI) HttpAuthSSPI auth_sspi_; diff --git a/chromium/net/http/http_auth_sspi_win.cc b/chromium/net/http/http_auth_sspi_win.cc index abc80508bd8..5718f9ef753 100644 --- a/chromium/net/http/http_auth_sspi_win.cc +++ b/chromium/net/http/http_auth_sspi_win.cc @@ -255,7 +255,7 @@ HttpAuth::AuthorizationResult HttpAuthSSPI::ParseChallenge( } int HttpAuthSSPI::GenerateAuthToken(const AuthCredentials* credentials, - const std::wstring& spn, + const std::string& spn, std::string* auth_token) { // Initial challenge. if (!SecIsValidHandle(&cred_)) { @@ -280,13 +280,9 @@ int HttpAuthSSPI::GenerateAuthToken(const AuthCredentials* credentials, // Base64 encode data in output buffer and prepend the scheme. std::string encode_input(static_cast<char*>(out_buf), out_buf_len); std::string encode_output; - bool base64_rv = base::Base64Encode(encode_input, &encode_output); + base::Base64Encode(encode_input, &encode_output); // OK, we are done with |out_buf| free(out_buf); - if (!base64_rv) { - LOG(ERROR) << "Base64 encoding of auth token failed."; - return ERR_ENCODING_CONVERSION_FAILED; - } *auth_token = scheme_ + " " + encode_output; return OK; } @@ -312,7 +308,7 @@ int HttpAuthSSPI::OnFirstRound(const AuthCredentials* credentials) { } int HttpAuthSSPI::GetNextSecurityToken( - const std::wstring& spn, + const std::string& spn, const void* in_token, int in_token_len, void** out_token, @@ -362,10 +358,11 @@ int HttpAuthSSPI::GetNextSecurityToken( // This returns a token that is passed to the remote server. DWORD context_attribute; + std::wstring spn_wide = base::ASCIIToWide(spn); SECURITY_STATUS status = library_->InitializeSecurityContext( &cred_, // phCredential ctxt_ptr, // phContext - const_cast<wchar_t *>(spn.c_str()), // pszTargetName + const_cast<wchar_t *>(spn_wide.c_str()), // pszTargetName context_flags, // fContextReq 0, // Reserved1 (must be 0) SECURITY_NATIVE_DREP, // TargetDataRep diff --git a/chromium/net/http/http_auth_sspi_win.h b/chromium/net/http/http_auth_sspi_win.h index 57a3daacfc5..bc7da46c312 100644 --- a/chromium/net/http/http_auth_sspi_win.h +++ b/chromium/net/http/http_auth_sspi_win.h @@ -144,7 +144,7 @@ class NET_EXPORT_PRIVATE HttpAuthSSPI { // obtained using |*credentials|. If |credentials| is NULL, the credentials // for the currently logged in user are used instead. int GenerateAuthToken(const AuthCredentials* credentials, - const std::wstring& spn, + const std::string& spn, std::string* auth_token); // Delegation is allowed on the Kerberos ticket. This allows certain servers @@ -156,7 +156,7 @@ class NET_EXPORT_PRIVATE HttpAuthSSPI { int OnFirstRound(const AuthCredentials* credentials); int GetNextSecurityToken( - const std::wstring& spn, + const std::string& spn, const void* in_token, int in_token_len, void** out_token, diff --git a/chromium/net/http/http_auth_sspi_win_unittest.cc b/chromium/net/http/http_auth_sspi_win_unittest.cc index d8521375900..09fe6fa25ef 100644 --- a/chromium/net/http/http_auth_sspi_win_unittest.cc +++ b/chromium/net/http/http_auth_sspi_win_unittest.cc @@ -82,7 +82,7 @@ TEST(HttpAuthSSPITest, ParseChallenge_TwoRounds) { // Generate an auth token and create another thing. std::string auth_token; - EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, L"HTTP/intranet.google.com", + EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, "HTTP/intranet.google.com", &auth_token)); std::string second_challenge_text = "Negotiate Zm9vYmFy"; @@ -118,7 +118,7 @@ TEST(HttpAuthSSPITest, ParseChallenge_MissingTokenSecondRound) { auth_sspi.ParseChallenge(&first_challenge)); std::string auth_token; - EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, L"HTTP/intranet.google.com", + EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, "HTTP/intranet.google.com", &auth_token)); std::string second_challenge_text = "Negotiate"; HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(), @@ -140,7 +140,7 @@ TEST(HttpAuthSSPITest, ParseChallenge_NonBase64EncodedToken) { auth_sspi.ParseChallenge(&first_challenge)); std::string auth_token; - EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, L"HTTP/intranet.google.com", + EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, "HTTP/intranet.google.com", &auth_token)); std::string second_challenge_text = "Negotiate =happyjoy="; HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(), diff --git a/chromium/net/http/http_basic_state.cc b/chromium/net/http/http_basic_state.cc new file mode 100644 index 00000000000..2b173b0897b --- /dev/null +++ b/chromium/net/http/http_basic_state.cc @@ -0,0 +1,68 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/http/http_basic_state.h" + +#include "base/basictypes.h" +#include "base/logging.h" +#include "net/base/io_buffer.h" +#include "net/http/http_request_info.h" +#include "net/http/http_response_body_drainer.h" +#include "net/http/http_stream_parser.h" +#include "net/http/http_util.h" +#include "net/socket/client_socket_handle.h" +#include "url/gurl.h" + +namespace net { + +HttpBasicState::HttpBasicState(ClientSocketHandle* connection, bool using_proxy) + : read_buf_(new GrowableIOBuffer()), + connection_(connection), + using_proxy_(using_proxy), + request_info_(NULL) {} + +HttpBasicState::~HttpBasicState() {} + +int HttpBasicState::Initialize(const HttpRequestInfo* request_info, + RequestPriority priority, + const BoundNetLog& net_log, + const CompletionCallback& callback) { + DCHECK(!parser_.get()); + request_info_ = request_info; + parser_.reset(new HttpStreamParser( + connection_.get(), request_info, read_buf_.get(), net_log)); + return OK; +} + +scoped_ptr<ClientSocketHandle> HttpBasicState::ReleaseConnection() { + return connection_.Pass(); +} + +scoped_refptr<GrowableIOBuffer> HttpBasicState::read_buf() const { + return read_buf_; +} + +void HttpBasicState::DeleteParser() { parser_.reset(); } + +std::string HttpBasicState::GenerateRequestLine() const { + static const char kSuffix[] = " HTTP/1.1\r\n"; + const size_t kSuffixLen = arraysize(kSuffix) - 1; + DCHECK(request_info_); + const GURL& url = request_info_->url; + const std::string path = using_proxy_ ? HttpUtil::SpecForRequest(url) + : HttpUtil::PathForRequest(url); + // Don't use StringPrintf for concatenation because it is very inefficient. + std::string request_line; + const size_t expected_size = request_info_->method.size() + 1 + path.size() + + kSuffixLen; + request_line.reserve(expected_size); + request_line.append(request_info_->method); + request_line.append(1, ' '); + request_line.append(path); + request_line.append(kSuffix, kSuffixLen); + DCHECK_EQ(expected_size, request_line.size()); + return request_line; +} + +} // namespace net diff --git a/chromium/net/http/http_basic_state.h b/chromium/net/http/http_basic_state.h new file mode 100644 index 00000000000..259c5022252 --- /dev/null +++ b/chromium/net/http/http_basic_state.h @@ -0,0 +1,72 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// A class that stores the common state between HttpBasicStream and +// WebSocketBasicHandshakeStream. + +#ifndef NET_HTTP_HTTP_BASIC_STATE_H_ +#define NET_HTTP_HTTP_BASIC_STATE_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "net/base/completion_callback.h" +#include "net/base/net_export.h" +#include "net/base/request_priority.h" + +namespace net { + +class BoundNetLog; +class ClientSocketHandle; +class GrowableIOBuffer; +class HttpStreamParser; +struct HttpRequestInfo; + +class NET_EXPORT_PRIVATE HttpBasicState { + public: + HttpBasicState(ClientSocketHandle* connection, bool using_proxy); + ~HttpBasicState(); + + // Initialize() must be called before using any of the other methods. + int Initialize(const HttpRequestInfo* request_info, + RequestPriority priority, + const BoundNetLog& net_log, + const CompletionCallback& callback); + + HttpStreamParser* parser() const { return parser_.get(); } + + bool using_proxy() const { return using_proxy_; } + + // Deletes |parser_| and sets it to NULL. + void DeleteParser(); + + ClientSocketHandle* connection() const { return connection_.get(); } + + scoped_ptr<ClientSocketHandle> ReleaseConnection(); + + scoped_refptr<GrowableIOBuffer> read_buf() const; + + // Generates a string of the form "METHOD PATH HTTP/1.1\r\n", based on the + // values of request_info_ and using_proxy_. + std::string GenerateRequestLine() const; + + private: + scoped_refptr<GrowableIOBuffer> read_buf_; + + scoped_ptr<HttpStreamParser> parser_; + + scoped_ptr<ClientSocketHandle> connection_; + + const bool using_proxy_; + + const HttpRequestInfo* request_info_; + + DISALLOW_COPY_AND_ASSIGN(HttpBasicState); +}; + +} // namespace net + +#endif // NET_HTTP_HTTP_BASIC_STATE_H_ diff --git a/chromium/net/http/http_basic_state_unittest.cc b/chromium/net/http/http_basic_state_unittest.cc new file mode 100644 index 00000000000..e95cfd26b59 --- /dev/null +++ b/chromium/net/http/http_basic_state_unittest.cc @@ -0,0 +1,78 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/http/http_basic_state.h" + +#include "net/base/completion_callback.h" +#include "net/base/request_priority.h" +#include "net/http/http_request_info.h" +#include "net/socket/client_socket_handle.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { +namespace { + +TEST(HttpBasicStateTest, ConstructsProperly) { + ClientSocketHandle* const handle = new ClientSocketHandle; + // Ownership of handle is passed to |state|. + const HttpBasicState state(handle, true); + EXPECT_EQ(handle, state.connection()); + EXPECT_TRUE(state.using_proxy()); +} + +TEST(HttpBasicStateTest, UsingProxyCanBeFalse) { + const HttpBasicState state(new ClientSocketHandle(), false); + EXPECT_FALSE(state.using_proxy()); +} + +TEST(HttpBasicStateTest, ReleaseConnectionWorks) { + ClientSocketHandle* const handle = new ClientSocketHandle; + HttpBasicState state(handle, false); + const scoped_ptr<ClientSocketHandle> released_connection( + state.ReleaseConnection()); + EXPECT_EQ(NULL, state.connection()); + EXPECT_EQ(handle, released_connection.get()); +} + +TEST(HttpBasicStateTest, InitializeWorks) { + HttpBasicState state(new ClientSocketHandle(), false); + const HttpRequestInfo request_info; + EXPECT_EQ(OK, + state.Initialize( + &request_info, LOW, BoundNetLog(), CompletionCallback())); + EXPECT_TRUE(state.parser()); +} + +TEST(HttpBasicStateTest, DeleteParser) { + HttpBasicState state(new ClientSocketHandle(), false); + const HttpRequestInfo request_info; + state.Initialize(&request_info, LOW, BoundNetLog(), CompletionCallback()); + EXPECT_TRUE(state.parser()); + state.DeleteParser(); + EXPECT_EQ(NULL, state.parser()); +} + +TEST(HttpBasicStateTest, GenerateRequestLineNoProxy) { + const bool use_proxy = false; + HttpBasicState state(new ClientSocketHandle(), use_proxy); + HttpRequestInfo request_info; + request_info.url = GURL("http://www.example.com/path?foo=bar#hoge"); + request_info.method = "PUT"; + state.Initialize(&request_info, LOW, BoundNetLog(), CompletionCallback()); + EXPECT_EQ("PUT /path?foo=bar HTTP/1.1\r\n", state.GenerateRequestLine()); +} + +TEST(HttpBasicStateTest, GenerateRequestLineWithProxy) { + const bool use_proxy = true; + HttpBasicState state(new ClientSocketHandle(), use_proxy); + HttpRequestInfo request_info; + request_info.url = GURL("http://www.example.com/path?foo=bar#hoge"); + request_info.method = "PUT"; + state.Initialize(&request_info, LOW, BoundNetLog(), CompletionCallback()); + EXPECT_EQ("PUT http://www.example.com/path?foo=bar HTTP/1.1\r\n", + state.GenerateRequestLine()); +} + +} // namespace +} // namespace net diff --git a/chromium/net/http/http_basic_stream.cc b/chromium/net/http/http_basic_stream.cc index c30e17d6203..87f6469ad61 100644 --- a/chromium/net/http/http_basic_stream.cc +++ b/chromium/net/http/http_basic_stream.cc @@ -4,122 +4,107 @@ #include "net/http/http_basic_stream.h" -#include "base/strings/stringprintf.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" -#include "net/http/http_request_headers.h" +#include "base/memory/scoped_ptr.h" #include "net/http/http_request_info.h" #include "net/http/http_response_body_drainer.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, - HttpStreamParser* parser, bool using_proxy) - : read_buf_(new GrowableIOBuffer()), - parser_(parser), - connection_(connection), - using_proxy_(using_proxy), - request_info_(NULL) { -} + : state_(connection, using_proxy) {} HttpBasicStream::~HttpBasicStream() {} -int HttpBasicStream::InitializeStream( - const HttpRequestInfo* request_info, - RequestPriority priority, - const BoundNetLog& net_log, - const CompletionCallback& callback) { - DCHECK(!parser_.get()); - request_info_ = request_info; - parser_.reset(new HttpStreamParser( - connection_.get(), request_info, read_buf_.get(), net_log)); +int HttpBasicStream::InitializeStream(const HttpRequestInfo* request_info, + RequestPriority priority, + const BoundNetLog& net_log, + const CompletionCallback& callback) { + state_.Initialize(request_info, priority, net_log, callback); return OK; } - int HttpBasicStream::SendRequest(const HttpRequestHeaders& headers, HttpResponseInfo* response, const CompletionCallback& callback) { - DCHECK(parser_.get()); - DCHECK(request_info_); - 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()); - return parser_->SendRequest(request_line_, headers, response, callback); + DCHECK(parser()); + return parser()->SendRequest( + state_.GenerateRequestLine(), headers, response, callback); } UploadProgress HttpBasicStream::GetUploadProgress() const { - return parser_->GetUploadProgress(); + return parser()->GetUploadProgress(); } int HttpBasicStream::ReadResponseHeaders(const CompletionCallback& callback) { - return parser_->ReadResponseHeaders(callback); + return parser()->ReadResponseHeaders(callback); } const HttpResponseInfo* HttpBasicStream::GetResponseInfo() const { - return parser_->GetResponseInfo(); + return parser()->GetResponseInfo(); } -int HttpBasicStream::ReadResponseBody(IOBuffer* buf, int buf_len, +int HttpBasicStream::ReadResponseBody(IOBuffer* buf, + int buf_len, const CompletionCallback& callback) { - return parser_->ReadResponseBody(buf, buf_len, callback); + return parser()->ReadResponseBody(buf, buf_len, callback); } void HttpBasicStream::Close(bool not_reusable) { - parser_->Close(not_reusable); + parser()->Close(not_reusable); } HttpStream* HttpBasicStream::RenewStreamForAuth() { DCHECK(IsResponseBodyComplete()); - DCHECK(!parser_->IsMoreDataBuffered()); - parser_.reset(); - return new HttpBasicStream(connection_.release(), NULL, using_proxy_); + DCHECK(!parser()->IsMoreDataBuffered()); + // The HttpStreamParser object still has a pointer to the connection. Just to + // be extra-sure it doesn't touch the connection again, delete it here rather + // than leaving it until the destructor is called. + state_.DeleteParser(); + return new HttpBasicStream(state_.ReleaseConnection().release(), + state_.using_proxy()); } bool HttpBasicStream::IsResponseBodyComplete() const { - return parser_->IsResponseBodyComplete(); + return parser()->IsResponseBodyComplete(); } bool HttpBasicStream::CanFindEndOfResponse() const { - return parser_->CanFindEndOfResponse(); + return parser()->CanFindEndOfResponse(); } bool HttpBasicStream::IsConnectionReused() const { - return parser_->IsConnectionReused(); + return parser()->IsConnectionReused(); } -void HttpBasicStream::SetConnectionReused() { - parser_->SetConnectionReused(); -} +void HttpBasicStream::SetConnectionReused() { parser()->SetConnectionReused(); } bool HttpBasicStream::IsConnectionReusable() const { - return parser_->IsConnectionReusable(); + return parser()->IsConnectionReusable(); +} + +int64 HttpBasicStream::GetTotalReceivedBytes() const { + return parser()->received_bytes(); } bool HttpBasicStream::GetLoadTimingInfo( LoadTimingInfo* load_timing_info) const { - return connection_->GetLoadTimingInfo(IsConnectionReused(), load_timing_info); + return state_.connection()->GetLoadTimingInfo(IsConnectionReused(), + load_timing_info); } void HttpBasicStream::GetSSLInfo(SSLInfo* ssl_info) { - parser_->GetSSLInfo(ssl_info); + parser()->GetSSLInfo(ssl_info); } void HttpBasicStream::GetSSLCertRequestInfo( SSLCertRequestInfo* cert_request_info) { - parser_->GetSSLCertRequestInfo(cert_request_info); + parser()->GetSSLCertRequestInfo(cert_request_info); } -bool HttpBasicStream::IsSpdyHttpStream() const { - return false; -} +bool HttpBasicStream::IsSpdyHttpStream() const { return false; } void HttpBasicStream::Drain(HttpNetworkSession* session) { HttpResponseBodyDrainer* drainer = new HttpResponseBodyDrainer(this); diff --git a/chromium/net/http/http_basic_stream.h b/chromium/net/http/http_basic_stream.h index 2057837e9a9..4a67ccaac00 100644 --- a/chromium/net/http/http_basic_stream.h +++ b/chromium/net/http/http_basic_stream.h @@ -12,13 +12,13 @@ #include <string> #include "base/basictypes.h" +#include "net/http/http_basic_state.h" #include "net/http/http_stream.h" namespace net { class BoundNetLog; class ClientSocketHandle; -class GrowableIOBuffer; class HttpResponseInfo; struct HttpRequestInfo; class HttpRequestHeaders; @@ -27,13 +27,9 @@ class IOBuffer; class HttpBasicStream : public HttpStream { public: - // Constructs a new HttpBasicStream. If |parser| is NULL, then - // InitializeStream should be called to initialize it correctly. If - // |parser| is non-null, then InitializeStream should not be called, - // as the stream is already initialized. - HttpBasicStream(ClientSocketHandle* connection, - HttpStreamParser* parser, - bool using_proxy); + // Constructs a new HttpBasicStream. InitializeStream must be called to + // initialize it correctly. + HttpBasicStream(ClientSocketHandle* connection, bool using_proxy); virtual ~HttpBasicStream(); // HttpStream methods: @@ -52,7 +48,8 @@ class HttpBasicStream : public HttpStream { virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE; - virtual int ReadResponseBody(IOBuffer* buf, int buf_len, + virtual int ReadResponseBody(IOBuffer* buf, + int buf_len, const CompletionCallback& callback) OVERRIDE; virtual void Close(bool not_reusable) OVERRIDE; @@ -69,6 +66,8 @@ class HttpBasicStream : public HttpStream { virtual bool IsConnectionReusable() const OVERRIDE; + virtual int64 GetTotalReceivedBytes() const OVERRIDE; + virtual bool GetLoadTimingInfo( LoadTimingInfo* load_timing_info) const OVERRIDE; @@ -84,17 +83,9 @@ class HttpBasicStream : public HttpStream { virtual void SetPriority(RequestPriority priority) OVERRIDE; private: - scoped_refptr<GrowableIOBuffer> read_buf_; - - scoped_ptr<HttpStreamParser> parser_; - - scoped_ptr<ClientSocketHandle> connection_; - - bool using_proxy_; - - std::string request_line_; + HttpStreamParser* parser() const { return state_.parser(); } - const HttpRequestInfo* request_info_; + HttpBasicState state_; DISALLOW_COPY_AND_ASSIGN(HttpBasicStream); }; diff --git a/chromium/net/http/http_byte_range.cc b/chromium/net/http/http_byte_range.cc index 60683c5584f..b43cb2e8008 100644 --- a/chromium/net/http/http_byte_range.cc +++ b/chromium/net/http/http_byte_range.cc @@ -4,6 +4,9 @@ #include <algorithm> +#include "base/format_macros.h" +#include "base/logging.h" +#include "base/strings/stringprintf.h" #include "net/http/http_byte_range.h" namespace { @@ -21,6 +24,29 @@ HttpByteRange::HttpByteRange() has_computed_bounds_(false) { } +// static +HttpByteRange HttpByteRange::Bounded(int64 first_byte_position, + int64 last_byte_position) { + HttpByteRange range; + range.set_first_byte_position(first_byte_position); + range.set_last_byte_position(last_byte_position); + return range; +} + +// static +HttpByteRange HttpByteRange::RightUnbounded(int64 first_byte_position) { + HttpByteRange range; + range.set_first_byte_position(first_byte_position); + return range; +} + +// static +HttpByteRange HttpByteRange::Suffix(int64 suffix_length) { + HttpByteRange range; + range.set_suffix_length(suffix_length); + return range; +} + bool HttpByteRange::IsSuffixByteRange() const { return suffix_length_ != kPositionNotSpecified; } @@ -41,6 +67,21 @@ bool HttpByteRange::IsValid() const { last_byte_position_ >= first_byte_position_)); } +std::string HttpByteRange::GetHeaderValue() const { + DCHECK(IsValid()); + + if (IsSuffixByteRange()) + return base::StringPrintf("bytes=-%" PRId64, suffix_length()); + + DCHECK(HasFirstBytePosition()); + + if (!HasLastBytePosition()) + return base::StringPrintf("bytes=%" PRId64 "-", first_byte_position()); + + return base::StringPrintf("bytes=%" PRId64 "-%" PRId64, + first_byte_position(), last_byte_position()); +} + bool HttpByteRange::ComputeBounds(int64 size) { if (size < 0) return false; diff --git a/chromium/net/http/http_byte_range.h b/chromium/net/http/http_byte_range.h index 2c06434439d..98708721a4f 100644 --- a/chromium/net/http/http_byte_range.h +++ b/chromium/net/http/http_byte_range.h @@ -5,6 +5,8 @@ #ifndef NET_HTTP_HTTP_BYTE_RANGE_H_ #define NET_HTTP_HTTP_BYTE_RANGE_H_ +#include <string> + #include "base/basictypes.h" #include "net/base/net_export.h" @@ -17,10 +19,16 @@ class NET_EXPORT HttpByteRange { public: HttpByteRange(); + // Convenience constructors. + static HttpByteRange Bounded(int64 first_byte_position, + int64 last_byte_position); + static HttpByteRange RightUnbounded(int64 first_byte_position); + static HttpByteRange Suffix(int64 suffix_length); + // Since this class is POD, we use constructor, assignment operator // and destructor provided by compiler. int64 first_byte_position() const { return first_byte_position_; } - void set_first_byte_position(int64 value) { first_byte_position_ = value; } + void set_first_byte_position(int64 value) { first_byte_position_ = value; } int64 last_byte_position() const { return last_byte_position_; } void set_last_byte_position(int64 value) { last_byte_position_ = value; } @@ -38,6 +46,10 @@ class NET_EXPORT HttpByteRange { // Returns true if this range is valid. bool IsValid() const; + // Gets the header string, e.g. "bytes=0-100", "bytes=100-", "bytes=-100". + // Assumes range is valid. + std::string GetHeaderValue() const; + // A method that when given the size in bytes of a file, adjust the internal // |first_byte_position_| and |last_byte_position_| values according to the // range specified by this object. If the range specified is invalid with diff --git a/chromium/net/http/http_byte_range_unittest.cc b/chromium/net/http/http_byte_range_unittest.cc index 6629a7c3c59..5dc6e5237f3 100644 --- a/chromium/net/http/http_byte_range_unittest.cc +++ b/chromium/net/http/http_byte_range_unittest.cc @@ -76,3 +76,17 @@ TEST(HttpByteRangeTest, SetInstanceSize) { } } } + +TEST(HttpByteRangeTest, GetHeaderValue) { + static const struct { + net::HttpByteRange range; + const char* expected; + } tests[] = {{net::HttpByteRange::Bounded(0, 0), "bytes=0-0"}, + {net::HttpByteRange::Bounded(0, 100), "bytes=0-100"}, + {net::HttpByteRange::Bounded(0, -1), "bytes=0-"}, + {net::HttpByteRange::RightUnbounded(100), "bytes=100-"}, + {net::HttpByteRange::Suffix(100), "bytes=-100"}, }; + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + EXPECT_EQ(tests[i].expected, tests[i].range.GetHeaderValue()); + } +} diff --git a/chromium/net/http/http_cache_transaction.cc b/chromium/net/http/http_cache_transaction.cc index 83efcb135cd..88fb53a69c4 100644 --- a/chromium/net/http/http_cache_transaction.cc +++ b/chromium/net/http/http_cache_transaction.cc @@ -101,6 +101,23 @@ void RecordOfflineStatus(int load_flags, RequestOfflineStatus status) { } } +// TODO(rvargas): Remove once we get the data. +void RecordVaryHeaderHistogram(const net::HttpResponseInfo* response) { + enum VaryType { + VARY_NOT_PRESENT, + VARY_UA, + VARY_OTHER, + VARY_MAX + }; + VaryType vary = VARY_NOT_PRESENT; + if (response->vary_data.is_valid()) { + vary = VARY_OTHER; + if (response->headers->HasHeaderValue("vary", "user-agent")) + vary = VARY_UA; + } + UMA_HISTOGRAM_ENUMERATION("HttpCache.Vary", vary, VARY_MAX); +} + } // namespace namespace net { @@ -196,7 +213,8 @@ HttpCache::Transaction::Transaction( io_callback_(base::Bind(&Transaction::OnIOComplete, weak_factory_.GetWeakPtr())), transaction_pattern_(PATTERN_UNDEFINED), - transaction_delegate_(transaction_delegate) { + transaction_delegate_(transaction_delegate), + websocket_handshake_stream_base_create_helper_(NULL) { COMPILE_ASSERT(HttpCache::Transaction::kNumValidationHeaders == arraysize(kValidationHeaders), Invalid_number_of_validation_headers); @@ -516,6 +534,13 @@ void HttpCache::Transaction::SetPriority(RequestPriority priority) { network_trans_->SetPriority(priority_); } +void HttpCache::Transaction::SetWebSocketHandshakeStreamCreateHelper( + WebSocketHandshakeStreamBase::CreateHelper* create_helper) { + websocket_handshake_stream_base_create_helper_ = create_helper; + if (network_trans_) + network_trans_->SetWebSocketHandshakeStreamCreateHelper(create_helper); +} + //----------------------------------------------------------------------------- void HttpCache::Transaction::DoCallback(int rv) { @@ -843,6 +868,10 @@ int HttpCache::Transaction::DoSendRequest() { // Old load timing information, if any, is now obsolete. old_network_trans_load_timing_.reset(); + if (websocket_handshake_stream_base_create_helper_) + network_trans_->SetWebSocketHandshakeStreamCreateHelper( + websocket_handshake_stream_base_create_helper_); + ReportNetworkActionStart(); next_state_ = STATE_SEND_REQUEST_COMPLETE; rv = network_trans_->Start(request_, io_callback_, net_log_); @@ -963,6 +992,8 @@ int HttpCache::Transaction::DoSuccessfulSendRequest() { cache_->DoomMainEntryForUrl(request_->url); } + RecordVaryHeaderHistogram(new_response); + // Are we expecting a response to a conditional query? if (mode_ == READ_WRITE || mode_ == UPDATE) { if (new_response->headers->response_code() == 304 || handling_206_) { @@ -1499,20 +1530,12 @@ int HttpCache::Transaction::DoCacheQueryData() { } int HttpCache::Transaction::DoCacheQueryDataComplete(int result) { -#if defined(OS_ANDROID) if (result == ERR_NOT_IMPLEMENTED) { // Restart the request overwriting the cache entry. - // - // Note: this would have fixed range requests for debug builds on all OSes, - // not just Android, but karen@ prefers to limit the effect based on OS for - // cherry-picked fixes. - // TODO(pasko): remove the OS_ANDROID limitation as soon as the fix proves - // useful after the cherry-pick. // TODO(pasko): remove this workaround as soon as the SimpleBackendImpl // supports Sparse IO. return DoRestartPartialRequest(); } -#endif DCHECK_EQ(OK, result); if (!cache_.get()) return ERR_UNEXPECTED; @@ -2388,6 +2411,8 @@ bool HttpCache::Transaction::CanResume(bool has_data) { if (request_->method != "GET") return false; + // Note that if this is a 206, content-length was already fixed after calling + // PartialData::ResponseHeadersOK(). if (response_.headers->GetContentLength() <= 0 || response_.headers->HasHeaderValue("Accept-Ranges", "none") || !response_.headers->HasStrongValidators()) { diff --git a/chromium/net/http/http_cache_transaction.h b/chromium/net/http/http_cache_transaction.h index b1f32bd820d..90c4db5a39c 100644 --- a/chromium/net/http/http_cache_transaction.h +++ b/chromium/net/http/http_cache_transaction.h @@ -130,6 +130,8 @@ class HttpCache::Transaction : public HttpTransaction { virtual bool GetLoadTimingInfo( LoadTimingInfo* load_timing_info) const OVERRIDE; virtual void SetPriority(RequestPriority priority) OVERRIDE; + virtual void SetWebSocketHandshakeStreamCreateHelper( + net::WebSocketHandshakeStreamBase::CreateHelper* create_helper) OVERRIDE; private: static const size_t kNumValidationHeaders = 2; @@ -433,6 +435,15 @@ class HttpCache::Transaction : public HttpTransaction { // 304 and 206 response cases, as the network transaction may be destroyed // before the caller requests load timing information. scoped_ptr<LoadTimingInfo> old_network_trans_load_timing_; + + // The helper object to use to create WebSocketHandshakeStreamBase + // objects. Only relevant when establishing a WebSocket connection. + // This is passed to the underlying network transaction. It is stored here in + // case the transaction does not exist yet. + WebSocketHandshakeStreamBase::CreateHelper* + websocket_handshake_stream_base_create_helper_; + + DISALLOW_COPY_AND_ASSIGN(Transaction); }; } // namespace net diff --git a/chromium/net/http/http_cache_unittest.cc b/chromium/net/http/http_cache_unittest.cc index e47852c01ac..aa6056a4177 100644 --- a/chromium/net/http/http_cache_unittest.cc +++ b/chromium/net/http/http_cache_unittest.cc @@ -31,7 +31,9 @@ #include "net/http/http_transaction_unittest.h" #include "net/http/http_util.h" #include "net/http/mock_http_cache.h" +#include "net/socket/client_socket_handle.h" #include "net/ssl/ssl_cert_request_info.h" +#include "net/websockets/websocket_handshake_stream_base.h" #include "testing/gtest/include/gtest/gtest.h" using base::Time; @@ -574,6 +576,21 @@ struct Context { scoped_ptr<net::HttpTransaction> trans; }; +class FakeWebSocketHandshakeStreamCreateHelper + : public net::WebSocketHandshakeStreamBase::CreateHelper { + public: + virtual ~FakeWebSocketHandshakeStreamCreateHelper() {} + virtual net::WebSocketHandshakeStreamBase* CreateBasicStream( + scoped_ptr<net::ClientSocketHandle> connect, bool using_proxy) OVERRIDE { + return NULL; + } + virtual net::WebSocketHandshakeStreamBase* CreateSpdyStream( + const base::WeakPtr<net::SpdySession>& session, + bool use_relative_url) OVERRIDE { + return NULL; + } +}; + } // namespace @@ -2785,7 +2802,7 @@ TEST(HttpCache, SimplePOST_LoadOnlyFromCache_Hit) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(&element_readers, kUploadId); + net::UploadDataStream upload_data_stream(element_readers.Pass(), kUploadId); MockHttpRequest request(transaction); request.upload_data_stream = &upload_data_stream; @@ -2816,7 +2833,7 @@ TEST(HttpCache, SimplePOST_WithRanges) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(&element_readers, kUploadId); + net::UploadDataStream upload_data_stream(element_readers.Pass(), kUploadId); MockHttpRequest request(transaction); request.upload_data_stream = &upload_data_stream; @@ -2835,7 +2852,7 @@ TEST(HttpCache, SimplePOST_SeparateCache) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(&element_readers, 1); + net::UploadDataStream upload_data_stream(element_readers.Pass(), 1); MockTransaction transaction(kSimplePOST_Transaction); MockHttpRequest req1(transaction); @@ -2874,7 +2891,7 @@ TEST(HttpCache, SimplePOST_Invalidate_205) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(&element_readers, 1); + net::UploadDataStream upload_data_stream(element_readers.Pass(), 1); transaction.method = "POST"; transaction.status = "HTTP/1.1 205 No Content"; @@ -2913,7 +2930,7 @@ TEST(HttpCache, SimplePOST_NoUploadId_Invalidate_205) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(&element_readers, 0); + net::UploadDataStream upload_data_stream(element_readers.Pass(), 0); transaction.method = "POST"; transaction.status = "HTTP/1.1 205 No Content"; @@ -2944,7 +2961,7 @@ TEST(HttpCache, SimplePOST_NoUploadId_NoBackend) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(&element_readers, 0); + net::UploadDataStream upload_data_stream(element_readers.Pass(), 0); MockTransaction transaction(kSimplePOST_Transaction); AddMockTransaction(&transaction); @@ -2973,7 +2990,7 @@ TEST(HttpCache, SimplePOST_DontInvalidate_100) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(&element_readers, 1); + net::UploadDataStream upload_data_stream(element_readers.Pass(), 1); transaction.method = "POST"; transaction.status = "HTTP/1.1 100 Continue"; @@ -3003,7 +3020,7 @@ TEST(HttpCache, SimplePUT_Miss) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(&element_readers, 0); + net::UploadDataStream upload_data_stream(element_readers.Pass(), 0); MockHttpRequest request(transaction); request.upload_data_stream = &upload_data_stream; @@ -3032,7 +3049,7 @@ TEST(HttpCache, SimplePUT_Invalidate) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(&element_readers, 0); + net::UploadDataStream upload_data_stream(element_readers.Pass(), 0); transaction.method = "PUT"; MockHttpRequest req2(transaction); @@ -3068,7 +3085,7 @@ TEST(HttpCache, SimplePUT_Invalidate_305) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(&element_readers, 0); + net::UploadDataStream upload_data_stream(element_readers.Pass(), 0); transaction.method = "PUT"; transaction.status = "HTTP/1.1 305 Use Proxy"; @@ -3106,7 +3123,7 @@ TEST(HttpCache, SimplePUT_DontInvalidate_404) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(&element_readers, 0); + net::UploadDataStream upload_data_stream(element_readers.Pass(), 0); transaction.method = "PUT"; transaction.status = "HTTP/1.1 404 Not Found"; @@ -3136,7 +3153,7 @@ TEST(HttpCache, SimpleDELETE_Miss) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(&element_readers, 0); + net::UploadDataStream upload_data_stream(element_readers.Pass(), 0); MockHttpRequest request(transaction); request.upload_data_stream = &upload_data_stream; @@ -3165,7 +3182,7 @@ TEST(HttpCache, SimpleDELETE_Invalidate) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(&element_readers, 0); + net::UploadDataStream upload_data_stream(element_readers.Pass(), 0); transaction.method = "DELETE"; MockHttpRequest req2(transaction); @@ -3395,6 +3412,37 @@ TEST(HttpCache, RangeGET_NoStrongValidators) { RemoveMockTransaction(&transaction); } +// Tests that we cache partial responses that lack content-length. +TEST(HttpCache, RangeGET_NoContentLength) { + MockHttpCache cache; + std::string headers; + + // Attempt to write to the cache (40-49). + MockTransaction transaction(kRangeGET_TransactionOK); + AddMockTransaction(&transaction); + transaction.response_headers = "ETag: \"foo\"\n" + "Accept-Ranges: bytes\n" + "Content-Range: bytes 40-49/80\n"; + transaction.handler = NULL; + RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); + + EXPECT_EQ(1, cache.network_layer()->transaction_count()); + EXPECT_EQ(0, cache.disk_cache()->open_count()); + EXPECT_EQ(1, cache.disk_cache()->create_count()); + + // Now verify that there's no cached data. + transaction.handler = &RangeTransactionServer::RangeHandler; + RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK, + &headers); + + Verify206Response(headers, 40, 49); + EXPECT_EQ(2, cache.network_layer()->transaction_count()); + EXPECT_EQ(1, cache.disk_cache()->open_count()); + EXPECT_EQ(1, cache.disk_cache()->create_count()); + + RemoveMockTransaction(&transaction); +} + // Tests that we can cache range requests and fetch random blocks from the // cache and the network. TEST(HttpCache, RangeGET_OK) { @@ -3455,8 +3503,6 @@ TEST(HttpCache, RangeGET_OK) { RemoveMockTransaction(&kRangeGET_TransactionOK); } -#if defined(OS_ANDROID) - // Checks that with a cache backend having Sparse IO unimplementes the cache // entry would be doomed after a range request. // TODO(pasko): remove when the SimpleBackendImpl implements Sparse IO. @@ -3529,8 +3575,6 @@ TEST(HttpCache, RangeGET_SparseNotImplementedOnEmptyCache) { RemoveMockTransaction(&transaction); } -#endif // OS_ANDROID - // Tests that we can cache range requests and fetch random blocks from the // cache and the network, with synchronous responses. TEST(HttpCache, RangeGET_SyncOK) { @@ -6271,6 +6315,35 @@ TEST(HttpCache, SetPriority) { EXPECT_EQ(net::OK, callback.WaitForResult()); } +// Make sure that calling SetWebSocketHandshakeStreamCreateHelper on a cache +// transaction passes on its argument to the underlying network transaction. +TEST(HttpCache, SetWebSocketHandshakeStreamCreateHelper) { + MockHttpCache cache; + + FakeWebSocketHandshakeStreamCreateHelper create_helper; + scoped_ptr<net::HttpTransaction> trans; + EXPECT_EQ(net::OK, cache.http_cache()->CreateTransaction( + net::IDLE, &trans, NULL)); + ASSERT_TRUE(trans.get()); + + EXPECT_FALSE(cache.network_layer()->last_transaction()); + + net::HttpRequestInfo info; + info.url = GURL(kSimpleGET_Transaction.url); + net::TestCompletionCallback callback; + EXPECT_EQ(net::ERR_IO_PENDING, + trans->Start(&info, callback.callback(), net::BoundNetLog())); + + ASSERT_TRUE(cache.network_layer()->last_transaction()); + EXPECT_FALSE(cache.network_layer()->last_transaction()-> + websocket_handshake_stream_create_helper()); + trans->SetWebSocketHandshakeStreamCreateHelper(&create_helper); + EXPECT_EQ(&create_helper, + cache.network_layer()->last_transaction()-> + websocket_handshake_stream_create_helper()); + EXPECT_EQ(net::OK, callback.WaitForResult()); +} + // Make sure that a cache transaction passes on its priority to // newly-created network transactions. TEST(HttpCache, SetPriorityNewTransaction) { diff --git a/chromium/net/http/http_chunked_decoder.cc b/chromium/net/http/http_chunked_decoder.cc index ca07f24de06..0d8be9f7cd2 100644 --- a/chromium/net/http/http_chunked_decoder.cc +++ b/chromium/net/http/http_chunked_decoder.cc @@ -44,6 +44,8 @@ #include "net/http/http_chunked_decoder.h" +#include <algorithm> + #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" diff --git a/chromium/net/http/http_network_layer.cc b/chromium/net/http/http_network_layer.cc index e4d082eb0fd..7d3f1588006 100644 --- a/chromium/net/http/http_network_layer.cc +++ b/chromium/net/http/http_network_layer.cc @@ -5,6 +5,7 @@ #include "net/http/http_network_layer.h" #include "base/logging.h" +#include "base/power_monitor/power_monitor.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" @@ -23,9 +24,19 @@ HttpNetworkLayer::HttpNetworkLayer(HttpNetworkSession* session) : session_(session), suspended_(false) { DCHECK(session_.get()); +#if defined(OS_WIN) + base::PowerMonitor* power_monitor = base::PowerMonitor::Get(); + if (power_monitor) + power_monitor->AddObserver(this); +#endif } HttpNetworkLayer::~HttpNetworkLayer() { +#if defined(OS_WIN) + base::PowerMonitor* power_monitor = base::PowerMonitor::Get(); + if (power_monitor) + power_monitor->RemoveObserver(this); +#endif } //----------------------------------------------------------------------------- @@ -42,7 +53,7 @@ HttpTransactionFactory* HttpNetworkLayer::CreateFactory( void HttpNetworkLayer::ForceAlternateProtocol() { PortAlternateProtocolPair pair; pair.port = 443; - pair.protocol = NPN_SPDY_2; + pair.protocol = NPN_SPDY_3; HttpServerPropertiesImpl::ForceAlternateProtocol(pair); } diff --git a/chromium/net/http/http_network_layer.h b/chromium/net/http/http_network_layer.h index 4b41b7190e8..c4c41aec43e 100644 --- a/chromium/net/http/http_network_layer.h +++ b/chromium/net/http/http_network_layer.h @@ -7,6 +7,8 @@ #include <string> +#include "base/basictypes.h" +#include "base/compiler_specific.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/power_monitor/power_observer.h" @@ -36,7 +38,7 @@ class NET_EXPORT HttpNetworkLayer // when network session is shared. static HttpTransactionFactory* CreateFactory(HttpNetworkSession* session); - // Forces an alternate protocol of SPDY/2 on port 443. + // Forces an alternate protocol of SPDY/3 on port 443. // TODO(rch): eliminate this method. static void ForceAlternateProtocol(); @@ -54,6 +56,8 @@ class NET_EXPORT HttpNetworkLayer private: const scoped_refptr<HttpNetworkSession> session_; bool suspended_; + + DISALLOW_COPY_AND_ASSIGN(HttpNetworkLayer); }; } // namespace net diff --git a/chromium/net/http/http_network_layer_unittest.cc b/chromium/net/http/http_network_layer_unittest.cc index 6d2ea358071..98b8d4eaf44 100644 --- a/chromium/net/http/http_network_layer_unittest.cc +++ b/chromium/net/http/http_network_layer_unittest.cc @@ -4,6 +4,7 @@ #include "net/http/http_network_layer.h" +#include "base/basictypes.h" #include "base/strings/stringprintf.h" #include "net/base/net_log.h" #include "net/cert/mock_cert_verifier.h" @@ -48,14 +49,27 @@ class HttpNetworkLayerTest : public PlatformTest { factory_.reset(new HttpNetworkLayer(network_session_.get())); } - void ExecuteRequestExpectingContentAndHeader(const std::string& content, +#if defined(SPDY_PROXY_AUTH_ORIGIN) + std::string GetChromeProxy() { + return HostPortPair::FromURL(GURL(SPDY_PROXY_AUTH_ORIGIN)).ToString(); + } +#endif + +#if defined(SPDY_PROXY_AUTH_ORIGIN) && defined(DATA_REDUCTION_FALLBACK_HOST) + std::string GetChromeFallbackProxy() { + return HostPortPair::FromURL(GURL(DATA_REDUCTION_FALLBACK_HOST)).ToString(); + } +#endif + + void ExecuteRequestExpectingContentAndHeader(const std::string& method, + const std::string& content, const std::string& header, const std::string& value) { TestCompletionCallback callback; HttpRequestInfo request_info; request_info.url = GURL("http://www.google.com/"); - request_info.method = "GET"; + request_info.method = method; request_info.load_flags = LOAD_NORMAL; scoped_ptr<HttpTransaction> trans; @@ -80,68 +94,105 @@ class HttpNetworkLayerTest : public PlatformTest { } // Check that |proxy_count| proxies are in the retry list. - // These will be, in order, "bad:8080" and "alsobad:8080". - void TestBadProxies(unsigned int proxy_count) { + // These will be, in order, |bad_proxy| and |bad_proxy2|". + void TestBadProxies(unsigned int proxy_count, const std::string& bad_proxy, + const std::string& bad_proxy2) { const ProxyRetryInfoMap& retry_info = proxy_service_->proxy_retry_info(); ASSERT_EQ(proxy_count, retry_info.size()); - ASSERT_TRUE(retry_info.find("bad:8080") != retry_info.end()); + if (proxy_count > 0) + ASSERT_TRUE(retry_info.find(bad_proxy) != retry_info.end()); if (proxy_count > 1) - ASSERT_TRUE(retry_info.find("alsobad:8080") != retry_info.end()); + ASSERT_TRUE(retry_info.find(bad_proxy2) != retry_info.end()); } // Simulates a request through a proxy which returns a bypass, which is then // retried through a second proxy that doesn't bypass. // Checks that the expected requests were issued, the expected content was - // recieved, and the first proxy ("bad:8080") was marked as bad. - void TestProxyFallback() { + // recieved, and the first proxy |bad_proxy| was marked as bad. + void TestProxyFallback(const std::string& bad_proxy) { MockRead data_reads[] = { MockRead("HTTP/1.1 200 OK\r\n" - "Connection: proxy-bypass\r\n\r\n"), + "Chrome-Proxy: bypass=0\r\n\r\n"), MockRead("Bypass message"), MockRead(SYNCHRONOUS, OK), }; + TestProxyFallbackWithMockReads(bad_proxy, "", data_reads, + arraysize(data_reads), 1u); + } + + void TestProxyFallbackWithMockReads(const std::string& bad_proxy, + const std::string& bad_proxy2, + MockRead data_reads[], + int data_reads_size, + unsigned int expected_retry_info_size) { + TestProxyFallbackByMethodWithMockReads(bad_proxy, bad_proxy2, data_reads, + data_reads_size, "GET", "content", + true, expected_retry_info_size); + } + + void TestProxyFallbackByMethodWithMockReads( + const std::string& bad_proxy, + const std::string& bad_proxy2, + MockRead data_reads[], + int data_reads_size, + std::string method, + std::string content, + bool retry_expected, + unsigned int expected_retry_info_size) { + std::string trailer = + (method == "HEAD" || method == "PUT" || method == "POST") ? + "Content-Length: 0\r\n\r\n" : "\r\n"; + std::string request = + base::StringPrintf("%s http://www.google.com/ HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "Proxy-Connection: keep-alive\r\n" + "%s", method.c_str(), trailer.c_str()); + MockWrite data_writes[] = { - MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" - "Host: www.google.com\r\n" - "Proxy-Connection: keep-alive\r\n\r\n"), + MockWrite(request.c_str()), }; - StaticSocketDataProvider data1(data_reads, arraysize(data_reads), + StaticSocketDataProvider data1(data_reads, data_reads_size, data_writes, arraysize(data_writes)); mock_socket_factory_.AddSocketDataProvider(&data1); // Second data provider returns the expected content. - MockRead data_reads2[] = { - MockRead("HTTP/1.0 200 OK\r\n" - "Server: not-proxy\r\n\r\n"), - MockRead("content"), - MockRead(SYNCHRONOUS, OK), - }; + MockRead data_reads2[3]; + size_t data_reads2_index = 0; + data_reads2[data_reads2_index++] = MockRead("HTTP/1.0 200 OK\r\n" + "Server: not-proxy\r\n\r\n"); + if (!content.empty()) + data_reads2[data_reads2_index++] = MockRead(content.c_str()); + data_reads2[data_reads2_index++] = MockRead(SYNCHRONOUS, OK); + MockWrite data_writes2[] = { - MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" - "Host: www.google.com\r\n" - "Proxy-Connection: keep-alive\r\n\r\n"), + MockWrite(request.c_str()), }; - StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), + StaticSocketDataProvider data2(data_reads2, data_reads2_index, data_writes2, arraysize(data_writes2)); mock_socket_factory_.AddSocketDataProvider(&data2); // Expect that we get "content" and not "Bypass message", and that there's // a "not-proxy" "Server:" header in the final response. - ExecuteRequestExpectingContentAndHeader("content", "server", "not-proxy"); + if (retry_expected) { + ExecuteRequestExpectingContentAndHeader(method, content, + "server", "not-proxy"); + } else { + ExecuteRequestExpectingContentAndHeader(method, content, "", ""); + } // We should also observe the bad proxy in the retry list. - TestBadProxies(1u); + TestBadProxies(expected_retry_info_size, bad_proxy, bad_proxy2); } // Simulates a request through a proxy which returns a bypass, which is then // retried through a direct connection to the origin site. // Checks that the expected requests were issued, the expected content was - // received, and the proxy ("bad:8080") was marked as bad. - void TestProxyFallbackToDirect() { + // received, and the proxy |bad_proxy| was marked as bad. + void TestProxyFallbackToDirect(const std::string& bad_proxy) { MockRead data_reads[] = { MockRead("HTTP/1.1 200 OK\r\n" - "Connection: proxy-bypass\r\n\r\n"), + "Chrome-Proxy: bypass=0\r\n\r\n"), MockRead("Bypass message"), MockRead(SYNCHRONOUS, OK), }; @@ -172,10 +223,11 @@ class HttpNetworkLayerTest : public PlatformTest { // Expect that we get "content" and not "Bypass message", and that there's // a "not-proxy" "Server:" header in the final response. - ExecuteRequestExpectingContentAndHeader("content", "server", "not-proxy"); + ExecuteRequestExpectingContentAndHeader("GET", "content", + "server", "not-proxy"); // We should also observe the bad proxy in the retry list. - TestBadProxies(1u); + TestBadProxies(1u, bad_proxy, ""); } // Simulates a request through a proxy which returns a bypass, under a @@ -183,10 +235,12 @@ class HttpNetworkLayerTest : public PlatformTest { // are expected to be configured. // Checks that the expected requests were issued, the bypass message was the // final received content, and all proxies were marked as bad. - void TestProxyFallbackFail(unsigned int proxy_count) { + void TestProxyFallbackFail(unsigned int proxy_count, + const std::string& bad_proxy, + const std::string& bad_proxy2) { MockRead data_reads[] = { MockRead("HTTP/1.1 200 OK\r\n" - "Connection: proxy-bypass\r\n\r\n"), + "Chrome-Proxy: bypass=0\r\n\r\n"), MockRead("Bypass message"), MockRead(SYNCHRONOUS, OK), }; @@ -205,10 +259,10 @@ class HttpNetworkLayerTest : public PlatformTest { mock_socket_factory_.AddSocketDataProvider(&data2); // Expect that we get "Bypass message", and not "content".. - ExecuteRequestExpectingContentAndHeader("Bypass message", "", ""); + ExecuteRequestExpectingContentAndHeader("GET", "Bypass message", "", ""); // We should also observe the bad proxy or proxies in the retry list. - TestBadProxies(proxy_count); + TestBadProxies(proxy_count, bad_proxy, bad_proxy2); } MockClientSocketFactory mock_socket_factory_; @@ -289,7 +343,7 @@ TEST_F(HttpNetworkLayerTest, GET) { } // Proxy bypass tests. These tests run through various server-induced -// proxy-bypass scenarios using both PAC file and fixed proxy params. +// proxy bypass scenarios using both PAC file and fixed proxy params. // The test scenarios are: // - bypass with two proxies configured and the first but not the second // is bypassed. @@ -299,55 +353,133 @@ TEST_F(HttpNetworkLayerTest, GET) { // - bypass with one proxy configured which is bypassed with no defined // fallback +#if defined(SPDY_PROXY_AUTH_ORIGIN) TEST_F(HttpNetworkLayerTest, ServerTwoProxyBypassPac) { + std::string bad_proxy = GetChromeProxy(); ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult( - "PROXY bad:8080; PROXY good:8080")); - TestProxyFallback(); + "PROXY " + bad_proxy + "; PROXY good:8080")); + TestProxyFallback(bad_proxy); } TEST_F(HttpNetworkLayerTest, ServerTwoProxyBypassFixed) { - ConfigureTestDependencies(ProxyService::CreateFixed("bad:8080, good:8080")); - TestProxyFallback(); + std::string bad_proxy = GetChromeProxy(); + ConfigureTestDependencies( + ProxyService::CreateFixed(bad_proxy +", good:8080")); + TestProxyFallback(bad_proxy); +} + +TEST_F(HttpNetworkLayerTest, BypassAndRetryIdempotentMethods) { + std::string bad_proxy = GetChromeProxy(); + const struct { + std::string method; + std::string content; + bool expected_to_retry; + } tests[] = { + { + "GET", + "content", + true, + }, + { + "OPTIONS", + "content", + true, + }, + { + "HEAD", + "", + true, + }, + { + "PUT", + "", + true, + }, + { + "DELETE", + "content", + true, + }, + { + "TRACE", + "content", + true, + }, + { + "POST", + "Bypass message", + false, + }, + }; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + ConfigureTestDependencies( + ProxyService::CreateFixed(bad_proxy +", good:8080")); + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n" + "Chrome-Proxy: bypass=0\r\n\r\n"), + MockRead("Bypass message"), + MockRead(SYNCHRONOUS, OK), + }; + TestProxyFallbackByMethodWithMockReads(bad_proxy, "", data_reads, + arraysize(data_reads), + tests[i].method, + tests[i].content, + tests[i].expected_to_retry, 1u); + } } TEST_F(HttpNetworkLayerTest, ServerOneProxyWithDirectBypassPac) { + std::string bad_proxy = GetChromeProxy(); ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult( - "PROXY bad:8080; DIRECT")); - TestProxyFallbackToDirect(); + "PROXY " + bad_proxy + "; DIRECT")); + TestProxyFallbackToDirect(bad_proxy); } TEST_F(HttpNetworkLayerTest, ServerOneProxyWithDirectBypassFixed) { - ConfigureTestDependencies(ProxyService::CreateFixed( "bad:8080, direct://")); - TestProxyFallbackToDirect(); + std::string bad_proxy = GetChromeProxy(); + ConfigureTestDependencies( + ProxyService::CreateFixed(bad_proxy + ", direct://")); + TestProxyFallbackToDirect(bad_proxy); } +#if defined(DATA_REDUCTION_FALLBACK_HOST) TEST_F(HttpNetworkLayerTest, ServerTwoProxyDoubleBypassPac) { + std::string bad_proxy = GetChromeProxy(); + std::string bad_proxy2 = + HostPortPair::FromURL(GURL(DATA_REDUCTION_FALLBACK_HOST)).ToString(); ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult( - "PROXY bad:8080; PROXY alsobad:8080")); - TestProxyFallbackFail(2u); + "PROXY " + bad_proxy + "; PROXY " + bad_proxy2)); + TestProxyFallbackFail(2u, bad_proxy, bad_proxy2); } TEST_F(HttpNetworkLayerTest, ServerTwoProxyDoubleBypassFixed) { + std::string bad_proxy = GetChromeProxy(); + std::string bad_proxy2 = + HostPortPair::FromURL(GURL(DATA_REDUCTION_FALLBACK_HOST)).ToString(); ConfigureTestDependencies(ProxyService::CreateFixed( - "bad:8080, alsobad:8080")); - TestProxyFallbackFail(2u); + bad_proxy + ", " + bad_proxy2)); + TestProxyFallbackFail(2u, bad_proxy, bad_proxy2); } +#endif TEST_F(HttpNetworkLayerTest, ServerOneProxyNoDirectBypassPac) { + std::string bad_proxy = GetChromeProxy(); ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult( - "PROXY bad:8080")); - TestProxyFallbackFail(1u); + "PROXY " + bad_proxy)); + TestProxyFallbackFail(1u, bad_proxy, ""); } TEST_F(HttpNetworkLayerTest, ServerOneProxyNoDirectBypassFixed) { - ConfigureTestDependencies(ProxyService::CreateFixed("bad:8080")); - TestProxyFallbackFail(1u); + std::string bad_proxy = GetChromeProxy(); + ConfigureTestDependencies(ProxyService::CreateFixed(bad_proxy)); + TestProxyFallbackFail(1u, bad_proxy, ""); } -#if defined(SPDY_PROXY_AUTH_ORIGIN) -TEST_F(HttpNetworkLayerTest, ServerFallbackOnInternalServerError) { - // Verify that "500 Internal Server Error" via the data reduction proxy - // induces proxy fallback to a second proxy, if configured. +TEST_F(HttpNetworkLayerTest, ServerFallbackOn5xxError) { + // Verify that "500 Internal Server Error", "502 Bad Gateway", and + // "503 Service Unavailable" via the data reduction proxy induce proxy + // fallback to a second proxy, if configured. // To configure this test, we need to wire up a custom proxy service to use // a pair of proxies. We'll induce fallback via the first and return @@ -356,79 +488,92 @@ TEST_F(HttpNetworkLayerTest, ServerFallbackOnInternalServerError) { HostPortPair::FromURL(GURL(SPDY_PROXY_AUTH_ORIGIN)).ToString()); std::string pac_string = base::StringPrintf( "PROXY %s; PROXY good:8080", data_reduction_proxy.data()); - ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(pac_string)); - MockRead data_reads[] = { - MockRead("HTTP/1.1 500 Internal Server Error\r\n\r\n"), - MockRead("Bypass message"), - MockRead(SYNCHRONOUS, OK), - }; - MockWrite data_writes[] = { - MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" - "Host: www.google.com\r\n" - "Proxy-Connection: keep-alive\r\n\r\n"), + std::string headers[] = { + "HTTP/1.1 500 Internal Server Error\r\n\r\n", + "HTTP/1.1 502 Bad Gateway\r\n\r\n", + "HTTP/1.1 503 Service Unavailable\r\n\r\n" }; - StaticSocketDataProvider data1(data_reads, arraysize(data_reads), - data_writes, arraysize(data_writes)); - mock_socket_factory_.AddSocketDataProvider(&data1); - // Second data provider returns the expected content. - MockRead data_reads2[] = { - MockRead("HTTP/1.0 200 OK\r\n" - "Server: not-proxy\r\n\r\n"), - MockRead("content"), - MockRead(SYNCHRONOUS, OK), - }; - MockWrite data_writes2[] = { - MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" - "Host: www.google.com\r\n" - "Proxy-Connection: keep-alive\r\n\r\n"), - }; - StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), - data_writes2, arraysize(data_writes2)); - mock_socket_factory_.AddSocketDataProvider(&data2); + for (size_t i = 0; i < arraysize(headers); ++i) { + ConfigureTestDependencies( + ProxyService::CreateFixedFromPacResult(pac_string)); - TestCompletionCallback callback; + MockRead data_reads[] = { + MockRead(headers[i].c_str()), + MockRead("Bypass message"), + MockRead(SYNCHRONOUS, OK), + }; - HttpRequestInfo request_info; - request_info.url = GURL("http://www.google.com/"); - request_info.method = "GET"; - request_info.load_flags = LOAD_NORMAL; + MockWrite data_writes[] = { + MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "Proxy-Connection: keep-alive\r\n\r\n"), + }; - scoped_ptr<HttpTransaction> trans; - int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans, NULL); - EXPECT_EQ(OK, rv); + StaticSocketDataProvider data1(data_reads, arraysize(data_reads), + data_writes, arraysize(data_writes)); + mock_socket_factory_.AddSocketDataProvider(&data1); - rv = trans->Start(&request_info, callback.callback(), BoundNetLog()); - if (rv == ERR_IO_PENDING) - rv = callback.WaitForResult(); - ASSERT_EQ(OK, rv); + // Second data provider returns the expected content. + MockRead data_reads2[] = { + MockRead("HTTP/1.0 200 OK\r\n" + "Server: not-proxy\r\n\r\n"), + MockRead("content"), + MockRead(SYNCHRONOUS, OK), + }; + MockWrite data_writes2[] = { + MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "Proxy-Connection: keep-alive\r\n\r\n"), + }; - std::string contents; - rv = ReadTransaction(trans.get(), &contents); - EXPECT_EQ(OK, rv); + StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), + data_writes2, arraysize(data_writes2)); + mock_socket_factory_.AddSocketDataProvider(&data2); + + TestCompletionCallback callback; + + HttpRequestInfo request_info; + request_info.url = GURL("http://www.google.com/"); + request_info.method = "GET"; + request_info.load_flags = LOAD_NORMAL; + + scoped_ptr<HttpTransaction> trans; + int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans, NULL); + EXPECT_EQ(OK, rv); + + rv = trans->Start(&request_info, callback.callback(), BoundNetLog()); + if (rv == ERR_IO_PENDING) + rv = callback.WaitForResult(); + ASSERT_EQ(OK, rv); - // We should obtain content from the second socket provider write - // corresponding to the fallback proxy. - EXPECT_EQ("content", contents); - // We also have a server header here that isn't set by the proxy. - EXPECT_TRUE(trans->GetResponseInfo()->headers->HasHeaderValue( - "server", "not-proxy")); - // We should also observe the data reduction proxy in the retry list. - ASSERT_TRUE(1u == proxy_service_->proxy_retry_info().size()); - EXPECT_EQ(data_reduction_proxy, - (*proxy_service_->proxy_retry_info().begin()).first); + std::string contents; + rv = ReadTransaction(trans.get(), &contents); + EXPECT_EQ(OK, rv); + + // We should obtain content from the second socket provider write + // corresponding to the fallback proxy. + EXPECT_EQ("content", contents); + // We also have a server header here that isn't set by the proxy. + EXPECT_TRUE(trans->GetResponseInfo()->headers->HasHeaderValue( + "server", "not-proxy")); + // We should also observe the data reduction proxy in the retry list. + ASSERT_EQ(1u, proxy_service_->proxy_retry_info().size()); + EXPECT_EQ(data_reduction_proxy, + (*proxy_service_->proxy_retry_info().begin()).first); + } } #endif // defined(SPDY_PROXY_AUTH_ORIGIN) TEST_F(HttpNetworkLayerTest, ProxyBypassIgnoredOnDirectConnectionPac) { - // Verify that a Connection: proxy-bypass header is ignored when returned - // from a directly connected origin server. + // Verify that a Chrome-Proxy header is ignored when returned from a directly + // connected origin server. ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult("DIRECT")); MockRead data_reads[] = { MockRead("HTTP/1.1 200 OK\r\n" - "Connection: proxy-bypass\r\n\r\n"), + "Chrome-Proxy: bypass=0\r\n\r\n"), MockRead("Bypass message"), MockRead(SYNCHRONOUS, OK), }; @@ -466,6 +611,132 @@ TEST_F(HttpNetworkLayerTest, ProxyBypassIgnoredOnDirectConnectionPac) { ASSERT_EQ(0u, proxy_service_->proxy_retry_info().size()); } +#if defined(SPDY_PROXY_AUTH_ORIGIN) +TEST_F(HttpNetworkLayerTest, ServerFallbackWithProxyTimedBypass) { + // Verify that a Chrome-Proxy: bypass=<seconds> header induces proxy + // fallback to a second proxy, if configured. + std::string bad_proxy = GetChromeProxy(); + ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult( + "PROXY " + bad_proxy + "; PROXY good:8080")); + + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n" + "Connection: keep-alive\r\n" + "Chrome-Proxy: bypass=86400\r\n" + "Via: 1.1 Chrome Compression Proxy\r\n\r\n"), + MockRead("Bypass message"), + MockRead(SYNCHRONOUS, OK), + }; + + TestProxyFallbackWithMockReads(bad_proxy, "", data_reads, + arraysize(data_reads), 1u); + EXPECT_EQ(base::TimeDelta::FromSeconds(86400), + (*proxy_service_->proxy_retry_info().begin()).second.current_delay); +} + +TEST_F(HttpNetworkLayerTest, ServerFallbackWithWrongViaHeader) { + // Verify that a Via header that lacks the Chrome-Proxy induces proxy fallback + // to a second proxy, if configured. + std::string chrome_proxy = GetChromeProxy(); + ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult( + "PROXY " + chrome_proxy + "; PROXY good:8080")); + + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n" + "Connection: keep-alive\r\n" + "Via: 1.0 some-other-proxy\r\n\r\n"), + MockRead("Bypass message"), + MockRead(SYNCHRONOUS, OK), + }; + + TestProxyFallbackWithMockReads(chrome_proxy, std::string(), data_reads, + arraysize(data_reads), 1u); +} + +TEST_F(HttpNetworkLayerTest, ServerFallbackWithNoViaHeader) { + // Verify that the lack of a Via header induces proxy fallback to a second + // proxy, if configured. + std::string chrome_proxy = GetChromeProxy(); + ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult( + "PROXY " + chrome_proxy + "; PROXY good:8080")); + + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n" + "Connection: keep-alive\r\n\r\n"), + MockRead("Bypass message"), + MockRead(SYNCHRONOUS, OK), + }; + + TestProxyFallbackWithMockReads(chrome_proxy, std::string(), data_reads, + arraysize(data_reads), 1u); +} + +TEST_F(HttpNetworkLayerTest, NoServerFallbackWith304Response) { + // Verify that Chrome will not be induced to bypass the Chrome proxy when + // the Chrome Proxy via header is absent on a 304. + std::string chrome_proxy = GetChromeProxy(); + ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult( + "PROXY " + chrome_proxy + "; PROXY good:8080")); + + MockRead data_reads[] = { + MockRead("HTTP/1.1 304 Not Modified\r\n" + "Connection: keep-alive\r\n\r\n"), + MockRead(SYNCHRONOUS, OK), + }; + + TestProxyFallbackByMethodWithMockReads(chrome_proxy, std::string(), + data_reads, arraysize(data_reads), + "GET", std::string(), false, 0); +} + +TEST_F(HttpNetworkLayerTest, NoServerFallbackWithChainedViaHeader) { + // Verify that Chrome will not be induced to bypass the Chrome proxy when + // the Chrome Proxy via header is present, even if that header is chained. + std::string chrome_proxy = GetChromeProxy(); + ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult( + "PROXY " + chrome_proxy + "; PROXY good:8080")); + + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n" + "Connection: keep-alive\r\n" + "Via: 1.1 Chrome Compression Proxy, 1.0 some-other-proxy\r\n\r\n"), + MockRead("Bypass message"), + MockRead(SYNCHRONOUS, OK), + }; + + TestProxyFallbackByMethodWithMockReads(chrome_proxy, std::string(), + data_reads, arraysize(data_reads), + "GET", "Bypass message", false, 0); +} + +#if defined(DATA_REDUCTION_FALLBACK_HOST) +TEST_F(HttpNetworkLayerTest, ServerFallbackWithProxyTimedBypassAll) { + // Verify that a Chrome-Proxy: block=<seconds> header bypasses a + // a configured Chrome-Proxy and fallback and induces proxy fallback to a + // third proxy, if configured. + std::string bad_proxy = GetChromeProxy(); + std::string fallback_proxy = GetChromeFallbackProxy(); + ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult( + "PROXY " + bad_proxy + "; PROXY " + fallback_proxy + + "; PROXY good:8080")); + + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n" + "Connection: keep-alive\r\n" + "Chrome-Proxy: block=86400\r\n" + "Via: 1.1 Chrome Compression Proxy\r\n\r\n"), + MockRead("Bypass message"), + MockRead(SYNCHRONOUS, OK), + }; + + TestProxyFallbackWithMockReads(bad_proxy, fallback_proxy, data_reads, + arraysize(data_reads), 2u); + EXPECT_EQ(base::TimeDelta::FromSeconds(86400), + (*proxy_service_->proxy_retry_info().begin()).second.current_delay); +} +#endif // defined(DATA_REDUCTION_FALLBACK_HOST) +#endif // defined(SPDY_PROXY_AUTH_ORIGIN) + TEST_F(HttpNetworkLayerTest, NetworkVerified) { MockRead data_reads[] = { MockRead("HTTP/1.0 200 OK\r\n\r\n"), diff --git a/chromium/net/http/http_network_session.cc b/chromium/net/http/http_network_session.cc index 346cbbc8941..1be93fe5c3f 100644 --- a/chromium/net/http/http_network_session.cc +++ b/chromium/net/http/http_network_session.cc @@ -42,6 +42,7 @@ net::ClientSocketPoolManager* CreateSocketPoolManager( params.cert_verifier, params.server_bound_cert_service, params.transport_security_state, + params.cert_transparency_verifier, params.ssl_session_cache_shard, params.proxy_service, params.ssl_config_service, @@ -58,6 +59,7 @@ HttpNetworkSession::Params::Params() cert_verifier(NULL), server_bound_cert_service(NULL), transport_security_state(NULL), + cert_transparency_verifier(NULL), proxy_service(NULL), ssl_config_service(NULL), http_auth_handler_factory(NULL), @@ -71,7 +73,6 @@ HttpNetworkSession::Params::Params() testing_fixed_https_port(0), force_spdy_single_domain(false), enable_spdy_ip_pooling(true), - enable_spdy_credential_frames(false), enable_spdy_compression(true), enable_spdy_ping_based_connection_checking(true), spdy_default_protocol(kProtoUnknown), @@ -83,6 +84,7 @@ HttpNetworkSession::Params::Params() enable_quic_https(false), quic_clock(NULL), quic_random(NULL), + quic_max_packet_length(kDefaultMaxPacketSize), enable_user_alternate_protocol_ports(false), quic_crypto_client_stream_factory(NULL) { } @@ -112,13 +114,13 @@ HttpNetworkSession::HttpNetworkSession(const Params& params) params.quic_random ? params.quic_random : QuicRandom::GetInstance(), params.quic_clock ? params. quic_clock : - new QuicClock()), + new QuicClock(), + params.quic_max_packet_length), spdy_session_pool_(params.host_resolver, params.ssl_config_service, params.http_server_properties, params.force_spdy_single_domain, params.enable_spdy_ip_pooling, - params.enable_spdy_credential_frames, params.enable_spdy_compression, params.enable_spdy_ping_based_connection_checking, params.spdy_default_protocol, @@ -128,7 +130,8 @@ HttpNetworkSession::HttpNetworkSession(const Params& params) params.time_func, params.trusted_spdy_proxy), http_stream_factory_(new HttpStreamFactoryImpl(this, false)), - websocket_stream_factory_(new HttpStreamFactoryImpl(this, true)), + http_stream_factory_for_websocket_( + new HttpStreamFactoryImpl(this, true)), params_(params) { DCHECK(proxy_service_); DCHECK(ssl_config_service_.get()); diff --git a/chromium/net/http/http_network_session.h b/chromium/net/http/http_network_session.h index c10bb1446f4..471041220ec 100644 --- a/chromium/net/http/http_network_session.h +++ b/chromium/net/http/http_network_session.h @@ -62,6 +62,7 @@ class NET_EXPORT HttpNetworkSession CertVerifier* cert_verifier; ServerBoundCertService* server_bound_cert_service; TransportSecurityState* transport_security_state; + CTVerifier* cert_transparency_verifier; ProxyService* proxy_service; std::string ssl_session_cache_shard; SSLConfigService* ssl_config_service; @@ -77,7 +78,6 @@ class NET_EXPORT HttpNetworkSession uint16 testing_fixed_https_port; bool force_spdy_single_domain; bool enable_spdy_ip_pooling; - bool enable_spdy_credential_frames; bool enable_spdy_compression; bool enable_spdy_ping_based_connection_checking; NextProto spdy_default_protocol; @@ -91,6 +91,7 @@ class NET_EXPORT HttpNetworkSession HostPortPair origin_to_force_quic_on; QuicClock* quic_clock; // Will be owned by QuicStreamFactory. QuicRandom* quic_random; + size_t quic_max_packet_length; bool enable_user_alternate_protocol_ports; QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory; }; @@ -141,8 +142,8 @@ class NET_EXPORT HttpNetworkSession HttpStreamFactory* http_stream_factory() { return http_stream_factory_.get(); } - HttpStreamFactory* websocket_stream_factory() { - return websocket_stream_factory_.get(); + HttpStreamFactory* http_stream_factory_for_websocket() { + return http_stream_factory_for_websocket_.get(); } NetLog* net_log() { return net_log_; @@ -198,7 +199,7 @@ class NET_EXPORT HttpNetworkSession QuicStreamFactory quic_stream_factory_; SpdySessionPool spdy_session_pool_; scoped_ptr<HttpStreamFactory> http_stream_factory_; - scoped_ptr<HttpStreamFactory> websocket_stream_factory_; + scoped_ptr<HttpStreamFactory> http_stream_factory_for_websocket_; std::set<HttpResponseBodyDrainer*> response_drainers_; Params params_; diff --git a/chromium/net/http/http_network_session_peer.cc b/chromium/net/http/http_network_session_peer.cc index 74b0d415310..a32e48b9ebb 100644 --- a/chromium/net/http/http_network_session_peer.cc +++ b/chromium/net/http/http_network_session_peer.cc @@ -21,8 +21,8 @@ HttpNetworkSessionPeer::HttpNetworkSessionPeer( HttpNetworkSessionPeer::~HttpNetworkSessionPeer() {} void HttpNetworkSessionPeer::SetClientSocketPoolManager( - ClientSocketPoolManager* socket_pool_manager) { - session_->normal_socket_pool_manager_.reset(socket_pool_manager); + scoped_ptr<ClientSocketPoolManager> socket_pool_manager) { + session_->normal_socket_pool_manager_.swap(socket_pool_manager); } void HttpNetworkSessionPeer::SetProxyService(ProxyService* proxy_service) { @@ -30,13 +30,13 @@ void HttpNetworkSessionPeer::SetProxyService(ProxyService* proxy_service) { } void HttpNetworkSessionPeer::SetHttpStreamFactory( - HttpStreamFactory* http_stream_factory) { - session_->http_stream_factory_.reset(http_stream_factory); + scoped_ptr<HttpStreamFactory> http_stream_factory) { + session_->http_stream_factory_.swap(http_stream_factory); } -void HttpNetworkSessionPeer::SetWebSocketStreamFactory( - HttpStreamFactory* http_stream_factory) { - session_->websocket_stream_factory_.reset(http_stream_factory); +void HttpNetworkSessionPeer::SetHttpStreamFactoryForWebSocket( + scoped_ptr<HttpStreamFactory> http_stream_factory) { + session_->http_stream_factory_for_websocket_.swap(http_stream_factory); } } // namespace net diff --git a/chromium/net/http/http_network_session_peer.h b/chromium/net/http/http_network_session_peer.h index eeccfefafd4..755e539cebb 100644 --- a/chromium/net/http/http_network_session_peer.h +++ b/chromium/net/http/http_network_session_peer.h @@ -6,6 +6,7 @@ #define NET_HTTP_HTTP_NETWORK_SESSION_PEER_H_ #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "net/base/net_export.h" namespace net { @@ -22,12 +23,13 @@ class NET_EXPORT_PRIVATE HttpNetworkSessionPeer { ~HttpNetworkSessionPeer(); void SetClientSocketPoolManager( - ClientSocketPoolManager* socket_pool_manager); + scoped_ptr<ClientSocketPoolManager> socket_pool_manager); void SetProxyService(ProxyService* proxy_service); - void SetHttpStreamFactory(HttpStreamFactory* http_stream_factory); - void SetWebSocketStreamFactory(HttpStreamFactory* websocket_stream_factory); + void SetHttpStreamFactory(scoped_ptr<HttpStreamFactory> http_stream_factory); + void SetHttpStreamFactoryForWebSocket( + scoped_ptr<HttpStreamFactory> http_stream_factory_for_websocket); private: const scoped_refptr<HttpNetworkSession> session_; diff --git a/chromium/net/http/http_network_transaction.cc b/chromium/net/http/http_network_transaction.cc index ff158a84e77..d7b3f41ff76 100644 --- a/chromium/net/http/http_network_transaction.cc +++ b/chromium/net/http/http_network_transaction.cc @@ -19,6 +19,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" +#include "base/time/time.h" #include "base/values.h" #include "build/build_config.h" #include "net/base/auth.h" @@ -60,7 +61,14 @@ #include "net/ssl/ssl_connection_status_flags.h" #include "url/gurl.h" +#if defined(SPDY_PROXY_AUTH_ORIGIN) +#include <algorithm> +#include "net/proxy/proxy_server.h" +#endif + + using base::Time; +using base::TimeDelta; namespace net { @@ -111,6 +119,30 @@ base::Value* NetLogSSLVersionFallbackCallback( return dict; } +#if defined(SPDY_PROXY_AUTH_ORIGIN) +// Returns true if |response_headers| contains the data reduction proxy Via +// header value. +bool IsChromeProxyResponse(const net::HttpResponseHeaders* response_headers) { + if (!response_headers) { + return false; + } + const char kDataReductionProxyViaValue[] = "1.1 Chrome Compression Proxy"; + size_t value_len = strlen(kDataReductionProxyViaValue); + void* iter = NULL; + std::string temp; + while (response_headers->EnumerateHeader(&iter, "Via", &temp)) { + std::string::const_iterator it = + std::search(temp.begin(), temp.end(), + kDataReductionProxyViaValue, + kDataReductionProxyViaValue + value_len, + base::CaseInsensitiveCompareASCII<char>()); + if (it != temp.end()) + return true; + } + return false; +} +#endif + } // namespace //----------------------------------------------------------------------------- @@ -125,10 +157,12 @@ HttpNetworkTransaction::HttpNetworkTransaction(RequestPriority priority, priority_(priority), headers_valid_(false), logged_response_time_(false), + fallback_error_code_(ERR_SSL_INAPPROPRIATE_FALLBACK), request_headers_(), read_buf_len_(0), next_state_(STATE_NONE), - establishing_tunnel_(false) { + establishing_tunnel_(false), + websocket_handshake_stream_base_create_helper_(NULL) { session->ssl_config_service()->GetSSLConfig(&server_ssl_config_); if (session->http_stream_factory()->has_next_protos()) { server_ssl_config_.next_protos = @@ -159,10 +193,13 @@ HttpNetworkTransaction::~HttpNetworkTransaction() { } else { // Otherwise, we try to drain the response body. HttpStreamBase* stream = stream_.release(); - stream->Drain(session_.get()); + stream->Drain(session_); } } } + + if (request_ && request_->upload_data_stream) + request_->upload_data_stream->Reset(); // Invalidate pending callbacks. } int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info, @@ -425,6 +462,11 @@ void HttpNetworkTransaction::SetPriority(RequestPriority priority) { stream_->SetPriority(priority); } +void HttpNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper( + WebSocketHandshakeStreamBase::CreateHelper* create_helper) { + websocket_handshake_stream_base_create_helper_ = create_helper; +} + void HttpNetworkTransaction::OnStreamReady(const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, HttpStreamBase* stream) { @@ -443,11 +485,11 @@ void HttpNetworkTransaction::OnStreamReady(const SSLConfig& used_ssl_config, OnIOComplete(OK); } -void HttpNetworkTransaction::OnWebSocketStreamReady( +void HttpNetworkTransaction::OnWebSocketHandshakeStreamReady( const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, - WebSocketStreamBase* stream) { - NOTREACHED() << "This function should never be called."; + WebSocketHandshakeStreamBase* stream) { + OnStreamReady(used_ssl_config, used_proxy_info, stream); } void HttpNetworkTransaction::OnStreamFailed(int result, @@ -653,14 +695,27 @@ int HttpNetworkTransaction::DoLoop(int result) { int HttpNetworkTransaction::DoCreateStream() { next_state_ = STATE_CREATE_STREAM_COMPLETE; - stream_request_.reset( - session_->http_stream_factory()->RequestStream( - *request_, - priority_, - server_ssl_config_, - proxy_ssl_config_, - this, - net_log_)); + if (ForWebSocketHandshake()) { + stream_request_.reset( + session_->http_stream_factory_for_websocket() + ->RequestWebSocketHandshakeStream( + *request_, + priority_, + server_ssl_config_, + proxy_ssl_config_, + this, + websocket_handshake_stream_base_create_helper_, + net_log_)); + } else { + stream_request_.reset( + session_->http_stream_factory()->RequestStream( + *request_, + priority_, + server_ssl_config_, + proxy_ssl_config_, + this, + net_log_)); + } DCHECK(stream_request_.get()); return ERR_IO_PENDING; } @@ -894,6 +949,11 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) { return result; } + if (result == ERR_QUIC_HANDSHAKE_FAILED) { + ResetConnectionAndRequestForResend(); + return OK; + } + if (result < 0 && result != ERR_CONNECTION_CLOSED) return HandleIOError(result); @@ -917,33 +977,85 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) { } DCHECK(response_.headers.get()); +#if defined(SPDY_PROXY_AUTH_ORIGIN) // Server-induced fallback; see: http://crbug.com/143712 if (response_.was_fetched_via_proxy && response_.headers.get() != NULL) { - bool should_fallback = - response_.headers->HasHeaderValue("connection", "proxy-bypass"); - // Additionally, fallback if a 500 is returned via the data reduction proxy. - // This is conservative, as the 500 might have been generated by the origin, - // and not the proxy. -#if defined(SPDY_PROXY_AUTH_ORIGIN) - if (!should_fallback) { - should_fallback = - response_.headers->response_code() == HTTP_INTERNAL_SERVER_ERROR && - proxy_info_.proxy_server().host_port_pair().Equals( - HostPortPair::FromURL(GURL(SPDY_PROXY_AUTH_ORIGIN))); + ProxyService::DataReductionProxyBypassEventType proxy_bypass_event = + ProxyService::BYPASS_EVENT_TYPE_MAX; + net::HttpResponseHeaders::ChromeProxyInfo chrome_proxy_info; + bool chrome_proxy_used = + proxy_info_.proxy_server().isDataReductionProxy(); + bool chrome_fallback_proxy_used = false; +#if defined(DATA_REDUCTION_FALLBACK_HOST) + if (!chrome_proxy_used) { + chrome_fallback_proxy_used = + proxy_info_.proxy_server().isDataReductionProxyFallback(); } #endif - if (should_fallback) { - ProxyService* proxy_service = session_->proxy_service(); - if (proxy_service->MarkProxyAsBad(proxy_info_, net_log_)) { - // Only retry in the case of GETs. We don't want to resubmit a POST - // if the proxy took some action. - if (request_->method == "GET") { - ResetConnectionAndRequestForResend(); - return OK; + + if (chrome_proxy_used || chrome_fallback_proxy_used) { + // A Via header might not be present in a 304. Since the goal of a 304 + // response is to minimize information transfer, a sender in general + // should not generate representation metadata other than Cache-Control, + // Content-Location, Date, ETag, Expires, and Vary. + if (!IsChromeProxyResponse(response_.headers.get()) && + (response_.headers->response_code() != HTTP_NOT_MODIFIED)) { + proxy_bypass_event = ProxyService::MISSING_VIA_HEADER; + } else if (response_.headers->GetChromeProxyInfo(&chrome_proxy_info)) { + if (chrome_proxy_info.bypass_duration < TimeDelta::FromMinutes(30)) + proxy_bypass_event = ProxyService::SHORT_BYPASS; + else + proxy_bypass_event = ProxyService::LONG_BYPASS; + } else { + // Additionally, fallback if a 500, 502 or 503 is returned via the data + // reduction proxy. This is conservative, as the 500, 502 or 503 might + // have been generated by the origin, and not the proxy. + if (response_.headers->response_code() == HTTP_INTERNAL_SERVER_ERROR || + response_.headers->response_code() == HTTP_BAD_GATEWAY || + response_.headers->response_code() == HTTP_SERVICE_UNAVAILABLE) { + proxy_bypass_event = ProxyService::INTERNAL_SERVER_ERROR_BYPASS; + } + } + + if (proxy_bypass_event < ProxyService::BYPASS_EVENT_TYPE_MAX) { + ProxyService* proxy_service = session_->proxy_service(); + + proxy_service->RecordDataReductionProxyBypassInfo( + chrome_proxy_used, proxy_info_.proxy_server(), proxy_bypass_event); + + ProxyServer proxy_server; +#if defined(DATA_REDUCTION_FALLBACK_HOST) + if (chrome_proxy_used && chrome_proxy_info.bypass_all) { + // TODO(bengr): Rename as DATA_REDUCTION_FALLBACK_ORIGIN. + GURL proxy_url(DATA_REDUCTION_FALLBACK_HOST); + if (proxy_url.SchemeIsHTTPOrHTTPS()) { + proxy_server = ProxyServer(proxy_url.SchemeIs("http") ? + ProxyServer::SCHEME_HTTP : + ProxyServer::SCHEME_HTTPS, + HostPortPair::FromURL(proxy_url)); + } + } +#endif + if (proxy_service->MarkProxiesAsBad(proxy_info_, + chrome_proxy_info.bypass_duration, + proxy_server, + net_log_)) { + // Only retry idempotent methods. We don't want to resubmit a POST + // if the proxy took some action. + if (request_->method == "GET" || + request_->method == "OPTIONS" || + request_->method == "HEAD" || + request_->method == "PUT" || + request_->method == "DELETE" || + request_->method == "TRACE") { + ResetConnectionAndRequestForResend(); + return OK; + } } } } } +#endif // defined(SPDY_PROXY_AUTH_ORIGIN) // Like Net.HttpResponseCode, but only for MAIN_FRAME loads. if (request_->load_flags & LOAD_MAIN_FRAME) { @@ -969,7 +1081,9 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) { // need to skip over it. // We treat any other 1xx in this same way (although in practice getting // a 1xx that isn't a 100 is rare). - if (response_.headers->response_code() / 100 == 1) { + // Unless this is a WebSocket request, in which case we pass it on up. + if (response_.headers->response_code() / 100 == 1 && + !ForWebSocketHandshake()) { response_.headers = new HttpResponseHeaders(std::string()); next_state_ = STATE_READ_HEADERS; return OK; @@ -1210,17 +1324,21 @@ int HttpNetworkTransaction::HandleCertificateRequest(int error) { return OK; } +void HttpNetworkTransaction::HandleClientAuthError(int error) { + if (server_ssl_config_.send_client_cert && + (error == ERR_SSL_PROTOCOL_ERROR || IsClientCertificateError(error))) { + session_->ssl_client_auth_cache()->Remove( + GetHostAndPort(request_->url)); + } +} + // TODO(rch): This does not correctly handle errors when an SSL proxy is // being used, as all of the errors are handled as if they were generated // by the endpoint host, request_->url, rather than considering if they were // generated by the SSL proxy. http://crbug.com/69329 int HttpNetworkTransaction::HandleSSLHandshakeError(int error) { DCHECK(request_); - if (server_ssl_config_.send_client_cert && - (error == ERR_SSL_PROTOCOL_ERROR || IsClientCertificateError(error))) { - session_->ssl_client_auth_cache()->Remove( - GetHostAndPort(request_->url)); - } + HandleClientAuthError(error); bool should_fallback = false; uint16 version_max = server_ssl_config_.version_max; @@ -1246,16 +1364,7 @@ int HttpNetworkTransaction::HandleSSLHandshakeError(int error) { // While SSL 3.0 fallback should be eliminated because of security // reasons, there is a high risk of breaking the servers if this is // done in general. - // For now SSL 3.0 fallback is disabled for Google servers first, - // and will be expanded to other servers after enough experiences - // have been gained showing that this experiment works well with - // today's Internet. - if (version_max > SSL_PROTOCOL_VERSION_SSL3 || - (server_ssl_config_.unrestricted_ssl3_fallback_enabled || - !TransportSecurityState::IsGooglePinnedProperty( - request_->url.host(), true /* include SNI */))) { - should_fallback = true; - } + should_fallback = true; } break; case ERR_SSL_BAD_RECORD_MAC_ALERT: @@ -1269,6 +1378,13 @@ int HttpNetworkTransaction::HandleSSLHandshakeError(int error) { should_fallback = true; } break; + case ERR_SSL_INAPPROPRIATE_FALLBACK: + // The server told us that we should not have fallen back. A buggy server + // could trigger ERR_SSL_INAPPROPRIATE_FALLBACK with the initial + // connection. |fallback_error_code_| is initialised to + // ERR_SSL_INAPPROPRIATE_FALLBACK to catch this case. + error = fallback_error_code_; + break; } if (should_fallback) { @@ -1277,6 +1393,7 @@ int HttpNetworkTransaction::HandleSSLHandshakeError(int error) { base::Bind(&NetLogSSLVersionFallbackCallback, &request_->url, error, server_ssl_config_.version_max, version_max)); + fallback_error_code_ = error; server_ssl_config_.version_max = version_max; server_ssl_config_.version_fallback = true; ResetConnectionAndRequestForResend(); @@ -1291,13 +1408,9 @@ int HttpNetworkTransaction::HandleSSLHandshakeError(int error) { // write errors or response header read errors. It should not be used in // other cases, such as a Connect error. int HttpNetworkTransaction::HandleIOError(int error) { - // SSL errors may happen at any time during the stream and indicate issues - // with the underlying connection. Because the peer may request - // renegotiation at any time, check and handle any possible SSL handshake - // related errors. In addition to renegotiation, TLS False Start may cause - // SSL handshake errors (specifically servers with buggy DEFLATE support) - // to be delayed until the first Read on the underlying connection. - error = HandleSSLHandshakeError(error); + // Because the peer may request renegotiation with client authentication at + // any time, check and handle client authentication errors. + HandleClientAuthError(error); switch (error) { // If we try to reuse a connection that the server is in the process of @@ -1332,6 +1445,7 @@ int HttpNetworkTransaction::HandleIOError(int error) { break; case ERR_SPDY_PING_FAILED: case ERR_SPDY_SERVER_REFUSED_STREAM: + case ERR_QUIC_HANDSHAKE_FAILED: net_log_.AddEventWithNetErrorCode( NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR, error); ResetConnectionAndRequestForResend(); @@ -1453,6 +1567,11 @@ GURL HttpNetworkTransaction::AuthURL(HttpAuth::Target target) const { } } +bool HttpNetworkTransaction::ForWebSocketHandshake() const { + return websocket_handshake_stream_base_create_helper_ && + request_->url.SchemeIsWSOrWSS(); +} + #define STATE_CASE(s) \ case s: \ description = base::StringPrintf("%s (0x%08X)", #s, s); \ diff --git a/chromium/net/http/http_network_transaction.h b/chromium/net/http/http_network_transaction.h index 6228487e615..3ae1725d1de 100644 --- a/chromium/net/http/http_network_transaction.h +++ b/chromium/net/http/http_network_transaction.h @@ -21,6 +21,7 @@ #include "net/http/http_transaction.h" #include "net/proxy/proxy_service.h" #include "net/ssl/ssl_config_service.h" +#include "net/websockets/websocket_handshake_stream_base.h" namespace net { @@ -68,15 +69,17 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction virtual bool GetLoadTimingInfo( LoadTimingInfo* load_timing_info) const OVERRIDE; virtual void SetPriority(RequestPriority priority) OVERRIDE; + virtual void SetWebSocketHandshakeStreamCreateHelper( + WebSocketHandshakeStreamBase::CreateHelper* create_helper) OVERRIDE; // HttpStreamRequest::Delegate methods: virtual void OnStreamReady(const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, HttpStreamBase* stream) OVERRIDE; - virtual void OnWebSocketStreamReady( + virtual void OnWebSocketHandshakeStreamReady( const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, - WebSocketStreamBase* stream) OVERRIDE; + WebSocketHandshakeStreamBase* stream) OVERRIDE; virtual void OnStreamFailed(int status, const SSLConfig& used_ssl_config) OVERRIDE; virtual void OnCertificateError(int status, @@ -184,6 +187,9 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction // Called to handle a client certificate request. int HandleCertificateRequest(int error); + // Called to possibly handle a client authentication error. + void HandleClientAuthError(int error); + // Called to possibly recover from an SSL handshake error. Sets next_state_ // and returns OK if recovering from the error. Otherwise, the same error // code is returned. @@ -242,6 +248,9 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction // Get the {scheme, host, path, port} for the authentication target GURL AuthURL(HttpAuth::Target target) const; + // Returns true if this transaction is for a WebSocket handshake + bool ForWebSocketHandshake() const; + // Debug helper. static std::string DescribeState(State state); @@ -256,7 +265,7 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction CompletionCallback io_callback_; CompletionCallback callback_; - scoped_refptr<HttpNetworkSession> session_; + HttpNetworkSession* session_; BoundNetLog net_log_; const HttpRequestInfo* request_; @@ -279,6 +288,12 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction SSLConfig server_ssl_config_; SSLConfig proxy_ssl_config_; + // fallback_error_code contains the error code that caused the last TLS + // fallback. If the fallback connection results in + // ERR_SSL_INAPPROPRIATE_FALLBACK (i.e. the server indicated that the + // fallback should not have been needed) then we use this value to return the + // original error that triggered the fallback. + int fallback_error_code_; HttpRequestHeaders request_headers_; @@ -306,6 +321,11 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction // read from the socket until the tunnel is done. bool establishing_tunnel_; + // The helper object to use to create WebSocketHandshakeStreamBase + // objects. Only relevant when establishing a WebSocket connection. + WebSocketHandshakeStreamBase::CreateHelper* + websocket_handshake_stream_base_create_helper_; + DISALLOW_COPY_AND_ASSIGN(HttpNetworkTransaction); }; diff --git a/chromium/net/http/http_network_transaction_ssl_unittest.cc b/chromium/net/http/http_network_transaction_ssl_unittest.cc index bb218498961..ab7eadf8928 100644 --- a/chromium/net/http/http_network_transaction_ssl_unittest.cc +++ b/chromium/net/http/http_network_transaction_ssl_unittest.cc @@ -103,148 +103,6 @@ class HttpNetworkTransactionSSLTest : public testing::Test { ScopedVector<HttpRequestInfo> request_info_vector_; }; -// Tests that HttpNetworkTransaction does not attempt to -// fallback to SSL 3.0 when a TLS 1.0 handshake fails and: -// * the site is pinned to the Google pin list (indicating that -// it is a Google site); -// * unrestricted SSL 3.0 fallback is disabled. -TEST_F(HttpNetworkTransactionSSLTest, SSL3FallbackDisabled_Google) { - // |ssl_data1| is for the first handshake (TLS 1.0), which will fail for - // protocol reasons (e.g., simulating a version rollback attack). - // Because unrestricted SSL 3.0 fallback is disabled, only this simulated - // SSL handshake is consumed. - SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_PROTOCOL_ERROR); - mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data1); - StaticSocketDataProvider data1(NULL, 0, NULL, 0); - mock_socket_factory_.AddSocketDataProvider(&data1); - - // This extra handshake, which should be unconsumed, is provided to ensure - // that even if the behaviour being tested here ever breaks (and Google - // properties begin SSL 3.0 fallbacks), this test will not crash (and bring - // down all of net_unittests), but it will fail gracefully. - SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR); - mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data2); - StaticSocketDataProvider data2(NULL, 0, NULL, 0); - mock_socket_factory_.AddSocketDataProvider(&data2); - - scoped_refptr<HttpNetworkSession> session( - new HttpNetworkSession(session_params_)); - scoped_ptr<HttpNetworkTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); - - SSLConfig& ssl_config = GetServerSSLConfig(trans.get()); - ssl_config.unrestricted_ssl3_fallback_enabled = false; - - TestCompletionCallback callback; - // This will consume only |ssl_data1|. |ssl_data2| will not be consumed. - int rv = callback.GetResult( - trans->Start(GetRequestInfo("https://www.google.com/"), - callback.callback(), BoundNetLog())); - EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, rv); - - SocketDataProviderArray<SocketDataProvider>& mock_data = - mock_socket_factory_.mock_data(); - // Confirms that only |ssl_data1| is consumed. - EXPECT_EQ(1u, mock_data.next_index()); - - // |version_max| never fallbacks to SSLv3 for Google properties. - EXPECT_EQ(SSL_PROTOCOL_VERSION_TLS1, ssl_config.version_max); - EXPECT_FALSE(ssl_config.version_fallback); -} - -// Tests that HttpNetworkTransaction attempts to fallback to SSL 3.0 -// when a TLS 1.0 handshake fails and: -// * the site is pinned to the Google pin list (indicating that -// it is a Google site); -// * unrestricted SSL 3.0 fallback is enabled. -TEST_F(HttpNetworkTransactionSSLTest, SSL3FallbackEnabled_Google) { - // |ssl_data1| is for the first handshake (TLS 1.0), which will fail - // for protocol reasons (e.g., simulating a version rollback attack). - SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_PROTOCOL_ERROR); - mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data1); - StaticSocketDataProvider data1(NULL, 0, NULL, 0); - mock_socket_factory_.AddSocketDataProvider(&data1); - - // |ssl_data2| contains the handshake result for a SSL 3.0 - // handshake which will be attempted after the TLS 1.0 - // handshake fails. - SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR); - mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data2); - StaticSocketDataProvider data2(NULL, 0, NULL, 0); - mock_socket_factory_.AddSocketDataProvider(&data2); - - scoped_refptr<HttpNetworkSession> session( - new HttpNetworkSession(session_params_)); - scoped_ptr<HttpNetworkTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); - - SSLConfig& ssl_config = GetServerSSLConfig(trans.get()); - ssl_config.unrestricted_ssl3_fallback_enabled = true; - - TestCompletionCallback callback; - // This will consume |ssl_data1| and |ssl_data2|. - int rv = callback.GetResult( - trans->Start(GetRequestInfo("https://www.google.com/"), - callback.callback(), BoundNetLog())); - EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, rv); - - SocketDataProviderArray<SocketDataProvider>& mock_data = - mock_socket_factory_.mock_data(); - // Confirms that both |ssl_data1| and |ssl_data2| are consumed. - EXPECT_EQ(2u, mock_data.next_index()); - - // |version_max| fallbacks to SSL 3.0 for Google properties when - // |unrestricted_ssl3_fallback_enabled| is true. - EXPECT_EQ(SSL_PROTOCOL_VERSION_SSL3, ssl_config.version_max); - EXPECT_TRUE(ssl_config.version_fallback); -} - -// Tests that HttpNetworkTransaction attempts to fallback to SSL 3.0 -// when a TLS 1.0 handshake fails and the site is not a Google domain, -// even if unrestricted SSL 3.0 fallback is disabled. -// TODO(thaidn): revise the above comment and this test when the -// SSL 3.0 fallback experiment is applied for non-Google domains. -TEST_F(HttpNetworkTransactionSSLTest, SSL3FallbackDisabled_Paypal) { - // |ssl_data1| is for the first handshake (TLS 1.0), which will fail - // for protocol reasons (e.g., simulating a version rollback attack). - SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_PROTOCOL_ERROR); - mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data1); - StaticSocketDataProvider data1(NULL, 0, NULL, 0); - mock_socket_factory_.AddSocketDataProvider(&data1); - - // |ssl_data2| contains the handshake result for a SSL 3.0 - // handshake which will be attempted after the TLS 1.0 - // handshake fails. - SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR); - mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data2); - StaticSocketDataProvider data2(NULL, 0, NULL, 0); - mock_socket_factory_.AddSocketDataProvider(&data2); - - scoped_refptr<HttpNetworkSession> session( - new HttpNetworkSession(session_params_)); - scoped_ptr<HttpNetworkTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); - - SSLConfig& ssl_config = GetServerSSLConfig(trans.get()); - ssl_config.unrestricted_ssl3_fallback_enabled = false; - - TestCompletionCallback callback; - // This will consume |ssl_data1| and |ssl_data2|. - int rv = callback.GetResult( - trans->Start(GetRequestInfo("https://www.paypal.com/"), - callback.callback(), BoundNetLog())); - EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, rv); - - SocketDataProviderArray<SocketDataProvider>& mock_data = - mock_socket_factory_.mock_data(); - // Confirms that both |ssl_data1| and |ssl_data2| are consumed. - EXPECT_EQ(2u, mock_data.next_index()); - - // |version_max| fallbacks to SSL 3.0. - EXPECT_EQ(SSL_PROTOCOL_VERSION_SSL3, ssl_config.version_max); - EXPECT_TRUE(ssl_config.version_fallback); -} - // Tests that HttpNetworkTransaction attempts to fallback from // TLS 1.1 to TLS 1.0, then from TLS 1.0 to SSL 3.0. TEST_F(HttpNetworkTransactionSSLTest, SSLFallback) { @@ -278,9 +136,6 @@ TEST_F(HttpNetworkTransactionSSLTest, SSLFallback) { scoped_ptr<HttpNetworkTransaction> trans( new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); - SSLConfig& ssl_config = GetServerSSLConfig(trans.get()); - ssl_config.unrestricted_ssl3_fallback_enabled = true; - TestCompletionCallback callback; // This will consume |ssl_data1|, |ssl_data2| and |ssl_data3|. int rv = callback.GetResult( @@ -293,6 +148,7 @@ TEST_F(HttpNetworkTransactionSSLTest, SSLFallback) { // Confirms that |ssl_data1|, |ssl_data2| and |ssl_data3| are consumed. EXPECT_EQ(3u, mock_data.next_index()); + SSLConfig& ssl_config = GetServerSSLConfig(trans.get()); // |version_max| fallbacks to SSL 3.0. EXPECT_EQ(SSL_PROTOCOL_VERSION_SSL3, ssl_config.version_max); EXPECT_TRUE(ssl_config.version_fallback); diff --git a/chromium/net/http/http_network_transaction_unittest.cc b/chromium/net/http/http_network_transaction_unittest.cc index a2165776c08..dd9eefecf37 100644 --- a/chromium/net/http/http_network_transaction_unittest.cc +++ b/chromium/net/http/http_network_transaction_unittest.cc @@ -64,6 +64,7 @@ #include "net/ssl/ssl_config_service_defaults.h" #include "net/ssl/ssl_info.h" #include "net/test/cert_test_util.h" +#include "net/websockets/websocket_handshake_stream_base.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" #include "url/gurl.h" @@ -111,7 +112,7 @@ bool GetHeaders(base::DictionaryValue* params, std::string* headers) { return false; std::string double_quote_headers; base::JSONWriter::Write(header_list, &double_quote_headers); - ReplaceChars(double_quote_headers, "\"", "'", headers); + base::ReplaceChars(double_quote_headers, "\"", "'", headers); return true; } @@ -289,9 +290,9 @@ class HttpNetworkTransactionTest CapturingBoundNetLog log; session_deps_.net_log = log.bound().net_log(); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); for (size_t i = 0; i < data_count; ++i) { session_deps_.socket_factory->AddSocketDataProvider(data[i]); @@ -386,7 +387,8 @@ class HttpNetworkTransactionTest INSTANTIATE_TEST_CASE_P( NextProto, HttpNetworkTransactionTest, - testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2, + testing::Values(kProtoDeprecatedSPDY2, + kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2, kProtoHTTP2Draft04)); namespace { @@ -510,6 +512,7 @@ CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool( cert_verifier, NULL, NULL, + NULL, std::string(), NULL, NULL, @@ -565,9 +568,9 @@ bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) { } // namespace TEST_P(HttpNetworkTransactionTest, Basic) { + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); } TEST_P(HttpNetworkTransactionTest, SimpleGET) { @@ -860,9 +863,9 @@ TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) { request.url = GURL("http://redirect.com/"); request.load_flags = 0; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); session_deps_.socket_factory->AddSocketDataProvider(&data); @@ -904,9 +907,9 @@ TEST_P(HttpNetworkTransactionTest, Head) { request.url = GURL("http://www.google.com/"); request.load_flags = 0; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes1[] = { MockWrite("HEAD / HTTP/1.1\r\n" @@ -1008,7 +1011,7 @@ TEST_P(HttpNetworkTransactionTest, ReuseConnection) { TEST_P(HttpNetworkTransactionTest, Ignores100) { ScopedVector<UploadElementReader> element_readers; element_readers.push_back(new UploadBytesElementReader("foo", 3)); - UploadDataStream upload_data_stream(&element_readers, 0); + UploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request; request.method = "POST"; @@ -1016,9 +1019,9 @@ TEST_P(HttpNetworkTransactionTest, Ignores100) { request.upload_data_stream = &upload_data_stream; request.load_flags = 0; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockRead data_reads[] = { MockRead("HTTP/1.0 100 Continue\r\n\r\n"), @@ -1058,9 +1061,9 @@ TEST_P(HttpNetworkTransactionTest, Ignores1xx) { request.url = GURL("http://www.foo.com/"); request.load_flags = 0; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockRead data_reads[] = { MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n" @@ -1097,9 +1100,9 @@ TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) { request.url = GURL("http://www.foo.com/"); request.load_flags = 0; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockRead data_reads[] = { MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"), @@ -1128,9 +1131,10 @@ TEST_P(HttpNetworkTransactionTest, EmptyResponse) { request.url = GURL("http://www.foo.com/"); request.load_flags = 0; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); + MockRead data_reads[] = { MockRead(ASYNC, 0), @@ -1258,9 +1262,9 @@ TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) { request.url = GURL("http://www.google.com/"); request.load_flags = 0; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockRead data_reads[] = { MockRead(ASYNC, ERR_CONNECTION_RESET), @@ -1506,9 +1510,9 @@ TEST_P(HttpNetworkTransactionTest, BasicAuth) { CapturingNetLog log; session_deps_.net_log = &log; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes1[] = { MockWrite("GET / HTTP/1.1\r\n" @@ -1599,9 +1603,9 @@ TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) { request.url = GURL("http://www.google.com/"); request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes[] = { MockWrite("GET / HTTP/1.1\r\n" @@ -2262,9 +2266,9 @@ TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) { request.load_flags = 0; // We are using a DIRECT connection (i.e. no proxy) for this session. + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes1[] = { MockWrite("GET / HTTP/1.1\r\n" @@ -3528,7 +3532,6 @@ void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus( // Configure against proxy server "myproxy:70". session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); - scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); // Since we have proxy, should try to establish tunnel. @@ -3740,11 +3743,12 @@ TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) { request.url = GURL("http://www.google.com/"); request.load_flags = 0; + // Configure against proxy server "myproxy:70". session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); - // Configure against proxy server "myproxy:70". - scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes1[] = { MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" @@ -4203,9 +4207,9 @@ TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) { request.url = GURL("http://www.google.com/"); request.load_flags = 0; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); // Respond with 300 kb of headers (we should fail after 256 kb). std::string large_headers_string; @@ -4563,7 +4567,7 @@ TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) { TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) { ScopedVector<UploadElementReader> element_readers; element_readers.push_back(new UploadBytesElementReader("foo", 3)); - UploadDataStream upload_data_stream(&element_readers, 0); + UploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request[2]; // Transaction 1: a GET request that succeeds. The socket is recycled @@ -4658,9 +4662,9 @@ TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) { request.url = GURL("http://foo:b@r@www.google.com/"); request.load_flags = LOAD_NORMAL; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); // The password contains an escaped character -- for this test to pass it // will need to be unescaped by HttpNetworkTransaction. @@ -4739,9 +4743,9 @@ TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) { request.load_flags = LOAD_NORMAL; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes1[] = { MockWrite("GET / HTTP/1.1\r\n" @@ -4847,9 +4851,9 @@ TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) { request.url = GURL("http://foo:bar@www.google.com/"); request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes1[] = { MockWrite("GET / HTTP/1.1\r\n" @@ -5438,9 +5442,9 @@ TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) { // Test the ResetStateForRestart() private method. TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) { // Create a transaction (the dependencies aren't important). + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpNetworkTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); // Setup some state (which we expect ResetStateForRestart() will clear). trans->read_buf_ = new IOBuffer(15); @@ -5485,9 +5489,9 @@ TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) { request.url = GURL("https://www.google.com/"); request.load_flags = 0; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes[] = { MockWrite("GET / HTTP/1.1\r\n" @@ -5589,9 +5593,9 @@ TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) { for (int i = 0; i < 2; i++) { session_deps_.socket_factory->ResetNextMockIndexes(); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); int rv = trans->Start(&request, callback.callback(), BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -5653,9 +5657,9 @@ TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) { TestCompletionCallback callback; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); int rv = trans->Start(&request, callback.callback(), BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -5711,9 +5715,9 @@ TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) { TestCompletionCallback callback; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); int rv = trans->Start(&request, callback.callback(), BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -5796,9 +5800,9 @@ TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) { TestCompletionCallback callback; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); int rv = trans->Start(&request, callback.callback(), BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -5848,9 +5852,9 @@ TEST_P(HttpNetworkTransactionTest, TestCompletionCallback callback; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); int rv = trans->Start(&request, callback.callback(), BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -5909,9 +5913,9 @@ TEST_P(HttpNetworkTransactionTest, TestCompletionCallback callback; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); int rv = trans->Start(&request, callback.callback(), BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -6334,9 +6338,9 @@ TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) { TestCompletionCallback callback; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); int rv = trans->Start(&request, callback.callback(), BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -6363,9 +6367,9 @@ TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) { request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, "Chromium Ultra Awesome X Edition"); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes[] = { MockWrite("GET / HTTP/1.1\r\n" @@ -6403,9 +6407,9 @@ TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) { "Chromium Ultra Awesome X Edition"); session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes[] = { MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" @@ -6442,9 +6446,9 @@ TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) { request.extra_headers.SetHeader(HttpRequestHeaders::kReferer, "http://the.previous.site.com/"); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes[] = { MockWrite("GET / HTTP/1.1\r\n" @@ -6479,9 +6483,9 @@ TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) { request.method = "POST"; request.url = GURL("http://www.google.com/"); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes[] = { MockWrite("POST / HTTP/1.1\r\n" @@ -6516,9 +6520,9 @@ TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) { request.method = "PUT"; request.url = GURL("http://www.google.com/"); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes[] = { MockWrite("PUT / HTTP/1.1\r\n" @@ -6553,9 +6557,9 @@ TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) { request.method = "HEAD"; request.url = GURL("http://www.google.com/"); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes[] = { MockWrite("HEAD / HTTP/1.1\r\n" @@ -6591,9 +6595,9 @@ TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) { request.url = GURL("http://www.google.com/"); request.load_flags = LOAD_BYPASS_CACHE; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes[] = { MockWrite("GET / HTTP/1.1\r\n" @@ -6631,9 +6635,9 @@ TEST_P(HttpNetworkTransactionTest, request.url = GURL("http://www.google.com/"); request.load_flags = LOAD_VALIDATE_CACHE; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes[] = { MockWrite("GET / HTTP/1.1\r\n" @@ -6669,9 +6673,9 @@ TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) { request.url = GURL("http://www.google.com/"); request.extra_headers.SetHeader("FooHeader", "Bar"); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes[] = { MockWrite("GET / HTTP/1.1\r\n" @@ -6709,9 +6713,9 @@ TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) { request.extra_headers.SetHeader("hEllo", "Kitty"); request.extra_headers.SetHeader("FoO", "bar"); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes[] = { MockWrite("GET / HTTP/1.1\r\n" @@ -6754,9 +6758,9 @@ TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) { CapturingNetLog net_log; session_deps_.net_log = &net_log; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 }; char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 }; @@ -6813,9 +6817,9 @@ TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) { CapturingNetLog net_log; session_deps_.net_log = &net_log; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 }; unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 }; @@ -6877,9 +6881,9 @@ TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) { CapturingNetLog net_log; session_deps_.net_log = &net_log; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 }; char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 }; @@ -6936,9 +6940,9 @@ TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) { CapturingNetLog net_log; session_deps_.net_log = &net_log; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 }; const char kSOCKS5GreetResponse[] = { 0x05, 0x00 }; @@ -7009,9 +7013,9 @@ TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) { CapturingNetLog net_log; session_deps_.net_log = &net_log; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 }; const char kSOCKS5GreetResponse[] = { 0x05, 0x00 }; @@ -7169,11 +7173,12 @@ TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) { new CaptureGroupNameTransportSocketPool(NULL, NULL); CaptureGroupNameSSLSocketPool* ssl_conn_pool = new CaptureGroupNameSSLSocketPool(NULL, NULL); - MockClientSocketPoolManager* mock_pool_manager = - new MockClientSocketPoolManager; + scoped_ptr<MockClientSocketPoolManager> mock_pool_manager( + new MockClientSocketPoolManager); mock_pool_manager->SetTransportSocketPool(transport_conn_pool); mock_pool_manager->SetSSLSocketPool(ssl_conn_pool); - peer.SetClientSocketPoolManager(mock_pool_manager); + peer.SetClientSocketPoolManager( + mock_pool_manager.PassAs<ClientSocketPoolManager>()); EXPECT_EQ(ERR_IO_PENDING, GroupNameTransactionHelper(tests[i].url, session)); @@ -7235,11 +7240,12 @@ TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) { CaptureGroupNameSSLSocketPool* ssl_conn_pool = new CaptureGroupNameSSLSocketPool(NULL, NULL); - MockClientSocketPoolManager* mock_pool_manager = - new MockClientSocketPoolManager; + scoped_ptr<MockClientSocketPoolManager> mock_pool_manager( + new MockClientSocketPoolManager); mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool); mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool); - peer.SetClientSocketPoolManager(mock_pool_manager); + peer.SetClientSocketPoolManager( + mock_pool_manager.PassAs<ClientSocketPoolManager>()); EXPECT_EQ(ERR_IO_PENDING, GroupNameTransactionHelper(tests[i].url, session)); @@ -7305,11 +7311,12 @@ TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) { CaptureGroupNameSSLSocketPool* ssl_conn_pool = new CaptureGroupNameSSLSocketPool(NULL, NULL); - MockClientSocketPoolManager* mock_pool_manager = - new MockClientSocketPoolManager; + scoped_ptr<MockClientSocketPoolManager> mock_pool_manager( + new MockClientSocketPoolManager); mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool); mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool); - peer.SetClientSocketPoolManager(mock_pool_manager); + peer.SetClientSocketPoolManager( + mock_pool_manager.PassAs<ClientSocketPoolManager>()); scoped_ptr<HttpTransaction> trans( new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); @@ -7337,9 +7344,9 @@ TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) { // connecting to both proxies (myproxy:70 and foobar:80). session_deps_.host_resolver->rules()->AddSimulatedFailure("*"); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); TestCompletionCallback callback; @@ -7363,8 +7370,9 @@ void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper( // Select a host resolver that does caching. session_deps_.host_resolver.reset(new MockCachingHostResolver); - scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); // Warm up the host cache so it has an entry for "www.google.com". AddressList addrlist; @@ -7428,8 +7436,6 @@ TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) { // Make sure we can handle an error when writing the request. TEST_P(HttpNetworkTransactionTest, RequestWriteError) { - scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); - HttpRequestInfo request; request.method = "GET"; request.url = GURL("http://www.foo.com/"); @@ -7441,12 +7447,12 @@ TEST_P(HttpNetworkTransactionTest, RequestWriteError) { StaticSocketDataProvider data(NULL, 0, write_failure, arraysize(write_failure)); session_deps_.socket_factory->AddSocketDataProvider(&data); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); TestCompletionCallback callback; scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); int rv = trans->Start(&request, callback.callback(), BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -7457,8 +7463,6 @@ TEST_P(HttpNetworkTransactionTest, RequestWriteError) { // Check that a connection closed after the start of the headers finishes ok. TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) { - scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); - HttpRequestInfo request; request.method = "GET"; request.url = GURL("http://www.foo.com/"); @@ -7471,12 +7475,12 @@ TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) { StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); session_deps_.socket_factory->AddSocketDataProvider(&data); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); TestCompletionCallback callback; scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); int rv = trans->Start(&request, callback.callback(), BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -7499,8 +7503,6 @@ TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) { // Make sure that a dropped connection while draining the body for auth // restart does the right thing. TEST_P(HttpNetworkTransactionTest, DrainResetOK) { - scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); - HttpRequestInfo request; request.method = "GET"; request.url = GURL("http://www.google.com/"); @@ -7545,6 +7547,7 @@ TEST_P(HttpNetworkTransactionTest, DrainResetOK) { StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), data_writes2, arraysize(data_writes2)); session_deps_.socket_factory->AddSocketDataProvider(&data2); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); TestCompletionCallback callback1; @@ -7600,9 +7603,9 @@ TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) { session_deps_.socket_factory->ResetNextMockIndexes(); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); int rv = trans->Start(&request, callback.callback(), BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -7617,9 +7620,9 @@ TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) { request.url = GURL("http://www.google.com/"); request.load_flags = 0; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockRead data_reads[] = { MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"), @@ -7649,7 +7652,7 @@ TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) { TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) { base::FilePath temp_file_path; - ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path)); + ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path)); const uint64 kFakeSize = 100000; // file is actually blank UploadFileElementReader::ScopedOverridingContentLengthForTests overriding_content_length(kFakeSize); @@ -7661,7 +7664,7 @@ TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) { 0, kuint64max, base::Time())); - UploadDataStream upload_data_stream(&element_readers, 0); + UploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request; request.method = "POST"; @@ -7669,9 +7672,9 @@ TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) { request.upload_data_stream = &upload_data_stream; request.load_flags = 0; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockRead data_reads[] = { MockRead("HTTP/1.0 200 OK\r\n\r\n"), @@ -7705,7 +7708,7 @@ TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) { TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) { base::FilePath temp_file; - ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file)); + ASSERT_TRUE(base::CreateTemporaryFile(&temp_file)); std::string temp_file_content("Unreadable file."); ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(), temp_file_content.length())); @@ -7718,7 +7721,7 @@ TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) { 0, kuint64max, base::Time())); - UploadDataStream upload_data_stream(&element_readers, 0); + UploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request; request.method = "POST"; @@ -7726,25 +7729,12 @@ TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) { request.upload_data_stream = &upload_data_stream; request.load_flags = 0; - // If we try to upload an unreadable file, the network stack should report - // the file size as zero and upload zero bytes for that file. + // If we try to upload an unreadable file, the transaction should fail. + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); - MockRead data_reads[] = { - MockRead("HTTP/1.0 200 OK\r\n\r\n"), - MockRead(SYNCHRONOUS, OK), - }; - MockWrite data_writes[] = { - MockWrite("POST /upload HTTP/1.1\r\n" - "Host: www.google.com\r\n" - "Connection: keep-alive\r\n" - "Content-Length: 0\r\n\r\n"), - MockWrite(SYNCHRONOUS, OK), - }; - StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes, - arraysize(data_writes)); + StaticSocketDataProvider data(NULL, 0, NULL, 0); session_deps_.socket_factory->AddSocketDataProvider(&data); TestCompletionCallback callback; @@ -7753,32 +7743,43 @@ TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) { EXPECT_EQ(ERR_IO_PENDING, rv); rv = callback.WaitForResult(); - EXPECT_EQ(OK, rv); + EXPECT_EQ(ERR_ACCESS_DENIED, rv); const HttpResponseInfo* response = trans->GetResponseInfo(); - ASSERT_TRUE(response != NULL); - EXPECT_TRUE(response->headers.get() != NULL); - EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine()); + EXPECT_FALSE(response); base::DeleteFile(temp_file, false); } -TEST_P(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) { - base::FilePath temp_file; - ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file)); - std::string temp_file_contents("Unreadable file."); - std::string unreadable_contents(temp_file_contents.length(), '\0'); - ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(), - temp_file_contents.length())); +TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) { + class FakeUploadElementReader : public UploadElementReader { + public: + FakeUploadElementReader() {} + virtual ~FakeUploadElementReader() {} + + const CompletionCallback& callback() const { return callback_; } + // UploadElementReader overrides: + virtual int Init(const CompletionCallback& callback) OVERRIDE { + callback_ = callback; + return ERR_IO_PENDING; + } + virtual uint64 GetContentLength() const OVERRIDE { return 0; } + virtual uint64 BytesRemaining() const OVERRIDE { return 0; } + virtual int Read(IOBuffer* buf, + int buf_length, + const CompletionCallback& callback) OVERRIDE { + return ERR_FAILED; + } + + private: + CompletionCallback callback_; + }; + + FakeUploadElementReader* fake_reader = new FakeUploadElementReader; ScopedVector<UploadElementReader> element_readers; - element_readers.push_back( - new UploadFileElementReader(base::MessageLoopProxy::current().get(), - temp_file, - 0, - kuint64max, - base::Time())); - UploadDataStream upload_data_stream(&element_readers, 0); + element_readers.push_back(fake_reader); + UploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request; request.method = "POST"; @@ -7786,72 +7787,24 @@ TEST_P(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) { request.upload_data_stream = &upload_data_stream; request.load_flags = 0; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); - - MockRead data_reads[] = { - MockRead("HTTP/1.1 401 Unauthorized\r\n"), - MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), - MockRead("Content-Length: 0\r\n\r\n"), // No response body. + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); - MockRead("HTTP/1.1 200 OK\r\n"), - MockRead("Content-Length: 0\r\n\r\n"), - MockRead(SYNCHRONOUS, OK), - }; - MockWrite data_writes[] = { - MockWrite("POST /upload HTTP/1.1\r\n" - "Host: www.google.com\r\n" - "Connection: keep-alive\r\n" - "Content-Length: 16\r\n\r\n"), - MockWrite(SYNCHRONOUS, temp_file_contents.c_str()), - - MockWrite("POST /upload HTTP/1.1\r\n" - "Host: www.google.com\r\n" - "Connection: keep-alive\r\n" - "Content-Length: 0\r\n" - "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), - MockWrite(SYNCHRONOUS, unreadable_contents.c_str(), - temp_file_contents.length()), - MockWrite(SYNCHRONOUS, OK), - }; - StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes, - arraysize(data_writes)); + StaticSocketDataProvider data; session_deps_.socket_factory->AddSocketDataProvider(&data); - TestCompletionCallback callback1; - - int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - - rv = callback1.WaitForResult(); - EXPECT_EQ(OK, rv); - - const HttpResponseInfo* response = trans->GetResponseInfo(); - ASSERT_TRUE(response != NULL); - ASSERT_TRUE(response->headers.get() != NULL); - EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine()); - EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); - - // Now make the file unreadable and try again. - ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file)); - - TestCompletionCallback callback2; - - rv = trans->RestartWithAuth( - AuthCredentials(kFoo, kBar), callback2.callback()); + TestCompletionCallback callback; + int rv = trans->Start(&request, callback.callback(), BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); + base::MessageLoop::current()->RunUntilIdle(); - rv = callback2.WaitForResult(); - EXPECT_EQ(OK, rv); - - response = trans->GetResponseInfo(); - ASSERT_TRUE(response != NULL); - EXPECT_TRUE(response->headers.get() != NULL); - EXPECT_TRUE(response->auth_challenge.get() == NULL); - EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); + // Transaction is pending on request body initialization. + ASSERT_FALSE(fake_reader->callback().is_null()); - base::DeleteFile(temp_file, false); + // Return Init()'s result after the transaction gets destroyed. + trans.reset(); + fake_reader->callback().Run(OK); // Should not crash. } // Tests that changes to Auth realms are treated like auth rejections. @@ -7938,9 +7891,9 @@ TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) { TestCompletionCallback callback1; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); // Issue the first request with Authorize headers. There should be a // password prompt for first_realm waiting to be filled in after the @@ -9313,8 +9266,7 @@ TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) { request.load_flags = 0; scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); - HttpNetworkTransaction trans( - DEFAULT_PRIORITY, CreateSession(&session_deps_)); + HttpNetworkTransaction trans(DEFAULT_PRIORITY, session); for (int round = 0; round < test_config.num_auth_rounds; ++round) { const TestRound& read_write_round = test_config.rounds[round]; @@ -9416,10 +9368,11 @@ TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) { session_deps_.host_resolver.get(), session_deps_.socket_factory.get(), session_deps_.net_log); - MockClientSocketPoolManager* mock_pool_manager = - new MockClientSocketPoolManager; + scoped_ptr<MockClientSocketPoolManager> mock_pool_manager( + new MockClientSocketPoolManager); mock_pool_manager->SetTransportSocketPool(transport_pool); - session_peer.SetClientSocketPoolManager(mock_pool_manager); + session_peer.SetClientSocketPoolManager( + mock_pool_manager.PassAs<ClientSocketPoolManager>()); scoped_ptr<HttpTransaction> trans( new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); @@ -9869,9 +9822,9 @@ TEST_P(HttpNetworkTransactionTest, SimpleCancel) { request.load_flags = 0; session_deps_.host_resolver->set_synchronous_mode(true); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); data.set_connect_data(mock_connect); @@ -11551,9 +11504,9 @@ TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) { request.url = GURL("http://www.google.com/"); request.load_flags = 0; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED); StaticSocketDataProvider data; @@ -11581,9 +11534,9 @@ TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) { request.url = GURL("http://www.google.com/"); request.load_flags = 0; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED); StaticSocketDataProvider data; @@ -11611,9 +11564,9 @@ TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) { request.url = GURL("http://www.google.com/"); request.load_flags = 0; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes[] = { MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET), @@ -11647,9 +11600,9 @@ TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) { request.url = GURL("http://www.google.com/"); request.load_flags = 0; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes[] = { MockWrite(ASYNC, ERR_CONNECTION_RESET), @@ -11683,9 +11636,9 @@ TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) { request.url = GURL("http://www.google.com/"); request.load_flags = 0; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes[] = { MockWrite("GET / HTTP/1.1\r\n" @@ -11721,9 +11674,9 @@ TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) { request.url = GURL("http://www.google.com/"); request.load_flags = 0; + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes[] = { MockWrite("GET / HTTP/1.1\r\n" @@ -11760,9 +11713,9 @@ TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) { request.load_flags = 0; request.extra_headers.SetHeader("X-Foo", "bar"); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, - CreateSession(&session_deps_))); + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); MockWrite data_writes[] = { MockWrite("GET / HTTP/1.1\r\n" @@ -11862,6 +11815,11 @@ class FakeStream : public HttpStreamBase, return false; } + virtual int64 GetTotalReceivedBytes() const OVERRIDE { + ADD_FAILURE(); + return 0; + } + virtual bool GetLoadTimingInfo( LoadTimingInfo* load_timing_info) const OVERRIDE { ADD_FAILURE(); @@ -11904,12 +11862,25 @@ class FakeStreamRequest : public HttpStreamRequest, FakeStreamRequest(RequestPriority priority, HttpStreamRequest::Delegate* delegate) : priority_(priority), - delegate_(delegate) {} + delegate_(delegate), + websocket_stream_create_helper_(NULL) {} + + FakeStreamRequest(RequestPriority priority, + HttpStreamRequest::Delegate* delegate, + WebSocketHandshakeStreamBase::CreateHelper* create_helper) + : priority_(priority), + delegate_(delegate), + websocket_stream_create_helper_(create_helper) {} virtual ~FakeStreamRequest() {} RequestPriority priority() const { return priority_; } + const WebSocketHandshakeStreamBase::CreateHelper* + websocket_stream_create_helper() const { + return websocket_stream_create_helper_; + } + // Create a new FakeStream and pass it to the request's // delegate. Returns a weak pointer to the FakeStream. base::WeakPtr<FakeStream> FinishStreamRequest() { @@ -11951,6 +11922,7 @@ class FakeStreamRequest : public HttpStreamRequest, private: RequestPriority priority_; HttpStreamRequest::Delegate* const delegate_; + WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_; DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest); }; @@ -11979,16 +11951,18 @@ class FakeStreamFactory : public HttpStreamFactory { return fake_request; } - virtual HttpStreamRequest* RequestWebSocketStream( + virtual HttpStreamRequest* RequestWebSocketHandshakeStream( const HttpRequestInfo& info, RequestPriority priority, const SSLConfig& server_ssl_config, const SSLConfig& proxy_ssl_config, HttpStreamRequest::Delegate* delegate, - WebSocketStreamBase::Factory* factory, + WebSocketHandshakeStreamBase::CreateHelper* create_helper, const BoundNetLog& net_log) OVERRIDE { - ADD_FAILURE(); - return NULL; + FakeStreamRequest* fake_request = + new FakeStreamRequest(priority, delegate, create_helper); + last_stream_request_ = fake_request->AsWeakPtr(); + return fake_request; } virtual void PreconnectStreams(int num_streams, @@ -12015,6 +11989,33 @@ class FakeStreamFactory : public HttpStreamFactory { DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory); }; +// TODO(yhirano): Split this class out into a net/websockets file, if it is +// worth doing. +class FakeWebSocketStreamCreateHelper : + public WebSocketHandshakeStreamBase::CreateHelper { + public: + virtual WebSocketHandshakeStreamBase* CreateBasicStream( + scoped_ptr<ClientSocketHandle> connection, + bool using_proxy) OVERRIDE { + NOTREACHED(); + return NULL; + } + + virtual WebSocketHandshakeStreamBase* CreateSpdyStream( + const base::WeakPtr<SpdySession>& session, + bool use_relative_url) OVERRIDE { + NOTREACHED(); + return NULL; + }; + + virtual ~FakeWebSocketStreamCreateHelper() {} + + virtual scoped_ptr<WebSocketStream> Upgrade() { + NOTREACHED(); + return scoped_ptr<WebSocketStream>(); + } +}; + } // namespace // Make sure that HttpNetworkTransaction passes on its priority to its @@ -12023,7 +12024,7 @@ TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) { scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); HttpNetworkSessionPeer peer(session); FakeStreamFactory* fake_factory = new FakeStreamFactory(); - peer.SetHttpStreamFactory(fake_factory); + peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory)); HttpNetworkTransaction trans(LOW, session); @@ -12046,7 +12047,7 @@ TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) { scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); HttpNetworkSessionPeer peer(session); FakeStreamFactory* fake_factory = new FakeStreamFactory(); - peer.SetHttpStreamFactory(fake_factory); + peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory)); HttpNetworkTransaction trans(LOW, session); @@ -12071,7 +12072,7 @@ TEST_P(HttpNetworkTransactionTest, SetStreamPriority) { scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); HttpNetworkSessionPeer peer(session); FakeStreamFactory* fake_factory = new FakeStreamFactory(); - peer.SetHttpStreamFactory(fake_factory); + peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory)); HttpNetworkTransaction trans(LOW, session); @@ -12091,6 +12092,39 @@ TEST_P(HttpNetworkTransactionTest, SetStreamPriority) { EXPECT_EQ(LOWEST, fake_stream->priority()); } +TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) { + // The same logic needs to be tested for both ws: and wss: schemes, but this + // test is already parameterised on NextProto, so it uses a loop to verify + // that the different schemes work. + std::string test_cases[] = {"ws://www.google.com/", "wss://www.google.com/"}; + for (size_t i = 0; i < arraysize(test_cases); ++i) { + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + HttpNetworkSessionPeer peer(session); + FakeStreamFactory* fake_factory = new FakeStreamFactory(); + FakeWebSocketStreamCreateHelper websocket_stream_create_helper; + peer.SetHttpStreamFactoryForWebSocket( + scoped_ptr<HttpStreamFactory>(fake_factory)); + + HttpNetworkTransaction trans(LOW, session); + trans.SetWebSocketHandshakeStreamCreateHelper( + &websocket_stream_create_helper); + + HttpRequestInfo request; + TestCompletionCallback callback; + request.method = "GET"; + request.url = GURL(test_cases[i]); + + EXPECT_EQ(ERR_IO_PENDING, + trans.Start(&request, callback.callback(), BoundNetLog())); + + base::WeakPtr<FakeStreamRequest> fake_request = + fake_factory->last_stream_request(); + ASSERT_TRUE(fake_request != NULL); + EXPECT_EQ(&websocket_stream_create_helper, + fake_request->websocket_stream_create_helper()); + } +} + // Tests that when a used socket is returned to the SSL socket pool, it's closed // if the transport socket pool is stalled on the global socket limit. TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) { diff --git a/chromium/net/http/http_pipelined_connection_impl.cc b/chromium/net/http/http_pipelined_connection_impl.cc index e2e53de47ba..284b25406d8 100644 --- a/chromium/net/http/http_pipelined_connection_impl.cc +++ b/chromium/net/http/http_pipelined_connection_impl.cc @@ -653,6 +653,13 @@ void HttpPipelinedConnectionImpl::SetConnectionReused(int pipeline_id) { connection_->set_is_reused(true); } +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(); +} + bool HttpPipelinedConnectionImpl::GetLoadTimingInfo( int pipeline_id, LoadTimingInfo* load_timing_info) const { return connection_->GetLoadTimingInfo(IsConnectionReused(pipeline_id), diff --git a/chromium/net/http/http_pipelined_connection_impl.h b/chromium/net/http/http_pipelined_connection_impl.h index f8246a06f9b..d558e47eb0b 100644 --- a/chromium/net/http/http_pipelined_connection_impl.h +++ b/chromium/net/http/http_pipelined_connection_impl.h @@ -125,6 +125,8 @@ class NET_EXPORT_PRIVATE HttpPipelinedConnectionImpl void SetConnectionReused(int pipeline_id); + int64 GetTotalReceivedBytes(int pipeline_id) const; + bool GetLoadTimingInfo(int pipeline_id, LoadTimingInfo* load_timing_info) const; diff --git a/chromium/net/http/http_pipelined_host_forced_unittest.cc b/chromium/net/http/http_pipelined_host_forced_unittest.cc index 37732aa800f..b86dd96d50a 100644 --- a/chromium/net/http/http_pipelined_host_forced_unittest.cc +++ b/chromium/net/http/http_pipelined_host_forced_unittest.cc @@ -37,7 +37,7 @@ class HttpPipelinedHostForcedTest : public testing::Test { MatchesOrigin(key_.origin()), Ref(ssl_config_), Ref(proxy_info_), Ref(net_log_), true, - kProtoSPDY2)) + kProtoSPDY3)) .Times(1) .WillOnce(Return(pipeline)); EXPECT_CALL(*pipeline, CreateNewStream()) @@ -45,7 +45,7 @@ class HttpPipelinedHostForcedTest : public testing::Test { .WillOnce(Return(kDummyStream)); EXPECT_EQ(kDummyStream, host_->CreateStreamOnNewPipeline( &connection_, ssl_config_, proxy_info_, net_log_, true, - kProtoSPDY2)); + kProtoSPDY3)); return pipeline; } diff --git a/chromium/net/http/http_pipelined_host_impl_unittest.cc b/chromium/net/http/http_pipelined_host_impl_unittest.cc index ea49e12c105..2658472138d 100644 --- a/chromium/net/http/http_pipelined_host_impl_unittest.cc +++ b/chromium/net/http/http_pipelined_host_impl_unittest.cc @@ -48,7 +48,7 @@ class HttpPipelinedHostImplTest : public testing::Test { MatchesOrigin(key_.origin()), Ref(ssl_config_), Ref(proxy_info_), Ref(net_log_), true, - kProtoSPDY2)) + kProtoSPDY3)) .Times(1) .WillOnce(Return(pipeline)); EXPECT_CALL(*pipeline, CreateNewStream()) @@ -56,7 +56,7 @@ class HttpPipelinedHostImplTest : public testing::Test { .WillOnce(Return(kDummyStream)); EXPECT_EQ(kDummyStream, host_->CreateStreamOnNewPipeline( kDummyConnection, ssl_config_, proxy_info_, net_log_, true, - kProtoSPDY2)); + kProtoSPDY3)); return pipeline; } @@ -208,7 +208,7 @@ TEST_F(HttpPipelinedHostImplTest, ShutsDownOnOldVersion) { ClearTestPipeline(pipeline); EXPECT_EQ(NULL, host_->CreateStreamOnNewPipeline( kDummyConnection, ssl_config_, proxy_info_, net_log_, true, - kProtoSPDY2)); + kProtoSPDY3)); } TEST_F(HttpPipelinedHostImplTest, ShutsDownOnAuthenticationRequired) { @@ -227,7 +227,7 @@ TEST_F(HttpPipelinedHostImplTest, ShutsDownOnAuthenticationRequired) { ClearTestPipeline(pipeline); EXPECT_EQ(NULL, host_->CreateStreamOnNewPipeline( kDummyConnection, ssl_config_, proxy_info_, net_log_, true, - kProtoSPDY2)); + kProtoSPDY3)); } TEST_F(HttpPipelinedHostImplTest, ConnectionCloseHasNoEffect) { diff --git a/chromium/net/http/http_pipelined_stream.cc b/chromium/net/http/http_pipelined_stream.cc index df5743556d1..cc267e2510e 100644 --- a/chromium/net/http/http_pipelined_stream.cc +++ b/chromium/net/http/http_pipelined_stream.cc @@ -99,6 +99,10 @@ bool HttpPipelinedStream::IsConnectionReusable() const { return pipeline_->usable(); } +int64 HttpPipelinedStream::GetTotalReceivedBytes() const { + return pipeline_->GetTotalReceivedBytes(pipeline_id_); +} + bool HttpPipelinedStream::GetLoadTimingInfo( LoadTimingInfo* load_timing_info) const { return pipeline_->GetLoadTimingInfo(pipeline_id_, load_timing_info); diff --git a/chromium/net/http/http_pipelined_stream.h b/chromium/net/http/http_pipelined_stream.h index d3a7991e5ca..7a853abc1a7 100644 --- a/chromium/net/http/http_pipelined_stream.h +++ b/chromium/net/http/http_pipelined_stream.h @@ -69,6 +69,8 @@ class HttpPipelinedStream : public HttpStream { virtual bool IsConnectionReusable() const OVERRIDE; + virtual int64 GetTotalReceivedBytes() const OVERRIDE; + virtual bool GetLoadTimingInfo( LoadTimingInfo* load_timing_info) const OVERRIDE; diff --git a/chromium/net/http/http_proxy_client_socket_pool_unittest.cc b/chromium/net/http/http_proxy_client_socket_pool_unittest.cc index 808305240ad..a70fe6ab067 100644 --- a/chromium/net/http/http_proxy_client_socket_pool_unittest.cc +++ b/chromium/net/http/http_proxy_client_socket_pool_unittest.cc @@ -41,7 +41,7 @@ enum HttpProxyType { struct HttpProxyClientSocketPoolTestParams { HttpProxyClientSocketPoolTestParams() : proxy_type(HTTP), - protocol(kProtoSPDY2) {} + protocol(kProtoSPDY3) {} HttpProxyClientSocketPoolTestParams( HttpProxyType proxy_type, @@ -77,6 +77,7 @@ class HttpProxyClientSocketPoolTest session_deps_.cert_verifier.get(), NULL /* server_bound_cert_store */, NULL /* transport_security_state */, + NULL /* cert_transparency_verifier */, std::string() /* ssl_session_cache_shard */, session_deps_.deterministic_socket_factory.get(), &transport_socket_pool_, @@ -238,9 +239,9 @@ INSTANTIATE_TEST_CASE_P( HttpProxyClientSocketPoolTests, HttpProxyClientSocketPoolTest, ::testing::Values( - HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY2), - HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY2), - HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY2), + HttpProxyClientSocketPoolTestParams(HTTP, kProtoDeprecatedSPDY2), + HttpProxyClientSocketPoolTestParams(HTTPS, kProtoDeprecatedSPDY2), + HttpProxyClientSocketPoolTestParams(SPDY, kProtoDeprecatedSPDY2), HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY3), HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY3), HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY3), diff --git a/chromium/net/http/http_request_headers.cc b/chromium/net/http/http_request_headers.cc index bf557df37b8..8c9c4289336 100644 --- a/chromium/net/http/http_request_headers.cc +++ b/chromium/net/http/http_request_headers.cc @@ -11,6 +11,18 @@ #include "base/values.h" #include "net/http/http_util.h" +namespace { + +bool ShouldShowHttpHeaderValue(const std::string& header_name) { +#if defined(SPDY_PROXY_AUTH_ORIGIN) + if (header_name == "Proxy-Authorization") + return false; +#endif + return true; +} + +} // namespace + namespace net { const char HttpRequestHeaders::kGetMethod[] = "GET"; @@ -191,10 +203,11 @@ base::Value* HttpRequestHeaders::NetLogCallback( base::ListValue* headers = new base::ListValue(); for (HeaderVector::const_iterator it = headers_.begin(); it != headers_.end(); ++it) { - headers->Append( - new base::StringValue(base::StringPrintf("%s: %s", - it->key.c_str(), - it->value.c_str()))); + headers->Append(new base::StringValue( + base::StringPrintf("%s: %s", + it->key.c_str(), + (ShouldShowHttpHeaderValue(it->key) ? + it->value.c_str() : "[elided]")))); } dict->Set("headers", headers); return dict; diff --git a/chromium/net/http/http_request_info.cc b/chromium/net/http/http_request_info.cc index 7feb4ac3d7f..bffc96ccfae 100644 --- a/chromium/net/http/http_request_info.cc +++ b/chromium/net/http/http_request_info.cc @@ -10,7 +10,6 @@ HttpRequestInfo::HttpRequestInfo() : upload_data_stream(NULL), load_flags(0), motivation(NORMAL_MOTIVATION), - request_id(0), privacy_mode(kPrivacyModeDisabled) { } diff --git a/chromium/net/http/http_request_info.h b/chromium/net/http/http_request_info.h index 607bba5806d..a587a421b58 100644 --- a/chromium/net/http/http_request_info.h +++ b/chromium/net/http/http_request_info.h @@ -49,10 +49,6 @@ struct NET_EXPORT HttpRequestInfo { // The motivation behind this request. RequestMotivation motivation; - // An optional globally unique identifier for this request for use by the - // consumer. 0 is invalid. - uint64 request_id; - // If enabled, then request must be sent over connection that cannot be // tracked by the server (e.g. without channel id). PrivacyMode privacy_mode; diff --git a/chromium/net/http/http_response_body_drainer.cc b/chromium/net/http/http_response_body_drainer.cc index d8f00853509..a1ba35ad31e 100644 --- a/chromium/net/http/http_response_body_drainer.cc +++ b/chromium/net/http/http_response_body_drainer.cc @@ -9,11 +9,11 @@ #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/http/http_network_session.h" -#include "net/http/http_stream.h" +#include "net/http/http_stream_base.h" namespace net { -HttpResponseBodyDrainer::HttpResponseBodyDrainer(HttpStream* stream) +HttpResponseBodyDrainer::HttpResponseBodyDrainer(HttpStreamBase* stream) : read_size_(0), stream_(stream), next_state_(STATE_NONE), diff --git a/chromium/net/http/http_response_body_drainer.h b/chromium/net/http/http_response_body_drainer.h index 915305cda46..284d08a99cd 100644 --- a/chromium/net/http/http_response_body_drainer.h +++ b/chromium/net/http/http_response_body_drainer.h @@ -15,7 +15,7 @@ namespace net { -class HttpStream; +class HttpStreamBase; class IOBuffer; class NET_EXPORT_PRIVATE HttpResponseBodyDrainer { @@ -27,7 +27,7 @@ class NET_EXPORT_PRIVATE HttpResponseBodyDrainer { static const int kDrainBodyBufferSize = 16384; static const int kTimeoutInSeconds = 5; - explicit HttpResponseBodyDrainer(HttpStream* stream); + explicit HttpResponseBodyDrainer(HttpStreamBase* stream); ~HttpResponseBodyDrainer(); // Starts reading the body until completion, or we hit the buffer limit, or we @@ -56,7 +56,7 @@ class NET_EXPORT_PRIVATE HttpResponseBodyDrainer { int read_size_; scoped_refptr<IOBuffer> read_buf_; - const scoped_ptr<HttpStream> stream_; + const scoped_ptr<HttpStreamBase> stream_; State next_state_; int total_read_; CompletionCallback user_callback_; diff --git a/chromium/net/http/http_response_body_drainer_unittest.cc b/chromium/net/http/http_response_body_drainer_unittest.cc index 70134cce1ea..f587b908529 100644 --- a/chromium/net/http/http_response_body_drainer_unittest.cc +++ b/chromium/net/http/http_response_body_drainer_unittest.cc @@ -101,6 +101,7 @@ class MockHttpStream : public HttpStream { virtual bool IsConnectionReused() const OVERRIDE { return false; } virtual void SetConnectionReused() OVERRIDE {} virtual bool IsConnectionReusable() const OVERRIDE { return false; } + virtual int64 GetTotalReceivedBytes() const OVERRIDE { return 0; } virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE {} virtual void GetSSLCertRequestInfo( SSLCertRequestInfo* cert_request_info) OVERRIDE {} diff --git a/chromium/net/http/http_response_headers.cc b/chromium/net/http/http_response_headers.cc index 6047aa12ac8..289facd4f9e 100644 --- a/chromium/net/http/http_response_headers.cc +++ b/chromium/net/http/http_response_headers.cc @@ -113,6 +113,14 @@ void CheckDoesNotHaveEmbededNulls(const std::string& str) { CHECK(str.find('\0') == std::string::npos); } +bool ShouldShowHttpHeaderValue(const std::string& header_name) { +#if defined(SPDY_PROXY_AUTH_ORIGIN) + if (header_name == "Proxy-Authenticate") + return false; +#endif + return true; +} + } // namespace struct HttpResponseHeaders::ParsedHeader { @@ -1309,9 +1317,11 @@ base::Value* HttpResponseHeaders::NetLogCallback( std::string value; while (EnumerateHeaderLines(&iterator, &name, &value)) { headers->Append( - new base::StringValue(base::StringPrintf("%s: %s", - name.c_str(), - value.c_str()))); + new base::StringValue( + base::StringPrintf("%s: %s", + name.c_str(), + (ShouldShowHttpHeaderValue(name) ? + value.c_str() : "[elided]")))); } dict->Set("headers", headers); return dict; @@ -1354,4 +1364,59 @@ bool HttpResponseHeaders::IsChunkEncoded() const { HasHeaderValue("Transfer-Encoding", "chunked"); } +#if defined(SPDY_PROXY_AUTH_ORIGIN) +bool HttpResponseHeaders::GetChromeProxyBypassDuration( + const std::string& action_prefix, + base::TimeDelta* duration) const { + void* iter = NULL; + std::string value; + std::string name = "chrome-proxy"; + + while (EnumerateHeader(&iter, name, &value)) { + if (value.size() > action_prefix.size()) { + if (LowerCaseEqualsASCII(value.begin(), + value.begin() + action_prefix.size(), + action_prefix.c_str())) { + int64 seconds; + if (!base::StringToInt64( + StringPiece(value.begin() + action_prefix.size(), value.end()), + &seconds) || seconds < 0) { + continue; // In case there is a well formed instruction. + } + *duration = TimeDelta::FromSeconds(seconds); + return true; + } + } + } + return false; +} + +bool HttpResponseHeaders::GetChromeProxyInfo( + ChromeProxyInfo* proxy_info) const { + DCHECK(proxy_info); + proxy_info->bypass_all = false; + proxy_info->bypass_duration = base::TimeDelta(); + + // Support header of the form Chrome-Proxy: bypass|block=<duration>, where + // <duration> is the number of seconds to wait before retrying + // the proxy. If the duration is 0, then the default proxy retry delay + // (specified in |ProxyList::UpdateRetryInfoOnFallback|) will be used. + // 'bypass' instructs Chrome to bypass the currently connected Chrome proxy, + // whereas 'block' instructs Chrome to bypass all available Chrome proxies. + + // 'block' takes precedence over 'bypass', so look for it first. + // TODO(bengr): Reduce checks for 'block' and 'bypass' to a single loop. + if (GetChromeProxyBypassDuration("block=", &proxy_info->bypass_duration)) { + proxy_info->bypass_all = true; + return true; + } + + // Next, look for 'bypass'. + if (GetChromeProxyBypassDuration("bypass=", &proxy_info->bypass_duration)) + return true; + + return false; +} +#endif // defined(SPDY_PROXY_AUTH_ORIGIN) + } // namespace net diff --git a/chromium/net/http/http_response_headers.h b/chromium/net/http/http_response_headers.h index 61075979535..e54ac5df669 100644 --- a/chromium/net/http/http_response_headers.h +++ b/chromium/net/http/http_response_headers.h @@ -250,6 +250,28 @@ class NET_EXPORT HttpResponseHeaders // Returns true if the response is chunk-encoded. bool IsChunkEncoded() const; +#if defined (SPDY_PROXY_AUTH_ORIGIN) + // Contains instructions contained in the Chrome-Proxy header. + struct ChromeProxyInfo { + ChromeProxyInfo() : bypass_all(false) {} + + // True if Chrome should bypass all available Chrome proxies. False if only + // the currently connected Chrome proxy should be bypassed. + bool bypass_all; + + // Amount of time to bypass the Chrome proxy or proxies. + base::TimeDelta bypass_duration; + }; + + // Returns true if the Chrome-Proxy header is present and contains a bypass + // delay. Sets |proxy_info->bypass_duration| to the specified delay if greater + // than 0, and to 0 otherwise to indicate that the default proxy delay + // (as specified in |ProxyList::UpdateRetryInfoOnFallback|) should be used. + // If all available Chrome proxies should by bypassed, |bypass_all| is set to + // true. |proxy_info| must be non-NULL. + bool GetChromeProxyInfo(ChromeProxyInfo* proxy_info) const; +#endif + // Creates a Value for use with the NetLog containing the response headers. base::Value* NetLogCallback(NetLog::LogLevel log_level) const; @@ -348,6 +370,13 @@ class NET_EXPORT HttpResponseHeaders // Adds the set of transport security state headers. static void AddSecurityStateHeaders(HeaderSet* header_names); +#if defined(SPDY_PROXY_AUTH_ORIGIN) + // Searches for the specified Chrome-Proxy action, and if present interprets + // its value as a duration in seconds. + bool GetChromeProxyBypassDuration(const std::string& action_prefix, + base::TimeDelta* duration) const; +#endif + // We keep a list of ParsedHeader objects. These tell us where to locate the // header-value pairs within raw_headers_. HeaderList parsed_; diff --git a/chromium/net/http/http_response_headers_unittest.cc b/chromium/net/http/http_response_headers_unittest.cc index 8bde289ed84..4be74783b74 100644 --- a/chromium/net/http/http_response_headers_unittest.cc +++ b/chromium/net/http/http_response_headers_unittest.cc @@ -1877,3 +1877,156 @@ TEST(HttpResponseHeadersTest, ToNetLogParamAndBackAgain) { parsed->GetNormalizedHeaders(&normalized_recreated); EXPECT_EQ(normalized_parsed, normalized_recreated); } + +#if defined(SPDY_PROXY_AUTH_ORIGIN) +TEST(HttpResponseHeadersTest, GetProxyBypassInfo) { + const struct { + const char* headers; + bool expected_result; + int64 expected_retry_delay; + bool expected_bypass_all; + } tests[] = { + { "HTTP/1.1 200 OK\n" + "Content-Length: 999\n", + false, + 0, + false, + }, + { "HTTP/1.1 200 OK\n" + "connection: keep-alive\n" + "Content-Length: 999\n", + false, + 0, + false, + }, + { "HTTP/1.1 200 OK\n" + "connection: keep-alive\n" + "Chrome-Proxy: bypass=86400\n" + "Content-Length: 999\n", + true, + 86400, + false, + }, + { "HTTP/1.1 200 OK\n" + "connection: keep-alive\n" + "Chrome-Proxy: bypass=0\n" + "Content-Length: 999\n", + true, + 0, + false, + }, + { "HTTP/1.1 200 OK\n" + "connection: keep-alive\n" + "Chrome-Proxy: bypass=-1\n" + "Content-Length: 999\n", + false, + 0, + false, + }, + { "HTTP/1.1 200 OK\n" + "connection: keep-alive\n" + "Chrome-Proxy: bypass=xyz\n" + "Content-Length: 999\n", + false, + 0, + false, + }, + { "HTTP/1.1 200 OK\n" + "connection: keep-alive\n" + "Chrome-Proxy: bypass\n" + "Content-Length: 999\n", + false, + 0, + false, + }, + { "HTTP/1.1 200 OK\n" + "connection: keep-alive\n" + "Chrome-Proxy: foo=abc, bypass=86400\n" + "Content-Length: 999\n", + true, + 86400, + false, + }, + { "HTTP/1.1 200 OK\n" + "connection: keep-alive\n" + "Chrome-Proxy: bypass=86400, bar=abc\n" + "Content-Length: 999\n", + true, + 86400, + false, + }, + { "HTTP/1.1 200 OK\n" + "connection: keep-alive\n" + "Chrome-Proxy: bypass=3600\n" + "Chrome-Proxy: bypass=86400\n" + "Content-Length: 999\n", + true, + 3600, + false, + }, + { "HTTP/1.1 200 OK\n" + "connection: keep-alive\n" + "Chrome-Proxy: bypass=3600, bypass=86400\n" + "Content-Length: 999\n", + true, + 3600, + false, + }, + { "HTTP/1.1 200 OK\n" + "connection: keep-alive\n" + "Chrome-Proxy: bypass=, bypass=86400\n" + "Content-Length: 999\n", + true, + 86400, + false, + }, + { "HTTP/1.1 200 OK\n" + "connection: keep-alive\n" + "Chrome-Proxy: bypass\n" + "Chrome-Proxy: bypass=86400\n" + "Content-Length: 999\n", + true, + 86400, + false, + }, + { "HTTP/1.1 200 OK\n" + "connection: keep-alive\n" + "Chrome-Proxy: block=, block=3600\n" + "Content-Length: 999\n", + true, + 3600, + true, + }, + { "HTTP/1.1 200 OK\n" + "connection: keep-alive\n" + "Chrome-Proxy: bypass=86400, block=3600\n" + "Content-Length: 999\n", + true, + 3600, + true, + }, + { "HTTP/1.1 200 OK\n" + "connection: proxy-bypass\n" + "Chrome-Proxy: block=, bypass=86400\n" + "Content-Length: 999\n", + true, + 86400, + false, + }, + }; + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + std::string headers(tests[i].headers); + HeadersToRaw(&headers); + scoped_refptr<net::HttpResponseHeaders> parsed( + new net::HttpResponseHeaders(headers)); + + net::HttpResponseHeaders::ChromeProxyInfo chrome_proxy_info; + EXPECT_EQ(tests[i].expected_result, + parsed->GetChromeProxyInfo(&chrome_proxy_info)); + EXPECT_EQ(tests[i].expected_retry_delay, + chrome_proxy_info.bypass_duration.InSeconds()); + EXPECT_EQ(tests[i].expected_bypass_all, + chrome_proxy_info.bypass_all); + } +} +#endif // defined(SPDY_PROXY_AUTH_ORIGIN) diff --git a/chromium/net/http/http_response_info.cc b/chromium/net/http/http_response_info.cc index 0b57a4e774b..4f9e014cfb2 100644 --- a/chromium/net/http/http_response_info.cc +++ b/chromium/net/http/http_response_info.cc @@ -10,6 +10,7 @@ #include "net/base/auth.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" +#include "net/cert/signed_certificate_timestamp.h" #include "net/cert/x509_certificate.h" #include "net/http/http_response_headers.h" #include "net/ssl/ssl_cert_request_info.h" @@ -87,6 +88,9 @@ enum { // This bit is set if the request has http authentication. RESPONSE_INFO_USE_HTTP_AUTHENTICATION = 1 << 19, + // This bit is set if ssl_info has SCTs. + RESPONSE_INFO_HAS_SIGNED_CERTIFICATE_TIMESTAMPS = 1 << 20, + // TODO(darin): Add other bits to indicate alternate request methods. // For now, we don't support storing those. }; @@ -207,6 +211,22 @@ bool HttpResponseInfo::InitFromPickle(const Pickle& pickle, ssl_info.connection_status = connection_status; } + if (flags & RESPONSE_INFO_HAS_SIGNED_CERTIFICATE_TIMESTAMPS) { + int num_scts; + if (!pickle.ReadInt(&iter, &num_scts)) + return false; + for (int i = 0; i < num_scts; ++i) { + scoped_refptr<ct::SignedCertificateTimestamp> sct( + ct::SignedCertificateTimestamp::CreateFromPickle(&iter)); + uint16 status; + if (!sct.get() || !pickle.ReadUInt16(&iter, &status)) + return false; + ssl_info.signed_certificate_timestamps.push_back( + SignedCertificateTimestampAndStatus( + sct, static_cast<ct::SCTVerifyStatus>(status))); + } + } + // Read vary-data if (flags & RESPONSE_INFO_HAS_VARY_DATA) { if (!vary_data.InitFromPickle(pickle, &iter)) @@ -286,6 +306,8 @@ void HttpResponseInfo::Persist(Pickle* pickle, flags |= RESPONSE_INFO_HAS_CONNECTION_INFO; if (did_use_http_auth) flags |= RESPONSE_INFO_USE_HTTP_AUTHENTICATION; + if (!ssl_info.signed_certificate_timestamps.empty()) + flags |= RESPONSE_INFO_HAS_SIGNED_CERTIFICATE_TIMESTAMPS; pickle->WriteInt(flags); pickle->WriteInt64(request_time.ToInternalValue()); @@ -313,6 +335,15 @@ void HttpResponseInfo::Persist(Pickle* pickle, pickle->WriteInt(ssl_info.security_bits); if (ssl_info.connection_status != 0) pickle->WriteInt(ssl_info.connection_status); + if (!ssl_info.signed_certificate_timestamps.empty()) { + pickle->WriteInt(ssl_info.signed_certificate_timestamps.size()); + for (SignedCertificateTimestampAndStatusList::const_iterator it = + ssl_info.signed_certificate_timestamps.begin(); it != + ssl_info.signed_certificate_timestamps.end(); ++it) { + it->sct_->Persist(pickle); + pickle->WriteUInt16(it->status_); + } + } } if (vary_data.is_valid()) @@ -331,8 +362,8 @@ void HttpResponseInfo::Persist(Pickle* pickle, HttpResponseInfo::ConnectionInfo HttpResponseInfo::ConnectionInfoFromNextProto( NextProto next_proto) { switch (next_proto) { - case kProtoSPDY2: - return CONNECTION_INFO_SPDY2; + case kProtoDeprecatedSPDY2: + return CONNECTION_INFO_DEPRECATED_SPDY2; case kProtoSPDY3: case kProtoSPDY31: return CONNECTION_INFO_SPDY3; @@ -345,8 +376,6 @@ HttpResponseInfo::ConnectionInfo HttpResponseInfo::ConnectionInfoFromNextProto( case kProtoUnknown: case kProtoHTTP11: - case kProtoSPDY1: - case kProtoSPDY21: break; } @@ -362,7 +391,7 @@ std::string HttpResponseInfo::ConnectionInfoToString( return "unknown"; case CONNECTION_INFO_HTTP1: return "http/1"; - case CONNECTION_INFO_SPDY2: + case CONNECTION_INFO_DEPRECATED_SPDY2: return "spdy/2"; case CONNECTION_INFO_SPDY3: return "spdy/3"; diff --git a/chromium/net/http/http_response_info.h b/chromium/net/http/http_response_info.h index 907ec96a570..f0908b0ab46 100644 --- a/chromium/net/http/http_response_info.h +++ b/chromium/net/http/http_response_info.h @@ -35,7 +35,7 @@ class NET_EXPORT HttpResponseInfo { enum ConnectionInfo { CONNECTION_INFO_UNKNOWN = 0, CONNECTION_INFO_HTTP1 = 1, - CONNECTION_INFO_SPDY2 = 2, + CONNECTION_INFO_DEPRECATED_SPDY2 = 2, CONNECTION_INFO_SPDY3 = 3, CONNECTION_INFO_SPDY4A2 = 4, CONNECTION_INFO_QUIC1_SPDY3 = 5, diff --git a/chromium/net/http/http_security_headers.cc b/chromium/net/http/http_security_headers.cc index 9fc7627cc5e..0c3305f6e42 100644 --- a/chromium/net/http/http_security_headers.cc +++ b/chromium/net/http/http_security_headers.cc @@ -325,7 +325,18 @@ bool ParseHPKPHeader(const std::string& value, *include_subdomains = include_subdomains_candidate; for (HashValueVector::const_iterator i = pins.begin(); i != pins.end(); ++i) { - hashes->push_back(*i); + bool found = false; + + for (HashValueVector::const_iterator j = hashes->begin(); + j != hashes->end(); ++j) { + if (j->Equals(*i)) { + found = true; + break; + } + } + + if (!found) + hashes->push_back(*i); } return true; diff --git a/chromium/net/http/http_security_headers_unittest.cc b/chromium/net/http/http_security_headers_unittest.cc index 0cc81b57eb8..42a5ee98960 100644 --- a/chromium/net/http/http_security_headers_unittest.cc +++ b/chromium/net/http/http_security_headers_unittest.cc @@ -416,6 +416,20 @@ static void TestValidPKPHeaders(HashValueTag tag) { expect_max_age = base::TimeDelta::FromSeconds(kMaxHSTSAgeSecs); EXPECT_EQ(expect_max_age, max_age); EXPECT_FALSE(include_subdomains); + + // Test that parsing the same header twice doesn't duplicate the recorded + // hashes. + hashes.clear(); + EXPECT_TRUE(ParseHPKPHeader( + " max-age=999; " + + backup_pin + ";" + good_pin + "; ", + chain_hashes, &max_age, &include_subdomains, &hashes)); + EXPECT_EQ(2u, hashes.size()); + EXPECT_TRUE(ParseHPKPHeader( + " max-age=999; " + + backup_pin + ";" + good_pin + "; ", + chain_hashes, &max_age, &include_subdomains, &hashes)); + EXPECT_EQ(2u, hashes.size()); } TEST_F(HttpSecurityHeadersTest, BogusPinsHeadersSHA1) { diff --git a/chromium/net/http/http_server_properties.cc b/chromium/net/http/http_server_properties.cc index bff262ade45..a10d5060c06 100644 --- a/chromium/net/http/http_server_properties.cc +++ b/chromium/net/http/http_server_properties.cc @@ -16,7 +16,6 @@ namespace { // The order of these strings much match the order of the enum definition // for AlternateProtocol. const char* const kAlternateProtocolStrings[] = { - "npn-spdy/1", "npn-spdy/2", "npn-spdy/3", "npn-spdy/3.1", @@ -26,25 +25,28 @@ const char* const kAlternateProtocolStrings[] = { }; const char kBrokenAlternateProtocol[] = "Broken"; -COMPILE_ASSERT(arraysize(kAlternateProtocolStrings) == NUM_ALTERNATE_PROTOCOLS, - kAlternateProtocolStringsSize_NUM_ALTERNATE_PROTOCOLS_nut_equal); +COMPILE_ASSERT( + arraysize(kAlternateProtocolStrings) == NUM_VALID_ALTERNATE_PROTOCOLS, + kAlternateProtocolStringsSize_kNumValidAlternateProtocols_not_equal); } // namespace +bool IsAlternateProtocolValid(AlternateProtocol protocol) { + return protocol >= ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION && + protocol <= ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION; +} + const char* AlternateProtocolToString(AlternateProtocol protocol) { switch (protocol) { - case NPN_SPDY_1: - case NPN_SPDY_2: + case DEPRECATED_NPN_SPDY_2: case NPN_SPDY_3: case NPN_SPDY_3_1: case NPN_SPDY_4A2: case NPN_HTTP2_DRAFT_04: case QUIC: - DCHECK_LT(static_cast<size_t>(protocol), - arraysize(kAlternateProtocolStrings)); - return kAlternateProtocolStrings[protocol]; - case NUM_ALTERNATE_PROTOCOLS: - break; + DCHECK(IsAlternateProtocolValid(protocol)); + return kAlternateProtocolStrings[ + protocol - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION]; case ALTERNATE_PROTOCOL_BROKEN: return kBrokenAlternateProtocol; case UNINITIALIZED_ALTERNATE_PROTOCOL: @@ -54,19 +56,22 @@ const char* AlternateProtocolToString(AlternateProtocol protocol) { return ""; } -AlternateProtocol AlternateProtocolFromString(const std::string& protocol) { - for (int i = NPN_SPDY_1; i < NUM_ALTERNATE_PROTOCOLS; ++i) - if (protocol == kAlternateProtocolStrings[i]) - return static_cast<AlternateProtocol>(i); - if (protocol == kBrokenAlternateProtocol) +AlternateProtocol AlternateProtocolFromString(const std::string& str) { + for (int i = ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION; + i <= ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION; ++i) { + AlternateProtocol protocol = static_cast<AlternateProtocol>(i); + if (str == AlternateProtocolToString(protocol)) + return protocol; + } + if (str == kBrokenAlternateProtocol) return ALTERNATE_PROTOCOL_BROKEN; return UNINITIALIZED_ALTERNATE_PROTOCOL; } AlternateProtocol AlternateProtocolFromNextProto(NextProto next_proto) { switch (next_proto) { - case kProtoSPDY2: - return NPN_SPDY_2; + case kProtoDeprecatedSPDY2: + return DEPRECATED_NPN_SPDY_2; case kProtoSPDY3: return NPN_SPDY_3; case kProtoSPDY31: @@ -80,8 +85,6 @@ AlternateProtocol AlternateProtocolFromNextProto(NextProto next_proto) { case kProtoUnknown: case kProtoHTTP11: - case kProtoSPDY1: - case kProtoSPDY21: break; } diff --git a/chromium/net/http/http_server_properties.h b/chromium/net/http/http_server_properties.h index 654d262024a..72fda4355b1 100644 --- a/chromium/net/http/http_server_properties.h +++ b/chromium/net/http/http_server_properties.h @@ -18,9 +18,9 @@ namespace net { enum AlternateProtocol { - NPN_SPDY_1 = 0, - NPN_SPDY_MINIMUM_VERSION = NPN_SPDY_1, - NPN_SPDY_2, + DEPRECATED_NPN_SPDY_2 = 0, + ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION = DEPRECATED_NPN_SPDY_2, + NPN_SPDY_MINIMUM_VERSION = DEPRECATED_NPN_SPDY_2, NPN_SPDY_3, NPN_SPDY_3_1, NPN_SPDY_4A2, @@ -28,14 +28,25 @@ enum AlternateProtocol { NPN_HTTP2_DRAFT_04, NPN_SPDY_MAXIMUM_VERSION = NPN_HTTP2_DRAFT_04, QUIC, - NUM_ALTERNATE_PROTOCOLS, + ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION = QUIC, ALTERNATE_PROTOCOL_BROKEN, // The alternate protocol is known to be broken. UNINITIALIZED_ALTERNATE_PROTOCOL, }; +// Simply returns whether |protocol| is between +// ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION and +// ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION (inclusive). +NET_EXPORT bool IsAlternateProtocolValid(AlternateProtocol protocol); + +enum AlternateProtocolSize { + NUM_VALID_ALTERNATE_PROTOCOLS = + ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION - + ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION + 1, +}; + NET_EXPORT const char* AlternateProtocolToString(AlternateProtocol protocol); NET_EXPORT AlternateProtocol AlternateProtocolFromString( - const std::string& protocol); + const std::string& str); NET_EXPORT_PRIVATE AlternateProtocol AlternateProtocolFromNextProto( NextProto next_proto); diff --git a/chromium/net/http/http_server_properties_impl.cc b/chromium/net/http/http_server_properties_impl.cc index a0b287de588..a4ac6dc3804 100644 --- a/chromium/net/http/http_server_properties_impl.cc +++ b/chromium/net/http/http_server_properties_impl.cc @@ -18,9 +18,9 @@ namespace net { static const int kDefaultNumHostsToRemember = 200; HttpServerPropertiesImpl::HttpServerPropertiesImpl() - : weak_ptr_factory_(this), - pipeline_capability_map_( - new CachedPipelineCapabilityMap(kDefaultNumHostsToRemember)) { + : pipeline_capability_map_( + new CachedPipelineCapabilityMap(kDefaultNumHostsToRemember)), + weak_ptr_factory_(this) { } HttpServerPropertiesImpl::~HttpServerPropertiesImpl() { diff --git a/chromium/net/http/http_server_properties_impl.h b/chromium/net/http/http_server_properties_impl.h index c1e2d4ba20b..cf96b7d4f32 100644 --- a/chromium/net/http/http_server_properties_impl.h +++ b/chromium/net/http/http_server_properties_impl.h @@ -145,14 +145,14 @@ class NET_EXPORT HttpServerPropertiesImpl // pair) that either support or not support SPDY protocol. typedef base::hash_map<std::string, bool> SpdyServerHostPortTable; - base::WeakPtrFactory<HttpServerPropertiesImpl> weak_ptr_factory_; - SpdyServerHostPortTable spdy_servers_table_; AlternateProtocolMap alternate_protocol_map_; SpdySettingsMap spdy_settings_map_; scoped_ptr<CachedPipelineCapabilityMap> pipeline_capability_map_; + base::WeakPtrFactory<HttpServerPropertiesImpl> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(HttpServerPropertiesImpl); }; diff --git a/chromium/net/http/http_server_properties_impl_unittest.cc b/chromium/net/http/http_server_properties_impl_unittest.cc index d125adcc40c..cf3a4643f9d 100644 --- a/chromium/net/http/http_server_properties_impl_unittest.cc +++ b/chromium/net/http/http_server_properties_impl_unittest.cc @@ -189,12 +189,12 @@ typedef HttpServerPropertiesImplTest AlternateProtocolServerPropertiesTest; TEST_F(AlternateProtocolServerPropertiesTest, Basic) { HostPortPair test_host_port_pair("foo", 80); EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair)); - impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_1); + impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_3); ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair)); const PortAlternateProtocolPair alternate = impl_.GetAlternateProtocol(test_host_port_pair); EXPECT_EQ(443, alternate.port); - EXPECT_EQ(NPN_SPDY_1, alternate.protocol); + EXPECT_EQ(NPN_SPDY_3, alternate.protocol); impl_.Clear(); EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair)); @@ -204,12 +204,12 @@ TEST_F(AlternateProtocolServerPropertiesTest, Initialize) { HostPortPair test_host_port_pair1("foo1", 80); impl_.SetBrokenAlternateProtocol(test_host_port_pair1); HostPortPair test_host_port_pair2("foo2", 80); - impl_.SetAlternateProtocol(test_host_port_pair2, 443, NPN_SPDY_1); + impl_.SetAlternateProtocol(test_host_port_pair2, 443, NPN_SPDY_3); AlternateProtocolMap alternate_protocol_map; PortAlternateProtocolPair port_alternate_protocol_pair; port_alternate_protocol_pair.port = 123; - port_alternate_protocol_pair.protocol = NPN_SPDY_2; + port_alternate_protocol_pair.protocol = NPN_SPDY_3; alternate_protocol_map[test_host_port_pair2] = port_alternate_protocol_pair; impl_.InitializeAlternateProtocolServers(&alternate_protocol_map); @@ -221,7 +221,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, Initialize) { port_alternate_protocol_pair = impl_.GetAlternateProtocol(test_host_port_pair2); EXPECT_EQ(123, port_alternate_protocol_pair.port); - EXPECT_EQ(NPN_SPDY_2, port_alternate_protocol_pair.protocol); + EXPECT_EQ(NPN_SPDY_3, port_alternate_protocol_pair.protocol); } TEST_F(AlternateProtocolServerPropertiesTest, SetBroken) { @@ -235,7 +235,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, SetBroken) { impl_.SetAlternateProtocol( test_host_port_pair, 1234, - NPN_SPDY_1); + NPN_SPDY_3); alternate = impl_.GetAlternateProtocol(test_host_port_pair); EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol) << "Second attempt should be ignored."; @@ -246,7 +246,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, Forced) { PortAlternateProtocolPair default_protocol; default_protocol.port = 1234; - default_protocol.protocol = NPN_SPDY_2; + default_protocol.protocol = NPN_SPDY_3; HttpServerPropertiesImpl::ForceAlternateProtocol(default_protocol); // Verify the forced protocol. @@ -258,11 +258,11 @@ TEST_F(AlternateProtocolServerPropertiesTest, Forced) { EXPECT_EQ(default_protocol.protocol, alternate.protocol); // Verify the real protocol overrides the forced protocol. - impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_1); + impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_3); ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair)); alternate = impl_.GetAlternateProtocol(test_host_port_pair); EXPECT_EQ(443, alternate.port); - EXPECT_EQ(NPN_SPDY_1, alternate.protocol); + EXPECT_EQ(NPN_SPDY_3, alternate.protocol); // Turn off the static, forced alternate protocol so that tests don't // have this state. diff --git a/chromium/net/http/http_stream_base.h b/chromium/net/http/http_stream_base.h index 596ed75dff1..f5dcc29409e 100644 --- a/chromium/net/http/http_stream_base.h +++ b/chromium/net/http/http_stream_base.h @@ -5,7 +5,7 @@ // HttpStreamBase is an interface for reading and writing data to an // HTTP-like stream that keeps the client agnostic of the actual underlying // transport layer. This provides an abstraction for HttpStream and -// WebSocketStream. +// WebSocketHandshakeStreamBase. #ifndef NET_HTTP_HTTP_STREAM_BASE_H_ #define NET_HTTP_HTTP_STREAM_BASE_H_ @@ -110,6 +110,9 @@ class NET_EXPORT_PRIVATE HttpStreamBase { // allows it to be reused. virtual bool IsConnectionReusable() const = 0; + // Get the total number of bytes received from network for this stream. + virtual int64 GetTotalReceivedBytes() const = 0; + // Populates the connection establishment part of |load_timing_info|, and // socket ID. |load_timing_info| must have all null times when called. // Returns false and does nothing if there is no underlying connection, either diff --git a/chromium/net/http/http_stream_factory.cc b/chromium/net/http/http_stream_factory.cc index a55ed075bb5..e88046fba3c 100644 --- a/chromium/net/http/http_stream_factory.cc +++ b/chromium/net/http/http_stream_factory.cc @@ -19,7 +19,7 @@ namespace net { // static std::vector<std::string>* HttpStreamFactory::next_protos_ = NULL; // static -bool HttpStreamFactory::enabled_protocols_[NUM_ALTERNATE_PROTOCOLS]; +bool HttpStreamFactory::enabled_protocols_[NUM_VALID_ALTERNATE_PROTOCOLS]; // static bool HttpStreamFactory::spdy_enabled_ = true; // static @@ -34,6 +34,28 @@ std::list<HostPortPair>* HttpStreamFactory::forced_spdy_exclusions_ = NULL; HttpStreamFactory::~HttpStreamFactory() {} // static +bool HttpStreamFactory::IsProtocolEnabled(AlternateProtocol protocol) { + DCHECK(IsAlternateProtocolValid(protocol)); + return enabled_protocols_[ + protocol - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION]; +} + +// static +void HttpStreamFactory::SetProtocolEnabled(AlternateProtocol protocol) { + DCHECK(IsAlternateProtocolValid(protocol)); + enabled_protocols_[ + protocol - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION] = true; +} + +// static +void HttpStreamFactory::ResetEnabledProtocols() { + for (int i = ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION; + i <= ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION; ++i) { + enabled_protocols_[i - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION] = false; + } +} + +// static void HttpStreamFactory::ResetStaticSettingsToInit() { // WARNING: These must match the initializers above. delete next_protos_; @@ -44,8 +66,7 @@ void HttpStreamFactory::ResetStaticSettingsToInit() { force_spdy_over_ssl_ = true; force_spdy_always_ = false; forced_spdy_exclusions_ = NULL; - for (int i = 0; i < NUM_ALTERNATE_PROTOCOLS; ++i) - enabled_protocols_[i] = false; + ResetEnabledProtocols(); } void HttpStreamFactory::ProcessAlternateProtocol( @@ -55,31 +76,31 @@ void HttpStreamFactory::ProcessAlternateProtocol( std::vector<std::string> port_protocol_vector; base::SplitString(alternate_protocol_str, ':', &port_protocol_vector); if (port_protocol_vector.size() != 2) { - DLOG(WARNING) << kAlternateProtocolHeader - << " header has too many tokens: " - << alternate_protocol_str; + DVLOG(1) << kAlternateProtocolHeader + << " header has too many tokens: " + << alternate_protocol_str; return; } int port; if (!base::StringToInt(port_protocol_vector[0], &port) || port <= 0 || port >= 1 << 16) { - DLOG(WARNING) << kAlternateProtocolHeader - << " header has unrecognizable port: " - << port_protocol_vector[0]; + DVLOG(1) << kAlternateProtocolHeader + << " header has unrecognizable port: " + << port_protocol_vector[0]; return; } AlternateProtocol protocol = AlternateProtocolFromString(port_protocol_vector[1]); - if (protocol < NUM_ALTERNATE_PROTOCOLS && !enabled_protocols_[protocol]) + if (IsAlternateProtocolValid(protocol) && !IsProtocolEnabled(protocol)) { protocol = ALTERNATE_PROTOCOL_BROKEN; + } if (protocol == ALTERNATE_PROTOCOL_BROKEN) { - // Currently, we only recognize the npn-spdy protocol. - DLOG(WARNING) << kAlternateProtocolHeader - << " header has unrecognized protocol: " - << port_protocol_vector[1]; + DVLOG(1) << kAlternateProtocolHeader + << " header has unrecognized protocol: " + << port_protocol_vector[1]; return; } @@ -136,16 +157,6 @@ bool HttpStreamFactory::HasSpdyExclusion(const HostPortPair& endpoint) { } // static -void HttpStreamFactory::EnableNpnSpdy() { - set_use_alternate_protocols(true); - std::vector<NextProto> next_protos; - next_protos.push_back(kProtoHTTP11); - next_protos.push_back(kProtoQUIC1SPDY3); - next_protos.push_back(kProtoSPDY2); - SetNextProtos(next_protos); -} - -// static void HttpStreamFactory::EnableNpnHttpOnly() { // Avoid alternate protocol in this case. Otherwise, browser will try SSL // and then fallback to http. This introduces extra load. @@ -161,7 +172,6 @@ void HttpStreamFactory::EnableNpnSpdy3() { std::vector<NextProto> next_protos; next_protos.push_back(kProtoHTTP11); next_protos.push_back(kProtoQUIC1SPDY3); - next_protos.push_back(kProtoSPDY2); next_protos.push_back(kProtoSPDY3); SetNextProtos(next_protos); } @@ -172,7 +182,18 @@ void HttpStreamFactory::EnableNpnSpdy31() { std::vector<NextProto> next_protos; next_protos.push_back(kProtoHTTP11); next_protos.push_back(kProtoQUIC1SPDY3); - next_protos.push_back(kProtoSPDY2); + next_protos.push_back(kProtoSPDY3); + next_protos.push_back(kProtoSPDY31); + SetNextProtos(next_protos); +} + +// static +void HttpStreamFactory::EnableNpnSpdy31WithSpdy2() { + set_use_alternate_protocols(true); + std::vector<NextProto> next_protos; + next_protos.push_back(kProtoHTTP11); + next_protos.push_back(kProtoQUIC1SPDY3); + next_protos.push_back(kProtoDeprecatedSPDY2); next_protos.push_back(kProtoSPDY3); next_protos.push_back(kProtoSPDY31); SetNextProtos(next_protos); @@ -184,7 +205,6 @@ void HttpStreamFactory::EnableNpnSpdy4a2() { std::vector<NextProto> next_protos; next_protos.push_back(kProtoHTTP11); next_protos.push_back(kProtoQUIC1SPDY3); - next_protos.push_back(kProtoSPDY2); next_protos.push_back(kProtoSPDY3); next_protos.push_back(kProtoSPDY31); next_protos.push_back(kProtoSPDY4a2); @@ -197,7 +217,6 @@ void HttpStreamFactory::EnableNpnHttp2Draft04() { std::vector<NextProto> next_protos; next_protos.push_back(kProtoHTTP11); next_protos.push_back(kProtoQUIC1SPDY3); - next_protos.push_back(kProtoSPDY2); next_protos.push_back(kProtoSPDY3); next_protos.push_back(kProtoSPDY31); next_protos.push_back(kProtoSPDY4a2); @@ -212,8 +231,7 @@ void HttpStreamFactory::SetNextProtos(const std::vector<NextProto>& value) { next_protos_->clear(); - for (uint32 i = 0; i < NUM_ALTERNATE_PROTOCOLS; ++i) - enabled_protocols_[i] = false; + ResetEnabledProtocols(); // TODO(rtenneti): bug 116575 - consider combining the NextProto and // AlternateProtocol. @@ -229,11 +247,11 @@ void HttpStreamFactory::SetNextProtos(const std::vector<NextProto>& value) { // which has not corresponding alternative. if (proto != kProtoHTTP11) { AlternateProtocol alternate = AlternateProtocolFromNextProto(proto); - if (alternate == UNINITIALIZED_ALTERNATE_PROTOCOL) { + if (!IsAlternateProtocolValid(alternate)) { NOTREACHED() << "Invalid next proto: " << proto; continue; } - enabled_protocols_[alternate] = true; + SetProtocolEnabled(alternate); } } } diff --git a/chromium/net/http/http_stream_factory.h b/chromium/net/http/http_stream_factory.h index 0de3b65bc57..0d854a5dd9d 100644 --- a/chromium/net/http/http_stream_factory.h +++ b/chromium/net/http/http_stream_factory.h @@ -21,7 +21,7 @@ // This file can be included from net/http even though // it is in net/websockets because it doesn't // introduce any link dependency to net/websockets. -#include "net/websockets/websocket_stream_base.h" +#include "net/websockets/websocket_handshake_stream_base.h" class GURL; @@ -71,17 +71,17 @@ class NET_EXPORT_PRIVATE HttpStreamRequest { const ProxyInfo& used_proxy_info, HttpStreamBase* stream) = 0; - // This is the success case for RequestWebSocketStream. + // This is the success case for RequestWebSocketHandshakeStream. // |stream| is now owned by the delegate. // |used_ssl_config| indicates the actual SSL configuration used for this // stream, since the HttpStreamRequest may have modified the configuration // during stream processing. // |used_proxy_info| indicates the actual ProxyInfo used for this stream, // since the HttpStreamRequest performs the proxy resolution. - virtual void OnWebSocketStreamReady( + virtual void OnWebSocketHandshakeStreamReady( const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, - WebSocketStreamBase* stream) = 0; + WebSocketHandshakeStreamBase* stream) = 0; // This is the failure to create a stream case. // |used_ssl_config| indicates the actual SSL configuration used for this @@ -197,15 +197,16 @@ class NET_EXPORT HttpStreamFactory { HttpStreamRequest::Delegate* delegate, const BoundNetLog& net_log) = 0; - // Request a WebSocket stream. - // Will call delegate->OnWebSocketStreamReady on successful completion. - virtual HttpStreamRequest* RequestWebSocketStream( + // Request a WebSocket handshake stream. + // Will call delegate->OnWebSocketHandshakeStreamReady on successful + // completion. + virtual HttpStreamRequest* RequestWebSocketHandshakeStream( const HttpRequestInfo& info, RequestPriority priority, const SSLConfig& server_ssl_config, const SSLConfig& proxy_ssl_config, HttpStreamRequest::Delegate* delegate, - WebSocketStreamBase::Factory* factory, + WebSocketHandshakeStreamBase::CreateHelper* create_helper, const BoundNetLog& net_log) = 0; // Requests that enough connections for |num_streams| be opened. @@ -265,25 +266,24 @@ class NET_EXPORT HttpStreamFactory { // Sets http/1.1 as the only protocol supported via NPN or Alternate-Protocol. static void EnableNpnHttpOnly(); - // Sets http/1.1, quic and spdy/2 (the default spdy protocol) as the protocols - // supported via NPN or Alternate-Protocol. - static void EnableNpnSpdy(); - - // Sets http/1.1, quic, spdy/2, and spdy/3 as the protocols supported via NPN - // or Alternate-Protocol. + // Sets http/1.1, quic, and spdy/3 as the protocols supported via + // NPN or Alternate-Protocol. static void EnableNpnSpdy3(); - // Sets http/1.1, quic, spdy/2, spdy/3, and spdy/3.1 as the protocols + // Sets http/1.1, quic, spdy/3, and spdy/3.1 as the protocols // supported via NPN or Alternate-Protocol. static void EnableNpnSpdy31(); - // Sets http/1.1, quic, spdy/2, spdy/3, spdy/3.1, and spdy/4a2 as - // the protocols supported via NPN or Alternate-Protocol. + // Sets http/1.1, quic, spdy/2, spdy/3, and spdy/3.1 as the + // protocols supported via NPN or Alternate-Protocol. + static void EnableNpnSpdy31WithSpdy2(); + + // Sets http/1.1, quic, spdy/3, spdy/3.1, and spdy/4a2 as the + // protocols supported via NPN or Alternate-Protocol. static void EnableNpnSpdy4a2(); - // Sets http/1.1, quic, spdy/2, spdy/3, spdy/3.1, spdy/4a2, and - // http/2 draft 04 as the protocols supported via NPN or - // Alternate-Protocol. + // Sets http/1.1, quic, spdy/3, spdy/3.1, spdy/4a2, and http/2 draft + // 04 as the protocols supported via NPN or Alternate-Protocol. static void EnableNpnHttp2Draft04(); // Sets the protocols supported by NPN (next protocol negotiation) during the @@ -298,8 +298,13 @@ class NET_EXPORT HttpStreamFactory { HttpStreamFactory(); private: + // |protocol| must be a valid protocol value. + static bool IsProtocolEnabled(AlternateProtocol protocol); + static void SetProtocolEnabled(AlternateProtocol protocol); + static void ResetEnabledProtocols(); + static std::vector<std::string>* next_protos_; - static bool enabled_protocols_[NUM_ALTERNATE_PROTOCOLS]; + static bool enabled_protocols_[NUM_VALID_ALTERNATE_PROTOCOLS]; static bool spdy_enabled_; static bool use_alternate_protocols_; static bool force_spdy_over_ssl_; diff --git a/chromium/net/http/http_stream_factory_impl.cc b/chromium/net/http/http_stream_factory_impl.cc index 35d94d779f8..056a0f6b879 100644 --- a/chromium/net/http/http_stream_factory_impl.cc +++ b/chromium/net/http/http_stream_factory_impl.cc @@ -82,22 +82,22 @@ HttpStreamRequest* HttpStreamFactoryImpl::RequestStream( net_log); } -HttpStreamRequest* HttpStreamFactoryImpl::RequestWebSocketStream( +HttpStreamRequest* HttpStreamFactoryImpl::RequestWebSocketHandshakeStream( const HttpRequestInfo& request_info, RequestPriority priority, const SSLConfig& server_ssl_config, const SSLConfig& proxy_ssl_config, HttpStreamRequest::Delegate* delegate, - WebSocketStreamBase::Factory* factory, + WebSocketHandshakeStreamBase::CreateHelper* create_helper, const BoundNetLog& net_log) { DCHECK(for_websockets_); - DCHECK(factory); + DCHECK(create_helper); return RequestStreamInternal(request_info, priority, server_ssl_config, proxy_ssl_config, delegate, - factory, + create_helper, net_log); } @@ -107,12 +107,13 @@ HttpStreamRequest* HttpStreamFactoryImpl::RequestStreamInternal( const SSLConfig& server_ssl_config, const SSLConfig& proxy_ssl_config, HttpStreamRequest::Delegate* delegate, - WebSocketStreamBase::Factory* websocket_stream_factory, + WebSocketHandshakeStreamBase::CreateHelper* + websocket_handshake_stream_create_helper, const BoundNetLog& net_log) { Request* request = new Request(request_info.url, this, delegate, - websocket_stream_factory, + websocket_handshake_stream_create_helper, net_log); GURL alternate_url; @@ -207,11 +208,10 @@ PortAlternateProtocolPair HttpStreamFactoryImpl::GetAlternateProtocolRequestFor( if (alternate.protocol == ALTERNATE_PROTOCOL_BROKEN) return kNoAlternateProtocol; - DCHECK_LE(NPN_SPDY_1, alternate.protocol); - DCHECK_GT(NUM_ALTERNATE_PROTOCOLS, alternate.protocol); - - if (alternate.protocol < NPN_SPDY_2) + if (!IsAlternateProtocolValid(alternate.protocol)) { + NOTREACHED(); return kNoAlternateProtocol; + } // Some shared unix systems may have user home directories (like // http://foo.com/~mike) which allow users to emit headers. This is a bad @@ -290,15 +290,15 @@ void HttpStreamFactoryImpl::OnNewSpdySessionReady( using_spdy, net_log); if (for_websockets_) { - WebSocketStreamBase::Factory* factory = - request->websocket_stream_factory(); - DCHECK(factory); + WebSocketHandshakeStreamBase::CreateHelper* create_helper = + request->websocket_handshake_stream_create_helper(); + DCHECK(create_helper); bool use_relative_url = direct || request->url().SchemeIs("wss"); - request->OnWebSocketStreamReady( + request->OnWebSocketHandshakeStreamReady( NULL, used_ssl_config, used_proxy_info, - factory->CreateSpdyStream(spdy_session, use_relative_url)); + create_helper->CreateSpdyStream(spdy_session, use_relative_url)); } else { bool use_relative_url = direct || request->url().SchemeIs("https"); request->OnStreamReady( diff --git a/chromium/net/http/http_stream_factory_impl.h b/chromium/net/http/http_stream_factory_impl.h index 4339fd350d7..4824dece14f 100644 --- a/chromium/net/http/http_stream_factory_impl.h +++ b/chromium/net/http/http_stream_factory_impl.h @@ -30,7 +30,8 @@ class NET_EXPORT_PRIVATE HttpStreamFactoryImpl : public HttpPipelinedHostPool::Delegate { public: // RequestStream may only be called if |for_websockets| is false. - // RequestWebSocketStream may only be called if |for_websockets| is true. + // RequestWebSocketHandshakeStream may only be called if |for_websockets| + // is true. HttpStreamFactoryImpl(HttpNetworkSession* session, bool for_websockets); virtual ~HttpStreamFactoryImpl(); @@ -43,13 +44,13 @@ class NET_EXPORT_PRIVATE HttpStreamFactoryImpl : HttpStreamRequest::Delegate* delegate, const BoundNetLog& net_log) OVERRIDE; - virtual HttpStreamRequest* RequestWebSocketStream( + virtual HttpStreamRequest* RequestWebSocketHandshakeStream( const HttpRequestInfo& info, RequestPriority priority, const SSLConfig& server_ssl_config, const SSLConfig& proxy_ssl_config, HttpStreamRequest::Delegate* delegate, - WebSocketStreamBase::Factory* factory, + WebSocketHandshakeStreamBase::CreateHelper* create_helper, const BoundNetLog& net_log) OVERRIDE; virtual void PreconnectStreams(int num_streams, @@ -84,7 +85,7 @@ class NET_EXPORT_PRIVATE HttpStreamFactoryImpl : const SSLConfig& server_ssl_config, const SSLConfig& proxy_ssl_config, HttpStreamRequest::Delegate* delegate, - WebSocketStreamBase::Factory* factory, + WebSocketHandshakeStreamBase::CreateHelper* create_helper, const BoundNetLog& net_log); PortAlternateProtocolPair GetAlternateProtocolRequestFor( diff --git a/chromium/net/http/http_stream_factory_impl_job.cc b/chromium/net/http/http_stream_factory_impl_job.cc index c0383f4772d..c86bee7495b 100644 --- a/chromium/net/http/http_stream_factory_impl_job.cc +++ b/chromium/net/http/http_stream_factory_impl_job.cc @@ -52,7 +52,7 @@ base::Value* NetLogHttpStreamJobCallback(const GURL* original_url, base::DictionaryValue* dict = new base::DictionaryValue(); dict->SetString("original_url", original_url->GetOrigin().spec()); dict->SetString("url", url->GetOrigin().spec()); - dict->SetInteger("priority", priority); + dict->SetString("priority", RequestPriorityToString(priority)); return dict; } @@ -221,9 +221,9 @@ void HttpStreamFactoryImpl::Job::Orphan(const Request* request) { connection_->socket()->Disconnect(); stream_factory_->OnOrphanedJobComplete(this); } else if (stream_factory_->for_websockets_) { - // We cancel this job because WebSocketStream can't be created - // without a WebSocketStreamBase::Factory which is stored in Request class - // and isn't accessible from this job. + // We cancel this job because a WebSocketHandshakeStream can't be created + // without a WebSocketHandshakeStreamBase::CreateHelper which is stored in + // the Request class and isn't accessible from this job. if (connection_ && connection_->socket()) connection_->socket()->Disconnect(); stream_factory_->OnOrphanedJobComplete(this); @@ -314,7 +314,7 @@ void HttpStreamFactoryImpl::Job::OnStreamReadyCallback() { // |this| may be deleted after this call. } -void HttpStreamFactoryImpl::Job::OnWebSocketStreamReadyCallback() { +void HttpStreamFactoryImpl::Job::OnWebSocketHandshakeStreamReadyCallback() { DCHECK(websocket_stream_); DCHECK(!IsPreconnecting()); DCHECK(stream_factory_->for_websockets_); @@ -325,10 +325,10 @@ void HttpStreamFactoryImpl::Job::OnWebSocketStreamReadyCallback() { protocol_negotiated(), using_spdy(), net_log_); - request_->OnWebSocketStreamReady(this, - server_ssl_config_, - proxy_info_, - websocket_stream_.release()); + request_->OnWebSocketHandshakeStreamReady(this, + server_ssl_config_, + proxy_info_, + websocket_stream_.release()); // |this| may be deleted after this call. } @@ -532,9 +532,8 @@ int HttpStreamFactoryImpl::Job::RunLoop(int result) { DCHECK(websocket_stream_); base::MessageLoop::current()->PostTask( FROM_HERE, - base::Bind( - &Job::OnWebSocketStreamReadyCallback, - ptr_factory_.GetWeakPtr())); + base::Bind(&Job::OnWebSocketHandshakeStreamReadyCallback, + ptr_factory_.GetWeakPtr())); } else { DCHECK(stream_.get()); base::MessageLoop::current()->PostTask( @@ -1065,10 +1064,10 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() { CHECK(stream_.get()); } else if (stream_factory_->for_websockets_) { DCHECK(request_); - DCHECK(request_->websocket_stream_factory()); + DCHECK(request_->websocket_handshake_stream_create_helper()); websocket_stream_.reset( - request_->websocket_stream_factory()->CreateBasicStream( - connection_.release(), using_proxy)); + request_->websocket_handshake_stream_create_helper() + ->CreateBasicStream(connection_.Pass(), using_proxy)); } else if (!using_proxy && IsRequestEligibleForPipelining()) { // TODO(simonjam): Support proxies. stream_.reset( @@ -1082,8 +1081,7 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() { protocol_negotiated_)); CHECK(stream_.get()); } else { - stream_.reset(new HttpBasicStream(connection_.release(), NULL, - using_proxy)); + stream_.reset(new HttpBasicStream(connection_.release(), using_proxy)); } return OK; } @@ -1143,10 +1141,10 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() { if (stream_factory_->for_websockets_) { DCHECK(request_); - DCHECK(request_->websocket_stream_factory()); + DCHECK(request_->websocket_handshake_stream_create_helper()); bool use_relative_url = direct || request_info_.url.SchemeIs("wss"); websocket_stream_.reset( - request_->websocket_stream_factory()->CreateSpdyStream( + request_->websocket_handshake_stream_create_helper()->CreateSpdyStream( spdy_session, use_relative_url)); } else { bool use_relative_url = direct || request_info_.url.SchemeIs("https"); diff --git a/chromium/net/http/http_stream_factory_impl_job.h b/chromium/net/http/http_stream_factory_impl_job.h index 01a794a1bc7..1970b5be08b 100644 --- a/chromium/net/http/http_stream_factory_impl_job.h +++ b/chromium/net/http/http_stream_factory_impl_job.h @@ -130,7 +130,7 @@ class HttpStreamFactoryImpl::Job { }; void OnStreamReadyCallback(); - void OnWebSocketStreamReadyCallback(); + void OnWebSocketHandshakeStreamReadyCallback(); // This callback function is called when a new SPDY session is created. void OnNewSpdySessionReadyCallback(); void OnStreamFailedCallback(int result); @@ -297,7 +297,7 @@ class HttpStreamFactoryImpl::Job { bool establishing_tunnel_; scoped_ptr<HttpStream> stream_; - scoped_ptr<WebSocketStreamBase> websocket_stream_; + scoped_ptr<WebSocketHandshakeStreamBase> websocket_stream_; // True if we negotiated NPN. bool was_npn_negotiated_; diff --git a/chromium/net/http/http_stream_factory_impl_request.cc b/chromium/net/http/http_stream_factory_impl_request.cc index 57190ed72e7..d731d414b71 100644 --- a/chromium/net/http/http_stream_factory_impl_request.cc +++ b/chromium/net/http/http_stream_factory_impl_request.cc @@ -17,11 +17,13 @@ HttpStreamFactoryImpl::Request::Request( const GURL& url, HttpStreamFactoryImpl* factory, HttpStreamRequest::Delegate* delegate, - WebSocketStreamBase::Factory* websocket_stream_factory, + WebSocketHandshakeStreamBase::CreateHelper* + websocket_handshake_stream_create_helper, const BoundNetLog& net_log) : url_(url), factory_(factory), - websocket_stream_factory_(websocket_stream_factory), + websocket_handshake_stream_create_helper_( + websocket_handshake_stream_create_helper), delegate_(delegate), net_log_(net_log), completed_(false), @@ -110,17 +112,18 @@ void HttpStreamFactoryImpl::Request::OnStreamReady( delegate_->OnStreamReady(used_ssl_config, used_proxy_info, stream); } -void HttpStreamFactoryImpl::Request::OnWebSocketStreamReady( +void HttpStreamFactoryImpl::Request::OnWebSocketHandshakeStreamReady( Job* job, const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, - WebSocketStreamBase* stream) { + WebSocketHandshakeStreamBase* stream) { DCHECK(factory_->for_websockets_); DCHECK(stream); DCHECK(completed_); OnJobSucceeded(job); - delegate_->OnWebSocketStreamReady(used_ssl_config, used_proxy_info, stream); + delegate_->OnWebSocketHandshakeStreamReady( + used_ssl_config, used_proxy_info, stream); } void HttpStreamFactoryImpl::Request::OnStreamFailed( @@ -315,13 +318,13 @@ void HttpStreamFactoryImpl::Request::OnNewSpdySessionReady( // Cache this so we can still use it if the request is deleted. HttpStreamFactoryImpl* factory = factory_; if (factory->for_websockets_) { - DCHECK(websocket_stream_factory_); + DCHECK(websocket_handshake_stream_create_helper_); bool use_relative_url = direct || url().SchemeIs("wss"); - delegate_->OnWebSocketStreamReady( + delegate_->OnWebSocketHandshakeStreamReady( job->server_ssl_config(), job->proxy_info(), - websocket_stream_factory_->CreateSpdyStream(spdy_session, - use_relative_url)); + websocket_handshake_stream_create_helper_->CreateSpdyStream( + spdy_session, use_relative_url)); } else { bool use_relative_url = direct || url().SchemeIs("https"); delegate_->OnStreamReady( diff --git a/chromium/net/http/http_stream_factory_impl_request.h b/chromium/net/http/http_stream_factory_impl_request.h index d6f9b02cbef..3d3b2c8bd63 100644 --- a/chromium/net/http/http_stream_factory_impl_request.h +++ b/chromium/net/http/http_stream_factory_impl_request.h @@ -23,7 +23,8 @@ class HttpStreamFactoryImpl::Request : public HttpStreamRequest { Request(const GURL& url, HttpStreamFactoryImpl* factory, HttpStreamRequest::Delegate* delegate, - WebSocketStreamBase::Factory* websocket_stream_factory, + WebSocketHandshakeStreamBase::CreateHelper* + websocket_handshake_stream_create_helper, const BoundNetLog& net_log); virtual ~Request(); @@ -66,8 +67,9 @@ class HttpStreamFactoryImpl::Request : public HttpStreamRequest { const base::WeakPtr<SpdySession>& spdy_session, bool direct); - WebSocketStreamBase::Factory* websocket_stream_factory() { - return websocket_stream_factory_; + WebSocketHandshakeStreamBase::CreateHelper* + websocket_handshake_stream_create_helper() { + return websocket_handshake_stream_create_helper_; } // HttpStreamRequest::Delegate methods which we implement. Note we don't @@ -77,10 +79,10 @@ class HttpStreamFactoryImpl::Request : public HttpStreamRequest { const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, HttpStreamBase* stream); - void OnWebSocketStreamReady(Job* job, - const SSLConfig& used_ssl_config, - const ProxyInfo& used_proxy_info, - WebSocketStreamBase* stream); + void OnWebSocketHandshakeStreamReady(Job* job, + const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, + WebSocketHandshakeStreamBase* stream); void OnStreamFailed(Job* job, int status, const SSLConfig& used_ssl_config); void OnCertificateError(Job* job, int status, @@ -124,7 +126,8 @@ class HttpStreamFactoryImpl::Request : public HttpStreamRequest { const GURL url_; HttpStreamFactoryImpl* const factory_; - WebSocketStreamBase::Factory* const websocket_stream_factory_; + WebSocketHandshakeStreamBase::CreateHelper* const + websocket_handshake_stream_create_helper_; HttpStreamRequest::Delegate* const delegate_; const BoundNetLog net_log_; diff --git a/chromium/net/http/http_stream_factory_impl_request_unittest.cc b/chromium/net/http/http_stream_factory_impl_request_unittest.cc index 1f38a2e56f6..b3b12bfa5a3 100644 --- a/chromium/net/http/http_stream_factory_impl_request_unittest.cc +++ b/chromium/net/http/http_stream_factory_impl_request_unittest.cc @@ -19,7 +19,8 @@ class HttpStreamFactoryImplRequestTest INSTANTIATE_TEST_CASE_P( NextProto, HttpStreamFactoryImplRequestTest, - testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2, + testing::Values(kProtoDeprecatedSPDY2, + kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2, kProtoHTTP2Draft04)); namespace { @@ -35,10 +36,10 @@ class DoNothingRequestDelegate : public HttpStreamRequest::Delegate { const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, HttpStreamBase* stream) OVERRIDE {} - virtual void OnWebSocketStreamReady( + virtual void OnWebSocketHandshakeStreamReady( const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, - WebSocketStreamBase* stream) OVERRIDE {} + WebSocketHandshakeStreamBase* stream) OVERRIDE {} virtual void OnStreamFailed( int status, const SSLConfig& used_ssl_config) OVERRIDE {} diff --git a/chromium/net/http/http_stream_factory_impl_unittest.cc b/chromium/net/http/http_stream_factory_impl_unittest.cc index f378c93ea18..e3169b65993 100644 --- a/chromium/net/http/http_stream_factory_impl_unittest.cc +++ b/chromium/net/http/http_stream_factory_impl_unittest.cc @@ -36,7 +36,7 @@ // This file can be included from net/http even though // it is in net/websockets because it doesn't // introduce any link dependency to net/websockets. -#include "net/websockets/websocket_stream_base.h" +#include "net/websockets/websocket_handshake_stream_base.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { @@ -57,23 +57,66 @@ class UseAlternateProtocolsScopedSetter { bool use_alternate_protocols_; }; -class MockWebSocketStream : public WebSocketStreamBase { +class MockWebSocketHandshakeStream : public WebSocketHandshakeStreamBase { public: enum StreamType { kStreamTypeBasic, kStreamTypeSpdy, }; - explicit MockWebSocketStream(StreamType type) : type_(type) {} + explicit MockWebSocketHandshakeStream(StreamType type) : type_(type) {} - virtual ~MockWebSocketStream() {} - - virtual WebSocketStream* AsWebSocketStream() OVERRIDE { return NULL; } + virtual ~MockWebSocketHandshakeStream() {} StreamType type() const { return type_; } + // HttpStreamBase methods + virtual int InitializeStream(const HttpRequestInfo* request_info, + RequestPriority priority, + const BoundNetLog& net_log, + const CompletionCallback& callback) OVERRIDE { + return ERR_IO_PENDING; + } + virtual int SendRequest(const HttpRequestHeaders& request_headers, + HttpResponseInfo* response, + const CompletionCallback& callback) OVERRIDE { + return ERR_IO_PENDING; + } + virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE { + return ERR_IO_PENDING; + } + virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE { + return NULL; + } + virtual int ReadResponseBody(IOBuffer* buf, + int buf_len, + const CompletionCallback& callback) OVERRIDE { + return ERR_IO_PENDING; + } + virtual void Close(bool not_reusable) OVERRIDE {} + virtual bool IsResponseBodyComplete() const OVERRIDE { return false; } + virtual bool CanFindEndOfResponse() const OVERRIDE { return false; } + virtual bool IsConnectionReused() const OVERRIDE { return false; } + virtual void SetConnectionReused() OVERRIDE {} + virtual bool IsConnectionReusable() const OVERRIDE { return false; } + virtual int64 GetTotalReceivedBytes() const OVERRIDE { return 0; } + virtual bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const + OVERRIDE { + return false; + } + virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE {} + virtual void GetSSLCertRequestInfo( + SSLCertRequestInfo* cert_request_info) OVERRIDE {} + virtual bool IsSpdyHttpStream() const OVERRIDE { return false; } + virtual void Drain(HttpNetworkSession* session) OVERRIDE {} + virtual void SetPriority(RequestPriority priority) OVERRIDE {} + + virtual scoped_ptr<WebSocketStream> Upgrade() OVERRIDE { + return scoped_ptr<WebSocketStream>(); + } + private: const StreamType type_; }; @@ -128,10 +171,10 @@ class StreamRequestWaiter : public HttpStreamRequest::Delegate { used_proxy_info_ = used_proxy_info; } - virtual void OnWebSocketStreamReady( + virtual void OnWebSocketHandshakeStreamReady( const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, - WebSocketStreamBase* stream) OVERRIDE { + WebSocketHandshakeStreamBase* stream) OVERRIDE { stream_done_ = true; if (waiting_for_stream_) base::MessageLoop::current()->Quit(); @@ -182,8 +225,8 @@ class StreamRequestWaiter : public HttpStreamRequest::Delegate { return stream_.get(); } - MockWebSocketStream* websocket_stream() { - return static_cast<MockWebSocketStream*>(websocket_stream_.get()); + MockWebSocketHandshakeStream* websocket_stream() { + return static_cast<MockWebSocketHandshakeStream*>(websocket_stream_.get()); } bool stream_done() const { return stream_done_; } @@ -192,19 +235,21 @@ class StreamRequestWaiter : public HttpStreamRequest::Delegate { bool waiting_for_stream_; bool stream_done_; scoped_ptr<HttpStreamBase> stream_; - scoped_ptr<WebSocketStreamBase> websocket_stream_; + scoped_ptr<WebSocketHandshakeStreamBase> websocket_stream_; SSLConfig used_ssl_config_; ProxyInfo used_proxy_info_; DISALLOW_COPY_AND_ASSIGN(StreamRequestWaiter); }; -class WebSocketSpdyStream : public MockWebSocketStream { +class WebSocketSpdyHandshakeStream : public MockWebSocketHandshakeStream { public: - explicit WebSocketSpdyStream(const base::WeakPtr<SpdySession>& spdy_session) - : MockWebSocketStream(kStreamTypeSpdy), spdy_session_(spdy_session) {} + explicit WebSocketSpdyHandshakeStream( + const base::WeakPtr<SpdySession>& spdy_session) + : MockWebSocketHandshakeStream(kStreamTypeSpdy), + spdy_session_(spdy_session) {} - virtual ~WebSocketSpdyStream() {} + virtual ~WebSocketSpdyHandshakeStream() {} SpdySession* spdy_session() { return spdy_session_.get(); } @@ -212,12 +257,14 @@ class WebSocketSpdyStream : public MockWebSocketStream { base::WeakPtr<SpdySession> spdy_session_; }; -class WebSocketBasicStream : public MockWebSocketStream { +class WebSocketBasicHandshakeStream : public MockWebSocketHandshakeStream { public: - explicit WebSocketBasicStream(ClientSocketHandle* connection) - : MockWebSocketStream(kStreamTypeBasic), connection_(connection) {} + explicit WebSocketBasicHandshakeStream( + scoped_ptr<ClientSocketHandle> connection) + : MockWebSocketHandshakeStream(kStreamTypeBasic), + connection_(connection.Pass()) {} - virtual ~WebSocketBasicStream() { + virtual ~WebSocketBasicHandshakeStream() { connection_->socket()->Disconnect(); } @@ -227,19 +274,21 @@ class WebSocketBasicStream : public MockWebSocketStream { scoped_ptr<ClientSocketHandle> connection_; }; -class WebSocketStreamFactory : public WebSocketStreamBase::Factory { +class WebSocketStreamCreateHelper + : public WebSocketHandshakeStreamBase::CreateHelper { public: - virtual ~WebSocketStreamFactory() {} + virtual ~WebSocketStreamCreateHelper() {} - virtual WebSocketStreamBase* CreateBasicStream(ClientSocketHandle* connection, - bool using_proxy) OVERRIDE { - return new WebSocketBasicStream(connection); + virtual WebSocketHandshakeStreamBase* CreateBasicStream( + scoped_ptr<ClientSocketHandle> connection, + bool using_proxy) OVERRIDE { + return new WebSocketBasicHandshakeStream(connection.Pass()); } - virtual WebSocketStreamBase* CreateSpdyStream( + virtual WebSocketHandshakeStreamBase* CreateSpdyStream( const base::WeakPtr<SpdySession>& spdy_session, bool use_relative_url) OVERRIDE { - return new WebSocketSpdyStream(spdy_session); + return new WebSocketSpdyHandshakeStream(spdy_session); } }; @@ -261,7 +310,7 @@ void PreconnectHelperForURL(int num_streams, HttpNetworkSessionPeer peer(session); MockHttpStreamFactoryImplForPreconnect* mock_factory = new MockHttpStreamFactoryImplForPreconnect(session, false); - peer.SetHttpStreamFactory(mock_factory); + peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(mock_factory)); SSLConfig ssl_config; session->ssl_config_service()->GetSSLConfig(&ssl_config); @@ -376,6 +425,7 @@ CapturePreconnectsSSLSocketPool::CapturePreconnectsSocketPool( cert_verifier, NULL, NULL, + NULL, std::string(), NULL, NULL, @@ -392,7 +442,8 @@ class HttpStreamFactoryTest : public ::testing::Test, INSTANTIATE_TEST_CASE_P( NextProto, HttpStreamFactoryTest, - testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2, + testing::Values(kProtoDeprecatedSPDY2, + kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2, kProtoHTTP2Draft04)); TEST_P(HttpStreamFactoryTest, PreconnectDirect) { @@ -410,11 +461,12 @@ TEST_P(HttpStreamFactoryTest, PreconnectDirect) { new CapturePreconnectsSSLSocketPool( session_deps.host_resolver.get(), session_deps.cert_verifier.get()); - MockClientSocketPoolManager* mock_pool_manager = - new MockClientSocketPoolManager; + scoped_ptr<MockClientSocketPoolManager> mock_pool_manager( + new MockClientSocketPoolManager); mock_pool_manager->SetTransportSocketPool(transport_conn_pool); mock_pool_manager->SetSSLSocketPool(ssl_conn_pool); - peer.SetClientSocketPoolManager(mock_pool_manager); + peer.SetClientSocketPoolManager( + mock_pool_manager.PassAs<ClientSocketPoolManager>()); PreconnectHelper(kTests[i], session.get()); if (kTests[i].ssl) EXPECT_EQ(kTests[i].num_streams, ssl_conn_pool->last_num_streams()); @@ -439,11 +491,12 @@ TEST_P(HttpStreamFactoryTest, PreconnectHttpProxy) { new CapturePreconnectsSSLSocketPool( session_deps.host_resolver.get(), session_deps.cert_verifier.get()); - MockClientSocketPoolManager* mock_pool_manager = - new MockClientSocketPoolManager; + scoped_ptr<MockClientSocketPoolManager> mock_pool_manager( + new MockClientSocketPoolManager); mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool); mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool); - peer.SetClientSocketPoolManager(mock_pool_manager); + peer.SetClientSocketPoolManager( + mock_pool_manager.PassAs<ClientSocketPoolManager>()); PreconnectHelper(kTests[i], session.get()); if (kTests[i].ssl) EXPECT_EQ(kTests[i].num_streams, ssl_conn_pool->last_num_streams()); @@ -468,11 +521,12 @@ TEST_P(HttpStreamFactoryTest, PreconnectSocksProxy) { new CapturePreconnectsSSLSocketPool( session_deps.host_resolver.get(), session_deps.cert_verifier.get()); - MockClientSocketPoolManager* mock_pool_manager = - new MockClientSocketPoolManager; + scoped_ptr<MockClientSocketPoolManager> mock_pool_manager( + new MockClientSocketPoolManager); mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_proxy_pool); mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool); - peer.SetClientSocketPoolManager(mock_pool_manager); + peer.SetClientSocketPoolManager( + mock_pool_manager.PassAs<ClientSocketPoolManager>()); PreconnectHelper(kTests[i], session.get()); if (kTests[i].ssl) EXPECT_EQ(kTests[i].num_streams, ssl_conn_pool->last_num_streams()); @@ -503,11 +557,12 @@ TEST_P(HttpStreamFactoryTest, PreconnectDirectWithExistingSpdySession) { new CapturePreconnectsSSLSocketPool( session_deps.host_resolver.get(), session_deps.cert_verifier.get()); - MockClientSocketPoolManager* mock_pool_manager = - new MockClientSocketPoolManager; + scoped_ptr<MockClientSocketPoolManager> mock_pool_manager( + new MockClientSocketPoolManager); mock_pool_manager->SetTransportSocketPool(transport_conn_pool); mock_pool_manager->SetSSLSocketPool(ssl_conn_pool); - peer.SetClientSocketPoolManager(mock_pool_manager); + peer.SetClientSocketPoolManager( + mock_pool_manager.PassAs<ClientSocketPoolManager>()); PreconnectHelper(kTests[i], session.get()); // We shouldn't be preconnecting if we have an existing session, which is // the case for https://www.google.com. @@ -534,10 +589,11 @@ TEST_P(HttpStreamFactoryTest, PreconnectUnsafePort) { new CapturePreconnectsTransportSocketPool( session_deps.host_resolver.get(), session_deps.cert_verifier.get()); - MockClientSocketPoolManager* mock_pool_manager = - new MockClientSocketPoolManager; + scoped_ptr<MockClientSocketPoolManager> mock_pool_manager( + new MockClientSocketPoolManager); mock_pool_manager->SetTransportSocketPool(transport_conn_pool); - peer.SetClientSocketPoolManager(mock_pool_manager); + peer.SetClientSocketPoolManager( + mock_pool_manager.PassAs<ClientSocketPoolManager>()); PreconnectHelperForURL(1, GURL("http://www.google.com:7"), session.get()); @@ -864,7 +920,7 @@ TEST_P(HttpStreamFactoryTest, RequestHttpStreamOverProxy) { EXPECT_FALSE(waiter.used_proxy_info().is_direct()); } -TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicStream) { +TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStream) { SpdySessionDependencies session_deps( GetParam(), ProxyService::CreateDirect()); @@ -883,21 +939,21 @@ TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicStream) { SSLConfig ssl_config; StreamRequestWaiter waiter; - WebSocketStreamFactory factory; + WebSocketStreamCreateHelper create_helper; scoped_ptr<HttpStreamRequest> request( - session->websocket_stream_factory()->RequestWebSocketStream( - request_info, - DEFAULT_PRIORITY, - ssl_config, - ssl_config, - &waiter, - &factory, - BoundNetLog())); + session->http_stream_factory_for_websocket() + ->RequestWebSocketHandshakeStream(request_info, + DEFAULT_PRIORITY, + ssl_config, + ssl_config, + &waiter, + &create_helper, + BoundNetLog())); waiter.WaitForStream(); EXPECT_TRUE(waiter.stream_done()); EXPECT_TRUE(NULL == waiter.stream()); ASSERT_TRUE(NULL != waiter.websocket_stream()); - EXPECT_EQ(MockWebSocketStream::kStreamTypeBasic, + EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeBasic, waiter.websocket_stream()->type()); EXPECT_EQ(0, GetSocketPoolGroupCount( session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); @@ -911,7 +967,7 @@ TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicStream) { EXPECT_TRUE(waiter.used_proxy_info().is_direct()); } -TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicStreamOverSSL) { +TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStreamOverSSL) { SpdySessionDependencies session_deps( GetParam(), ProxyService::CreateDirect()); @@ -934,21 +990,21 @@ TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicStreamOverSSL) { SSLConfig ssl_config; StreamRequestWaiter waiter; - WebSocketStreamFactory factory; + WebSocketStreamCreateHelper create_helper; scoped_ptr<HttpStreamRequest> request( - session->websocket_stream_factory()->RequestWebSocketStream( - request_info, - DEFAULT_PRIORITY, - ssl_config, - ssl_config, - &waiter, - &factory, - BoundNetLog())); + session->http_stream_factory_for_websocket() + ->RequestWebSocketHandshakeStream(request_info, + DEFAULT_PRIORITY, + ssl_config, + ssl_config, + &waiter, + &create_helper, + BoundNetLog())); waiter.WaitForStream(); EXPECT_TRUE(waiter.stream_done()); EXPECT_TRUE(NULL == waiter.stream()); ASSERT_TRUE(NULL != waiter.websocket_stream()); - EXPECT_EQ(MockWebSocketStream::kStreamTypeBasic, + EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeBasic, waiter.websocket_stream()->type()); EXPECT_EQ(0, GetSocketPoolGroupCount( session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); @@ -962,7 +1018,7 @@ TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicStreamOverSSL) { EXPECT_TRUE(waiter.used_proxy_info().is_direct()); } -TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicStreamOverProxy) { +TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStreamOverProxy) { SpdySessionDependencies session_deps( GetParam(), ProxyService::CreateFixed("myproxy:8888")); @@ -982,21 +1038,21 @@ TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicStreamOverProxy) { SSLConfig ssl_config; StreamRequestWaiter waiter; - WebSocketStreamFactory factory; + WebSocketStreamCreateHelper create_helper; scoped_ptr<HttpStreamRequest> request( - session->websocket_stream_factory()->RequestWebSocketStream( - request_info, - DEFAULT_PRIORITY, - ssl_config, - ssl_config, - &waiter, - &factory, - BoundNetLog())); + session->http_stream_factory_for_websocket() + ->RequestWebSocketHandshakeStream(request_info, + DEFAULT_PRIORITY, + ssl_config, + ssl_config, + &waiter, + &create_helper, + BoundNetLog())); waiter.WaitForStream(); EXPECT_TRUE(waiter.stream_done()); EXPECT_TRUE(NULL == waiter.stream()); ASSERT_TRUE(NULL != waiter.websocket_stream()); - EXPECT_EQ(MockWebSocketStream::kStreamTypeBasic, + EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeBasic, waiter.websocket_stream()->type()); EXPECT_EQ(0, GetSocketPoolGroupCount( session->GetTransportSocketPool( @@ -1071,7 +1127,7 @@ TEST_P(HttpStreamFactoryTest, RequestSpdyHttpStream) { EXPECT_TRUE(waiter.used_proxy_info().is_direct()); } -TEST_P(HttpStreamFactoryTest, RequestWebSocketSpdyStream) { +TEST_P(HttpStreamFactoryTest, RequestWebSocketSpdyHandshakeStream) { SpdySessionDependencies session_deps(GetParam(), ProxyService::CreateDirect()); @@ -1096,44 +1152,44 @@ TEST_P(HttpStreamFactoryTest, RequestWebSocketSpdyStream) { SSLConfig ssl_config; StreamRequestWaiter waiter1; - WebSocketStreamFactory factory; + WebSocketStreamCreateHelper create_helper; scoped_ptr<HttpStreamRequest> request1( - session->websocket_stream_factory()->RequestWebSocketStream( - request_info, - DEFAULT_PRIORITY, - ssl_config, - ssl_config, - &waiter1, - &factory, - BoundNetLog())); + session->http_stream_factory_for_websocket() + ->RequestWebSocketHandshakeStream(request_info, + DEFAULT_PRIORITY, + ssl_config, + ssl_config, + &waiter1, + &create_helper, + BoundNetLog())); waiter1.WaitForStream(); EXPECT_TRUE(waiter1.stream_done()); ASSERT_TRUE(NULL != waiter1.websocket_stream()); - EXPECT_EQ(MockWebSocketStream::kStreamTypeSpdy, + EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeSpdy, waiter1.websocket_stream()->type()); EXPECT_TRUE(NULL == waiter1.stream()); StreamRequestWaiter waiter2; scoped_ptr<HttpStreamRequest> request2( - session->websocket_stream_factory()->RequestWebSocketStream( - request_info, - DEFAULT_PRIORITY, - ssl_config, - ssl_config, - &waiter2, - &factory, - BoundNetLog())); + session->http_stream_factory_for_websocket() + ->RequestWebSocketHandshakeStream(request_info, + DEFAULT_PRIORITY, + ssl_config, + ssl_config, + &waiter2, + &create_helper, + BoundNetLog())); waiter2.WaitForStream(); EXPECT_TRUE(waiter2.stream_done()); ASSERT_TRUE(NULL != waiter2.websocket_stream()); - EXPECT_EQ(MockWebSocketStream::kStreamTypeSpdy, + EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeSpdy, waiter2.websocket_stream()->type()); EXPECT_TRUE(NULL == waiter2.stream()); EXPECT_NE(waiter2.websocket_stream(), waiter1.websocket_stream()); - EXPECT_EQ(static_cast<WebSocketSpdyStream*>(waiter2.websocket_stream())-> - spdy_session(), - static_cast<WebSocketSpdyStream*>(waiter1.websocket_stream())-> - spdy_session()); + EXPECT_EQ(static_cast<WebSocketSpdyHandshakeStream*>( + waiter2.websocket_stream())->spdy_session(), + static_cast<WebSocketSpdyHandshakeStream*>( + waiter1.websocket_stream())->spdy_session()); EXPECT_EQ(0, GetSocketPoolGroupCount( session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); @@ -1186,21 +1242,21 @@ TEST_P(HttpStreamFactoryTest, OrphanedWebSocketStream) { SSLConfig ssl_config; StreamRequestWaiter waiter; - WebSocketStreamFactory factory; + WebSocketStreamCreateHelper create_helper; scoped_ptr<HttpStreamRequest> request( - session->websocket_stream_factory()->RequestWebSocketStream( - request_info, - DEFAULT_PRIORITY, - ssl_config, - ssl_config, - &waiter, - &factory, - BoundNetLog())); + session->http_stream_factory_for_websocket() + ->RequestWebSocketHandshakeStream(request_info, + DEFAULT_PRIORITY, + ssl_config, + ssl_config, + &waiter, + &create_helper, + BoundNetLog())); waiter.WaitForStream(); EXPECT_TRUE(waiter.stream_done()); EXPECT_TRUE(NULL == waiter.stream()); ASSERT_TRUE(NULL != waiter.websocket_stream()); - EXPECT_EQ(MockWebSocketStream::kStreamTypeSpdy, + EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeSpdy, waiter.websocket_stream()->type()); // Make sure that there was an alternative connection @@ -1218,7 +1274,7 @@ TEST_P(HttpStreamFactoryTest, OrphanedWebSocketStream) { // Make sure there is no orphaned job. it is already canceled. ASSERT_EQ(0u, static_cast<HttpStreamFactoryImpl*>( - session->websocket_stream_factory())->num_orphaned_jobs()); + session->http_stream_factory_for_websocket())->num_orphaned_jobs()); } } // namespace diff --git a/chromium/net/http/http_stream_parser.cc b/chromium/net/http/http_stream_parser.cc index 853414a106a..0821c848652 100644 --- a/chromium/net/http/http_stream_parser.cc +++ b/chromium/net/http/http_stream_parser.cc @@ -179,6 +179,7 @@ HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection, read_buf_(read_buffer), read_buf_unused_offset_(0), response_header_start_offset_(-1), + received_bytes_(0), response_body_length_(-1), response_body_read_(0), user_read_buf_(NULL), @@ -693,6 +694,9 @@ int HttpStreamParser::DoReadBodyComplete(int result) { result = ERR_CONTENT_LENGTH_MISMATCH; } + if (result > 0) + received_bytes_ += result; + // Filter incoming data if appropriate. FilterBuf may return an error. if (result > 0 && chunked_decoder_.get()) { result = chunked_decoder_->FilterBuf(user_read_buf_->data(), result); @@ -734,6 +738,7 @@ int HttpStreamParser::DoReadBodyComplete(int result) { } if (save_amount) { + received_bytes_ -= save_amount; memcpy(read_buf_->StartOfBuffer(), user_read_buf_->data() + result, save_amount); } @@ -788,6 +793,7 @@ int HttpStreamParser::DoParseResponseHeaders(int end_offset) { DCHECK_EQ(0, read_buf_unused_offset_); if (response_header_start_offset_ >= 0) { + received_bytes_ += end_offset; headers = new HttpResponseHeaders(HttpUtil::AssembleRawHeaders( read_buf_->StartOfBuffer(), end_offset)); } else { diff --git a/chromium/net/http/http_stream_parser.h b/chromium/net/http/http_stream_parser.h index 43e1514c2fe..e3690322bbd 100644 --- a/chromium/net/http/http_stream_parser.h +++ b/chromium/net/http/http_stream_parser.h @@ -77,6 +77,8 @@ class NET_EXPORT_PRIVATE HttpStreamParser { bool IsConnectionReusable() const; + int64 received_bytes() const { return received_bytes_; } + void GetSSLInfo(SSLInfo* ssl_info); void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info); @@ -186,6 +188,10 @@ class NET_EXPORT_PRIVATE HttpStreamParser { // -1 if not found yet. int response_header_start_offset_; + // The amount of received data. If connection is reused then intermediate + // value may be bigger than final. + int64 received_bytes_; + // The parsed response headers. Owned by the caller. HttpResponseInfo* response_; diff --git a/chromium/net/http/http_stream_parser_unittest.cc b/chromium/net/http/http_stream_parser_unittest.cc index 6e0053e6255..dcaf1f3e9c3 100644 --- a/chromium/net/http/http_stream_parser_unittest.cc +++ b/chromium/net/http/http_stream_parser_unittest.cc @@ -4,6 +4,10 @@ #include "net/http/http_stream_parser.h" +#include <algorithm> +#include <string> +#include <vector> + #include "base/file_util.h" #include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" @@ -19,6 +23,7 @@ #include "net/base/upload_file_element_reader.h" #include "net/http/http_request_headers.h" #include "net/http/http_request_info.h" +#include "net/http/http_response_headers.h" #include "net/http/http_response_info.h" #include "net/socket/client_socket_handle.h" #include "net/socket/socket_test_util.h" @@ -27,6 +32,8 @@ namespace net { +namespace { + const size_t kOutputSize = 1024; // Just large enough for this test. // The number of bytes that can fit in a buffer of kOutputSize. const size_t kMaxPayloadSize = @@ -98,7 +105,8 @@ TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_NoBody) { TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_EmptyBody) { ScopedVector<UploadElementReader> element_readers; - scoped_ptr<UploadDataStream> body(new UploadDataStream(&element_readers, 0)); + scoped_ptr<UploadDataStream> body( + new UploadDataStream(element_readers.Pass(), 0)); ASSERT_EQ(OK, body->Init(CompletionCallback())); // Shouldn't be merged if upload data is empty. ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody( @@ -124,8 +132,8 @@ TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_FileBody) { base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); base::FilePath temp_file_path; - ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir.path(), - &temp_file_path)); + ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.path(), + &temp_file_path)); element_readers.push_back( new UploadFileElementReader(base::MessageLoopProxy::current().get(), @@ -135,7 +143,7 @@ TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_FileBody) { base::Time())); scoped_ptr<UploadDataStream> body( - new UploadDataStream(&element_readers, 0)); + new UploadDataStream(element_readers.Pass(), 0)); TestCompletionCallback callback; ASSERT_EQ(ERR_IO_PENDING, body->Init(callback.callback())); ASSERT_EQ(OK, callback.WaitForResult()); @@ -153,7 +161,8 @@ TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_SmallBodyInMemory) { element_readers.push_back(new UploadBytesElementReader( payload.data(), payload.size())); - scoped_ptr<UploadDataStream> body(new UploadDataStream(&element_readers, 0)); + scoped_ptr<UploadDataStream> body( + new UploadDataStream(element_readers.Pass(), 0)); ASSERT_EQ(OK, body->Init(CompletionCallback())); // Yes, should be merged if the in-memory body is small here. ASSERT_TRUE(HttpStreamParser::ShouldMergeRequestHeadersAndBody( @@ -166,7 +175,8 @@ TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_LargeBodyInMemory) { element_readers.push_back(new UploadBytesElementReader( payload.data(), payload.size())); - scoped_ptr<UploadDataStream> body(new UploadDataStream(&element_readers, 0)); + scoped_ptr<UploadDataStream> body( + new UploadDataStream(element_readers.Pass(), 0)); ASSERT_EQ(OK, body->Init(CompletionCallback())); // Shouldn't be merged if the in-memory body is large here. ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody( @@ -419,4 +429,381 @@ TEST(HttpStreamParser, TruncatedHeaders) { } } +// Confirm that on 101 response, the headers are parsed but the data that +// follows remains in the buffer. +TEST(HttpStreamParser, Websocket101Response) { + MockRead reads[] = { + MockRead(SYNCHRONOUS, 1, + "HTTP/1.1 101 Switching Protocols\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "\r\n" + "a fake websocket frame"), + }; + + MockWrite writes[] = { + MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n"), + }; + + DeterministicSocketData data(reads, arraysize(reads), + writes, arraysize(writes)); + data.set_connect_data(MockConnect(SYNCHRONOUS, OK)); + data.SetStop(2); + + scoped_ptr<DeterministicMockTCPClientSocket> transport( + new DeterministicMockTCPClientSocket(NULL, &data)); + data.set_delegate(transport->AsWeakPtr()); + + TestCompletionCallback callback; + int rv = transport->Connect(callback.callback()); + rv = callback.GetResult(rv); + ASSERT_EQ(OK, rv); + + scoped_ptr<ClientSocketHandle> socket_handle(new ClientSocketHandle); + socket_handle->SetSocket(transport.PassAs<StreamSocket>()); + + HttpRequestInfo request_info; + request_info.method = "GET"; + request_info.url = GURL("http://localhost"); + request_info.load_flags = LOAD_NORMAL; + + scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); + HttpStreamParser parser( + socket_handle.get(), &request_info, read_buffer.get(), BoundNetLog()); + + HttpRequestHeaders request_headers; + HttpResponseInfo response_info; + rv = parser.SendRequest("GET / HTTP/1.1\r\n", request_headers, + &response_info, callback.callback()); + ASSERT_EQ(OK, rv); + + rv = parser.ReadResponseHeaders(callback.callback()); + EXPECT_EQ(OK, rv); + ASSERT_TRUE(response_info.headers.get()); + EXPECT_EQ(101, response_info.headers->response_code()); + EXPECT_TRUE(response_info.headers->HasHeaderValue("Connection", "Upgrade")); + EXPECT_TRUE(response_info.headers->HasHeaderValue("Upgrade", "websocket")); + EXPECT_EQ(read_buffer->capacity(), read_buffer->offset()); + EXPECT_EQ("a fake websocket frame", + base::StringPiece(read_buffer->StartOfBuffer(), + read_buffer->capacity())); +} + +// Helper class for constructing HttpStreamParser and running GET requests. +class SimpleGetRunner { + public: + SimpleGetRunner() : read_buffer_(new GrowableIOBuffer), sequence_number_(0) { + writes_.push_back(MockWrite( + SYNCHRONOUS, sequence_number_++, "GET / HTTP/1.1\r\n\r\n")); + } + + HttpStreamParser* parser() { return parser_.get(); } + GrowableIOBuffer* read_buffer() { return read_buffer_.get(); } + HttpResponseInfo* response_info() { return &response_info_; } + + void AddInitialData(const std::string& data) { + int offset = read_buffer_->offset(); + int size = data.size(); + read_buffer_->SetCapacity(offset + size); + memcpy(read_buffer_->StartOfBuffer() + offset, data.data(), size); + read_buffer_->set_offset(offset + size); + } + + void AddRead(const std::string& data) { + reads_.push_back(MockRead(SYNCHRONOUS, sequence_number_++, data.data())); + } + + void SetupParserAndSendRequest() { + reads_.push_back(MockRead(SYNCHRONOUS, 0, sequence_number_++)); // EOF + + socket_handle_.reset(new ClientSocketHandle); + data_.reset(new DeterministicSocketData( + &reads_.front(), reads_.size(), &writes_.front(), writes_.size())); + data_->set_connect_data(MockConnect(SYNCHRONOUS, OK)); + data_->SetStop(reads_.size() + writes_.size()); + + transport_.reset(new DeterministicMockTCPClientSocket(NULL, data_.get())); + data_->set_delegate(transport_->AsWeakPtr()); + + TestCompletionCallback callback; + int rv = transport_->Connect(callback.callback()); + rv = callback.GetResult(rv); + ASSERT_EQ(OK, rv); + + socket_handle_->SetSocket(transport_.PassAs<StreamSocket>()); + + request_info_.method = "GET"; + request_info_.url = GURL("http://localhost"); + request_info_.load_flags = LOAD_NORMAL; + + parser_.reset(new HttpStreamParser( + socket_handle_.get(), &request_info_, read_buffer(), BoundNetLog())); + + rv = parser_->SendRequest("GET / HTTP/1.1\r\n", request_headers_, + &response_info_, callback.callback()); + ASSERT_EQ(OK, rv); + } + + void ReadHeaders() { + TestCompletionCallback callback; + EXPECT_EQ(OK, parser_->ReadResponseHeaders(callback.callback())); + } + + void ReadBody(int user_buf_len, int* read_lengths) { + TestCompletionCallback callback; + scoped_refptr<IOBuffer> buffer = new IOBuffer(user_buf_len); + int rv; + int i = 0; + while (true) { + rv = parser_->ReadResponseBody(buffer, user_buf_len, callback.callback()); + EXPECT_EQ(read_lengths[i], rv); + i++; + if (rv <= 0) + return; + } + } + + private: + HttpRequestHeaders request_headers_; + HttpResponseInfo response_info_; + HttpRequestInfo request_info_; + scoped_refptr<GrowableIOBuffer> read_buffer_; + std::vector<MockRead> reads_; + std::vector<MockWrite> writes_; + scoped_ptr<ClientSocketHandle> socket_handle_; + scoped_ptr<DeterministicSocketData> data_; + scoped_ptr<DeterministicMockTCPClientSocket> transport_; + scoped_ptr<HttpStreamParser> parser_; + int sequence_number_; +}; + +// Test that HTTP/0.9 response size is correctly calculated. +TEST(HttpStreamParser, ReceivedBytesNoHeaders) { + std::string response = "hello\r\nworld\r\n"; + + SimpleGetRunner get_runner; + get_runner.AddRead(response); + get_runner.SetupParserAndSendRequest(); + get_runner.ReadHeaders(); + EXPECT_EQ(0, get_runner.parser()->received_bytes()); + int response_size = response.size(); + int read_lengths[] = {response_size, 0}; + get_runner.ReadBody(response_size, read_lengths); + EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); +} + +// Test basic case where there is no keep-alive or extra data from the socket, +// and the entire response is received in a single read. +TEST(HttpStreamParser, ReceivedBytesNormal) { + std::string headers = "HTTP/1.1 200 OK\r\n" + "Content-Length: 7\r\n\r\n"; + std::string body = "content"; + std::string response = headers + body; + + SimpleGetRunner get_runner; + get_runner.AddRead(response); + get_runner.SetupParserAndSendRequest(); + get_runner.ReadHeaders(); + int64 headers_size = headers.size(); + EXPECT_EQ(headers_size, get_runner.parser()->received_bytes()); + int body_size = body.size(); + int read_lengths[] = {body_size, 0}; + get_runner.ReadBody(body_size, read_lengths); + int64 response_size = response.size(); + EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); +} + +// Test that bytes that represent "next" response are not counted +// as current response "received_bytes". +TEST(HttpStreamParser, ReceivedBytesExcludesNextResponse) { + std::string headers = "HTTP/1.1 200 OK\r\n" + "Content-Length: 8\r\n\r\n"; + std::string body = "content8"; + std::string response = headers + body; + std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO"; + std::string data = response + next_response; + + SimpleGetRunner get_runner; + get_runner.AddRead(data); + get_runner.SetupParserAndSendRequest(); + get_runner.ReadHeaders(); + EXPECT_EQ(39, get_runner.parser()->received_bytes()); + int64 headers_size = headers.size(); + EXPECT_EQ(headers_size, get_runner.parser()->received_bytes()); + int body_size = body.size(); + int read_lengths[] = {body_size, 0}; + get_runner.ReadBody(body_size, read_lengths); + int64 response_size = response.size(); + EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); + int64 next_response_size = next_response.size(); + EXPECT_EQ(next_response_size, get_runner.read_buffer()->offset()); +} + +// Test that "received_bytes" calculation works fine when last read +// contains more data than requested by user. +// We send data in two reads: +// 1) Headers + beginning of response +// 2) remaining part of response + next response start +// We setup user read buffer so it fully accepts the beginnig of response +// body, but it is larger that remaining part of body. +TEST(HttpStreamParser, ReceivedBytesMultiReadExcludesNextResponse) { + std::string headers = "HTTP/1.1 200 OK\r\n" + "Content-Length: 36\r\n\r\n"; + int64 user_buf_len = 32; + std::string body_start = std::string(user_buf_len, '#'); + int body_start_size = body_start.size(); + EXPECT_EQ(user_buf_len, body_start_size); + std::string response_start = headers + body_start; + std::string body_end = "abcd"; + std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO"; + std::string response_end = body_end + next_response; + + SimpleGetRunner get_runner; + get_runner.AddRead(response_start); + get_runner.AddRead(response_end); + get_runner.SetupParserAndSendRequest(); + get_runner.ReadHeaders(); + int64 headers_size = headers.size(); + EXPECT_EQ(headers_size, get_runner.parser()->received_bytes()); + int body_end_size = body_end.size(); + int read_lengths[] = {body_start_size, body_end_size, 0}; + get_runner.ReadBody(body_start_size, read_lengths); + int64 response_size = response_start.size() + body_end_size; + EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); + int64 next_response_size = next_response.size(); + EXPECT_EQ(next_response_size, get_runner.read_buffer()->offset()); +} + +// Test that "received_bytes" calculation works fine when there is no +// network activity at all; that is when all data is read from read buffer. +// In this case read buffer contains two responses. We expect that only +// bytes that correspond to the first one are taken into account. +TEST(HttpStreamParser, ReceivedBytesFromReadBufExcludesNextResponse) { + std::string headers = "HTTP/1.1 200 OK\r\n" + "Content-Length: 7\r\n\r\n"; + std::string body = "content"; + std::string response = headers + body; + std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO"; + std::string data = response + next_response; + + SimpleGetRunner get_runner; + get_runner.AddInitialData(data); + get_runner.SetupParserAndSendRequest(); + get_runner.ReadHeaders(); + int64 headers_size = headers.size(); + EXPECT_EQ(headers_size, get_runner.parser()->received_bytes()); + int body_size = body.size(); + int read_lengths[] = {body_size, 0}; + get_runner.ReadBody(body_size, read_lengths); + int64 response_size = response.size(); + EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); + int64 next_response_size = next_response.size(); + EXPECT_EQ(next_response_size, get_runner.read_buffer()->offset()); +} + +// Test calculating "received_bytes" when part of request has been already +// loaded and placed to read buffer by previous stream parser. +TEST(HttpStreamParser, ReceivedBytesUseReadBuf) { + std::string buffer = "HTTP/1.1 200 OK\r\n"; + std::string remaining_headers = "Content-Length: 7\r\n\r\n"; + int64 headers_size = buffer.size() + remaining_headers.size(); + std::string body = "content"; + std::string response = remaining_headers + body; + + SimpleGetRunner get_runner; + get_runner.AddInitialData(buffer); + get_runner.AddRead(response); + get_runner.SetupParserAndSendRequest(); + get_runner.ReadHeaders(); + EXPECT_EQ(headers_size, get_runner.parser()->received_bytes()); + int body_size = body.size(); + int read_lengths[] = {body_size, 0}; + get_runner.ReadBody(body_size, read_lengths); + EXPECT_EQ(headers_size + body_size, get_runner.parser()->received_bytes()); + EXPECT_EQ(0, get_runner.read_buffer()->offset()); +} + +// Test the case when the resulting read_buf contains both unused bytes and +// bytes ejected by chunked-encoding filter. +TEST(HttpStreamParser, ReceivedBytesChunkedTransferExcludesNextResponse) { + std::string response = "HTTP/1.1 200 OK\r\n" + "Transfer-Encoding: chunked\r\n\r\n" + "7\r\nChunk 1\r\n" + "8\r\nChunky 2\r\n" + "6\r\nTest 3\r\n" + "0\r\n\r\n"; + std::string next_response = "foo bar\r\n"; + std::string data = response + next_response; + + SimpleGetRunner get_runner; + get_runner.AddInitialData(data); + get_runner.SetupParserAndSendRequest(); + get_runner.ReadHeaders(); + int read_lengths[] = {4, 3, 6, 2, 6, 0}; + get_runner.ReadBody(7, read_lengths); + int64 response_size = response.size(); + EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); + int64 next_response_size = next_response.size(); + EXPECT_EQ(next_response_size, get_runner.read_buffer()->offset()); +} + +// Test that data transfered in multiple reads is correctly processed. +// We feed data into 4-bytes reads. Also we set length of read +// buffer to 5-bytes to test all possible buffer misaligments. +TEST(HttpStreamParser, ReceivedBytesMultipleReads) { + std::string headers = "HTTP/1.1 200 OK\r\n" + "Content-Length: 33\r\n\r\n"; + std::string body = "foo bar baz\r\n" + "sputnik mir babushka"; + std::string response = headers + body; + + size_t receive_length = 4; + std::vector<std::string> blocks; + for (size_t i = 0; i < response.size(); i += receive_length) { + size_t length = std::min(receive_length, response.size() - i); + blocks.push_back(response.substr(i, length)); + } + + SimpleGetRunner get_runner; + for (std::vector<std::string>::size_type i = 0; i < blocks.size(); ++i) + get_runner.AddRead(blocks[i]); + get_runner.SetupParserAndSendRequest(); + get_runner.ReadHeaders(); + int64 headers_size = headers.size(); + EXPECT_EQ(headers_size, get_runner.parser()->received_bytes()); + int read_lengths[] = {1, 4, 4, 4, 4, 4, 4, 4, 4, 0}; + get_runner.ReadBody(receive_length + 1, read_lengths); + int64 response_size = response.size(); + EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); +} + +// Test that "continue" HTTP header is counted as "received_bytes". +TEST(HttpStreamParser, ReceivedBytesIncludesContinueHeader) { + std::string status100 = "HTTP/1.1 100 OK\r\n\r\n"; + std::string headers = "HTTP/1.1 200 OK\r\n" + "Content-Length: 7\r\n\r\n"; + int64 headers_size = status100.size() + headers.size(); + std::string body = "content"; + std::string response = headers + body; + + SimpleGetRunner get_runner; + get_runner.AddRead(status100); + get_runner.AddRead(response); + get_runner.SetupParserAndSendRequest(); + get_runner.ReadHeaders(); + EXPECT_EQ(100, get_runner.response_info()->headers->response_code()); + int64 status100_size = status100.size(); + EXPECT_EQ(status100_size, get_runner.parser()->received_bytes()); + get_runner.ReadHeaders(); + EXPECT_EQ(200, get_runner.response_info()->headers->response_code()); + EXPECT_EQ(headers_size, get_runner.parser()->received_bytes()); + int64 response_size = headers_size + body.size(); + int body_size = body.size(); + int read_lengths[] = {body_size, 0}; + get_runner.ReadBody(body_size, read_lengths); + EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); +} + +} // namespace + } // namespace net diff --git a/chromium/net/http/http_transaction.h b/chromium/net/http/http_transaction.h index d44050080ba..849d03af50c 100644 --- a/chromium/net/http/http_transaction.h +++ b/chromium/net/http/http_transaction.h @@ -10,6 +10,7 @@ #include "net/base/net_export.h" #include "net/base/request_priority.h" #include "net/base/upload_progress.h" +#include "net/websockets/websocket_handshake_stream_base.h" namespace net { @@ -134,6 +135,12 @@ class NET_EXPORT_PRIVATE HttpTransaction { // Called when the priority of the parent job changes. virtual void SetPriority(RequestPriority priority) = 0; + + // Set the WebSocketHandshakeStreamBase::CreateHelper to be used for the + // request. Only relevant to WebSocket transactions. Must be called before + // Start(). Ownership of |create_helper| remains with the caller. + virtual void SetWebSocketHandshakeStreamCreateHelper( + WebSocketHandshakeStreamBase::CreateHelper* create_helper) = 0; }; } // namespace net diff --git a/chromium/net/http/http_transaction_unittest.cc b/chromium/net/http/http_transaction_unittest.cc index 9aa81cf608e..e161ecac506 100644 --- a/chromium/net/http/http_transaction_unittest.cc +++ b/chromium/net/http/http_transaction_unittest.cc @@ -228,6 +228,7 @@ MockNetworkTransaction::MockNetworkTransaction( : weak_factory_(this), data_cursor_(0), priority_(priority), + websocket_handshake_stream_create_helper_(NULL), transaction_factory_(factory->AsWeakPtr()), socket_log_id_(net::NetLog::Source::kInvalidId) { } @@ -375,6 +376,11 @@ void MockNetworkTransaction::SetPriority(net::RequestPriority priority) { priority_ = priority; } +void MockNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper( + net::WebSocketHandshakeStreamBase::CreateHelper* create_helper) { + websocket_handshake_stream_create_helper_ = create_helper; +} + void MockNetworkTransaction::CallbackLater( const net::CompletionCallback& callback, int result) { base::MessageLoop::current()->PostTask( diff --git a/chromium/net/http/http_transaction_unittest.h b/chromium/net/http/http_transaction_unittest.h index 407fc9fff9a..3d6bb0287fb 100644 --- a/chromium/net/http/http_transaction_unittest.h +++ b/chromium/net/http/http_transaction_unittest.h @@ -162,6 +162,7 @@ class MockNetworkLayer; class MockNetworkTransaction : public net::HttpTransaction, public base::SupportsWeakPtr<MockNetworkTransaction> { + typedef net::WebSocketHandshakeStreamBase::CreateHelper CreateHelper; public: MockNetworkTransaction(net::RequestPriority priority, MockNetworkLayer* factory); @@ -205,6 +206,12 @@ class MockNetworkTransaction virtual void SetPriority(net::RequestPriority priority) OVERRIDE; + virtual void SetWebSocketHandshakeStreamCreateHelper( + CreateHelper* create_helper) OVERRIDE; + + CreateHelper* websocket_handshake_stream_create_helper() { + return websocket_handshake_stream_create_helper_; + } net::RequestPriority priority() const { return priority_; } private: @@ -217,6 +224,7 @@ class MockNetworkTransaction int data_cursor_; int test_mode_; net::RequestPriority priority_; + CreateHelper* websocket_handshake_stream_create_helper_; base::WeakPtr<MockNetworkLayer> transaction_factory_; // NetLog ID of the fake / non-existent underlying socket used by the diff --git a/chromium/net/http/http_util_icu.cc b/chromium/net/http/http_util_icu.cc index 4f38f84d75b..88ad5906e7b 100644 --- a/chromium/net/http/http_util_icu.cc +++ b/chromium/net/http/http_util_icu.cc @@ -14,7 +14,8 @@ namespace net { // static std::string HttpUtil::PathForRequest(const GURL& url) { - DCHECK(url.is_valid() && url.SchemeIsHTTPOrHTTPS()); + DCHECK(url.is_valid() && (url.SchemeIsHTTPOrHTTPS() || + url.SchemeIsWSOrWSS())); if (url.has_query()) return url.path() + "?" + url.query(); return url.path(); @@ -23,8 +24,8 @@ std::string HttpUtil::PathForRequest(const GURL& url) { // static std::string HttpUtil::SpecForRequest(const GURL& url) { // We may get ftp scheme when fetching ftp resources through proxy. - DCHECK(url.is_valid() && (url.SchemeIsHTTPOrHTTPS() || - url.SchemeIs("ftp"))); + DCHECK(url.is_valid() && (url.SchemeIsHTTPOrHTTPS() || url.SchemeIs("ftp") || + url.SchemeIsWSOrWSS())); return SimplifyUrlForRequest(url).spec(); } diff --git a/chromium/net/http/http_util_unittest.cc b/chromium/net/http/http_util_unittest.cc index fe2d8b47496..54acf68d3c3 100644 --- a/chromium/net/http/http_util_unittest.cc +++ b/chromium/net/http/http_util_unittest.cc @@ -612,6 +612,21 @@ TEST(HttpUtilTest, RequestUrlSanitize) { "http://user:pass@google.com", "http://google.com/", "/" + }, + { // https scheme + "https://www.google.com:78/foobar?query=1#hash", + "https://www.google.com:78/foobar?query=1", + "/foobar?query=1" + }, + { // WebSocket's ws scheme + "ws://www.google.com:78/foobar?query=1#hash", + "ws://www.google.com:78/foobar?query=1", + "/foobar?query=1" + }, + { // WebSocket's wss scheme + "wss://www.google.com:78/foobar?query=1#hash", + "wss://www.google.com:78/foobar?query=1", + "/foobar?query=1" } }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { @@ -624,6 +639,13 @@ TEST(HttpUtilTest, RequestUrlSanitize) { } } +// Test SpecForRequest() for "ftp" scheme. +TEST(HttpUtilTest, SpecForRequestForUrlWithFtpScheme) { + GURL ftp_url("ftp://user:pass@google.com/pub/chromium/"); + EXPECT_EQ("ftp://google.com/pub/chromium/", + HttpUtil::SpecForRequest(ftp_url)); +} + TEST(HttpUtilTest, GenerateAcceptLanguageHeader) { EXPECT_EQ(std::string("en-US,fr;q=0.8,de;q=0.6"), HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de")); diff --git a/chromium/net/http/partial_data.cc b/chromium/net/http/partial_data.cc index 02fda6cc9b1..ee3678b5ea0 100644 --- a/chromium/net/http/partial_data.cc +++ b/chromium/net/http/partial_data.cc @@ -25,19 +25,6 @@ const char kLengthHeader[] = "Content-Length"; const char kRangeHeader[] = "Content-Range"; const int kDataStream = 1; -void AddRangeHeader(int64 start, int64 end, HttpRequestHeaders* headers) { - DCHECK(start >= 0 || end >= 0); - std::string my_start, my_end; - if (start >= 0) - my_start = base::Int64ToString(start); - if (end >= 0) - my_end = base::Int64ToString(end); - - headers->SetHeader( - HttpRequestHeaders::kRange, - base::StringPrintf("bytes=%s-%s", my_start.c_str(), my_end.c_str())); -} - } // namespace // A core object that can be detached from the Partialdata object at destruction @@ -156,8 +143,17 @@ void PartialData::RestoreHeaders(HttpRequestHeaders* headers) const { byte_range_.suffix_length() : byte_range_.last_byte_position(); headers->CopyFrom(extra_headers_); - if (!truncated_ && byte_range_.IsValid()) - AddRangeHeader(current_range_start_, end, headers); + if (truncated_ || !byte_range_.IsValid()) + return; + + if (current_range_start_ < 0) { + headers->SetHeader(HttpRequestHeaders::kRange, + HttpByteRange::Suffix(end).GetHeaderValue()); + } else { + headers->SetHeader(HttpRequestHeaders::kRange, + HttpByteRange::Bounded( + current_range_start_, end).GetHeaderValue()); + } } int PartialData::ShouldValidateCache(disk_cache::Entry* entry, @@ -222,11 +218,17 @@ void PartialData::PrepareCacheValidation(disk_cache::Entry* entry, range_present_ = true; if (len == cached_min_len_) final_range_ = true; - AddRangeHeader(current_range_start_, cached_start_ + cached_min_len_ - 1, - headers); + headers->SetHeader( + HttpRequestHeaders::kRange, + net::HttpByteRange::Bounded( + current_range_start_, + cached_start_ + cached_min_len_ - 1).GetHeaderValue()); } else { // This range is not in the cache. - AddRangeHeader(current_range_start_, cached_start_ - 1, headers); + headers->SetHeader( + HttpRequestHeaders::kRange, + net::HttpByteRange::Bounded( + current_range_start_, cached_start_ - 1).GetHeaderValue()); } } @@ -337,8 +339,12 @@ bool PartialData::ResponseHeadersOK(const HttpResponseHeaders* headers) { if (total_length <= 0) return false; + DCHECK_EQ(headers->response_code(), 206); + + // A server should return a valid content length with a 206 (per the standard) + // but relax the requirement because some servers don't do that. int64 content_length = headers->GetContentLength(); - if (content_length < 0 || content_length != end - start + 1) + if (content_length > 0 && content_length != end - start + 1) return false; if (!resource_size_) { diff --git a/chromium/net/http/proxy_connect_redirect_http_stream.cc b/chromium/net/http/proxy_connect_redirect_http_stream.cc index 59bb0146953..0857a7451ca 100644 --- a/chromium/net/http/proxy_connect_redirect_http_stream.cc +++ b/chromium/net/http/proxy_connect_redirect_http_stream.cc @@ -82,6 +82,10 @@ bool ProxyConnectRedirectHttpStream::IsConnectionReusable() const { return false; } +int64 ProxyConnectRedirectHttpStream::GetTotalReceivedBytes() const { + return 0; +} + bool ProxyConnectRedirectHttpStream::GetLoadTimingInfo( LoadTimingInfo* load_timing_info) const { if (!has_load_timing_info_) diff --git a/chromium/net/http/proxy_connect_redirect_http_stream.h b/chromium/net/http/proxy_connect_redirect_http_stream.h index c335c218c71..0547654ab92 100644 --- a/chromium/net/http/proxy_connect_redirect_http_stream.h +++ b/chromium/net/http/proxy_connect_redirect_http_stream.h @@ -50,6 +50,8 @@ class ProxyConnectRedirectHttpStream : public HttpStream { virtual void SetConnectionReused() OVERRIDE; virtual bool IsConnectionReusable() const OVERRIDE; + virtual int64 GetTotalReceivedBytes() const OVERRIDE; + // This function may be called. virtual bool GetLoadTimingInfo( LoadTimingInfo* load_timing_info) const OVERRIDE; diff --git a/chromium/net/http/transport_security_persister.cc b/chromium/net/http/transport_security_persister.cc new file mode 100644 index 00000000000..771d07dc1bc --- /dev/null +++ b/chromium/net/http/transport_security_persister.cc @@ -0,0 +1,318 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/http/transport_security_persister.h" + +#include "base/base64.h" +#include "base/bind.h" +#include "base/file_util.h" +#include "base/files/file_path.h" +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/message_loop/message_loop.h" +#include "base/message_loop/message_loop_proxy.h" +#include "base/sequenced_task_runner.h" +#include "base/task_runner_util.h" +#include "base/values.h" +#include "crypto/sha2.h" +#include "net/cert/x509_certificate.h" +#include "net/http/transport_security_state.h" + +using net::HashValue; +using net::HashValueTag; +using net::HashValueVector; +using net::TransportSecurityState; + +namespace { + +ListValue* SPKIHashesToListValue(const HashValueVector& hashes) { + ListValue* pins = new ListValue; + for (size_t i = 0; i != hashes.size(); i++) + pins->Append(new StringValue(hashes[i].ToString())); + return pins; +} + +void SPKIHashesFromListValue(const ListValue& pins, HashValueVector* hashes) { + size_t num_pins = pins.GetSize(); + for (size_t i = 0; i < num_pins; ++i) { + std::string type_and_base64; + HashValue fingerprint; + if (pins.GetString(i, &type_and_base64) && + fingerprint.FromString(type_and_base64)) { + hashes->push_back(fingerprint); + } + } +} + +// This function converts the binary hashes to a base64 string which we can +// include in a JSON file. +std::string HashedDomainToExternalString(const std::string& hashed) { + std::string out; + base::Base64Encode(hashed, &out); + return out; +} + +// This inverts |HashedDomainToExternalString|, above. It turns an external +// string (from a JSON file) into an internal (binary) string. +std::string ExternalStringToHashedDomain(const std::string& external) { + std::string out; + if (!base::Base64Decode(external, &out) || + out.size() != crypto::kSHA256Length) { + return std::string(); + } + + return out; +} + +const char kIncludeSubdomains[] = "include_subdomains"; +const char kStsIncludeSubdomains[] = "sts_include_subdomains"; +const char kPkpIncludeSubdomains[] = "pkp_include_subdomains"; +const char kMode[] = "mode"; +const char kExpiry[] = "expiry"; +const char kDynamicSPKIHashesExpiry[] = "dynamic_spki_hashes_expiry"; +const char kStaticSPKIHashes[] = "static_spki_hashes"; +const char kPreloadedSPKIHashes[] = "preloaded_spki_hashes"; +const char kDynamicSPKIHashes[] = "dynamic_spki_hashes"; +const char kForceHTTPS[] = "force-https"; +const char kStrict[] = "strict"; +const char kDefault[] = "default"; +const char kPinningOnly[] = "pinning-only"; +const char kCreated[] = "created"; + +std::string LoadState(const base::FilePath& path) { + std::string result; + if (!base::ReadFileToString(path, &result)) { + return ""; + } + return result; +} + +} // namespace + + +namespace net { + +TransportSecurityPersister::TransportSecurityPersister( + TransportSecurityState* state, + const base::FilePath& profile_path, + base::SequencedTaskRunner* background_runner, + bool readonly) + : transport_security_state_(state), + writer_(profile_path.AppendASCII("TransportSecurity"), background_runner), + foreground_runner_(base::MessageLoop::current()->message_loop_proxy()), + background_runner_(background_runner), + readonly_(readonly), + weak_ptr_factory_(this) { + transport_security_state_->SetDelegate(this); + + base::PostTaskAndReplyWithResult( + background_runner_, + FROM_HERE, + base::Bind(&::LoadState, writer_.path()), + base::Bind(&TransportSecurityPersister::CompleteLoad, + weak_ptr_factory_.GetWeakPtr())); +} + +TransportSecurityPersister::~TransportSecurityPersister() { + DCHECK(foreground_runner_->RunsTasksOnCurrentThread()); + + if (writer_.HasPendingWrite()) + writer_.DoScheduledWrite(); + + transport_security_state_->SetDelegate(NULL); +} + +void TransportSecurityPersister::StateIsDirty( + TransportSecurityState* state) { + DCHECK(foreground_runner_->RunsTasksOnCurrentThread()); + DCHECK_EQ(transport_security_state_, state); + + if (!readonly_) + writer_.ScheduleWrite(this); +} + +bool TransportSecurityPersister::SerializeData(std::string* output) { + DCHECK(foreground_runner_->RunsTasksOnCurrentThread()); + + DictionaryValue toplevel; + base::Time now = base::Time::Now(); + TransportSecurityState::Iterator state(*transport_security_state_); + for (; state.HasNext(); state.Advance()) { + const std::string& hostname = state.hostname(); + const TransportSecurityState::DomainState& domain_state = + state.domain_state(); + + DictionaryValue* serialized = new DictionaryValue; + serialized->SetBoolean(kStsIncludeSubdomains, + domain_state.sts_include_subdomains); + serialized->SetBoolean(kPkpIncludeSubdomains, + domain_state.pkp_include_subdomains); + serialized->SetDouble(kCreated, domain_state.created.ToDoubleT()); + serialized->SetDouble(kExpiry, domain_state.upgrade_expiry.ToDoubleT()); + serialized->SetDouble(kDynamicSPKIHashesExpiry, + domain_state.dynamic_spki_hashes_expiry.ToDoubleT()); + + switch (domain_state.upgrade_mode) { + case TransportSecurityState::DomainState::MODE_FORCE_HTTPS: + serialized->SetString(kMode, kForceHTTPS); + break; + case TransportSecurityState::DomainState::MODE_DEFAULT: + serialized->SetString(kMode, kDefault); + break; + default: + NOTREACHED() << "DomainState with unknown mode"; + delete serialized; + continue; + } + + serialized->Set(kStaticSPKIHashes, + SPKIHashesToListValue(domain_state.static_spki_hashes)); + + if (now < domain_state.dynamic_spki_hashes_expiry) { + serialized->Set(kDynamicSPKIHashes, + SPKIHashesToListValue(domain_state.dynamic_spki_hashes)); + } + + toplevel.Set(HashedDomainToExternalString(hostname), serialized); + } + + base::JSONWriter::WriteWithOptions(&toplevel, + base::JSONWriter::OPTIONS_PRETTY_PRINT, + output); + return true; +} + +bool TransportSecurityPersister::LoadEntries(const std::string& serialized, + bool* dirty) { + DCHECK(foreground_runner_->RunsTasksOnCurrentThread()); + + transport_security_state_->ClearDynamicData(); + return Deserialize(serialized, dirty, transport_security_state_); +} + +// static +bool TransportSecurityPersister::Deserialize(const std::string& serialized, + bool* dirty, + TransportSecurityState* state) { + scoped_ptr<Value> value(base::JSONReader::Read(serialized)); + DictionaryValue* dict_value = NULL; + if (!value.get() || !value->GetAsDictionary(&dict_value)) + return false; + + const base::Time current_time(base::Time::Now()); + bool dirtied = false; + + for (DictionaryValue::Iterator i(*dict_value); !i.IsAtEnd(); i.Advance()) { + const DictionaryValue* parsed = NULL; + if (!i.value().GetAsDictionary(&parsed)) { + LOG(WARNING) << "Could not parse entry " << i.key() << "; skipping entry"; + continue; + } + + std::string mode_string; + double created; + double expiry; + double dynamic_spki_hashes_expiry = 0.0; + TransportSecurityState::DomainState domain_state; + + // kIncludeSubdomains is a legacy synonym for kStsIncludeSubdomains and + // kPkpIncludeSubdomains. Parse at least one of these properties, + // preferably the new ones. + bool include_subdomains = false; + bool parsed_include_subdomains = parsed->GetBoolean(kIncludeSubdomains, + &include_subdomains); + domain_state.sts_include_subdomains = include_subdomains; + domain_state.pkp_include_subdomains = include_subdomains; + if (parsed->GetBoolean(kStsIncludeSubdomains, &include_subdomains)) { + domain_state.sts_include_subdomains = include_subdomains; + parsed_include_subdomains = true; + } + if (parsed->GetBoolean(kPkpIncludeSubdomains, &include_subdomains)) { + domain_state.pkp_include_subdomains = include_subdomains; + parsed_include_subdomains = true; + } + + if (!parsed_include_subdomains || + !parsed->GetString(kMode, &mode_string) || + !parsed->GetDouble(kExpiry, &expiry)) { + LOG(WARNING) << "Could not parse some elements of entry " << i.key() + << "; skipping entry"; + continue; + } + + // Don't fail if this key is not present. + parsed->GetDouble(kDynamicSPKIHashesExpiry, + &dynamic_spki_hashes_expiry); + + const ListValue* pins_list = NULL; + // preloaded_spki_hashes is a legacy synonym for static_spki_hashes. + if (parsed->GetList(kStaticSPKIHashes, &pins_list)) + SPKIHashesFromListValue(*pins_list, &domain_state.static_spki_hashes); + else if (parsed->GetList(kPreloadedSPKIHashes, &pins_list)) + SPKIHashesFromListValue(*pins_list, &domain_state.static_spki_hashes); + + if (parsed->GetList(kDynamicSPKIHashes, &pins_list)) + SPKIHashesFromListValue(*pins_list, &domain_state.dynamic_spki_hashes); + + if (mode_string == kForceHTTPS || mode_string == kStrict) { + domain_state.upgrade_mode = + TransportSecurityState::DomainState::MODE_FORCE_HTTPS; + } else if (mode_string == kDefault || mode_string == kPinningOnly) { + domain_state.upgrade_mode = + TransportSecurityState::DomainState::MODE_DEFAULT; + } else { + LOG(WARNING) << "Unknown TransportSecurityState mode string " + << mode_string << " found for entry " << i.key() + << "; skipping entry"; + continue; + } + + domain_state.upgrade_expiry = base::Time::FromDoubleT(expiry); + domain_state.dynamic_spki_hashes_expiry = + base::Time::FromDoubleT(dynamic_spki_hashes_expiry); + if (parsed->GetDouble(kCreated, &created)) { + domain_state.created = base::Time::FromDoubleT(created); + } else { + // We're migrating an old entry with no creation date. Make sure we + // write the new date back in a reasonable time frame. + dirtied = true; + domain_state.created = base::Time::Now(); + } + + if (domain_state.upgrade_expiry <= current_time && + domain_state.dynamic_spki_hashes_expiry <= current_time) { + // Make sure we dirty the state if we drop an entry. + dirtied = true; + continue; + } + + std::string hashed = ExternalStringToHashedDomain(i.key()); + if (hashed.empty()) { + dirtied = true; + continue; + } + + state->AddOrUpdateEnabledHosts(hashed, domain_state); + } + + *dirty = dirtied; + return true; +} + +void TransportSecurityPersister::CompleteLoad(const std::string& state) { + DCHECK(foreground_runner_->RunsTasksOnCurrentThread()); + + if (state.empty()) + return; + + bool dirty = false; + if (!LoadEntries(state, &dirty)) { + LOG(ERROR) << "Failed to deserialize state: " << state; + return; + } + if (dirty) + StateIsDirty(transport_security_state_); +} + +} // namespace net diff --git a/chromium/net/http/transport_security_persister.h b/chromium/net/http/transport_security_persister.h new file mode 100644 index 00000000000..7725ba124e6 --- /dev/null +++ b/chromium/net/http/transport_security_persister.h @@ -0,0 +1,138 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// TransportSecurityState maintains an in memory database containing the +// list of hosts that currently have transport security enabled. This +// singleton object deals with writing that data out to disk as needed and +// loading it at startup. + +// At startup we need to load the transport security state from the +// disk. For the moment, we don't want to delay startup for this load, so we +// let the TransportSecurityState run for a while without being loaded. +// This means that it's possible for pages opened very quickly not to get the +// correct transport security information. +// +// To load the state, we schedule a Task on file_task_runner, which +// deserializes and configures the TransportSecurityState. +// +// The TransportSecurityState object supports running a callback function +// when it changes. This object registers the callback, pointing at itself. +// +// TransportSecurityState calls... +// TransportSecurityPersister::StateIsDirty +// since the callback isn't allowed to block or reenter, we schedule a Task +// on the file task runner after some small amount of time +// +// ... +// +// TransportSecurityPersister::SerializeState +// copies the current state of the TransportSecurityState, serializes +// and writes to disk. + +#ifndef NET_HTTP_TRANSPORT_SECURITY_PERSISTER_H_ +#define NET_HTTP_TRANSPORT_SECURITY_PERSISTER_H_ + +#include <string> + +#include "base/files/file_path.h" +#include "base/files/important_file_writer.h" +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "net/base/net_export.h" +#include "net/http/transport_security_state.h" + +namespace base { +class SequencedTaskRunner; +} + +namespace net { + +// Reads and updates on-disk TransportSecurity state. Clients of this class +// should create, destroy, and call into it from one thread. +// +// file_task_runner is the task runner this class should use internally to +// perform file IO, and can optionally be associated with a different thread. +class NET_EXPORT TransportSecurityPersister + : public TransportSecurityState::Delegate, + public base::ImportantFileWriter::DataSerializer { + public: + TransportSecurityPersister(TransportSecurityState* state, + const base::FilePath& profile_path, + base::SequencedTaskRunner* file_task_runner, + bool readonly); + virtual ~TransportSecurityPersister(); + + // Called by the TransportSecurityState when it changes its state. + virtual void StateIsDirty(TransportSecurityState*) OVERRIDE; + + // ImportantFileWriter::DataSerializer: + // + // Serializes |transport_security_state_| into |*output|. Returns true if + // all DomainStates were serialized correctly. + // + // The serialization format is JSON; the JSON represents a dictionary of + // host:DomainState pairs (host is a string). The DomainState is + // represented as a dictionary containing the following keys and value + // types (not all keys will always be present): + // + // "sts_include_subdomains": true|false + // "pkp_include_subdomains": true|false + // "created": double + // "expiry": double + // "dynamic_spki_hashes_expiry": double + // "mode": "default"|"force-https" + // legacy value synonyms "strict" = "force-https" + // "pinning-only" = "default" + // legacy value "spdy-only" is unused and ignored + // "static_spki_hashes": list of strings + // legacy key synonym "preloaded_spki_hashes" + // "bad_static_spki_hashes": list of strings + // legacy key synonym "bad_preloaded_spki_hashes" + // "dynamic_spki_hashes": list of strings + // + // The JSON dictionary keys are strings containing + // Base64(SHA256(TransportSecurityState::CanonicalizeHost(domain))). + // The reason for hashing them is so that the stored state does not + // trivially reveal a user's browsing history to an attacker reading the + // serialized state on disk. + virtual bool SerializeData(std::string* data) OVERRIDE; + + // Clears any existing non-static entries, and then re-populates + // |transport_security_state_|. + // + // Sets |*dirty| to true if the new state differs from the persisted + // state; false otherwise. + bool LoadEntries(const std::string& serialized, bool* dirty); + + private: + // Populates |state| from the JSON string |serialized|. Returns true if + // all entries were parsed and deserialized correctly. + // + // Sets |*dirty| to true if the new state differs from the persisted + // state; false otherwise. + static bool Deserialize(const std::string& serialized, + bool* dirty, + TransportSecurityState* state); + + void CompleteLoad(const std::string& state); + + TransportSecurityState* transport_security_state_; + + // Helper for safely writing the data. + base::ImportantFileWriter writer_; + + scoped_refptr<base::SequencedTaskRunner> foreground_runner_; + scoped_refptr<base::SequencedTaskRunner> background_runner_; + + // Whether or not we're in read-only mode. + const bool readonly_; + + base::WeakPtrFactory<TransportSecurityPersister> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(TransportSecurityPersister); +}; + +} // namespace net + +#endif // NET_HTTP_TRANSPORT_SECURITY_PERSISTER_H_ diff --git a/chromium/net/http/transport_security_persister_unittest.cc b/chromium/net/http/transport_security_persister_unittest.cc new file mode 100644 index 00000000000..8c41f9e81da --- /dev/null +++ b/chromium/net/http/transport_security_persister_unittest.cc @@ -0,0 +1,201 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/http/transport_security_persister.h" + +#include <map> +#include <string> +#include <vector> + +#include "base/file_util.h" +#include "base/files/file_path.h" +#include "base/files/scoped_temp_dir.h" +#include "base/message_loop/message_loop.h" +#include "net/http/transport_security_state.h" +#include "testing/gtest/include/gtest/gtest.h" + +using net::TransportSecurityPersister; +using net::TransportSecurityState; + +class TransportSecurityPersisterTest : public testing::Test { + public: + TransportSecurityPersisterTest() { + } + + virtual ~TransportSecurityPersisterTest() { + base::MessageLoopForIO::current()->RunUntilIdle(); + } + + virtual void SetUp() OVERRIDE { + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + persister_.reset(new TransportSecurityPersister( + &state_, + temp_dir_.path(), + base::MessageLoopForIO::current()->message_loop_proxy(), + false)); + } + + protected: + base::ScopedTempDir temp_dir_; + TransportSecurityState state_; + scoped_ptr<TransportSecurityPersister> persister_; +}; + +TEST_F(TransportSecurityPersisterTest, SerializeData1) { + std::string output; + bool dirty; + + EXPECT_TRUE(persister_->SerializeData(&output)); + EXPECT_TRUE(persister_->LoadEntries(output, &dirty)); + EXPECT_FALSE(dirty); +} + +TEST_F(TransportSecurityPersisterTest, SerializeData2) { + TransportSecurityState::DomainState domain_state; + const base::Time current_time(base::Time::Now()); + const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); + static const char kYahooDomain[] = "yahoo.com"; + + EXPECT_FALSE(state_.GetDomainState(kYahooDomain, true, &domain_state)); + + bool include_subdomains = true; + state_.AddHSTS(kYahooDomain, expiry, include_subdomains); + + std::string output; + bool dirty; + EXPECT_TRUE(persister_->SerializeData(&output)); + EXPECT_TRUE(persister_->LoadEntries(output, &dirty)); + + EXPECT_TRUE(state_.GetDomainState(kYahooDomain, true, &domain_state)); + EXPECT_EQ(domain_state.upgrade_mode, + TransportSecurityState::DomainState::MODE_FORCE_HTTPS); + EXPECT_TRUE(state_.GetDomainState("foo.yahoo.com", true, &domain_state)); + EXPECT_EQ(domain_state.upgrade_mode, + TransportSecurityState::DomainState::MODE_FORCE_HTTPS); + EXPECT_TRUE(state_.GetDomainState("foo.bar.yahoo.com", true, &domain_state)); + EXPECT_EQ(domain_state.upgrade_mode, + TransportSecurityState::DomainState::MODE_FORCE_HTTPS); + EXPECT_TRUE(state_.GetDomainState("foo.bar.baz.yahoo.com", true, + &domain_state)); + EXPECT_EQ(domain_state.upgrade_mode, + TransportSecurityState::DomainState::MODE_FORCE_HTTPS); + EXPECT_FALSE(state_.GetDomainState("com", true, &domain_state)); +} + +TEST_F(TransportSecurityPersisterTest, SerializeData3) { + // Add an entry. + net::HashValue fp1(net::HASH_VALUE_SHA1); + memset(fp1.data(), 0, fp1.size()); + net::HashValue fp2(net::HASH_VALUE_SHA1); + memset(fp2.data(), 1, fp2.size()); + base::Time expiry = + base::Time::Now() + base::TimeDelta::FromSeconds(1000); + net::HashValueVector dynamic_spki_hashes; + dynamic_spki_hashes.push_back(fp1); + dynamic_spki_hashes.push_back(fp2); + bool include_subdomains = false; + state_.AddHSTS("www.example.com", expiry, include_subdomains); + state_.AddHPKP("www.example.com", expiry, include_subdomains, + dynamic_spki_hashes); + + // Add another entry. + memset(fp1.data(), 2, fp1.size()); + memset(fp2.data(), 3, fp2.size()); + expiry = + base::Time::Now() + base::TimeDelta::FromSeconds(3000); + dynamic_spki_hashes.push_back(fp1); + dynamic_spki_hashes.push_back(fp2); + state_.AddHSTS("www.example.net", expiry, include_subdomains); + state_.AddHPKP("www.example.net", expiry, include_subdomains, + dynamic_spki_hashes); + + // Save a copy of everything. + std::map<std::string, TransportSecurityState::DomainState> saved; + TransportSecurityState::Iterator i(state_); + while (i.HasNext()) { + saved[i.hostname()] = i.domain_state(); + i.Advance(); + } + + std::string serialized; + EXPECT_TRUE(persister_->SerializeData(&serialized)); + + // Persist the data to the file. For the test to be fast and not flaky, we + // just do it directly rather than call persister_->StateIsDirty. (That uses + // ImportantFileWriter, which has an asynchronous commit interval rather + // than block.) Use a different basename just for cleanliness. + base::FilePath path = + temp_dir_.path().AppendASCII("TransportSecurityPersisterTest"); + EXPECT_TRUE(file_util::WriteFile(path, serialized.c_str(), + serialized.size())); + + // Read the data back. + std::string persisted; + EXPECT_TRUE(base::ReadFileToString(path, &persisted)); + EXPECT_EQ(persisted, serialized); + bool dirty; + EXPECT_TRUE(persister_->LoadEntries(persisted, &dirty)); + EXPECT_FALSE(dirty); + + // Check that states are the same as saved. + size_t count = 0; + TransportSecurityState::Iterator j(state_); + while (j.HasNext()) { + count++; + j.Advance(); + } + EXPECT_EQ(count, saved.size()); +} + +TEST_F(TransportSecurityPersisterTest, SerializeDataOld) { + // This is an old-style piece of transport state JSON, which has no creation + // date. + std::string output = + "{ " + "\"NiyD+3J1r6z1wjl2n1ALBu94Zj9OsEAMo0kCN8js0Uk=\": {" + "\"expiry\": 1266815027.983453, " + "\"include_subdomains\": false, " + "\"mode\": \"strict\" " + "}" + "}"; + bool dirty; + EXPECT_TRUE(persister_->LoadEntries(output, &dirty)); + EXPECT_TRUE(dirty); +} + +TEST_F(TransportSecurityPersisterTest, PublicKeyHashes) { + TransportSecurityState::DomainState domain_state; + static const char kTestDomain[] = "example.com"; + EXPECT_FALSE(state_.GetDomainState(kTestDomain, false, &domain_state)); + net::HashValueVector hashes; + EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes)); + + net::HashValue sha1(net::HASH_VALUE_SHA1); + memset(sha1.data(), '1', sha1.size()); + domain_state.dynamic_spki_hashes.push_back(sha1); + + EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes)); + + hashes.push_back(sha1); + EXPECT_TRUE(domain_state.CheckPublicKeyPins(hashes)); + + hashes[0].data()[0] = '2'; + EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes)); + + const base::Time current_time(base::Time::Now()); + const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); + bool include_subdomains = false; + state_.AddHSTS(kTestDomain, expiry, include_subdomains); + state_.AddHPKP(kTestDomain, expiry, include_subdomains, + domain_state.dynamic_spki_hashes); + std::string ser; + EXPECT_TRUE(persister_->SerializeData(&ser)); + bool dirty; + EXPECT_TRUE(persister_->LoadEntries(ser, &dirty)); + EXPECT_TRUE(state_.GetDomainState(kTestDomain, false, &domain_state)); + EXPECT_EQ(1u, domain_state.dynamic_spki_hashes.size()); + EXPECT_EQ(sha1.tag, domain_state.dynamic_spki_hashes[0].tag); + EXPECT_EQ(0, memcmp(domain_state.dynamic_spki_hashes[0].data(), sha1.data(), + sha1.size())); +} diff --git a/chromium/net/http/transport_security_state.cc b/chromium/net/http/transport_security_state.cc index d238e995568..f9ba807ff79 100644 --- a/chromium/net/http/transport_security_state.cc +++ b/chromium/net/http/transport_security_state.cc @@ -244,18 +244,8 @@ std::string TransportSecurityState::CanonicalizeHost(const std::string& host) { break; for (size_t j = 0; j < label_length; ++j) { - // RFC 3490, 4.1, step 3 - if (!IsSTD3ASCIIValidCharacter(new_host[i + 1 + j])) - return std::string(); - new_host[i + 1 + j] = tolower(new_host[i + 1 + j]); } - - // step 3(b) - if (new_host[i + 1] == '-' || - new_host[i + label_length] == '-') { - return std::string(); - } } return new_host; @@ -522,6 +512,9 @@ enum SecondLevelDomainName { DOMAIN_CHROMIUM_ORG, DOMAIN_CRYPTO_CAT, + DOMAIN_LAVABIT_COM, + + DOMAIN_GOOGLETAGMANAGER_COM, // Boundary value for UMA_HISTOGRAM_ENUMERATION: DOMAIN_NUM_EVENTS diff --git a/chromium/net/http/transport_security_state.h b/chromium/net/http/transport_security_state.h index ccbc53a087d..97b4d7c1fc8 100644 --- a/chromium/net/http/transport_security_state.h +++ b/chromium/net/http/transport_security_state.h @@ -35,7 +35,7 @@ class SSLInfo; class NET_EXPORT TransportSecurityState : NON_EXPORTED_BASE(public base::NonThreadSafe) { public: - class Delegate { + class NET_EXPORT Delegate { public: // This function may not block and may be called with internal locks held. // Thus it must not reenter the TransportSecurityState object. diff --git a/chromium/net/http/transport_security_state_static.certs b/chromium/net/http/transport_security_state_static.certs index ca6ef535bc8..718b7300f57 100644 --- a/chromium/net/http/transport_security_state_static.certs +++ b/chromium/net/http/transport_security_state_static.certs @@ -54,136 +54,12 @@ F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== -----END CERTIFICATE----- -Google1024 ------BEGIN CERTIFICATE----- -MIICsDCCAhmgAwIBAgIDC2dxMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT -MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0 -aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkwNjA4MjA0MzI3WhcNMTMwNjA3MTk0MzI3 -WjBGMQswCQYDVQQGEwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzEiMCAGA1UEAxMZ -R29vZ2xlIEludGVybmV0IEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw -gYkCgYEAye23pIucV+eEPkB9hPSP0XFjU5nneXQUr0SZMyCSjXvlKAy6rWxJfoNf -NFlOCnowzdDXxFdF7dWq1nMmzq0yE7jXDx07393cCDaob1FEm8rWIFJztyaHNWrb -qeXUWaUr/GcZOfqTGBhs3t0lig4zFEfC7wFQeeT9adGnwKziV28CAwEAAaOBozCB -oDAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFL/AMOv1QxE+Z7qekfv8atrjaxIk -MB8GA1UdIwQYMBaAFEjmaPkr0rKV10fYIyAQTzOYkJ/UMBIGA1UdEwEB/wQIMAYB -Af8CAQAwOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20v -Y3Jscy9zZWN1cmVjYS5jcmwwDQYJKoZIhvcNAQEFBQADgYEAuIojxkiWsRF8YHde -BZqrocb6ghwYB8TrgbCoZutJqOkM0ymt9e8kTP3kS8p/XmOrmSfLnzYhLLkQYGfN -0rTw8Ktx5YtaiScRhKqOv5nwnQkhClIZmloJ0pC3+gz4fniisIWvXEyZ2VxVKfml -UUIuOss4jHg7y/j7lYe8vJD5UDI= ------END CERTIFICATE----- - -Google2048 -sha1/AbkhxY0L343gKf+cki7NVWp+ozk= - -GoogleBackup1024 -sha1/fVujyo43ZR18ccPjt3TN6XsbWUM= - GoogleBackup2048 sha1/vq7OyjSnqOco9nyMCDGdy77eijM= GoogleG2 sha1/Q9rWMO5T+KmAym79hfRqo3mQ4Oo= -ThawteSGCCA ------BEGIN CERTIFICATE----- -MIIDIzCCAoygAwIBAgIEMAAAAjANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJV -UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDMgUHVi -bGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNTEzMDAw -MDAwWhcNMTQwNTEyMjM1OTU5WjBMMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhh -d3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBD -QTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1NNn0I0Vf67NMf59HZGhPwtx -PKzMyGT7Y/wySweUvW+Aui/hBJPAM/wJMyPpC3QrccQDxtLN4i/1CWPN/0ilAL/g -5/OIty0y3pg25gqtAHvEZEo7hHUD8nCSfQ5i9SGraTaEMXWQ+L/HbIgbBpV8yeWo -3nWhLHpo39XKHIdYYBkCAwEAAaOB/jCB+zASBgNVHRMBAf8ECDAGAQH/AgEAMAsG -A1UdDwQEAwIBBjARBglghkgBhvhCAQEEBAMCAQYwKAYDVR0RBCEwH6QdMBsxGTAX -BgNVBAMTEFByaXZhdGVMYWJlbDMtMTUwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDov -L2NybC52ZXJpc2lnbi5jb20vcGNhMy5jcmwwMgYIKwYBBQUHAQEEJjAkMCIGCCsG -AQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29tMDQGA1UdJQQtMCsGCCsGAQUF -BwMBBggrBgEFBQcDAgYJYIZIAYb4QgQBBgpghkgBhvhFAQgBMA0GCSqGSIb3DQEB -BQUAA4GBAFWsY+reod3SkF+fC852vhNRj5PZBSvIG3dLrWlQoe7e3P3bB+noOZTc -q3J5Lwa/q4FwxKjt6lM07e8eU9kGx1Yr0Vz00YqOtCuxN5BICEIlxT6Ky3/rbwTR -bcV0oveifHtgPHfNDs5IAn8BL7abN+AqKjbc1YXWrOU/VG+WHgWv ------END CERTIFICATE----- - -VeriSignClass3SSPIntermediateCA ------BEGIN CERTIFICATE----- -MIIGVDCCBTygAwIBAgIQGYH0QFTS4OtUK7v7RciQfjANBgkqhkiG9w0BAQUFADCB -yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMTk5OSBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW -ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5IC0gRzMwHhcNMTEwMTA3MDAwMDAwWhcNMTMxMjMxMjM1OTU5WjB2MQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxLTArBgNVBAMTJFZlcmlTaWduIENsYXNzIDMg -U1NQIEludGVybWVkaWF0ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBANfMaBonchSI7reVYNNe3hhSwUY/fbEmnDwCoonR2MFXsQkP9n8yNaU1nhRT -Eovg4zAetI+e0bDAt9/0Lw/n1x/FdiTTPdMN6SxKLqc8z7xql0MZ+MBzyhsstmIB -RmJWkGisFFAZ51BYB/k9AfLtHjQnvc1yHYBgo0ySG2a6ejkJd2r6U/dvjgbu2dSj -Eo5XJGl//xSSLKs4HPhkuAsdZr2HqPiBwjlFpCd//Fs8he43JBI60+bRSBiUKpQC -ssu6oAj2rvKcy2AMTvjIAlz9Iy3B92fB1Q1JxpbWcLochUca7/NFQTkKMaVeBXxy -i2D+SFWfuBLtcl7p/kbtwqfiDbMCAwEAAaOCAocwggKDMA8GA1UdEwEB/wQFMAMB -Af8wDgYDVR0PAQH/BAQDAgEGMIHoBgNVHSAEgeAwgd0wDwYNYIZIAYb4RQEHFwMB -BjAPBg1ghkgBhvhFAQcXAwEHMA8GDWCGSAGG+EUBBxcDAQgwDwYNYIZIAYb4RQEH -FwMBDTAPBg1ghkgBhvhFAQcXAwEOMA8GDWCGSAGG+EUBBxcDAQ8wDwYNYIZIAYb4 -RQEHFwMBETAPBg1ghkgBhvhFAQcXAwEUMA8GDWCGSAGG+EUBBxcDARcwDwYNYIZI -AYb4RQEHFwMBGDAPBg1ghkgBhvhFAQcXAwEZMA8GDWCGSAGG+EUBBxcDARowDwYN -YIZIAYb4RQEHFwMBGzA4BgNVHR8EMTAvMC2gK6AphidodHRwOi8vc3NwLWNybC52 -ZXJpc2lnbi5jb20vcGNhMy1nMy5jcmwwKAYDVR0RBCEwH6QdMBsxGTAXBgNVBAMT -EFZlcmlTaWduTVBLSS0xLTgwHQYDVR0OBBYEFCwx/8HOq/lN6IkVwGry5atCfUL6 -MIHxBgNVHSMEgekwgeahgdCkgc0wgcoxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5W -ZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazE6 -MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXpl -ZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24gQ2xhc3MgMyBQdWJsaWMgUHJp -bWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczghEAm34GSaM+YrnV7pBI -cSnvVzANBgkqhkiG9w0BAQUFAAOCAQEAIS19vzG9j+KXiQ0G1bOuJCeiD9KKW1+8 -69cutvgDf3hEvrw39Gr2ek3cAdso7dvwW0Z17muzpHV08gWTjjKba8mBzjijmgr9 -I2vE2K/Ls72WJvTDUjCAHfBJKeK1q8v7xv1xtf2Jz7BV8sNH3kDB7jhhE++8zLVC -gyFilU0KZfhBpLPVlVYnLozRdvsHfNnO/JskJvRqhDYbeC5ginQT0m5sTQiyTYqL -/IU+i82TxANXjC7syl0dfcGr8pJ85T9bF1EZLxdgikAYLKPGTuXMwOGqT5bR0dKD -lWShiGTRl7HW0KJMg05F0HjOnYpdOYGaFrQghecrkcrRPRevSdFVHQ== ------END CERTIFICATE----- - -EquifaxSecureCA ------BEGIN CERTIFICATE----- -MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV -UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy -dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 -MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx -dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B -AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f -BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A -cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC -AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ -MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm -aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw -ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj -IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF -MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA -A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y -7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh -1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 ------END CERTIFICATE----- - -Aetna ------BEGIN CERTIFICATE----- -MIICsjCCAhugAwIBAgIDBe3YMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT -MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0 -aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDUwODMxMjA0MDM3WhcNMTIwODMxMjA0MDM3 -WjBIMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQWV0bmEgSW5jLjEkMCIGA1UEAxMb -QWV0bmEgSW5jLiBTZWN1cmUgU2VydmVyIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQCnB2yrm4i44DG5epPu0fbe/pOZDWOvAS7qCcy6YbSkPfOHfH9Blmf3 -8L6D5yY1pzmTXaU7cDQu4qmj21toEIGwBziMmW6NsiV8nHtmtfXfHP6xrmyPUdN2 -DdTj937fnrYOoyMhGgBYEjiemeHFQxZSpKZdolFEFXbUa2/yWQafrQIDAQABo4Gj -MIGgMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU2S4/xnaeitmFkzoxLnZeo33n -H4owHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gjIBBPM5iQn9QwEgYDVR0TAQH/BAgw -BgEB/wIBADA6BgNVHR8EMzAxMC+gLaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNv -bS9jcmxzL3NlY3VyZWNhLmNybDANBgkqhkiG9w0BAQUFAAOBgQBMSoZHIrD1rq8v -UG3UYbN76xiF9FDRzWTs5Mvv4Psvf2kk426slzNO0ukFAsmwqN1mA/P9Nc4FlMMC -YtcnLNwC/syEYdQBOJjxfTVGTqh5q6jDs7S3rPJv8mrFk8ldC8PxU1ZJVfSlFCDn -6diMDgvOAJfUeJlIRLGu2k/ksI0Y1w== ------END CERTIFICATE----- - GeoTrustGlobal -----BEGIN CERTIFICATE----- MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT @@ -230,83 +106,6 @@ HoiVA8lJOq9nCEmw1Qj1ID2AkaDFh6P7yaMXkfmoL67pD9+Wcg91F4BdeAFNnx9t e9j1QjgjGpmT9IO+OzV05zcTNXqstLaQgmwnpODsnjW9v+UpoUefWzL86Zl9Kzk= -----END CERTIFICATE----- -Intel ------BEGIN CERTIFICATE----- -MIIFijCCBHKgAwIBAgIKYSCKYgAAAAAACDANBgkqhkiG9w0BAQUFADBSMQswCQYD -VQQGEwJVUzEaMBgGA1UEChMRSW50ZWwgQ29ycG9yYXRpb24xJzAlBgNVBAMTHklu -dGVsIEV4dGVybmFsIEJhc2ljIFBvbGljeSBDQTAeFw0wOTA1MTUxOTI3MjZaFw0x -NTA1MTUxOTM3MjZaMFYxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFJbnRlbCBDb3Jw -b3JhdGlvbjErMCkGA1UEAxMiSW50ZWwgRXh0ZXJuYWwgQmFzaWMgSXNzdWluZyBD -QSAzQjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKQEM1Wn9TU9vc9C -+/Tc7KB+eiYElmrcEWE32WUdHvWG+IcQHVQsikTmMyKKojNLw2B5s6Iekc8ivDo/ -wCfjZzX9JyftMnc+AArc0la87Olybzm8K9jXEfTBvTnUSFSiI9ZYefITdiUgqlAF -uljFZEHYKYtLuhrRacpmQfP4mV63NKdc2bT804HRf6YptZFa4k6YN94zlrGNrBuQ -Q74WFzz/jLBusbUpEkro6Mu/ZYFOFWQrV9lBhF9Ruk8yN+3N6n9fUo/qBigiF2kE -n9xVh1ykl7SCGL2jBUkXx4qgV27a6Si8lRRdgrHGtN/HWnSWlLXTH5l575H4Lq++ -77OFv38CAwEAAaOCAlwwggJYMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFA7G -KvdZsggQkCVvw939imYxMCvFMAsGA1UdDwQEAwIBhjASBgkrBgEEAYI3FQEEBQID -AQABMCMGCSsGAQQBgjcVAgQWBBQ5oFY2ekKQ/5Ktim+VdMeSWb4QWTAZBgkrBgEE -AYI3FAIEDB4KAFMAdQBiAEMAQTAfBgNVHSMEGDAWgBQaxgxKxEdvqNutK/D0Vgaj -7TdUDDCBvQYDVR0fBIG1MIGyMIGvoIGsoIGphk5odHRwOi8vd3d3LmludGVsLmNv -bS9yZXBvc2l0b3J5L0NSTC9JbnRlbCUyMEV4dGVybmFsJTIwQmFzaWMlMjBQb2xp -Y3klMjBDQS5jcmyGV2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuaW50ZWwuY29tL3JlcG9z -aXRvcnkvQ1JML0ludGVsJTIwRXh0ZXJuYWwlMjBCYXNpYyUyMFBvbGljeSUyMENB -LmNybDCB4wYIKwYBBQUHAQEEgdYwgdMwYwYIKwYBBQUHMAKGV2h0dHA6Ly93d3cu -aW50ZWwuY29tL3JlcG9zaXRvcnkvY2VydGlmaWNhdGVzL0ludGVsJTIwRXh0ZXJu -YWwlMjBCYXNpYyUyMFBvbGljeSUyMENBLmNydDBsBggrBgEFBQcwAoZgaHR0cDov -L2NlcnRpZmljYXRlcy5pbnRlbC5jb20vcmVwb3NpdG9yeS9jZXJ0aWZpY2F0ZXMv -SW50ZWwlMjBFeHRlcm5hbCUyMEJhc2ljJTIwUG9saWN5JTIwQ0EuY3J0MA0GCSqG -SIb3DQEBBQUAA4IBAQCxtQEHchVQhXyjEqtMVUMe6gkmPsIczHxSeqNbo9dsD+6x -bT65JT+oYgpIAtfEsYXeUJu1cChqpb22U5bMAz7eaQcW5bzefufWvA6lg2048B8o -czBj/q+5P5NpYrUO8jOmN4jTjfJq3ElZ7yFWpy7rB3Vm/aN6ATYqWfMbS/xfh+JC -xmH3droUmMJI0/aZJHsLtjbjFnNsHDNrJZX1vxlM78Lb1hjskTENPmhbVbfTj5i/ -ZGnhv4tmI8QZPCNtcegXJrfhRl2D9bWpdTOPrWiLDUqzy1Z6KL7TcOS/PCl8RHCJ -XkPau/thTQCpIoDa2+c+3XA++gRTfAQ4svTO260N ------END CERTIFICATE----- - -TCTrustCenter ------BEGIN CERTIFICATE----- -MIIDWzCCAsSgAwIBAgIDCaxIMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT -MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0 -aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDgwODE1MTY0NTE1WhcNMTMwMjE0MTc0NTE1 -WjBtMQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21iSDEe -MBwGA1UECxMVVEMgVHJ1c3RDZW50ZXIgU1NMIENBMSAwHgYDVQQDExdUQyBUcnVz -dENlbnRlciBTU0wgQ0EgSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AOkCoJoNbJw33wSxNWbDdmIfDIedR8Zmr/mjOhMkXdxRYb6qrl/WfMEuo4PBcysJ -kF81LaDMkBH0zc7Hs1eYixrMVObkCmEUjxYylgOk4ExGwhmIWDJUWGslNBUIIhFf -+ucDWuGZNfILQrwCWRHYBG0n/6lZPylCqopCMYhBK5sTI/PyuHEAzDL7+buep/Na -zn+oy/a6x1nobsuL9X2oFaWZb7Z6ty5kZ/U56JHa7vnsLrg4ePwiQb8jtyUdz0fD -uMHkNzK0gWxr4hm0v92otYFuOTZqNLEJneeiILxUCCMop2chr1obpq2zGVNxJ/rP -StWmcu75KBGMpT+mzFgIyf0CAwEAAaOBozCBoDAOBgNVHQ8BAf8EBAMCAQYwHQYD -VR0OBBYEFOe/bKlImXeG4tD/MKCQHQtk0IU6MB8GA1UdIwQYMBaAFEjmaPkr0rKV -10fYIyAQTzOYkJ/UMBIGA1UdEwEB/wQIMAYBAf8CAQAwOgYDVR0fBDMwMTAvoC2g -K4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9zZWN1cmVjYS5jcmwwDQYJ -KoZIhvcNAQEFBQADgYEAVKyJLbJha83PggEit8+dzh50wIsKXpTV2K6K4HnUI1kh -xqocLVfQORluC+LS7L78D2EKTWLZ8WNujiP6DbbIPSTsMasuiBMQMBUlJMUqsp/M -XmQJgIGAbxsr19MY6mmB30oWuo4cjHnkMzSCfhcON6Rxvbjijk2qCWXkk2T2HAk= ------END CERTIFICATE----- - -Vodafone ------BEGIN CERTIFICATE----- -MIIDJDCCAo2gAwIBAgIDBfw3MA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT -MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0 -aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYwNzIxMTUwNTA2WhcNMTEwNzEyMTUwNTA2 -WjA5MQswCQYDVQQGEwJVSzEXMBUGA1UEChMOVm9kYWZvbmUgR3JvdXAxETAPBgNV -BAMTCFZvZGFmb25lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs61K -wbMcB+GGGbjyo1dYEiVNGRYKRsDXfeOgeq03Vebf7D5Xq6a0Qs4Rvp6CuRTSNDPi -M+0vuQRW5sib9UD8UB2x4znc6FriRV4FUpAyKNVqQ9NB0MOBpQekVlX9DzcXkn+p -zWRi6tt3CtPsaDyHo06oAwX5qu3tW3pjtf0vnQqJWwwA6Mp4YJ/acHD/vVtt67hz -a0Upz0O2DEJetb3OaqI5yaNZ91y6i7sK0KTvBQxZHeJs+y5UjluHv3ptMUZvmsf0 -SiKysXnkg5mtsZSFlfM+U7dADq1zNb764NV5sSlmbDLEkvohQyg1p9gh2HX9Jk4A -e9nnF4hjw2U33HLBXwIDAQABo4GgMIGdMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E -FgQUR+YiAaq+68BPLD6l0UcvzlkcgvswHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj -IBBPM5iQn9QwDwYDVR0TAQH/BAUwAwEB/zA6BgNVHR8EMzAxMC+gLaArhilodHRw -Oi8vY3JsLmdlb3RydXN0LmNvbS9jcmxzL3NlY3VyZWNhLmNybDANBgkqhkiG9w0B -AQUFAAOBgQCs37zuSY/KkPigCvJevu+ewWy9GP2bFZi5EaxKuHGF+tYFZUNkyc06 -ACYMM3ADPM6dVUYeXIDZnPfV8BJFCpdoAHkSNlg341AVjabCOWtzOYolBn0ua8Wi -BM471XfzzXD7yMliek9J4fUn2vQU7MYgEkSAA53ZkMScGDkA/c1wMQ== ------END CERTIFICATE----- - RapidSSL -----BEGIN CERTIFICATE----- MIID1TCCAr2gAwIBAgIDAjbRMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT @@ -1346,3 +1145,111 @@ TvwjIDhO+wtc3qXjtO1zej3+GBmGz7RcZckturc2pZe3NRWQ7wO8ZzWShWU/ii3z 2PftKlqZo3WAeJoUCPtQNsLnBFGvdUx2rUZwMhdgPuGeV4kEULAtu8M74xR5/Opz nRGP22zr1K4q -----END CERTIFICATE----- + +Libertylavabitcom +-----BEGIN CERTIFICATE----- +MIIGWjCCBUKgAwIBAgIHAMn6RGIIgjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE +BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY +BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlm +aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5 +IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTERMA8GA1UEBRMIMDc5Njky +ODcwHhcNMTMxMDExMDgzNjAyWhcNMTQxMDExMDgzNjAyWjBBMSEwHwYDVQQLExhE +b21haW4gQ29udHJvbCBWYWxpZGF0ZWQxHDAaBgNVBAMTE2xpYmVydHkubGF2YWJp +dC5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCo/gQ2t5YtS2dj +BhIo2ke667uC2qhnUbnroyuqyf+GZafWZC/cmPYpkAWclu14ETBsR3u+6QtDHhOe +q3OBN0+IVLu5QwYSB2sqYUwyOHZ342uHQktWpPvNiwNHyfl1LsHL4WLuvQw3stK4 +DR+l6H/Ex11bl4KVvfk8uy+kXawcIQv7gr69OwEFEmGqeLSqr+fZdegLKPY20Ujx +WHSe8ErtW0eMY2A/DvrDrnfw+rVX5sxJIKk77AutIoyt+Ce2TwMVQtfbeQVWy91g +ST+sqC69wI5BOSguV5zECqIP1zxo939VVVciNGA3+3gyLJa+NDDpbT8xCwXClXN4 +3iektxfP7OgPjPwhDueZNhq54mA5mBY+qdkLyCmvURiczSNeoDTWouqaJq1lKjuh +CgkAhgoaLueAQv+uGNlVFtbQHApEvYcdz8XTqoL24wf3kadu6vxhrYVS+hguVVEE +YOc7LJsiQ3ERDjh1naFlL9h5khn6qhjw77oS6PWaCIJT8GfD8bjqCozdOdS1e+Sh +Bbp2Yg48m/XyQ3ocpEUmTt7n3fRv41XOY4tmBhloqkdPIDccl5deUhI//1VgycJv +uDqsMgRhyZvdS1kxhDAwbi1GtomURGdB/9kptYshUrR6xk1EP60pjWNxuvB7HMPg +seGNxPa15U/4z+5h8iSFdKa2TLkk7wIDAQABo4IByzCCAccwDwYDVR0TAQH/BAUw +AwEBADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDgYDVR0PAQH/BAQD +AgWgMDQGA1UdHwQtMCswKaAnoCWGI2h0dHA6Ly9jcmwuZ29kYWRkeS5jb20vZ2Rz +MS0xMDAuY3JsMFMGA1UdIARMMEowSAYLYIZIAYb9bQEHFwEwOTA3BggrBgEFBQcC +ARYraHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5LzCB +gAYIKwYBBQUHAQEEdDByMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5nb2RhZGR5 +LmNvbS8wSgYIKwYBBQUHMAKGPmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j +b20vcmVwb3NpdG9yeS9nZF9pbnRlcm1lZGlhdGUuY3J0MB8GA1UdIwQYMBaAFP2s +YTKTbEXW4u6FX5q653aZaMznMDcGA1UdEQQwMC6CE2xpYmVydHkubGF2YWJpdC5j +b22CF3d3dy5saWJlcnR5LmxhdmFiaXQuY29tMB0GA1UdDgQWBBSVRSbXCJKN6lms +ZtlccHBz/xVLwDANBgkqhkiG9w0BAQUFAAOCAQEAKja1YxyoTuHD1RV4L7wULpiy +ot4Z3OEuoOZTPJsoHfUCtOtKlUu2ZSwp5+IpaLnC3iCIxy1Yb6qu6Li5dqgtOkxl +4JqrOooQ9IUzuTLhSzPf6rEtw9gnYN/dpQ2q0YLh+K5SgRUm9y0PHBV4acfSh2TJ +vyaXDmuonX5zG7u3nz/oCo/qziW46Phz/leMhCAgLnZUYcAv6KPET+RMRmt4n8gg +C0xlOcCQbMh9VIPZ0WSnmdFn5DUCW+oVlwhxDB/3CvWIa0k/WI6NNW8vg+VdSyW7 +p/dp4mikGH37Tc5VAhcYMbAem69nSg7Qfrs35tak/JPJlx1LWayERGHLvTy7Ag== +-----END CERTIFICATE----- + +GlobalSignRootCA +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw +MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT +aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ +jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp +xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp +1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG +snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ +U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 +9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B +AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz +yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE +38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP +AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad +DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME +HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- + +GlobalSignRootCA_R2 +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 +MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL +v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 +eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq +tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd +C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa +zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB +mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH +V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n +bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG +3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs +J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO +291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS +ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd +AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- + +GlobalSignRootCA_R3 +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 +MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 +RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT +gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm +KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd +QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ +XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o +LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU +RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp +jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK +6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX +mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs +Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH +WD9f +-----END CERTIFICATE----- diff --git a/chromium/net/http/transport_security_state_static.h b/chromium/net/http/transport_security_state_static.h index a924550cbec..6a28ca4562b 100644 --- a/chromium/net/http/transport_security_state_static.h +++ b/chromium/net/http/transport_security_state_static.h @@ -22,18 +22,6 @@ static const char kSPKIHash_VeriSignClass3_G3[] = "\x22\xf1\x9e\x2e\xc6\xea\xcc\xfc\x5d\x23" "\x46\xf4\xc2\xe8\xf6\xc5\x54\xdd\x5e\x07"; -static const char kSPKIHash_Google1024[] = - "\x40\xc5\x40\x1d\x6f\x8c\xba\xf0\x8b\x00" - "\xed\xef\xb1\xee\x87\xd0\x05\xb3\xb9\xcd"; - -static const char kSPKIHash_Google2048[] = - "\x01\xb9\x21\xc5\x8d\x0b\xdf\x8d\xe0\x29" - "\xff\x9c\x92\x2e\xcd\x55\x6a\x7e\xa3\x39"; - -static const char kSPKIHash_GoogleBackup1024[] = - "\x7d\x5b\xa3\xca\x8e\x37\x65\x1d\x7c\x71" - "\xc3\xe3\xb7\x74\xcd\xe9\x7b\x1b\x59\x43"; - static const char kSPKIHash_GoogleBackup2048[] = "\xbe\xae\xce\xca\x34\xa7\xa8\xe7\x28\xf6" "\x7c\x8c\x08\x31\x9d\xcb\xbe\xde\x8a\x33"; @@ -42,22 +30,6 @@ static const char kSPKIHash_GoogleG2[] = "\x43\xda\xd6\x30\xee\x53\xf8\xa9\x80\xca" "\x6e\xfd\x85\xf4\x6a\xa3\x79\x90\xe0\xea"; -static const char kSPKIHash_ThawteSGCCA[] = - "\x87\x31\xea\x0e\x3d\xf5\xe8\x70\x3e\x83" - "\x72\x57\x77\xa9\x65\x3b\x3b\xfa\x5e\x14"; - -static const char kSPKIHash_VeriSignClass3SSPIntermediateCA[] = - "\x99\x6a\x20\x6a\x85\x57\x62\xcb\x9a\xf2" - "\x02\x37\xb3\xc0\x69\x5d\xa9\x1e\xc2\x22"; - -static const char kSPKIHash_EquifaxSecureCA[] = - "\x48\xe6\x68\xf9\x2b\xd2\xb2\x95\xd7\x47" - "\xd8\x23\x20\x10\x4f\x33\x98\x90\x9f\xd4"; - -static const char kSPKIHash_Aetna[] = - "\x92\x52\xaa\x14\xde\xbf\x80\xae\x30\xaa" - "\xd9\x4e\x60\x38\x70\x24\xa5\x43\x2f\x1a"; - static const char kSPKIHash_GeoTrustGlobal[] = "\xc0\x7a\x98\x68\x8d\x89\xfb\xab\x05\x64" "\x0c\x11\x7d\xaa\x7d\x65\xb8\xca\xcc\x4e"; @@ -66,18 +38,6 @@ static const char kSPKIHash_GeoTrustPrimary[] = "\xb0\x19\x89\xe7\xef\xfb\x4a\xaf\xcb\x14" "\x8f\x58\x46\x39\x76\x22\x41\x50\xe1\xba"; -static const char kSPKIHash_Intel[] = - "\x0e\xc6\x2a\xf7\x59\xb2\x08\x10\x90\x25" - "\x6f\xc3\xdd\xfd\x8a\x66\x31\x30\x2b\xc5"; - -static const char kSPKIHash_TCTrustCenter[] = - "\x83\x3b\x84\x10\x00\x7f\x6e\x4a\x9d\x41" - "\x2d\xc4\x22\x39\x36\x6f\x2e\xe5\x5b\xe9"; - -static const char kSPKIHash_Vodafone[] = - "\x0d\x7f\xe1\x5c\x55\x14\x36\x68\x99\xfc" - "\x40\xd6\x22\x08\xef\x22\xeb\xd1\x15\x1c"; - static const char kSPKIHash_RapidSSL[] = "\xa3\x93\x99\xc4\x04\xc3\xb2\x09\xb0\x81" "\xc2\x1f\x21\x62\x27\x78\xc2\x74\x8e\x4c"; @@ -250,6 +210,22 @@ static const char kSPKIHash_CryptoCat1[] = "\x4c\x87\xce\x85\x2c\xf4\xc0\x4d\x67\xa9" "\xe0\xec\x51\x0c\x7f\x3b\x14\xb3\xe9\xc9"; +static const char kSPKIHash_Libertylavabitcom[] = + "\x41\xbb\x3b\x8b\xc7\xcf\x3d\x13\x3f\x17" + "\xb3\x25\x7e\xe4\x03\xca\x8a\x5c\x6d\x36"; + +static const char kSPKIHash_GlobalSignRootCA[] = + "\x87\xdb\xd4\x5f\xb0\x92\x8d\x4e\x1d\xf8" + "\x15\x67\xe7\xf2\xab\xaf\xd6\x2b\x67\x75"; + +static const char kSPKIHash_GlobalSignRootCA_R2[] = + "\xa5\x06\x8a\x78\xcf\x84\xbd\x74\x32\xdd" + "\x58\xf9\x65\xeb\x3a\x55\xe7\xc7\x80\xdc"; + +static const char kSPKIHash_GlobalSignRootCA_R3[] = + "\xf7\x93\x19\xef\xdf\xc1\xf5\x20\xfb\xac" + "\x85\x55\x2c\xf2\xd2\x8f\x5a\xb9\xca\x0b"; + // The following is static data describing the hosts that are hardcoded with // certificate pins or HSTS information. @@ -268,29 +244,13 @@ static const char* const kTestAcceptableCerts[] = { } static const char* const kGoogleAcceptableCerts[] = { - kSPKIHash_VeriSignClass3, - kSPKIHash_VeriSignClass3_G3, - kSPKIHash_Google1024, - kSPKIHash_Google2048, - kSPKIHash_GoogleBackup1024, kSPKIHash_GoogleBackup2048, kSPKIHash_GoogleG2, - kSPKIHash_EquifaxSecureCA, - kSPKIHash_GeoTrustGlobal, - NULL, -}; -static const char* const kGoogleRejectedCerts[] = { - kSPKIHash_Aetna, - kSPKIHash_Intel, - kSPKIHash_TCTrustCenter, - kSPKIHash_Vodafone, - kSPKIHash_ThawteSGCCA, - kSPKIHash_VeriSignClass3SSPIntermediateCA, NULL, }; #define kGooglePins { \ kGoogleAcceptableCerts, \ - kGoogleRejectedCerts, \ + kNoRejectedPublicKeys, \ } static const char* const kTorAcceptableCerts[] = { @@ -377,6 +337,9 @@ static const char* const kTwitterCDNAcceptableCerts[] = { kSPKIHash_UTNUSERFirstObject, kSPKIHash_GTECyberTrustGlobalRoot, kSPKIHash_BaltimoreCyberTrustRoot, + kSPKIHash_GlobalSignRootCA, + kSPKIHash_GlobalSignRootCA_R2, + kSPKIHash_GlobalSignRootCA_R3, NULL, }; #define kTwitterCDNPins { \ @@ -404,6 +367,15 @@ static const char* const kCryptoCatAcceptableCerts[] = { kNoRejectedPublicKeys, \ } +static const char* const kLavabitAcceptableCerts[] = { + kSPKIHash_Libertylavabitcom, + NULL, +}; +#define kLavabitPins { \ + kLavabitAcceptableCerts, \ + kNoRejectedPublicKeys, \ +} + #define kNoPins {\ NULL, NULL, \ } @@ -430,6 +402,10 @@ static const struct HSTSPreload kPreloadedSTS[] = { {19, true, "\006script\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM }, {20, true, "\007history\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM }, {21, true, "\010security\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM }, + {17, true, "\004goto\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM }, + {18, true, "\005cloud\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM }, + {18, true, "\005glass\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM }, + {17, false, "\004play\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM }, {20, true, "\006market\007android\003com", true, kGooglePins, DOMAIN_ANDROID_COM }, {26, true, "\003ssl\020google-analytics\003com", true, kGooglePins, DOMAIN_GOOGLE_ANALYTICS_COM }, {18, true, "\005drive\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM }, @@ -453,13 +429,14 @@ static const struct HSTSPreload kPreloadedSTS[] = { {13, true, "\007appspot\003com", false, kGooglePins, DOMAIN_APPSPOT_COM }, {23, true, "\021googlesyndication\003com", false, kGooglePins, DOMAIN_GOOGLESYNDICATION_COM }, {17, true, "\013doubleclick\003net", false, kGooglePins, DOMAIN_DOUBLECLICK_NET }, - {17, true, "\003ssl\007gstatic\003com", false, kGooglePins, DOMAIN_GSTATIC_COM }, + {13, true, "\007gstatic\003com", false, kGooglePins, DOMAIN_GSTATIC_COM }, {10, true, "\005youtu\002be", false, kGooglePins, DOMAIN_YOUTU_BE }, {13, true, "\007android\003com", false, kGooglePins, DOMAIN_ANDROID_COM }, {20, true, "\016googlecommerce\003com", false, kGooglePins, DOMAIN_GOOGLECOMMERCE_COM }, {12, true, "\006urchin\003com", false, kGooglePins, DOMAIN_URCHIN_COM }, {8, true, "\003goo\002gl", false, kGooglePins, DOMAIN_GOO_GL }, {6, true, "\001g\002co", false, kGooglePins, DOMAIN_G_CO }, + {22, true, "\020googletagmanager\003com", false, kGooglePins, DOMAIN_GOOGLETAGMANAGER_COM }, {11, true, "\006google\002ac", false, kGooglePins, DOMAIN_GOOGLE_AC }, {11, true, "\006google\002ad", false, kGooglePins, DOMAIN_GOOGLE_AD }, {11, true, "\006google\002ae", false, kGooglePins, DOMAIN_GOOGLE_AE }, @@ -753,8 +730,7 @@ static const struct HSTSPreload kPreloadedSTS[] = { {17, true, "\003dev\007twitter\003com", false, kTwitterComPins, DOMAIN_TWITTER_COM }, {22, true, "\010business\007twitter\003com", false, kTwitterComPins, DOMAIN_TWITTER_COM }, {22, true, "\010platform\007twitter\003com", false, kTwitterCDNPins, DOMAIN_TWITTER_COM }, - {15, true, "\003si0\005twimg\003com", false, kTwitterCDNPins, DOMAIN_TWIMG_COM }, - {23, true, "\010twimg0-a\010akamaihd\003net", false, kTwitterCDNPins, DOMAIN_AKAMAIHD_NET }, + {11, true, "\005twimg\003com", false, kTwitterCDNPins, DOMAIN_TWIMG_COM }, {22, true, "\020braintreegateway\003com", true, kNoPins, DOMAIN_NOT_PINNED }, {23, false, "\021braintreepayments\003com", true, kNoPins, DOMAIN_NOT_PINNED }, {27, false, "\003www\021braintreepayments\003com", true, kNoPins, DOMAIN_NOT_PINNED }, @@ -794,8 +770,12 @@ static const struct HSTSPreload kPreloadedSTS[] = { {17, false, "\003www\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED }, {15, false, "\011mylookout\003com", true, kNoPins, DOMAIN_NOT_PINNED }, {19, false, "\003www\011mylookout\003com", true, kNoPins, DOMAIN_NOT_PINNED }, - {16, false, "\002dm\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED }, - {18, false, "\002dm\011mylookout\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {16, true, "\002dm\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {22, true, "\010business\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {18, true, "\004blog\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {17, true, "\003faq\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {22, true, "\010platform\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {19, true, "\005email\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED }, {15, true, "\011itriskltd\003com", true, kNoPins, DOMAIN_NOT_PINNED }, {15, true, "\012stocktrade\002de", true, kNoPins, DOMAIN_NOT_PINNED }, {22, true, "\011openshift\006redhat\003com", true, kNoPins, DOMAIN_NOT_PINNED }, @@ -855,8 +835,6 @@ static const struct HSTSPreload kPreloadedSTS[] = { {21, true, "\003www\013cyveillance\003com", true, kNoPins, DOMAIN_NOT_PINNED }, {22, true, "\004blog\013cyveillance\003com", true, kNoPins, DOMAIN_NOT_PINNED }, {12, true, "\006whonix\003org", true, kNoPins, DOMAIN_NOT_PINNED }, - {13, true, "\010blueseed\002co", true, kNoPins, DOMAIN_NOT_PINNED }, - {26, true, "\005forum\016quantifiedself\003com", true, kNoPins, DOMAIN_NOT_PINNED }, {11, true, "\006shodan\002io", true, kNoPins, DOMAIN_NOT_PINNED }, {18, true, "\015rapidresearch\002me", true, kNoPins, DOMAIN_NOT_PINNED }, {14, true, "\010surkatty\003org", true, kNoPins, DOMAIN_NOT_PINNED }, @@ -873,6 +851,39 @@ static const struct HSTSPreload kPreloadedSTS[] = { {22, true, "\020appseccalifornia\003org", true, kNoPins, DOMAIN_NOT_PINNED }, {17, true, "\013crowdcurity\003com", true, kNoPins, DOMAIN_NOT_PINNED }, {19, true, "\013saturngames\002co\002uk", true, kNoPins, DOMAIN_NOT_PINNED }, + {23, true, "\021strongest-privacy\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {25, true, "\011ecosystem\011atlassian\003net", true, kNoPins, DOMAIN_NOT_PINNED }, + {18, true, "\002id\011atlassian\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {15, false, "\011bitbucket\003org", true, kNoPins, DOMAIN_NOT_PINNED }, + {12, true, "\007cupcake\002io", true, kNoPins, DOMAIN_NOT_PINNED }, + {12, true, "\007cupcake\002is", true, kNoPins, DOMAIN_NOT_PINNED }, + {9, true, "\004tent\002io", true, kNoPins, DOMAIN_NOT_PINNED }, + {12, true, "\006cybozu\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {17, true, "\013davidlyness\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {12, true, "\006medium\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {21, true, "\007liberty\007lavabit\003com", true, kLavabitPins, DOMAIN_LAVABIT_COM }, + {16, true, "\012getlantern\003org", true, kNoPins, DOMAIN_NOT_PINNED }, + {15, false, "\011kinsights\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {15, false, "\007simbolo\002co\002uk", true, kNoPins, DOMAIN_NOT_PINNED }, + {19, false, "\003www\007simbolo\002co\002uk", true, kNoPins, DOMAIN_NOT_PINNED }, + {16, false, "\012zenpayroll\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {20, false, "\003www\012zenpayroll\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {20, false, "\003get\012zenpayroll\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {23, false, "\006errors\012zenpayroll\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {23, false, "\006manage\012zenpayroll\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {19, true, "\016gernert-server\002de", true, kNoPins, DOMAIN_NOT_PINNED }, + {19, true, "\010skydrive\004live\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {21, true, "\011lifeguard\005aecom\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {17, false, "\004data\003qld\003gov\002au", true, kNoPins, DOMAIN_NOT_PINNED }, + {25, false, "\014publications\003qld\003gov\002au", true, kNoPins, DOMAIN_NOT_PINNED }, + {13, true, "\002go\004xero\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {16, true, "\005login\004xero\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {13, true, "\002my\004xero\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {18, true, "\007payroll\004xero\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {13, true, "\002in\004xero\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {14, true, "\003api\004xero\003com", true, kNoPins, DOMAIN_NOT_PINNED }, + {9, true, "\003eff\003org", true, kNoPins, DOMAIN_NOT_PINNED }, + {9, true, "\004mail\002de", true, kNoPins, DOMAIN_NOT_PINNED }, }; static const size_t kNumPreloadedSTS = ARRAYSIZE_UNSAFE(kPreloadedSTS); diff --git a/chromium/net/http/transport_security_state_static.json b/chromium/net/http/transport_security_state_static.json index 67e5a86ccd8..500e1782110 100644 --- a/chromium/net/http/transport_security_state_static.json +++ b/chromium/net/http/transport_security_state_static.json @@ -42,23 +42,8 @@ { "name": "google", "static_spki_hashes": [ - "VeriSignClass3", - "VeriSignClass3_G3", - "Google1024", - "Google2048", - "GoogleBackup1024", "GoogleBackup2048", - "GoogleG2", - "EquifaxSecureCA", - "GeoTrustGlobal" - ], - "bad_static_spki_hashes": [ - "Aetna", - "Intel", - "TCTrustCenter", - "Vodafone", - "ThawteSGCCA", - "VeriSignClass3SSPIntermediateCA" + "GoogleG2" ] }, { @@ -141,7 +126,10 @@ "UTNUSERFirstHardware", "UTNUSERFirstObject", "GTECyberTrustGlobalRoot", - "BaltimoreCyberTrustRoot" + "BaltimoreCyberTrustRoot", + "GlobalSignRootCA", + "GlobalSignRootCA_R2", + "GlobalSignRootCA_R3" ] }, { @@ -157,6 +145,12 @@ "DigiCertEVRoot", "CryptoCat1" ] + }, + { + "name": "lavabit", + "static_spki_hashes": [ + "Libertylavabitcom" + ] } ], @@ -187,6 +181,11 @@ { "name": "script.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" }, { "name": "history.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" }, { "name": "security.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" }, + { "name": "goto.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" }, + { "name": "cloud.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" }, + { "name": "glass.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" }, + // play.google.com doesn't have include_subdomains because of crbug.com/327834. + { "name": "play.google.com", "mode": "force-https", "pins": "google" }, // Other Google-related domains that must use HTTPS. { "name": "market.android.com", "include_subdomains": true, "mode": "force-https", "pins": "google" }, @@ -219,13 +218,14 @@ { "name": "appspot.com", "include_subdomains": true, "pins": "google" }, { "name": "googlesyndication.com", "include_subdomains": true, "pins": "google" }, { "name": "doubleclick.net", "include_subdomains": true, "pins": "google" }, - { "name": "ssl.gstatic.com", "include_subdomains": true, "pins": "google" }, + { "name": "gstatic.com", "include_subdomains": true, "pins": "google" }, { "name": "youtu.be", "include_subdomains": true, "pins": "google" }, { "name": "android.com", "include_subdomains": true, "pins": "google" }, { "name": "googlecommerce.com", "include_subdomains": true, "pins": "google" }, { "name": "urchin.com", "include_subdomains": true, "pins": "google" }, { "name": "goo.gl", "include_subdomains": true, "pins": "google" }, { "name": "g.co", "include_subdomains": true, "pins": "google" }, + { "name": "googletagmanager.com", "include_subdomains": true, "pins": "google" }, { "name": "google.ac", "include_subdomains": true, "pins": "google" }, { "name": "google.ad", "include_subdomains": true, "pins": "google" }, { "name": "google.ae", "include_subdomains": true, "pins": "google" }, @@ -523,8 +523,7 @@ { "name": "dev.twitter.com", "include_subdomains": true, "pins": "twitterCom" }, { "name": "business.twitter.com", "include_subdomains": true, "pins": "twitterCom" }, { "name": "platform.twitter.com", "include_subdomains": true, "pins": "twitterCDN" }, - { "name": "si0.twimg.com", "include_subdomains": true, "pins": "twitterCDN" }, - { "name": "twimg0-a.akamaihd.net", "include_subdomains": true, "pins": "twitterCDN" }, + { "name": "twimg.com", "include_subdomains": true, "pins": "twitterCDN" }, { "name": "braintreegateway.com", "include_subdomains": true, "mode": "force-https" }, { "name": "braintreepayments.com", "mode": "force-https" }, { "name": "www.braintreepayments.com", "mode": "force-https" }, @@ -564,8 +563,12 @@ { "name": "www.lookout.com", "mode": "force-https" }, { "name": "mylookout.com", "mode": "force-https" }, { "name": "www.mylookout.com", "mode": "force-https" }, - { "name": "dm.lookout.com", "mode": "force-https" }, - { "name": "dm.mylookout.com", "mode": "force-https" }, + { "name": "dm.lookout.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "business.lookout.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "blog.lookout.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "faq.lookout.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "platform.lookout.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "email.lookout.com", "include_subdomains": true, "mode": "force-https" }, { "name": "itriskltd.com", "include_subdomains": true, "mode": "force-https" }, { "name": "stocktrade.de", "include_subdomains": true, "mode": "force-https" }, { "name": "openshift.redhat.com", "include_subdomains": true, "mode": "force-https" }, @@ -625,8 +628,6 @@ { "name": "www.cyveillance.com", "include_subdomains": true, "mode": "force-https" }, { "name": "blog.cyveillance.com", "include_subdomains": true, "mode": "force-https" }, { "name": "whonix.org", "include_subdomains": true, "mode": "force-https" }, - { "name": "blueseed.co", "include_subdomains": true, "mode": "force-https" }, - { "name": "forum.quantifiedself.com", "include_subdomains": true, "mode": "force-https" }, { "name": "shodan.io", "include_subdomains": true, "mode": "force-https" }, { "name": "rapidresearch.me", "include_subdomains": true, "mode": "force-https" }, { "name": "surkatty.org", "include_subdomains": true, "mode": "force-https" }, @@ -643,6 +644,39 @@ { "name": "appseccalifornia.org", "include_subdomains": true, "mode": "force-https" }, { "name": "crowdcurity.com", "include_subdomains": true, "mode": "force-https" }, { "name": "saturngames.co.uk", "include_subdomains": true, "mode": "force-https" }, + { "name": "strongest-privacy.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "ecosystem.atlassian.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "id.atlassian.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "bitbucket.org", "mode": "force-https" }, + { "name": "cupcake.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "cupcake.is", "include_subdomains": true, "mode": "force-https" }, + { "name": "tent.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "cybozu.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "davidlyness.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "medium.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "liberty.lavabit.com", "include_subdomains": true, "mode": "force-https", "pins": "lavabit" }, + { "name": "getlantern.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "kinsights.com", "mode": "force-https" }, + { "name": "simbolo.co.uk", "mode": "force-https" }, + { "name": "www.simbolo.co.uk", "mode": "force-https" }, + { "name": "zenpayroll.com", "mode": "force-https" }, + { "name": "www.zenpayroll.com", "mode": "force-https" }, + { "name": "get.zenpayroll.com", "mode": "force-https" }, + { "name": "errors.zenpayroll.com", "mode": "force-https" }, + { "name": "manage.zenpayroll.com", "mode": "force-https" }, + { "name": "gernert-server.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "skydrive.live.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "lifeguard.aecom.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "data.qld.gov.au", "mode": "force-https" }, + { "name": "publications.qld.gov.au", "mode": "force-https" }, + { "name": "go.xero.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "login.xero.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "my.xero.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "payroll.xero.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "in.xero.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "api.xero.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "eff.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "mail.de", "include_subdomains": true, "mode": "force-https" }, // Entries that are only valid if the client supports SNI. { "name": "gmail.com", "mode": "force-https", "pins": "google", "snionly": true }, diff --git a/chromium/net/http/transport_security_state_unittest.cc b/chromium/net/http/transport_security_state_unittest.cc index 936d5628249..c3d15da29f9 100644 --- a/chromium/net/http/transport_security_state_unittest.cc +++ b/chromium/net/http/transport_security_state_unittest.cc @@ -117,6 +117,19 @@ TEST_F(TransportSecurityStateTest, SubdomainMatches) { EXPECT_FALSE(state.GetDomainState("com", true, &domain_state)); } +TEST_F(TransportSecurityStateTest, InvalidDomains) { + TransportSecurityState state; + TransportSecurityState::DomainState domain_state; + const base::Time current_time(base::Time::Now()); + const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); + + EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state)); + bool include_subdomains = true; + state.AddHSTS("yahoo.com", expiry, include_subdomains); + EXPECT_TRUE(state.GetDomainState("www-.foo.yahoo.com", true, &domain_state)); + EXPECT_TRUE(state.GetDomainState("2\x01.foo.yahoo.com", true, &domain_state)); +} + TEST_F(TransportSecurityStateTest, DeleteAllDynamicDataSince) { TransportSecurityState state; TransportSecurityState::DomainState domain_state; @@ -506,7 +519,8 @@ TEST_F(TransportSecurityStateTest, BuiltinCertPins) { EXPECT_TRUE(HasPublicKeyPins("apis.google.com")); EXPECT_TRUE(HasPublicKeyPins("ssl.gstatic.com")); - EXPECT_FALSE(HasPublicKeyPins("www.gstatic.com")); + EXPECT_TRUE(HasPublicKeyPins("gstatic.com")); + EXPECT_TRUE(HasPublicKeyPins("www.gstatic.com")); EXPECT_TRUE(HasPublicKeyPins("ssl.google-analytics.com")); EXPECT_TRUE(HasPublicKeyPins("www.googleplex.com")); @@ -521,7 +535,6 @@ TEST_F(TransportSecurityStateTest, BuiltinCertPins) { EXPECT_TRUE(HasPublicKeyPins("business.twitter.com")); EXPECT_TRUE(HasPublicKeyPins("platform.twitter.com")); EXPECT_TRUE(HasPublicKeyPins("si0.twimg.com")); - EXPECT_TRUE(HasPublicKeyPins("twimg0-a.akamaihd.net")); } static bool AddHash(const std::string& type_and_base64, @@ -534,43 +547,6 @@ static bool AddHash(const std::string& type_and_base64, return true; } -TEST_F(TransportSecurityStateTest, PinValidationWithRejectedCerts) { - // kGoodPath is plus.google.com via Google Internet Authority. - static const char* kGoodPath[] = { - "sha1/4BjDjn8v2lWeUFQnqSs0BgbIcrU=", - "sha1/QMVAHW+MuvCLAO3vse6H0AWzuc0=", - "sha1/SOZo+SvSspXXR9gjIBBPM5iQn9Q=", - NULL, - }; - - // kBadPath is plus.google.com via Trustcenter, which contains a required - // certificate (Equifax root), but also an excluded certificate - // (Trustcenter). - static const char* kBadPath[] = { - "sha1/4BjDjn8v2lWeUFQnqSs0BgbIcrU=", - "sha1/gzuEEAB/bkqdQS3EIjk2by7lW+k=", - "sha1/SOZo+SvSspXXR9gjIBBPM5iQn9Q=", - NULL, - }; - - HashValueVector good_hashes, bad_hashes; - - for (size_t i = 0; kGoodPath[i]; i++) { - EXPECT_TRUE(AddHash(kGoodPath[i], &good_hashes)); - } - for (size_t i = 0; kBadPath[i]; i++) { - EXPECT_TRUE(AddHash(kBadPath[i], &bad_hashes)); - } - - TransportSecurityState state; - TransportSecurityState::DomainState domain_state; - EXPECT_TRUE(state.GetDomainState("plus.google.com", true, &domain_state)); - EXPECT_TRUE(domain_state.HasPublicKeyPins()); - - EXPECT_TRUE(domain_state.CheckPublicKeyPins(good_hashes)); - EXPECT_FALSE(domain_state.CheckPublicKeyPins(bad_hashes)); -} - TEST_F(TransportSecurityStateTest, PinValidationWithoutRejectedCerts) { // kGoodPath is blog.torproject.org. static const char* kGoodPath[] = { @@ -607,100 +583,6 @@ TEST_F(TransportSecurityStateTest, PinValidationWithoutRejectedCerts) { EXPECT_FALSE(domain_state.CheckPublicKeyPins(bad_hashes)); } -TEST_F(TransportSecurityStateTest, PinValidationWithRejectedCertsMixedHashes) { - static const char* ee_sha1 = "sha1/4BjDjn8v2lWeUFQnqSs0BgbIcrU="; - static const char* ee_sha256 = - "sha256/sRJBQqWhpaKIGcc1NA7/jJ4vgWj+47oYfyU7waOS1+I="; - static const char* google_1024_sha1 = "sha1/QMVAHW+MuvCLAO3vse6H0AWzuc0="; - static const char* google_1024_sha256 = - "sha256/trlUMquuV/4CDLK3T0+fkXPIxwivyecyrOIyeQR8bQU="; - static const char* equifax_sha1 = "sha1/SOZo+SvSspXXR9gjIBBPM5iQn9Q="; - static const char* equifax_sha256 = - "sha256//1aAzXOlcD2gSBegdf1GJQanNQbEuBoVg+9UlHjSZHY="; - static const char* trustcenter_sha1 = "sha1/gzuEEAB/bkqdQS3EIjk2by7lW+k="; - static const char* trustcenter_sha256 = - "sha256/Dq58KIA4NMLsboWMLU8/aTREzaAGEFW+EtUule8dd/M="; - - // Good chains for plus.google.com chain up through google_1024_sha{1,256} - // to equifax_sha{1,256}. Bad chains chain up to Equifax through - // trustcenter_sha{1,256}, which is a blacklisted key. Even though Equifax - // and Google1024 are known-good, the blacklistedness of Trustcenter - // should override and cause pin validation failure. - - TransportSecurityState state; - TransportSecurityState::DomainState domain_state; - EXPECT_TRUE(state.GetDomainState("plus.google.com", true, &domain_state)); - EXPECT_TRUE(domain_state.HasPublicKeyPins()); - - // The statically-defined pins are all SHA-1, so we add some SHA-256 pins - // manually: - EXPECT_TRUE(AddHash(google_1024_sha256, &domain_state.static_spki_hashes)); - EXPECT_TRUE(AddHash(trustcenter_sha256, - &domain_state.bad_static_spki_hashes)); - - // Try an all-good SHA1 chain. - HashValueVector validated_chain; - EXPECT_TRUE(AddHash(ee_sha1, &validated_chain)); - EXPECT_TRUE(AddHash(google_1024_sha1, &validated_chain)); - EXPECT_TRUE(AddHash(equifax_sha1, &validated_chain)); - EXPECT_TRUE(domain_state.CheckPublicKeyPins(validated_chain)); - - // Try an all-bad SHA1 chain. - validated_chain.clear(); - EXPECT_TRUE(AddHash(ee_sha1, &validated_chain)); - EXPECT_TRUE(AddHash(trustcenter_sha1, &validated_chain)); - EXPECT_TRUE(AddHash(equifax_sha1, &validated_chain)); - EXPECT_FALSE(domain_state.CheckPublicKeyPins(validated_chain)); - - // Try an all-good SHA-256 chain. - validated_chain.clear(); - EXPECT_TRUE(AddHash(ee_sha256, &validated_chain)); - EXPECT_TRUE(AddHash(google_1024_sha256, &validated_chain)); - EXPECT_TRUE(AddHash(equifax_sha256, &validated_chain)); - EXPECT_TRUE(domain_state.CheckPublicKeyPins(validated_chain)); - - // Try an all-bad SHA-256 chain. - validated_chain.clear(); - EXPECT_TRUE(AddHash(ee_sha256, &validated_chain)); - EXPECT_TRUE(AddHash(trustcenter_sha256, &validated_chain)); - EXPECT_TRUE(AddHash(equifax_sha256, &validated_chain)); - EXPECT_FALSE(domain_state.CheckPublicKeyPins(validated_chain)); - - // Try a mixed-hash good chain. - validated_chain.clear(); - EXPECT_TRUE(AddHash(ee_sha256, &validated_chain)); - EXPECT_TRUE(AddHash(google_1024_sha1, &validated_chain)); - EXPECT_TRUE(AddHash(equifax_sha256, &validated_chain)); - EXPECT_TRUE(domain_state.CheckPublicKeyPins(validated_chain)); - - // Try a mixed-hash bad chain. - validated_chain.clear(); - EXPECT_TRUE(AddHash(ee_sha1, &validated_chain)); - EXPECT_TRUE(AddHash(trustcenter_sha256, &validated_chain)); - EXPECT_TRUE(AddHash(equifax_sha1, &validated_chain)); - EXPECT_FALSE(domain_state.CheckPublicKeyPins(validated_chain)); - - // Try a chain with all good hashes. - validated_chain.clear(); - EXPECT_TRUE(AddHash(ee_sha1, &validated_chain)); - EXPECT_TRUE(AddHash(google_1024_sha1, &validated_chain)); - EXPECT_TRUE(AddHash(equifax_sha1, &validated_chain)); - EXPECT_TRUE(AddHash(ee_sha256, &validated_chain)); - EXPECT_TRUE(AddHash(google_1024_sha256, &validated_chain)); - EXPECT_TRUE(AddHash(equifax_sha256, &validated_chain)); - EXPECT_TRUE(domain_state.CheckPublicKeyPins(validated_chain)); - - // Try a chain with all bad hashes. - validated_chain.clear(); - EXPECT_TRUE(AddHash(ee_sha1, &validated_chain)); - EXPECT_TRUE(AddHash(trustcenter_sha1, &validated_chain)); - EXPECT_TRUE(AddHash(equifax_sha1, &validated_chain)); - EXPECT_TRUE(AddHash(ee_sha256, &validated_chain)); - EXPECT_TRUE(AddHash(trustcenter_sha256, &validated_chain)); - EXPECT_TRUE(AddHash(equifax_sha256, &validated_chain)); - EXPECT_FALSE(domain_state.CheckPublicKeyPins(validated_chain)); -} - TEST_F(TransportSecurityStateTest, OptionalHSTSCertPins) { TransportSecurityState state; TransportSecurityState::DomainState domain_state; @@ -744,38 +626,6 @@ TEST_F(TransportSecurityStateTest, OverrideBuiltins) { EXPECT_TRUE(state.GetDomainState("www.google.com", true, &domain_state)); } -static const uint8 kSidePinLeafSPKI[] = { - 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0xe4, - 0x1d, 0xcc, 0xf2, 0x92, 0xe7, 0x7a, 0xc6, 0x36, 0xf7, 0x1a, 0x62, 0x31, 0x7d, - 0x37, 0xea, 0x0d, 0xa2, 0xa8, 0x12, 0x2b, 0xc2, 0x1c, 0x82, 0x3e, 0xa5, 0x70, - 0x4a, 0x83, 0x5d, 0x9b, 0x84, 0x82, 0x70, 0xa4, 0x88, 0x98, 0x98, 0x41, 0x29, - 0x31, 0xcb, 0x6e, 0x2a, 0x54, 0x65, 0x14, 0x60, 0xcc, 0x00, 0xe8, 0x10, 0x30, - 0x0a, 0x4a, 0xd1, 0xa7, 0x52, 0xfe, 0x2d, 0x31, 0x2a, 0x1d, 0x0d, 0x02, 0x03, - 0x01, 0x00, 0x01, -}; - -static const uint8 kSidePinInfo[] = { - 0x01, 0x00, 0x53, 0x50, 0x49, 0x4e, 0xa0, 0x00, 0x03, 0x00, 0x53, 0x49, 0x47, - 0x00, 0x50, 0x55, 0x42, 0x4b, 0x41, 0x4c, 0x47, 0x4f, 0x47, 0x00, 0x41, 0x00, - 0x04, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xfb, 0x26, 0xd5, 0xe8, 0x76, 0x35, - 0x96, 0x6d, 0x91, 0x9b, 0x5b, 0x27, 0xe6, 0x09, 0x1c, 0x7b, 0x6c, 0xcd, 0xc8, - 0x10, 0x25, 0x95, 0xc0, 0xa5, 0xf6, 0x6c, 0x6f, 0xfb, 0x59, 0x1e, 0x2d, 0xf4, - 0x02, 0x20, 0x33, 0x0a, 0xf8, 0x8b, 0x3e, 0xc4, 0xca, 0x75, 0x28, 0xdf, 0x5f, - 0xab, 0xe4, 0x46, 0xa0, 0xdd, 0x2d, 0xe5, 0xad, 0xc3, 0x81, 0x44, 0x70, 0xb2, - 0x10, 0x87, 0xe8, 0xc3, 0xd6, 0x6e, 0x12, 0x5d, 0x04, 0x67, 0x0b, 0x7d, 0xf2, - 0x99, 0x75, 0x57, 0x99, 0x3a, 0x98, 0xf8, 0xe4, 0xdf, 0x79, 0xdf, 0x8e, 0x02, - 0x2c, 0xbe, 0xd8, 0xfd, 0x75, 0x80, 0x18, 0xb1, 0x6f, 0x43, 0xd9, 0x8a, 0x79, - 0xc3, 0x6e, 0x18, 0xdf, 0x79, 0xc0, 0x59, 0xab, 0xd6, 0x77, 0x37, 0x6a, 0x94, - 0x5a, 0x7e, 0xfb, 0xa9, 0xc5, 0x54, 0x14, 0x3a, 0x7b, 0x97, 0x17, 0x2a, 0xb6, - 0x1e, 0x59, 0x4f, 0x2f, 0xb1, 0x15, 0x1a, 0x34, 0x50, 0x32, 0x35, 0x36, -}; - -static const uint8 kSidePinExpectedHash[20] = { - 0xb5, 0x91, 0x66, 0x47, 0x43, 0x16, 0x62, 0x86, 0xd4, 0x1e, 0x5d, 0x36, 0xe1, - 0xc4, 0x09, 0x3d, 0x2d, 0x1d, 0xea, 0x1e, -}; - TEST_F(TransportSecurityStateTest, GooglePinnedProperties) { EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty( "www.example.com", true)); |