| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/single_threaded_proxy_resolver.h" | 5 #include "net/proxy/single_threaded_proxy_resolver.h" |
| 6 | 6 |
| 7 #include "base/thread.h" | 7 #include "base/thread.h" |
| 8 #include "net/base/load_log.h" | 8 #include "net/base/net_log.h" |
| 9 #include "net/base/net_errors.h" | 9 #include "net/base/net_errors.h" |
| 10 #include "net/proxy/proxy_info.h" | 10 #include "net/proxy/proxy_info.h" |
| 11 | 11 |
| 12 namespace net { | 12 namespace net { |
| 13 | 13 |
| 14 namespace { | 14 namespace { |
| 15 | 15 |
| 16 class PurgeMemoryTask : public base::RefCountedThreadSafe<PurgeMemoryTask> { | 16 class PurgeMemoryTask : public base::RefCountedThreadSafe<PurgeMemoryTask> { |
| 17 public: | 17 public: |
| 18 explicit PurgeMemoryTask(ProxyResolver* resolver) : resolver_(resolver) {} | 18 explicit PurgeMemoryTask(ProxyResolver* resolver) : resolver_(resolver) {} |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 class SingleThreadedProxyResolver::Job | 103 class SingleThreadedProxyResolver::Job |
| 104 : public base::RefCountedThreadSafe<SingleThreadedProxyResolver::Job> { | 104 : public base::RefCountedThreadSafe<SingleThreadedProxyResolver::Job> { |
| 105 public: | 105 public: |
| 106 // |coordinator| -- the SingleThreadedProxyResolver that owns this job. | 106 // |coordinator| -- the SingleThreadedProxyResolver that owns this job. |
| 107 // |url| -- the URL of the query. | 107 // |url| -- the URL of the query. |
| 108 // |results| -- the structure to fill with proxy resolve results. | 108 // |results| -- the structure to fill with proxy resolve results. |
| 109 Job(SingleThreadedProxyResolver* coordinator, | 109 Job(SingleThreadedProxyResolver* coordinator, |
| 110 const GURL& url, | 110 const GURL& url, |
| 111 ProxyInfo* results, | 111 ProxyInfo* results, |
| 112 CompletionCallback* callback, | 112 CompletionCallback* callback, |
| 113 LoadLog* load_log) | 113 const BoundNetLog& net_log) |
| 114 : coordinator_(coordinator), | 114 : coordinator_(coordinator), |
| 115 callback_(callback), | 115 callback_(callback), |
| 116 results_(results), | 116 results_(results), |
| 117 load_log_(load_log), | 117 net_log_(net_log), |
| 118 url_(url), | 118 url_(url), |
| 119 is_started_(false), | 119 is_started_(false), |
| 120 origin_loop_(MessageLoop::current()) { | 120 origin_loop_(MessageLoop::current()) { |
| 121 DCHECK(callback); | 121 DCHECK(callback); |
| 122 } | 122 } |
| 123 | 123 |
| 124 // Start the resolve proxy request on the worker thread. | 124 // Start the resolve proxy request on the worker thread. |
| 125 void Start() { | 125 void Start() { |
| 126 is_started_ = true; | 126 is_started_ = true; |
| 127 | 127 |
| 128 size_t load_log_bound = load_log_ ? load_log_->max_num_entries() : 0; | 128 size_t load_log_bound = 100; |
| 129 | 129 |
| 130 coordinator_->thread()->message_loop()->PostTask( | 130 coordinator_->thread()->message_loop()->PostTask( |
| 131 FROM_HERE, NewRunnableMethod(this, &Job::DoQuery, | 131 FROM_HERE, NewRunnableMethod(this, &Job::DoQuery, |
| 132 coordinator_->resolver_.get(), | 132 coordinator_->resolver_.get(), |
| 133 load_log_bound)); | 133 load_log_bound)); |
| 134 } | 134 } |
| 135 | 135 |
| 136 bool is_started() const { return is_started_; } | 136 bool is_started() const { return is_started_; } |
| 137 | 137 |
| 138 void Cancel() { | 138 void Cancel() { |
| 139 // Clear these to inform QueryComplete that it should not try to | 139 // Clear these to inform QueryComplete that it should not try to |
| 140 // access them. | 140 // access them. |
| 141 coordinator_ = NULL; | 141 coordinator_ = NULL; |
| 142 callback_ = NULL; | 142 callback_ = NULL; |
| 143 results_ = NULL; | 143 results_ = NULL; |
| 144 } | 144 } |
| 145 | 145 |
| 146 // Returns true if Cancel() has been called. | 146 // Returns true if Cancel() has been called. |
| 147 bool was_cancelled() const { return callback_ == NULL; } | 147 bool was_cancelled() const { return callback_ == NULL; } |
| 148 | 148 |
| 149 LoadLog* load_log() { return load_log_; } | 149 BoundNetLog* net_log() { return &net_log_; } |
| 150 | 150 |
| 151 private: | 151 private: |
| 152 friend class base::RefCountedThreadSafe<SingleThreadedProxyResolver::Job>; | 152 friend class base::RefCountedThreadSafe<SingleThreadedProxyResolver::Job>; |
| 153 | 153 |
| 154 ~Job() {} | 154 ~Job() {} |
| 155 | 155 |
| 156 // Runs on the worker thread. | 156 // Runs on the worker thread. |
| 157 void DoQuery(ProxyResolver* resolver, size_t load_log_bound) { | 157 void DoQuery(ProxyResolver* resolver, size_t load_log_bound) { |
| 158 LoadLog* worker_log = NULL; | 158 scoped_ptr<CapturingNetLog> worker_log(new CapturingNetLog(load_log_bound)); |
| 159 if (load_log_bound > 0) { | 159 BoundNetLog bound_worker_log(NetLog::Source(), worker_log.get()); |
| 160 worker_log = new LoadLog(load_log_bound); | |
| 161 worker_log->AddRef(); // Balanced in QueryComplete. | |
| 162 } | |
| 163 | 160 |
| 164 int rv = resolver->GetProxyForURL(url_, &results_buf_, NULL, NULL, | 161 int rv = resolver->GetProxyForURL(url_, &results_buf_, NULL, NULL, |
| 165 worker_log); | 162 bound_worker_log); |
| 166 DCHECK_NE(rv, ERR_IO_PENDING); | 163 DCHECK_NE(rv, ERR_IO_PENDING); |
| 167 | 164 |
| 168 origin_loop_->PostTask(FROM_HERE, | 165 origin_loop_->PostTask(FROM_HERE, |
| 169 NewRunnableMethod(this, &Job::QueryComplete, rv, worker_log)); | 166 NewRunnableMethod(this, &Job::QueryComplete, rv, worker_log.release())); |
| 170 } | 167 } |
| 171 | 168 |
| 172 // Runs the completion callback on the origin thread. | 169 // Runs the completion callback on the origin thread. |
| 173 void QueryComplete(int result_code, LoadLog* worker_log) { | 170 void QueryComplete(int result_code, CapturingNetLog* worker_log) { |
| 174 // Merge the load log that was generated on the worker thread, into the | 171 // Merge the load log that was generated on the worker thread, into the |
| 175 // main log. | 172 // main log. |
| 176 if (worker_log) { | 173 CapturingBoundNetLog bound_worker_log(NetLog::Source(), worker_log); |
| 177 if (load_log_) | 174 bound_worker_log.AppendTo(net_log_); |
| 178 load_log_->Append(worker_log); | |
| 179 worker_log->Release(); | |
| 180 } | |
| 181 | 175 |
| 182 // The Job may have been cancelled after it was started. | 176 // The Job may have been cancelled after it was started. |
| 183 if (!was_cancelled()) { | 177 if (!was_cancelled()) { |
| 184 if (result_code >= OK) { // Note: unit-tests use values > 0. | 178 if (result_code >= OK) { // Note: unit-tests use values > 0. |
| 185 results_->Use(results_buf_); | 179 results_->Use(results_buf_); |
| 186 } | 180 } |
| 187 callback_->Run(result_code); | 181 callback_->Run(result_code); |
| 188 | 182 |
| 189 // We check for cancellation once again, in case the callback deleted | 183 // We check for cancellation once again, in case the callback deleted |
| 190 // the owning ProxyService (whose destructor will in turn cancel us). | 184 // the owning ProxyService (whose destructor will in turn cancel us). |
| 191 if (!was_cancelled()) | 185 if (!was_cancelled()) |
| 192 coordinator_->RemoveFrontOfJobsQueueAndStartNext(this); | 186 coordinator_->RemoveFrontOfJobsQueueAndStartNext(this); |
| 193 } | 187 } |
| 194 } | 188 } |
| 195 | 189 |
| 196 // Must only be used on the "origin" thread. | 190 // Must only be used on the "origin" thread. |
| 197 SingleThreadedProxyResolver* coordinator_; | 191 SingleThreadedProxyResolver* coordinator_; |
| 198 CompletionCallback* callback_; | 192 CompletionCallback* callback_; |
| 199 ProxyInfo* results_; | 193 ProxyInfo* results_; |
| 200 scoped_refptr<LoadLog> load_log_; | 194 BoundNetLog net_log_; |
| 201 GURL url_; | 195 GURL url_; |
| 202 bool is_started_; | 196 bool is_started_; |
| 203 | 197 |
| 204 // Usable from within DoQuery on the worker thread. | 198 // Usable from within DoQuery on the worker thread. |
| 205 ProxyInfo results_buf_; | 199 ProxyInfo results_buf_; |
| 206 MessageLoop* origin_loop_; | 200 MessageLoop* origin_loop_; |
| 207 }; | 201 }; |
| 208 | 202 |
| 209 // SingleThreadedProxyResolver ------------------------------------------------ | 203 // SingleThreadedProxyResolver ------------------------------------------------ |
| 210 | 204 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 226 outstanding_set_pac_script_task_->Cancel(); | 220 outstanding_set_pac_script_task_->Cancel(); |
| 227 | 221 |
| 228 // Note that |thread_| is destroyed before |resolver_|. This is important | 222 // Note that |thread_| is destroyed before |resolver_|. This is important |
| 229 // since |resolver_| could be running on |thread_|. | 223 // since |resolver_| could be running on |thread_|. |
| 230 } | 224 } |
| 231 | 225 |
| 232 int SingleThreadedProxyResolver::GetProxyForURL(const GURL& url, | 226 int SingleThreadedProxyResolver::GetProxyForURL(const GURL& url, |
| 233 ProxyInfo* results, | 227 ProxyInfo* results, |
| 234 CompletionCallback* callback, | 228 CompletionCallback* callback, |
| 235 RequestHandle* request, | 229 RequestHandle* request, |
| 236 LoadLog* load_log) { | 230 const BoundNetLog& net_log) { |
| 237 DCHECK(callback); | 231 DCHECK(callback); |
| 238 | 232 |
| 239 scoped_refptr<Job> job = new Job(this, url, results, callback, load_log); | 233 scoped_refptr<Job> job = new Job(this, url, results, callback, net_log); |
| 240 bool is_first_job = pending_jobs_.empty(); | 234 bool is_first_job = pending_jobs_.empty(); |
| 241 pending_jobs_.push_back(job); // Jobs can never finish synchronously. | 235 pending_jobs_.push_back(job); // Jobs can never finish synchronously. |
| 242 | 236 |
| 243 if (is_first_job) { | 237 if (is_first_job) { |
| 244 // If there is nothing already running, start the job now. | 238 // If there is nothing already running, start the job now. |
| 245 EnsureThreadStarted(); | 239 EnsureThreadStarted(); |
| 246 job->Start(); | 240 job->Start(); |
| 247 } else { | 241 } else { |
| 248 // Otherwise the job will get started eventually by ProcessPendingJobs(). | 242 // Otherwise the job will get started eventually by ProcessPendingJobs(). |
| 249 LoadLog::BeginEvent( | 243 job->net_log()->BeginEvent(NetLog::TYPE_WAITING_FOR_SINGLE_PROXY_RESOLVER_TH
READ); |
| 250 job->load_log(), | |
| 251 LoadLog::TYPE_WAITING_FOR_SINGLE_PROXY_RESOLVER_THREAD); | |
| 252 } | 244 } |
| 253 | 245 |
| 254 // Completion will be notified through |callback|, unless the caller cancels | 246 // Completion will be notified through |callback|, unless the caller cancels |
| 255 // the request using |request|. | 247 // the request using |request|. |
| 256 if (request) | 248 if (request) |
| 257 *request = reinterpret_cast<RequestHandle>(job.get()); | 249 *request = reinterpret_cast<RequestHandle>(job.get()); |
| 258 | 250 |
| 259 return ERR_IO_PENDING; | 251 return ERR_IO_PENDING; |
| 260 } | 252 } |
| 261 | 253 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 | 314 |
| 323 void SingleThreadedProxyResolver::ProcessPendingJobs() { | 315 void SingleThreadedProxyResolver::ProcessPendingJobs() { |
| 324 if (pending_jobs_.empty()) | 316 if (pending_jobs_.empty()) |
| 325 return; | 317 return; |
| 326 | 318 |
| 327 // Get the next job to process (FIFO). | 319 // Get the next job to process (FIFO). |
| 328 Job* job = pending_jobs_.front().get(); | 320 Job* job = pending_jobs_.front().get(); |
| 329 if (job->is_started()) | 321 if (job->is_started()) |
| 330 return; | 322 return; |
| 331 | 323 |
| 332 LoadLog::EndEvent( | 324 job->net_log()->EndEvent( |
| 333 job->load_log(), | 325 NetLog::TYPE_WAITING_FOR_SINGLE_PROXY_RESOLVER_THREAD); |
| 334 LoadLog::TYPE_WAITING_FOR_SINGLE_PROXY_RESOLVER_THREAD); | |
| 335 | 326 |
| 336 EnsureThreadStarted(); | 327 EnsureThreadStarted(); |
| 337 job->Start(); | 328 job->Start(); |
| 338 } | 329 } |
| 339 | 330 |
| 340 void SingleThreadedProxyResolver::RemoveFrontOfJobsQueueAndStartNext( | 331 void SingleThreadedProxyResolver::RemoveFrontOfJobsQueueAndStartNext( |
| 341 Job* expected_job) { | 332 Job* expected_job) { |
| 342 DCHECK_EQ(expected_job, pending_jobs_.front().get()); | 333 DCHECK_EQ(expected_job, pending_jobs_.front().get()); |
| 343 pending_jobs_.pop_front(); | 334 pending_jobs_.pop_front(); |
| 344 | 335 |
| 345 // Start next work item. | 336 // Start next work item. |
| 346 ProcessPendingJobs(); | 337 ProcessPendingJobs(); |
| 347 } | 338 } |
| 348 | 339 |
| 349 void SingleThreadedProxyResolver::RemoveOutstandingSetPacScriptTask( | 340 void SingleThreadedProxyResolver::RemoveOutstandingSetPacScriptTask( |
| 350 SetPacScriptTask* task) { | 341 SetPacScriptTask* task) { |
| 351 DCHECK_EQ(outstanding_set_pac_script_task_.get(), task); | 342 DCHECK_EQ(outstanding_set_pac_script_task_.get(), task); |
| 352 outstanding_set_pac_script_task_ = NULL; | 343 outstanding_set_pac_script_task_ = NULL; |
| 353 } | 344 } |
| 354 | 345 |
| 355 } // namespace net | 346 } // namespace net |
| OLD | NEW |