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 @@
#include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h"
#include "base/profiler/scoped_tracker.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "net/base/load_flags.h"
......@@ -135,6 +136,20 @@ class StreamRequestImpl : public WebSocketStreamRequest {
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() {
DCHECK(timer_);
timer_->Stop();
......@@ -150,9 +165,7 @@ class StreamRequestImpl : public WebSocketStreamRequest {
failure_message_ = "WebSocket opening handshake was canceled";
break;
case URLRequestStatus::FAILED:
failure_message_ =
std::string("Error in connection establishment: ") +
ErrorToString(url_request_->status().error());
failure_message_ = FailureMessageFromNetError();
break;
}
}
......
......@@ -22,6 +22,7 @@
#include "net/base/test_data_directory.h"
#include "net/http/http_request_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/socket_test_util.h"
#include "net/test/cert_test_util.h"
......@@ -1412,5 +1413,33 @@ TEST_F(WebSocketStreamCreateTest, HandleErrConnectionClosed) {
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 net
......@@ -11,6 +11,7 @@
#include "base/memory/scoped_vector.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "net/proxy/proxy_service.h"
#include "net/socket/socket_test_util.h"
namespace net {
......@@ -151,6 +152,13 @@ void WebSocketTestURLRequestContextHost::AddSSLSocketDataProvider(
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*
WebSocketTestURLRequestContextHost::GetURLRequestContext() {
if (!url_request_context_initialized_) {
......
......@@ -27,6 +27,7 @@ namespace net {
class BoundNetLog;
class DeterministicMockClientSocketFactory;
class DeterministicSocketData;
class ProxyService;
class URLRequestContext;
class WebSocketHandshakeStreamCreateHelper;
struct SSLSocketDataProvider;
......@@ -123,6 +124,12 @@ struct WebSocketTestURLRequestContextHost {
void AddSSLSocketDataProvider(
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
// returned pointer remains owned by this object.
TestURLRequestContext* GetURLRequestContext();
......@@ -131,6 +138,7 @@ struct WebSocketTestURLRequestContextHost {
WebSocketDeterministicMockClientSocketFactoryMaker maker_;
TestURLRequestContext url_request_context_;
TestNetworkDelegate network_delegate_;
scoped_ptr<ProxyService> proxy_service_;
bool url_request_context_initialized_;
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