summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/browser/renderer_host/socket_stream_host.cc3
-rw-r--r--net/socket_stream/socket_stream_job.cc21
-rw-r--r--net/socket_stream/socket_stream_job.h5
-rw-r--r--net/url_request/url_request_context.cc9
-rw-r--r--net/url_request/url_request_context.h3
-rw-r--r--net/url_request/url_request_http_job.cc16
-rw-r--r--net/url_request/url_request_http_job.h2
-rw-r--r--net/websockets/websocket_job_unittest.cc26
-rw-r--r--webkit/tools/test_shell/simple_socket_stream_bridge.cc3
9 files changed, 68 insertions, 20 deletions
diff --git a/content/browser/renderer_host/socket_stream_host.cc b/content/browser/renderer_host/socket_stream_host.cc
index c2f1a79..67350fd 100644
--- a/content/browser/renderer_host/socket_stream_host.cc
+++ b/content/browser/renderer_host/socket_stream_host.cc
@@ -47,7 +47,8 @@ SocketStreamHost::~SocketStreamHost() {
void SocketStreamHost::Connect(const GURL& url,
net::URLRequestContext* request_context) {
VLOG(1) << "SocketStreamHost::Connect url=" << url;
- socket_ = net::SocketStreamJob::CreateSocketStreamJob(url, delegate_);
+ socket_ = net::SocketStreamJob::CreateSocketStreamJob(
+ url, delegate_, *request_context);
socket_->set_context(request_context);
socket_->SetUserData(kSocketIdKey, new SocketStreamId(socket_id_));
socket_->Connect();
diff --git a/net/socket_stream/socket_stream_job.cc b/net/socket_stream/socket_stream_job.cc
index b52945a..0349de8 100644
--- a/net/socket_stream/socket_stream_job.cc
+++ b/net/socket_stream/socket_stream_job.cc
@@ -5,7 +5,9 @@
#include "net/socket_stream/socket_stream_job.h"
#include "base/memory/singleton.h"
+#include "net/base/transport_security_state.h"
#include "net/socket_stream/socket_stream_job_manager.h"
+#include "net/url_request/url_request_context.h"
namespace net {
@@ -18,8 +20,23 @@ SocketStreamJob::ProtocolFactory* SocketStreamJob::RegisterProtocolFactory(
// static
SocketStreamJob* SocketStreamJob::CreateSocketStreamJob(
- const GURL& url, SocketStream::Delegate* delegate) {
- return SocketStreamJobManager::GetInstance()->CreateJob(url, delegate);
+ const GURL& url,
+ SocketStream::Delegate* delegate,
+ const URLRequestContext& context) {
+ GURL socket_url(url);
+ TransportSecurityState::DomainState domain_state;
+ if (url.scheme() == "ws" &&
+ context.transport_security_state() &&
+ context.transport_security_state()->IsEnabledForHost(
+ &domain_state, url.host(), context.IsSNIAvailable()) &&
+ domain_state.mode == TransportSecurityState::DomainState::MODE_STRICT) {
+ url_canon::Replacements<char> replacements;
+ static const char kNewScheme[] = "wss";
+ replacements.SetScheme(kNewScheme,
+ url_parse::Component(0, strlen(kNewScheme)));
+ socket_url = url.ReplaceComponents(replacements);
+ }
+ return SocketStreamJobManager::GetInstance()->CreateJob(socket_url, delegate);
}
SocketStreamJob::SocketStreamJob() {}
diff --git a/net/socket_stream/socket_stream_job.h b/net/socket_stream/socket_stream_job.h
index 9a4577e..24eaa19 100644
--- a/net/socket_stream/socket_stream_job.h
+++ b/net/socket_stream/socket_stream_job.h
@@ -32,7 +32,9 @@ class SocketStreamJob : public base::RefCountedThreadSafe<SocketStreamJob> {
ProtocolFactory* factory);
static SocketStreamJob* CreateSocketStreamJob(
- const GURL& url, SocketStream::Delegate* delegate);
+ const GURL& url,
+ SocketStream::Delegate* delegate,
+ const URLRequestContext& context);
SocketStreamJob();
void InitSocketStream(SocketStream* socket) {
@@ -61,6 +63,7 @@ class SocketStreamJob : public base::RefCountedThreadSafe<SocketStreamJob> {
virtual void DetachDelegate();
protected:
+ friend class WebSocketJobTest;
friend class base::RefCountedThreadSafe<SocketStreamJob>;
virtual ~SocketStreamJob();
diff --git a/net/url_request/url_request_context.cc b/net/url_request/url_request_context.cc
index 7e02641..09ac381 100644
--- a/net/url_request/url_request_context.cc
+++ b/net/url_request/url_request_context.cc
@@ -58,6 +58,15 @@ const std::string& URLRequestContext::GetUserAgent(const GURL& url) const {
return EmptyString();
}
+bool URLRequestContext::IsSNIAvailable() const {
+ if (!ssl_config_service_)
+ return false;
+
+ SSLConfig ssl_config;
+ ssl_config_service_->GetSSLConfig(&ssl_config);
+ return ssl_config.tls1_enabled;
+}
+
URLRequestContext::~URLRequestContext() {
}
diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h
index ea80143..2c99059 100644
--- a/net/url_request/url_request_context.h
+++ b/net/url_request/url_request_context.h
@@ -180,6 +180,9 @@ class URLRequestContext
bool is_main() const { return is_main_; }
void set_is_main(bool is_main) { is_main_ = is_main; }
+ // Is SNI available in this request context?
+ bool IsSNIAvailable() const;
+
protected:
friend class base::RefCountedThreadSafe<URLRequestContext>;
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 7166e5f..19b86a8 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -183,7 +183,7 @@ URLRequestJob* URLRequestHttpJob::Factory(URLRequest* request,
request->context()->transport_security_state()->IsEnabledForHost(
&domain_state,
request->url().host(),
- IsSNIAvailable(request->context()))) {
+ request->context()->IsSNIAvailable())) {
if (domain_state.mode ==
TransportSecurityState::DomainState::MODE_STRICT) {
DCHECK_EQ(request->url().scheme(), "http");
@@ -665,7 +665,7 @@ void URLRequestHttpJob::OnStartCompleted(int result) {
if (context_->transport_security_state()->IsEnabledForHost(
&domain_state,
request_->url().host(),
- IsSNIAvailable(context_)) &&
+ context_->IsSNIAvailable()) &&
ssl_info.is_issued_by_known_root &&
!domain_state.IsChainOfPublicKeysPermitted(ssl_info.public_key_hashes)){
result = ERR_CERT_INVALID;
@@ -720,7 +720,7 @@ bool URLRequestHttpJob::ShouldTreatAsCertificateError(int result) {
TransportSecurityState::DomainState domain_state;
// TODO(agl): don't ignore opportunistic mode.
const bool r = context_->transport_security_state()->IsEnabledForHost(
- &domain_state, request_info_.url.host(), IsSNIAvailable(context_));
+ &domain_state, request_info_.url.host(), context_->IsSNIAvailable());
return !r || domain_state.mode ==
TransportSecurityState::DomainState::MODE_OPPORTUNISTIC;
@@ -1370,14 +1370,4 @@ bool URLRequestHttpJob::IsCompressibleContent() const {
IsSupportedNonImageMimeType(mime_type.c_str()));
}
-// static
-bool URLRequestHttpJob::IsSNIAvailable(URLRequestContext* context) {
- if (!context->ssl_config_service())
- return false;
-
- SSLConfig ssl_config;
- context->ssl_config_service()->GetSSLConfig(&ssl_config);
- return ssl_config.tls1_enabled;
-}
-
} // namespace net
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h
index 5173ae1..7ac5c97 100644
--- a/net/url_request/url_request_http_job.h
+++ b/net/url_request/url_request_http_job.h
@@ -147,8 +147,6 @@ class URLRequestHttpJob : public URLRequestJob {
void RecordCompressionHistograms();
bool IsCompressibleContent() const;
- static bool IsSNIAvailable(URLRequestContext* context);
-
base::Time request_creation_time_;
// Data used for statistics gathering. This data is only used for histograms
diff --git a/net/websockets/websocket_job_unittest.cc b/net/websockets/websocket_job_unittest.cc
index a0ae1d4..f027a4a 100644
--- a/net/websockets/websocket_job_unittest.cc
+++ b/net/websockets/websocket_job_unittest.cc
@@ -13,6 +13,7 @@
#include "net/base/cookie_store.h"
#include "net/base/net_errors.h"
#include "net/base/sys_addrinfo.h"
+#include "net/base/transport_security_state.h"
#include "net/socket_stream/socket_stream.h"
#include "net/url_request/url_request_context.h"
#include "net/websockets/websocket_job.h"
@@ -156,11 +157,18 @@ class MockURLRequestContext : public URLRequestContext {
CookiePolicy* cookie_policy) {
set_cookie_store(cookie_store);
set_cookie_policy(cookie_policy);
+ transport_security_state_ = new TransportSecurityState();
+ set_transport_security_state(transport_security_state_.get());
+ TransportSecurityState::DomainState state;
+ state.expiry = base::Time::Now() + base::TimeDelta::FromSeconds(1000);
+ transport_security_state_->EnableHost("upgrademe.com", state);
}
private:
friend class base::RefCountedThreadSafe<MockURLRequestContext>;
virtual ~MockURLRequestContext() {}
+
+ scoped_refptr<TransportSecurityState> transport_security_state_;
};
class WebSocketJobTest : public PlatformTest {
@@ -209,6 +217,9 @@ class WebSocketJobTest : public PlatformTest {
websocket_->delegate_ = NULL;
websocket_->socket_ = NULL;
}
+ SocketStream* GetSocket(SocketStreamJob* job) {
+ return job->socket_.get();
+ }
scoped_refptr<MockCookieStore> cookie_store_;
scoped_ptr<MockCookiePolicy> cookie_policy_;
@@ -494,4 +505,19 @@ TEST_F(WebSocketJobTest, HandshakeWithCookieButNotAllowed) {
CloseWebSocketJob();
}
+TEST_F(WebSocketJobTest, HSTSUpgrade) {
+ GURL url("ws://upgrademe.com/");
+ MockSocketStreamDelegate delegate;
+ scoped_refptr<SocketStreamJob> job = SocketStreamJob::CreateSocketStreamJob(
+ url, &delegate, *context_.get());
+ EXPECT_TRUE(GetSocket(job.get())->is_secure());
+ job->DetachDelegate();
+
+ url = GURL("ws://donotupgrademe.com/");
+ job = SocketStreamJob::CreateSocketStreamJob(
+ url, &delegate, *context_.get());
+ EXPECT_FALSE(GetSocket(job.get())->is_secure());
+ job->DetachDelegate();
+}
+
} // namespace net
diff --git a/webkit/tools/test_shell/simple_socket_stream_bridge.cc b/webkit/tools/test_shell/simple_socket_stream_bridge.cc
index 4420b26..a555b48 100644
--- a/webkit/tools/test_shell/simple_socket_stream_bridge.cc
+++ b/webkit/tools/test_shell/simple_socket_stream_bridge.cc
@@ -156,7 +156,8 @@ void WebSocketStreamHandleBridgeImpl::OnClose(net::SocketStream* socket) {
void WebSocketStreamHandleBridgeImpl::DoConnect(const GURL& url) {
DCHECK(MessageLoop::current() == g_io_thread);
- socket_ = net::SocketStreamJob::CreateSocketStreamJob(url, this);
+ socket_ = net::SocketStreamJob::CreateSocketStreamJob(
+ url, this, *g_request_context);
socket_->set_context(g_request_context);
socket_->Connect();
}