diff options
author | sammc <sammc@chromium.org> | 2015-02-24 20:59:21 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-02-25 05:00:09 +0000 |
commit | 5403aa1dc4fa777f106c7c311644abf3d3d576ba (patch) | |
tree | 82acdfe2fb7c6463c281d39520ccfcdfc65507d6 /net | |
parent | 5b570913b6d7a9254a43c576614c6d2de53df78e (diff) | |
download | chromium_src-5403aa1dc4fa777f106c7c311644abf3d3d576ba.zip chromium_src-5403aa1dc4fa777f106c7c311644abf3d3d576ba.tar.gz chromium_src-5403aa1dc4fa777f106c7c311644abf3d3d576ba.tar.bz2 |
Implement utility-side proxy resolver Mojo service.
BUG=11746
Review URL: https://codereview.chromium.org/896203003
Cr-Commit-Position: refs/heads/master@{#317976}
Diffstat (limited to 'net')
-rw-r--r-- | net/BUILD.gn | 23 | ||||
-rw-r--r-- | net/DEPS | 1 | ||||
-rw-r--r-- | net/interfaces/proxy_resolver_service.mojom | 4 | ||||
-rw-r--r-- | net/net.gyp | 20 | ||||
-rw-r--r-- | net/net.gypi | 1 | ||||
-rw-r--r-- | net/proxy/mojo_proxy_resolver_impl.cc | 156 | ||||
-rw-r--r-- | net/proxy/mojo_proxy_resolver_impl.h | 64 | ||||
-rw-r--r-- | net/proxy/mojo_proxy_resolver_impl_unittest.cc | 416 | ||||
-rw-r--r-- | net/proxy/mojo_type_converters.cc | 83 | ||||
-rw-r--r-- | net/proxy/mojo_type_converters.h | 29 | ||||
-rw-r--r-- | net/proxy/proxy_list.cc | 4 | ||||
-rw-r--r-- | net/proxy/proxy_list.h | 3 |
12 files changed, 802 insertions, 2 deletions
diff --git a/net/BUILD.gn b/net/BUILD.gn index 76a5cf8..78c6d5d 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn @@ -808,6 +808,8 @@ if (use_v8_in_net && !is_android) { sources = [ "dns/mojo_type_converters.cc", "dns/mojo_type_converters.h", + "proxy/mojo_type_converters.cc", + "proxy/mojo_type_converters.h", ] public_deps = [ @@ -816,6 +818,21 @@ if (use_v8_in_net && !is_android) { "//third_party/mojo/src/mojo/public/cpp/bindings", ] } + + source_set("net_utility_services") { + sources = [ + "proxy/mojo_proxy_resolver_impl.cc", + "proxy/mojo_proxy_resolver_impl.h", + ] + + public_deps = [ + ":mojo_type_converters", + ":net", + "//mojo/common", + "//net/interfaces", + "//third_party/mojo/src/mojo/public/cpp/bindings", + ] + } } if (!is_ios && !is_android) { @@ -1369,11 +1386,15 @@ if (!is_android && !is_win && !is_mac) { if (use_v8_in_net && !is_android) { deps += [ ":net_browser_services", + ":net_utility_services", "//mojo/environment:chromium", "//third_party/mojo/src/mojo/edk/system", ] } else { - sources -= [ "dns/mojo_host_resolver_impl_unittest.cc" ] + sources -= [ + "dns/mojo_host_resolver_impl_unittest.cc", + "proxy/mojo_proxy_resolver_impl_unittest.cc", + ] } if (!enable_mdns) { @@ -2,6 +2,7 @@ include_rules = [ "+crypto", "+gin", "+jni", + "+mojo/common", "+third_party/apple_apsl", "+third_party/libevent", "+third_party/mojo/src/mojo/public", diff --git a/net/interfaces/proxy_resolver_service.mojom b/net/interfaces/proxy_resolver_service.mojom index a2fb70e..abe263b 100644 --- a/net/interfaces/proxy_resolver_service.mojom +++ b/net/interfaces/proxy_resolver_service.mojom @@ -23,7 +23,9 @@ enum ProxyScheme { // Mirror of net::ProxyServer. struct ProxyServer { ProxyScheme scheme; - string host; + + // |host| and |port| are only valid if |scheme| is not INVALID or DIRECT. + string? host; uint16 port; }; diff --git a/net/net.gyp b/net/net.gyp index 54f90bd..c56c528 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -711,11 +711,13 @@ 'dependencies': [ 'net_with_v8', 'net_browser_services', + 'net_utility_services', '../third_party/mojo/mojo_edk.gyp:mojo_system_impl', ], }, { # else 'sources!': [ 'dns/mojo_host_resolver_impl_unittest.cc', + 'proxy/mojo_proxy_resolver_impl_unittest.cc', ], }, ], @@ -1275,12 +1277,30 @@ ], }, { + # GN version: //net:net_utility_services + 'target_name': 'net_utility_services', + 'type': 'static_library', + 'sources': [ + 'proxy/mojo_proxy_resolver_impl.cc', + 'proxy/mojo_proxy_resolver_impl.h', + ], + 'dependencies': [ + 'mojo_type_converters', + 'net', + 'net_interfaces', + '../mojo/mojo_base.gyp:mojo_common_lib', + '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + ], + }, + { # GN version: //net:mojo_type_converters 'target_name': 'mojo_type_converters', 'type': 'static_library', 'sources': [ 'dns/mojo_type_converters.cc', 'dns/mojo_type_converters.h', + 'proxy/mojo_type_converters.cc', + 'proxy/mojo_type_converters.h', ], 'dependencies': [ 'net', diff --git a/net/net.gypi b/net/net.gypi index a40989b..40e89d1 100644 --- a/net/net.gypi +++ b/net/net.gypi @@ -1436,6 +1436,7 @@ 'proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc', 'proxy/dhcp_proxy_script_fetcher_factory_unittest.cc', 'proxy/dhcp_proxy_script_fetcher_win_unittest.cc', + 'proxy/mojo_proxy_resolver_impl_unittest.cc', 'proxy/multi_threaded_proxy_resolver_unittest.cc', 'proxy/network_delegate_error_observer_unittest.cc', 'proxy/proxy_bypass_rules_unittest.cc', diff --git a/net/proxy/mojo_proxy_resolver_impl.cc b/net/proxy/mojo_proxy_resolver_impl.cc new file mode 100644 index 0000000..870f5d7 --- /dev/null +++ b/net/proxy/mojo_proxy_resolver_impl.cc @@ -0,0 +1,156 @@ +// Copyright 2015 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/proxy/mojo_proxy_resolver_impl.h" + +#include "base/stl_util.h" +#include "mojo/common/common_type_converters.h" +#include "net/base/net_errors.h" +#include "net/base/net_log.h" +#include "net/proxy/mojo_type_converters.h" +#include "net/proxy/proxy_info.h" +#include "net/proxy/proxy_resolver.h" +#include "net/proxy/proxy_resolver_script_data.h" + +namespace net { + +class MojoProxyResolverImpl::Job : public mojo::ErrorHandler { + public: + Job(interfaces::ProxyResolverRequestClientPtr client, + MojoProxyResolverImpl* resolver, + const GURL& url); + ~Job() override; + + void Start(); + + private: + // mojo::ErrorHandler override. + // This is invoked in response to the client disconnecting, indicating + // cancellation. + void OnConnectionError() override; + + void GetProxyDone(int error); + + MojoProxyResolverImpl* resolver_; + + interfaces::ProxyResolverRequestClientPtr client_; + ProxyInfo result_; + GURL url_; + net::ProxyResolver::RequestHandle request_handle_; + + DISALLOW_COPY_AND_ASSIGN(Job); +}; + +MojoProxyResolverImpl::MojoProxyResolverImpl( + scoped_ptr<net::ProxyResolver> resolver) + : resolver_(resolver.Pass()) { + DCHECK(resolver_->expects_pac_bytes()); +} + +MojoProxyResolverImpl::~MojoProxyResolverImpl() { + if (!set_pac_script_requests_.empty()) + resolver_->CancelSetPacScript(); + STLDeleteElements(&resolve_jobs_); +} + +void MojoProxyResolverImpl::SetPacScript( + const mojo::String& data, + const mojo::Callback<void(int32_t)>& callback) { + DVLOG(1) << "SetPacScript(" << data << ")"; + set_pac_script_requests_.push( + SetPacScriptRequest(ProxyResolverScriptData::FromUTF8(data), callback)); + if (set_pac_script_requests_.size() == 1) + StartSetPacScript(); +} + +void MojoProxyResolverImpl::GetProxyForUrl( + const mojo::String& url, + interfaces::ProxyResolverRequestClientPtr client) { + DVLOG(1) << "GetProxyForUrl(" << url << ")"; + Job* job = new Job(client.Pass(), this, url.To<GURL>()); + bool inserted = resolve_jobs_.insert(job).second; + DCHECK(inserted); + job->Start(); +} + +void MojoProxyResolverImpl::DeleteJob(Job* job) { + size_t num_erased = resolve_jobs_.erase(job); + DCHECK(num_erased); + delete job; +} + +void MojoProxyResolverImpl::StartSetPacScript() { + DCHECK(!set_pac_script_requests_.empty()); + int result = resolver_->SetPacScript( + set_pac_script_requests_.front().script_data, + base::Bind(&MojoProxyResolverImpl::SetPacScriptDone, + base::Unretained(this))); + if (result != ERR_IO_PENDING) + SetPacScriptDone(result); +} + +void MojoProxyResolverImpl::SetPacScriptDone(int result) { + DVLOG(1) << "SetPacScript finished with error " << result; + DCHECK(!set_pac_script_requests_.empty()); + set_pac_script_requests_.front().callback.Run(result); + set_pac_script_requests_.pop(); + if (!set_pac_script_requests_.empty()) + StartSetPacScript(); +} + +MojoProxyResolverImpl::Job::Job( + interfaces::ProxyResolverRequestClientPtr client, + MojoProxyResolverImpl* resolver, + const GURL& url) + : resolver_(resolver), + client_(client.Pass()), + url_(url), + request_handle_(nullptr) { +} + +MojoProxyResolverImpl::Job::~Job() { + if (request_handle_) + resolver_->resolver_->CancelRequest(request_handle_); +} + +void MojoProxyResolverImpl::Job::Start() { + int result = resolver_->resolver_->GetProxyForURL( + url_, &result_, base::Bind(&Job::GetProxyDone, base::Unretained(this)), + &request_handle_, BoundNetLog()); + if (result != ERR_IO_PENDING) { + GetProxyDone(result); + return; + } + client_.set_error_handler(this); +} + +void MojoProxyResolverImpl::Job::GetProxyDone(int error) { + request_handle_ = nullptr; + DVLOG(1) << "GetProxyForUrl(" << url_ << ") finished with error " << error + << ". " << result_.proxy_list().size() << " Proxies returned:"; + for (const auto& proxy : result_.proxy_list().GetAll()) { + DVLOG(1) << proxy.ToURI(); + } + mojo::Array<interfaces::ProxyServerPtr> result; + if (error == OK) { + result = mojo::Array<interfaces::ProxyServerPtr>::From( + result_.proxy_list().GetAll()); + } + client_->ReportResult(error, result.Pass()); + resolver_->DeleteJob(this); +} + +void MojoProxyResolverImpl::Job::OnConnectionError() { + resolver_->DeleteJob(this); +} + +MojoProxyResolverImpl::SetPacScriptRequest::SetPacScriptRequest( + const scoped_refptr<ProxyResolverScriptData>& script_data, + const mojo::Callback<void(int32_t)>& callback) + : script_data(script_data), callback(callback) { +} + +MojoProxyResolverImpl::SetPacScriptRequest::~SetPacScriptRequest() = default; + +} // namespace net diff --git a/net/proxy/mojo_proxy_resolver_impl.h b/net/proxy/mojo_proxy_resolver_impl.h new file mode 100644 index 0000000..2cbf8bb --- /dev/null +++ b/net/proxy/mojo_proxy_resolver_impl.h @@ -0,0 +1,64 @@ +// Copyright 2015 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. + +#ifndef NET_PROXY_MOJO_PROXY_RESOLVER_IMPL_H_ +#define NET_PROXY_MOJO_PROXY_RESOLVER_IMPL_H_ + +#include <queue> +#include <set> + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "net/interfaces/proxy_resolver_service.mojom.h" + +namespace net { + +class ProxyResolver; +class ProxyResolverScriptData; + +class MojoProxyResolverImpl : public interfaces::ProxyResolver { + public: + explicit MojoProxyResolverImpl(scoped_ptr<net::ProxyResolver> resolver); + + ~MojoProxyResolverImpl() override; + + private: + class Job; + + struct SetPacScriptRequest { + SetPacScriptRequest( + const scoped_refptr<ProxyResolverScriptData>& script_data, + const mojo::Callback<void(int32_t)>& callback); + ~SetPacScriptRequest(); + + // The script data for this request. + scoped_refptr<ProxyResolverScriptData> script_data; + + // The callback to run to report the result of this request. + const mojo::Callback<void(int32_t)> callback; + }; + + // interfaces::ProxyResolver overrides. + void SetPacScript(const mojo::String& data, + const mojo::Callback<void(int32_t)>& callback) override; + void GetProxyForUrl( + const mojo::String& url, + interfaces::ProxyResolverRequestClientPtr client) override; + + void DeleteJob(Job* job); + + void StartSetPacScript(); + void SetPacScriptDone(int result); + + scoped_ptr<net::ProxyResolver> resolver_; + std::set<Job*> resolve_jobs_; + + std::queue<SetPacScriptRequest> set_pac_script_requests_; + + DISALLOW_COPY_AND_ASSIGN(MojoProxyResolverImpl); +}; + +} // namespace net + +#endif // NET_PROXY_MOJO_PROXY_RESOLVER_IMPL_H_ diff --git a/net/proxy/mojo_proxy_resolver_impl_unittest.cc b/net/proxy/mojo_proxy_resolver_impl_unittest.cc new file mode 100644 index 0000000..7fa67c6 --- /dev/null +++ b/net/proxy/mojo_proxy_resolver_impl_unittest.cc @@ -0,0 +1,416 @@ +// Copyright 2015 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/proxy/mojo_proxy_resolver_impl.h" + +#include <string> +#include <vector> + +#include "base/run_loop.h" +#include "base/strings/utf_string_conversions.h" +#include "net/base/net_errors.h" +#include "net/proxy/mock_proxy_resolver.h" +#include "net/proxy/mojo_type_converters.h" +#include "net/proxy/proxy_info.h" +#include "net/proxy/proxy_server.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h" + +namespace net { +namespace { + +class TestRequestClient : public interfaces::ProxyResolverRequestClient, + public mojo::ErrorHandler { + public: + explicit TestRequestClient( + mojo::InterfaceRequest<interfaces::ProxyResolverRequestClient> request); + + void WaitForResult(); + void WaitForConnectionError(); + + Error error() { return error_; } + const mojo::Array<interfaces::ProxyServerPtr>& results() { return results_; } + + private: + // interfaces::ProxyResolverRequestClient override. + void ReportResult(int32_t error, + mojo::Array<interfaces::ProxyServerPtr> results) override; + + // mojo::ErrorHandler override. + void OnConnectionError() override; + + bool done_ = false; + bool encountered_connection_error_ = false; + Error error_ = ERR_FAILED; + mojo::Array<interfaces::ProxyServerPtr> results_; + base::Closure run_loop_quit_closure_; + base::Closure connection_error_callback_; + + mojo::Binding<interfaces::ProxyResolverRequestClient> binding_; +}; + +TestRequestClient::TestRequestClient( + mojo::InterfaceRequest<interfaces::ProxyResolverRequestClient> request) + : binding_(this, request.Pass()) { + binding_.set_error_handler(this); +} + +void TestRequestClient::WaitForResult() { + if (done_) + return; + + base::RunLoop run_loop; + run_loop_quit_closure_ = run_loop.QuitClosure(); + run_loop.Run(); + ASSERT_TRUE(done_); +} + +void TestRequestClient::WaitForConnectionError() { + if (encountered_connection_error_) + return; + + base::RunLoop run_loop; + connection_error_callback_ = run_loop.QuitClosure(); + run_loop.Run(); + ASSERT_TRUE(encountered_connection_error_); +} + +void TestRequestClient::ReportResult( + int32_t error, + mojo::Array<interfaces::ProxyServerPtr> results) { + if (!run_loop_quit_closure_.is_null()) { + run_loop_quit_closure_.Run(); + } + ASSERT_FALSE(done_); + error_ = static_cast<Error>(error); + results_ = results.Pass(); + done_ = true; +} + +void TestRequestClient::OnConnectionError() { + if (!connection_error_callback_.is_null()) + connection_error_callback_.Run(); + encountered_connection_error_ = true; +} + +class SetPacScriptClient { + public: + base::Callback<void(int32_t)> CreateCallback(); + Error error() { return error_; } + + private: + void ReportResult(int32_t error); + + Error error_ = ERR_FAILED; +}; + +base::Callback<void(int32_t)> SetPacScriptClient::CreateCallback() { + return base::Bind(&SetPacScriptClient::ReportResult, base::Unretained(this)); +} + +void SetPacScriptClient::ReportResult(int32_t error) { + error_ = static_cast<Error>(error); +} + +class CallbackMockProxyResolver : public MockAsyncProxyResolverExpectsBytes { + public: + CallbackMockProxyResolver() {} + ~CallbackMockProxyResolver() override; + + // MockAsyncProxyResolverExpectsBytes overrides. + int GetProxyForURL(const GURL& url, + ProxyInfo* results, + const net::CompletionCallback& callback, + RequestHandle* request_handle, + const BoundNetLog& net_log) override; + void CancelRequest(RequestHandle request_handle) override; + int SetPacScript(const scoped_refptr<ProxyResolverScriptData>& script_data, + const net::CompletionCallback& callback) override; + + // Wait until the mock resolver has received a CancelRequest call. + void WaitForCancel(); + + // Queues a proxy result to be returned synchronously. + void ReturnProxySynchronously(const ProxyInfo& result); + + // Queues a SetPacScript to be completed synchronously. + void CompleteSetPacScriptSynchronously(); + + private: + base::Closure cancel_callback_; + scoped_ptr<ProxyInfo> sync_result_; + bool set_pac_script_sync_ = false; +}; + +CallbackMockProxyResolver::~CallbackMockProxyResolver() { + EXPECT_TRUE(pending_requests().empty()); +} + +int CallbackMockProxyResolver::GetProxyForURL( + const GURL& url, + ProxyInfo* results, + const net::CompletionCallback& callback, + RequestHandle* request_handle, + const BoundNetLog& net_log) { + if (sync_result_) { + *results = *sync_result_; + sync_result_.reset(); + return OK; + } + return MockAsyncProxyResolverExpectsBytes::GetProxyForURL( + url, results, callback, request_handle, net_log); +} + +void CallbackMockProxyResolver::CancelRequest(RequestHandle request_handle) { + MockAsyncProxyResolverExpectsBytes::CancelRequest(request_handle); + if (!cancel_callback_.is_null()) { + cancel_callback_.Run(); + cancel_callback_.Reset(); + } +} + +int CallbackMockProxyResolver::SetPacScript( + const scoped_refptr<ProxyResolverScriptData>& script_data, + const net::CompletionCallback& callback) { + if (set_pac_script_sync_) { + set_pac_script_sync_ = false; + return OK; + } + return MockAsyncProxyResolverExpectsBytes::SetPacScript(script_data, + callback); +} + +void CallbackMockProxyResolver::WaitForCancel() { + while (cancelled_requests().empty()) { + base::RunLoop run_loop; + cancel_callback_ = run_loop.QuitClosure(); + run_loop.Run(); + } +} + +void CallbackMockProxyResolver::ReturnProxySynchronously( + const ProxyInfo& result) { + sync_result_.reset(new ProxyInfo(result)); +} + +void CallbackMockProxyResolver::CompleteSetPacScriptSynchronously() { + set_pac_script_sync_ = true; +} + +void Fail(int32_t error) { + FAIL() << "Unexpected callback with error: " << error; +} + +} // namespace + +class MojoProxyResolverImplTest : public testing::Test { + protected: + void SetUp() override { + scoped_ptr<CallbackMockProxyResolver> mock_resolver( + new CallbackMockProxyResolver); + mock_proxy_resolver_ = mock_resolver.get(); + resolver_.reset(new MojoProxyResolverImpl(mock_resolver.Pass())); + } + + CallbackMockProxyResolver* mock_proxy_resolver_; + + scoped_ptr<interfaces::ProxyResolver> resolver_; +}; + +TEST_F(MojoProxyResolverImplTest, GetProxyForUrl) { + interfaces::ProxyResolverRequestClientPtr client_ptr; + TestRequestClient client(mojo::GetProxy(&client_ptr)); + + resolver_->GetProxyForUrl("http://example.com", client_ptr.Pass()); + ASSERT_EQ(1u, mock_proxy_resolver_->pending_requests().size()); + scoped_refptr<MockAsyncProxyResolverBase::Request> request = + mock_proxy_resolver_->pending_requests()[0]; + EXPECT_EQ(GURL("http://example.com"), request->url()); + request->results()->UsePacString( + "PROXY proxy.example.com:1; " + "SOCKS4 socks4.example.com:2; " + "SOCKS5 socks5.example.com:3; " + "HTTPS https.example.com:4; " + "QUIC quic.example.com:65000; " + "DIRECT"); + request->CompleteNow(OK); + client.WaitForResult(); + + EXPECT_EQ(net::OK, client.error()); + std::vector<net::ProxyServer> servers = + client.results().To<std::vector<net::ProxyServer>>(); + ASSERT_EQ(6u, servers.size()); + EXPECT_EQ(ProxyServer::SCHEME_HTTP, servers[0].scheme()); + EXPECT_EQ("proxy.example.com", servers[0].host_port_pair().host()); + EXPECT_EQ(1, servers[0].host_port_pair().port()); + + EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, servers[1].scheme()); + EXPECT_EQ("socks4.example.com", servers[1].host_port_pair().host()); + EXPECT_EQ(2, servers[1].host_port_pair().port()); + + EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, servers[2].scheme()); + EXPECT_EQ("socks5.example.com", servers[2].host_port_pair().host()); + EXPECT_EQ(3, servers[2].host_port_pair().port()); + + EXPECT_EQ(ProxyServer::SCHEME_HTTPS, servers[3].scheme()); + EXPECT_EQ("https.example.com", servers[3].host_port_pair().host()); + EXPECT_EQ(4, servers[3].host_port_pair().port()); + + EXPECT_EQ(ProxyServer::SCHEME_QUIC, servers[4].scheme()); + EXPECT_EQ("quic.example.com", servers[4].host_port_pair().host()); + EXPECT_EQ(65000, servers[4].host_port_pair().port()); + + EXPECT_EQ(ProxyServer::SCHEME_DIRECT, servers[5].scheme()); +} + +TEST_F(MojoProxyResolverImplTest, GetProxyForUrlSynchronous) { + interfaces::ProxyResolverRequestClientPtr client_ptr; + TestRequestClient client(mojo::GetProxy(&client_ptr)); + + ProxyInfo result; + result.UsePacString("DIRECT"); + mock_proxy_resolver_->ReturnProxySynchronously(result); + resolver_->GetProxyForUrl("http://example.com", client_ptr.Pass()); + ASSERT_EQ(0u, mock_proxy_resolver_->pending_requests().size()); + client.WaitForResult(); + + EXPECT_EQ(net::OK, client.error()); + std::vector<net::ProxyServer> proxy_servers = + client.results().To<std::vector<net::ProxyServer>>(); + ASSERT_EQ(1u, proxy_servers.size()); + net::ProxyServer& server = proxy_servers[0]; + EXPECT_TRUE(server.is_direct()); +} + +TEST_F(MojoProxyResolverImplTest, GetProxyForUrlFailure) { + interfaces::ProxyResolverRequestClientPtr client_ptr; + TestRequestClient client(mojo::GetProxy(&client_ptr)); + + resolver_->GetProxyForUrl("http://example.com", client_ptr.Pass()); + ASSERT_EQ(1u, mock_proxy_resolver_->pending_requests().size()); + scoped_refptr<MockAsyncProxyResolverBase::Request> request = + mock_proxy_resolver_->pending_requests()[0]; + EXPECT_EQ(GURL("http://example.com"), request->url()); + request->CompleteNow(ERR_FAILED); + client.WaitForResult(); + + EXPECT_EQ(ERR_FAILED, client.error()); + std::vector<net::ProxyServer> proxy_servers = + client.results().To<std::vector<net::ProxyServer>>(); + EXPECT_TRUE(proxy_servers.empty()); +} + +TEST_F(MojoProxyResolverImplTest, GetProxyForUrlMultiple) { + interfaces::ProxyResolverRequestClientPtr client_ptr1; + TestRequestClient client1(mojo::GetProxy(&client_ptr1)); + interfaces::ProxyResolverRequestClientPtr client_ptr2; + TestRequestClient client2(mojo::GetProxy(&client_ptr2)); + + resolver_->GetProxyForUrl("http://example.com", client_ptr1.Pass()); + resolver_->GetProxyForUrl("https://example.com", client_ptr2.Pass()); + ASSERT_EQ(2u, mock_proxy_resolver_->pending_requests().size()); + scoped_refptr<MockAsyncProxyResolverBase::Request> request1 = + mock_proxy_resolver_->pending_requests()[0]; + EXPECT_EQ(GURL("http://example.com"), request1->url()); + scoped_refptr<MockAsyncProxyResolverBase::Request> request2 = + mock_proxy_resolver_->pending_requests()[1]; + EXPECT_EQ(GURL("https://example.com"), request2->url()); + request1->results()->UsePacString("HTTPS proxy.example.com:12345"); + request1->CompleteNow(OK); + request2->results()->UsePacString("SOCKS5 another-proxy.example.com:6789"); + request2->CompleteNow(OK); + client1.WaitForResult(); + client2.WaitForResult(); + + EXPECT_EQ(net::OK, client1.error()); + std::vector<net::ProxyServer> proxy_servers1 = + client1.results().To<std::vector<net::ProxyServer>>(); + ASSERT_EQ(1u, proxy_servers1.size()); + net::ProxyServer& server1 = proxy_servers1[0]; + EXPECT_EQ(ProxyServer::SCHEME_HTTPS, server1.scheme()); + EXPECT_EQ("proxy.example.com", server1.host_port_pair().host()); + EXPECT_EQ(12345, server1.host_port_pair().port()); + + EXPECT_EQ(net::OK, client2.error()); + std::vector<net::ProxyServer> proxy_servers2 = + client2.results().To<std::vector<net::ProxyServer>>(); + ASSERT_EQ(1u, proxy_servers1.size()); + net::ProxyServer& server2 = proxy_servers2[0]; + EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, server2.scheme()); + EXPECT_EQ("another-proxy.example.com", server2.host_port_pair().host()); + EXPECT_EQ(6789, server2.host_port_pair().port()); +} + +TEST_F(MojoProxyResolverImplTest, SetPacScript) { + SetPacScriptClient client; + + resolver_->SetPacScript("pac script", client.CreateCallback()); + MockAsyncProxyResolverBase::SetPacScriptRequest* request = + mock_proxy_resolver_->pending_set_pac_script_request(); + ASSERT_TRUE(request); + EXPECT_EQ("pac script", base::UTF16ToUTF8(request->script_data()->utf16())); + request->CompleteNow(OK); + EXPECT_EQ(OK, client.error()); +} + +TEST_F(MojoProxyResolverImplTest, SetPacScriptSynchronous) { + SetPacScriptClient client; + + mock_proxy_resolver_->CompleteSetPacScriptSynchronously(); + resolver_->SetPacScript("pac script", client.CreateCallback()); + EXPECT_FALSE(mock_proxy_resolver_->pending_set_pac_script_request()); + EXPECT_EQ(OK, client.error()); +} + +TEST_F(MojoProxyResolverImplTest, SetPacScriptMultiple) { + SetPacScriptClient client1; + SetPacScriptClient client2; + + resolver_->SetPacScript("pac script", client1.CreateCallback()); + resolver_->SetPacScript("a different pac script", client2.CreateCallback()); + MockAsyncProxyResolverBase::SetPacScriptRequest* request = + mock_proxy_resolver_->pending_set_pac_script_request(); + ASSERT_TRUE(request); + EXPECT_EQ("pac script", base::UTF16ToUTF8(request->script_data()->utf16())); + request->CompleteNow(OK); + EXPECT_EQ(OK, client1.error()); + + request = mock_proxy_resolver_->pending_set_pac_script_request(); + ASSERT_TRUE(request); + EXPECT_EQ("a different pac script", + base::UTF16ToUTF8(request->script_data()->utf16())); + request->CompleteNow(ERR_PAC_SCRIPT_FAILED); + EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, client2.error()); +} + +TEST_F(MojoProxyResolverImplTest, DestroyClient) { + interfaces::ProxyResolverRequestClientPtr client_ptr; + scoped_ptr<TestRequestClient> client( + new TestRequestClient(mojo::GetProxy(&client_ptr))); + + resolver_->GetProxyForUrl("http://example.com", client_ptr.Pass()); + ASSERT_EQ(1u, mock_proxy_resolver_->pending_requests().size()); + scoped_refptr<MockAsyncProxyResolverBase::Request> request = + mock_proxy_resolver_->pending_requests()[0]; + EXPECT_EQ(GURL("http://example.com"), request->url()); + request->results()->UsePacString("PROXY proxy.example.com:8080"); + client.reset(); + mock_proxy_resolver_->WaitForCancel(); +} + +TEST_F(MojoProxyResolverImplTest, DestroyService) { + interfaces::ProxyResolverRequestClientPtr client_ptr; + TestRequestClient client(mojo::GetProxy(&client_ptr)); + + resolver_->GetProxyForUrl("http://example.com", client_ptr.Pass()); + resolver_->SetPacScript("pac script", base::Bind(&Fail)); + ASSERT_EQ(1u, mock_proxy_resolver_->pending_requests().size()); + scoped_refptr<MockAsyncProxyResolverBase::Request> request = + mock_proxy_resolver_->pending_requests()[0]; + resolver_.reset(); + client.WaitForConnectionError(); +} + +} // namespace net diff --git a/net/proxy/mojo_type_converters.cc b/net/proxy/mojo_type_converters.cc new file mode 100644 index 0000000..2117853 --- /dev/null +++ b/net/proxy/mojo_type_converters.cc @@ -0,0 +1,83 @@ +// Copyright 2015 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/proxy/mojo_type_converters.h" + +#include "base/logging.h" +#include "net/base/host_port_pair.h" +#include "net/proxy/proxy_server.h" + +namespace net { +namespace { + +interfaces::ProxyScheme ProxySchemeToMojo(ProxyServer::Scheme scheme) { + switch (scheme) { + case ProxyServer::SCHEME_INVALID: + return interfaces::PROXY_SCHEME_INVALID; + case ProxyServer::SCHEME_DIRECT: + return interfaces::PROXY_SCHEME_DIRECT; + case ProxyServer::SCHEME_HTTP: + return interfaces::PROXY_SCHEME_HTTP; + case ProxyServer::SCHEME_SOCKS4: + return interfaces::PROXY_SCHEME_SOCKS4; + case ProxyServer::SCHEME_SOCKS5: + return interfaces::PROXY_SCHEME_SOCKS5; + case ProxyServer::SCHEME_HTTPS: + return interfaces::PROXY_SCHEME_HTTPS; + case ProxyServer::SCHEME_QUIC: + return interfaces::PROXY_SCHEME_QUIC; + } + NOTREACHED(); + return interfaces::PROXY_SCHEME_INVALID; +} + +ProxyServer::Scheme ProxySchemeFromMojo(interfaces::ProxyScheme scheme) { + switch (scheme) { + case interfaces::PROXY_SCHEME_INVALID: + return ProxyServer::SCHEME_INVALID; + case interfaces::PROXY_SCHEME_DIRECT: + return ProxyServer::SCHEME_DIRECT; + case interfaces::PROXY_SCHEME_HTTP: + return ProxyServer::SCHEME_HTTP; + case interfaces::PROXY_SCHEME_SOCKS4: + return ProxyServer::SCHEME_SOCKS4; + case interfaces::PROXY_SCHEME_SOCKS5: + return ProxyServer::SCHEME_SOCKS5; + case interfaces::PROXY_SCHEME_HTTPS: + return ProxyServer::SCHEME_HTTPS; + case interfaces::PROXY_SCHEME_QUIC: + return ProxyServer::SCHEME_QUIC; + } + NOTREACHED(); + return ProxyServer::SCHEME_INVALID; +} + +} // namespace +} // namespace net + +namespace mojo { + +// static +net::interfaces::ProxyServerPtr +TypeConverter<net::interfaces::ProxyServerPtr, net::ProxyServer>::Convert( + const net::ProxyServer& obj) { + net::interfaces::ProxyServerPtr server(net::interfaces::ProxyServer::New()); + server->scheme = net::ProxySchemeToMojo(obj.scheme()); + if (server->scheme != net::interfaces::PROXY_SCHEME_DIRECT && + server->scheme != net::interfaces::PROXY_SCHEME_INVALID) { + server->host = obj.host_port_pair().host(); + server->port = obj.host_port_pair().port(); + } + return server.Pass(); +} + +// static +net::ProxyServer +TypeConverter<net::ProxyServer, net::interfaces::ProxyServerPtr>::Convert( + const net::interfaces::ProxyServerPtr& obj) { + return net::ProxyServer(net::ProxySchemeFromMojo(obj->scheme), + net::HostPortPair(obj->host, obj->port)); +} + +} // namespace mojo diff --git a/net/proxy/mojo_type_converters.h b/net/proxy/mojo_type_converters.h new file mode 100644 index 0000000..3ab9258 --- /dev/null +++ b/net/proxy/mojo_type_converters.h @@ -0,0 +1,29 @@ +// Copyright 2015 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. + +#ifndef NET_PROXY_MOJO_TYPE_CONVERTERS_H_ +#define NET_PROXY_MOJO_TYPE_CONVERTERS_H_ + +#include "net/interfaces/proxy_resolver_service.mojom.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/type_converter.h" + +namespace net { +class ProxyServer; +} + +namespace mojo { + +template <> +struct TypeConverter<net::interfaces::ProxyServerPtr, net::ProxyServer> { + static net::interfaces::ProxyServerPtr Convert(const net::ProxyServer& obj); +}; + +template <> +struct TypeConverter<net::ProxyServer, net::interfaces::ProxyServerPtr> { + static net::ProxyServer Convert(const net::interfaces::ProxyServerPtr& obj); +}; + +} // namespace mojo + +#endif // NET_PROXY_MOJO_TYPE_CONVERTERS_H_ diff --git a/net/proxy/proxy_list.cc b/net/proxy/proxy_list.cc index 4dc4626..524cc15 100644 --- a/net/proxy/proxy_list.cc +++ b/net/proxy/proxy_list.cc @@ -109,6 +109,10 @@ const ProxyServer& ProxyList::Get() const { return proxies_[0]; } +const std::vector<ProxyServer>& ProxyList::GetAll() const { + return proxies_; +} + void ProxyList::SetFromPacString(const std::string& pac_string) { base::StringTokenizer entry_tok(pac_string, ";"); proxies_.clear(); diff --git a/net/proxy/proxy_list.h b/net/proxy/proxy_list.h index d57743e..2bdb12d 100644 --- a/net/proxy/proxy_list.h +++ b/net/proxy/proxy_list.h @@ -63,6 +63,9 @@ class NET_EXPORT_PRIVATE ProxyList { // this if !IsEmpty(). const ProxyServer& Get() const; + // Returns all proxy servers in the list. + const std::vector<ProxyServer>& GetAll() const; + // Sets the list by parsing the pac result |pac_string|. // Some examples for |pac_string|: // "DIRECT" |