Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chromeos/dbus/services/proxy_resolution_service_provider.h" | 5 #include "chromeos/dbus/services/proxy_resolution_service_provider.h" |
| 6 | 6 |
| 7 #include <string> | |
| 8 #include <utility> | 7 #include <utility> |
| 9 | 8 |
| 10 #include "base/bind.h" | 9 #include "base/bind.h" |
| 11 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 12 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/memory/ptr_util.h" | |
| 13 #include "base/threading/thread_task_runner_handle.h" | 13 #include "base/threading/thread_task_runner_handle.h" |
| 14 #include "dbus/bus.h" | 14 #include "dbus/bus.h" |
| 15 #include "dbus/message.h" | 15 #include "dbus/message.h" |
| 16 #include "net/base/net_errors.h" | 16 #include "net/base/net_errors.h" |
| 17 #include "net/log/net_log_with_source.h" | 17 #include "net/log/net_log_with_source.h" |
| 18 #include "net/proxy/proxy_service.h" | 18 #include "net/proxy/proxy_service.h" |
| 19 #include "net/url_request/url_request_context.h" | 19 #include "net/url_request/url_request_context.h" |
| 20 #include "net/url_request/url_request_context_getter.h" | 20 #include "net/url_request/url_request_context_getter.h" |
| 21 #include "third_party/cros_system_api/dbus/service_constants.h" | 21 #include "third_party/cros_system_api/dbus/service_constants.h" |
| 22 | 22 |
| 23 namespace chromeos { | 23 namespace chromeos { |
| 24 | 24 |
| 25 // The ProxyResolverInterface implementation used in production. | 25 // The ProxyResolverInterface implementation used in production. |
| 26 class ProxyResolverImpl : public ProxyResolverInterface { | 26 class ProxyResolverImpl : public ProxyResolverInterface { |
| 27 public: | 27 public: |
| 28 // Data being used in one proxy resolution. | |
| 29 class Request { | |
|
Daniel Erat
2017/03/22 14:43:43
this is moved to the private section. i also made
| |
| 30 public: | |
| 31 explicit Request(const std::string& source_url) : source_url_(source_url) { | |
| 32 } | |
| 33 | |
| 34 virtual ~Request() {} | |
| 35 | |
| 36 // Callback on IO thread for when net::ProxyService::ResolveProxy | |
| 37 // completes, synchronously or asynchronously. | |
| 38 void OnCompletion(scoped_refptr<base::SingleThreadTaskRunner> origin_thread, | |
| 39 int result) { | |
| 40 // Generate the error message if the error message is not yet set, | |
| 41 // and there was an error. | |
| 42 if (error_.empty() && result != net::OK) | |
| 43 error_ = net::ErrorToString(result); | |
| 44 origin_thread->PostTask(FROM_HERE, notify_task_); | |
| 45 } | |
| 46 | |
| 47 std::string source_url_; // URL being resolved. | |
| 48 net::ProxyInfo proxy_info_; // ProxyInfo resolved for source_url_. | |
| 49 std::string error_; // Error from proxy resolution. | |
| 50 base::Closure notify_task_; // Task to notify of resolution result. | |
| 51 | |
| 52 private: | |
| 53 DISALLOW_COPY_AND_ASSIGN(Request); | |
| 54 }; | |
| 55 | |
| 56 explicit ProxyResolverImpl(std::unique_ptr<ProxyResolverDelegate> delegate) | 28 explicit ProxyResolverImpl(std::unique_ptr<ProxyResolverDelegate> delegate) |
| 57 : delegate_(std::move(delegate)), | 29 : delegate_(std::move(delegate)), |
| 58 origin_thread_(base::ThreadTaskRunnerHandle::Get()), | 30 origin_thread_(base::ThreadTaskRunnerHandle::Get()), |
| 59 weak_ptr_factory_(this) {} | 31 weak_ptr_factory_(this) {} |
| 60 | 32 |
| 61 ~ProxyResolverImpl() override { | 33 ~ProxyResolverImpl() override { |
| 62 DCHECK(OnOriginThread()); | 34 DCHECK(OnOriginThread()); |
| 63 | |
| 64 for (std::set<Request*>::iterator iter = all_requests_.begin(); | |
| 65 iter != all_requests_.end(); ++iter) { | |
| 66 Request* request = *iter; | |
| 67 LOG(WARNING) << "Pending request for " << request->source_url_; | |
| 68 delete request; | |
| 69 } | |
| 70 } | 35 } |
| 71 | 36 |
| 72 // ProxyResolverInterface override. | 37 // ProxyResolverInterface override. |
| 73 void ResolveProxy( | 38 void ResolveProxy( |
|
James Cook
2017/03/22 19:53:20
nit: There's a lot of inline code in these class m
Daniel Erat
2017/03/22 20:11:18
sure, i've moved the implementations out.
| |
| 74 const std::string& source_url, | 39 const std::string& source_url, |
| 75 const std::string& signal_interface, | 40 const std::string& signal_interface, |
| 76 const std::string& signal_name, | 41 const std::string& signal_name, |
| 77 scoped_refptr<dbus::ExportedObject> exported_object) override { | 42 scoped_refptr<dbus::ExportedObject> exported_object) override { |
| 78 DCHECK(OnOriginThread()); | 43 DCHECK(OnOriginThread()); |
| 79 | 44 |
| 80 // Create a request slot for this proxy resolution request. | 45 auto request = base::MakeUnique<Request>(source_url, signal_interface, |
| 81 Request* request = new Request(source_url); | 46 signal_name, exported_object, |
| 82 request->notify_task_ = base::Bind( | 47 delegate_->GetRequestContext()); |
| 83 &ProxyResolverImpl::NotifyProxyResolved, | |
| 84 weak_ptr_factory_.GetWeakPtr(), | |
| 85 signal_interface, | |
| 86 signal_name, | |
| 87 exported_object, | |
| 88 request); | |
| 89 all_requests_.insert(request); | |
| 90 | 48 |
| 91 // GetRequestContext() must be called on UI thread. | 49 // This would ideally call PostTaskAndReply() instead of PostTask(), but |
| 92 scoped_refptr<net::URLRequestContextGetter> getter = | 50 // ResolveProxyInternal()'s call to net::ProxyService::ResolveProxy() can |
| 93 delegate_->GetRequestContext(); | 51 // result in an asynchronous lookup, in which case the result won't be |
| 94 | 52 // available immediately. |
| 95 getter->GetNetworkTaskRunner()->PostTask( | 53 request->context_getter->GetNetworkTaskRunner()->PostTask( |
| 96 FROM_HERE, | 54 FROM_HERE, base::Bind(&ProxyResolverImpl::ResolveProxyInternal, |
| 97 base::Bind(&ProxyResolverImpl::ResolveProxyInternal, | 55 weak_ptr_factory_.GetWeakPtr(), |
| 98 request, | 56 base::Passed(std::move(request)))); |
| 99 origin_thread_, | |
| 100 getter, | |
| 101 exported_object)); | |
| 102 } | 57 } |
| 103 | 58 |
| 104 private: | 59 private: |
| 105 // Helper function for ResolveProxy(). | 60 // Data being used in one proxy resolution. |
| 106 static void ResolveProxyInternal( | 61 struct Request { |
| 107 Request* request, | 62 public: |
| 108 scoped_refptr<base::SingleThreadTaskRunner> origin_thread, | 63 Request(const std::string& source_url, |
| 109 scoped_refptr<net::URLRequestContextGetter> getter, | 64 const std::string& signal_interface, |
| 110 scoped_refptr<dbus::ExportedObject> exported_object) { | 65 const std::string& signal_name, |
| 111 // Make sure we're running on IO thread. | 66 scoped_refptr<dbus::ExportedObject> exported_object, |
| 112 DCHECK(getter->GetNetworkTaskRunner()->BelongsToCurrentThread()); | 67 scoped_refptr<net::URLRequestContextGetter> context_getter) |
| 68 : source_url(source_url), | |
| 69 signal_interface(signal_interface), | |
| 70 signal_name(signal_name), | |
| 71 exported_object(exported_object), | |
| 72 context_getter(context_getter) {} | |
| 73 ~Request() = default; | |
| 113 | 74 |
| 114 // Check if we have the URLRequestContextGetter. | 75 // URL being resolved. |
| 115 if (!getter.get()) { | 76 const std::string source_url; |
|
Daniel Erat
2017/03/22 14:43:43
i don't understand the reason for this check. it's
| |
| 116 request->error_ = "No URLRequestContextGetter"; | 77 |
| 117 request->OnCompletion(origin_thread, net::ERR_UNEXPECTED); | 78 // D-Bus interface, name, and object for emitting result signal after |
| 79 // resolution is complete. | |
| 80 const std::string signal_interface; | |
| 81 const std::string signal_name; | |
| 82 const scoped_refptr<dbus::ExportedObject> exported_object; | |
| 83 | |
| 84 // Used to get the network context associated with the profile used to run | |
| 85 // this request. | |
| 86 const scoped_refptr<net::URLRequestContextGetter> context_getter; | |
| 87 | |
| 88 // ProxyInfo resolved for |source_url|. | |
| 89 net::ProxyInfo proxy_info; | |
| 90 | |
| 91 // Error from proxy resolution. | |
| 92 std::string error; | |
| 93 | |
| 94 private: | |
| 95 DISALLOW_COPY_AND_ASSIGN(Request); | |
| 96 }; | |
| 97 | |
| 98 // Returns true if the current thread is on the origin thread. | |
| 99 bool OnOriginThread() { return origin_thread_->BelongsToCurrentThread(); } | |
| 100 | |
| 101 // Helper method for ResolveProxy() that runs on network thread. | |
| 102 void ResolveProxyInternal(std::unique_ptr<Request> request) { | |
|
James Cook
2017/03/22 19:53:20
nit: Maybe ResolveProxyOnNetworkThread()?
Daniel Erat
2017/03/22 20:11:18
Done.
| |
| 103 DCHECK(request->context_getter->GetNetworkTaskRunner() | |
| 104 ->BelongsToCurrentThread()); | |
| 105 | |
| 106 net::ProxyService* proxy_service = | |
| 107 request->context_getter->GetURLRequestContext()->proxy_service(); | |
| 108 if (!proxy_service) { | |
| 109 request->error = "No proxy service in chrome"; | |
| 110 OnResolutionComplete(std::move(request), net::ERR_UNEXPECTED); | |
| 118 return; | 111 return; |
| 119 } | 112 } |
| 120 | 113 |
| 121 // Retrieve ProxyService from profile's request context. | 114 Request* request_ptr = request.get(); |
| 122 net::ProxyService* proxy_service = | 115 net::CompletionCallback callback = base::Bind( |
| 123 getter->GetURLRequestContext()->proxy_service(); | 116 &ProxyResolverImpl::OnResolutionComplete, |
| 124 if (!proxy_service) { | 117 weak_ptr_factory_.GetWeakPtr(), base::Passed(std::move(request))); |
| 125 request->error_ = "No proxy service in chrome"; | |
| 126 request->OnCompletion(origin_thread, net::ERR_UNEXPECTED); | |
| 127 return; | |
| 128 } | |
| 129 | 118 |
| 130 VLOG(1) << "Starting network proxy resolution for " | 119 VLOG(1) << "Starting network proxy resolution for " |
| 131 << request->source_url_; | 120 << request_ptr->source_url; |
| 132 net::CompletionCallback completion_callback = | |
| 133 base::Bind(&Request::OnCompletion, | |
| 134 base::Unretained(request), | |
| 135 origin_thread); | |
| 136 const int result = proxy_service->ResolveProxy( | 121 const int result = proxy_service->ResolveProxy( |
| 137 GURL(request->source_url_), std::string(), &request->proxy_info_, | 122 GURL(request_ptr->source_url), std::string(), &request_ptr->proxy_info, |
|
Daniel Erat
2017/03/22 14:43:43
i mentioned it in an earlier patch set, but i thin
| |
| 138 completion_callback, NULL, NULL, net::NetLogWithSource()); | 123 callback, nullptr, nullptr, net::NetLogWithSource()); |
| 139 if (result != net::ERR_IO_PENDING) { | 124 if (result != net::ERR_IO_PENDING) { |
| 140 VLOG(1) << "Network proxy resolution completed synchronously."; | 125 VLOG(1) << "Network proxy resolution completed synchronously."; |
| 141 completion_callback.Run(result); | 126 callback.Run(result); |
| 142 } | 127 } |
| 143 } | 128 } |
| 144 | 129 |
| 145 // Called on UI thread as task posted from Request::OnCompletion on IO | 130 // Callback on network thread for when net::ProxyService::ResolveProxy() |
| 146 // thread. | 131 // completes, synchronously or asynchronously. |
| 147 void NotifyProxyResolved( | 132 void OnResolutionComplete(std::unique_ptr<Request> request, int result) { |
| 148 const std::string& signal_interface, | 133 DCHECK(request->context_getter->GetNetworkTaskRunner() |
| 149 const std::string& signal_name, | 134 ->BelongsToCurrentThread()); |
| 150 scoped_refptr<dbus::ExportedObject> exported_object, | 135 |
| 151 Request* request) { | 136 if (request->error.empty() && result != net::OK) |
| 137 request->error = net::ErrorToString(result); | |
| 138 | |
| 139 origin_thread_->PostTask(FROM_HERE, | |
| 140 base::Bind(&ProxyResolverImpl::NotifyProxyResolved, | |
| 141 weak_ptr_factory_.GetWeakPtr(), | |
| 142 base::Passed(std::move(request)))); | |
| 143 } | |
| 144 | |
| 145 // Called on UI thread from OnResolutionCompletion(). | |
| 146 void NotifyProxyResolved(std::unique_ptr<Request> request) { | |
| 152 DCHECK(OnOriginThread()); | 147 DCHECK(OnOriginThread()); |
| 153 | 148 |
| 154 // Send a signal to the client. | 149 // Send a signal to the client. |
| 155 dbus::Signal signal(signal_interface, signal_name); | 150 dbus::Signal signal(request->signal_interface, request->signal_name); |
| 156 dbus::MessageWriter writer(&signal); | 151 dbus::MessageWriter writer(&signal); |
| 157 writer.AppendString(request->source_url_); | 152 writer.AppendString(request->source_url); |
| 158 writer.AppendString(request->proxy_info_.ToPacString()); | 153 writer.AppendString(request->proxy_info.ToPacString()); |
| 159 writer.AppendString(request->error_); | 154 writer.AppendString(request->error); |
| 160 exported_object->SendSignal(&signal); | 155 request->exported_object->SendSignal(&signal); |
| 161 VLOG(1) << "Sending signal: " << signal.ToString(); | 156 VLOG(1) << "Sending signal: " << signal.ToString(); |
| 162 | |
| 163 std::set<Request*>::iterator iter = all_requests_.find(request); | |
| 164 if (iter == all_requests_.end()) { | |
| 165 LOG(ERROR) << "can't find request slot(" << request->source_url_ | |
| 166 << ") in proxy-resolution queue"; | |
| 167 } else { | |
| 168 all_requests_.erase(iter); | |
| 169 } | |
| 170 delete request; | |
| 171 } | |
| 172 | |
| 173 // Returns true if the current thread is on the origin thread. | |
| 174 bool OnOriginThread() { | |
| 175 return origin_thread_->BelongsToCurrentThread(); | |
| 176 } | 157 } |
| 177 | 158 |
| 178 std::unique_ptr<ProxyResolverDelegate> delegate_; | 159 std::unique_ptr<ProxyResolverDelegate> delegate_; |
| 179 scoped_refptr<base::SingleThreadTaskRunner> origin_thread_; | 160 scoped_refptr<base::SingleThreadTaskRunner> origin_thread_; |
| 180 std::set<Request*> all_requests_; | |
| 181 base::WeakPtrFactory<ProxyResolverImpl> weak_ptr_factory_; | 161 base::WeakPtrFactory<ProxyResolverImpl> weak_ptr_factory_; |
| 182 | 162 |
| 183 DISALLOW_COPY_AND_ASSIGN(ProxyResolverImpl); | 163 DISALLOW_COPY_AND_ASSIGN(ProxyResolverImpl); |
| 184 }; | 164 }; |
| 185 | 165 |
| 186 ProxyResolutionServiceProvider::ProxyResolutionServiceProvider( | 166 ProxyResolutionServiceProvider::ProxyResolutionServiceProvider( |
| 187 ProxyResolverInterface* resolver) | 167 ProxyResolverInterface* resolver) |
| 188 : resolver_(resolver), | 168 : resolver_(resolver), |
| 189 origin_thread_(base::ThreadTaskRunnerHandle::Get()), | 169 origin_thread_(base::ThreadTaskRunnerHandle::Get()), |
| 190 weak_ptr_factory_(this) { | 170 weak_ptr_factory_(this) { |
| 191 } | 171 } |
| 192 | 172 |
| 193 ProxyResolutionServiceProvider::~ProxyResolutionServiceProvider() { | 173 ProxyResolutionServiceProvider::~ProxyResolutionServiceProvider() = default; |
| 194 } | |
| 195 | 174 |
| 196 void ProxyResolutionServiceProvider::Start( | 175 void ProxyResolutionServiceProvider::Start( |
| 197 scoped_refptr<dbus::ExportedObject> exported_object) { | 176 scoped_refptr<dbus::ExportedObject> exported_object) { |
| 198 DCHECK(OnOriginThread()); | 177 DCHECK(OnOriginThread()); |
| 199 exported_object_ = exported_object; | 178 exported_object_ = exported_object; |
| 200 VLOG(1) << "ProxyResolutionServiceProvider started"; | 179 VLOG(1) << "ProxyResolutionServiceProvider started"; |
| 201 exported_object_->ExportMethod( | 180 exported_object_->ExportMethod( |
| 202 kLibCrosServiceInterface, | 181 kLibCrosServiceInterface, |
| 203 kResolveNetworkProxy, | 182 kResolveNetworkProxy, |
| 204 // Weak pointers can only bind to methods without return values, | 183 // Weak pointers can only bind to methods without return values, |
| 205 // hence we cannot bind ResolveProxyInternal here. Instead we use a | 184 // hence we cannot bind ResolveProxyInternal here. Instead we use a |
| 206 // static function to solve this problem. | 185 // static function to solve this problem. |
| 207 base::Bind(&ProxyResolutionServiceProvider::CallResolveProxyHandler, | 186 base::Bind(&ProxyResolutionServiceProvider::CallResolveProxyHandler, |
| 208 weak_ptr_factory_.GetWeakPtr()), | 187 weak_ptr_factory_.GetWeakPtr()), |
| 209 base::Bind(&ProxyResolutionServiceProvider::OnExported, | 188 base::Bind(&ProxyResolutionServiceProvider::OnExported, |
| 210 weak_ptr_factory_.GetWeakPtr())); | 189 weak_ptr_factory_.GetWeakPtr())); |
| 211 } | 190 } |
| 212 | 191 |
| 213 void ProxyResolutionServiceProvider::OnExported( | 192 void ProxyResolutionServiceProvider::OnExported( |
| 214 const std::string& interface_name, | 193 const std::string& interface_name, |
| 215 const std::string& method_name, | 194 const std::string& method_name, |
| 216 bool success) { | 195 bool success) { |
| 217 if (!success) { | 196 if (!success) { |
| 218 LOG(ERROR) << "Failed to export " << interface_name << "." | 197 LOG(ERROR) << "Failed to export " << interface_name << "." |
| 219 << method_name; | 198 << method_name; |
| 199 } else { | |
| 200 VLOG(1) << "Method exported: " << interface_name << "." << method_name; | |
| 220 } | 201 } |
| 221 VLOG(1) << "Method exported: " << interface_name << "." << method_name; | |
| 222 } | 202 } |
| 223 | 203 |
| 224 bool ProxyResolutionServiceProvider::OnOriginThread() { | 204 bool ProxyResolutionServiceProvider::OnOriginThread() { |
| 225 return origin_thread_->BelongsToCurrentThread(); | 205 return origin_thread_->BelongsToCurrentThread(); |
| 226 } | 206 } |
| 227 | 207 |
| 228 void ProxyResolutionServiceProvider::ResolveProxyHandler( | 208 void ProxyResolutionServiceProvider::ResolveProxyHandler( |
| 229 dbus::MethodCall* method_call, | 209 dbus::MethodCall* method_call, |
| 230 dbus::ExportedObject::ResponseSender response_sender) { | 210 dbus::ExportedObject::ResponseSender response_sender) { |
| 231 DCHECK(OnOriginThread()); | 211 DCHECK(OnOriginThread()); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 265 } | 245 } |
| 266 provider_weak_ptr->ResolveProxyHandler(method_call, response_sender); | 246 provider_weak_ptr->ResolveProxyHandler(method_call, response_sender); |
| 267 } | 247 } |
| 268 | 248 |
| 269 ProxyResolutionServiceProvider* ProxyResolutionServiceProvider::Create( | 249 ProxyResolutionServiceProvider* ProxyResolutionServiceProvider::Create( |
| 270 std::unique_ptr<ProxyResolverDelegate> delegate) { | 250 std::unique_ptr<ProxyResolverDelegate> delegate) { |
| 271 return new ProxyResolutionServiceProvider( | 251 return new ProxyResolutionServiceProvider( |
| 272 new ProxyResolverImpl(std::move(delegate))); | 252 new ProxyResolverImpl(std::move(delegate))); |
| 273 } | 253 } |
| 274 | 254 |
| 275 ProxyResolverInterface::~ProxyResolverInterface() { | 255 ProxyResolverInterface::~ProxyResolverInterface() = default; |
| 276 } | |
| 277 | 256 |
| 278 } // namespace chromeos | 257 } // namespace chromeos |
| OLD | NEW |