15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/password_manager/password_form_manager.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/password_manager/password_manager.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/password_manager/password_store.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/password_manager/password_store_factory.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 16d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "components/autofill/content/browser/autofill_driver_impl.h" 17d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)#include "components/autofill/content/common/autofill_messages.h" 18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "components/autofill/core/browser/form_structure.h" 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "components/autofill/core/browser/validation.h" 2058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "components/autofill/core/common/password_form.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using autofill::FormStructure; 2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using autofill::PasswordForm; 2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using autofill::PasswordFormMap; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PasswordFormManager::PasswordFormManager(Profile* profile, 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PasswordManager* password_manager, 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::WebContents* web_contents, 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PasswordForm& observed_form, 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ssl_valid) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : best_matches_deleter_(&best_matches_), 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observed_form_(observed_form), 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_new_login_(true), 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_generated_password_(false), 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) password_manager_(password_manager), 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) preferred_match_(NULL), 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_(PRE_MATCHING_PHASE), 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_(profile), 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_contents_(web_contents), 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manager_action_(kManagerActionNone), 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_action_(kUserActionNone), 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) submit_result_(kSubmitResultNotSubmitted) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(profile_); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (observed_form_.origin.is_valid()) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SplitString(observed_form_.origin.path(), '/', &form_path_tokens_); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observed_form_.ssl_valid = ssl_valid; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PasswordFormManager::~PasswordFormManager() { 534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("PasswordManager.ActionsTakenWithPsl", 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetActionsTaken(), 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMaxNumActionsTaken); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int PasswordFormManager::GetActionsTaken() { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return user_action_ + kUserActionMax * (manager_action_ + 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kManagerActionMax * submit_result_); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(timsteele): use a hash of some sort in the future? 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordFormManager::DoesManage(const PasswordForm& form, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ActionMatch action_match) const { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (form.scheme != PasswordForm::SCHEME_HTML) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return observed_form_.signon_realm == form.signon_realm; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // HTML form case. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // At a minimum, username and password element must match. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!((form.username_element == observed_form_.username_element) && 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (form.password_element == observed_form_.password_element))) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When action match is required, the action URL must match, but 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the form is allowed to have an empty action URL (See bug 1107719). 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Otherwise ignore action URL, this is to allow saving password form with 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dynamically changed action URL (See bug 27246). 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (form.action.is_valid() && (form.action != observed_form_.action)) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (action_match == ACTION_MATCH_REQUIRED) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this is a replay of the same form in the case a user entered an invalid 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // password, the origin of the new form may equal the action of the "first" 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // form. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!((form.origin == observed_form_.origin) || 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (form.origin == observed_form_.action))) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (form.origin.SchemeIsSecure() && 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !observed_form_.origin.SchemeIsSecure()) { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compare origins, ignoring scheme. There is no easy way to do this 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with GURL because clearing the scheme would result in an invalid url. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is for some sites (such as Hotmail) that begin on an http page and 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // head to https for the retry when password was invalid. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string::const_iterator after_scheme1 = form.origin.spec().begin() + 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) form.origin.scheme().length(); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string::const_iterator after_scheme2 = 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observed_form_.origin.spec().begin() + 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observed_form_.origin.scheme().length(); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::search(after_scheme1, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) form.origin.spec().end(), 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) after_scheme2, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observed_form_.origin.spec().end()) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) != form.origin.spec().end(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordFormManager::IsBlacklisted() { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(state_, POST_MATCHING_PHASE); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (preferred_match_ && preferred_match_->blacklisted_by_user) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordFormManager::PermanentlyBlacklist() { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(state_, POST_MATCHING_PHASE); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Configure the form about to be saved for blacklist status. 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_credentials_.preferred = true; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_credentials_.blacklisted_by_user = true; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_credentials_.username_value.clear(); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_credentials_.password_value.clear(); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retroactively forget existing matches for this form, so we NEVER prompt or 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // autofill it again. 1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int num_passwords_deleted = 0; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!best_matches_.empty()) { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PasswordFormMap::const_iterator iter; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PasswordStore* password_store = PasswordStoreFactory::GetForProfile( 1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) profile_, Profile::EXPLICIT_ACCESS).get(); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!password_store) { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (iter = best_matches_.begin(); iter != best_matches_.end(); ++iter) { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We want to remove existing matches for this form so that the exact 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // origin match with |blackisted_by_user == true| is the only result that 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // shows up in the future for this origin URL. However, we don't want to 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // delete logins that were actually saved on a different page (hence with 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // different origin URL) and just happened to match this form because of 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the scoring algorithm. See bug 1204493. 1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (iter->second->origin == observed_form_.origin) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) password_store->RemoveLogin(*iter->second); 1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ++num_passwords_deleted; 1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) UMA_HISTOGRAM_COUNTS("PasswordManager.NumPasswordsDeletedWhenBlacklisting", 1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) num_passwords_deleted); 1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the pending_credentials_ entry marked as blacklisted. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveAsNewLogin(false); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordFormManager::IsNewLogin() { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(state_, POST_MATCHING_PHASE); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return is_new_login_; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool PasswordFormManager::IsPendingCredentialsPublicSuffixMatch() { 166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return pending_credentials_.IsPublicSuffixMatch(); 167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordFormManager::SetHasGeneratedPassword() { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_generated_password_ = true; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordFormManager::HasGeneratedPassword() { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This check is permissive, as the user may have generated a password and 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // then edited it in the form itself. However, even in this case the user 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // has already given consent, so we treat these cases the same. 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return has_generated_password_; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordFormManager::HasValidPasswordForm() { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(state_, POST_MATCHING_PHASE); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Non-HTML password forms (primarily HTTP and FTP autentication) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // do not contain username_element and password_element values. 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (observed_form_.scheme != PasswordForm::SCHEME_HTML) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !observed_form_.username_element.empty() && 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !observed_form_.password_element.empty(); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void PasswordFormManager::ProvisionallySave( 191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const PasswordForm& credentials, 192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) OtherPossibleUsernamesAction action) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(state_, POST_MATCHING_PHASE); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(DoesManage(credentials, ACTION_MATCH_NOT_REQUIRED)); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure the important fields stay the same as the initially observed or 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // autofilled ones, as they may have changed if the user experienced a login 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // failure. 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Look for these credentials in the list containing auto-fill entries. 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PasswordFormMap::const_iterator it = 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_matches_.find(credentials.username_value); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != best_matches_.end()) { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The user signed in with a login we autofilled. 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_credentials_ = *it->second; 205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Public suffix matches should always be new logins, since we want to store 207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // them so they can automatically be filled in later. 208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch is_new_login_ = IsPendingCredentialsPublicSuffixMatch(); 2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (is_new_login_) 2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) user_action_ = kUserActionChoosePslMatch; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check to see if we're using a known username but a new password. 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_credentials_.password_value != credentials.password_value) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_action_ = kUserActionOverride; 215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else if (action == ALLOW_OTHER_POSSIBLE_USERNAMES && 216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) UpdatePendingCredentialsIfOtherPossibleUsername( 217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) credentials.username_value)) { 218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // |pending_credentials_| is now set. Note we don't update 219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // |pending_credentials_.username_value| to |credentials.username_value| 220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // yet because we need to keep the original username to modify the stored 221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // credential. 222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) selected_username_ = credentials.username_value; 223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) is_new_login_ = false; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // User typed in a new, unknown username. 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_action_ = kUserActionOverride; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_credentials_ = observed_form_; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_credentials_.username_value = credentials.username_value; 229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) pending_credentials_.other_possible_usernames = 230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) credentials.other_possible_usernames; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_credentials_.action = credentials.action; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the user selected credentials we autofilled from a PasswordForm 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that contained no action URL (IE6/7 imported passwords, for example), 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bless it with the action URL from the observed form. See bug 1107719. 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_credentials_.action.is_empty()) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_credentials_.action = observed_form_.action; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_credentials_.password_value = credentials.password_value; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_credentials_.preferred = credentials.preferred; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_generated_password_) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_credentials_.type = PasswordForm::TYPE_GENERATED; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordFormManager::Save() { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(state_, POST_MATCHING_PHASE); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!profile_->IsOffTheRecord()); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsNewLogin()) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveAsNewLogin(true); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateLogin(); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 257f60fc993c7b081abf77ce2ffc7fcca1142c8cb01Torne (Richard Coles)void PasswordFormManager::FetchMatchingLoginsFromPasswordStore( 258f60fc993c7b081abf77ce2ffc7fcca1142c8cb01Torne (Richard Coles) PasswordStore::AuthorizationPromptPolicy prompt_policy) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(state_, PRE_MATCHING_PHASE); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = MATCHING_PHASE; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PasswordStore* password_store = PasswordStoreFactory::GetForProfile( 2627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) profile_, Profile::EXPLICIT_ACCESS).get(); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!password_store) { 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 267f60fc993c7b081abf77ce2ffc7fcca1142c8cb01Torne (Richard Coles) password_store->GetLogins(observed_form_, prompt_policy, this); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordFormManager::HasCompletedMatching() { 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return state_ == POST_MATCHING_PHASE; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PasswordFormManager::OnRequestDone( 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<PasswordForm*>& logins_result) { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that the result gets deleted after this call completes, but we own 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the PasswordForm objects pointed to by the result vector, thus we keep 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // copies to a minimum here. 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int best_score = 0; 28168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // These credentials will be in the final result regardless of score. 28268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::vector<PasswordForm> credentials_to_keep; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < logins_result.size(); i++) { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IgnoreResult(*logins_result[i])) { 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete logins_result[i]; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Score and update best matches. 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int current_score = ScoreResult(*logins_result[i]); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This check is here so we can append empty path matches in the event 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // they don't score as high as others and aren't added to best_matches_. 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is most commonly imported firefox logins. We skip blacklisted 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ones because clearly we don't want to autofill them, and secondly 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because they only mean something when we have no other matches already 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // saved in Chrome - in which case they'll make it through the regular 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // scoring flow below by design. Note signon_realm == origin implies empty 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // path logins_result, since signon_realm is a prefix of origin for HTML 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // password forms. 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(timsteele): Bug 1269400. We probably should do something more 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // elegant for any shorter-path match instead of explicitly handling empty 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // path matches. 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((observed_form_.scheme == PasswordForm::SCHEME_HTML) && 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (observed_form_.signon_realm == logins_result[i]->origin.spec()) && 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (current_score > 0) && (!logins_result[i]->blacklisted_by_user)) { 30568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) credentials_to_keep.push_back(*logins_result[i]); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Always keep generated passwords as part of the result set. If a user 30968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // generates a password on a signup form, it should show on a login form 31068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // even if they have a previous login saved. 31168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // TODO(gcasto): We don't want to cut credentials that were saved on signup 31268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // forms even if they weren't generated, but currently it's hard to 31368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // distinguish between those forms and two different login forms on the 31468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // same domain. Filed http://crbug.com/294468 to look into this. 31568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (logins_result[i]->type == PasswordForm::TYPE_GENERATED) 31668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) credentials_to_keep.push_back(*logins_result[i]); 31768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_score < best_score) { 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete logins_result[i]; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_score == best_score) { 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_matches_[logins_result[i]->username_value] = logins_result[i]; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (current_score > best_score) { 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_score = current_score; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This new login has a better score than all those up to this point 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note 'this' owns all the PasswordForms in best_matches_. 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteValues(&best_matches_); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_matches_.clear(); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) preferred_match_ = NULL; // Don't delete, its owned by best_matches_. 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_matches_[logins_result[i]->username_value] = logins_result[i]; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) preferred_match_ = logins_result[i]->preferred ? logins_result[i] 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : preferred_match_; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We're done matching now. 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = POST_MATCHING_PHASE; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (best_score <= 0) { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 34368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (std::vector<PasswordForm>::const_iterator it = 34468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) credentials_to_keep.begin(); 34568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) it != credentials_to_keep.end(); ++it) { 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we don't already have a result with the same username, add the 34768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // lower-scored match (if it had equal score it would already be in 34868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // best_matches_). 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (best_matches_.find(it->username_value) == best_matches_.end()) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_matches_[it->username_value] = new PasswordForm(*it); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) UMA_HISTOGRAM_COUNTS("PasswordManager.NumPasswordsNotShown", 3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) logins_result.size() - best_matches_.size()); 3554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It is possible we have at least one match but have no preferred_match_, 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because a user may have chosen to 'Forget' the preferred match. So we 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // just pick the first one and whichever the user selects for submit will 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be saved as preferred. 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!best_matches_.empty()); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!preferred_match_) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) preferred_match_ = best_matches_.begin()->second; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check to see if the user told us to ignore this site in the past. 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (preferred_match_->blacklisted_by_user) { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manager_action_ = kManagerActionBlacklisted; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If not blacklisted, send a message to allow password generation. 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendNotBlacklistedToRenderer(); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Proceed to autofill. 374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Note that we provide the choices but don't actually prefill a value if: 375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // (1) we are in Incognito mode, (2) the ACTION paths don't match, 376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // or (3) if it matched using public suffix domain matching. 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool wait_for_username = 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_->IsOffTheRecord() || 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observed_form_.action.GetWithEmptyPath() != 380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch preferred_match_->action.GetWithEmptyPath() || 381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch preferred_match_->IsPublicSuffixMatch(); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (wait_for_username) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manager_action_ = kManagerActionNone; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manager_action_ = kManagerActionAutofilled; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) password_manager_->Autofill(observed_form_, best_matches_, 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *preferred_match_, wait_for_username); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordFormManager::OnPasswordStoreRequestDone( 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CancelableRequestProvider::Handle handle, 39258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::vector<autofill::PasswordForm*>& result) { 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(kaiwang): Remove this function. 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PasswordFormManager::OnGetPasswordStoreResults( 39858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::vector<autofill::PasswordForm*>& results) { 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(state_, MATCHING_PHASE); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (results.empty()) { 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = POST_MATCHING_PHASE; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No result means that we visit this site the first time so we don't need 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to check whether this site is blacklisted or not. Just send a message 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to allow password generation. 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendNotBlacklistedToRenderer(); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnRequestDone(results); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordFormManager::IgnoreResult(const PasswordForm& form) const { 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ignore change password forms until we have some change password 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // functionality 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (observed_form_.old_password_element.length() != 0) { 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't match an invalid SSL form with one saved under secure 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // circumstances. 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (form.ssl_valid && !observed_form_.ssl_valid) { 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordFormManager::SaveAsNewLogin(bool reset_preferred_login) { 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(state_, POST_MATCHING_PHASE); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsNewLogin()); 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The new_form is being used to sign in, so it is preferred. 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(pending_credentials_.preferred); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // new_form contains the same basic data as observed_form_ (because its the 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // same form), but with the newly added credentials. 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!profile_->IsOffTheRecord()); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PasswordStore* password_store = PasswordStoreFactory::GetForProfile( 4377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) profile_, Profile::IMPLICIT_ACCESS).get(); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!password_store) { 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_credentials_.date_created = Time::Now(); 444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SanitizePossibleUsernames(&pending_credentials_); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) password_store->AddLogin(pending_credentials_); 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reset_preferred_login) { 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdatePreferredLoginState(password_store); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PasswordFormManager::SanitizePossibleUsernames(PasswordForm* form) { 453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Remove any possible usernames that could be credit cards or SSN for privacy 454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // reasons. Also remove duplicates, both in other_possible_usernames and 455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // between other_possible_usernames and username_value. 456d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) std::set<base::string16> set; 457d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) for (std::vector<base::string16>::iterator it = 458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) form->other_possible_usernames.begin(); 459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it != form->other_possible_usernames.end(); ++it) { 460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!autofill::IsValidCreditCardNumber(*it) && !autofill::IsSSN(*it)) 461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) set.insert(*it); 462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) set.erase(form->username_value); 464d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) std::vector<base::string16> temp(set.begin(), set.end()); 465868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) form->other_possible_usernames.swap(temp); 466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordFormManager::UpdatePreferredLoginState( 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PasswordStore* password_store) { 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(password_store); 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PasswordFormMap::iterator iter; 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (iter = best_matches_.begin(); iter != best_matches_.end(); iter++) { 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter->second->username_value != pending_credentials_.username_value && 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter->second->preferred) { 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This wasn't the selected login but it used to be preferred. 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter->second->preferred = false; 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (user_action_ == kUserActionNone) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_action_ = kUserActionChoose; 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) password_store->UpdateLogin(*iter->second); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordFormManager::UpdateLogin() { 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(state_, POST_MATCHING_PHASE); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(preferred_match_); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we're doing an Update, we either autofilled correctly and need to 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // update the stats, or the user typed in a new password for autofilled 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // username, or the user selected one of the non-preferred matches, 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thus requiring a swap of preferred bits. 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!IsNewLogin() && pending_credentials_.preferred); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!profile_->IsOffTheRecord()); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PasswordStore* password_store = PasswordStoreFactory::GetForProfile( 4957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) profile_, Profile::IMPLICIT_ACCESS).get(); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!password_store) { 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 50190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Update metadata. 50290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ++pending_credentials_.times_used; 50390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 504d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Check to see if this form is a candidate for password generation. 505d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) CheckForAccountCreationForm(pending_credentials_, observed_form_); 506d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdatePreferredLoginState(password_store); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Remove alternate usernames. At this point we assume that we have found 510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // the right username. 511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) pending_credentials_.other_possible_usernames.clear(); 512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the new preferred login. 514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!selected_username_.empty()) { 515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // An other possible username is selected. We set this selected username 516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // as the real username. The PasswordStore API isn't designed to update 517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // username, so we delete the old credentials and add a new one instead. 518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) password_store->RemoveLogin(pending_credentials_); 519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) pending_credentials_.username_value = selected_username_; 520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) password_store->AddLogin(pending_credentials_); 521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else if ((observed_form_.scheme == PasswordForm::SCHEME_HTML) && 522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) (observed_form_.origin.spec().length() > 523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) observed_form_.signon_realm.length()) && 524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) (observed_form_.signon_realm == 525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) pending_credentials_.origin.spec())) { 526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Note origin.spec().length > signon_realm.length implies the origin has a 527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // path, since signon_realm is a prefix of origin for HTML password forms. 528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The user logged in successfully with one of our autofilled logins on a 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // page with non-empty path, but the autofilled entry was initially saved/ 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // imported with an empty path. Rather than just mark this entry preferred, 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we create a more specific copy for this exact page and leave the "master" 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unchanged. This is to prevent the case where that master login is used 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on several sites (e.g site.com/a and site.com/b) but the user actually 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // has a different preference on each site. For example, on /a, he wants the 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // general empty-path login so it is flagged as preferred, but on /b he logs 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in with a different saved entry - we don't want to remove the preferred 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // status of the former because upon return to /a it won't be the default- 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fill match. 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(timsteele): Bug 1188626 - expire the master copies. 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PasswordForm copy(pending_credentials_); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copy.origin = observed_form_.origin; 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copy.action = observed_form_.action; 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) password_store->AddLogin(copy); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) password_store->UpdateLogin(pending_credentials_); 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool PasswordFormManager::UpdatePendingCredentialsIfOtherPossibleUsername( 551a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& username) { 552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (PasswordFormMap::const_iterator it = best_matches_.begin(); 553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it != best_matches_.end(); ++it) { 554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (size_t i = 0; i < it->second->other_possible_usernames.size(); ++i) { 555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (it->second->other_possible_usernames[i] == username) { 556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) pending_credentials_ = *it->second; 557868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return true; 558868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 564d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void PasswordFormManager::CheckForAccountCreationForm( 565d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const PasswordForm& pending, const PasswordForm& observed) { 566d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // We check to see if the saved form_data is the same as the observed 567d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // form_data, which should never be true for passwords saved on account 568d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // creation forms. This check is only made the first time a password is used 569d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // to cut down on false positives. Specifically a site may have multiple login 570d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // forms with different markup, which might look similar to a signup form. 571d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (pending.times_used == 1) { 572d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FormStructure pending_structure(pending.form_data); 573d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FormStructure observed_structure(observed.form_data); 5744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Ignore |pending_structure| if its FormData has no fields. This is to 5754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // weed out those credentials that were saved before FormData was added 5764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // to PasswordForm. Even without this check, these FormStructure's won't 5774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // be uploaded, but it makes it hard to see if we are encountering 5784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // unexpected errors. 5794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!pending.form_data.fields.empty() && 5804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pending_structure.FormSignature() != 581d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) observed_structure.FormSignature()) { 582d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) autofill::AutofillDriverImpl* driver = 583d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) autofill::AutofillDriverImpl::FromWebContents(web_contents_); 584d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (driver && driver->autofill_manager()) { 585d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Note that this doesn't guarantee that the upload succeeded, only that 586d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // |pending.form_data| is considered uploadable. 587d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bool success = driver->autofill_manager()->UploadPasswordGenerationForm( 588d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) pending.form_data); 589d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("PasswordGeneration.UploadStarted", success); 590d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 591d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 592d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 593d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 594d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int PasswordFormManager::ScoreResult(const PasswordForm& candidate) const { 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(state_, MATCHING_PHASE); 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For scoring of candidate login data: 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The most important element that should match is the origin, followed by 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the action, the password name, the submit button name, and finally the 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // username input field name. 601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Exact origin match gives an addition of 64 (1 << 6) + # of matching url 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dirs. 603eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Partial match gives an addition of 32 (1 << 5) + # matching url dirs 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // That way, a partial match cannot trump an exact match even if 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the partial one matches all other attributes (action, elements) (and 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // regardless of the matching depth in the URL path). 607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // If public suffix origin match was not used, it gives an addition of 608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // 16 (1 << 4). 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int score = 0; 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (candidate.origin == observed_form_.origin) { 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This check is here for the most common case which 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is we have a single match in the db for the given host, 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so we don't generally need to walk the entire URL path (the else 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // clause). 615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch score += (1 << 6) + static_cast<int>(form_path_tokens_.size()); 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Walk the origin URL paths one directory at a time to see how 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // deep the two match. 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> candidate_path_tokens; 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SplitString(candidate.origin.path(), '/', &candidate_path_tokens); 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t depth = 0; 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t max_dirs = std::min(form_path_tokens_.size(), 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) candidate_path_tokens.size()); 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((depth < max_dirs) && (form_path_tokens_[depth] == 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) candidate_path_tokens[depth])) { 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) depth++; 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) score++; 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // do we have a partial match? 630eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch score += (depth > 0) ? 1 << 5 : 0; 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (observed_form_.scheme == PasswordForm::SCHEME_HTML) { 633eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!candidate.IsPublicSuffixMatch()) 634eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch score += 1 << 4; 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (candidate.action == observed_form_.action) 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) score += 1 << 3; 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (candidate.password_element == observed_form_.password_element) 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) score += 1 << 2; 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (candidate.submit_element == observed_form_.submit_element) 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) score += 1 << 1; 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (candidate.username_element == observed_form_.username_element) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) score += 1 << 0; 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return score; 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordFormManager::SubmitPassed() { 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) submit_result_ = kSubmitResultPassed; 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordFormManager::SubmitFailed() { 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) submit_result_ = kSubmitResultFailed; 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordFormManager::SendNotBlacklistedToRenderer() { 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderViewHost* host = web_contents_->GetRenderViewHost(); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host->Send(new AutofillMsg_FormNotBlacklisted(host->GetRoutingID(), 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observed_form_)); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 661