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 24 PasswordManagerHandler::PasswordManagerHandler() 25 : ALLOW_THIS_IN_INITIALIZER_LIST(populater_(this)), 26 ALLOW_THIS_IN_INITIALIZER_LIST(exception_populater_(this)) { 27 } 28 29 PasswordManagerHandler::~PasswordManagerHandler() { 30 GetPasswordStore()->RemoveObserver(this); 31 } 32 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 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 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 95 void PasswordManagerHandler::OnLoginsChanged() { 96 UpdatePasswordLists(NULL); 97 } 98 99 PasswordStore* PasswordManagerHandler::GetPasswordStore() { 100 return web_ui_->GetProfile()->GetPasswordStore(Profile::EXPLICIT_ACCESS); 101 } 102 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 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 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 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 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 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 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 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 188 PasswordManagerHandler::ListPopulater::ListPopulater( 189 PasswordManagerHandler* page) 190 : page_(page), 191 pending_login_query_(0) { 192 } 193 194 PasswordManagerHandler::ListPopulater::~ListPopulater() { 195 } 196 197 PasswordManagerHandler::PasswordListPopulater::PasswordListPopulater( 198 PasswordManagerHandler* page) : ListPopulater(page) { 199 } 200 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:: 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:: 226 PasswordExceptionListPopulater(PasswordManagerHandler* page) 227 : ListPopulater(page) { 228 } 229 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:: 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