diff options
-rw-r--r-- | chrome/browser/extensions/extension_proxy_apitest.cc | 4 | ||||
-rw-r--r-- | chrome/browser/io_thread.cc | 3 | ||||
-rw-r--r-- | chrome/browser/net/chrome_network_delegate.cc | 28 | ||||
-rw-r--r-- | chrome/browser/net/chrome_network_delegate.h | 2 | ||||
-rw-r--r-- | net/http/http_network_delegate.h | 8 | ||||
-rw-r--r-- | net/url_request/url_request.cc | 7 | ||||
-rw-r--r-- | net/url_request/url_request_job.cc | 12 | ||||
-rw-r--r-- | net/url_request/url_request_test_util.cc | 37 | ||||
-rw-r--r-- | net/url_request/url_request_test_util.h | 24 | ||||
-rw-r--r-- | net/url_request/url_request_unittest.cc | 60 |
10 files changed, 178 insertions, 7 deletions
diff --git a/chrome/browser/extensions/extension_proxy_apitest.cc b/chrome/browser/extensions/extension_proxy_apitest.cc index ad77ed4..970ca71 100644 --- a/chrome/browser/extensions/extension_proxy_apitest.cc +++ b/chrome/browser/extensions/extension_proxy_apitest.cc @@ -284,8 +284,8 @@ IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, pref_service); } -// TODO(jochen): enable once network side has landed. Tests error events. -IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, DISABLED_ProxyEvents) { +// Tests error events. +IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxyEvents) { CommandLine::ForCurrentProcess()->AppendSwitch( switches::kEnableExperimentalExtensionApis); diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index 2a854b8..e966707 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc @@ -346,7 +346,8 @@ void IOThread::Init() { globals_->proxy_script_fetcher_proxy_service.get(); session_params.http_auth_handler_factory = globals_->http_auth_handler_factory.get(); - session_params.network_delegate = &globals_->network_delegate; + // TODO(willchan): Enable for proxy script fetcher context. + session_params.network_delegate = NULL; session_params.net_log = net_log_; session_params.ssl_config_service = globals_->ssl_config_service; scoped_refptr<net::HttpNetworkSession> network_session( diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc index 0c92721..ce79045 100644 --- a/chrome/browser/net/chrome_network_delegate.cc +++ b/chrome/browser/net/chrome_network_delegate.cc @@ -1,12 +1,14 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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 "chrome/browser/net/chrome_network_delegate.h" #include "base/logging.h" +#include "chrome/browser/extensions/extension_proxy_api.h" #include "chrome/browser/extensions/extension_webrequest_api.h" #include "chrome/browser/net/chrome_url_request_context.h" +#include "net/base/net_errors.h" #include "net/http/http_request_headers.h" #include "net/url_request/url_request.h" @@ -21,6 +23,21 @@ const ExtensionIOEventRouter* GetIOEventRouter( extension_io_event_router(); } +// If the |request| failed due to problems with a proxy, forward the error to +// the proxy extension API. +void ForwardProxyErrors(net::URLRequest* request) { + if (request->status().status() == net::URLRequestStatus::FAILED) { + switch (request->status().os_error()) { + case net::ERR_PROXY_AUTH_UNSUPPORTED: + case net::ERR_PROXY_CONNECTION_FAILED: + case net::ERR_TUNNEL_CONNECTION_FAILED: + ExtensionProxyEventRouter::GetInstance()->OnProxyError( + GetIOEventRouter(request->context()), + request->status().os_error()); + } + } +} + } // namespace ChromeNetworkDelegate::ChromeNetworkDelegate() {} @@ -37,3 +54,12 @@ void ChromeNetworkDelegate::OnSendHttpRequest( // TODO(willchan): Add Chrome-side hooks to listen / mutate requests here. } + +void ChromeNetworkDelegate::OnResponseStarted(net::URLRequest* request) { + ForwardProxyErrors(request); +} + +void ChromeNetworkDelegate::OnReadCompleted(net::URLRequest* request, + int bytes_read) { + ForwardProxyErrors(request); +} diff --git a/chrome/browser/net/chrome_network_delegate.h b/chrome/browser/net/chrome_network_delegate.h index 8bff160..06c7c93 100644 --- a/chrome/browser/net/chrome_network_delegate.h +++ b/chrome/browser/net/chrome_network_delegate.h @@ -19,6 +19,8 @@ class ChromeNetworkDelegate : public net::HttpNetworkDelegate { // net::HttpNetworkDelegate methods: virtual void OnBeforeURLRequest(net::URLRequest* request); virtual void OnSendHttpRequest(net::HttpRequestHeaders* headers); + virtual void OnResponseStarted(net::URLRequest* request); + virtual void OnReadCompleted(net::URLRequest* request, int bytes_read); // TODO(willchan): Add functions for consumers to register ways to // access/modify the request. diff --git a/net/http/http_network_delegate.h b/net/http/http_network_delegate.h index 1533bc3..9a9300b 100644 --- a/net/http/http_network_delegate.h +++ b/net/http/http_network_delegate.h @@ -14,12 +14,18 @@ class URLRequest; class HttpNetworkDelegate { public: // Called before a request is sent. - virtual void OnBeforeURLRequest(net::URLRequest* request) = 0; + virtual void OnBeforeURLRequest(URLRequest* request) = 0; // Called right before the HTTP headers are sent. Allows the delegate to // read/write |headers| before they get sent out. virtual void OnSendHttpRequest(HttpRequestHeaders* headers) = 0; + // This corresponds to URLRequestDelegate::OnResponseStarted. + virtual void OnResponseStarted(URLRequest* request) = 0; + + // This corresponds to URLRequestDelegate::OnReadCompleted. + virtual void OnReadCompleted(URLRequest* request, int bytes_read) = 0; + protected: virtual ~HttpNetworkDelegate() {} }; diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index 848b810..ca8aacb 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc @@ -492,8 +492,11 @@ void URLRequest::ResponseStarted() { URLRequestJobManager::GetInstance()->MaybeInterceptResponse(this); if (job) { RestartWithJob(job); - } else if (delegate_) { - delegate_->OnResponseStarted(this); + } else { + if (context_ && context_->network_delegate()) + context_->network_delegate()->OnResponseStarted(this); + if (delegate_) + delegate_->OnResponseStarted(this); } } diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc index 12c8d2e..2aede15 100644 --- a/net/url_request/url_request_job.cc +++ b/net/url_request/url_request_job.cc @@ -14,8 +14,10 @@ #include "net/base/load_flags.h" #include "net/base/mime_util.h" #include "net/base/net_errors.h" +#include "net/http/http_network_delegate.h" #include "net/http/http_response_headers.h" #include "net/url_request/url_request.h" +#include "net/url_request/url_request_context.h" #include "net/url_request/url_request_job_metrics.h" #include "net/url_request/url_request_job_tracker.h" @@ -535,10 +537,18 @@ void URLRequestJob::NotifyReadComplete(int bytes_read) { int filter_bytes_read = 0; if (ReadFilteredData(&filter_bytes_read)) { postfilter_bytes_read_ += filter_bytes_read; + if (request_->context() && request_->context()->network_delegate()) { + request_->context()->network_delegate()->OnReadCompleted( + request_, filter_bytes_read); + } request_->delegate()->OnReadCompleted(request_, filter_bytes_read); } } else { postfilter_bytes_read_ += bytes_read; + if (request_->context() && request_->context()->network_delegate()) { + request_->context()->network_delegate()->OnReadCompleted( + request_, bytes_read); + } request_->delegate()->OnReadCompleted(request_, bytes_read); } } @@ -610,6 +620,8 @@ void URLRequestJob::CompleteNotifyDone() { // OnResponseStarted yet. if (has_handled_response_) { // We signal the error by calling OnReadComplete with a bytes_read of -1. + if (request_->context() && request_->context()->network_delegate()) + request_->context()->network_delegate()->OnReadCompleted(request_, -1); request_->delegate()->OnReadCompleted(request_, -1); } else { has_handled_response_ = true; diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc index b20cfc7..0302ce5 100644 --- a/net/url_request/url_request_test_util.cc +++ b/net/url_request/url_request_test_util.cc @@ -96,6 +96,15 @@ TestURLRequestContext::TestURLRequestContext(const std::string& proxy) { Init(); } +TestURLRequestContext::TestURLRequestContext(const std::string& proxy, + net::HostResolver* host_resolver) { + set_host_resolver(host_resolver); + net::ProxyConfig proxy_config; + proxy_config.proxy_rules().ParseFromString(proxy); + set_proxy_service(net::ProxyService::CreateFixed(proxy_config)); + Init(); +} + TestURLRequestContext::~TestURLRequestContext() { delete ftp_transaction_factory(); delete http_transaction_factory(); @@ -278,3 +287,31 @@ void TestDelegate::OnResponseCompleted(net::URLRequest* request) { if (quit_on_complete_) MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); } + +TestHttpNetworkDelegate::TestHttpNetworkDelegate() + : last_os_error_(0), + error_count_(0) { +} + +TestHttpNetworkDelegate::~TestHttpNetworkDelegate() {} + +void TestHttpNetworkDelegate::OnBeforeURLRequest(net::URLRequest* request) { +} + +void TestHttpNetworkDelegate::OnSendHttpRequest( + net::HttpRequestHeaders* headers) { +} + +void TestHttpNetworkDelegate::OnResponseStarted(net::URLRequest* request) { + if (request->status().status() == net::URLRequestStatus::FAILED) { + error_count_++; + last_os_error_ = request->status().os_error(); + } +} +void TestHttpNetworkDelegate::OnReadCompleted(net::URLRequest* request, + int bytes_read) { + if (request->status().status() == net::URLRequestStatus::FAILED) { + error_count_++; + last_os_error_ = request->status().os_error(); + } +} diff --git a/net/url_request/url_request_test_util.h b/net/url_request/url_request_test_util.h index 3f8b4b4..1b75205 100644 --- a/net/url_request/url_request_test_util.h +++ b/net/url_request/url_request_test_util.h @@ -28,6 +28,7 @@ #include "net/ftp/ftp_network_layer.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_cache.h" +#include "net/http/http_network_delegate.h" #include "net/http/http_network_layer.h" #include "net/test/test_server.h" #include "net/url_request/url_request.h" @@ -75,6 +76,8 @@ class TestURLRequestContext : public net::URLRequestContext { public: TestURLRequestContext(); explicit TestURLRequestContext(const std::string& proxy); + TestURLRequestContext(const std::string& proxy, + net::HostResolver* host_resolver); protected: virtual ~TestURLRequestContext(); @@ -183,4 +186,25 @@ class TestDelegate : public net::URLRequest::Delegate { scoped_refptr<net::IOBuffer> buf_; }; +//----------------------------------------------------------------------------- + +class TestHttpNetworkDelegate : public net::HttpNetworkDelegate { + public: + TestHttpNetworkDelegate(); + virtual ~TestHttpNetworkDelegate(); + + // net::HttpNetworkDelegate: + virtual void OnBeforeURLRequest(net::URLRequest* request); + virtual void OnSendHttpRequest(net::HttpRequestHeaders* headers); + virtual void OnResponseStarted(net::URLRequest* request); + virtual void OnReadCompleted(net::URLRequest* request, int bytes_read); + + int last_os_error() const { return last_os_error_; } + int error_count() const { return error_count_; } + + private: + int last_os_error_; + int error_count_; +}; + #endif // NET_URL_REQUEST_URL_REQUEST_TEST_UTIL_H_ diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 3192b39..c3b8e37 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc @@ -27,6 +27,7 @@ #include "net/base/cookie_monster.h" #include "net/base/cookie_policy.h" #include "net/base/load_flags.h" +#include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" #include "net/base/net_log.h" #include "net/base/net_log_unittest.h" @@ -230,6 +231,37 @@ TEST_F(URLRequestTestHTTP, ProxyTunnelRedirectTest) { } } +// This is the same as the previous test, but checks that the network delegate +// registers the error. +TEST_F(URLRequestTestHTTP, NetworkDelegateTunnelConnectionFailed) { + ASSERT_TRUE(test_server_.Start()); + + TestDelegate d; + { + net::URLRequest r(GURL("https://www.redirect.com/"), &d); + scoped_refptr<TestURLRequestContext> context( + new TestURLRequestContext(test_server_.host_port_pair().ToString())); + TestHttpNetworkDelegate network_delegate; + context->set_network_delegate(&network_delegate); + r.set_context(context); + + r.Start(); + EXPECT_TRUE(r.is_pending()); + + MessageLoop::current()->Run(); + + EXPECT_EQ(net::URLRequestStatus::FAILED, r.status().status()); + EXPECT_EQ(net::ERR_TUNNEL_CONNECTION_FAILED, r.status().os_error()); + EXPECT_EQ(1, d.response_started_count()); + // We should not have followed the redirect. + EXPECT_EQ(0, d.received_redirect_count()); + + EXPECT_EQ(1, network_delegate.error_count()); + EXPECT_EQ(net::ERR_TUNNEL_CONNECTION_FAILED, + network_delegate.last_os_error()); + } +} + // In this unit test, we're using the HTTPTestServer as a proxy server and // issuing a CONNECT request with the magic host name "www.server-auth.com". // The HTTPTestServer will return a 401 response, which we should balk at. @@ -2366,6 +2398,34 @@ TEST_F(URLRequestTest, Identifiers) { ASSERT_NE(req.identifier(), other_req.identifier()); } +// Check that a failure to connect to the proxy is reported to the network +// delegate. +TEST_F(URLRequestTest, NetworkDelegateProxyError) { + TestDelegate d; + TestURLRequest req(GURL("http://example.com"), &d); + req.set_method("GET"); + + scoped_ptr<net::MockHostResolverBase> host_resolver( + new net::MockHostResolver); + host_resolver->rules()->AddSimulatedFailure("*"); + scoped_refptr<TestURLRequestContext> context( + new TestURLRequestContext("myproxy:70", host_resolver.release())); + TestHttpNetworkDelegate network_delegate; + context->set_network_delegate(&network_delegate); + req.set_context(context); + + req.Start(); + MessageLoop::current()->Run(); + + // Check we see a failed request. + EXPECT_FALSE(req.status().is_success()); + EXPECT_EQ(net::URLRequestStatus::FAILED, req.status().status()); + EXPECT_EQ(net::ERR_PROXY_CONNECTION_FAILED, req.status().os_error()); + + EXPECT_EQ(1, network_delegate.error_count()); + EXPECT_EQ(net::ERR_PROXY_CONNECTION_FAILED, network_delegate.last_os_error()); +} + class URLRequestTestFTP : public URLRequestTest { public: URLRequestTestFTP() : test_server_(net::TestServer::TYPE_FTP, FilePath()) { |