Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / passwords / password_manager_presenter.cc
blobdd7759c490a2612603149131befdc98efbf3209c
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/passwords/password_manager_presenter.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/metrics/user_metrics_action.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/time/time.h"
13 #include "base/values.h"
14 #include "chrome/browser/password_manager/password_store_factory.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/signin/signin_manager_factory.h"
17 #include "chrome/browser/sync/profile_sync_service.h"
18 #include "chrome/browser/sync/profile_sync_service_factory.h"
19 #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
20 #include "chrome/browser/ui/passwords/password_ui_view.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "chrome/common/pref_names.h"
23 #include "chrome/common/url_constants.h"
24 #include "components/autofill/core/common/password_form.h"
25 #include "components/password_manager/core/browser/affiliation_utils.h"
26 #include "components/password_manager/core/common/password_manager_pref_names.h"
27 #include "components/password_manager/sync/browser/password_sync_util.h"
28 #include "content/public/browser/user_metrics.h"
29 #include "content/public/browser/web_contents.h"
31 #if defined(OS_WIN)
32 #include "chrome/browser/password_manager/password_manager_util_win.h"
33 #elif defined(OS_MACOSX)
34 #include "chrome/browser/password_manager/password_manager_util_mac.h"
35 #endif
37 using password_manager::PasswordStore;
39 PasswordManagerPresenter::PasswordManagerPresenter(
40 PasswordUIView* password_view)
41 : populater_(this),
42 exception_populater_(this),
43 require_reauthentication_(
44 !base::CommandLine::ForCurrentProcess()->HasSwitch(
45 switches::kDisablePasswordManagerReauthentication)),
46 password_view_(password_view) {
47 DCHECK(password_view_);
50 PasswordManagerPresenter::~PasswordManagerPresenter() {
51 PasswordStore* store = GetPasswordStore();
52 if (store)
53 store->RemoveObserver(this);
56 void PasswordManagerPresenter::Initialize() {
57 // Due to the way that handlers are (re)initialized under certain types of
58 // navigation, the presenter may already be initialized. (See bugs 88986
59 // and 86448). If this is the case, return immediately. This is a hack.
60 // TODO(mdm): remove this hack once it is no longer necessary.
61 if (!show_passwords_.GetPrefName().empty())
62 return;
64 show_passwords_.Init(
65 password_manager::prefs::kPasswordManagerAllowShowPasswords,
66 password_view_->GetProfile()->GetPrefs(),
67 base::Bind(&PasswordManagerPresenter::UpdatePasswordLists,
68 base::Unretained(this)));
69 // TODO(jhawkins) We should not cache web_ui()->GetProfile().See
70 // crosbug.com/6304.
71 PasswordStore* store = GetPasswordStore();
72 if (store)
73 store->AddObserver(this);
75 languages_ = password_view_->GetProfile()->GetPrefs()->
76 GetString(prefs::kAcceptLanguages);
79 void PasswordManagerPresenter::OnLoginsChanged(
80 const password_manager::PasswordStoreChangeList& changes) {
81 // Entire list is updated for convenience.
82 UpdatePasswordLists();
85 PasswordStore* PasswordManagerPresenter::GetPasswordStore() {
86 return PasswordStoreFactory::GetForProfile(password_view_->GetProfile(),
87 ServiceAccessType::EXPLICIT_ACCESS)
88 .get();
91 void PasswordManagerPresenter::UpdatePasswordLists() {
92 // Reset so that showing a password will require re-authentication.
93 last_authentication_time_ = base::TimeTicks();
95 // Reset the current lists.
96 password_list_.clear();
97 password_exception_list_.clear();
99 populater_.Populate();
100 exception_populater_.Populate();
103 void PasswordManagerPresenter::RemoveSavedPassword(size_t index) {
104 if (index >= password_list_.size()) {
105 // |index| out of bounds might come from a compromised renderer, don't let
106 // it crash the browser. http://crbug.com/362054
107 NOTREACHED();
108 return;
110 PasswordStore* store = GetPasswordStore();
111 if (!store)
112 return;
113 store->RemoveLogin(*password_list_[index]);
114 content::RecordAction(
115 base::UserMetricsAction("PasswordManager_RemoveSavedPassword"));
118 void PasswordManagerPresenter::RemovePasswordException(size_t index) {
119 if (index >= password_exception_list_.size()) {
120 // |index| out of bounds might come from a compromised renderer, don't let
121 // it crash the browser. http://crbug.com/362054
122 NOTREACHED();
123 return;
125 PasswordStore* store = GetPasswordStore();
126 if (!store)
127 return;
128 store->RemoveLogin(*password_exception_list_[index]);
129 content::RecordAction(
130 base::UserMetricsAction("PasswordManager_RemovePasswordException"));
133 void PasswordManagerPresenter::RequestShowPassword(size_t index) {
134 #if !defined(OS_ANDROID) // This is never called on Android.
135 if (index >= password_list_.size()) {
136 // |index| out of bounds might come from a compromised renderer, don't let
137 // it crash the browser. http://crbug.com/362054
138 NOTREACHED();
139 return;
141 if (require_reauthentication_ &&
142 (base::TimeTicks::Now() - last_authentication_time_) >
143 base::TimeDelta::FromSeconds(60)) {
144 bool authenticated = true;
145 #if defined(OS_WIN)
146 authenticated = password_manager_util_win::AuthenticateUser(
147 password_view_->GetNativeWindow());
148 #elif defined(OS_MACOSX)
149 authenticated = password_manager_util_mac::AuthenticateUser();
150 #endif
151 if (authenticated)
152 last_authentication_time_ = base::TimeTicks::Now();
153 else
154 return;
157 sync_driver::SyncService* sync_service = nullptr;
158 if (ProfileSyncServiceFactory::HasProfileSyncService(
159 password_view_->GetProfile())) {
160 sync_service =
161 ProfileSyncServiceFactory::GetForProfile(password_view_->GetProfile());
163 if (password_manager::sync_util::IsSyncAccountCredential(
164 *password_list_[index], sync_service,
165 SigninManagerFactory::GetForProfile(password_view_->GetProfile()))) {
166 content::RecordAction(
167 base::UserMetricsAction("PasswordManager_SyncCredentialShown"));
170 // Call back the front end to reveal the password.
171 std::string origin_url = password_manager::GetHumanReadableOrigin(
172 *password_list_[index], languages_);
173 password_view_->ShowPassword(
174 index,
175 origin_url,
176 base::UTF16ToUTF8(password_list_[index]->username_value),
177 password_list_[index]->password_value);
178 #endif
181 const autofill::PasswordForm* PasswordManagerPresenter::GetPassword(
182 size_t index) {
183 if (index >= password_list_.size()) {
184 // |index| out of bounds might come from a compromised renderer, don't let
185 // it crash the browser. http://crbug.com/362054
186 NOTREACHED();
187 return NULL;
189 return password_list_[index];
192 const autofill::PasswordForm* PasswordManagerPresenter::GetPasswordException(
193 size_t index) {
194 if (index >= password_exception_list_.size()) {
195 // |index| out of bounds might come from a compromised renderer, don't let
196 // it crash the browser. http://crbug.com/362054
197 NOTREACHED();
198 return NULL;
200 return password_exception_list_[index];
203 void PasswordManagerPresenter::SetPasswordList() {
204 // Due to the way that handlers are (re)initialized under certain types of
205 // navigation, the presenter may already be initialized. (See bugs 88986
206 // and 86448). If this is the case, return immediately. This is a hack.
207 // If this is the case, initialize on demand. This is a hack.
208 // TODO(mdm): remove this hack once it is no longer necessary.
209 if (show_passwords_.GetPrefName().empty())
210 Initialize();
212 bool show_passwords = *show_passwords_ && !require_reauthentication_;
213 password_view_->SetPasswordList(password_list_, show_passwords);
216 void PasswordManagerPresenter::SetPasswordExceptionList() {
217 password_view_->SetPasswordExceptionList(password_exception_list_);
220 PasswordManagerPresenter::ListPopulater::ListPopulater(
221 PasswordManagerPresenter* page) : page_(page) {
224 PasswordManagerPresenter::ListPopulater::~ListPopulater() {
227 PasswordManagerPresenter::PasswordListPopulater::PasswordListPopulater(
228 PasswordManagerPresenter* page) : ListPopulater(page) {
231 void PasswordManagerPresenter::PasswordListPopulater::Populate() {
232 PasswordStore* store = page_->GetPasswordStore();
233 if (store != NULL) {
234 cancelable_task_tracker()->TryCancelAll();
235 store->GetAutofillableLogins(this);
236 } else {
237 LOG(ERROR) << "No password store! Cannot display passwords.";
241 void PasswordManagerPresenter::PasswordListPopulater::OnGetPasswordStoreResults(
242 ScopedVector<autofill::PasswordForm> results) {
243 page_->password_list_.swap(results);
244 page_->SetPasswordList();
247 PasswordManagerPresenter::PasswordExceptionListPopulater::
248 PasswordExceptionListPopulater(PasswordManagerPresenter* page)
249 : ListPopulater(page) {
252 void PasswordManagerPresenter::PasswordExceptionListPopulater::Populate() {
253 PasswordStore* store = page_->GetPasswordStore();
254 if (store != NULL) {
255 cancelable_task_tracker()->TryCancelAll();
256 store->GetBlacklistLogins(this);
257 } else {
258 LOG(ERROR) << "No password store! Cannot display exceptions.";
262 void PasswordManagerPresenter::PasswordExceptionListPopulater::
263 OnGetPasswordStoreResults(ScopedVector<autofill::PasswordForm> results) {
264 page_->password_exception_list_.swap(results);
265 page_->SetPasswordExceptionList();