| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "base/compiler_specific.h" | 5 #include "base/compiler_specific.h" |
| 6 #include "googleurl/src/gurl.h" | 6 #include "googleurl/src/gurl.h" |
| 7 #include "net/base/net_errors.h" | 7 #include "net/base/net_errors.h" |
| 8 #include "net/proxy/proxy_config_service.h" | 8 #include "net/proxy/proxy_config_service.h" |
| 9 #include "net/proxy/proxy_resolver.h" | 9 #include "net/proxy/proxy_resolver.h" |
| 10 #include "net/proxy/proxy_script_fetcher.h" | 10 #include "net/proxy/proxy_script_fetcher.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 net::ProxyInfo info; | 51 net::ProxyInfo info; |
| 52 | 52 |
| 53 // info is only returned if query_url in GetProxyForURL matches this: | 53 // info is only returned if query_url in GetProxyForURL matches this: |
| 54 std::string info_predicate_query_host; | 54 std::string info_predicate_query_host; |
| 55 | 55 |
| 56 // If true, then GetProxyForURL will fail, which simulates failure to | 56 // If true, then GetProxyForURL will fail, which simulates failure to |
| 57 // download or execute the PAC file. | 57 // download or execute the PAC file. |
| 58 bool fail_get_proxy_for_url; | 58 bool fail_get_proxy_for_url; |
| 59 }; | 59 }; |
| 60 | 60 |
| 61 class SyncProxyService { | |
| 62 public: | |
| 63 SyncProxyService(net::ProxyConfigService* config_service, | |
| 64 net::ProxyResolver* resolver) | |
| 65 : io_thread_("IO_Thread"), | |
| 66 service_(config_service, resolver) { | |
| 67 base::Thread::Options options; | |
| 68 options.message_loop_type = MessageLoop::TYPE_IO; | |
| 69 io_thread_.StartWithOptions(options); | |
| 70 sync_proxy_service_ = new net::SyncProxyServiceHelper( | |
| 71 io_thread_.message_loop(), &service_); | |
| 72 } | |
| 73 | |
| 74 int ResolveProxy(const GURL& url, net::ProxyInfo* proxy_info) { | |
| 75 return sync_proxy_service_->ResolveProxy(url, proxy_info); | |
| 76 } | |
| 77 | |
| 78 int ReconsiderProxyAfterError(const GURL& url, net::ProxyInfo* proxy_info) { | |
| 79 return sync_proxy_service_->ReconsiderProxyAfterError(url, proxy_info); | |
| 80 } | |
| 81 | |
| 82 private: | |
| 83 base::Thread io_thread_; | |
| 84 net::ProxyService service_; | |
| 85 scoped_refptr<net::SyncProxyServiceHelper> sync_proxy_service_; | |
| 86 }; | |
| 87 | |
| 88 // ResultFuture is a handle to get at the result from | 61 // ResultFuture is a handle to get at the result from |
| 89 // ProxyService::ResolveProxyForURL() that ran on another thread. | 62 // ProxyService::ResolveProxyForURL() that ran on another thread. |
| 90 class ResultFuture : public base::RefCountedThreadSafe<ResultFuture> { | 63 class ResultFuture : public base::RefCountedThreadSafe<ResultFuture> { |
| 91 public: | 64 public: |
| 92 // |service| is the ProxyService to issue requests on, and |io_message_loop| | 65 // |service| is the ProxyService to issue requests on, and |io_message_loop| |
| 93 // is the message loop where ProxyService lives. | 66 // is the message loop where ProxyService lives. |
| 94 ResultFuture(MessageLoop* io_message_loop, | 67 ResultFuture(MessageLoop* io_message_loop, |
| 95 net::ProxyService* service) | 68 net::ProxyService* service) |
| 96 : io_message_loop_(io_message_loop), | 69 : io_message_loop_(io_message_loop), |
| 97 service_(service), | 70 service_(service), |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 // Wait until the ProxyService completes this request. | 109 // Wait until the ProxyService completes this request. |
| 137 void WaitUntilCompleted() { | 110 void WaitUntilCompleted() { |
| 138 DCHECK(MessageLoop::current() != io_message_loop_); | 111 DCHECK(MessageLoop::current() != io_message_loop_); |
| 139 completion_.Wait(); | 112 completion_.Wait(); |
| 140 DCHECK(did_complete_); | 113 DCHECK(did_complete_); |
| 141 } | 114 } |
| 142 | 115 |
| 143 private: | 116 private: |
| 144 friend class ProxyServiceWithFutures; | 117 friend class ProxyServiceWithFutures; |
| 145 | 118 |
| 146 // Start the request. Return once ProxyService::GetProxyForURL() returns. | 119 typedef int (net::ProxyService::*RequestMethod)(const GURL&, net::ProxyInfo*, |
| 120 net::CompletionCallback*, net::ProxyService::PacRequest**); |
| 121 |
| 147 void StartResolve(const GURL& url) { | 122 void StartResolve(const GURL& url) { |
| 123 StartRequest(url, &net::ProxyService::ResolveProxy); |
| 124 } |
| 125 |
| 126 // |proxy_info| is the *previous* result (that we are reconsidering). |
| 127 void StartReconsider(const GURL& url, const net::ProxyInfo& proxy_info) { |
| 128 proxy_info_ = proxy_info; |
| 129 StartRequest(url, &net::ProxyService::ReconsiderProxyAfterError); |
| 130 } |
| 131 |
| 132 // Start the request. Return once ProxyService::GetProxyForURL() or |
| 133 // ProxyService::ReconsiderProxyAfterError() returns. |
| 134 void StartRequest(const GURL& url, RequestMethod method) { |
| 148 DCHECK(MessageLoop::current() != io_message_loop_); | 135 DCHECK(MessageLoop::current() != io_message_loop_); |
| 149 io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 136 io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
| 150 this, &ResultFuture::DoStartResolve, url)); | 137 this, &ResultFuture::DoStartRequest, url, method)); |
| 151 started_.Wait(); | 138 started_.Wait(); |
| 152 } | 139 } |
| 153 | 140 |
| 154 // Called on |io_message_loop_|. | 141 // Called on |io_message_loop_|. |
| 155 void DoStartResolve(const GURL& url) { | 142 void DoStartRequest(const GURL& url, RequestMethod method) { |
| 156 DCHECK(MessageLoop::current() == io_message_loop_); | 143 DCHECK(MessageLoop::current() == io_message_loop_); |
| 157 int rv = service_->ResolveProxy(url, &proxy_info_, &callback_, &request_); | 144 int rv = (service_->*method)(url, &proxy_info_, &callback_, &request_); |
| 158 if (rv != net::ERR_IO_PENDING) { | 145 if (rv != net::ERR_IO_PENDING) { |
| 159 // Completed synchronously. | 146 // Completed synchronously. |
| 160 OnCompletion(rv); | 147 OnCompletion(rv); |
| 161 } | 148 } |
| 162 started_.Signal(); | 149 started_.Signal(); |
| 163 } | 150 } |
| 164 | 151 |
| 165 // Called on |io_message_loop_|. | 152 // Called on |io_message_loop_|. |
| 166 void DoCancel() { | 153 void DoCancel() { |
| 167 DCHECK(MessageLoop::current() == io_message_loop_); | 154 DCHECK(MessageLoop::current() == io_message_loop_); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 int result_code_; | 186 int result_code_; |
| 200 net::ProxyInfo proxy_info_; | 187 net::ProxyInfo proxy_info_; |
| 201 }; | 188 }; |
| 202 | 189 |
| 203 // Wraps a ProxyService running on its own IO thread. | 190 // Wraps a ProxyService running on its own IO thread. |
| 204 class ProxyServiceWithFutures { | 191 class ProxyServiceWithFutures { |
| 205 public: | 192 public: |
| 206 ProxyServiceWithFutures(net::ProxyConfigService* config_service, | 193 ProxyServiceWithFutures(net::ProxyConfigService* config_service, |
| 207 net::ProxyResolver* resolver) | 194 net::ProxyResolver* resolver) |
| 208 : io_thread_("IO_Thread"), | 195 : io_thread_("IO_Thread"), |
| 209 service_(config_service, resolver) { | 196 io_thread_state_(new IOThreadState) { |
| 210 base::Thread::Options options; | 197 base::Thread::Options options; |
| 211 options.message_loop_type = MessageLoop::TYPE_IO; | 198 options.message_loop_type = MessageLoop::TYPE_IO; |
| 212 io_thread_.StartWithOptions(options); | 199 io_thread_.StartWithOptions(options); |
| 200 |
| 201 // Initialize state that lives on |io_thread_|. |
| 202 io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( |
| 203 io_thread_state_.get(), &IOThreadState::DoInit, |
| 204 config_service, resolver)); |
| 205 io_thread_state_->event.Wait(); |
| 206 } |
| 207 |
| 208 ~ProxyServiceWithFutures() { |
| 209 // Destroy state that lives on |io_thread_|. |
| 210 io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( |
| 211 io_thread_state_.get(), &IOThreadState::DoDestroy)); |
| 212 io_thread_state_->event.Wait(); |
| 213 } | 213 } |
| 214 | 214 |
| 215 // Start the request on |io_thread_|, and return a handle that can be | 215 // Start the request on |io_thread_|, and return a handle that can be |
| 216 // used to access the results. The caller is responsible for freeing | 216 // used to access the results. The caller is responsible for freeing |
| 217 // the ResultFuture. | 217 // the ResultFuture. |
| 218 void ResolveProxy(scoped_refptr<ResultFuture>* result, const GURL& url) { | 218 void ResolveProxy(scoped_refptr<ResultFuture>* result, const GURL& url) { |
| 219 (*result) = new ResultFuture(io_thread_.message_loop(), &service_); | 219 *result = new ResultFuture(io_thread_.message_loop(), |
| 220 io_thread_state_->service); |
| 220 (*result)->StartResolve(url); | 221 (*result)->StartResolve(url); |
| 221 } | 222 } |
| 222 | 223 |
| 224 // Same as above, but for "ReconsiderProxyAfterError()". |
| 225 void ReconsiderProxyAfterError(scoped_refptr<ResultFuture>* result, |
| 226 const GURL& url, |
| 227 const net::ProxyInfo& proxy_info) { |
| 228 *result = new ResultFuture(io_thread_.message_loop(), |
| 229 io_thread_state_->service); |
| 230 (*result)->StartReconsider(url, proxy_info); |
| 231 } |
| 232 |
| 223 void SetProxyScriptFetcher(net::ProxyScriptFetcher* proxy_script_fetcher) { | 233 void SetProxyScriptFetcher(net::ProxyScriptFetcher* proxy_script_fetcher) { |
| 224 service_.SetProxyScriptFetcher(proxy_script_fetcher); | 234 io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( |
| 235 io_thread_state_.get(), &IOThreadState::DoSetProxyScriptFetcher, |
| 236 proxy_script_fetcher)); |
| 237 io_thread_state_->event.Wait(); |
| 225 } | 238 } |
| 226 | 239 |
| 227 private: | 240 private: |
| 241 // Class that encapsulates the state living on IO thread. It needs to be |
| 242 // ref-counted for posting tasks. |
| 243 class IOThreadState : public base::RefCounted<IOThreadState> { |
| 244 public: |
| 245 IOThreadState() : event(false, false), service(NULL) {} |
| 246 |
| 247 void DoInit(net::ProxyConfigService* config_service, |
| 248 net::ProxyResolver* resolver) { |
| 249 service = new net::ProxyService(config_service, resolver); |
| 250 event.Signal(); |
| 251 } |
| 252 |
| 253 void DoDestroy() { |
| 254 delete service; |
| 255 service = NULL; |
| 256 event.Signal(); |
| 257 } |
| 258 |
| 259 void DoSetProxyScriptFetcher( |
| 260 net::ProxyScriptFetcher* proxy_script_fetcher) { |
| 261 service->SetProxyScriptFetcher(proxy_script_fetcher); |
| 262 event.Signal(); |
| 263 } |
| 264 |
| 265 base::WaitableEvent event; |
| 266 net::ProxyService* service; |
| 267 }; |
| 268 |
| 228 base::Thread io_thread_; | 269 base::Thread io_thread_; |
| 229 net::ProxyService service_; | 270 scoped_refptr<IOThreadState> io_thread_state_; // Lives on |io_thread_|. |
| 271 }; |
| 272 |
| 273 // Wrapper around ProxyServiceWithFutures to do one request at a time. |
| 274 class SyncProxyService { |
| 275 public: |
| 276 SyncProxyService(net::ProxyConfigService* config_service, |
| 277 net::ProxyResolver* resolver) |
| 278 : service_(config_service, resolver) { |
| 279 } |
| 280 |
| 281 int ResolveProxy(const GURL& url, net::ProxyInfo* proxy_info) { |
| 282 scoped_refptr<ResultFuture> result; |
| 283 service_.ResolveProxy(&result, url); |
| 284 *proxy_info = result->GetProxyInfo(); |
| 285 return result->GetResultCode(); |
| 286 } |
| 287 |
| 288 int ReconsiderProxyAfterError(const GURL& url, net::ProxyInfo* proxy_info) { |
| 289 scoped_refptr<ResultFuture> result; |
| 290 service_.ReconsiderProxyAfterError(&result, url, *proxy_info); |
| 291 *proxy_info = result->GetProxyInfo(); |
| 292 return result->GetResultCode(); |
| 293 } |
| 294 |
| 295 private: |
| 296 ProxyServiceWithFutures service_; |
| 230 }; | 297 }; |
| 231 | 298 |
| 232 // A ProxyResolver which can be set to block upon reaching GetProxyForURL. | 299 // A ProxyResolver which can be set to block upon reaching GetProxyForURL. |
| 233 class BlockableProxyResolver : public net::ProxyResolver { | 300 class BlockableProxyResolver : public net::ProxyResolver { |
| 234 public: | 301 public: |
| 235 BlockableProxyResolver() : net::ProxyResolver(true), | 302 BlockableProxyResolver() : net::ProxyResolver(true), |
| 236 should_block_(false), | 303 should_block_(false), |
| 237 unblocked_(true, true), | 304 unblocked_(true, true), |
| 238 blocked_(true, false) { | 305 blocked_(true, false) { |
| 239 } | 306 } |
| (...skipping 676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 916 result3->WaitUntilCompleted(); | 983 result3->WaitUntilCompleted(); |
| 917 | 984 |
| 918 EXPECT_FALSE(result1->IsCompleted()); // Cancelled. | 985 EXPECT_FALSE(result1->IsCompleted()); // Cancelled. |
| 919 EXPECT_FALSE(result2->IsCompleted()); // Cancelled. | 986 EXPECT_FALSE(result2->IsCompleted()); // Cancelled. |
| 920 | 987 |
| 921 EXPECT_TRUE(result3->IsCompleted()); | 988 EXPECT_TRUE(result3->IsCompleted()); |
| 922 EXPECT_EQ(net::OK, result3->GetResultCode()); | 989 EXPECT_EQ(net::OK, result3->GetResultCode()); |
| 923 EXPECT_EQ("pac-v1.request3:80", | 990 EXPECT_EQ("pac-v1.request3:80", |
| 924 result3->GetProxyInfo().proxy_server().ToURI()); | 991 result3->GetProxyInfo().proxy_server().ToURI()); |
| 925 } | 992 } |
| OLD | NEW |