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

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: apply feedback: un-inline ProxyResolverImpl and rename method to ResolveProxyOnNetworkThread 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 auto request = base::MakeUnique<Request>(source_url, signal_interface,
117 signal_name, exported_object,
118 delegate_->GetRequestContext());
119
120 // This would ideally call PostTaskAndReply() instead of PostTask(), but
121 // ResolveProxyOnNetworkThread()'s call to net::ProxyService::ResolveProxy()
122 // can result in an asynchronous lookup, in which case the result won't be
123 // available immediately.
124 request->context_getter->GetNetworkTaskRunner()->PostTask(
Daniel Erat 2017/03/22 21:35:59 whoops, introduced a bug here (dereferencing |requ
125 FROM_HERE, base::Bind(&ProxyResolverImpl::ResolveProxyOnNetworkThread,
126 weak_ptr_factory_.GetWeakPtr(),
127 base::Passed(std::move(request))));
128 }
129
130 void ProxyResolverImpl::ResolveProxyOnNetworkThread(
131 std::unique_ptr<Request> request) {
132 DCHECK(request->context_getter->GetNetworkTaskRunner()
133 ->BelongsToCurrentThread());
134
135 net::ProxyService* proxy_service =
136 request->context_getter->GetURLRequestContext()->proxy_service();
137 if (!proxy_service) {
138 request->error = "No proxy service in chrome";
139 OnResolutionComplete(std::move(request), net::ERR_UNEXPECTED);
140 return;
141 }
142
143 Request* request_ptr = request.get();
144 net::CompletionCallback callback = base::Bind(
145 &ProxyResolverImpl::OnResolutionComplete, weak_ptr_factory_.GetWeakPtr(),
146 base::Passed(std::move(request)));
147
148 VLOG(1) << "Starting network proxy resolution for "
149 << request_ptr->source_url;
150 const int result = proxy_service->ResolveProxy(
151 GURL(request_ptr->source_url), std::string(), &request_ptr->proxy_info,
152 callback, nullptr, nullptr, net::NetLogWithSource());
153 if (result != net::ERR_IO_PENDING) {
154 VLOG(1) << "Network proxy resolution completed synchronously.";
155 callback.Run(result);
156 }
157 }
158
159 void ProxyResolverImpl::OnResolutionComplete(std::unique_ptr<Request> request,
160 int result) {
161 DCHECK(request->context_getter->GetNetworkTaskRunner()
162 ->BelongsToCurrentThread());
163
164 if (request->error.empty() && result != net::OK)
165 request->error = net::ErrorToString(result);
166
167 origin_thread_->PostTask(FROM_HERE,
168 base::Bind(&ProxyResolverImpl::NotifyProxyResolved,
169 weak_ptr_factory_.GetWeakPtr(),
170 base::Passed(std::move(request))));
171 }
172
173 void ProxyResolverImpl::NotifyProxyResolved(std::unique_ptr<Request> request) {
174 DCHECK(OnOriginThread());
175
176 // Send a signal to the client.
177 dbus::Signal signal(request->signal_interface, request->signal_name);
178 dbus::MessageWriter writer(&signal);
179 writer.AppendString(request->source_url);
180 writer.AppendString(request->proxy_info.ToPacString());
181 writer.AppendString(request->error);
182 request->exported_object->SendSignal(&signal);
183 VLOG(1) << "Sending signal: " << signal.ToString();
184 }
185
186 } // namespace
187
186 ProxyResolutionServiceProvider::ProxyResolutionServiceProvider( 188 ProxyResolutionServiceProvider::ProxyResolutionServiceProvider(
187 ProxyResolverInterface* resolver) 189 ProxyResolverInterface* resolver)
188 : resolver_(resolver), 190 : resolver_(resolver),
189 origin_thread_(base::ThreadTaskRunnerHandle::Get()), 191 origin_thread_(base::ThreadTaskRunnerHandle::Get()),
190 weak_ptr_factory_(this) { 192 weak_ptr_factory_(this) {
191 } 193 }
192 194
193 ProxyResolutionServiceProvider::~ProxyResolutionServiceProvider() { 195 ProxyResolutionServiceProvider::~ProxyResolutionServiceProvider() = default;
194 }
195 196
196 void ProxyResolutionServiceProvider::Start( 197 void ProxyResolutionServiceProvider::Start(
197 scoped_refptr<dbus::ExportedObject> exported_object) { 198 scoped_refptr<dbus::ExportedObject> exported_object) {
198 DCHECK(OnOriginThread()); 199 DCHECK(OnOriginThread());
199 exported_object_ = exported_object; 200 exported_object_ = exported_object;
200 VLOG(1) << "ProxyResolutionServiceProvider started"; 201 VLOG(1) << "ProxyResolutionServiceProvider started";
201 exported_object_->ExportMethod( 202 exported_object_->ExportMethod(
202 kLibCrosServiceInterface, 203 kLibCrosServiceInterface,
203 kResolveNetworkProxy, 204 kResolveNetworkProxy,
204 // Weak pointers can only bind to methods without return values, 205 // Weak pointers can only bind to methods without return values,
205 // hence we cannot bind ResolveProxyInternal here. Instead we use a 206 // hence we cannot bind ResolveProxyInternal here. Instead we use a
206 // static function to solve this problem. 207 // static function to solve this problem.
207 base::Bind(&ProxyResolutionServiceProvider::CallResolveProxyHandler, 208 base::Bind(&ProxyResolutionServiceProvider::CallResolveProxyHandler,
208 weak_ptr_factory_.GetWeakPtr()), 209 weak_ptr_factory_.GetWeakPtr()),
209 base::Bind(&ProxyResolutionServiceProvider::OnExported, 210 base::Bind(&ProxyResolutionServiceProvider::OnExported,
210 weak_ptr_factory_.GetWeakPtr())); 211 weak_ptr_factory_.GetWeakPtr()));
211 } 212 }
212 213
213 void ProxyResolutionServiceProvider::OnExported( 214 void ProxyResolutionServiceProvider::OnExported(
214 const std::string& interface_name, 215 const std::string& interface_name,
215 const std::string& method_name, 216 const std::string& method_name,
216 bool success) { 217 bool success) {
217 if (!success) { 218 if (!success) {
218 LOG(ERROR) << "Failed to export " << interface_name << "." 219 LOG(ERROR) << "Failed to export " << interface_name << "."
219 << method_name; 220 << method_name;
221 } else {
222 VLOG(1) << "Method exported: " << interface_name << "." << method_name;
220 } 223 }
221 VLOG(1) << "Method exported: " << interface_name << "." << method_name;
222 } 224 }
223 225
224 bool ProxyResolutionServiceProvider::OnOriginThread() { 226 bool ProxyResolutionServiceProvider::OnOriginThread() {
225 return origin_thread_->BelongsToCurrentThread(); 227 return origin_thread_->BelongsToCurrentThread();
226 } 228 }
227 229
228 void ProxyResolutionServiceProvider::ResolveProxyHandler( 230 void ProxyResolutionServiceProvider::ResolveProxyHandler(
229 dbus::MethodCall* method_call, 231 dbus::MethodCall* method_call,
230 dbus::ExportedObject::ResponseSender response_sender) { 232 dbus::ExportedObject::ResponseSender response_sender) {
231 DCHECK(OnOriginThread()); 233 DCHECK(OnOriginThread());
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 } 267 }
266 provider_weak_ptr->ResolveProxyHandler(method_call, response_sender); 268 provider_weak_ptr->ResolveProxyHandler(method_call, response_sender);
267 } 269 }
268 270
269 ProxyResolutionServiceProvider* ProxyResolutionServiceProvider::Create( 271 ProxyResolutionServiceProvider* ProxyResolutionServiceProvider::Create(
270 std::unique_ptr<ProxyResolverDelegate> delegate) { 272 std::unique_ptr<ProxyResolverDelegate> delegate) {
271 return new ProxyResolutionServiceProvider( 273 return new ProxyResolutionServiceProvider(
272 new ProxyResolverImpl(std::move(delegate))); 274 new ProxyResolverImpl(std::move(delegate)));
273 } 275 }
274 276
275 ProxyResolverInterface::~ProxyResolverInterface() { 277 ProxyResolverInterface::~ProxyResolverInterface() = default;
276 }
277 278
278 } // namespace chromeos 279 } // 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