diff options
author | wtc@google.com <wtc@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-14 00:36:54 +0000 |
---|---|---|
committer | wtc@google.com <wtc@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-14 00:36:54 +0000 |
commit | fbdf63cb3cf3fbc608f4979fc702fada3147a329 (patch) | |
tree | 83a3cd931b7150429ee1bceee696d2746a60b823 /net | |
parent | 56d5c570a0ef7da0e71290a7614c9cb140c77374 (diff) | |
download | chromium_src-fbdf63cb3cf3fbc608f4979fc702fada3147a329.zip chromium_src-fbdf63cb3cf3fbc608f4979fc702fada3147a329.tar.gz chromium_src-fbdf63cb3cf3fbc608f4979fc702fada3147a329.tar.bz2 |
Fix the duplicate session_callback_->AddRef() calls made by
the Restart() calls in DidReceiveError() and the RestartWithAuth()
call in DidReceiveHeaders() by adding a new RestartInternal()
method that doesn't call session_callback_->AddRef().
Remove the username/password that the server rejected from the
auth cache only if the cache entry has the same username/password.
Use the username:password specified in the URL after receiving
a 401 response from the server. Do not send it preemptively.
R=eroman
BUG=b/1473850
Review URL: http://codereview.chromium.org/10668
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5421 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/http/http_transaction_winhttp.cc | 95 | ||||
-rw-r--r-- | net/http/http_transaction_winhttp.h | 4 |
2 files changed, 56 insertions, 43 deletions
diff --git a/net/http/http_transaction_winhttp.cc b/net/http/http_transaction_winhttp.cc index 460ad8a..aa52faf 100644 --- a/net/http/http_transaction_winhttp.cc +++ b/net/http/http_transaction_winhttp.cc @@ -782,9 +782,10 @@ HttpTransactionWinHttp::HttpTransactionWinHttp(Session* session, is_https_(false), is_tls_intolerant_(false), rev_checking_enabled_(false), - request_submitted_(false), have_proxy_info_(false), - need_to_wait_for_handle_closing_(false) { + need_to_wait_for_handle_closing_(false), + request_submitted_(false), + used_embedded_credentials_(false) { session->AddRef(); session_callback_ = new SessionCallback(this, session); if (info) { @@ -940,10 +941,7 @@ int HttpTransactionWinHttp::Restart(CompletionCallback* callback) { // ensure that we only have one asynchronous call at a time. DCHECK(!callback_); - content_length_remaining_ = -1; - upload_progress_ = 0; - - int rv = SendRequest(); + int rv = RestartInternal(); if (rv != ERR_IO_PENDING) return rv; @@ -953,6 +951,17 @@ int HttpTransactionWinHttp::Restart(CompletionCallback* callback) { return ERR_IO_PENDING; } +// If HttpTransactionWinHttp needs to restart itself after handling an error, +// it calls this method. This method leaves callback_ unchanged. The caller +// is responsible for calling session_callback_->AddRef() if this method +// returns ERR_IO_PENDING. +int HttpTransactionWinHttp::RestartInternal() { + content_length_remaining_ = -1; + upload_progress_ = 0; + + return SendRequest(); +} + // We use WinHttpQueryDataAvailable rather than pure async read to trade // a better latency for a decreased throughput. We'll make more IO calls, // and thus use more CPU for a given transaction by using @@ -1308,11 +1317,8 @@ int HttpTransactionWinHttp::DidReceiveError(DWORD error, int rv; - if (error == ERROR_WINHTTP_RESEND_REQUEST) { - CompletionCallback* callback = callback_; - callback_ = NULL; - return Restart(callback); - } + if (error == ERROR_WINHTTP_RESEND_REQUEST) + return RestartInternal(); if (error == ERROR_WINHTTP_NAME_NOT_RESOLVED || error == ERROR_WINHTTP_CANNOT_CONNECT || @@ -1353,9 +1359,7 @@ int HttpTransactionWinHttp::DidReceiveError(DWORD error, is_tls_intolerant_ = true; if (!ReopenRequest()) return TranslateLastOSError(); - CompletionCallback* callback = callback_; - callback_ = NULL; - return Restart(callback); + return RestartInternal(); } if (rv == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { // TODO(wtc): Bug 1230409: We don't support SSL client authentication yet. @@ -1365,11 +1369,8 @@ int HttpTransactionWinHttp::DidReceiveError(DWORD error, // client certificates. if (WinHttpSetOption(request_handle_, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, - WINHTTP_NO_CLIENT_CERT_CONTEXT, 0)) { - CompletionCallback* callback = callback_; - callback_ = NULL; - return Restart(callback); - } + WINHTTP_NO_CLIENT_CERT_CONTEXT, 0)) + return RestartInternal(); } if (IsCertificateError(rv)) { response_.ssl_info.cert = GetServerCertificate(); @@ -1568,17 +1569,39 @@ int HttpTransactionWinHttp::PopulateAuthChallenge() { DCHECK(!auth_cache_key->empty()); auth->scheme = auth_info->scheme; if (auth->state == AUTH_STATE_HAVE_AUTH) { - session_->auth_cache()->Remove(*auth_cache_key); - auth->state = AUTH_STATE_NEED_AUTH; - } else { + // Remove the cache entry for the credentials we just failed on. + // Note: we require the username/password to match before removing + // since the entry in the cache may be newer than what we used last time. AuthData* cached_auth = session_->auth_cache()->Lookup(*auth_cache_key); - if (cached_auth) { - CompletionCallback* callback = callback_; - callback_ = NULL; - return RestartWithAuth(cached_auth->username, - cached_auth->password, - callback); - } + if (cached_auth && cached_auth->username == auth->username && + cached_auth->password == auth->password) + session_->auth_cache()->Remove(*auth_cache_key); + auth->state = AUTH_STATE_NEED_AUTH; + } + DCHECK(auth->state == AUTH_STATE_NEED_AUTH); + + // Try to use the username/password embedded in the URL first. + // (By checking !used_embedded_credentials_, we make sure that this + // is only done once for the transaction.) + if (!auth_info->is_proxy && request_->url.has_username() && + !used_embedded_credentials_) { + // TODO(wtc) It may be necessary to unescape the username and password + // after extracting them from the URL. We should be careful about + // embedded nulls in that case. + used_embedded_credentials_ = true; + auth->state = AUTH_STATE_HAVE_AUTH; + auth->username = ASCIIToWide(request_->url.username()); + auth->password = ASCIIToWide(request_->url.password()); + return RestartInternal(); + } + + // Check the auth cache for an entry. + AuthData* cached_auth = session_->auth_cache()->Lookup(*auth_cache_key); + if (cached_auth) { + auth->state = AUTH_STATE_HAVE_AUTH; + auth->username = cached_auth->username; + auth->password = cached_auth->password; + return RestartInternal(); } response_.auth_challenge.swap(auth_info); @@ -1619,10 +1642,6 @@ void HttpTransactionWinHttp::ApplyAuth() { NULL); } - // First, check if we have auth, then check URL. - // That way a user can re-enter credentials, and we'll try with their - // latest input rather than always trying what they specified - // in the URL (if anything). if (server_auth_ && server_auth_->state == AUTH_STATE_HAVE_AUTH) { // Add auth data to cache. DCHECK(!server_auth_cache_key_.empty()); @@ -1637,16 +1656,6 @@ void HttpTransactionWinHttp::ApplyAuth() { server_auth_->username.c_str(), server_auth_->password.c_str(), NULL); - } else if (request_->url.has_username()) { - // TODO(wtc) It may be necessary to unescape the username and password - // after extracting them from the URL. We should be careful about - // embedded nulls in that case. - rv = WinHttpSetCredentials(request_handle_, - WINHTTP_AUTH_TARGET_SERVER, - WINHTTP_AUTH_SCHEME_BASIC, // TODO(wtc) - ASCIIToWide(request_->url.username()).c_str(), - ASCIIToWide(request_->url.password()).c_str(), - NULL); } } diff --git a/net/http/http_transaction_winhttp.h b/net/http/http_transaction_winhttp.h index 5bb3b94..46b69d8 100644 --- a/net/http/http_transaction_winhttp.h +++ b/net/http/http_transaction_winhttp.h @@ -87,6 +87,7 @@ class HttpTransactionWinHttp : public HttpTransaction { int SendRequest(); bool ReopenRequest(); int Restart(CompletionCallback* callback); + int RestartInternal(); int DidResolveProxy(); int DidReceiveError(DWORD error, DWORD secure_failure); int DidSendRequest(); @@ -189,6 +190,9 @@ class HttpTransactionWinHttp : public HttpTransaction { // called WinHttpRequestThrottle::NotifyRequestDone. bool request_submitted_; + // True if we have used the username/password embedded in the URL. + bool used_embedded_credentials_; + DISALLOW_EVIL_CONSTRUCTORS(HttpTransactionWinHttp); }; |