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 |