| 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 <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 11 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/memory/ptr_util.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_info.h" | 18 #include "net/proxy/proxy_info.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 #include "url/gurl.h" | 22 #include "url/gurl.h" |
| 23 | 23 |
| 24 namespace chromeos { | 24 namespace chromeos { |
| 25 namespace { | |
| 26 | 25 |
| 27 // The ProxyResolverInterface implementation used in production. | 26 struct ProxyResolutionServiceProvider::Request { |
| 28 class ProxyResolverImpl : public ProxyResolverInterface { | |
| 29 public: | 27 public: |
| 30 explicit ProxyResolverImpl(std::unique_ptr<ProxyResolverDelegate> delegate); | 28 Request(const std::string& source_url, |
| 31 ~ProxyResolverImpl() override; | 29 const std::string& signal_interface, |
| 30 const std::string& signal_name, |
| 31 scoped_refptr<net::URLRequestContextGetter> context_getter) |
| 32 : source_url(source_url), |
| 33 signal_interface(signal_interface), |
| 34 signal_name(signal_name), |
| 35 context_getter(context_getter) {} |
| 36 ~Request() = default; |
| 32 | 37 |
| 33 // ProxyResolverInterface override. | 38 // URL being resolved. |
| 34 void ResolveProxy( | 39 const std::string source_url; |
| 35 const std::string& source_url, | 40 |
| 36 const std::string& signal_interface, | 41 // D-Bus interface and name for emitting result signal after resolution is |
| 37 const std::string& signal_name, | 42 // complete. |
| 38 scoped_refptr<dbus::ExportedObject> exported_object) override; | 43 const std::string signal_interface; |
| 44 const std::string signal_name; |
| 45 |
| 46 // Used to get the network context associated with the profile used to run |
| 47 // this request. |
| 48 const scoped_refptr<net::URLRequestContextGetter> context_getter; |
| 49 |
| 50 // ProxyInfo resolved for |source_url|. |
| 51 net::ProxyInfo proxy_info; |
| 52 |
| 53 // Error from proxy resolution. |
| 54 std::string error; |
| 39 | 55 |
| 40 private: | 56 private: |
| 41 // Data being used in one proxy resolution. | 57 DISALLOW_COPY_AND_ASSIGN(Request); |
| 42 struct Request { | |
| 43 public: | |
| 44 Request(const std::string& source_url, | |
| 45 const std::string& signal_interface, | |
| 46 const std::string& signal_name, | |
| 47 scoped_refptr<dbus::ExportedObject> exported_object, | |
| 48 scoped_refptr<net::URLRequestContextGetter> context_getter) | |
| 49 : source_url(source_url), | |
| 50 signal_interface(signal_interface), | |
| 51 signal_name(signal_name), | |
| 52 exported_object(exported_object), | |
| 53 context_getter(context_getter) {} | |
| 54 ~Request() = default; | |
| 55 | |
| 56 // URL being resolved. | |
| 57 const std::string source_url; | |
| 58 | |
| 59 // D-Bus interface, name, and object for emitting result signal after | |
| 60 // resolution is complete. | |
| 61 const std::string signal_interface; | |
| 62 const std::string signal_name; | |
| 63 const scoped_refptr<dbus::ExportedObject> exported_object; | |
| 64 | |
| 65 // Used to get the network context associated with the profile used to run | |
| 66 // this request. | |
| 67 const scoped_refptr<net::URLRequestContextGetter> context_getter; | |
| 68 | |
| 69 // ProxyInfo resolved for |source_url|. | |
| 70 net::ProxyInfo proxy_info; | |
| 71 | |
| 72 // Error from proxy resolution. | |
| 73 std::string error; | |
| 74 | |
| 75 private: | |
| 76 DISALLOW_COPY_AND_ASSIGN(Request); | |
| 77 }; | |
| 78 | |
| 79 // Returns true if the current thread is on the origin thread. | |
| 80 bool OnOriginThread() { return origin_thread_->BelongsToCurrentThread(); } | |
| 81 | |
| 82 // Helper method for ResolveProxy() that runs on network thread. | |
| 83 void ResolveProxyOnNetworkThread(std::unique_ptr<Request> request); | |
| 84 | |
| 85 // Callback on network thread for when net::ProxyService::ResolveProxy() | |
| 86 // completes, synchronously or asynchronously. | |
| 87 void OnResolutionComplete(std::unique_ptr<Request> request, int result); | |
| 88 | |
| 89 // Called on UI thread from OnResolutionCompletion() to pass the resolved | |
| 90 // proxy information to the client over D-Bus. | |
| 91 void NotifyProxyResolved(std::unique_ptr<Request> request); | |
| 92 | |
| 93 std::unique_ptr<ProxyResolverDelegate> delegate_; | |
| 94 scoped_refptr<base::SingleThreadTaskRunner> origin_thread_; | |
| 95 base::WeakPtrFactory<ProxyResolverImpl> weak_ptr_factory_; | |
| 96 | |
| 97 DISALLOW_COPY_AND_ASSIGN(ProxyResolverImpl); | |
| 98 }; | 58 }; |
| 99 | 59 |
| 100 ProxyResolverImpl::ProxyResolverImpl( | 60 ProxyResolutionServiceProvider::ProxyResolutionServiceProvider( |
| 101 std::unique_ptr<ProxyResolverDelegate> delegate) | 61 std::unique_ptr<Delegate> delegate) |
| 102 : delegate_(std::move(delegate)), | 62 : delegate_(std::move(delegate)), |
| 103 origin_thread_(base::ThreadTaskRunnerHandle::Get()), | 63 origin_thread_(base::ThreadTaskRunnerHandle::Get()), |
| 104 weak_ptr_factory_(this) {} | 64 weak_ptr_factory_(this) {} |
| 105 | 65 |
| 106 ProxyResolverImpl::~ProxyResolverImpl() { | 66 ProxyResolutionServiceProvider::~ProxyResolutionServiceProvider() { |
| 107 DCHECK(OnOriginThread()); | 67 DCHECK(OnOriginThread()); |
| 108 } | 68 } |
| 109 | 69 |
| 110 void ProxyResolverImpl::ResolveProxy( | 70 void ProxyResolutionServiceProvider::Start( |
| 111 const std::string& source_url, | |
| 112 const std::string& signal_interface, | |
| 113 const std::string& signal_name, | |
| 114 scoped_refptr<dbus::ExportedObject> exported_object) { | 71 scoped_refptr<dbus::ExportedObject> exported_object) { |
| 115 DCHECK(OnOriginThread()); | 72 DCHECK(OnOriginThread()); |
| 73 exported_object_ = exported_object; |
| 74 VLOG(1) << "ProxyResolutionServiceProvider started"; |
| 75 exported_object_->ExportMethod( |
| 76 kLibCrosServiceInterface, kResolveNetworkProxy, |
| 77 base::Bind(&ProxyResolutionServiceProvider::ResolveProxy, |
| 78 weak_ptr_factory_.GetWeakPtr()), |
| 79 base::Bind(&ProxyResolutionServiceProvider::OnExported, |
| 80 weak_ptr_factory_.GetWeakPtr())); |
| 81 } |
| 82 |
| 83 bool ProxyResolutionServiceProvider::OnOriginThread() { |
| 84 return origin_thread_->BelongsToCurrentThread(); |
| 85 } |
| 86 |
| 87 void ProxyResolutionServiceProvider::OnExported( |
| 88 const std::string& interface_name, |
| 89 const std::string& method_name, |
| 90 bool success) { |
| 91 if (success) |
| 92 VLOG(1) << "Method exported: " << interface_name << "." << method_name; |
| 93 else |
| 94 LOG(ERROR) << "Failed to export " << interface_name << "." << method_name; |
| 95 } |
| 96 |
| 97 void ProxyResolutionServiceProvider::ResolveProxy( |
| 98 dbus::MethodCall* method_call, |
| 99 dbus::ExportedObject::ResponseSender response_sender) { |
| 100 DCHECK(OnOriginThread()); |
| 101 VLOG(1) << "Handling method call: " << method_call->ToString(); |
| 102 // The method call should contain the three string parameters. |
| 103 dbus::MessageReader reader(method_call); |
| 104 std::string source_url; |
| 105 std::string signal_interface; |
| 106 std::string signal_name; |
| 107 if (!reader.PopString(&source_url) || !reader.PopString(&signal_interface) || |
| 108 !reader.PopString(&signal_name)) { |
| 109 LOG(ERROR) << "Unexpected method call: " << method_call->ToString(); |
| 110 response_sender.Run(std::unique_ptr<dbus::Response>()); |
| 111 return; |
| 112 } |
| 116 | 113 |
| 117 scoped_refptr<net::URLRequestContextGetter> context_getter = | 114 scoped_refptr<net::URLRequestContextGetter> context_getter = |
| 118 delegate_->GetRequestContext(); | 115 delegate_->GetRequestContext(); |
| 119 auto request = | 116 auto request = base::MakeUnique<Request>(source_url, signal_interface, |
| 120 base::MakeUnique<Request>(source_url, signal_interface, signal_name, | 117 signal_name, context_getter); |
| 121 exported_object, context_getter); | |
| 122 | 118 |
| 123 // This would ideally call PostTaskAndReply() instead of PostTask(), but | 119 // This would ideally call PostTaskAndReply() instead of PostTask(), but |
| 124 // ResolveProxyOnNetworkThread()'s call to net::ProxyService::ResolveProxy() | 120 // ResolveProxyOnNetworkThread()'s call to net::ProxyService::ResolveProxy() |
| 125 // can result in an asynchronous lookup, in which case the result won't be | 121 // can result in an asynchronous lookup, in which case the result won't be |
| 126 // available immediately. | 122 // available immediately. |
| 127 context_getter->GetNetworkTaskRunner()->PostTask( | 123 context_getter->GetNetworkTaskRunner()->PostTask( |
| 128 FROM_HERE, base::Bind(&ProxyResolverImpl::ResolveProxyOnNetworkThread, | 124 FROM_HERE, |
| 129 weak_ptr_factory_.GetWeakPtr(), | 125 base::Bind(&ProxyResolutionServiceProvider::ResolveProxyOnNetworkThread, |
| 130 base::Passed(std::move(request)))); | 126 weak_ptr_factory_.GetWeakPtr(), |
| 127 base::Passed(std::move(request)))); |
| 128 |
| 129 // Send an empty response for now. We'll send a signal once the network proxy |
| 130 // resolution is completed. |
| 131 response_sender.Run(dbus::Response::FromMethodCall(method_call)); |
| 131 } | 132 } |
| 132 | 133 |
| 133 void ProxyResolverImpl::ResolveProxyOnNetworkThread( | 134 void ProxyResolutionServiceProvider::ResolveProxyOnNetworkThread( |
| 134 std::unique_ptr<Request> request) { | 135 std::unique_ptr<Request> request) { |
| 135 DCHECK(request->context_getter->GetNetworkTaskRunner() | 136 DCHECK(request->context_getter->GetNetworkTaskRunner() |
| 136 ->BelongsToCurrentThread()); | 137 ->BelongsToCurrentThread()); |
| 137 | 138 |
| 138 net::ProxyService* proxy_service = | 139 net::ProxyService* proxy_service = |
| 139 request->context_getter->GetURLRequestContext()->proxy_service(); | 140 request->context_getter->GetURLRequestContext()->proxy_service(); |
| 140 if (!proxy_service) { | 141 if (!proxy_service) { |
| 141 request->error = "No proxy service in chrome"; | 142 request->error = "No proxy service in chrome"; |
| 142 OnResolutionComplete(std::move(request), net::ERR_UNEXPECTED); | 143 OnResolutionComplete(std::move(request), net::ERR_UNEXPECTED); |
| 143 return; | 144 return; |
| 144 } | 145 } |
| 145 | 146 |
| 146 Request* request_ptr = request.get(); | 147 Request* request_ptr = request.get(); |
| 147 net::CompletionCallback callback = base::Bind( | 148 net::CompletionCallback callback = base::Bind( |
| 148 &ProxyResolverImpl::OnResolutionComplete, weak_ptr_factory_.GetWeakPtr(), | 149 &ProxyResolutionServiceProvider::OnResolutionComplete, |
| 149 base::Passed(std::move(request))); | 150 weak_ptr_factory_.GetWeakPtr(), base::Passed(std::move(request))); |
| 150 | 151 |
| 151 VLOG(1) << "Starting network proxy resolution for " | 152 VLOG(1) << "Starting network proxy resolution for " |
| 152 << request_ptr->source_url; | 153 << request_ptr->source_url; |
| 153 const int result = | 154 const int result = |
| 154 delegate_->ResolveProxy(proxy_service, GURL(request_ptr->source_url), | 155 delegate_->ResolveProxy(proxy_service, GURL(request_ptr->source_url), |
| 155 &request_ptr->proxy_info, callback); | 156 &request_ptr->proxy_info, callback); |
| 156 if (result != net::ERR_IO_PENDING) { | 157 if (result != net::ERR_IO_PENDING) { |
| 157 VLOG(1) << "Network proxy resolution completed synchronously."; | 158 VLOG(1) << "Network proxy resolution completed synchronously."; |
| 158 callback.Run(result); | 159 callback.Run(result); |
| 159 } | 160 } |
| 160 } | 161 } |
| 161 | 162 |
| 162 void ProxyResolverImpl::OnResolutionComplete(std::unique_ptr<Request> request, | 163 void ProxyResolutionServiceProvider::OnResolutionComplete( |
| 163 int result) { | 164 std::unique_ptr<Request> request, |
| 165 int result) { |
| 164 DCHECK(request->context_getter->GetNetworkTaskRunner() | 166 DCHECK(request->context_getter->GetNetworkTaskRunner() |
| 165 ->BelongsToCurrentThread()); | 167 ->BelongsToCurrentThread()); |
| 166 | 168 |
| 167 if (request->error.empty() && result != net::OK) | 169 if (request->error.empty() && result != net::OK) |
| 168 request->error = net::ErrorToString(result); | 170 request->error = net::ErrorToString(result); |
| 169 | 171 |
| 170 origin_thread_->PostTask(FROM_HERE, | 172 origin_thread_->PostTask( |
| 171 base::Bind(&ProxyResolverImpl::NotifyProxyResolved, | 173 FROM_HERE, |
| 172 weak_ptr_factory_.GetWeakPtr(), | 174 base::Bind(&ProxyResolutionServiceProvider::NotifyProxyResolved, |
| 173 base::Passed(std::move(request)))); | 175 weak_ptr_factory_.GetWeakPtr(), |
| 176 base::Passed(std::move(request)))); |
| 174 } | 177 } |
| 175 | 178 |
| 176 void ProxyResolverImpl::NotifyProxyResolved(std::unique_ptr<Request> request) { | 179 void ProxyResolutionServiceProvider::NotifyProxyResolved( |
| 180 std::unique_ptr<Request> request) { |
| 177 DCHECK(OnOriginThread()); | 181 DCHECK(OnOriginThread()); |
| 178 | 182 |
| 179 // Send a signal to the client. | 183 // Send a signal to the client. |
| 180 dbus::Signal signal(request->signal_interface, request->signal_name); | 184 dbus::Signal signal(request->signal_interface, request->signal_name); |
| 181 dbus::MessageWriter writer(&signal); | 185 dbus::MessageWriter writer(&signal); |
| 182 writer.AppendString(request->source_url); | 186 writer.AppendString(request->source_url); |
| 183 writer.AppendString(request->proxy_info.ToPacString()); | 187 writer.AppendString(request->proxy_info.ToPacString()); |
| 184 writer.AppendString(request->error); | 188 writer.AppendString(request->error); |
| 185 request->exported_object->SendSignal(&signal); | 189 exported_object_->SendSignal(&signal); |
| 186 VLOG(1) << "Sending signal: " << signal.ToString(); | 190 VLOG(1) << "Sending signal: " << signal.ToString(); |
| 187 } | 191 } |
| 188 | 192 |
| 189 } // namespace | |
| 190 | |
| 191 ProxyResolutionServiceProvider::ProxyResolutionServiceProvider( | |
| 192 ProxyResolverInterface* resolver) | |
| 193 : resolver_(resolver), | |
| 194 origin_thread_(base::ThreadTaskRunnerHandle::Get()), | |
| 195 weak_ptr_factory_(this) { | |
| 196 } | |
| 197 | |
| 198 ProxyResolutionServiceProvider::~ProxyResolutionServiceProvider() = default; | |
| 199 | |
| 200 void ProxyResolutionServiceProvider::Start( | |
| 201 scoped_refptr<dbus::ExportedObject> exported_object) { | |
| 202 DCHECK(OnOriginThread()); | |
| 203 exported_object_ = exported_object; | |
| 204 VLOG(1) << "ProxyResolutionServiceProvider started"; | |
| 205 exported_object_->ExportMethod( | |
| 206 kLibCrosServiceInterface, | |
| 207 kResolveNetworkProxy, | |
| 208 // Weak pointers can only bind to methods without return values, | |
| 209 // hence we cannot bind ResolveProxyInternal here. Instead we use a | |
| 210 // static function to solve this problem. | |
| 211 base::Bind(&ProxyResolutionServiceProvider::CallResolveProxyHandler, | |
| 212 weak_ptr_factory_.GetWeakPtr()), | |
| 213 base::Bind(&ProxyResolutionServiceProvider::OnExported, | |
| 214 weak_ptr_factory_.GetWeakPtr())); | |
| 215 } | |
| 216 | |
| 217 void ProxyResolutionServiceProvider::OnExported( | |
| 218 const std::string& interface_name, | |
| 219 const std::string& method_name, | |
| 220 bool success) { | |
| 221 if (!success) { | |
| 222 LOG(ERROR) << "Failed to export " << interface_name << "." | |
| 223 << method_name; | |
| 224 } else { | |
| 225 VLOG(1) << "Method exported: " << interface_name << "." << method_name; | |
| 226 } | |
| 227 } | |
| 228 | |
| 229 bool ProxyResolutionServiceProvider::OnOriginThread() { | |
| 230 return origin_thread_->BelongsToCurrentThread(); | |
| 231 } | |
| 232 | |
| 233 void ProxyResolutionServiceProvider::ResolveProxyHandler( | |
| 234 dbus::MethodCall* method_call, | |
| 235 dbus::ExportedObject::ResponseSender response_sender) { | |
| 236 DCHECK(OnOriginThread()); | |
| 237 VLOG(1) << "Handing method call: " << method_call->ToString(); | |
| 238 // The method call should contain the three string parameters. | |
| 239 dbus::MessageReader reader(method_call); | |
| 240 std::string source_url; | |
| 241 std::string signal_interface; | |
| 242 std::string signal_name; | |
| 243 if (!reader.PopString(&source_url) || | |
| 244 !reader.PopString(&signal_interface) || | |
| 245 !reader.PopString(&signal_name)) { | |
| 246 LOG(ERROR) << "Unexpected method call: " << method_call->ToString(); | |
| 247 response_sender.Run(std::unique_ptr<dbus::Response>()); | |
| 248 return; | |
| 249 } | |
| 250 | |
| 251 resolver_->ResolveProxy(source_url, | |
| 252 signal_interface, | |
| 253 signal_name, | |
| 254 exported_object_); | |
| 255 | |
| 256 // Send an empty response for now. We'll send a signal once the network proxy | |
| 257 // resolution is completed. | |
| 258 response_sender.Run(dbus::Response::FromMethodCall(method_call)); | |
| 259 } | |
| 260 | |
| 261 // static | |
| 262 void ProxyResolutionServiceProvider::CallResolveProxyHandler( | |
| 263 base::WeakPtr<ProxyResolutionServiceProvider> provider_weak_ptr, | |
| 264 dbus::MethodCall* method_call, | |
| 265 dbus::ExportedObject::ResponseSender response_sender) { | |
| 266 if (!provider_weak_ptr) { | |
| 267 LOG(WARNING) << "Called after the object is deleted"; | |
| 268 response_sender.Run(std::unique_ptr<dbus::Response>()); | |
| 269 return; | |
| 270 } | |
| 271 provider_weak_ptr->ResolveProxyHandler(method_call, response_sender); | |
| 272 } | |
| 273 | |
| 274 ProxyResolutionServiceProvider* ProxyResolutionServiceProvider::Create( | |
| 275 std::unique_ptr<ProxyResolverDelegate> delegate) { | |
| 276 return new ProxyResolutionServiceProvider( | |
| 277 new ProxyResolverImpl(std::move(delegate))); | |
| 278 } | |
| 279 | |
| 280 ProxyResolverInterface::~ProxyResolverInterface() = default; | |
| 281 | |
| 282 } // namespace chromeos | 193 } // namespace chromeos |
| OLD | NEW |