Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/password_manager/password_form_manager.h" | 5 #include "chrome/browser/password_manager/password_form_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/string_split.h" | 10 #include "base/string_split.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 51 GetActionsTaken(), | 51 GetActionsTaken(), |
| 52 kMaxNumActionsTaken); | 52 kMaxNumActionsTaken); |
| 53 } | 53 } |
| 54 | 54 |
| 55 int PasswordFormManager::GetActionsTaken() { | 55 int PasswordFormManager::GetActionsTaken() { |
| 56 return user_action_ + kUserActionMax * (manager_action_ + | 56 return user_action_ + kUserActionMax * (manager_action_ + |
| 57 kManagerActionMax * submit_result_); | 57 kManagerActionMax * submit_result_); |
| 58 }; | 58 }; |
| 59 | 59 |
| 60 // TODO(timsteele): use a hash of some sort in the future? | 60 // TODO(timsteele): use a hash of some sort in the future? |
| 61 bool PasswordFormManager::DoesManage(const PasswordForm& form) const { | 61 bool PasswordFormManager::DoesManage(const PasswordForm& form, |
| 62 ActionMatch action_match) const { | |
| 62 if (form.scheme != PasswordForm::SCHEME_HTML) | 63 if (form.scheme != PasswordForm::SCHEME_HTML) |
| 63 return observed_form_.signon_realm == form.signon_realm; | 64 return observed_form_.signon_realm == form.signon_realm; |
| 64 | 65 |
| 65 // HTML form case. | 66 // HTML form case. |
| 66 // At a minimum, username and password element must match. | 67 // At a minimum, username and password element must match. |
| 67 if (!((form.username_element == observed_form_.username_element) && | 68 if (!((form.username_element == observed_form_.username_element) && |
| 68 (form.password_element == observed_form_.password_element))) { | 69 (form.password_element == observed_form_.password_element))) { |
| 69 return false; | 70 return false; |
| 70 } | 71 } |
| 71 | 72 |
| 72 // The action URL must also match, but the form is allowed to have an empty | 73 // When action match is required, the action URL must match, but |
| 73 // action URL (See bug 1107719). | 74 // the form is allowed to have an empty action URL (See bug 1107719). |
| 74 if (form.action.is_valid() && (form.action != observed_form_.action)) | 75 // Otherwise ignore action URL, this is to allow saving password form with |
| 75 return false; | 76 // dynamically changed action URL (See bug 27246). |
| 77 if (form.action.is_valid() && (form.action != observed_form_.action)) { | |
| 78 if (action_match == kActionMatchRequired) | |
|
tim (not reviewing)
2012/09/05 21:40:59
nit - chromium style diverges from Google style he
guohui
2012/09/17 13:28:55
Done.
| |
| 79 return false; | |
| 80 } | |
| 76 | 81 |
| 77 // If this is a replay of the same form in the case a user entered an invalid | 82 // If this is a replay of the same form in the case a user entered an invalid |
| 78 // password, the origin of the new form may equal the action of the "first" | 83 // password, the origin of the new form may equal the action of the "first" |
| 79 // form. | 84 // form. |
| 80 if (!((form.origin == observed_form_.origin) || | 85 if (!((form.origin == observed_form_.origin) || |
| 81 (form.origin == observed_form_.action))) { | 86 (form.origin == observed_form_.action))) { |
| 82 if (form.origin.SchemeIsSecure() && | 87 if (form.origin.SchemeIsSecure() && |
| 83 !observed_form_.origin.SchemeIsSecure()) { | 88 !observed_form_.origin.SchemeIsSecure()) { |
| 84 // Compare origins, ignoring scheme. There is no easy way to do this | 89 // Compare origins, ignoring scheme. There is no easy way to do this |
| 85 // with GURL because clearing the scheme would result in an invalid url. | 90 // with GURL because clearing the scheme would result in an invalid url. |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 164 // Non-HTML password forms (primarily HTTP and FTP autentication) | 169 // Non-HTML password forms (primarily HTTP and FTP autentication) |
| 165 // do not contain username_element and password_element values. | 170 // do not contain username_element and password_element values. |
| 166 if (observed_form_.scheme != PasswordForm::SCHEME_HTML) | 171 if (observed_form_.scheme != PasswordForm::SCHEME_HTML) |
| 167 return true; | 172 return true; |
| 168 return !observed_form_.username_element.empty() && | 173 return !observed_form_.username_element.empty() && |
| 169 !observed_form_.password_element.empty(); | 174 !observed_form_.password_element.empty(); |
| 170 } | 175 } |
| 171 | 176 |
| 172 void PasswordFormManager::ProvisionallySave(const PasswordForm& credentials) { | 177 void PasswordFormManager::ProvisionallySave(const PasswordForm& credentials) { |
| 173 DCHECK_EQ(state_, POST_MATCHING_PHASE); | 178 DCHECK_EQ(state_, POST_MATCHING_PHASE); |
| 174 DCHECK(DoesManage(credentials)); | 179 DCHECK(DoesManage(credentials, kActionMatchNotRequired)); |
| 175 | 180 |
| 176 // Make sure the important fields stay the same as the initially observed or | 181 // Make sure the important fields stay the same as the initially observed or |
| 177 // autofilled ones, as they may have changed if the user experienced a login | 182 // autofilled ones, as they may have changed if the user experienced a login |
| 178 // failure. | 183 // failure. |
| 179 // Look for these credentials in the list containing auto-fill entries. | 184 // Look for these credentials in the list containing auto-fill entries. |
| 180 PasswordFormMap::const_iterator it = | 185 PasswordFormMap::const_iterator it = |
| 181 best_matches_.find(credentials.username_value); | 186 best_matches_.find(credentials.username_value); |
| 182 if (it != best_matches_.end()) { | 187 if (it != best_matches_.end()) { |
| 183 // The user signed in with a login we autofilled. | 188 // The user signed in with a login we autofilled. |
| 184 pending_credentials_ = *it->second; | 189 pending_credentials_ = *it->second; |
| 185 is_new_login_ = false; | 190 is_new_login_ = false; |
| 186 // If the user selected credentials we autofilled from a PasswordForm | |
| 187 // that contained no action URL (IE6/7 imported passwords, for example), | |
| 188 // bless it with the action URL from the observed form. See bug 1107719. | |
| 189 if (pending_credentials_.action.is_empty()) | |
| 190 pending_credentials_.action = observed_form_.action; | |
| 191 | 191 |
| 192 // Check to see if we're using a known username but a new password. | 192 // Check to see if we're using a known username but a new password. |
| 193 if (pending_credentials_.password_value != credentials.password_value) | 193 if (pending_credentials_.password_value != credentials.password_value) |
| 194 user_action_ = kUserActionOverride; | 194 user_action_ = kUserActionOverride; |
| 195 } else { | 195 } else { |
| 196 // User typed in a new, unknown username. | 196 // User typed in a new, unknown username. |
| 197 user_action_ = kUserActionOverride; | 197 user_action_ = kUserActionOverride; |
| 198 pending_credentials_ = observed_form_; | 198 pending_credentials_ = observed_form_; |
| 199 pending_credentials_.username_value = credentials.username_value; | 199 pending_credentials_.username_value = credentials.username_value; |
| 200 } | 200 } |
| 201 | 201 |
| 202 pending_credentials_.action = credentials.action; | |
| 203 // If the user selected credentials we autofilled from a PasswordForm | |
| 204 // that contained no action URL (IE6/7 imported passwords, for example), | |
| 205 // bless it with the action URL from the observed form. See bug 1107719. | |
| 206 if (pending_credentials_.action.is_empty()) | |
| 207 pending_credentials_.action = observed_form_.action; | |
|
tim (not reviewing)
2012/09/05 21:40:59
Could we add a test that verifies this gets update
guohui
2012/09/17 13:28:55
Updated TestNewLogin to verify the action gets pop
| |
| 208 | |
| 202 pending_credentials_.password_value = credentials.password_value; | 209 pending_credentials_.password_value = credentials.password_value; |
| 203 pending_credentials_.preferred = credentials.preferred; | 210 pending_credentials_.preferred = credentials.preferred; |
| 204 } | 211 } |
| 205 | 212 |
| 206 void PasswordFormManager::Save() { | 213 void PasswordFormManager::Save() { |
| 207 DCHECK_EQ(state_, POST_MATCHING_PHASE); | 214 DCHECK_EQ(state_, POST_MATCHING_PHASE); |
| 208 DCHECK(!profile_->IsOffTheRecord()); | 215 DCHECK(!profile_->IsOffTheRecord()); |
| 209 | 216 |
| 210 if (IsNewLogin()) | 217 if (IsNewLogin()) |
| 211 SaveAsNewLogin(true); | 218 SaveAsNewLogin(true); |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 505 | 512 |
| 506 void PasswordFormManager::SubmitFailed() { | 513 void PasswordFormManager::SubmitFailed() { |
| 507 submit_result_ = kSubmitResultFailed; | 514 submit_result_ = kSubmitResultFailed; |
| 508 } | 515 } |
| 509 | 516 |
| 510 void PasswordFormManager::SendNotBlacklistedToRenderer() { | 517 void PasswordFormManager::SendNotBlacklistedToRenderer() { |
| 511 content::RenderViewHost* host = web_contents_->GetRenderViewHost(); | 518 content::RenderViewHost* host = web_contents_->GetRenderViewHost(); |
| 512 host->Send(new AutofillMsg_FormNotBlacklisted(host->GetRoutingID(), | 519 host->Send(new AutofillMsg_FormNotBlacklisted(host->GetRoutingID(), |
| 513 observed_form_)); | 520 observed_form_)); |
| 514 } | 521 } |
| OLD | NEW |