diff options
Diffstat (limited to 'net/proxy/single_threaded_proxy_resolver.cc')
-rw-r--r-- | net/proxy/single_threaded_proxy_resolver.cc | 353 |
1 files changed, 0 insertions, 353 deletions
diff --git a/net/proxy/single_threaded_proxy_resolver.cc b/net/proxy/single_threaded_proxy_resolver.cc deleted file mode 100644 index 2fdc3ac..0000000 --- a/net/proxy/single_threaded_proxy_resolver.cc +++ /dev/null @@ -1,353 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/proxy/single_threaded_proxy_resolver.h" - -#include "base/message_loop.h" -#include "base/thread.h" -#include "net/base/capturing_net_log.h" -#include "net/base/net_errors.h" -#include "net/proxy/proxy_info.h" - -namespace net { - -namespace { - -class PurgeMemoryTask : public base::RefCountedThreadSafe<PurgeMemoryTask> { - public: - explicit PurgeMemoryTask(ProxyResolver* resolver) : resolver_(resolver) {} - void PurgeMemory() { resolver_->PurgeMemory(); } - private: - friend class base::RefCountedThreadSafe<PurgeMemoryTask>; - ~PurgeMemoryTask() {} - ProxyResolver* resolver_; -}; - -} // namespace - -// SingleThreadedProxyResolver::SetPacScriptTask ------------------------------ - -// Runs on the worker thread to call ProxyResolver::SetPacScript. -class SingleThreadedProxyResolver::SetPacScriptTask - : public base::RefCountedThreadSafe< - SingleThreadedProxyResolver::SetPacScriptTask> { - public: - SetPacScriptTask(SingleThreadedProxyResolver* coordinator, - const GURL& pac_url, - const string16& pac_script, - CompletionCallback* callback) - : coordinator_(coordinator), - callback_(callback), - pac_script_(pac_script), - pac_url_(pac_url), - origin_loop_(MessageLoop::current()) { - DCHECK(callback); - } - - // Start the SetPacScript request on the worker thread. - void Start() { - coordinator_->thread()->message_loop()->PostTask( - FROM_HERE, NewRunnableMethod(this, &SetPacScriptTask::DoRequest, - coordinator_->resolver_.get())); - } - - void Cancel() { - // Clear these to inform RequestComplete that it should not try to - // access them. - coordinator_ = NULL; - callback_ = NULL; - } - - // Returns true if Cancel() has been called. - bool was_cancelled() const { return callback_ == NULL; } - - private: - friend class base::RefCountedThreadSafe< - SingleThreadedProxyResolver::SetPacScriptTask>; - - ~SetPacScriptTask() {} - - // Runs on the worker thread. - void DoRequest(ProxyResolver* resolver) { - int rv = resolver->expects_pac_bytes() ? - resolver->SetPacScriptByData(pac_script_, NULL) : - resolver->SetPacScriptByUrl(pac_url_, NULL); - - DCHECK_NE(rv, ERR_IO_PENDING); - origin_loop_->PostTask(FROM_HERE, - NewRunnableMethod(this, &SetPacScriptTask::RequestComplete, rv)); - } - - // Runs the completion callback on the origin thread. - void RequestComplete(int result_code) { - // The task may have been cancelled after it was started. - if (!was_cancelled()) { - CompletionCallback* callback = callback_; - coordinator_->RemoveOutstandingSetPacScriptTask(this); - callback->Run(result_code); - } - } - - // Must only be used on the "origin" thread. - SingleThreadedProxyResolver* coordinator_; - CompletionCallback* callback_; - string16 pac_script_; - GURL pac_url_; - - // Usable from within DoQuery on the worker thread. - MessageLoop* origin_loop_; -}; - -// SingleThreadedProxyResolver::Job ------------------------------------------- - -class SingleThreadedProxyResolver::Job - : public base::RefCountedThreadSafe<SingleThreadedProxyResolver::Job> { - public: - // |coordinator| -- the SingleThreadedProxyResolver that owns this job. - // |url| -- the URL of the query. - // |results| -- the structure to fill with proxy resolve results. - Job(SingleThreadedProxyResolver* coordinator, - const GURL& url, - ProxyInfo* results, - CompletionCallback* callback, - const BoundNetLog& net_log) - : coordinator_(coordinator), - callback_(callback), - results_(results), - net_log_(net_log), - url_(url), - is_started_(false), - origin_loop_(MessageLoop::current()) { - DCHECK(callback); - } - - // Start the resolve proxy request on the worker thread. - void Start() { - is_started_ = true; - - size_t load_log_bound = 100; - - coordinator_->thread()->message_loop()->PostTask( - FROM_HERE, NewRunnableMethod(this, &Job::DoQuery, - coordinator_->resolver_.get(), - load_log_bound)); - } - - bool is_started() const { return is_started_; } - - void Cancel() { - // Clear these to inform QueryComplete that it should not try to - // access them. - coordinator_ = NULL; - callback_ = NULL; - results_ = NULL; - } - - // Returns true if Cancel() has been called. - bool was_cancelled() const { return callback_ == NULL; } - - BoundNetLog* net_log() { return &net_log_; } - - private: - friend class base::RefCountedThreadSafe<SingleThreadedProxyResolver::Job>; - - ~Job() {} - - // Runs on the worker thread. - void DoQuery(ProxyResolver* resolver, size_t load_log_bound) { - worker_log_.reset(new CapturingNetLog(load_log_bound)); - BoundNetLog bound_worker_log(NetLog::Source(), worker_log_.get()); - - int rv = resolver->GetProxyForURL(url_, &results_buf_, NULL, NULL, - bound_worker_log); - DCHECK_NE(rv, ERR_IO_PENDING); - - origin_loop_->PostTask(FROM_HERE, - NewRunnableMethod(this, &Job::QueryComplete, rv)); - } - - // Runs the completion callback on the origin thread. - void QueryComplete(int result_code) { - // Merge the load log that was generated on the worker thread, into the - // main log. - CapturingBoundNetLog bound_worker_log(NetLog::Source(), - worker_log_.release()); - bound_worker_log.AppendTo(net_log_); - - // The Job may have been cancelled after it was started. - if (!was_cancelled()) { - if (result_code >= OK) { // Note: unit-tests use values > 0. - results_->Use(results_buf_); - } - callback_->Run(result_code); - - // We check for cancellation once again, in case the callback deleted - // the owning ProxyService (whose destructor will in turn cancel us). - if (!was_cancelled()) - coordinator_->RemoveFrontOfJobsQueueAndStartNext(this); - } - } - - // Must only be used on the "origin" thread. - SingleThreadedProxyResolver* coordinator_; - CompletionCallback* callback_; - ProxyInfo* results_; - BoundNetLog net_log_; - GURL url_; - bool is_started_; - - // Usable from within DoQuery on the worker thread. - ProxyInfo results_buf_; - MessageLoop* origin_loop_; - - // Used to pass the captured events between DoQuery [worker thread] and - // QueryComplete [origin thread]. - scoped_ptr<CapturingNetLog> worker_log_; -}; - -// SingleThreadedProxyResolver ------------------------------------------------ - -SingleThreadedProxyResolver::SingleThreadedProxyResolver( - ProxyResolver* resolver) - : ProxyResolver(resolver->expects_pac_bytes()), - resolver_(resolver) { -} - -SingleThreadedProxyResolver::~SingleThreadedProxyResolver() { - // Cancel the inprogress job (if any), and free the rest. - for (PendingJobsQueue::iterator it = pending_jobs_.begin(); - it != pending_jobs_.end(); - ++it) { - (*it)->Cancel(); - } - - if (outstanding_set_pac_script_task_) - outstanding_set_pac_script_task_->Cancel(); - - // Note that |thread_| is destroyed before |resolver_|. This is important - // since |resolver_| could be running on |thread_|. -} - -int SingleThreadedProxyResolver::GetProxyForURL(const GURL& url, - ProxyInfo* results, - CompletionCallback* callback, - RequestHandle* request, - const BoundNetLog& net_log) { - DCHECK(callback); - - scoped_refptr<Job> job = new Job(this, url, results, callback, net_log); - bool is_first_job = pending_jobs_.empty(); - pending_jobs_.push_back(job); // Jobs can never finish synchronously. - - if (is_first_job) { - // If there is nothing already running, start the job now. - EnsureThreadStarted(); - job->Start(); - } else { - // Otherwise the job will get started eventually by ProcessPendingJobs(). - job->net_log()->BeginEvent( - NetLog::TYPE_WAITING_FOR_SINGLE_PROXY_RESOLVER_THREAD, NULL); - } - - // Completion will be notified through |callback|, unless the caller cancels - // the request using |request|. - if (request) - *request = reinterpret_cast<RequestHandle>(job.get()); - - return ERR_IO_PENDING; -} - -// There are three states of the request we need to handle: -// (1) Not started (just sitting in the queue). -// (2) Executing Job::DoQuery in the worker thread. -// (3) Waiting for Job::QueryComplete to be run on the origin thread. -void SingleThreadedProxyResolver::CancelRequest(RequestHandle req) { - DCHECK(req); - - Job* job = reinterpret_cast<Job*>(req); - - bool is_active_job = job->is_started() && !pending_jobs_.empty() && - pending_jobs_.front().get() == job; - - job->Cancel(); - - if (is_active_job) { - RemoveFrontOfJobsQueueAndStartNext(job); - return; - } - - // Otherwise just delete the job from the queue. - PendingJobsQueue::iterator it = std::find( - pending_jobs_.begin(), pending_jobs_.end(), job); - DCHECK(it != pending_jobs_.end()); - pending_jobs_.erase(it); -} - -void SingleThreadedProxyResolver::CancelSetPacScript() { - DCHECK(outstanding_set_pac_script_task_); - outstanding_set_pac_script_task_->Cancel(); - outstanding_set_pac_script_task_ = NULL; -} - -void SingleThreadedProxyResolver::PurgeMemory() { - if (thread_.get()) { - scoped_refptr<PurgeMemoryTask> helper(new PurgeMemoryTask(resolver_.get())); - thread_->message_loop()->PostTask(FROM_HERE, - NewRunnableMethod(helper.get(), &PurgeMemoryTask::PurgeMemory)); - } -} - -int SingleThreadedProxyResolver::SetPacScript( - const GURL& pac_url, - const string16& pac_script, - CompletionCallback* callback) { - EnsureThreadStarted(); - DCHECK(!outstanding_set_pac_script_task_); - - SetPacScriptTask* task = new SetPacScriptTask( - this, pac_url, pac_script, callback); - outstanding_set_pac_script_task_ = task; - task->Start(); - return ERR_IO_PENDING; -} - -void SingleThreadedProxyResolver::EnsureThreadStarted() { - if (!thread_.get()) { - thread_.reset(new base::Thread("pac-thread")); - thread_->Start(); - } -} - -void SingleThreadedProxyResolver::ProcessPendingJobs() { - if (pending_jobs_.empty()) - return; - - // Get the next job to process (FIFO). - Job* job = pending_jobs_.front().get(); - if (job->is_started()) - return; - - job->net_log()->EndEvent( - NetLog::TYPE_WAITING_FOR_SINGLE_PROXY_RESOLVER_THREAD, NULL); - - EnsureThreadStarted(); - job->Start(); -} - -void SingleThreadedProxyResolver::RemoveFrontOfJobsQueueAndStartNext( - Job* expected_job) { - DCHECK_EQ(expected_job, pending_jobs_.front().get()); - pending_jobs_.pop_front(); - - // Start next work item. - ProcessPendingJobs(); -} - -void SingleThreadedProxyResolver::RemoveOutstandingSetPacScriptTask( - SetPacScriptTask* task) { - DCHECK_EQ(outstanding_set_pac_script_task_.get(), task); - outstanding_set_pac_script_task_ = NULL; -} - -} // namespace net |