1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2009 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/proxy/single_threaded_proxy_resolver.h" 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/thread.h" 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/load_log.h" 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h" 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/proxy/proxy_info.h" 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net { 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace { 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass PurgeMemoryTask : public base::RefCountedThreadSafe<PurgeMemoryTask> { 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit PurgeMemoryTask(ProxyResolver* resolver) : resolver_(resolver) {} 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void PurgeMemory() { resolver_->PurgeMemory(); } 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott friend class base::RefCountedThreadSafe<PurgeMemoryTask>; 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~PurgeMemoryTask() {} 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ProxyResolver* resolver_; 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// SingleThreadedProxyResolver::SetPacScriptTask ------------------------------ 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Runs on the worker thread to call ProxyResolver::SetPacScript. 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass SingleThreadedProxyResolver::SetPacScriptTask 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : public base::RefCountedThreadSafe< 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SingleThreadedProxyResolver::SetPacScriptTask> { 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SetPacScriptTask(SingleThreadedProxyResolver* coordinator, 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const GURL& pac_url, 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string& pac_bytes, 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* callback) 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : coordinator_(coordinator), 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott callback_(callback), 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pac_bytes_(pac_bytes), 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pac_url_(pac_url), 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott origin_loop_(MessageLoop::current()) { 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(callback); 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Start the SetPacScript request on the worker thread. 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void Start() { 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott coordinator_->thread()->message_loop()->PostTask( 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FROM_HERE, NewRunnableMethod(this, &SetPacScriptTask::DoRequest, 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott coordinator_->resolver_.get())); 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void Cancel() { 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Clear these to inform RequestComplete that it should not try to 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // access them. 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott coordinator_ = NULL; 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott callback_ = NULL; 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Returns true if Cancel() has been called. 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool was_cancelled() const { return callback_ == NULL; } 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott friend class base::RefCountedThreadSafe< 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SingleThreadedProxyResolver::SetPacScriptTask>; 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~SetPacScriptTask() {} 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Runs on the worker thread. 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void DoRequest(ProxyResolver* resolver) { 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = resolver->expects_pac_bytes() ? 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott resolver->SetPacScriptByData(pac_bytes_, NULL) : 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott resolver->SetPacScriptByUrl(pac_url_, NULL); 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(rv, ERR_IO_PENDING); 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott origin_loop_->PostTask(FROM_HERE, 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NewRunnableMethod(this, &SetPacScriptTask::RequestComplete, rv)); 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Runs the completion callback on the origin thread. 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void RequestComplete(int result_code) { 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The task may have been cancelled after it was started. 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!was_cancelled()) { 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* callback = callback_; 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott coordinator_->RemoveOutstandingSetPacScriptTask(this); 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott callback->Run(result_code); 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Must only be used on the "origin" thread. 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SingleThreadedProxyResolver* coordinator_; 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* callback_; 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string pac_bytes_; 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GURL pac_url_; 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Usable from within DoQuery on the worker thread. 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessageLoop* origin_loop_; 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// SingleThreadedProxyResolver::Job ------------------------------------------- 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass SingleThreadedProxyResolver::Job 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : public base::RefCountedThreadSafe<SingleThreadedProxyResolver::Job> { 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // |coordinator| -- the SingleThreadedProxyResolver that owns this job. 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // |url| -- the URL of the query. 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // |results| -- the structure to fill with proxy resolve results. 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Job(SingleThreadedProxyResolver* coordinator, 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const GURL& url, 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ProxyInfo* results, 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* callback, 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LoadLog* load_log) 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : coordinator_(coordinator), 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott callback_(callback), 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott results_(results), 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott load_log_(load_log), 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott url_(url), 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott is_started_(false), 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott origin_loop_(MessageLoop::current()) { 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(callback); 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Start the resolve proxy request on the worker thread. 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void Start() { 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott is_started_ = true; 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t load_log_bound = load_log_ ? load_log_->max_num_entries() : 0; 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott coordinator_->thread()->message_loop()->PostTask( 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FROM_HERE, NewRunnableMethod(this, &Job::DoQuery, 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott coordinator_->resolver_.get(), 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott load_log_bound)); 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool is_started() const { return is_started_; } 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void Cancel() { 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Clear these to inform QueryComplete that it should not try to 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // access them. 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott coordinator_ = NULL; 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott callback_ = NULL; 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott results_ = NULL; 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Returns true if Cancel() has been called. 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool was_cancelled() const { return callback_ == NULL; } 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott friend class base::RefCountedThreadSafe<SingleThreadedProxyResolver::Job>; 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~Job() {} 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Runs on the worker thread. 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void DoQuery(ProxyResolver* resolver, size_t load_log_bound) { 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LoadLog* worker_log = NULL; 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (load_log_bound > 0) { 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott worker_log = new LoadLog(load_log_bound); 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott worker_log->AddRef(); // Balanced in QueryComplete. 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = resolver->GetProxyForURL(url_, &results_buf_, NULL, NULL, 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott worker_log); 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(rv, ERR_IO_PENDING); 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott origin_loop_->PostTask(FROM_HERE, 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NewRunnableMethod(this, &Job::QueryComplete, rv, worker_log)); 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Runs the completion callback on the origin thread. 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void QueryComplete(int result_code, LoadLog* worker_log) { 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Merge the load log that was generated on the worker thread, into the 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // main log. 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (worker_log) { 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (load_log_) 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott load_log_->Append(worker_log); 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott worker_log->Release(); 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The Job may have been cancelled after it was started. 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!was_cancelled()) { 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result_code >= OK) { // Note: unit-tests use values > 0. 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott results_->Use(results_buf_); 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott callback_->Run(result_code); 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We check for cancellation once again, in case the callback deleted 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the owning ProxyService (whose destructor will in turn cancel us). 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!was_cancelled()) 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott coordinator_->RemoveFrontOfJobsQueueAndStartNext(this); 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Must only be used on the "origin" thread. 195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SingleThreadedProxyResolver* coordinator_; 196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* callback_; 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ProxyInfo* results_; 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_refptr<LoadLog> load_log_; 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GURL url_; 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool is_started_; 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Usable from within DoQuery on the worker thread. 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ProxyInfo results_buf_; 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessageLoop* origin_loop_; 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// SingleThreadedProxyResolver ------------------------------------------------ 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSingleThreadedProxyResolver::SingleThreadedProxyResolver( 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ProxyResolver* resolver) 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : ProxyResolver(resolver->expects_pac_bytes()), 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott resolver_(resolver) { 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSingleThreadedProxyResolver::~SingleThreadedProxyResolver() { 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Cancel the inprogress job (if any), and free the rest. 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (PendingJobsQueue::iterator it = pending_jobs_.begin(); 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott it != pending_jobs_.end(); 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++it) { 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (*it)->Cancel(); 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (outstanding_set_pac_script_task_) 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott outstanding_set_pac_script_task_->Cancel(); 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Note that |thread_| is destroyed before |resolver_|. This is important 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // since |resolver_| could be running on |thread_|. 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SingleThreadedProxyResolver::GetProxyForURL(const GURL& url, 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ProxyInfo* results, 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* callback, 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RequestHandle* request, 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LoadLog* load_log) { 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(callback); 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_refptr<Job> job = new Job(this, url, results, callback, load_log); 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pending_jobs_.push_back(job); 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ProcessPendingJobs(); // Jobs can never finish synchronously. 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Completion will be notified through |callback|, unless the caller cancels 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the request using |request|. 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (request) 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *request = reinterpret_cast<RequestHandle>(job.get()); 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_IO_PENDING; 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// There are three states of the request we need to handle: 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// (1) Not started (just sitting in the queue). 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// (2) Executing Job::DoQuery in the worker thread. 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// (3) Waiting for Job::QueryComplete to be run on the origin thread. 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SingleThreadedProxyResolver::CancelRequest(RequestHandle req) { 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(req); 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Job* job = reinterpret_cast<Job*>(req); 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool is_active_job = job->is_started() && !pending_jobs_.empty() && 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pending_jobs_.front().get() == job; 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott job->Cancel(); 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (is_active_job) { 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RemoveFrontOfJobsQueueAndStartNext(job); 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Otherwise just delete the job from the queue. 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PendingJobsQueue::iterator it = std::find( 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pending_jobs_.begin(), pending_jobs_.end(), job); 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(it != pending_jobs_.end()); 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pending_jobs_.erase(it); 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SingleThreadedProxyResolver::CancelSetPacScript() { 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(outstanding_set_pac_script_task_); 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott outstanding_set_pac_script_task_->Cancel(); 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott outstanding_set_pac_script_task_ = NULL; 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SingleThreadedProxyResolver::PurgeMemory() { 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (thread_.get()) { 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_refptr<PurgeMemoryTask> helper(new PurgeMemoryTask(resolver_.get())); 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott thread_->message_loop()->PostTask(FROM_HERE, 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NewRunnableMethod(helper.get(), &PurgeMemoryTask::PurgeMemory)); 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SingleThreadedProxyResolver::SetPacScript( 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const GURL& pac_url, 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string& pac_bytes, 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* callback) { 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnsureThreadStarted(); 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!outstanding_set_pac_script_task_); 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SetPacScriptTask* task = new SetPacScriptTask( 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott this, pac_url, pac_bytes, callback); 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott outstanding_set_pac_script_task_ = task; 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott task->Start(); 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_IO_PENDING; 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SingleThreadedProxyResolver::EnsureThreadStarted() { 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!thread_.get()) { 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott thread_.reset(new base::Thread("pac-thread")); 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott thread_->Start(); 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SingleThreadedProxyResolver::ProcessPendingJobs() { 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (pending_jobs_.empty()) 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Get the next job to process (FIFO). 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Job* job = pending_jobs_.front().get(); 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (job->is_started()) 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnsureThreadStarted(); 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott job->Start(); 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SingleThreadedProxyResolver::RemoveFrontOfJobsQueueAndStartNext( 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Job* expected_job) { 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(expected_job, pending_jobs_.front().get()); 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pending_jobs_.pop_front(); 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Start next work item. 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ProcessPendingJobs(); 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SingleThreadedProxyResolver::RemoveOutstandingSetPacScriptTask( 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SetPacScriptTask* task) { 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(outstanding_set_pac_script_task_.get(), task); 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott outstanding_set_pac_script_task_ = NULL; 336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace net 339