| 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/net_errors.h" | 8 #include "net/base/net_errors.h" |
| 9 #include "net/proxy/proxy_info.h" | 9 #include "net/proxy/proxy_info.h" |
| 10 | 10 |
| 11 namespace net { | 11 namespace net { |
| 12 | 12 |
| 13 // Runs on the worker thread to call ProxyResolver::SetPacScriptByUrl or | 13 // SingleThreadedProxyResolver::SetPacScriptTask ------------------------------ |
| 14 // ProxyResolver::SetPacScriptByData. | 14 |
| 15 // TODO(eroman): the lifetime of this task is ill-defined; |resolver_| must | 15 // Runs on the worker thread to call ProxyResolver::SetPacScript. |
| 16 // be valid when the task eventually is run. Make this task cancellable. | 16 class SingleThreadedProxyResolver::SetPacScriptTask |
| 17 class SetPacScriptTask : public Task { | 17 : public base::RefCountedThreadSafe< |
| 18 SingleThreadedProxyResolver::SetPacScriptTask> { |
| 18 public: | 19 public: |
| 19 SetPacScriptTask(ProxyResolver* resolver, | 20 SetPacScriptTask(SingleThreadedProxyResolver* coordinator, |
| 20 const GURL& pac_url, | 21 const GURL& pac_url, |
| 21 const std::string& bytes) | 22 const std::string& pac_bytes, |
| 22 : resolver_(resolver), pac_url_(pac_url), bytes_(bytes) {} | 23 CompletionCallback* callback) |
| 23 | 24 : coordinator_(coordinator), |
| 24 virtual void Run() { | 25 callback_(callback), |
| 25 if (resolver_->expects_pac_bytes()) | 26 pac_bytes_(pac_bytes), |
| 26 resolver_->SetPacScriptByData(bytes_); | 27 pac_url_(pac_url), |
| 27 else | 28 origin_loop_(MessageLoop::current()) { |
| 28 resolver_->SetPacScriptByUrl(pac_url_); | 29 DCHECK(callback); |
| 29 } | 30 } |
| 30 | 31 |
| 32 // Start the SetPacScript request on the worker thread. |
| 33 void Start() { |
| 34 // TODO(eroman): Are these manual AddRef / Release necessary? |
| 35 AddRef(); // balanced in RequestComplete |
| 36 |
| 37 coordinator_->thread()->message_loop()->PostTask( |
| 38 FROM_HERE, NewRunnableMethod(this, &SetPacScriptTask::DoRequest, |
| 39 coordinator_->resolver_.get())); |
| 40 } |
| 41 |
| 42 void Cancel() { |
| 43 // Clear these to inform RequestComplete that it should not try to |
| 44 // access them. |
| 45 coordinator_ = NULL; |
| 46 callback_ = NULL; |
| 47 } |
| 48 |
| 49 // Returns true if Cancel() has been called. |
| 50 bool was_cancelled() const { return callback_ == NULL; } |
| 51 |
| 31 private: | 52 private: |
| 32 ProxyResolver* resolver_; | 53 // Runs on the worker thread. |
| 54 void DoRequest(ProxyResolver* resolver) { |
| 55 int rv = resolver->expects_pac_bytes() ? |
| 56 resolver->SetPacScriptByData(pac_bytes_, NULL) : |
| 57 resolver->SetPacScriptByUrl(pac_url_, NULL); |
| 58 |
| 59 DCHECK_NE(rv, ERR_IO_PENDING); |
| 60 origin_loop_->PostTask(FROM_HERE, |
| 61 NewRunnableMethod(this, &SetPacScriptTask::RequestComplete, rv)); |
| 62 } |
| 63 |
| 64 // Runs the completion callback on the origin thread. |
| 65 void RequestComplete(int result_code) { |
| 66 // The task may have been cancelled after it was started. |
| 67 if (!was_cancelled()) { |
| 68 CompletionCallback* callback = callback_; |
| 69 coordinator_->RemoveOutstandingSetPacScriptTask(this); |
| 70 callback->Run(result_code); |
| 71 } |
| 72 |
| 73 Release(); // Balances the AddRef in Start. |
| 74 } |
| 75 |
| 76 // Must only be used on the "origin" thread. |
| 77 SingleThreadedProxyResolver* coordinator_; |
| 78 CompletionCallback* callback_; |
| 79 std::string pac_bytes_; |
| 33 GURL pac_url_; | 80 GURL pac_url_; |
| 34 std::string bytes_; | 81 |
| 82 // Usable from within DoQuery on the worker thread. |
| 83 MessageLoop* origin_loop_; |
| 35 }; | 84 }; |
| 36 | 85 |
| 37 // SingleThreadedProxyResolver::Job ------------------------------------------- | 86 // SingleThreadedProxyResolver::Job ------------------------------------------- |
| 38 | 87 |
| 39 class SingleThreadedProxyResolver::Job | 88 class SingleThreadedProxyResolver::Job |
| 40 : public base::RefCountedThreadSafe<SingleThreadedProxyResolver::Job> { | 89 : public base::RefCountedThreadSafe<SingleThreadedProxyResolver::Job> { |
| 41 public: | 90 public: |
| 42 // |coordinator| -- the SingleThreadedProxyResolver that owns this job. | 91 // |coordinator| -- the SingleThreadedProxyResolver that owns this job. |
| 43 // |url| -- the URL of the query. | 92 // |url| -- the URL of the query. |
| 44 // |results| -- the structure to fill with proxy resolve results. | 93 // |results| -- the structure to fill with proxy resolve results. |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 results_->Use(results_buf_); | 144 results_->Use(results_buf_); |
| 96 } | 145 } |
| 97 callback_->Run(result_code); | 146 callback_->Run(result_code); |
| 98 | 147 |
| 99 // We check for cancellation once again, in case the callback deleted | 148 // We check for cancellation once again, in case the callback deleted |
| 100 // the owning ProxyService (whose destructor will in turn cancel us). | 149 // the owning ProxyService (whose destructor will in turn cancel us). |
| 101 if (!was_cancelled()) | 150 if (!was_cancelled()) |
| 102 coordinator_->RemoveFrontOfJobsQueueAndStartNext(this); | 151 coordinator_->RemoveFrontOfJobsQueueAndStartNext(this); |
| 103 } | 152 } |
| 104 | 153 |
| 105 Release(); // balances the AddRef in Query. we may get deleted after | 154 Release(); // Balances the AddRef in Start. We may get deleted after |
| 106 // we return. | 155 // we return. |
| 107 } | 156 } |
| 108 | 157 |
| 109 // Must only be used on the "origin" thread. | 158 // Must only be used on the "origin" thread. |
| 110 SingleThreadedProxyResolver* coordinator_; | 159 SingleThreadedProxyResolver* coordinator_; |
| 111 CompletionCallback* callback_; | 160 CompletionCallback* callback_; |
| 112 ProxyInfo* results_; | 161 ProxyInfo* results_; |
| 113 GURL url_; | 162 GURL url_; |
| 114 bool is_started_; | 163 bool is_started_; |
| 115 | 164 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 127 } | 176 } |
| 128 | 177 |
| 129 SingleThreadedProxyResolver::~SingleThreadedProxyResolver() { | 178 SingleThreadedProxyResolver::~SingleThreadedProxyResolver() { |
| 130 // Cancel the inprogress job (if any), and free the rest. | 179 // Cancel the inprogress job (if any), and free the rest. |
| 131 for (PendingJobsQueue::iterator it = pending_jobs_.begin(); | 180 for (PendingJobsQueue::iterator it = pending_jobs_.begin(); |
| 132 it != pending_jobs_.end(); | 181 it != pending_jobs_.end(); |
| 133 ++it) { | 182 ++it) { |
| 134 (*it)->Cancel(); | 183 (*it)->Cancel(); |
| 135 } | 184 } |
| 136 | 185 |
| 186 if (outstanding_set_pac_script_task_) |
| 187 outstanding_set_pac_script_task_->Cancel(); |
| 188 |
| 137 // Note that |thread_| is destroyed before |resolver_|. This is important | 189 // Note that |thread_| is destroyed before |resolver_|. This is important |
| 138 // since |resolver_| could be running on |thread_|. | 190 // since |resolver_| could be running on |thread_|. |
| 139 } | 191 } |
| 140 | 192 |
| 141 int SingleThreadedProxyResolver::GetProxyForURL(const GURL& url, | 193 int SingleThreadedProxyResolver::GetProxyForURL(const GURL& url, |
| 142 ProxyInfo* results, | 194 ProxyInfo* results, |
| 143 CompletionCallback* callback, | 195 CompletionCallback* callback, |
| 144 RequestHandle* request) { | 196 RequestHandle* request) { |
| 145 DCHECK(callback); | 197 DCHECK(callback); |
| 146 | 198 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 175 return; | 227 return; |
| 176 } | 228 } |
| 177 | 229 |
| 178 // Otherwise just delete the job from the queue. | 230 // Otherwise just delete the job from the queue. |
| 179 PendingJobsQueue::iterator it = std::find( | 231 PendingJobsQueue::iterator it = std::find( |
| 180 pending_jobs_.begin(), pending_jobs_.end(), job); | 232 pending_jobs_.begin(), pending_jobs_.end(), job); |
| 181 DCHECK(it != pending_jobs_.end()); | 233 DCHECK(it != pending_jobs_.end()); |
| 182 pending_jobs_.erase(it); | 234 pending_jobs_.erase(it); |
| 183 } | 235 } |
| 184 | 236 |
| 185 void SingleThreadedProxyResolver::SetPacScriptByUrlInternal( | 237 void SingleThreadedProxyResolver::CancelSetPacScript() { |
| 186 const GURL& pac_url) { | 238 DCHECK(outstanding_set_pac_script_task_); |
| 187 SetPacScriptHelper(pac_url, std::string()); | 239 outstanding_set_pac_script_task_->Cancel(); |
| 240 outstanding_set_pac_script_task_ = NULL; |
| 188 } | 241 } |
| 189 | 242 |
| 190 void SingleThreadedProxyResolver::SetPacScriptByDataInternal( | 243 int SingleThreadedProxyResolver::SetPacScript( |
| 191 const std::string& bytes) { | 244 const GURL& pac_url, |
| 192 SetPacScriptHelper(GURL(), bytes); | 245 const std::string& pac_bytes, |
| 193 } | 246 CompletionCallback* callback) { |
| 247 EnsureThreadStarted(); |
| 248 DCHECK(!outstanding_set_pac_script_task_); |
| 194 | 249 |
| 195 void SingleThreadedProxyResolver::SetPacScriptHelper(const GURL& pac_url, | 250 SetPacScriptTask* task = new SetPacScriptTask( |
| 196 const std::string& bytes) { | 251 this, pac_url, pac_bytes, callback); |
| 197 EnsureThreadStarted(); | 252 outstanding_set_pac_script_task_ = task; |
| 198 thread()->message_loop()->PostTask( | 253 task->Start(); |
| 199 FROM_HERE, new SetPacScriptTask(resolver(), pac_url, bytes)); | 254 return ERR_IO_PENDING; |
| 200 } | 255 } |
| 201 | 256 |
| 202 void SingleThreadedProxyResolver::EnsureThreadStarted() { | 257 void SingleThreadedProxyResolver::EnsureThreadStarted() { |
| 203 if (!thread_.get()) { | 258 if (!thread_.get()) { |
| 204 thread_.reset(new base::Thread("pac-thread")); | 259 thread_.reset(new base::Thread("pac-thread")); |
| 205 thread_->Start(); | 260 thread_->Start(); |
| 206 } | 261 } |
| 207 } | 262 } |
| 208 | 263 |
| 209 void SingleThreadedProxyResolver::ProcessPendingJobs() { | 264 void SingleThreadedProxyResolver::ProcessPendingJobs() { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 221 | 276 |
| 222 void SingleThreadedProxyResolver::RemoveFrontOfJobsQueueAndStartNext( | 277 void SingleThreadedProxyResolver::RemoveFrontOfJobsQueueAndStartNext( |
| 223 Job* expected_job) { | 278 Job* expected_job) { |
| 224 DCHECK_EQ(expected_job, pending_jobs_.front().get()); | 279 DCHECK_EQ(expected_job, pending_jobs_.front().get()); |
| 225 pending_jobs_.pop_front(); | 280 pending_jobs_.pop_front(); |
| 226 | 281 |
| 227 // Start next work item. | 282 // Start next work item. |
| 228 ProcessPendingJobs(); | 283 ProcessPendingJobs(); |
| 229 } | 284 } |
| 230 | 285 |
| 286 void SingleThreadedProxyResolver::RemoveOutstandingSetPacScriptTask( |
| 287 SetPacScriptTask* task) { |
| 288 DCHECK_EQ(outstanding_set_pac_script_task_.get(), task); |
| 289 outstanding_set_pac_script_task_ = NULL; |
| 290 } |
| 291 |
| 231 } // namespace net | 292 } // namespace net |
| OLD | NEW |