| 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 "net/http/http_transaction_winhttp.h" | 5 #include "net/http/http_transaction_winhttp.h" |
| 6 | 6 |
| 7 #include <winhttp.h> | 7 #include <winhttp.h> |
| 8 | 8 |
| 9 #include "base/lock.h" | 9 #include "base/lock.h" |
| 10 #include "base/memory_debug.h" | 10 #include "base/memory_debug.h" |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 | 165 |
| 166 class HttpTransactionWinHttp::Session | 166 class HttpTransactionWinHttp::Session |
| 167 : public base::RefCounted<HttpTransactionWinHttp::Session> { | 167 : public base::RefCounted<HttpTransactionWinHttp::Session> { |
| 168 public: | 168 public: |
| 169 enum { | 169 enum { |
| 170 // By default WinHTTP enables only SSL3 and TLS1. | 170 // By default WinHTTP enables only SSL3 and TLS1. |
| 171 SECURE_PROTOCOLS_SSL3_TLS1 = WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | | 171 SECURE_PROTOCOLS_SSL3_TLS1 = WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | |
| 172 WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 | 172 WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 |
| 173 }; | 173 }; |
| 174 | 174 |
| 175 Session() | 175 Session(); |
| 176 : internet_(NULL), | |
| 177 internet_no_tls_(NULL), | |
| 178 message_loop_(NULL), | |
| 179 handle_closing_event_(NULL), | |
| 180 quit_event_(NULL), | |
| 181 session_callback_ref_count_(0), | |
| 182 quitting_(false), | |
| 183 rev_checking_enabled_(false), | |
| 184 secure_protocols_(SECURE_PROTOCOLS_SSL3_TLS1) { | |
| 185 } | |
| 186 | 176 |
| 187 bool Init(); | 177 // Opens the primary WinHttp session handle. |
| 178 bool Init(const std::string& user_agent); |
| 188 | 179 |
| 189 // Opens the alternative WinHttp session handle for TLS-intolerant servers. | 180 // Opens the alternative WinHttp session handle for TLS-intolerant servers. |
| 190 bool InitNoTLS(); | 181 bool InitNoTLS(const std::string& user_agent); |
| 191 | 182 |
| 192 void AddRefBySessionCallback(); | 183 void AddRefBySessionCallback(); |
| 193 | 184 |
| 194 void ReleaseBySessionCallback(); | 185 void ReleaseBySessionCallback(); |
| 195 | 186 |
| 196 // The primary WinHttp session handle. | 187 // The primary WinHttp session handle. |
| 197 HINTERNET internet() { return internet_; } | 188 HINTERNET internet() { return internet_; } |
| 198 | 189 |
| 199 // An alternative WinHttp session handle. It is not opened until we have | 190 // An alternative WinHttp session handle. It is not opened until we have |
| 200 // encountered a TLS-intolerant server and used for those servers only. | 191 // encountered a TLS-intolerant server and used for those servers only. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 } | 224 } |
| 234 | 225 |
| 235 private: | 226 private: |
| 236 friend class base::RefCounted<HttpTransactionWinHttp::Session>; | 227 friend class base::RefCounted<HttpTransactionWinHttp::Session>; |
| 237 | 228 |
| 238 ~Session(); | 229 ~Session(); |
| 239 | 230 |
| 240 // Called by the destructor only. | 231 // Called by the destructor only. |
| 241 void WaitUntilCallbacksAllDone(); | 232 void WaitUntilCallbacksAllDone(); |
| 242 | 233 |
| 243 HINTERNET OpenWinHttpSession(); | 234 HINTERNET OpenWinHttpSession(const std::string& user_agent); |
| 244 | 235 |
| 245 // Get the SSL configuration settings and apply them to the session handle. | 236 // Get the SSL configuration settings and save them in rev_checking_enabled_ |
| 246 void ConfigureSSL(); | 237 // and secure_protocols_. |
| 238 void GetSSLConfig(); |
| 247 | 239 |
| 248 HINTERNET internet_; | 240 HINTERNET internet_; |
| 249 HINTERNET internet_no_tls_; | 241 HINTERNET internet_no_tls_; |
| 250 MessageLoop* message_loop_; | 242 MessageLoop* message_loop_; |
| 251 scoped_ptr<ProxyService> proxy_service_; | 243 scoped_ptr<ProxyService> proxy_service_; |
| 252 scoped_ptr<ProxyResolver> proxy_resolver_; | 244 scoped_ptr<ProxyResolver> proxy_resolver_; |
| 253 AuthCache auth_cache_; | 245 AuthCache auth_cache_; |
| 254 | 246 |
| 255 // This event object is used when destroying a transaction. It is given | 247 // This event object is used when destroying a transaction. It is given |
| 256 // to the transaction's session callback if WinHTTP still has the caller's | 248 // to the transaction's session callback if WinHTTP still has the caller's |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 // the session, we will have to remember all the servers we have visited | 289 // the session, we will have to remember all the servers we have visited |
| 298 // while the rev_checking_enabled setting is false. This will consume a | 290 // while the rev_checking_enabled setting is false. This will consume a |
| 299 // lot of memory. So we now require the users to restart Chrome for a | 291 // lot of memory. So we now require the users to restart Chrome for a |
| 300 // rev_checking_enabled change to take effect, just like IE does. | 292 // rev_checking_enabled change to take effect, just like IE does. |
| 301 typedef std::set<std::string> OriginSet; | 293 typedef std::set<std::string> OriginSet; |
| 302 OriginSet ignore_cert_rev_servers_; | 294 OriginSet ignore_cert_rev_servers_; |
| 303 | 295 |
| 304 WinHttpRequestThrottle request_throttle_; | 296 WinHttpRequestThrottle request_throttle_; |
| 305 }; | 297 }; |
| 306 | 298 |
| 299 HttpTransactionWinHttp::Session::Session() |
| 300 : internet_(NULL), |
| 301 internet_no_tls_(NULL), |
| 302 session_callback_ref_count_(0), |
| 303 quitting_(false) { |
| 304 proxy_resolver_.reset(new ProxyResolverWinHttp()); |
| 305 proxy_service_.reset(new ProxyService(proxy_resolver_.get())); |
| 306 |
| 307 GetSSLConfig(); |
| 308 |
| 309 // Save the current message loop for callback notifications. |
| 310 message_loop_ = MessageLoop::current(); |
| 311 |
| 312 handle_closing_event_ = CreateEvent(NULL, |
| 313 FALSE, // auto-reset |
| 314 FALSE, // initially nonsignaled |
| 315 NULL); // unnamed |
| 316 |
| 317 quit_event_ = CreateEvent(NULL, |
| 318 FALSE, // auto-reset |
| 319 FALSE, // initially nonsignaled |
| 320 NULL); // unnamed |
| 321 } |
| 322 |
| 307 HttpTransactionWinHttp::Session::~Session() { | 323 HttpTransactionWinHttp::Session::~Session() { |
| 308 // It is important to shutdown the proxy service before closing the WinHTTP | 324 // It is important to shutdown the proxy service before closing the WinHTTP |
| 309 // session handle since the proxy service uses the WinHTTP session handle. | 325 // session handle since the proxy service uses the WinHTTP session handle. |
| 310 proxy_service_.reset(); | 326 proxy_service_.reset(); |
| 311 | 327 |
| 312 // Next, the resolver which also references our session handle. | 328 // Next, the resolver which also references our session handle. |
| 313 proxy_resolver_.reset(); | 329 proxy_resolver_.reset(); |
| 314 | 330 |
| 315 if (internet_) { | 331 if (internet_) { |
| 316 WinHttpCloseHandle(internet_); | 332 WinHttpCloseHandle(internet_); |
| 317 if (internet_no_tls_) | 333 if (internet_no_tls_) |
| 318 WinHttpCloseHandle(internet_no_tls_); | 334 WinHttpCloseHandle(internet_no_tls_); |
| 319 | 335 |
| 320 // Ensure that all status callbacks that may reference the MessageLoop | 336 // Ensure that all status callbacks that may reference the MessageLoop |
| 321 // of this thread are done before we can allow the current thread to exit. | 337 // of this thread are done before we can allow the current thread to exit. |
| 322 WaitUntilCallbacksAllDone(); | 338 WaitUntilCallbacksAllDone(); |
| 323 } | 339 } |
| 324 | 340 |
| 325 if (handle_closing_event_) | 341 if (handle_closing_event_) |
| 326 CloseHandle(handle_closing_event_); | 342 CloseHandle(handle_closing_event_); |
| 327 if (quit_event_) | 343 if (quit_event_) |
| 328 CloseHandle(quit_event_); | 344 CloseHandle(quit_event_); |
| 329 } | 345 } |
| 330 | 346 |
| 331 bool HttpTransactionWinHttp::Session::Init() { | 347 bool HttpTransactionWinHttp::Session::Init(const std::string& user_agent) { |
| 332 DCHECK(!internet_); | 348 DCHECK(!internet_); |
| 333 | 349 |
| 334 internet_ = OpenWinHttpSession(); | 350 internet_ = OpenWinHttpSession(user_agent); |
| 335 | 351 |
| 336 if (!internet_) | 352 if (!internet_) |
| 337 return false; | 353 return false; |
| 338 | 354 |
| 339 proxy_resolver_.reset(new ProxyResolverWinHttp()); | 355 if (secure_protocols_ != SECURE_PROTOCOLS_SSL3_TLS1) { |
| 340 proxy_service_.reset(new ProxyService(proxy_resolver_.get())); | 356 BOOL rv = WinHttpSetOption(internet_, WINHTTP_OPTION_SECURE_PROTOCOLS, |
| 341 | 357 &secure_protocols_, sizeof(secure_protocols_)); |
| 342 ConfigureSSL(); | 358 DCHECK(rv); |
| 343 | 359 } |
| 344 // Save the current message loop for callback notifications. | |
| 345 message_loop_ = MessageLoop::current(); | |
| 346 | |
| 347 handle_closing_event_ = CreateEvent(NULL, | |
| 348 FALSE, // auto-reset | |
| 349 FALSE, // initially nonsignaled | |
| 350 NULL); // unnamed | |
| 351 | |
| 352 quit_event_ = CreateEvent(NULL, | |
| 353 FALSE, // auto-reset | |
| 354 FALSE, // initially nonsignaled | |
| 355 NULL); // unnamed | |
| 356 | 360 |
| 357 return true; | 361 return true; |
| 358 } | 362 } |
| 359 | 363 |
| 360 bool HttpTransactionWinHttp::Session::InitNoTLS() { | 364 bool HttpTransactionWinHttp::Session::InitNoTLS( |
| 365 const std::string& user_agent) { |
| 361 DCHECK(tls_enabled()); | 366 DCHECK(tls_enabled()); |
| 362 DCHECK(internet_); | 367 DCHECK(internet_); |
| 363 DCHECK(!internet_no_tls_); | 368 DCHECK(!internet_no_tls_); |
| 364 | 369 |
| 365 internet_no_tls_ = OpenWinHttpSession(); | 370 internet_no_tls_ = OpenWinHttpSession(user_agent); |
| 366 | 371 |
| 367 if (!internet_no_tls_) | 372 if (!internet_no_tls_) |
| 368 return false; | 373 return false; |
| 369 | 374 |
| 370 DWORD protocols = secure_protocols_ & ~WINHTTP_FLAG_SECURE_PROTOCOL_TLS1; | 375 DWORD protocols = secure_protocols_ & ~WINHTTP_FLAG_SECURE_PROTOCOL_TLS1; |
| 371 BOOL rv = WinHttpSetOption(internet_no_tls_, | 376 BOOL rv = WinHttpSetOption(internet_no_tls_, |
| 372 WINHTTP_OPTION_SECURE_PROTOCOLS, | 377 WINHTTP_OPTION_SECURE_PROTOCOLS, |
| 373 &protocols, sizeof(protocols)); | 378 &protocols, sizeof(protocols)); |
| 374 DCHECK(rv); | 379 DCHECK(rv); |
| 375 | 380 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 402 { | 407 { |
| 403 AutoLock lock(lock_); | 408 AutoLock lock(lock_); |
| 404 quitting_ = true; | 409 quitting_ = true; |
| 405 need_to_wait = (session_callback_ref_count_ != 0); | 410 need_to_wait = (session_callback_ref_count_ != 0); |
| 406 } | 411 } |
| 407 if (need_to_wait) | 412 if (need_to_wait) |
| 408 WaitForSingleObject(quit_event_, INFINITE); | 413 WaitForSingleObject(quit_event_, INFINITE); |
| 409 DCHECK(session_callback_ref_count_ == 0); | 414 DCHECK(session_callback_ref_count_ == 0); |
| 410 } | 415 } |
| 411 | 416 |
| 412 HINTERNET HttpTransactionWinHttp::Session::OpenWinHttpSession() { | 417 HINTERNET HttpTransactionWinHttp::Session::OpenWinHttpSession( |
| 413 // UA string and proxy config will be set explicitly for each request | 418 const std::string& user_agent) { |
| 414 HINTERNET internet = WinHttpOpen(NULL, | 419 // Proxy config will be set explicitly for each request. |
| 420 // |
| 421 // Although UA string will also be set explicitly for each request, HTTP |
| 422 // CONNECT requests use the UA string of the session handle, so we have to |
| 423 // pass a UA string to WinHttpOpen. |
| 424 HINTERNET internet = WinHttpOpen(ASCIIToWide(user_agent).c_str(), |
| 415 WINHTTP_ACCESS_TYPE_NO_PROXY, | 425 WINHTTP_ACCESS_TYPE_NO_PROXY, |
| 416 WINHTTP_NO_PROXY_NAME, | 426 WINHTTP_NO_PROXY_NAME, |
| 417 WINHTTP_NO_PROXY_BYPASS, | 427 WINHTTP_NO_PROXY_BYPASS, |
| 418 WINHTTP_FLAG_ASYNC); | 428 WINHTTP_FLAG_ASYNC); |
| 419 if (!internet) | 429 if (!internet) |
| 420 return internet; | 430 return internet; |
| 421 | 431 |
| 422 // Use a 90-second timeout (1.5 times the default) for connect. Disable | 432 // Use a 90-second timeout (1.5 times the default) for connect. Disable |
| 423 // name resolution, send, and receive timeouts. We expect our consumer to | 433 // name resolution, send, and receive timeouts. We expect our consumer to |
| 424 // apply timeouts or provide controls for users to stop requests that are | 434 // apply timeouts or provide controls for users to stop requests that are |
| 425 // taking too long. | 435 // taking too long. |
| 426 BOOL rv = WinHttpSetTimeouts(internet, 0, 90000, 0, 0); | 436 BOOL rv = WinHttpSetTimeouts(internet, 0, 90000, 0, 0); |
| 427 DCHECK(rv); | 437 DCHECK(rv); |
| 428 | 438 |
| 429 return internet; | 439 return internet; |
| 430 } | 440 } |
| 431 | 441 |
| 432 void HttpTransactionWinHttp::Session::ConfigureSSL() { | 442 void HttpTransactionWinHttp::Session::GetSSLConfig() { |
| 433 DCHECK(internet_); | |
| 434 | |
| 435 SSLConfig ssl_config; | 443 SSLConfig ssl_config; |
| 436 SSLConfigService::GetSSLConfigNow(&ssl_config); | 444 SSLConfigService::GetSSLConfigNow(&ssl_config); |
| 437 rev_checking_enabled_ = ssl_config.rev_checking_enabled; | 445 rev_checking_enabled_ = ssl_config.rev_checking_enabled; |
| 438 DWORD protocols = 0; | 446 secure_protocols_ = 0; |
| 439 if (ssl_config.ssl2_enabled) | 447 if (ssl_config.ssl2_enabled) |
| 440 protocols |= WINHTTP_FLAG_SECURE_PROTOCOL_SSL2; | 448 secure_protocols_ |= WINHTTP_FLAG_SECURE_PROTOCOL_SSL2; |
| 441 if (ssl_config.ssl3_enabled) | 449 if (ssl_config.ssl3_enabled) |
| 442 protocols |= WINHTTP_FLAG_SECURE_PROTOCOL_SSL3; | 450 secure_protocols_ |= WINHTTP_FLAG_SECURE_PROTOCOL_SSL3; |
| 443 if (ssl_config.tls1_enabled) | 451 if (ssl_config.tls1_enabled) |
| 444 protocols |= WINHTTP_FLAG_SECURE_PROTOCOL_TLS1; | 452 secure_protocols_ |= WINHTTP_FLAG_SECURE_PROTOCOL_TLS1; |
| 445 if (protocols != secure_protocols_) { | |
| 446 BOOL rv = WinHttpSetOption(internet_, WINHTTP_OPTION_SECURE_PROTOCOLS, | |
| 447 &protocols, sizeof(protocols)); | |
| 448 DCHECK(rv); | |
| 449 secure_protocols_ = protocols; | |
| 450 } | |
| 451 } | 453 } |
| 452 | 454 |
| 453 // SessionCallback ------------------------------------------------------------ | 455 // SessionCallback ------------------------------------------------------------ |
| 454 | 456 |
| 455 class HttpTransactionWinHttp::SessionCallback | 457 class HttpTransactionWinHttp::SessionCallback |
| 456 : public base::RefCountedThreadSafe<HttpTransactionWinHttp::SessionCallback> { | 458 : public base::RefCountedThreadSafe<HttpTransactionWinHttp::SessionCallback> { |
| 457 public: | 459 public: |
| 458 SessionCallback(HttpTransactionWinHttp* trans, Session* session) | 460 SessionCallback(HttpTransactionWinHttp* trans, Session* session) |
| 459 : trans_(trans), | 461 : trans_(trans), |
| 460 session_(session), | 462 session_(session), |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 735 session_->Release(); | 737 session_->Release(); |
| 736 } | 738 } |
| 737 | 739 |
| 738 HttpTransaction* HttpTransactionWinHttp::Factory::CreateTransaction() { | 740 HttpTransaction* HttpTransactionWinHttp::Factory::CreateTransaction() { |
| 739 if (is_suspended_) | 741 if (is_suspended_) |
| 740 return NULL; | 742 return NULL; |
| 741 | 743 |
| 742 if (!session_) { | 744 if (!session_) { |
| 743 session_ = new Session(); | 745 session_ = new Session(); |
| 744 session_->AddRef(); | 746 session_->AddRef(); |
| 745 if (!session_->Init()) { | |
| 746 DLOG(ERROR) << "unable to create the internet"; | |
| 747 session_->Release(); | |
| 748 session_ = NULL; | |
| 749 return NULL; | |
| 750 } | |
| 751 } | 747 } |
| 752 return new HttpTransactionWinHttp(session_, proxy_info_.get()); | 748 return new HttpTransactionWinHttp(session_, proxy_info_.get()); |
| 753 } | 749 } |
| 754 | 750 |
| 755 HttpCache* HttpTransactionWinHttp::Factory::GetCache() { | 751 HttpCache* HttpTransactionWinHttp::Factory::GetCache() { |
| 756 return NULL; | 752 return NULL; |
| 757 } | 753 } |
| 758 | 754 |
| 759 AuthCache* HttpTransactionWinHttp::Factory::GetAuthCache() { | 755 AuthCache* HttpTransactionWinHttp::Factory::GetAuthCache() { |
| 760 return session_->auth_cache(); | 756 return session_->auth_cache(); |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1055 } | 1051 } |
| 1056 | 1052 |
| 1057 const std::string& host = url.host(); | 1053 const std::string& host = url.host(); |
| 1058 | 1054 |
| 1059 // Use the primary session handle unless we are talking to a TLS-intolerant | 1055 // Use the primary session handle unless we are talking to a TLS-intolerant |
| 1060 // server. | 1056 // server. |
| 1061 // | 1057 // |
| 1062 // Since the SSL protocol versions enabled are an option of a session | 1058 // Since the SSL protocol versions enabled are an option of a session |
| 1063 // handle, supporting TLS-intolerant servers unfortunately requires opening | 1059 // handle, supporting TLS-intolerant servers unfortunately requires opening |
| 1064 // an alternative session in which TLS 1.0 is disabled. | 1060 // an alternative session in which TLS 1.0 is disabled. |
| 1061 if (!session_->internet() && !session_->Init(request_->user_agent)) { |
| 1062 DLOG(ERROR) << "unable to create the internet"; |
| 1063 return false; |
| 1064 } |
| 1065 HINTERNET internet = session_->internet(); | 1065 HINTERNET internet = session_->internet(); |
| 1066 if (is_tls_intolerant_) { | 1066 if (is_tls_intolerant_) { |
| 1067 if (!session_->internet_no_tls() && !session_->InitNoTLS()) { | 1067 if (!session_->internet_no_tls() && |
| 1068 !session_->InitNoTLS(request_->user_agent)) { |
| 1068 DLOG(ERROR) << "unable to create the no-TLS alternative internet"; | 1069 DLOG(ERROR) << "unable to create the no-TLS alternative internet"; |
| 1069 return false; | 1070 return false; |
| 1070 } | 1071 } |
| 1071 internet = session_->internet_no_tls(); | 1072 internet = session_->internet_no_tls(); |
| 1072 } | 1073 } |
| 1073 | 1074 |
| 1074 // This function operates synchronously. | 1075 // This function operates synchronously. |
| 1075 connect_handle_ = | 1076 connect_handle_ = |
| 1076 WinHttpConnect(internet, ASCIIToWide(host).c_str(), port, 0); | 1077 WinHttpConnect(internet, ASCIIToWide(host).c_str(), port, 0); |
| 1077 if (!connect_handle_) { | 1078 if (!connect_handle_) { |
| (...skipping 710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1788 | 1789 |
| 1789 if (rv == ERR_IO_PENDING) { | 1790 if (rv == ERR_IO_PENDING) { |
| 1790 session_callback_->AddRef(); // balanced when callback runs. | 1791 session_callback_->AddRef(); // balanced when callback runs. |
| 1791 } else if (callback_) { | 1792 } else if (callback_) { |
| 1792 DoCallback(rv); | 1793 DoCallback(rv); |
| 1793 } | 1794 } |
| 1794 } | 1795 } |
| 1795 | 1796 |
| 1796 } // namespace net | 1797 } // namespace net |
| 1797 | 1798 |
| OLD | NEW |