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

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: 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> 7 #include <string>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/bind_helpers.h" 11 #include "base/bind_helpers.h"
12 #include "base/macros.h" 12 #include "base/macros.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. 28 // Data being used in one proxy resolution.
29 class Request { 29 // This would ideally be bound to callbacks as a std::unique_ptr<Request> and
30 // passed around as long as it's needed instead of being ref-counted, but we
31 // don't know whether the callback will be run or not when calling
32 // net::ProxyService::ResolveProxy(): if the proxy can be resolved
33 // synchronously, it won't be, and we don't want to lose ownership of the
satorux1 2017/03/22 04:04:02 I'm confused. Even if it's completed synchronously
Daniel Erat 2017/03/22 05:07:23 sorry if the comment is unclear. i meant that net:
34 // Request object in that case.
Daniel Erat 2017/03/22 00:54:00 i initially considered binding base::WeakPtr<Reque
35 // TODO(derat): Why is this class public? Make it private.
36 class Request : public base::RefCountedThreadSafe<Request> {
30 public: 37 public:
31 explicit Request(const std::string& source_url) : source_url_(source_url) { 38 Request(const std::string& source_url,
32 } 39 const std::string& signal_interface,
33 40 const std::string& signal_name,
34 virtual ~Request() {} 41 scoped_refptr<dbus::ExportedObject> exported_object,
42 scoped_refptr<net::URLRequestContextGetter> context_getter,
43 base::Callback<void(scoped_refptr<Request>)> notify_task,
44 scoped_refptr<base::SingleThreadTaskRunner> notify_thread)
45 : source_url_(source_url),
46 signal_interface_(signal_interface),
47 signal_name_(signal_name),
48 exported_object_(exported_object),
49 context_getter_(context_getter),
50 notify_task_(notify_task),
Daniel Erat 2017/03/22 00:54:00 note that members like this one should be unnecess
51 notify_thread_(notify_thread) {}
35 52
36 // Callback on IO thread for when net::ProxyService::ResolveProxy 53 // Callback on IO thread for when net::ProxyService::ResolveProxy
37 // completes, synchronously or asynchronously. 54 // completes, synchronously or asynchronously.
38 void OnCompletion(scoped_refptr<base::SingleThreadTaskRunner> origin_thread, 55 void OnCompletion(int result) {
39 int result) {
40 // Generate the error message if the error message is not yet set, 56 // Generate the error message if the error message is not yet set,
41 // and there was an error. 57 // and there was an error.
42 if (error_.empty() && result != net::OK) 58 if (error_.empty() && result != net::OK)
43 error_ = net::ErrorToString(result); 59 error_ = net::ErrorToString(result);
44 origin_thread->PostTask(FROM_HERE, notify_task_); 60 notify_thread_->PostTask(
61 FROM_HERE, base::Bind(notify_task_, scoped_refptr<Request>(this)));
45 } 62 }
46 63
47 std::string source_url_; // URL being resolved. 64 // URL being resolved.
48 net::ProxyInfo proxy_info_; // ProxyInfo resolved for source_url_. 65 const std::string source_url_;
49 std::string error_; // Error from proxy resolution. 66
50 base::Closure notify_task_; // Task to notify of resolution result. 67 // D-Bus interface, name, and object for emitting result signal after
68 // resolution is complete.
69 const std::string signal_interface_;
70 const std::string signal_name_;
71 const scoped_refptr<dbus::ExportedObject> exported_object_;
72
73 // Used to get network context.
74 const scoped_refptr<net::URLRequestContextGetter> context_getter_;
75
76 // Task to notify of resolution result and task runner to post it to.
77 const base::Callback<void(scoped_refptr<Request>)> notify_task_;
78 const scoped_refptr<base::SingleThreadTaskRunner> notify_thread_;
79
80 // ProxyInfo resolved for |source_url_|.
81 net::ProxyInfo proxy_info_;
82
83 // Error from proxy resolution.
84 std::string error_;
51 85
52 private: 86 private:
87 friend class base::RefCountedThreadSafe<Request>;
88 virtual ~Request() = default;
89
53 DISALLOW_COPY_AND_ASSIGN(Request); 90 DISALLOW_COPY_AND_ASSIGN(Request);
54 }; 91 };
55 92
93 // TODO(derat): Consider moving all of this class's implementation apart from
94 // ResolveProxy() into the Request class.
56 explicit ProxyResolverImpl(std::unique_ptr<ProxyResolverDelegate> delegate) 95 explicit ProxyResolverImpl(std::unique_ptr<ProxyResolverDelegate> delegate)
57 : delegate_(std::move(delegate)), 96 : delegate_(std::move(delegate)),
58 origin_thread_(base::ThreadTaskRunnerHandle::Get()), 97 origin_thread_(base::ThreadTaskRunnerHandle::Get()),
59 weak_ptr_factory_(this) {} 98 weak_ptr_factory_(this) {}
60 99
61 ~ProxyResolverImpl() override { 100 ~ProxyResolverImpl() override {
62 DCHECK(OnOriginThread()); 101 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 } 102 }
71 103
72 // ProxyResolverInterface override. 104 // ProxyResolverInterface override.
73 void ResolveProxy( 105 void ResolveProxy(
74 const std::string& source_url, 106 const std::string& source_url,
75 const std::string& signal_interface, 107 const std::string& signal_interface,
76 const std::string& signal_name, 108 const std::string& signal_name,
77 scoped_refptr<dbus::ExportedObject> exported_object) override { 109 scoped_refptr<dbus::ExportedObject> exported_object) override {
78 DCHECK(OnOriginThread()); 110 DCHECK(OnOriginThread());
79 111
80 // Create a request slot for this proxy resolution request. 112 // Create a request slot for this proxy resolution request.
81 Request* request = new Request(source_url); 113 // GetRequestContext() must be called on UI thread.
82 request->notify_task_ = base::Bind( 114 scoped_refptr<Request> request =
83 &ProxyResolverImpl::NotifyProxyResolved, 115 new Request(source_url, signal_interface, signal_name, exported_object,
84 weak_ptr_factory_.GetWeakPtr(), 116 delegate_->GetRequestContext(),
85 signal_interface, 117 base::Bind(&ProxyResolverImpl::NotifyProxyResolved,
86 signal_name, 118 weak_ptr_factory_.GetWeakPtr()),
87 exported_object, 119 origin_thread_);
88 request);
89 all_requests_.insert(request);
90 120
91 // GetRequestContext() must be called on UI thread. 121 // This would ideally call PostTaskAndReply() instead of PostTask(), but
92 scoped_refptr<net::URLRequestContextGetter> getter = 122 // ResolveProxyInternal()'s call to net::ProxyService::ResolveProxy() can
93 delegate_->GetRequestContext(); 123 // result in an asynchronous lookup, in which case the result won't be
94 124 // available immediately.
95 getter->GetNetworkTaskRunner()->PostTask( 125 request->context_getter_->GetNetworkTaskRunner()->PostTask(
96 FROM_HERE, 126 FROM_HERE,
97 base::Bind(&ProxyResolverImpl::ResolveProxyInternal, 127 base::Bind(&ProxyResolverImpl::ResolveProxyInternal, request));
98 request,
99 origin_thread_,
100 getter,
101 exported_object));
102 } 128 }
103 129
104 private: 130 private:
105 // Helper function for ResolveProxy(). 131 // Helper function for ResolveProxy().
106 static void ResolveProxyInternal( 132 static void ResolveProxyInternal(scoped_refptr<Request> request) {
107 Request* request, 133 DCHECK(request->context_getter_->GetNetworkTaskRunner()
108 scoped_refptr<base::SingleThreadTaskRunner> origin_thread, 134 ->BelongsToCurrentThread());
109 scoped_refptr<net::URLRequestContextGetter> getter,
110 scoped_refptr<dbus::ExportedObject> exported_object) {
111 // Make sure we're running on IO thread.
112 DCHECK(getter->GetNetworkTaskRunner()->BelongsToCurrentThread());
113 135
114 // Check if we have the URLRequestContextGetter. 136 if (!request->context_getter_.get()) {
115 if (!getter.get()) {
116 request->error_ = "No URLRequestContextGetter"; 137 request->error_ = "No URLRequestContextGetter";
Daniel Erat 2017/03/22 00:54:00 i suspect that the old code is susceptible to use-
117 request->OnCompletion(origin_thread, net::ERR_UNEXPECTED); 138 request->OnCompletion(net::ERR_UNEXPECTED);
118 return; 139 return;
119 } 140 }
120 141
121 // Retrieve ProxyService from profile's request context.
122 net::ProxyService* proxy_service = 142 net::ProxyService* proxy_service =
123 getter->GetURLRequestContext()->proxy_service(); 143 request->context_getter_->GetURLRequestContext()->proxy_service();
124 if (!proxy_service) { 144 if (!proxy_service) {
125 request->error_ = "No proxy service in chrome"; 145 request->error_ = "No proxy service in chrome";
126 request->OnCompletion(origin_thread, net::ERR_UNEXPECTED); 146 request->OnCompletion(net::ERR_UNEXPECTED);
127 return; 147 return;
128 } 148 }
129 149
130 VLOG(1) << "Starting network proxy resolution for " 150 VLOG(1) << "Starting network proxy resolution for "
131 << request->source_url_; 151 << request->source_url_;
132 net::CompletionCallback completion_callback = 152 net::CompletionCallback completion_callback =
133 base::Bind(&Request::OnCompletion, 153 base::Bind(&Request::OnCompletion, request);
134 base::Unretained(request),
135 origin_thread);
136 const int result = proxy_service->ResolveProxy( 154 const int result = proxy_service->ResolveProxy(
137 GURL(request->source_url_), std::string(), &request->proxy_info_, 155 GURL(request->source_url_), std::string(), &request->proxy_info_,
138 completion_callback, NULL, NULL, net::NetLogWithSource()); 156 completion_callback, nullptr, nullptr, net::NetLogWithSource());
139 if (result != net::ERR_IO_PENDING) { 157 if (result != net::ERR_IO_PENDING) {
140 VLOG(1) << "Network proxy resolution completed synchronously."; 158 VLOG(1) << "Network proxy resolution completed synchronously.";
141 completion_callback.Run(result); 159 completion_callback.Run(result);
142 } 160 }
143 } 161 }
144 162
145 // Called on UI thread as task posted from Request::OnCompletion on IO 163 // Called on UI thread as task posted from Request::OnCompletion on network
146 // thread. 164 // thread.
147 void NotifyProxyResolved( 165 void NotifyProxyResolved(scoped_refptr<Request> request) {
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()); 166 DCHECK(OnOriginThread());
153 167
154 // Send a signal to the client. 168 // Send a signal to the client.
155 dbus::Signal signal(signal_interface, signal_name); 169 dbus::Signal signal(request->signal_interface_, request->signal_name_);
Daniel Erat 2017/03/22 00:54:00 moving the implementation into Request will also a
156 dbus::MessageWriter writer(&signal); 170 dbus::MessageWriter writer(&signal);
157 writer.AppendString(request->source_url_); 171 writer.AppendString(request->source_url_);
158 writer.AppendString(request->proxy_info_.ToPacString()); 172 writer.AppendString(request->proxy_info_.ToPacString());
159 writer.AppendString(request->error_); 173 writer.AppendString(request->error_);
160 exported_object->SendSignal(&signal); 174 request->exported_object_->SendSignal(&signal);
161 VLOG(1) << "Sending signal: " << signal.ToString(); 175 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 } 176 }
172 177
173 // Returns true if the current thread is on the origin thread. 178 // Returns true if the current thread is on the origin thread.
174 bool OnOriginThread() { 179 bool OnOriginThread() {
175 return origin_thread_->BelongsToCurrentThread(); 180 return origin_thread_->BelongsToCurrentThread();
176 } 181 }
177 182
178 std::unique_ptr<ProxyResolverDelegate> delegate_; 183 std::unique_ptr<ProxyResolverDelegate> delegate_;
179 scoped_refptr<base::SingleThreadTaskRunner> origin_thread_; 184 scoped_refptr<base::SingleThreadTaskRunner> origin_thread_;
180 std::set<Request*> all_requests_;
181 base::WeakPtrFactory<ProxyResolverImpl> weak_ptr_factory_; 185 base::WeakPtrFactory<ProxyResolverImpl> weak_ptr_factory_;
182 186
183 DISALLOW_COPY_AND_ASSIGN(ProxyResolverImpl); 187 DISALLOW_COPY_AND_ASSIGN(ProxyResolverImpl);
184 }; 188 };
185 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