1 // Copyright (c) 2011 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/webui/options/password_manager_handler.h"
6
7 #include "base/callback.h"
8 #include "base/string_number_conversions.h"
9 #include "base/utf_string_conversions.h"
10 #include "base/values.h"
11 #include "chrome/browser/google/google_util.h"
12 #include "chrome/browser/prefs/pref_service.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/common/pref_names.h"
15 #include "chrome/common/url_constants.h"
16 #include "content/common/notification_details.h"
17 #include "content/common/notification_source.h"
18 #include "grit/chromium_strings.h"
19 #include "grit/generated_resources.h"
20 #include "net/base/net_util.h"
21 #include "ui/base/l10n/l10n_util.h"
22 #include "webkit/glue/password_form.h"
23
PasswordManagerHandler()24 PasswordManagerHandler::PasswordManagerHandler()
25 : ALLOW_THIS_IN_INITIALIZER_LIST(populater_(this)),
26 ALLOW_THIS_IN_INITIALIZER_LIST(exception_populater_(this)) {
27 }
28
~PasswordManagerHandler()29 PasswordManagerHandler::~PasswordManagerHandler() {
30 GetPasswordStore()->RemoveObserver(this);
31 }
32
GetLocalizedValues(DictionaryValue * localized_strings)33 void PasswordManagerHandler::GetLocalizedValues(
34 DictionaryValue* localized_strings) {
35 DCHECK(localized_strings);
36
37 static const OptionsStringResource resources[] = {
38 { "savedPasswordsTitle",
39 IDS_PASSWORDS_SHOW_PASSWORDS_TAB_TITLE },
40 { "passwordExceptionsTitle",
41 IDS_PASSWORDS_EXCEPTIONS_TAB_TITLE },
42 { "passwordShowButton",
43 IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON },
44 { "passwordHideButton",
45 IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON },
46 { "passwordsSiteColumn",
47 IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN },
48 { "passwordsUsernameColumn",
49 IDS_PASSWORDS_PAGE_VIEW_USERNAME_COLUMN },
50 { "passwordsRemoveButton",
51 IDS_PASSWORDS_PAGE_VIEW_REMOVE_BUTTON },
52 { "passwordsNoPasswordsDescription",
53 IDS_PASSWORDS_PAGE_VIEW_NO_PASSWORDS_DESCRIPTION },
54 { "passwordsNoExceptionsDescription",
55 IDS_PASSWORDS_PAGE_VIEW_NO_EXCEPTIONS_DESCRIPTION },
56 { "passwordsRemoveAllButton",
57 IDS_PASSWORDS_PAGE_VIEW_REMOVE_ALL_BUTTON },
58 { "passwordsRemoveAllTitle",
59 IDS_PASSWORDS_PAGE_VIEW_CAPTION_DELETE_ALL_PASSWORDS },
60 { "passwordsRemoveAllWarning",
61 IDS_PASSWORDS_PAGE_VIEW_TEXT_DELETE_ALL_PASSWORDS },
62 };
63
64 RegisterStrings(localized_strings, resources, arraysize(resources));
65 RegisterTitle(localized_strings, "passwordsPage",
66 IDS_PASSWORDS_EXCEPTIONS_WINDOW_TITLE);
67
68 localized_strings->SetString("passwordManagerLearnMoreURL",
69 google_util::AppendGoogleLocaleParam(
70 GURL(chrome::kPasswordManagerLearnMoreURL)).spec());
71 }
72
Initialize()73 void PasswordManagerHandler::Initialize() {
74 show_passwords_.Init(prefs::kPasswordManagerAllowShowPasswords,
75 web_ui_->GetProfile()->GetPrefs(), this);
76 // We should not cache web_ui_->GetProfile(). See crosbug.com/6304.
77 GetPasswordStore()->AddObserver(this);
78 }
79
RegisterMessages()80 void PasswordManagerHandler::RegisterMessages() {
81 DCHECK(web_ui_);
82
83 web_ui_->RegisterMessageCallback("updatePasswordLists",
84 NewCallback(this, &PasswordManagerHandler::UpdatePasswordLists));
85 web_ui_->RegisterMessageCallback("removeSavedPassword",
86 NewCallback(this, &PasswordManagerHandler::RemoveSavedPassword));
87 web_ui_->RegisterMessageCallback("removePasswordException",
88 NewCallback(this, &PasswordManagerHandler::RemovePasswordException));
89 web_ui_->RegisterMessageCallback("removeAllSavedPasswords",
90 NewCallback(this, &PasswordManagerHandler::RemoveAllSavedPasswords));
91 web_ui_->RegisterMessageCallback("removeAllPasswordExceptions", NewCallback(
92 this, &PasswordManagerHandler::RemoveAllPasswordExceptions));
93 }
94
OnLoginsChanged()95 void PasswordManagerHandler::OnLoginsChanged() {
96 UpdatePasswordLists(NULL);
97 }
98
GetPasswordStore()99 PasswordStore* PasswordManagerHandler::GetPasswordStore() {
100 return web_ui_->GetProfile()->GetPasswordStore(Profile::EXPLICIT_ACCESS);
101 }
102
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)103 void PasswordManagerHandler::Observe(NotificationType type,
104 const NotificationSource& source,
105 const NotificationDetails& details) {
106 if (type.value == NotificationType::PREF_CHANGED) {
107 std::string* pref_name = Details<std::string>(details).ptr();
108 if (*pref_name == prefs::kPasswordManagerAllowShowPasswords) {
109 UpdatePasswordLists(NULL);
110 }
111 }
112
113 OptionsPageUIHandler::Observe(type, source, details);
114 }
115
UpdatePasswordLists(const ListValue * args)116 void PasswordManagerHandler::UpdatePasswordLists(const ListValue* args) {
117 // Reset the current lists.
118 password_list_.reset();
119 password_exception_list_.reset();
120
121 languages_ =
122 web_ui_->GetProfile()->GetPrefs()->GetString(prefs::kAcceptLanguages);
123 populater_.Populate();
124 exception_populater_.Populate();
125 }
126
RemoveSavedPassword(const ListValue * args)127 void PasswordManagerHandler::RemoveSavedPassword(const ListValue* args) {
128 std::string string_value = UTF16ToUTF8(ExtractStringValue(args));
129 int index;
130 base::StringToInt(string_value, &index);
131 GetPasswordStore()->RemoveLogin(*password_list_[index]);
132 }
133
RemovePasswordException(const ListValue * args)134 void PasswordManagerHandler::RemovePasswordException(
135 const ListValue* args) {
136 std::string string_value = UTF16ToUTF8(ExtractStringValue(args));
137 int index;
138 base::StringToInt(string_value, &index);
139
140 GetPasswordStore()->RemoveLogin(*password_exception_list_[index]);
141 }
142
RemoveAllSavedPasswords(const ListValue * args)143 void PasswordManagerHandler::RemoveAllSavedPasswords(
144 const ListValue* args) {
145 // TODO(jhawkins): This will cause a list refresh for every password in the
146 // list. Add PasswordStore::RemoveAllLogins().
147 PasswordStore* store = GetPasswordStore();
148 for (size_t i = 0; i < password_list_.size(); ++i)
149 store->RemoveLogin(*password_list_[i]);
150 }
151
RemoveAllPasswordExceptions(const ListValue * args)152 void PasswordManagerHandler::RemoveAllPasswordExceptions(
153 const ListValue* args) {
154 PasswordStore* store = GetPasswordStore();
155 for (size_t i = 0; i < password_exception_list_.size(); ++i)
156 store->RemoveLogin(*password_exception_list_[i]);
157 }
158
SetPasswordList()159 void PasswordManagerHandler::SetPasswordList() {
160 ListValue entries;
161 bool show_passwords = *show_passwords_;
162 string16 empty;
163 for (size_t i = 0; i < password_list_.size(); ++i) {
164 ListValue* entry = new ListValue();
165 entry->Append(new StringValue(net::FormatUrl(password_list_[i]->origin,
166 languages_)));
167 entry->Append(new StringValue(password_list_[i]->username_value));
168 entry->Append(new StringValue(
169 show_passwords ? password_list_[i]->password_value : empty));
170 entries.Append(entry);
171 }
172
173 web_ui_->CallJavascriptFunction("PasswordManager.setSavedPasswordsList",
174 entries);
175 }
176
SetPasswordExceptionList()177 void PasswordManagerHandler::SetPasswordExceptionList() {
178 ListValue entries;
179 for (size_t i = 0; i < password_exception_list_.size(); ++i) {
180 entries.Append(new StringValue(
181 net::FormatUrl(password_exception_list_[i]->origin, languages_)));
182 }
183
184 web_ui_->CallJavascriptFunction("PasswordManager.setPasswordExceptionsList",
185 entries);
186 }
187
ListPopulater(PasswordManagerHandler * page)188 PasswordManagerHandler::ListPopulater::ListPopulater(
189 PasswordManagerHandler* page)
190 : page_(page),
191 pending_login_query_(0) {
192 }
193
~ListPopulater()194 PasswordManagerHandler::ListPopulater::~ListPopulater() {
195 }
196
PasswordListPopulater(PasswordManagerHandler * page)197 PasswordManagerHandler::PasswordListPopulater::PasswordListPopulater(
198 PasswordManagerHandler* page) : ListPopulater(page) {
199 }
200
Populate()201 void PasswordManagerHandler::PasswordListPopulater::Populate() {
202 PasswordStore* store = page_->GetPasswordStore();
203 if (store != NULL) {
204 if (pending_login_query_)
205 store->CancelRequest(pending_login_query_);
206
207 pending_login_query_ = store->GetAutofillableLogins(this);
208 } else {
209 LOG(ERROR) << "No password store! Cannot display passwords.";
210 }
211 }
212
213 void PasswordManagerHandler::PasswordListPopulater::
OnPasswordStoreRequestDone(CancelableRequestProvider::Handle handle,const std::vector<webkit_glue::PasswordForm * > & result)214 OnPasswordStoreRequestDone(
215 CancelableRequestProvider::Handle handle,
216 const std::vector<webkit_glue::PasswordForm*>& result) {
217 DCHECK_EQ(pending_login_query_, handle);
218 pending_login_query_ = 0;
219 page_->password_list_.reset();
220 page_->password_list_.insert(page_->password_list_.end(),
221 result.begin(), result.end());
222 page_->SetPasswordList();
223 }
224
225 PasswordManagerHandler::PasswordExceptionListPopulater::
PasswordExceptionListPopulater(PasswordManagerHandler * page)226 PasswordExceptionListPopulater(PasswordManagerHandler* page)
227 : ListPopulater(page) {
228 }
229
Populate()230 void PasswordManagerHandler::PasswordExceptionListPopulater::Populate() {
231 PasswordStore* store = page_->GetPasswordStore();
232 if (store != NULL) {
233 if (pending_login_query_)
234 store->CancelRequest(pending_login_query_);
235
236 pending_login_query_ = store->GetBlacklistLogins(this);
237 } else {
238 LOG(ERROR) << "No password store! Cannot display exceptions.";
239 }
240 }
241
242 void PasswordManagerHandler::PasswordExceptionListPopulater::
OnPasswordStoreRequestDone(CancelableRequestProvider::Handle handle,const std::vector<webkit_glue::PasswordForm * > & result)243 OnPasswordStoreRequestDone(
244 CancelableRequestProvider::Handle handle,
245 const std::vector<webkit_glue::PasswordForm*>& result) {
246 DCHECK_EQ(pending_login_query_, handle);
247 pending_login_query_ = 0;
248 page_->password_exception_list_.reset();
249 page_->password_exception_list_.insert(page_->password_exception_list_.end(),
250 result.begin(), result.end());
251 page_->SetPasswordExceptionList();
252 }
253