Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / passwords / password_manager_presenter.cc
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.
4
5 #include "chrome/browser/ui/passwords/password_manager_presenter.h"
6
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_manager_util.h"
15 #include "chrome/browser/password_manager/password_store_factory.h"
16 #include "chrome/browser/password_manager/sync_metrics.h"
17 #include "chrome/browser/ui/passwords/password_ui_view.h"
18 #include "chrome/common/chrome_switches.h"
19 #include "chrome/common/url_constants.h"
20 #include "components/autofill/core/common/password_form.h"
21 #include "components/password_manager/core/common/password_manager_pref_names.h"
22 #include "content/public/browser/user_metrics.h"
23 #include "content/public/browser/web_contents.h"
24
25 using password_manager::PasswordStore;
26
27 PasswordManagerPresenter::PasswordManagerPresenter(
28     PasswordUIView* password_view)
29     : populater_(this),
30       exception_populater_(this),
31       password_view_(password_view) {
32   DCHECK(password_view_);
33   require_reauthentication_ = !CommandLine::ForCurrentProcess()->HasSwitch(
34       switches::kDisablePasswordManagerReauthentication);
35 }
36
37 PasswordManagerPresenter::~PasswordManagerPresenter() {
38   PasswordStore* store = GetPasswordStore();
39   if (store)
40     store->RemoveObserver(this);
41 }
42
43 void PasswordManagerPresenter::Initialize() {
44   // Due to the way that handlers are (re)initialized under certain types of
45   // navigation, the presenter may already be initialized. (See bugs 88986
46   // and 86448). If this is the case, return immediately. This is a hack.
47   // TODO(mdm): remove this hack once it is no longer necessary.
48   if (!show_passwords_.GetPrefName().empty())
49     return;
50
51   show_passwords_.Init(
52       password_manager::prefs::kPasswordManagerAllowShowPasswords,
53       password_view_->GetProfile()->GetPrefs(),
54       base::Bind(&PasswordManagerPresenter::UpdatePasswordLists,
55                  base::Unretained(this)));
56   // TODO(jhawkins) We should not cache web_ui()->GetProfile().See
57   // crosbug.com/6304.
58   PasswordStore* store = GetPasswordStore();
59   if (store)
60     store->AddObserver(this);
61 }
62
63 void PasswordManagerPresenter::OnLoginsChanged(
64     const password_manager::PasswordStoreChangeList& changes) {
65   // Entire list is updated for convenience.
66   UpdatePasswordLists();
67 }
68
69 PasswordStore* PasswordManagerPresenter::GetPasswordStore() {
70   return PasswordStoreFactory::GetForProfile(password_view_->GetProfile(),
71                                              Profile::EXPLICIT_ACCESS).get();
72 }
73
74 void PasswordManagerPresenter::UpdatePasswordLists() {
75   // Reset so that showing a password will require re-authentication.
76   last_authentication_time_ = base::TimeTicks();
77
78   // Reset the current lists.
79   password_list_.clear();
80   password_exception_list_.clear();
81
82   populater_.Populate();
83   exception_populater_.Populate();
84 }
85
86 void PasswordManagerPresenter::RemoveSavedPassword(size_t index) {
87   if (index >= password_list_.size()) {
88     // |index| out of bounds might come from a compromised renderer, don't let
89     // it crash the browser. http://crbug.com/362054
90     NOTREACHED();
91     return;
92   }
93   PasswordStore* store = GetPasswordStore();
94   if (!store)
95     return;
96   store->RemoveLogin(*password_list_[index]);
97   content::RecordAction(
98       base::UserMetricsAction("PasswordManager_RemoveSavedPassword"));
99 }
100
101 void PasswordManagerPresenter::RemovePasswordException(size_t index) {
102   if (index >= password_exception_list_.size()) {
103     // |index| out of bounds might come from a compromised renderer, don't let
104     // it crash the browser. http://crbug.com/362054
105     NOTREACHED();
106     return;
107   }
108   PasswordStore* store = GetPasswordStore();
109   if (!store)
110     return;
111   store->RemoveLogin(*password_exception_list_[index]);
112   content::RecordAction(
113       base::UserMetricsAction("PasswordManager_RemovePasswordException"));
114 }
115
116 void PasswordManagerPresenter::RequestShowPassword(size_t index) {
117 #if !defined(OS_ANDROID) // This is never called on Android.
118   if (index >= password_list_.size()) {
119     // |index| out of bounds might come from a compromised renderer, don't let
120     // it crash the browser. http://crbug.com/362054
121     NOTREACHED();
122     return;
123   }
124   if (IsAuthenticationRequired()) {
125     if (password_manager_util::AuthenticateUser(
126         password_view_->GetNativeWindow()))
127       last_authentication_time_ = base::TimeTicks::Now();
128     else
129       return;
130   }
131
132   if (password_manager_sync_metrics::IsSyncAccountCredential(
133           password_view_->GetProfile(),
134           base::UTF16ToUTF8(password_list_[index]->username_value),
135           password_list_[index]->signon_realm)) {
136     content::RecordAction(
137         base::UserMetricsAction("PasswordManager_SyncCredentialShown"));
138   }
139
140   // Call back the front end to reveal the password.
141   password_view_->ShowPassword(index, password_list_[index]->password_value);
142 #endif
143 }
144
145 const autofill::PasswordForm* PasswordManagerPresenter::GetPassword(
146     size_t index) {
147   if (index >= password_list_.size()) {
148     // |index| out of bounds might come from a compromised renderer, don't let
149     // it crash the browser. http://crbug.com/362054
150     NOTREACHED();
151     return NULL;
152   }
153   return password_list_[index];
154 }
155
156 const autofill::PasswordForm* PasswordManagerPresenter::GetPasswordException(
157     size_t index) {
158   if (index >= password_exception_list_.size()) {
159     // |index| out of bounds might come from a compromised renderer, don't let
160     // it crash the browser. http://crbug.com/362054
161     NOTREACHED();
162     return NULL;
163   }
164   return password_exception_list_[index];
165 }
166
167 void PasswordManagerPresenter::SetPasswordList() {
168   // Due to the way that handlers are (re)initialized under certain types of
169   // navigation, the presenter may already be initialized. (See bugs 88986
170   // and 86448). If this is the case, return immediately. This is a hack.
171   // If this is the case, initialize on demand. This is a hack.
172   // TODO(mdm): remove this hack once it is no longer necessary.
173   if (show_passwords_.GetPrefName().empty())
174     Initialize();
175
176   bool show_passwords = *show_passwords_ && !require_reauthentication_;
177   password_view_->SetPasswordList(password_list_, show_passwords);
178 }
179
180 void PasswordManagerPresenter::SetPasswordExceptionList() {
181   password_view_->SetPasswordExceptionList(password_exception_list_);
182 }
183
184 bool PasswordManagerPresenter::IsAuthenticationRequired() {
185   base::TimeDelta delta = base::TimeDelta::FromSeconds(60);
186   return require_reauthentication_ &&
187       (base::TimeTicks::Now() - last_authentication_time_) > delta;
188 }
189
190 PasswordManagerPresenter::ListPopulater::ListPopulater(
191     PasswordManagerPresenter* page) : page_(page) {
192 }
193
194 PasswordManagerPresenter::ListPopulater::~ListPopulater() {
195 }
196
197 PasswordManagerPresenter::PasswordListPopulater::PasswordListPopulater(
198     PasswordManagerPresenter* page) : ListPopulater(page) {
199 }
200
201 void PasswordManagerPresenter::PasswordListPopulater::Populate() {
202   PasswordStore* store = page_->GetPasswordStore();
203   if (store != NULL) {
204     cancelable_task_tracker()->TryCancelAll();
205     store->GetAutofillableLogins(this);
206   } else {
207     LOG(ERROR) << "No password store! Cannot display passwords.";
208   }
209 }
210
211 void PasswordManagerPresenter::PasswordListPopulater::OnGetPasswordStoreResults(
212     const std::vector<autofill::PasswordForm*>& results) {
213   page_->password_list_.clear();
214   page_->password_list_.insert(page_->password_list_.end(),
215                                results.begin(), results.end());
216   page_->SetPasswordList();
217 }
218
219 PasswordManagerPresenter::PasswordExceptionListPopulater::
220     PasswordExceptionListPopulater(PasswordManagerPresenter* page)
221         : ListPopulater(page) {
222 }
223
224 void PasswordManagerPresenter::PasswordExceptionListPopulater::Populate() {
225   PasswordStore* store = page_->GetPasswordStore();
226   if (store != NULL) {
227     cancelable_task_tracker()->TryCancelAll();
228     store->GetBlacklistLogins(this);
229   } else {
230     LOG(ERROR) << "No password store! Cannot display exceptions.";
231   }
232 }
233
234 void PasswordManagerPresenter::PasswordExceptionListPopulater::
235     OnGetPasswordStoreResults(
236         const std::vector<autofill::PasswordForm*>& results) {
237   page_->password_exception_list_.clear();
238   page_->password_exception_list_.insert(page_->password_exception_list_.end(),
239                                          results.begin(), results.end());
240   page_->SetPasswordExceptionList();
241 }