Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(250)

Side by Side Diff: chromeos/dbus/services/proxy_resolution_service_provider.cc

Issue 2763963003: chromeos: Simplify D-Bus proxy resolution service code. (Closed)
Patch Set: fix crash Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 namespace {
24 25
25 // The ProxyResolverInterface implementation used in production. 26 // The ProxyResolverInterface implementation used in production.
26 class ProxyResolverImpl : public ProxyResolverInterface { 27 class ProxyResolverImpl : public ProxyResolverInterface {
27 public: 28 public:
28 // Data being used in one proxy resolution. 29 explicit ProxyResolverImpl(std::unique_ptr<ProxyResolverDelegate> delegate);
29 class Request { 30 ~ProxyResolverImpl() override;
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)
57 : delegate_(std::move(delegate)),
58 origin_thread_(base::ThreadTaskRunnerHandle::Get()),
59 weak_ptr_factory_(this) {}
60
61 ~ProxyResolverImpl() override {
62 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 }
71 31
72 // ProxyResolverInterface override. 32 // ProxyResolverInterface override.
73 void ResolveProxy( 33 void ResolveProxy(
74 const std::string& source_url, 34 const std::string& source_url,
75 const std::string& signal_interface, 35 const std::string& signal_interface,
76 const std::string& signal_name, 36 const std::string& signal_name,
77 scoped_refptr<dbus::ExportedObject> exported_object) override { 37 scoped_refptr<dbus::ExportedObject> exported_object) override;
78 DCHECK(OnOriginThread());
79
80 // Create a request slot for this proxy resolution request.
81 Request* request = new Request(source_url);
82 request->notify_task_ = base::Bind(
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
91 // GetRequestContext() must be called on UI thread.
92 scoped_refptr<net::URLRequestContextGetter> getter =
93 delegate_->GetRequestContext();
94
95 getter->GetNetworkTaskRunner()->PostTask(
96 FROM_HERE,
97 base::Bind(&ProxyResolverImpl::ResolveProxyInternal,
98 request,
99 origin_thread_,
100 getter,
101 exported_object));
102 }
103 38
104 private: 39 private:
105 // Helper function for ResolveProxy(). 40 // Data being used in one proxy resolution.
106 static void ResolveProxyInternal( 41 struct Request {
107 Request* request, 42 public:
108 scoped_refptr<base::SingleThreadTaskRunner> origin_thread, 43 Request(const std::string& source_url,
109 scoped_refptr<net::URLRequestContextGetter> getter, 44 const std::string& signal_interface,
110 scoped_refptr<dbus::ExportedObject> exported_object) { 45 const std::string& signal_name,
111 // Make sure we're running on IO thread. 46 scoped_refptr<dbus::ExportedObject> exported_object,
112 DCHECK(getter->GetNetworkTaskRunner()->BelongsToCurrentThread()); 47 scoped_refptr<net::URLRequestContextGetter> context_getter)
48 : source_url(source_url),
49 signal_interface(signal_interface),
50 signal_name(signal_name),
51 exported_object(exported_object),
52 context_getter(context_getter) {}
53 ~Request() = default;
113 54
114 // Check if we have the URLRequestContextGetter. 55 // URL being resolved.
115 if (!getter.get()) { 56 const std::string source_url;
116 request->error_ = "No URLRequestContextGetter";
117 request->OnCompletion(origin_thread, net::ERR_UNEXPECTED);
118 return;
119 }
120 57
121 // Retrieve ProxyService from profile's request context. 58 // D-Bus interface, name, and object for emitting result signal after
122 net::ProxyService* proxy_service = 59 // resolution is complete.
123 getter->GetURLRequestContext()->proxy_service(); 60 const std::string signal_interface;
124 if (!proxy_service) { 61 const std::string signal_name;
125 request->error_ = "No proxy service in chrome"; 62 const scoped_refptr<dbus::ExportedObject> exported_object;
126 request->OnCompletion(origin_thread, net::ERR_UNEXPECTED);
127 return;
128 }
129 63
130 VLOG(1) << "Starting network proxy resolution for " 64 // Used to get the network context associated with the profile used to run
131 << request->source_url_; 65 // this request.
132 net::CompletionCallback completion_callback = 66 const scoped_refptr<net::URLRequestContextGetter> context_getter;
133 base::Bind(&Request::OnCompletion,
134 base::Unretained(request),
135 origin_thread);
136 const int result = proxy_service->ResolveProxy(
137 GURL(request->source_url_), std::string(), &request->proxy_info_,
138 completion_callback, NULL, NULL, net::NetLogWithSource());
139 if (result != net::ERR_IO_PENDING) {
140 VLOG(1) << "Network proxy resolution completed synchronously.";
141 completion_callback.Run(result);
142 }
143 }
144 67
145 // Called on UI thread as task posted from Request::OnCompletion on IO 68 // ProxyInfo resolved for |source_url|.
146 // thread. 69 net::ProxyInfo proxy_info;
147 void NotifyProxyResolved(
148 const std::string& signal_interface,
149 const std::string& signal_name,
150 scoped_refptr<dbus::ExportedObject> exported_object,
151 Request* request) {
152 DCHECK(OnOriginThread());
153 70
154 // Send a signal to the client. 71 // Error from proxy resolution.
155 dbus::Signal signal(signal_interface, signal_name); 72 std::string error;
156 dbus::MessageWriter writer(&signal);
157 writer.AppendString(request->source_url_);
158 writer.AppendString(request->proxy_info_.ToPacString());
159 writer.AppendString(request->error_);
160 exported_object->SendSignal(&signal);
161 VLOG(1) << "Sending signal: " << signal.ToString();
162 73
163 std::set<Request*>::iterator iter = all_requests_.find(request); 74 private:
164 if (iter == all_requests_.end()) { 75 DISALLOW_COPY_AND_ASSIGN(Request);
165 LOG(ERROR) << "can't find request slot(" << request->source_url_ 76 };
166 << ") in proxy-resolution queue";
167 } else {
168 all_requests_.erase(iter);
169 }
170 delete request;
171 }
172 77
173 // Returns true if the current thread is on the origin thread. 78 // Returns true if the current thread is on the origin thread.
174 bool OnOriginThread() { 79 bool OnOriginThread() { return origin_thread_->BelongsToCurrentThread(); }
175 return origin_thread_->BelongsToCurrentThread(); 80
176 } 81 // Helper method for ResolveProxy() that runs on network thread.
82 void ResolveProxyOnNetworkThread(std::unique_ptr<Request> request);
83
84 // Callback on network thread for when net::ProxyService::ResolveProxy()
85 // completes, synchronously or asynchronously.
86 void OnResolutionComplete(std::unique_ptr<Request> request, int result);
87
88 // Called on UI thread from OnResolutionCompletion() to pass the resolved
89 // proxy information to the client over D-Bus.
90 void NotifyProxyResolved(std::unique_ptr<Request> request);
177 91
178 std::unique_ptr<ProxyResolverDelegate> delegate_; 92 std::unique_ptr<ProxyResolverDelegate> delegate_;
179 scoped_refptr<base::SingleThreadTaskRunner> origin_thread_; 93 scoped_refptr<base::SingleThreadTaskRunner> origin_thread_;
180 std::set<Request*> all_requests_;
181 base::WeakPtrFactory<ProxyResolverImpl> weak_ptr_factory_; 94 base::WeakPtrFactory<ProxyResolverImpl> weak_ptr_factory_;
182 95
183 DISALLOW_COPY_AND_ASSIGN(ProxyResolverImpl); 96 DISALLOW_COPY_AND_ASSIGN(ProxyResolverImpl);
184 }; 97 };
185 98
99 ProxyResolverImpl::ProxyResolverImpl(
100 std::unique_ptr<ProxyResolverDelegate> delegate)
101 : delegate_(std::move(delegate)),
102 origin_thread_(base::ThreadTaskRunnerHandle::Get()),
103 weak_ptr_factory_(this) {}
104
105 ProxyResolverImpl::~ProxyResolverImpl() {
106 DCHECK(OnOriginThread());
107 }
108
109 void ProxyResolverImpl::ResolveProxy(
110 const std::string& source_url,
111 const std::string& signal_interface,
112 const std::string& signal_name,
113 scoped_refptr<dbus::ExportedObject> exported_object) {
114 DCHECK(OnOriginThread());
115
116 scoped_refptr<net::URLRequestContextGetter> context_getter =
117 delegate_->GetRequestContext();
118 auto request =
119 base::MakeUnique<Request>(source_url, signal_interface, signal_name,
120 exported_object, context_getter);
121
122 // This would ideally call PostTaskAndReply() instead of PostTask(), but
123 // ResolveProxyOnNetworkThread()'s call to net::ProxyService::ResolveProxy()
124 // can result in an asynchronous lookup, in which case the result won't be
125 // available immediately.
126 context_getter->GetNetworkTaskRunner()->PostTask(
127 FROM_HERE, base::Bind(&ProxyResolverImpl::ResolveProxyOnNetworkThread,
128 weak_ptr_factory_.GetWeakPtr(),
129 base::Passed(std::move(request))));
130 }
131
132 void ProxyResolverImpl::ResolveProxyOnNetworkThread(
133 std::unique_ptr<Request> request) {
134 DCHECK(request->context_getter->GetNetworkTaskRunner()
135 ->BelongsToCurrentThread());
136
137 net::ProxyService* proxy_service =
138 request->context_getter->GetURLRequestContext()->proxy_service();
139 if (!proxy_service) {
140 request->error = "No proxy service in chrome";
141 OnResolutionComplete(std::move(request), net::ERR_UNEXPECTED);
142 return;
143 }
144
145 Request* request_ptr = request.get();
146 net::CompletionCallback callback = base::Bind(
147 &ProxyResolverImpl::OnResolutionComplete, weak_ptr_factory_.GetWeakPtr(),
148 base::Passed(std::move(request)));
149
150 VLOG(1) << "Starting network proxy resolution for "
151 << request_ptr->source_url;
152 const int result = proxy_service->ResolveProxy(
153 GURL(request_ptr->source_url), std::string(), &request_ptr->proxy_info,
154 callback, nullptr, nullptr, net::NetLogWithSource());
155 if (result != net::ERR_IO_PENDING) {
156 VLOG(1) << "Network proxy resolution completed synchronously.";
157 callback.Run(result);
158 }
159 }
160
161 void ProxyResolverImpl::OnResolutionComplete(std::unique_ptr<Request> request,
162 int result) {
163 DCHECK(request->context_getter->GetNetworkTaskRunner()
164 ->BelongsToCurrentThread());
165
166 if (request->error.empty() && result != net::OK)
167 request->error = net::ErrorToString(result);
168
169 origin_thread_->PostTask(FROM_HERE,
170 base::Bind(&ProxyResolverImpl::NotifyProxyResolved,
171 weak_ptr_factory_.GetWeakPtr(),
172 base::Passed(std::move(request))));
173 }
174
175 void ProxyResolverImpl::NotifyProxyResolved(std::unique_ptr<Request> request) {
176 DCHECK(OnOriginThread());
177
178 // Send a signal to the client.
179 dbus::Signal signal(request->signal_interface, request->signal_name);
180 dbus::MessageWriter writer(&signal);
181 writer.AppendString(request->source_url);
182 writer.AppendString(request->proxy_info.ToPacString());
183 writer.AppendString(request->error);
184 request->exported_object->SendSignal(&signal);
185 VLOG(1) << "Sending signal: " << signal.ToString();
186 }
187
188 } // namespace
189
186 ProxyResolutionServiceProvider::ProxyResolutionServiceProvider( 190 ProxyResolutionServiceProvider::ProxyResolutionServiceProvider(
187 ProxyResolverInterface* resolver) 191 ProxyResolverInterface* resolver)
188 : resolver_(resolver), 192 : resolver_(resolver),
189 origin_thread_(base::ThreadTaskRunnerHandle::Get()), 193 origin_thread_(base::ThreadTaskRunnerHandle::Get()),
190 weak_ptr_factory_(this) { 194 weak_ptr_factory_(this) {
191 } 195 }
192 196
193 ProxyResolutionServiceProvider::~ProxyResolutionServiceProvider() { 197 ProxyResolutionServiceProvider::~ProxyResolutionServiceProvider() = default;
194 }
195 198
196 void ProxyResolutionServiceProvider::Start( 199 void ProxyResolutionServiceProvider::Start(
197 scoped_refptr<dbus::ExportedObject> exported_object) { 200 scoped_refptr<dbus::ExportedObject> exported_object) {
198 DCHECK(OnOriginThread()); 201 DCHECK(OnOriginThread());
199 exported_object_ = exported_object; 202 exported_object_ = exported_object;
200 VLOG(1) << "ProxyResolutionServiceProvider started"; 203 VLOG(1) << "ProxyResolutionServiceProvider started";
201 exported_object_->ExportMethod( 204 exported_object_->ExportMethod(
202 kLibCrosServiceInterface, 205 kLibCrosServiceInterface,
203 kResolveNetworkProxy, 206 kResolveNetworkProxy,
204 // Weak pointers can only bind to methods without return values, 207 // Weak pointers can only bind to methods without return values,
205 // hence we cannot bind ResolveProxyInternal here. Instead we use a 208 // hence we cannot bind ResolveProxyInternal here. Instead we use a
206 // static function to solve this problem. 209 // static function to solve this problem.
207 base::Bind(&ProxyResolutionServiceProvider::CallResolveProxyHandler, 210 base::Bind(&ProxyResolutionServiceProvider::CallResolveProxyHandler,
208 weak_ptr_factory_.GetWeakPtr()), 211 weak_ptr_factory_.GetWeakPtr()),
209 base::Bind(&ProxyResolutionServiceProvider::OnExported, 212 base::Bind(&ProxyResolutionServiceProvider::OnExported,
210 weak_ptr_factory_.GetWeakPtr())); 213 weak_ptr_factory_.GetWeakPtr()));
211 } 214 }
212 215
213 void ProxyResolutionServiceProvider::OnExported( 216 void ProxyResolutionServiceProvider::OnExported(
214 const std::string& interface_name, 217 const std::string& interface_name,
215 const std::string& method_name, 218 const std::string& method_name,
216 bool success) { 219 bool success) {
217 if (!success) { 220 if (!success) {
218 LOG(ERROR) << "Failed to export " << interface_name << "." 221 LOG(ERROR) << "Failed to export " << interface_name << "."
219 << method_name; 222 << method_name;
223 } else {
224 VLOG(1) << "Method exported: " << interface_name << "." << method_name;
220 } 225 }
221 VLOG(1) << "Method exported: " << interface_name << "." << method_name;
222 } 226 }
223 227
224 bool ProxyResolutionServiceProvider::OnOriginThread() { 228 bool ProxyResolutionServiceProvider::OnOriginThread() {
225 return origin_thread_->BelongsToCurrentThread(); 229 return origin_thread_->BelongsToCurrentThread();
226 } 230 }
227 231
228 void ProxyResolutionServiceProvider::ResolveProxyHandler( 232 void ProxyResolutionServiceProvider::ResolveProxyHandler(
229 dbus::MethodCall* method_call, 233 dbus::MethodCall* method_call,
230 dbus::ExportedObject::ResponseSender response_sender) { 234 dbus::ExportedObject::ResponseSender response_sender) {
231 DCHECK(OnOriginThread()); 235 DCHECK(OnOriginThread());
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 } 269 }
266 provider_weak_ptr->ResolveProxyHandler(method_call, response_sender); 270 provider_weak_ptr->ResolveProxyHandler(method_call, response_sender);
267 } 271 }
268 272
269 ProxyResolutionServiceProvider* ProxyResolutionServiceProvider::Create( 273 ProxyResolutionServiceProvider* ProxyResolutionServiceProvider::Create(
270 std::unique_ptr<ProxyResolverDelegate> delegate) { 274 std::unique_ptr<ProxyResolverDelegate> delegate) {
271 return new ProxyResolutionServiceProvider( 275 return new ProxyResolutionServiceProvider(
272 new ProxyResolverImpl(std::move(delegate))); 276 new ProxyResolverImpl(std::move(delegate)));
273 } 277 }
274 278
275 ProxyResolverInterface::~ProxyResolverInterface() { 279 ProxyResolverInterface::~ProxyResolverInterface() = default;
276 }
277 280
278 } // namespace chromeos 281 } // namespace chromeos
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698