OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 "net/proxy/proxy_resolver_v8_tracing.h" | 5 #include "net/proxy/proxy_resolver_v8_tracing.h" |
6 | 6 |
| 7 #include <map> |
| 8 #include <string> |
| 9 #include <vector> |
| 10 |
7 #include "base/bind.h" | 11 #include "base/bind.h" |
8 #include "base/single_thread_task_runner.h" | 12 #include "base/single_thread_task_runner.h" |
9 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
10 #include "base/synchronization/cancellation_flag.h" | 14 #include "base/synchronization/cancellation_flag.h" |
11 #include "base/synchronization/waitable_event.h" | 15 #include "base/synchronization/waitable_event.h" |
12 #include "base/thread_task_runner_handle.h" | 16 #include "base/thread_task_runner_handle.h" |
13 #include "base/threading/thread.h" | 17 #include "base/threading/thread.h" |
14 #include "base/threading/thread_restrictions.h" | 18 #include "base/threading/thread_restrictions.h" |
15 #include "base/values.h" | 19 #include "base/values.h" |
16 #include "net/base/address_list.h" | 20 #include "net/base/address_list.h" |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 // Returns event parameters for a PAC error message (line number + message). | 61 // Returns event parameters for a PAC error message (line number + message). |
58 base::Value* NetLogErrorCallback(int line_number, | 62 base::Value* NetLogErrorCallback(int line_number, |
59 const base::string16* message, | 63 const base::string16* message, |
60 NetLogCaptureMode /* capture_mode */) { | 64 NetLogCaptureMode /* capture_mode */) { |
61 base::DictionaryValue* dict = new base::DictionaryValue(); | 65 base::DictionaryValue* dict = new base::DictionaryValue(); |
62 dict->SetInteger("line_number", line_number); | 66 dict->SetInteger("line_number", line_number); |
63 dict->SetString("message", *message); | 67 dict->SetString("message", *message); |
64 return dict; | 68 return dict; |
65 } | 69 } |
66 | 70 |
67 } // namespace | |
68 | |
69 // The Job class is responsible for executing GetProxyForURL() and | 71 // The Job class is responsible for executing GetProxyForURL() and |
70 // SetPacScript(), since both of these operations share similar code. | 72 // creating ProxyResolverV8 instances, since both of these operations share |
| 73 // similar code. |
71 // | 74 // |
72 // The DNS for these operations can operate in either blocking or | 75 // The DNS for these operations can operate in either blocking or |
73 // non-blocking mode. Blocking mode is used as a fallback when the PAC script | 76 // non-blocking mode. Blocking mode is used as a fallback when the PAC script |
74 // seems to be misbehaving under the tracing optimization. | 77 // seems to be misbehaving under the tracing optimization. |
75 // | 78 // |
76 // Note that this class runs on both the origin thread and a worker | 79 // Note that this class runs on both the origin thread and a worker |
77 // thread. Most methods are expected to be used exclusively on one thread | 80 // thread. Most methods are expected to be used exclusively on one thread |
78 // or the other. | 81 // or the other. |
79 // | 82 // |
80 // The lifetime of Jobs does not exceed that of the ProxyResolverV8Tracing that | 83 // The lifetime of Jobs does not exceed that of the ProxyResolverV8Tracing that |
81 // spawned it. Destruction might happen on either the origin thread or the | 84 // spawned it. Destruction might happen on either the origin thread or the |
82 // worker thread. | 85 // worker thread. |
83 class ProxyResolverV8Tracing::Job | 86 class Job : public base::RefCountedThreadSafe<Job>, |
84 : public base::RefCountedThreadSafe<ProxyResolverV8Tracing::Job>, | 87 public ProxyResolverV8::JSBindings { |
85 public ProxyResolverV8::JSBindings { | |
86 public: | 88 public: |
87 // |parent| is non-owned. It is the ProxyResolverV8Tracing that spawned this | 89 struct Params { |
88 // Job, and must oulive it. | 90 Params( |
89 explicit Job(ProxyResolverV8Tracing* parent); | 91 const scoped_refptr<base::SingleThreadTaskRunner>& worker_task_runner, |
| 92 HostResolver* host_resolver, |
| 93 ProxyResolverErrorObserver* error_observer, |
| 94 NetLog* net_log, |
| 95 ProxyResolver::LoadStateChangedCallback on_load_state_changed, |
| 96 int* num_outstanding_callbacks) |
| 97 : v8_resolver(nullptr), |
| 98 worker_task_runner(worker_task_runner), |
| 99 host_resolver(host_resolver), |
| 100 error_observer(error_observer), |
| 101 net_log(net_log), |
| 102 on_load_state_changed(on_load_state_changed), |
| 103 num_outstanding_callbacks(num_outstanding_callbacks) {} |
| 104 |
| 105 ProxyResolverV8* v8_resolver; |
| 106 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner; |
| 107 HostResolver* host_resolver; |
| 108 ProxyResolverErrorObserver* error_observer; |
| 109 NetLog* net_log; |
| 110 ProxyResolver::LoadStateChangedCallback on_load_state_changed; |
| 111 int* num_outstanding_callbacks; |
| 112 }; |
| 113 // |params| is non-owned. It contains the parameters for this Job, and must |
| 114 // outlive it. |
| 115 explicit Job(const Params* params); |
90 | 116 |
91 // Called from origin thread. | 117 // Called from origin thread. |
92 void StartSetPacScript( | 118 void StartCreateV8Resolver( |
93 const scoped_refptr<ProxyResolverScriptData>& script_data, | 119 const scoped_refptr<ProxyResolverScriptData>& script_data, |
| 120 scoped_ptr<ProxyResolverV8>* resolver, |
94 const CompletionCallback& callback); | 121 const CompletionCallback& callback); |
95 | 122 |
96 // Called from origin thread. | 123 // Called from origin thread. |
97 void StartGetProxyForURL(const GURL& url, | 124 void StartGetProxyForURL(const GURL& url, |
98 ProxyInfo* results, | 125 ProxyInfo* results, |
99 const BoundNetLog& net_log, | 126 const BoundNetLog& net_log, |
100 const CompletionCallback& callback); | 127 const CompletionCallback& callback); |
101 | 128 |
102 // Called from origin thread. | 129 // Called from origin thread. |
103 void Cancel(); | 130 void Cancel(); |
104 | 131 |
105 // Called from origin thread. | 132 // Called from origin thread. |
106 LoadState GetLoadState() const; | 133 LoadState GetLoadState() const; |
107 | 134 |
108 private: | 135 private: |
109 typedef std::map<std::string, std::string> DnsCache; | 136 typedef std::map<std::string, std::string> DnsCache; |
110 friend class base::RefCountedThreadSafe<ProxyResolverV8Tracing::Job>; | 137 friend class base::RefCountedThreadSafe<Job>; |
111 | 138 |
112 enum Operation { | 139 enum Operation { |
113 SET_PAC_SCRIPT, | 140 CREATE_V8_RESOLVER, |
114 GET_PROXY_FOR_URL, | 141 GET_PROXY_FOR_URL, |
115 }; | 142 }; |
116 | 143 |
117 struct AlertOrError { | 144 struct AlertOrError { |
118 bool is_alert; | 145 bool is_alert; |
119 int line_number; | 146 int line_number; |
120 base::string16 message; | 147 base::string16 message; |
121 }; | 148 }; |
122 | 149 |
123 ~Job() override; | 150 ~Job() override; |
124 | 151 |
125 void CheckIsOnWorkerThread() const; | 152 void CheckIsOnWorkerThread() const; |
126 void CheckIsOnOriginThread() const; | 153 void CheckIsOnOriginThread() const; |
127 | 154 |
128 void SetCallback(const CompletionCallback& callback); | 155 void SetCallback(const CompletionCallback& callback); |
129 void ReleaseCallback(); | 156 void ReleaseCallback(); |
130 | 157 |
131 ProxyResolverV8* v8_resolver(); | 158 ProxyResolverV8* v8_resolver(); |
132 base::MessageLoop* worker_loop(); | 159 const scoped_refptr<base::SingleThreadTaskRunner>& worker_task_runner(); |
133 HostResolver* host_resolver(); | 160 HostResolver* host_resolver(); |
134 ProxyResolverErrorObserver* error_observer(); | 161 ProxyResolverErrorObserver* error_observer(); |
135 NetLog* net_log(); | 162 NetLog* net_log(); |
136 | 163 |
137 // Invokes the user's callback. | 164 // Invokes the user's callback. |
138 void NotifyCaller(int result); | 165 void NotifyCaller(int result); |
139 void NotifyCallerOnOriginLoop(int result); | 166 void NotifyCallerOnOriginLoop(int result); |
140 | 167 |
141 void Start(Operation op, bool blocking_dns, | 168 void Start(Operation op, bool blocking_dns, |
142 const CompletionCallback& callback); | 169 const CompletionCallback& callback); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 const base::string16& message); | 223 const base::string16& message); |
197 | 224 |
198 void LogEventToCurrentRequestAndGlobally( | 225 void LogEventToCurrentRequestAndGlobally( |
199 NetLog::EventType type, | 226 NetLog::EventType type, |
200 const NetLog::ParametersCallback& parameters_callback); | 227 const NetLog::ParametersCallback& parameters_callback); |
201 | 228 |
202 // The thread which called into ProxyResolverV8Tracing, and on which the | 229 // The thread which called into ProxyResolverV8Tracing, and on which the |
203 // completion callback is expected to run. | 230 // completion callback is expected to run. |
204 scoped_refptr<base::SingleThreadTaskRunner> origin_runner_; | 231 scoped_refptr<base::SingleThreadTaskRunner> origin_runner_; |
205 | 232 |
206 // The ProxyResolverV8Tracing which spawned this Job. | 233 // The Parameters for this Job. |
207 // Initialized on origin thread and then accessed from both threads. | 234 // Initialized on origin thread and then accessed from both threads. |
208 ProxyResolverV8Tracing* parent_; | 235 const Params* const params_; |
209 | 236 |
210 // The callback to run (on the origin thread) when the Job finishes. | 237 // The callback to run (on the origin thread) when the Job finishes. |
211 // Should only be accessed from origin thread. | 238 // Should only be accessed from origin thread. |
212 CompletionCallback callback_; | 239 CompletionCallback callback_; |
213 | 240 |
214 // Flag to indicate whether the request has been cancelled. | 241 // Flag to indicate whether the request has been cancelled. |
215 base::CancellationFlag cancelled_; | 242 base::CancellationFlag cancelled_; |
216 | 243 |
217 // The operation that this Job is running. | 244 // The operation that this Job is running. |
218 // Initialized on origin thread and then accessed from both threads. | 245 // Initialized on origin thread and then accessed from both threads. |
(...skipping 10 matching lines...) Expand all Loading... |
229 | 256 |
230 // Map of DNS operations completed so far. Written into on the origin thread | 257 // Map of DNS operations completed so far. Written into on the origin thread |
231 // and read on the worker thread. | 258 // and read on the worker thread. |
232 DnsCache dns_cache_; | 259 DnsCache dns_cache_; |
233 | 260 |
234 // The job holds a reference to itself to ensure that it remains alive until | 261 // The job holds a reference to itself to ensure that it remains alive until |
235 // either completion or cancellation. | 262 // either completion or cancellation. |
236 scoped_refptr<Job> owned_self_reference_; | 263 scoped_refptr<Job> owned_self_reference_; |
237 | 264 |
238 // ------------------------------------------------------- | 265 // ------------------------------------------------------- |
239 // State specific to SET_PAC_SCRIPT. | 266 // State specific to CREATE_V8_RESOLVER. |
240 // ------------------------------------------------------- | 267 // ------------------------------------------------------- |
241 | 268 |
242 scoped_refptr<ProxyResolverScriptData> script_data_; | 269 scoped_refptr<ProxyResolverScriptData> script_data_; |
| 270 scoped_ptr<ProxyResolverV8>* resolver_out_; |
243 | 271 |
244 // ------------------------------------------------------- | 272 // ------------------------------------------------------- |
245 // State specific to GET_PROXY_FOR_URL. | 273 // State specific to GET_PROXY_FOR_URL. |
246 // ------------------------------------------------------- | 274 // ------------------------------------------------------- |
247 | 275 |
248 ProxyInfo* user_results_; // Owned by caller, lives on origin thread. | 276 ProxyInfo* user_results_; // Owned by caller, lives on origin thread. |
249 GURL url_; | 277 GURL url_; |
250 ProxyInfo results_; | 278 ProxyInfo results_; |
251 BoundNetLog bound_net_log_; | 279 BoundNetLog bound_net_log_; |
252 | 280 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 // These are the inputs to DoDnsOperation(). Written on the worker thread, | 316 // These are the inputs to DoDnsOperation(). Written on the worker thread, |
289 // read by the origin thread. | 317 // read by the origin thread. |
290 std::string pending_dns_host_; | 318 std::string pending_dns_host_; |
291 ResolveDnsOperation pending_dns_op_; | 319 ResolveDnsOperation pending_dns_op_; |
292 | 320 |
293 // This contains the resolved address list that DoDnsOperation() fills in. | 321 // This contains the resolved address list that DoDnsOperation() fills in. |
294 // Used exclusively on the origin thread. | 322 // Used exclusively on the origin thread. |
295 AddressList pending_dns_addresses_; | 323 AddressList pending_dns_addresses_; |
296 }; | 324 }; |
297 | 325 |
298 ProxyResolverV8Tracing::Job::Job(ProxyResolverV8Tracing* parent) | 326 class ProxyResolverV8Tracing : public ProxyResolver, |
| 327 public base::NonThreadSafe { |
| 328 public: |
| 329 // Constructs a ProxyResolver that will issue DNS requests through |
| 330 // |job_params->host_resolver|, forward Javascript errors through |
| 331 // |error_observer|, and log Javascript errors and alerts to |
| 332 // |job_params->net_log|. When the LoadState for a request changes, |
| 333 // |job_params->on_load_state_changed| will be invoked with the RequestHandle |
| 334 // for that request with the new LoadState. |
| 335 // |
| 336 // Note that the constructor takes ownership of |error_observer|, whereas |
| 337 // |job_params->host_resolver| and |job_params->net_log| are expected to |
| 338 // outlive |this|. |
| 339 ProxyResolverV8Tracing(scoped_ptr<ProxyResolverErrorObserver> error_observer, |
| 340 scoped_ptr<base::Thread> thread, |
| 341 scoped_ptr<ProxyResolverV8> resolver, |
| 342 scoped_ptr<Job::Params> job_params); |
| 343 |
| 344 ~ProxyResolverV8Tracing() override; |
| 345 |
| 346 // ProxyResolver implementation: |
| 347 int GetProxyForURL(const GURL& url, |
| 348 ProxyInfo* results, |
| 349 const CompletionCallback& callback, |
| 350 RequestHandle* request, |
| 351 const BoundNetLog& net_log) override; |
| 352 void CancelRequest(RequestHandle request) override; |
| 353 LoadState GetLoadState(RequestHandle request) const override; |
| 354 void CancelSetPacScript() override; |
| 355 int SetPacScript(const scoped_refptr<ProxyResolverScriptData>& script_data, |
| 356 const CompletionCallback& callback) override; |
| 357 |
| 358 private: |
| 359 // The worker thread on which the ProxyResolverV8 will be run. |
| 360 scoped_ptr<base::Thread> thread_; |
| 361 scoped_ptr<ProxyResolverV8> v8_resolver_; |
| 362 |
| 363 scoped_ptr<ProxyResolverErrorObserver> error_observer_; |
| 364 |
| 365 scoped_ptr<Job::Params> job_params_; |
| 366 |
| 367 // The number of outstanding (non-cancelled) jobs. |
| 368 int num_outstanding_callbacks_; |
| 369 |
| 370 DISALLOW_COPY_AND_ASSIGN(ProxyResolverV8Tracing); |
| 371 }; |
| 372 |
| 373 Job::Job(const Job::Params* params) |
299 : origin_runner_(base::ThreadTaskRunnerHandle::Get()), | 374 : origin_runner_(base::ThreadTaskRunnerHandle::Get()), |
300 parent_(parent), | 375 params_(params), |
301 event_(true, false), | 376 event_(true, false), |
302 last_num_dns_(0), | 377 last_num_dns_(0), |
303 pending_dns_(NULL) { | 378 pending_dns_(NULL) { |
304 CheckIsOnOriginThread(); | 379 CheckIsOnOriginThread(); |
305 } | 380 } |
306 | 381 |
307 void ProxyResolverV8Tracing::Job::StartSetPacScript( | 382 void Job::StartCreateV8Resolver( |
308 const scoped_refptr<ProxyResolverScriptData>& script_data, | 383 const scoped_refptr<ProxyResolverScriptData>& script_data, |
| 384 scoped_ptr<ProxyResolverV8>* resolver, |
309 const CompletionCallback& callback) { | 385 const CompletionCallback& callback) { |
310 CheckIsOnOriginThread(); | 386 CheckIsOnOriginThread(); |
311 | 387 |
| 388 resolver_out_ = resolver; |
312 script_data_ = script_data; | 389 script_data_ = script_data; |
313 | 390 |
314 // Script initialization uses blocking DNS since there isn't any | 391 // Script initialization uses blocking DNS since there isn't any |
315 // advantage to using non-blocking mode here. That is because the | 392 // advantage to using non-blocking mode here. That is because the |
316 // parent ProxyService can't submit any ProxyResolve requests until | 393 // parent ProxyService can't submit any ProxyResolve requests until |
317 // initialization has completed successfully! | 394 // initialization has completed successfully! |
318 Start(SET_PAC_SCRIPT, true /*blocking*/, callback); | 395 Start(CREATE_V8_RESOLVER, true /*blocking*/, callback); |
319 } | 396 } |
320 | 397 |
321 void ProxyResolverV8Tracing::Job::StartGetProxyForURL( | 398 void Job::StartGetProxyForURL(const GURL& url, |
322 const GURL& url, | 399 ProxyInfo* results, |
323 ProxyInfo* results, | 400 const BoundNetLog& net_log, |
324 const BoundNetLog& net_log, | 401 const CompletionCallback& callback) { |
325 const CompletionCallback& callback) { | |
326 CheckIsOnOriginThread(); | 402 CheckIsOnOriginThread(); |
327 | 403 |
328 url_ = url; | 404 url_ = url; |
329 user_results_ = results; | 405 user_results_ = results; |
330 bound_net_log_ = net_log; | 406 bound_net_log_ = net_log; |
331 | 407 |
332 Start(GET_PROXY_FOR_URL, false /*non-blocking*/, callback); | 408 Start(GET_PROXY_FOR_URL, false /*non-blocking*/, callback); |
333 } | 409 } |
334 | 410 |
335 void ProxyResolverV8Tracing::Job::Cancel() { | 411 void Job::Cancel() { |
336 CheckIsOnOriginThread(); | 412 CheckIsOnOriginThread(); |
337 | 413 |
338 // There are several possibilities to consider for cancellation: | 414 // There are several possibilities to consider for cancellation: |
339 // (a) The job has been posted to the worker thread, however script execution | 415 // (a) The job has been posted to the worker thread, however script execution |
340 // has not yet started. | 416 // has not yet started. |
341 // (b) The script is executing on the worker thread. | 417 // (b) The script is executing on the worker thread. |
342 // (c) The script is executing on the worker thread, however is blocked inside | 418 // (c) The script is executing on the worker thread, however is blocked inside |
343 // of dnsResolve() waiting for a response from the origin thread. | 419 // of dnsResolve() waiting for a response from the origin thread. |
344 // (d) Nothing is running on the worker thread, however the host resolver has | 420 // (d) Nothing is running on the worker thread, however the host resolver has |
345 // a pending DNS request which upon completion will restart the script | 421 // a pending DNS request which upon completion will restart the script |
(...skipping 14 matching lines...) Expand all Loading... |
360 host_resolver()->CancelRequest(pending_dns_); | 436 host_resolver()->CancelRequest(pending_dns_); |
361 pending_dns_ = NULL; | 437 pending_dns_ = NULL; |
362 } | 438 } |
363 | 439 |
364 // The worker thread might be blocked waiting for DNS. | 440 // The worker thread might be blocked waiting for DNS. |
365 event_.Signal(); | 441 event_.Signal(); |
366 | 442 |
367 owned_self_reference_ = NULL; | 443 owned_self_reference_ = NULL; |
368 } | 444 } |
369 | 445 |
370 LoadState ProxyResolverV8Tracing::Job::GetLoadState() const { | 446 LoadState Job::GetLoadState() const { |
371 CheckIsOnOriginThread(); | 447 CheckIsOnOriginThread(); |
372 | 448 |
373 if (pending_dns_) | 449 if (pending_dns_) |
374 return LOAD_STATE_RESOLVING_HOST_IN_PROXY_SCRIPT; | 450 return LOAD_STATE_RESOLVING_HOST_IN_PROXY_SCRIPT; |
375 | 451 |
376 return LOAD_STATE_RESOLVING_PROXY_FOR_URL; | 452 return LOAD_STATE_RESOLVING_PROXY_FOR_URL; |
377 } | 453 } |
378 | 454 |
379 ProxyResolverV8Tracing::Job::~Job() { | 455 Job::~Job() { |
380 DCHECK(!pending_dns_); | 456 DCHECK(!pending_dns_); |
381 DCHECK(callback_.is_null()); | 457 DCHECK(callback_.is_null()); |
382 } | 458 } |
383 | 459 |
384 void ProxyResolverV8Tracing::Job::CheckIsOnWorkerThread() const { | 460 void Job::CheckIsOnWorkerThread() const { |
385 DCHECK_EQ(base::MessageLoop::current(), parent_->thread_->message_loop()); | 461 DCHECK(params_->worker_task_runner->BelongsToCurrentThread()); |
386 } | 462 } |
387 | 463 |
388 void ProxyResolverV8Tracing::Job::CheckIsOnOriginThread() const { | 464 void Job::CheckIsOnOriginThread() const { |
389 DCHECK(origin_runner_->BelongsToCurrentThread()); | 465 DCHECK(origin_runner_->BelongsToCurrentThread()); |
390 } | 466 } |
391 | 467 |
392 void ProxyResolverV8Tracing::Job::SetCallback( | 468 void Job::SetCallback(const CompletionCallback& callback) { |
393 const CompletionCallback& callback) { | |
394 CheckIsOnOriginThread(); | 469 CheckIsOnOriginThread(); |
395 DCHECK(callback_.is_null()); | 470 DCHECK(callback_.is_null()); |
396 parent_->num_outstanding_callbacks_++; | 471 (*params_->num_outstanding_callbacks)++; |
397 callback_ = callback; | 472 callback_ = callback; |
398 } | 473 } |
399 | 474 |
400 void ProxyResolverV8Tracing::Job::ReleaseCallback() { | 475 void Job::ReleaseCallback() { |
401 CheckIsOnOriginThread(); | 476 CheckIsOnOriginThread(); |
402 DCHECK(!callback_.is_null()); | 477 DCHECK(!callback_.is_null()); |
403 CHECK_GT(parent_->num_outstanding_callbacks_, 0); | 478 CHECK_GT(*params_->num_outstanding_callbacks, 0); |
404 parent_->num_outstanding_callbacks_--; | 479 (*params_->num_outstanding_callbacks)--; |
405 callback_.Reset(); | 480 callback_.Reset(); |
406 | 481 |
407 // For good measure, clear this other user-owned pointer. | 482 // For good measure, clear this other user-owned pointer. |
408 user_results_ = NULL; | 483 user_results_ = NULL; |
409 } | 484 } |
410 | 485 |
411 ProxyResolverV8* ProxyResolverV8Tracing::Job::v8_resolver() { | 486 ProxyResolverV8* Job::v8_resolver() { |
412 return parent_->v8_resolver_.get(); | 487 return params_->v8_resolver; |
413 } | 488 } |
414 | 489 |
415 base::MessageLoop* ProxyResolverV8Tracing::Job::worker_loop() { | 490 const scoped_refptr<base::SingleThreadTaskRunner>& Job::worker_task_runner() { |
416 return parent_->thread_->message_loop(); | 491 return params_->worker_task_runner; |
417 } | 492 } |
418 | 493 |
419 HostResolver* ProxyResolverV8Tracing::Job::host_resolver() { | 494 HostResolver* Job::host_resolver() { |
420 return parent_->host_resolver_; | 495 return params_->host_resolver; |
421 } | 496 } |
422 | 497 |
423 ProxyResolverErrorObserver* ProxyResolverV8Tracing::Job::error_observer() { | 498 ProxyResolverErrorObserver* Job::error_observer() { |
424 return parent_->error_observer_.get(); | 499 return params_->error_observer; |
425 } | 500 } |
426 | 501 |
427 NetLog* ProxyResolverV8Tracing::Job::net_log() { | 502 NetLog* Job::net_log() { |
428 return parent_->net_log_; | 503 return params_->net_log; |
429 } | 504 } |
430 | 505 |
431 void ProxyResolverV8Tracing::Job::NotifyCaller(int result) { | 506 void Job::NotifyCaller(int result) { |
432 CheckIsOnWorkerThread(); | 507 CheckIsOnWorkerThread(); |
433 | 508 |
434 origin_runner_->PostTask( | 509 origin_runner_->PostTask( |
435 FROM_HERE, base::Bind(&Job::NotifyCallerOnOriginLoop, this, result)); | 510 FROM_HERE, base::Bind(&Job::NotifyCallerOnOriginLoop, this, result)); |
436 } | 511 } |
437 | 512 |
438 void ProxyResolverV8Tracing::Job::NotifyCallerOnOriginLoop(int result) { | 513 void Job::NotifyCallerOnOriginLoop(int result) { |
439 CheckIsOnOriginThread(); | 514 CheckIsOnOriginThread(); |
440 | 515 |
441 if (cancelled_.IsSet()) | 516 if (cancelled_.IsSet()) |
442 return; | 517 return; |
443 | 518 |
444 DCHECK(!callback_.is_null()); | 519 DCHECK(!callback_.is_null()); |
445 DCHECK(!pending_dns_); | 520 DCHECK(!pending_dns_); |
446 | 521 |
447 if (operation_ == GET_PROXY_FOR_URL) { | 522 if (operation_ == GET_PROXY_FOR_URL) { |
448 *user_results_ = results_; | 523 *user_results_ = results_; |
449 } | 524 } |
450 | 525 |
451 // There is only ever 1 outstanding SET_PAC_SCRIPT job. It needs to be | |
452 // tracked to support cancellation. | |
453 if (operation_ == SET_PAC_SCRIPT) { | |
454 DCHECK_EQ(parent_->set_pac_script_job_.get(), this); | |
455 parent_->set_pac_script_job_ = NULL; | |
456 } | |
457 | |
458 CompletionCallback callback = callback_; | 526 CompletionCallback callback = callback_; |
459 ReleaseCallback(); | 527 ReleaseCallback(); |
460 callback.Run(result); | 528 callback.Run(result); |
461 | 529 |
462 owned_self_reference_ = NULL; | 530 owned_self_reference_ = NULL; |
463 } | 531 } |
464 | 532 |
465 void ProxyResolverV8Tracing::Job::Start(Operation op, bool blocking_dns, | 533 void Job::Start(Operation op, |
466 const CompletionCallback& callback) { | 534 bool blocking_dns, |
| 535 const CompletionCallback& callback) { |
467 CheckIsOnOriginThread(); | 536 CheckIsOnOriginThread(); |
468 | 537 |
469 operation_ = op; | 538 operation_ = op; |
470 blocking_dns_ = blocking_dns; | 539 blocking_dns_ = blocking_dns; |
471 SetCallback(callback); | 540 SetCallback(callback); |
472 | 541 |
473 owned_self_reference_ = this; | 542 owned_self_reference_ = this; |
474 | 543 |
475 worker_loop()->PostTask(FROM_HERE, | 544 worker_task_runner()->PostTask( |
476 blocking_dns_ ? base::Bind(&Job::ExecuteBlocking, this) : | 545 FROM_HERE, blocking_dns_ ? base::Bind(&Job::ExecuteBlocking, this) |
477 base::Bind(&Job::ExecuteNonBlocking, this)); | 546 : base::Bind(&Job::ExecuteNonBlocking, this)); |
478 } | 547 } |
479 | 548 |
480 void ProxyResolverV8Tracing::Job::ExecuteBlocking() { | 549 void Job::ExecuteBlocking() { |
481 CheckIsOnWorkerThread(); | 550 CheckIsOnWorkerThread(); |
482 DCHECK(blocking_dns_); | 551 DCHECK(blocking_dns_); |
483 | 552 |
484 if (cancelled_.IsSet()) | 553 if (cancelled_.IsSet()) |
485 return; | 554 return; |
486 | 555 |
487 NotifyCaller(ExecuteProxyResolver()); | 556 NotifyCaller(ExecuteProxyResolver()); |
488 } | 557 } |
489 | 558 |
490 void ProxyResolverV8Tracing::Job::ExecuteNonBlocking() { | 559 void Job::ExecuteNonBlocking() { |
491 CheckIsOnWorkerThread(); | 560 CheckIsOnWorkerThread(); |
492 DCHECK(!blocking_dns_); | 561 DCHECK(!blocking_dns_); |
493 | 562 |
494 if (cancelled_.IsSet()) | 563 if (cancelled_.IsSet()) |
495 return; | 564 return; |
496 | 565 |
497 // Reset state for the current execution. | 566 // Reset state for the current execution. |
498 abandoned_ = false; | 567 abandoned_ = false; |
499 num_dns_ = 0; | 568 num_dns_ = 0; |
500 alerts_and_errors_.clear(); | 569 alerts_and_errors_.clear(); |
(...skipping 10 matching lines...) Expand all Loading... |
511 return; | 580 return; |
512 } | 581 } |
513 | 582 |
514 if (abandoned_) | 583 if (abandoned_) |
515 return; | 584 return; |
516 | 585 |
517 DispatchBufferedAlertsAndErrors(); | 586 DispatchBufferedAlertsAndErrors(); |
518 NotifyCaller(result); | 587 NotifyCaller(result); |
519 } | 588 } |
520 | 589 |
521 int ProxyResolverV8Tracing::Job::ExecuteProxyResolver() { | 590 int Job::ExecuteProxyResolver() { |
522 JSBindings* prev_bindings = v8_resolver()->js_bindings(); | |
523 v8_resolver()->set_js_bindings(this); | |
524 | |
525 int result = ERR_UNEXPECTED; // Initialized to silence warnings. | 591 int result = ERR_UNEXPECTED; // Initialized to silence warnings. |
526 | 592 |
527 switch (operation_) { | 593 switch (operation_) { |
528 case SET_PAC_SCRIPT: | 594 case CREATE_V8_RESOLVER: { |
529 result = v8_resolver()->SetPacScript( | 595 scoped_ptr<ProxyResolverV8> resolver(new ProxyResolverV8); |
530 script_data_, CompletionCallback()); | 596 resolver->set_js_bindings(this); |
| 597 result = resolver->SetPacScript(script_data_, CompletionCallback()); |
| 598 resolver->set_js_bindings(nullptr); |
| 599 if (result == OK) |
| 600 *resolver_out_ = resolver.Pass(); |
531 break; | 601 break; |
532 case GET_PROXY_FOR_URL: | 602 } |
| 603 case GET_PROXY_FOR_URL: { |
| 604 JSBindings* prev_bindings = v8_resolver()->js_bindings(); |
| 605 v8_resolver()->set_js_bindings(this); |
| 606 |
533 result = v8_resolver()->GetProxyForURL( | 607 result = v8_resolver()->GetProxyForURL( |
534 url_, | 608 url_, |
535 // Important: Do not write directly into |user_results_|, since if the | 609 // Important: Do not write directly into |user_results_|, since if the |
536 // request were to be cancelled from the origin thread, must guarantee | 610 // request were to be cancelled from the origin thread, must guarantee |
537 // that |user_results_| is not accessed anymore. | 611 // that |user_results_| is not accessed anymore. |
538 &results_, | 612 &results_, |
539 CompletionCallback(), | 613 CompletionCallback(), |
540 NULL, | 614 NULL, |
541 bound_net_log_); | 615 bound_net_log_); |
| 616 v8_resolver()->set_js_bindings(prev_bindings); |
542 break; | 617 break; |
| 618 } |
543 } | 619 } |
544 | 620 |
545 v8_resolver()->set_js_bindings(prev_bindings); | |
546 | |
547 return result; | 621 return result; |
548 } | 622 } |
549 | 623 |
550 bool ProxyResolverV8Tracing::Job::ResolveDns(const std::string& host, | 624 bool Job::ResolveDns(const std::string& host, |
551 ResolveDnsOperation op, | 625 ResolveDnsOperation op, |
552 std::string* output, | 626 std::string* output, |
553 bool* terminate) { | 627 bool* terminate) { |
554 if (cancelled_.IsSet()) { | 628 if (cancelled_.IsSet()) { |
555 *terminate = true; | 629 *terminate = true; |
556 return false; | 630 return false; |
557 } | 631 } |
558 | 632 |
559 if ((op == DNS_RESOLVE || op == DNS_RESOLVE_EX) && host.empty()) { | 633 if ((op == DNS_RESOLVE || op == DNS_RESOLVE_EX) && host.empty()) { |
560 // a DNS resolve with an empty hostname is considered an error. | 634 // a DNS resolve with an empty hostname is considered an error. |
561 return false; | 635 return false; |
562 } | 636 } |
563 | 637 |
564 return blocking_dns_ ? | 638 return blocking_dns_ ? |
565 ResolveDnsBlocking(host, op, output) : | 639 ResolveDnsBlocking(host, op, output) : |
566 ResolveDnsNonBlocking(host, op, output, terminate); | 640 ResolveDnsNonBlocking(host, op, output, terminate); |
567 } | 641 } |
568 | 642 |
569 void ProxyResolverV8Tracing::Job::Alert(const base::string16& message) { | 643 void Job::Alert(const base::string16& message) { |
570 HandleAlertOrError(true, -1, message); | 644 HandleAlertOrError(true, -1, message); |
571 } | 645 } |
572 | 646 |
573 void ProxyResolverV8Tracing::Job::OnError(int line_number, | 647 void Job::OnError(int line_number, const base::string16& error) { |
574 const base::string16& error) { | |
575 HandleAlertOrError(false, line_number, error); | 648 HandleAlertOrError(false, line_number, error); |
576 } | 649 } |
577 | 650 |
578 bool ProxyResolverV8Tracing::Job::ResolveDnsBlocking(const std::string& host, | 651 bool Job::ResolveDnsBlocking(const std::string& host, |
579 ResolveDnsOperation op, | 652 ResolveDnsOperation op, |
580 std::string* output) { | 653 std::string* output) { |
581 CheckIsOnWorkerThread(); | 654 CheckIsOnWorkerThread(); |
582 | 655 |
583 // Check if the DNS result for this host has already been cached. | 656 // Check if the DNS result for this host has already been cached. |
584 bool rv; | 657 bool rv; |
585 if (GetDnsFromLocalCache(host, op, output, &rv)) { | 658 if (GetDnsFromLocalCache(host, op, output, &rv)) { |
586 // Yay, cache hit! | 659 // Yay, cache hit! |
587 return rv; | 660 return rv; |
588 } | 661 } |
589 | 662 |
590 if (dns_cache_.size() >= kMaxUniqueResolveDnsPerExec) { | 663 if (dns_cache_.size() >= kMaxUniqueResolveDnsPerExec) { |
591 // Safety net for scripts with unexpectedly many DNS calls. | 664 // Safety net for scripts with unexpectedly many DNS calls. |
592 // We will continue running to completion, but will fail every | 665 // We will continue running to completion, but will fail every |
593 // subsequent DNS request. | 666 // subsequent DNS request. |
594 return false; | 667 return false; |
595 } | 668 } |
596 | 669 |
597 if (!PostDnsOperationAndWait(host, op, NULL)) | 670 if (!PostDnsOperationAndWait(host, op, NULL)) |
598 return false; // Was cancelled. | 671 return false; // Was cancelled. |
599 | 672 |
600 CHECK(GetDnsFromLocalCache(host, op, output, &rv)); | 673 CHECK(GetDnsFromLocalCache(host, op, output, &rv)); |
601 return rv; | 674 return rv; |
602 } | 675 } |
603 | 676 |
604 bool ProxyResolverV8Tracing::Job::ResolveDnsNonBlocking(const std::string& host, | 677 bool Job::ResolveDnsNonBlocking(const std::string& host, |
605 ResolveDnsOperation op, | 678 ResolveDnsOperation op, |
606 std::string* output, | 679 std::string* output, |
607 bool* terminate) { | 680 bool* terminate) { |
608 CheckIsOnWorkerThread(); | 681 CheckIsOnWorkerThread(); |
609 | 682 |
610 if (abandoned_) { | 683 if (abandoned_) { |
611 // If this execution was already abandoned can fail right away. Only 1 DNS | 684 // If this execution was already abandoned can fail right away. Only 1 DNS |
612 // dependency will be traced at a time (for more predictable outcomes). | 685 // dependency will be traced at a time (for more predictable outcomes). |
613 return false; | 686 return false; |
614 } | 687 } |
615 | 688 |
616 num_dns_ += 1; | 689 num_dns_ += 1; |
617 | 690 |
(...skipping 29 matching lines...) Expand all Loading... |
647 | 720 |
648 // Otherwise if the result was not in the cache, then a DNS request has | 721 // Otherwise if the result was not in the cache, then a DNS request has |
649 // been started. Abandon this invocation of FindProxyForURL(), it will be | 722 // been started. Abandon this invocation of FindProxyForURL(), it will be |
650 // restarted once the DNS request completes. | 723 // restarted once the DNS request completes. |
651 abandoned_ = true; | 724 abandoned_ = true; |
652 *terminate = true; | 725 *terminate = true; |
653 last_num_dns_ = num_dns_; | 726 last_num_dns_ = num_dns_; |
654 return false; | 727 return false; |
655 } | 728 } |
656 | 729 |
657 bool ProxyResolverV8Tracing::Job::PostDnsOperationAndWait( | 730 bool Job::PostDnsOperationAndWait(const std::string& host, |
658 const std::string& host, ResolveDnsOperation op, | 731 ResolveDnsOperation op, |
659 bool* completed_synchronously) { | 732 bool* completed_synchronously) { |
660 | |
661 // Post the DNS request to the origin thread. | 733 // Post the DNS request to the origin thread. |
662 DCHECK(!pending_dns_); | 734 DCHECK(!pending_dns_); |
663 pending_dns_host_ = host; | 735 pending_dns_host_ = host; |
664 pending_dns_op_ = op; | 736 pending_dns_op_ = op; |
665 origin_runner_->PostTask(FROM_HERE, base::Bind(&Job::DoDnsOperation, this)); | 737 origin_runner_->PostTask(FROM_HERE, base::Bind(&Job::DoDnsOperation, this)); |
666 | 738 |
667 event_.Wait(); | 739 event_.Wait(); |
668 event_.Reset(); | 740 event_.Reset(); |
669 | 741 |
670 if (cancelled_.IsSet()) | 742 if (cancelled_.IsSet()) |
671 return false; | 743 return false; |
672 | 744 |
673 if (completed_synchronously) | 745 if (completed_synchronously) |
674 *completed_synchronously = pending_dns_completed_synchronously_; | 746 *completed_synchronously = pending_dns_completed_synchronously_; |
675 | 747 |
676 return true; | 748 return true; |
677 } | 749 } |
678 | 750 |
679 void ProxyResolverV8Tracing::Job::DoDnsOperation() { | 751 void Job::DoDnsOperation() { |
680 CheckIsOnOriginThread(); | 752 CheckIsOnOriginThread(); |
681 DCHECK(!pending_dns_); | 753 DCHECK(!pending_dns_); |
682 | 754 |
683 if (cancelled_.IsSet()) | 755 if (cancelled_.IsSet()) |
684 return; | 756 return; |
685 | 757 |
686 HostResolver::RequestHandle dns_request = NULL; | 758 HostResolver::RequestHandle dns_request = NULL; |
687 int result = host_resolver()->Resolve( | 759 int result = host_resolver()->Resolve( |
688 MakeDnsRequestInfo(pending_dns_host_, pending_dns_op_), | 760 MakeDnsRequestInfo(pending_dns_host_, pending_dns_op_), |
689 DEFAULT_PRIORITY, | 761 DEFAULT_PRIORITY, |
(...skipping 11 matching lines...) Expand all Loading... |
701 if (!pending_dns_completed_synchronously_) | 773 if (!pending_dns_completed_synchronously_) |
702 host_resolver()->CancelRequest(dns_request); | 774 host_resolver()->CancelRequest(dns_request); |
703 return; | 775 return; |
704 } | 776 } |
705 | 777 |
706 if (pending_dns_completed_synchronously_) { | 778 if (pending_dns_completed_synchronously_) { |
707 OnDnsOperationComplete(result); | 779 OnDnsOperationComplete(result); |
708 } else { | 780 } else { |
709 DCHECK(dns_request); | 781 DCHECK(dns_request); |
710 pending_dns_ = dns_request; | 782 pending_dns_ = dns_request; |
711 if (!parent_->on_load_state_changed_.is_null()) { | 783 if (!params_->on_load_state_changed.is_null()) { |
712 parent_->on_load_state_changed_.Run( | 784 params_->on_load_state_changed.Run( |
713 this, LOAD_STATE_RESOLVING_HOST_IN_PROXY_SCRIPT); | 785 this, LOAD_STATE_RESOLVING_HOST_IN_PROXY_SCRIPT); |
714 } | 786 } |
715 // OnDnsOperationComplete() will be called by host resolver on completion. | 787 // OnDnsOperationComplete() will be called by host resolver on completion. |
716 } | 788 } |
717 | 789 |
718 if (!blocking_dns_) { | 790 if (!blocking_dns_) { |
719 // The worker thread always blocks waiting to see if the result can be | 791 // The worker thread always blocks waiting to see if the result can be |
720 // serviced from cache before restarting. | 792 // serviced from cache before restarting. |
721 event_.Signal(); | 793 event_.Signal(); |
722 } | 794 } |
723 } | 795 } |
724 | 796 |
725 void ProxyResolverV8Tracing::Job::OnDnsOperationComplete(int result) { | 797 void Job::OnDnsOperationComplete(int result) { |
726 CheckIsOnOriginThread(); | 798 CheckIsOnOriginThread(); |
727 | 799 |
728 DCHECK(!cancelled_.IsSet()); | 800 DCHECK(!cancelled_.IsSet()); |
729 DCHECK(pending_dns_completed_synchronously_ == (pending_dns_ == NULL)); | 801 DCHECK(pending_dns_completed_synchronously_ == (pending_dns_ == NULL)); |
730 | 802 |
731 SaveDnsToLocalCache(pending_dns_host_, pending_dns_op_, result, | 803 SaveDnsToLocalCache(pending_dns_host_, pending_dns_op_, result, |
732 pending_dns_addresses_); | 804 pending_dns_addresses_); |
733 pending_dns_ = NULL; | 805 pending_dns_ = NULL; |
734 | 806 |
735 if (!parent_->on_load_state_changed_.is_null() && | 807 if (!params_->on_load_state_changed.is_null() && |
736 !pending_dns_completed_synchronously_ && !cancelled_.IsSet()) { | 808 !pending_dns_completed_synchronously_ && !cancelled_.IsSet()) { |
737 parent_->on_load_state_changed_.Run(this, | 809 params_->on_load_state_changed.Run(this, |
738 LOAD_STATE_RESOLVING_PROXY_FOR_URL); | 810 LOAD_STATE_RESOLVING_PROXY_FOR_URL); |
739 } | 811 } |
740 | 812 |
741 if (blocking_dns_) { | 813 if (blocking_dns_) { |
742 event_.Signal(); | 814 event_.Signal(); |
743 return; | 815 return; |
744 } | 816 } |
745 | 817 |
746 if (!blocking_dns_ && !pending_dns_completed_synchronously_) { | 818 if (!blocking_dns_ && !pending_dns_completed_synchronously_) { |
747 // Restart. This time it should make more progress due to having | 819 // Restart. This time it should make more progress due to having |
748 // cached items. | 820 // cached items. |
749 worker_loop()->PostTask(FROM_HERE, | 821 worker_task_runner()->PostTask(FROM_HERE, |
750 base::Bind(&Job::ExecuteNonBlocking, this)); | 822 base::Bind(&Job::ExecuteNonBlocking, this)); |
751 } | 823 } |
752 } | 824 } |
753 | 825 |
754 void ProxyResolverV8Tracing::Job::ScheduleRestartWithBlockingDns() { | 826 void Job::ScheduleRestartWithBlockingDns() { |
755 CheckIsOnWorkerThread(); | 827 CheckIsOnWorkerThread(); |
756 | 828 |
757 DCHECK(!should_restart_with_blocking_dns_); | 829 DCHECK(!should_restart_with_blocking_dns_); |
758 DCHECK(!abandoned_); | 830 DCHECK(!abandoned_); |
759 DCHECK(!blocking_dns_); | 831 DCHECK(!blocking_dns_); |
760 | 832 |
761 abandoned_ = true; | 833 abandoned_ = true; |
762 | 834 |
763 // The restart will happen after ExecuteNonBlocking() finishes. | 835 // The restart will happen after ExecuteNonBlocking() finishes. |
764 should_restart_with_blocking_dns_ = true; | 836 should_restart_with_blocking_dns_ = true; |
765 } | 837 } |
766 | 838 |
767 bool ProxyResolverV8Tracing::Job::GetDnsFromLocalCache( | 839 bool Job::GetDnsFromLocalCache(const std::string& host, |
768 const std::string& host, | 840 ResolveDnsOperation op, |
769 ResolveDnsOperation op, | 841 std::string* output, |
770 std::string* output, | 842 bool* return_value) { |
771 bool* return_value) { | |
772 CheckIsOnWorkerThread(); | 843 CheckIsOnWorkerThread(); |
773 | 844 |
774 DnsCache::const_iterator it = dns_cache_.find(MakeDnsCacheKey(host, op)); | 845 DnsCache::const_iterator it = dns_cache_.find(MakeDnsCacheKey(host, op)); |
775 if (it == dns_cache_.end()) | 846 if (it == dns_cache_.end()) |
776 return false; | 847 return false; |
777 | 848 |
778 *output = it->second; | 849 *output = it->second; |
779 *return_value = !it->second.empty(); | 850 *return_value = !it->second.empty(); |
780 return true; | 851 return true; |
781 } | 852 } |
782 | 853 |
783 void ProxyResolverV8Tracing::Job::SaveDnsToLocalCache( | 854 void Job::SaveDnsToLocalCache(const std::string& host, |
784 const std::string& host, | 855 ResolveDnsOperation op, |
785 ResolveDnsOperation op, | 856 int net_error, |
786 int net_error, | 857 const AddressList& addresses) { |
787 const AddressList& addresses) { | |
788 CheckIsOnOriginThread(); | 858 CheckIsOnOriginThread(); |
789 | 859 |
790 // Serialize the result into a string to save to the cache. | 860 // Serialize the result into a string to save to the cache. |
791 std::string cache_value; | 861 std::string cache_value; |
792 if (net_error != OK) { | 862 if (net_error != OK) { |
793 cache_value = std::string(); | 863 cache_value = std::string(); |
794 } else if (op == DNS_RESOLVE || op == MY_IP_ADDRESS) { | 864 } else if (op == DNS_RESOLVE || op == MY_IP_ADDRESS) { |
795 // dnsResolve() and myIpAddress() are expected to return a single IP | 865 // dnsResolve() and myIpAddress() are expected to return a single IP |
796 // address. | 866 // address. |
797 cache_value = addresses.front().ToStringWithoutPort(); | 867 cache_value = addresses.front().ToStringWithoutPort(); |
798 } else { | 868 } else { |
799 // The *Ex versions are expected to return a semi-colon separated list. | 869 // The *Ex versions are expected to return a semi-colon separated list. |
800 for (AddressList::const_iterator iter = addresses.begin(); | 870 for (AddressList::const_iterator iter = addresses.begin(); |
801 iter != addresses.end(); ++iter) { | 871 iter != addresses.end(); ++iter) { |
802 if (!cache_value.empty()) | 872 if (!cache_value.empty()) |
803 cache_value += ";"; | 873 cache_value += ";"; |
804 cache_value += iter->ToStringWithoutPort(); | 874 cache_value += iter->ToStringWithoutPort(); |
805 } | 875 } |
806 } | 876 } |
807 | 877 |
808 dns_cache_[MakeDnsCacheKey(host, op)] = cache_value; | 878 dns_cache_[MakeDnsCacheKey(host, op)] = cache_value; |
809 } | 879 } |
810 | 880 |
811 // static | 881 // static |
812 HostResolver::RequestInfo ProxyResolverV8Tracing::Job::MakeDnsRequestInfo( | 882 HostResolver::RequestInfo Job::MakeDnsRequestInfo(const std::string& host, |
813 const std::string& host, ResolveDnsOperation op) { | 883 ResolveDnsOperation op) { |
814 HostPortPair host_port = HostPortPair(host, 80); | 884 HostPortPair host_port = HostPortPair(host, 80); |
815 if (op == MY_IP_ADDRESS || op == MY_IP_ADDRESS_EX) { | 885 if (op == MY_IP_ADDRESS || op == MY_IP_ADDRESS_EX) { |
816 host_port.set_host(GetHostName()); | 886 host_port.set_host(GetHostName()); |
817 } | 887 } |
818 | 888 |
819 HostResolver::RequestInfo info(host_port); | 889 HostResolver::RequestInfo info(host_port); |
820 // Flag myIpAddress requests. | 890 // Flag myIpAddress requests. |
821 if (op == MY_IP_ADDRESS || op == MY_IP_ADDRESS_EX) { | 891 if (op == MY_IP_ADDRESS || op == MY_IP_ADDRESS_EX) { |
822 // TODO: Provide a RequestInfo construction mechanism that does not | 892 // TODO: Provide a RequestInfo construction mechanism that does not |
823 // require a hostname and sets is_my_ip_address to true instead of this. | 893 // require a hostname and sets is_my_ip_address to true instead of this. |
824 info.set_is_my_ip_address(true); | 894 info.set_is_my_ip_address(true); |
825 } | 895 } |
826 // The non-ex flavors are limited to IPv4 results. | 896 // The non-ex flavors are limited to IPv4 results. |
827 if (op == MY_IP_ADDRESS || op == DNS_RESOLVE) { | 897 if (op == MY_IP_ADDRESS || op == DNS_RESOLVE) { |
828 info.set_address_family(ADDRESS_FAMILY_IPV4); | 898 info.set_address_family(ADDRESS_FAMILY_IPV4); |
829 } | 899 } |
830 | 900 |
831 return info; | 901 return info; |
832 } | 902 } |
833 | 903 |
834 std::string ProxyResolverV8Tracing::Job::MakeDnsCacheKey( | 904 std::string Job::MakeDnsCacheKey(const std::string& host, |
835 const std::string& host, ResolveDnsOperation op) { | 905 ResolveDnsOperation op) { |
836 return base::StringPrintf("%d:%s", op, host.c_str()); | 906 return base::StringPrintf("%d:%s", op, host.c_str()); |
837 } | 907 } |
838 | 908 |
839 void ProxyResolverV8Tracing::Job::HandleAlertOrError( | 909 void Job::HandleAlertOrError(bool is_alert, |
840 bool is_alert, | 910 int line_number, |
841 int line_number, | 911 const base::string16& message) { |
842 const base::string16& message) { | |
843 CheckIsOnWorkerThread(); | 912 CheckIsOnWorkerThread(); |
844 | 913 |
845 if (cancelled_.IsSet()) | 914 if (cancelled_.IsSet()) |
846 return; | 915 return; |
847 | 916 |
848 if (blocking_dns_) { | 917 if (blocking_dns_) { |
849 // In blocking DNS mode the events can be dispatched immediately. | 918 // In blocking DNS mode the events can be dispatched immediately. |
850 DispatchAlertOrError(is_alert, line_number, message); | 919 DispatchAlertOrError(is_alert, line_number, message); |
851 return; | 920 return; |
852 } | 921 } |
(...skipping 11 matching lines...) Expand all Loading... |
864 // Avoid this by falling back to blocking mode. | 933 // Avoid this by falling back to blocking mode. |
865 if (alerts_and_errors_byte_cost_ > kMaxAlertsAndErrorsBytes) { | 934 if (alerts_and_errors_byte_cost_ > kMaxAlertsAndErrorsBytes) { |
866 ScheduleRestartWithBlockingDns(); | 935 ScheduleRestartWithBlockingDns(); |
867 return; | 936 return; |
868 } | 937 } |
869 | 938 |
870 AlertOrError entry = {is_alert, line_number, message}; | 939 AlertOrError entry = {is_alert, line_number, message}; |
871 alerts_and_errors_.push_back(entry); | 940 alerts_and_errors_.push_back(entry); |
872 } | 941 } |
873 | 942 |
874 void ProxyResolverV8Tracing::Job::DispatchBufferedAlertsAndErrors() { | 943 void Job::DispatchBufferedAlertsAndErrors() { |
875 CheckIsOnWorkerThread(); | 944 CheckIsOnWorkerThread(); |
876 DCHECK(!blocking_dns_); | 945 DCHECK(!blocking_dns_); |
877 DCHECK(!abandoned_); | 946 DCHECK(!abandoned_); |
878 | 947 |
879 for (size_t i = 0; i < alerts_and_errors_.size(); ++i) { | 948 for (size_t i = 0; i < alerts_and_errors_.size(); ++i) { |
880 const AlertOrError& x = alerts_and_errors_[i]; | 949 const AlertOrError& x = alerts_and_errors_[i]; |
881 DispatchAlertOrError(x.is_alert, x.line_number, x.message); | 950 DispatchAlertOrError(x.is_alert, x.line_number, x.message); |
882 } | 951 } |
883 } | 952 } |
884 | 953 |
885 void ProxyResolverV8Tracing::Job::DispatchAlertOrError( | 954 void Job::DispatchAlertOrError(bool is_alert, |
886 bool is_alert, int line_number, const base::string16& message) { | 955 int line_number, |
| 956 const base::string16& message) { |
887 CheckIsOnWorkerThread(); | 957 CheckIsOnWorkerThread(); |
888 | 958 |
889 // Note that the handling of cancellation is racy with regard to | 959 // Note that the handling of cancellation is racy with regard to |
890 // alerts/errors. The request might get cancelled shortly after this | 960 // alerts/errors. The request might get cancelled shortly after this |
891 // check! (There is no lock being held to guarantee otherwise). | 961 // check! (There is no lock being held to guarantee otherwise). |
892 // | 962 // |
893 // If this happens, then some information will get written to the NetLog | 963 // If this happens, then some information will get written to the NetLog |
894 // needlessly, however the NetLog will still be alive so it shouldn't cause | 964 // needlessly, however the NetLog will still be alive so it shouldn't cause |
895 // problems. | 965 // problems. |
896 if (cancelled_.IsSet()) | 966 if (cancelled_.IsSet()) |
(...skipping 21 matching lines...) Expand all Loading... |
918 // Send the error to the NetLog. | 988 // Send the error to the NetLog. |
919 LogEventToCurrentRequestAndGlobally( | 989 LogEventToCurrentRequestAndGlobally( |
920 NetLog::TYPE_PAC_JAVASCRIPT_ERROR, | 990 NetLog::TYPE_PAC_JAVASCRIPT_ERROR, |
921 base::Bind(&NetLogErrorCallback, line_number, &message)); | 991 base::Bind(&NetLogErrorCallback, line_number, &message)); |
922 | 992 |
923 if (error_observer()) | 993 if (error_observer()) |
924 error_observer()->OnPACScriptError(line_number, message); | 994 error_observer()->OnPACScriptError(line_number, message); |
925 } | 995 } |
926 } | 996 } |
927 | 997 |
928 void ProxyResolverV8Tracing::Job::LogEventToCurrentRequestAndGlobally( | 998 void Job::LogEventToCurrentRequestAndGlobally( |
929 NetLog::EventType type, | 999 NetLog::EventType type, |
930 const NetLog::ParametersCallback& parameters_callback) { | 1000 const NetLog::ParametersCallback& parameters_callback) { |
931 CheckIsOnWorkerThread(); | 1001 CheckIsOnWorkerThread(); |
932 bound_net_log_.AddEvent(type, parameters_callback); | 1002 bound_net_log_.AddEvent(type, parameters_callback); |
933 | 1003 |
934 // Emit to the global NetLog event stream. | 1004 // Emit to the global NetLog event stream. |
935 if (net_log()) | 1005 if (net_log()) |
936 net_log()->AddGlobalEntry(type, parameters_callback); | 1006 net_log()->AddGlobalEntry(type, parameters_callback); |
937 } | 1007 } |
938 | 1008 |
939 ProxyResolverV8Tracing::ProxyResolverV8Tracing( | 1009 ProxyResolverV8Tracing::ProxyResolverV8Tracing( |
940 HostResolver* host_resolver, | 1010 scoped_ptr<ProxyResolverErrorObserver> error_observer, |
941 ProxyResolverErrorObserver* error_observer, | 1011 scoped_ptr<base::Thread> thread, |
942 NetLog* net_log) | 1012 scoped_ptr<ProxyResolverV8> resolver, |
943 : ProxyResolverV8Tracing(host_resolver, | 1013 scoped_ptr<Job::Params> job_params) |
944 error_observer, | |
945 net_log, | |
946 LoadStateChangedCallback()) { | |
947 } | |
948 | |
949 ProxyResolverV8Tracing::ProxyResolverV8Tracing( | |
950 HostResolver* host_resolver, | |
951 ProxyResolverErrorObserver* error_observer, | |
952 NetLog* net_log, | |
953 const LoadStateChangedCallback& on_load_state_changed) | |
954 : ProxyResolver(true /*expects_pac_bytes*/), | 1014 : ProxyResolver(true /*expects_pac_bytes*/), |
955 host_resolver_(host_resolver), | 1015 thread_(thread.Pass()), |
956 error_observer_(error_observer), | 1016 v8_resolver_(resolver.Pass()), |
957 net_log_(net_log), | 1017 error_observer_(error_observer.Pass()), |
958 num_outstanding_callbacks_(0), | 1018 job_params_(job_params.Pass()), |
959 on_load_state_changed_(on_load_state_changed) { | 1019 num_outstanding_callbacks_(0) { |
960 DCHECK(host_resolver); | 1020 job_params_->num_outstanding_callbacks = &num_outstanding_callbacks_; |
961 // Start up the thread. | |
962 thread_.reset(new base::Thread("Proxy resolver")); | |
963 base::Thread::Options options; | |
964 options.timer_slack = base::TIMER_SLACK_MAXIMUM; | |
965 CHECK(thread_->StartWithOptions(options)); | |
966 | |
967 v8_resolver_.reset(new ProxyResolverV8); | |
968 } | 1021 } |
969 | 1022 |
970 ProxyResolverV8Tracing::~ProxyResolverV8Tracing() { | 1023 ProxyResolverV8Tracing::~ProxyResolverV8Tracing() { |
971 // Note, all requests should have been cancelled. | 1024 // Note, all requests should have been cancelled. |
972 CHECK(!set_pac_script_job_.get()); | |
973 CHECK_EQ(0, num_outstanding_callbacks_); | 1025 CHECK_EQ(0, num_outstanding_callbacks_); |
974 | 1026 |
975 // Join the worker thread. See http://crbug.com/69710. Note that we call | 1027 // Join the worker thread. See http://crbug.com/69710. |
976 // Stop() here instead of simply clearing thread_ since there may be pending | |
977 // callbacks on the worker thread which want to dereference thread_. | |
978 base::ThreadRestrictions::ScopedAllowIO allow_io; | 1028 base::ThreadRestrictions::ScopedAllowIO allow_io; |
979 thread_->Stop(); | 1029 thread_.reset(); |
980 } | 1030 } |
981 | 1031 |
982 int ProxyResolverV8Tracing::GetProxyForURL(const GURL& url, | 1032 int ProxyResolverV8Tracing::GetProxyForURL(const GURL& url, |
983 ProxyInfo* results, | 1033 ProxyInfo* results, |
984 const CompletionCallback& callback, | 1034 const CompletionCallback& callback, |
985 RequestHandle* request, | 1035 RequestHandle* request, |
986 const BoundNetLog& net_log) { | 1036 const BoundNetLog& net_log) { |
987 DCHECK(CalledOnValidThread()); | 1037 DCHECK(CalledOnValidThread()); |
988 DCHECK(!callback.is_null()); | 1038 DCHECK(!callback.is_null()); |
989 DCHECK(!set_pac_script_job_.get()); | |
990 | 1039 |
991 scoped_refptr<Job> job = new Job(this); | 1040 scoped_refptr<Job> job = new Job(job_params_.get()); |
992 | 1041 |
993 if (request) | 1042 if (request) |
994 *request = job.get(); | 1043 *request = job.get(); |
995 | 1044 |
996 job->StartGetProxyForURL(url, results, net_log, callback); | 1045 job->StartGetProxyForURL(url, results, net_log, callback); |
997 return ERR_IO_PENDING; | 1046 return ERR_IO_PENDING; |
998 } | 1047 } |
999 | 1048 |
1000 void ProxyResolverV8Tracing::CancelRequest(RequestHandle request) { | 1049 void ProxyResolverV8Tracing::CancelRequest(RequestHandle request) { |
1001 Job* job = reinterpret_cast<Job*>(request); | 1050 Job* job = reinterpret_cast<Job*>(request); |
1002 job->Cancel(); | 1051 job->Cancel(); |
1003 } | 1052 } |
1004 | 1053 |
1005 LoadState ProxyResolverV8Tracing::GetLoadState(RequestHandle request) const { | 1054 LoadState ProxyResolverV8Tracing::GetLoadState(RequestHandle request) const { |
1006 Job* job = reinterpret_cast<Job*>(request); | 1055 Job* job = reinterpret_cast<Job*>(request); |
1007 return job->GetLoadState(); | 1056 return job->GetLoadState(); |
1008 } | 1057 } |
1009 | 1058 |
1010 void ProxyResolverV8Tracing::CancelSetPacScript() { | 1059 void ProxyResolverV8Tracing::CancelSetPacScript() { |
1011 DCHECK(set_pac_script_job_.get()); | 1060 NOTREACHED(); |
1012 set_pac_script_job_->Cancel(); | |
1013 set_pac_script_job_ = NULL; | |
1014 } | 1061 } |
1015 | 1062 |
1016 int ProxyResolverV8Tracing::SetPacScript( | 1063 int ProxyResolverV8Tracing::SetPacScript( |
1017 const scoped_refptr<ProxyResolverScriptData>& script_data, | 1064 const scoped_refptr<ProxyResolverScriptData>& script_data, |
1018 const CompletionCallback& callback) { | 1065 const CompletionCallback& callback) { |
1019 DCHECK(CalledOnValidThread()); | 1066 NOTREACHED(); |
1020 DCHECK(!callback.is_null()); | 1067 return ERR_NOT_IMPLEMENTED; |
| 1068 } |
1021 | 1069 |
1022 // Note that there should not be any outstanding (non-cancelled) Jobs when | 1070 } // namespace |
1023 // setting the PAC script (ProxyService should guarantee this). If there are, | |
1024 // then they might complete in strange ways after the new script is set. | |
1025 DCHECK(!set_pac_script_job_.get()); | |
1026 CHECK_EQ(0, num_outstanding_callbacks_); | |
1027 | 1071 |
1028 set_pac_script_job_ = new Job(this); | 1072 class ProxyResolverFactoryV8Tracing::CreateJob |
1029 set_pac_script_job_->StartSetPacScript(script_data, callback); | 1073 : public ProxyResolverFactory::Request { |
| 1074 public: |
| 1075 CreateJob(ProxyResolverFactoryV8Tracing* factory, |
| 1076 HostResolver* host_resolver, |
| 1077 scoped_ptr<ProxyResolverErrorObserver> error_observer, |
| 1078 NetLog* net_log, |
| 1079 const ProxyResolver::LoadStateChangedCallback& |
| 1080 load_state_changed_callback, |
| 1081 const scoped_refptr<ProxyResolverScriptData>& pac_script, |
| 1082 scoped_ptr<ProxyResolver>* resolver_out, |
| 1083 const CompletionCallback& callback) |
| 1084 : factory_(factory), |
| 1085 thread_(new base::Thread("Proxy Resolver")), |
| 1086 error_observer_(error_observer.Pass()), |
| 1087 resolver_out_(resolver_out), |
| 1088 callback_(callback), |
| 1089 num_outstanding_callbacks_(0) { |
| 1090 // Start up the thread. |
| 1091 base::Thread::Options options; |
| 1092 options.timer_slack = base::TIMER_SLACK_MAXIMUM; |
| 1093 CHECK(thread_->StartWithOptions(options)); |
| 1094 job_params_.reset(new Job::Params( |
| 1095 thread_->task_runner(), host_resolver, error_observer_.get(), net_log, |
| 1096 load_state_changed_callback, &num_outstanding_callbacks_)); |
| 1097 create_resolver_job_ = new Job(job_params_.get()); |
| 1098 create_resolver_job_->StartCreateV8Resolver( |
| 1099 pac_script, &v8_resolver_, |
| 1100 base::Bind( |
| 1101 &ProxyResolverFactoryV8Tracing::CreateJob::OnV8ResolverCreated, |
| 1102 base::Unretained(this))); |
| 1103 } |
1030 | 1104 |
| 1105 ~CreateJob() override { |
| 1106 if (factory_) { |
| 1107 factory_->RemoveJob(this); |
| 1108 DCHECK(create_resolver_job_); |
| 1109 create_resolver_job_->Cancel(); |
| 1110 StopWorkerThread(); |
| 1111 } |
| 1112 DCHECK_EQ(0, num_outstanding_callbacks_); |
| 1113 } |
| 1114 |
| 1115 void FactoryDestroyed() { |
| 1116 factory_ = nullptr; |
| 1117 create_resolver_job_->Cancel(); |
| 1118 create_resolver_job_ = nullptr; |
| 1119 StopWorkerThread(); |
| 1120 } |
| 1121 |
| 1122 private: |
| 1123 void OnV8ResolverCreated(int error) { |
| 1124 DCHECK(factory_); |
| 1125 if (error == OK) { |
| 1126 job_params_->v8_resolver = v8_resolver_.get(); |
| 1127 resolver_out_->reset( |
| 1128 new ProxyResolverV8Tracing(error_observer_.Pass(), thread_.Pass(), |
| 1129 v8_resolver_.Pass(), job_params_.Pass())); |
| 1130 } else { |
| 1131 StopWorkerThread(); |
| 1132 } |
| 1133 |
| 1134 factory_->RemoveJob(this); |
| 1135 factory_ = nullptr; |
| 1136 create_resolver_job_ = nullptr; |
| 1137 callback_.Run(error); |
| 1138 } |
| 1139 |
| 1140 void StopWorkerThread() { |
| 1141 // Join the worker thread. See http://crbug.com/69710. |
| 1142 base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 1143 thread_.reset(); |
| 1144 } |
| 1145 |
| 1146 ProxyResolverFactoryV8Tracing* factory_; |
| 1147 scoped_ptr<base::Thread> thread_; |
| 1148 scoped_ptr<ProxyResolverErrorObserver> error_observer_; |
| 1149 scoped_ptr<Job::Params> job_params_; |
| 1150 scoped_refptr<Job> create_resolver_job_; |
| 1151 scoped_ptr<ProxyResolverV8> v8_resolver_; |
| 1152 scoped_ptr<ProxyResolver>* resolver_out_; |
| 1153 const CompletionCallback callback_; |
| 1154 int num_outstanding_callbacks_; |
| 1155 |
| 1156 DISALLOW_COPY_AND_ASSIGN(CreateJob); |
| 1157 }; |
| 1158 |
| 1159 ProxyResolverFactoryV8Tracing::ProxyResolverFactoryV8Tracing( |
| 1160 HostResolver* host_resolver, |
| 1161 NetLog* net_log, |
| 1162 const ProxyResolver::LoadStateChangedCallback& callback, |
| 1163 const base::Callback<scoped_ptr<ProxyResolverErrorObserver>()>& |
| 1164 error_observer_factory) |
| 1165 : ProxyResolverFactory(true), |
| 1166 host_resolver_(host_resolver), |
| 1167 net_log_(net_log), |
| 1168 load_state_changed_callback_(callback), |
| 1169 error_observer_factory_(error_observer_factory) { |
| 1170 } |
| 1171 |
| 1172 ProxyResolverFactoryV8Tracing::~ProxyResolverFactoryV8Tracing() { |
| 1173 for (auto job : jobs_) { |
| 1174 job->FactoryDestroyed(); |
| 1175 } |
| 1176 } |
| 1177 |
| 1178 // ProxyResolverFactory override. |
| 1179 int ProxyResolverFactoryV8Tracing::CreateProxyResolver( |
| 1180 const scoped_refptr<ProxyResolverScriptData>& pac_script, |
| 1181 scoped_ptr<ProxyResolver>* resolver, |
| 1182 const CompletionCallback& callback, |
| 1183 scoped_ptr<Request>* request) { |
| 1184 scoped_ptr<CreateJob> job(new CreateJob( |
| 1185 this, host_resolver_, |
| 1186 error_observer_factory_.is_null() ? nullptr |
| 1187 : error_observer_factory_.Run(), |
| 1188 net_log_, load_state_changed_callback_, pac_script, resolver, callback)); |
| 1189 jobs_.insert(job.get()); |
| 1190 *request = job.Pass(); |
1031 return ERR_IO_PENDING; | 1191 return ERR_IO_PENDING; |
1032 } | 1192 } |
1033 | 1193 |
| 1194 void ProxyResolverFactoryV8Tracing::RemoveJob( |
| 1195 ProxyResolverFactoryV8Tracing::CreateJob* job) { |
| 1196 size_t erased = jobs_.erase(job); |
| 1197 DCHECK_EQ(1u, erased); |
| 1198 } |
| 1199 |
1034 } // namespace net | 1200 } // namespace net |
OLD | NEW |