Index: net/proxy/proxy_service.cc |
=================================================================== |
--- net/proxy/proxy_service.cc (revision 8870) |
+++ net/proxy/proxy_service.cc (working copy) |
@@ -11,6 +11,7 @@ |
#include <algorithm> |
+#include "base/compiler_specific.h" |
#include "base/logging.h" |
#include "base/message_loop.h" |
#include "base/string_tokenizer.h" |
@@ -165,26 +166,6 @@ |
proxy_list_.Set(proxy_server); |
} |
-#if defined(OS_WIN) |
-void ProxyInfo::Apply(HINTERNET request_handle) { |
- WINHTTP_PROXY_INFO pi; |
- std::wstring proxy; // We need to declare this variable here because |
- // lpszProxy needs to be valid in WinHttpSetOption. |
- if (is_direct()) { |
- pi.dwAccessType = WINHTTP_ACCESS_TYPE_NO_PROXY; |
- pi.lpszProxy = WINHTTP_NO_PROXY_NAME; |
- pi.lpszProxyBypass = WINHTTP_NO_PROXY_BYPASS; |
- } else { |
- proxy = ASCIIToWide(proxy_list_.Get()); |
- pi.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY; |
- pi.lpszProxy = const_cast<LPWSTR>(proxy.c_str()); |
- // NOTE: Specifying a bypass list here would serve no purpose. |
- pi.lpszProxyBypass = WINHTTP_NO_PROXY_BYPASS; |
- } |
- WinHttpSetOption(request_handle, WINHTTP_OPTION_PROXY, &pi, sizeof(pi)); |
-} |
-#endif |
- |
std::string ProxyInfo::GetAnnotatedProxyList() { |
return is_direct() ? "DIRECT" : proxy_list_.GetAnnotatedList(); |
} |
@@ -205,23 +186,17 @@ |
results_(NULL), |
config_id_(service->config_id()), |
pac_url_(pac_url), |
- origin_loop_(NULL) { |
- // We need to remember original loop if only in case of asynchronous call |
- if (callback_) |
- origin_loop_ = MessageLoop::current(); |
+ origin_loop_(MessageLoop::current()) { |
+ DCHECK(callback); |
} |
void Query(const GURL& url, ProxyInfo* results) { |
results_ = results; |
- // If we have a valid callback then execute Query asynchronously |
- if (callback_) { |
- AddRef(); // balanced in QueryComplete |
- service_->pac_thread()->message_loop()->PostTask(FROM_HERE, |
- NewRunnableMethod(this, &ProxyService::PacRequest::DoQuery, |
- service_->resolver(), url, pac_url_)); |
- } else { |
- DoQuery(service_->resolver(), url, pac_url_); |
- } |
+ // Execute Query asynchronously |
+ AddRef(); // balanced in QueryComplete |
+ service_->pac_thread()->message_loop()->PostTask(FROM_HERE, |
+ NewRunnableMethod(this, &ProxyService::PacRequest::DoQuery, |
+ service_->resolver(), url, pac_url_)); |
} |
void Cancel() { |
@@ -233,37 +208,33 @@ |
} |
private: |
- // Runs on the PAC thread if a valid callback is provided. |
+ // Runs on the PAC thread. |
void DoQuery(ProxyResolver* resolver, |
const GURL& query_url, |
const GURL& pac_url) { |
int rv = resolver->GetProxyForURL(query_url, pac_url, &results_buf_); |
- if (origin_loop_) { |
- origin_loop_->PostTask(FROM_HERE, |
- NewRunnableMethod(this, &PacRequest::QueryComplete, rv)); |
- } else { |
- QueryComplete(rv); |
- } |
+ origin_loop_->PostTask(FROM_HERE, |
+ NewRunnableMethod(this, &PacRequest::QueryComplete, rv)); |
} |
- // If a valid callback is provided, this runs on the origin thread to |
- // indicate that the completion callback should be run. |
+ // Runs the completion callback on the origin thread. |
void QueryComplete(int result_code) { |
- if (service_) |
+ // The PacRequest may have been cancelled after it was started. If it was |
+ // cancelled then |callback_|, |service_|, and |results_| will be NULL. |
+ bool was_cancelled = callback_ == NULL; |
+ |
+ if (!was_cancelled) { |
service_->DidCompletePacRequest(config_id_, result_code); |
- if (result_code == OK && results_) { |
- results_->Use(results_buf_); |
- results_->RemoveBadProxies(service_->proxy_retry_info_); |
+ if (result_code == OK) { |
+ results_->Use(results_buf_); |
+ results_->RemoveBadProxies(service_->proxy_retry_info_); |
+ } |
+ callback_->Run(result_code); |
} |
- if (callback_) |
- callback_->Run(result_code); |
- |
- if (origin_loop_) { |
- Release(); // balances the AddRef in Query. we may get deleted after |
- // we return. |
- } |
+ Release(); // balances the AddRef in Query. we may get deleted after |
+ // we return. |
} |
// Must only be used on the "origin" thread. |
@@ -321,6 +292,7 @@ |
int ProxyService::ResolveProxy(const GURL& url, ProxyInfo* result, |
CompletionCallback* callback, |
PacRequest** pac_request) { |
+ DCHECK(callback); |
// The overhead of calling ProxyConfigService::GetProxyConfig is very low. |
const TimeDelta kProxyConfigMaxAge = TimeDelta::FromSeconds(5); |
@@ -381,18 +353,11 @@ |
} |
if (config_.pac_url.is_valid() || config_.auto_detect) { |
- if (callback) { |
- // Create PAC thread for asynchronous mode. |
- if (!pac_thread_.get()) { |
- pac_thread_.reset(new base::Thread("pac-thread")); |
- pac_thread_->Start(); |
- } |
- } else { |
- // If this request is synchronous, then there's no point |
- // in returning PacRequest instance |
- DCHECK(!pac_request); |
+ if (!pac_thread_.get()) { |
+ pac_thread_.reset(new base::Thread("pac-thread")); |
+ pac_thread_->Start(); |
} |
- |
+ |
scoped_refptr<PacRequest> req = |
new PacRequest(this, config_.pac_url, callback); |
@@ -410,12 +375,10 @@ |
req->Query(sanitized_url, result); |
- if (callback) { |
- if (pac_request) |
- *pac_request = req; |
- return ERR_IO_PENDING; // Wait for callback. |
- } |
- return OK; |
+ if (pac_request) |
+ *pac_request = req; |
+ |
+ return ERR_IO_PENDING; // Wait for callback. |
} |
} |
@@ -554,5 +517,65 @@ |
return false; |
} |
+SyncProxyServiceHelper::SyncProxyServiceHelper(MessageLoop* io_message_loop, |
+ ProxyService* proxy_service) |
+ : io_message_loop_(io_message_loop), |
+ proxy_service_(proxy_service), |
+ event_(false, false), |
+ ALLOW_THIS_IN_INITIALIZER_LIST(callback_( |
+ this, &SyncProxyServiceHelper::OnCompletion)) { |
+ DCHECK(io_message_loop_ != MessageLoop::current()); |
+} |
+ |
+int SyncProxyServiceHelper::ResolveProxy(const GURL& url, |
+ ProxyInfo* proxy_info) { |
+ DCHECK(io_message_loop_ != MessageLoop::current()); |
+ |
+ io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
+ this, &SyncProxyServiceHelper::StartAsyncResolve, url)); |
+ |
+ event_.Wait(); |
+ |
+ if (result_ == net::OK) { |
+ *proxy_info = proxy_info_; |
+ } |
+ return result_; |
+} |
+ |
+int SyncProxyServiceHelper::ReconsiderProxyAfterError(const GURL& url, |
+ ProxyInfo* proxy_info) { |
+ DCHECK(io_message_loop_ != MessageLoop::current()); |
+ |
+ io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
+ this, &SyncProxyServiceHelper::StartAsyncReconsider, url)); |
+ |
+ event_.Wait(); |
+ |
+ if (result_ == net::OK) { |
+ *proxy_info = proxy_info_; |
+ } |
+ return result_; |
+} |
+ |
+void SyncProxyServiceHelper::StartAsyncResolve(const GURL& url) { |
+ result_ = proxy_service_->ResolveProxy(url, &proxy_info_, &callback_, NULL); |
+ if (result_ != net::ERR_IO_PENDING) { |
+ OnCompletion(result_); |
+ } |
+} |
+ |
+void SyncProxyServiceHelper::StartAsyncReconsider(const GURL& url) { |
+ result_ = proxy_service_->ReconsiderProxyAfterError( |
+ url, &proxy_info_, &callback_, NULL); |
+ if (result_ != net::ERR_IO_PENDING) { |
+ OnCompletion(result_); |
+ } |
+} |
+ |
+void SyncProxyServiceHelper::OnCompletion(int rv) { |
+ result_ = rv; |
+ event_.Signal(); |
+} |
+ |
} // namespace net |