| Index: net/proxy/proxy_service_unittest.cc
|
| ===================================================================
|
| --- net/proxy/proxy_service_unittest.cc (revision 12402)
|
| +++ net/proxy/proxy_service_unittest.cc (working copy)
|
| @@ -58,33 +58,6 @@
|
| bool fail_get_proxy_for_url;
|
| };
|
|
|
| -class SyncProxyService {
|
| - public:
|
| - SyncProxyService(net::ProxyConfigService* config_service,
|
| - net::ProxyResolver* resolver)
|
| - : io_thread_("IO_Thread"),
|
| - service_(config_service, resolver) {
|
| - base::Thread::Options options;
|
| - options.message_loop_type = MessageLoop::TYPE_IO;
|
| - io_thread_.StartWithOptions(options);
|
| - sync_proxy_service_ = new net::SyncProxyServiceHelper(
|
| - io_thread_.message_loop(), &service_);
|
| - }
|
| -
|
| - int ResolveProxy(const GURL& url, net::ProxyInfo* proxy_info) {
|
| - return sync_proxy_service_->ResolveProxy(url, proxy_info);
|
| - }
|
| -
|
| - int ReconsiderProxyAfterError(const GURL& url, net::ProxyInfo* proxy_info) {
|
| - return sync_proxy_service_->ReconsiderProxyAfterError(url, proxy_info);
|
| - }
|
| -
|
| - private:
|
| - base::Thread io_thread_;
|
| - net::ProxyService service_;
|
| - scoped_refptr<net::SyncProxyServiceHelper> sync_proxy_service_;
|
| -};
|
| -
|
| // ResultFuture is a handle to get at the result from
|
| // ProxyService::ResolveProxyForURL() that ran on another thread.
|
| class ResultFuture : public base::RefCountedThreadSafe<ResultFuture> {
|
| @@ -143,18 +116,32 @@
|
| private:
|
| friend class ProxyServiceWithFutures;
|
|
|
| - // Start the request. Return once ProxyService::GetProxyForURL() returns.
|
| + typedef int (net::ProxyService::*RequestMethod)(const GURL&, net::ProxyInfo*,
|
| + net::CompletionCallback*, net::ProxyService::PacRequest**);
|
| +
|
| void StartResolve(const GURL& url) {
|
| + StartRequest(url, &net::ProxyService::ResolveProxy);
|
| + }
|
| +
|
| + // |proxy_info| is the *previous* result (that we are reconsidering).
|
| + void StartReconsider(const GURL& url, const net::ProxyInfo& proxy_info) {
|
| + proxy_info_ = proxy_info;
|
| + StartRequest(url, &net::ProxyService::ReconsiderProxyAfterError);
|
| + }
|
| +
|
| + // Start the request. Return once ProxyService::GetProxyForURL() or
|
| + // ProxyService::ReconsiderProxyAfterError() returns.
|
| + void StartRequest(const GURL& url, RequestMethod method) {
|
| DCHECK(MessageLoop::current() != io_message_loop_);
|
| io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
|
| - this, &ResultFuture::DoStartResolve, url));
|
| + this, &ResultFuture::DoStartRequest, url, method));
|
| started_.Wait();
|
| }
|
|
|
| // Called on |io_message_loop_|.
|
| - void DoStartResolve(const GURL& url) {
|
| + void DoStartRequest(const GURL& url, RequestMethod method) {
|
| DCHECK(MessageLoop::current() == io_message_loop_);
|
| - int rv = service_->ResolveProxy(url, &proxy_info_, &callback_, &request_);
|
| + int rv = (service_->*method)(url, &proxy_info_, &callback_, &request_);
|
| if (rv != net::ERR_IO_PENDING) {
|
| // Completed synchronously.
|
| OnCompletion(rv);
|
| @@ -206,29 +193,109 @@
|
| ProxyServiceWithFutures(net::ProxyConfigService* config_service,
|
| net::ProxyResolver* resolver)
|
| : io_thread_("IO_Thread"),
|
| - service_(config_service, resolver) {
|
| + io_thread_state_(new IOThreadState) {
|
| base::Thread::Options options;
|
| options.message_loop_type = MessageLoop::TYPE_IO;
|
| io_thread_.StartWithOptions(options);
|
| +
|
| + // Initialize state that lives on |io_thread_|.
|
| + io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
|
| + io_thread_state_.get(), &IOThreadState::DoInit,
|
| + config_service, resolver));
|
| + io_thread_state_->event.Wait();
|
| }
|
|
|
| + ~ProxyServiceWithFutures() {
|
| + // Destroy state that lives on |io_thread_|.
|
| + io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
|
| + io_thread_state_.get(), &IOThreadState::DoDestroy));
|
| + io_thread_state_->event.Wait();
|
| + }
|
| +
|
| // Start the request on |io_thread_|, and return a handle that can be
|
| // used to access the results. The caller is responsible for freeing
|
| // the ResultFuture.
|
| void ResolveProxy(scoped_refptr<ResultFuture>* result, const GURL& url) {
|
| - (*result) = new ResultFuture(io_thread_.message_loop(), &service_);
|
| + *result = new ResultFuture(io_thread_.message_loop(),
|
| + io_thread_state_->service);
|
| (*result)->StartResolve(url);
|
| }
|
|
|
| + // Same as above, but for "ReconsiderProxyAfterError()".
|
| + void ReconsiderProxyAfterError(scoped_refptr<ResultFuture>* result,
|
| + const GURL& url,
|
| + const net::ProxyInfo& proxy_info) {
|
| + *result = new ResultFuture(io_thread_.message_loop(),
|
| + io_thread_state_->service);
|
| + (*result)->StartReconsider(url, proxy_info);
|
| + }
|
| +
|
| void SetProxyScriptFetcher(net::ProxyScriptFetcher* proxy_script_fetcher) {
|
| - service_.SetProxyScriptFetcher(proxy_script_fetcher);
|
| + io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
|
| + io_thread_state_.get(), &IOThreadState::DoSetProxyScriptFetcher,
|
| + proxy_script_fetcher));
|
| + io_thread_state_->event.Wait();
|
| }
|
|
|
| private:
|
| + // Class that encapsulates the state living on IO thread. It needs to be
|
| + // ref-counted for posting tasks.
|
| + class IOThreadState : public base::RefCounted<IOThreadState> {
|
| + public:
|
| + IOThreadState() : event(false, false), service(NULL) {}
|
| +
|
| + void DoInit(net::ProxyConfigService* config_service,
|
| + net::ProxyResolver* resolver) {
|
| + service = new net::ProxyService(config_service, resolver);
|
| + event.Signal();
|
| + }
|
| +
|
| + void DoDestroy() {
|
| + delete service;
|
| + service = NULL;
|
| + event.Signal();
|
| + }
|
| +
|
| + void DoSetProxyScriptFetcher(
|
| + net::ProxyScriptFetcher* proxy_script_fetcher) {
|
| + service->SetProxyScriptFetcher(proxy_script_fetcher);
|
| + event.Signal();
|
| + }
|
| +
|
| + base::WaitableEvent event;
|
| + net::ProxyService* service;
|
| + };
|
| +
|
| base::Thread io_thread_;
|
| - net::ProxyService service_;
|
| + scoped_refptr<IOThreadState> io_thread_state_; // Lives on |io_thread_|.
|
| };
|
|
|
| +// Wrapper around ProxyServiceWithFutures to do one request at a time.
|
| +class SyncProxyService {
|
| + public:
|
| + SyncProxyService(net::ProxyConfigService* config_service,
|
| + net::ProxyResolver* resolver)
|
| + : service_(config_service, resolver) {
|
| + }
|
| +
|
| + int ResolveProxy(const GURL& url, net::ProxyInfo* proxy_info) {
|
| + scoped_refptr<ResultFuture> result;
|
| + service_.ResolveProxy(&result, url);
|
| + *proxy_info = result->GetProxyInfo();
|
| + return result->GetResultCode();
|
| + }
|
| +
|
| + int ReconsiderProxyAfterError(const GURL& url, net::ProxyInfo* proxy_info) {
|
| + scoped_refptr<ResultFuture> result;
|
| + service_.ReconsiderProxyAfterError(&result, url, *proxy_info);
|
| + *proxy_info = result->GetProxyInfo();
|
| + return result->GetResultCode();
|
| + }
|
| +
|
| + private:
|
| + ProxyServiceWithFutures service_;
|
| +};
|
| +
|
| // A ProxyResolver which can be set to block upon reaching GetProxyForURL.
|
| class BlockableProxyResolver : public net::ProxyResolver {
|
| public:
|
|
|