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"
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"
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"
37 using password_manager::PasswordStore
;
39 PasswordManagerPresenter::PasswordManagerPresenter(
40 PasswordUIView
* password_view
)
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();
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())
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
71 PasswordStore
* store
= GetPasswordStore();
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
)
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
110 PasswordStore
* store
= GetPasswordStore();
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
125 PasswordStore
* store
= GetPasswordStore();
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
141 if (require_reauthentication_
&&
142 (base::TimeTicks::Now() - last_authentication_time_
) >
143 base::TimeDelta::FromSeconds(60)) {
144 bool authenticated
= true;
146 authenticated
= password_manager_util_win::AuthenticateUser(
147 password_view_
->GetNativeWindow());
148 #elif defined(OS_MACOSX)
149 authenticated
= password_manager_util_mac::AuthenticateUser();
152 last_authentication_time_
= base::TimeTicks::Now();
157 sync_driver::SyncService
* sync_service
= nullptr;
158 if (ProfileSyncServiceFactory::HasProfileSyncService(
159 password_view_
->GetProfile())) {
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(
176 base::UTF16ToUTF8(password_list_
[index
]->username_value
),
177 password_list_
[index
]->password_value
);
181 const autofill::PasswordForm
* PasswordManagerPresenter::GetPassword(
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
189 return password_list_
[index
];
192 const autofill::PasswordForm
* PasswordManagerPresenter::GetPasswordException(
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
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())
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();
234 cancelable_task_tracker()->TryCancelAll();
235 store
->GetAutofillableLogins(this);
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();
255 cancelable_task_tracker()->TryCancelAll();
256 store
->GetBlacklistLogins(this);
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();