Commit 38fc268c authored by ricea's avatar ricea Committed by Commit bot

Change error message for WebSocket tunnel failure.

Currently a proxy refusal to allow a WebSocket to establish a tunnel
results in an error message like:

WebSocket connection to 'ws://foo:5036/' failed: Error in connection
establishment: net::ERR_TUNNEL_CONNECTION_FAILED

It is not obvious from this message that a proxy is the cause of the
problem. Change the message to:

WebSocket connection to 'ws://foo:5036/' failed: Establishing a tunnel
via proxy server failed.

BUG=454311
TEST=net_unittests, browser_tests, layout tests

Review URL: https://codereview.chromium.org/902553002

Cr-Commit-Position: refs/heads/master@{#315257}
parent 8a9c0f30
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/metrics/histogram.h" #include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h" #include "base/metrics/sparse_histogram.h"
#include "base/profiler/scoped_tracker.h" #include "base/profiler/scoped_tracker.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/timer/timer.h" #include "base/timer/timer.h"
#include "net/base/load_flags.h" #include "net/base/load_flags.h"
...@@ -135,6 +136,20 @@ class StreamRequestImpl : public WebSocketStreamRequest { ...@@ -135,6 +136,20 @@ class StreamRequestImpl : public WebSocketStreamRequest {
connect_delegate_->OnSuccess(create_helper_->Upgrade()); connect_delegate_->OnSuccess(create_helper_->Upgrade());
} }
std::string FailureMessageFromNetError() {
int error = url_request_->status().error();
if (error == ERR_TUNNEL_CONNECTION_FAILED) {
// This error is common and confusing, so special-case it.
// TODO(ricea): Include the HostPortPair of the selected proxy server in
// the error message. This is not currently possible because it isn't set
// in HttpResponseInfo when a ERR_TUNNEL_CONNECTION_FAILED error happens.
return "Establishing a tunnel via proxy server failed.";
} else {
return std::string("Error in connection establishment: ") +
ErrorToString(url_request_->status().error());
}
}
void ReportFailure() { void ReportFailure() {
DCHECK(timer_); DCHECK(timer_);
timer_->Stop(); timer_->Stop();
...@@ -150,9 +165,7 @@ class StreamRequestImpl : public WebSocketStreamRequest { ...@@ -150,9 +165,7 @@ class StreamRequestImpl : public WebSocketStreamRequest {
failure_message_ = "WebSocket opening handshake was canceled"; failure_message_ = "WebSocket opening handshake was canceled";
break; break;
case URLRequestStatus::FAILED: case URLRequestStatus::FAILED:
failure_message_ = failure_message_ = FailureMessageFromNetError();
std::string("Error in connection establishment: ") +
ErrorToString(url_request_->status().error());
break; break;
} }
} }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "net/base/test_data_directory.h" #include "net/base/test_data_directory.h"
#include "net/http/http_request_headers.h" #include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h" #include "net/http/http_response_headers.h"
#include "net/proxy/proxy_service.h"
#include "net/socket/client_socket_handle.h" #include "net/socket/client_socket_handle.h"
#include "net/socket/socket_test_util.h" #include "net/socket/socket_test_util.h"
#include "net/test/cert_test_util.h" #include "net/test/cert_test_util.h"
...@@ -1412,5 +1413,33 @@ TEST_F(WebSocketStreamCreateTest, HandleErrConnectionClosed) { ...@@ -1412,5 +1413,33 @@ TEST_F(WebSocketStreamCreateTest, HandleErrConnectionClosed) {
EXPECT_TRUE(has_failed()); EXPECT_TRUE(has_failed());
} }
TEST_F(WebSocketStreamCreateTest, HandleErrTunnelConnectionFailed) {
static const char kConnectRequest[] =
"CONNECT localhost:80 HTTP/1.1\r\n"
"Host: localhost\r\n"
"Proxy-Connection: keep-alive\r\n"
"\r\n";
static const char kProxyResponse[] =
"HTTP/1.1 403 Forbidden\r\n"
"Content-Type: text/html\r\n"
"Content-Length: 9\r\n"
"Connection: keep-alive\r\n"
"\r\n"
"Forbidden";
MockRead reads[] = {MockRead(SYNCHRONOUS, 1, kProxyResponse)};
MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, kConnectRequest)};
scoped_ptr<DeterministicSocketData> socket_data(
BuildSocketData(reads, writes));
url_request_context_host_.SetProxyConfig("https=proxy:8000");
CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
"http://localhost", socket_data.Pass());
RunUntilIdle();
EXPECT_TRUE(has_failed());
EXPECT_EQ("Establishing a tunnel via proxy server failed.",
failure_message());
}
} // namespace } // namespace
} // namespace net } // namespace net
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/memory/scoped_vector.h" #include "base/memory/scoped_vector.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "net/proxy/proxy_service.h"
#include "net/socket/socket_test_util.h" #include "net/socket/socket_test_util.h"
namespace net { namespace net {
...@@ -151,6 +152,13 @@ void WebSocketTestURLRequestContextHost::AddSSLSocketDataProvider( ...@@ -151,6 +152,13 @@ void WebSocketTestURLRequestContextHost::AddSSLSocketDataProvider(
maker_.AddSSLSocketDataProvider(ssl_socket_data.Pass()); maker_.AddSSLSocketDataProvider(ssl_socket_data.Pass());
} }
void WebSocketTestURLRequestContextHost::SetProxyConfig(
const std::string& proxy_rules) {
DCHECK(!url_request_context_initialized_);
proxy_service_.reset(ProxyService::CreateFixed(proxy_rules));
url_request_context_.set_proxy_service(proxy_service_.get());
}
TestURLRequestContext* TestURLRequestContext*
WebSocketTestURLRequestContextHost::GetURLRequestContext() { WebSocketTestURLRequestContextHost::GetURLRequestContext() {
if (!url_request_context_initialized_) { if (!url_request_context_initialized_) {
......
...@@ -27,6 +27,7 @@ namespace net { ...@@ -27,6 +27,7 @@ namespace net {
class BoundNetLog; class BoundNetLog;
class DeterministicMockClientSocketFactory; class DeterministicMockClientSocketFactory;
class DeterministicSocketData; class DeterministicSocketData;
class ProxyService;
class URLRequestContext; class URLRequestContext;
class WebSocketHandshakeStreamCreateHelper; class WebSocketHandshakeStreamCreateHelper;
struct SSLSocketDataProvider; struct SSLSocketDataProvider;
...@@ -123,6 +124,12 @@ struct WebSocketTestURLRequestContextHost { ...@@ -123,6 +124,12 @@ struct WebSocketTestURLRequestContextHost {
void AddSSLSocketDataProvider( void AddSSLSocketDataProvider(
scoped_ptr<SSLSocketDataProvider> ssl_socket_data); scoped_ptr<SSLSocketDataProvider> ssl_socket_data);
// Allow a proxy to be set. Usage:
// SetProxyConfig("proxy1:8000");
// Any syntax accepted by net::ProxyConfig::ParseFromString() will work.
// Do not call after GetURLRequestContext() has been called.
void SetProxyConfig(const std::string& proxy_rules);
// Call after calling one of SetExpections() or AddRawExpectations(). The // Call after calling one of SetExpections() or AddRawExpectations(). The
// returned pointer remains owned by this object. // returned pointer remains owned by this object.
TestURLRequestContext* GetURLRequestContext(); TestURLRequestContext* GetURLRequestContext();
...@@ -131,6 +138,7 @@ struct WebSocketTestURLRequestContextHost { ...@@ -131,6 +138,7 @@ struct WebSocketTestURLRequestContextHost {
WebSocketDeterministicMockClientSocketFactoryMaker maker_; WebSocketDeterministicMockClientSocketFactoryMaker maker_;
TestURLRequestContext url_request_context_; TestURLRequestContext url_request_context_;
TestNetworkDelegate network_delegate_; TestNetworkDelegate network_delegate_;
scoped_ptr<ProxyService> proxy_service_;
bool url_request_context_initialized_; bool url_request_context_initialized_;
DISALLOW_COPY_AND_ASSIGN(WebSocketTestURLRequestContextHost); DISALLOW_COPY_AND_ASSIGN(WebSocketTestURLRequestContextHost);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment