password_manager_handler.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
1// Copyright (c) 2012 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/bind.h" 8#include "base/prefs/pref_service.h" 9#include "base/strings/string_number_conversions.h" 10#include "base/strings/utf_string_conversions.h" 11#include "base/values.h" 12#include "chrome/browser/chrome_notification_types.h" 13#include "chrome/browser/password_manager/password_store_factory.h" 14#include "chrome/browser/profiles/profile.h" 15#include "chrome/common/pref_names.h" 16#include "chrome/common/url_constants.h" 17#include "content/public/browser/notification_details.h" 18#include "content/public/browser/notification_source.h" 19#include "content/public/browser/web_ui.h" 20#include "content/public/common/password_form.h" 21#include "grit/chromium_strings.h" 22#include "grit/generated_resources.h" 23#include "net/base/net_util.h" 24#include "ui/base/l10n/l10n_util.h" 25 26namespace options { 27 28PasswordManagerHandler::PasswordManagerHandler() 29 : populater_(this), 30 exception_populater_(this) { 31} 32 33PasswordManagerHandler::~PasswordManagerHandler() { 34 PasswordStore* store = GetPasswordStore(); 35 if (store) 36 store->RemoveObserver(this); 37} 38 39void PasswordManagerHandler::GetLocalizedValues( 40 DictionaryValue* localized_strings) { 41 DCHECK(localized_strings); 42 43 static const OptionsStringResource resources[] = { 44 { "savedPasswordsTitle", 45 IDS_PASSWORDS_SHOW_PASSWORDS_TAB_TITLE }, 46 { "passwordExceptionsTitle", 47 IDS_PASSWORDS_EXCEPTIONS_TAB_TITLE }, 48 { "passwordSearchPlaceholder", 49 IDS_PASSWORDS_PAGE_SEARCH_PASSWORDS }, 50 { "passwordShowButton", 51 IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON }, 52 { "passwordHideButton", 53 IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON }, 54 { "passwordsNoPasswordsDescription", 55 IDS_PASSWORDS_PAGE_VIEW_NO_PASSWORDS_DESCRIPTION }, 56 { "passwordsNoExceptionsDescription", 57 IDS_PASSWORDS_PAGE_VIEW_NO_EXCEPTIONS_DESCRIPTION }, 58 }; 59 60 RegisterStrings(localized_strings, resources, arraysize(resources)); 61 RegisterTitle(localized_strings, "passwordsPage", 62 IDS_PASSWORDS_EXCEPTIONS_WINDOW_TITLE); 63 64 localized_strings->SetString("passwordManagerLearnMoreURL", 65 chrome::kPasswordManagerLearnMoreURL); 66} 67 68void PasswordManagerHandler::InitializeHandler() { 69 // Due to the way that handlers are (re)initialized under certain types of 70 // navigation, we may already be initialized. (See bugs 88986 and 86448.) 71 // If this is the case, return immediately. This is a hack. 72 // TODO(mdm): remove this hack once it is no longer necessary. 73 if (!show_passwords_.GetPrefName().empty()) 74 return; 75 76 show_passwords_.Init(prefs::kPasswordManagerAllowShowPasswords, 77 Profile::FromWebUI(web_ui())->GetPrefs(), 78 base::Bind(&PasswordManagerHandler::UpdatePasswordLists, 79 base::Unretained(this), 80 static_cast<base::ListValue*>(NULL))); 81 // We should not cache web_ui()->GetProfile(). See crosbug.com/6304. 82 PasswordStore* store = GetPasswordStore(); 83 if (store) 84 store->AddObserver(this); 85} 86 87void PasswordManagerHandler::RegisterMessages() { 88 web_ui()->RegisterMessageCallback("updatePasswordLists", 89 base::Bind(&PasswordManagerHandler::UpdatePasswordLists, 90 base::Unretained(this))); 91 web_ui()->RegisterMessageCallback("removeSavedPassword", 92 base::Bind(&PasswordManagerHandler::RemoveSavedPassword, 93 base::Unretained(this))); 94 web_ui()->RegisterMessageCallback("removePasswordException", 95 base::Bind(&PasswordManagerHandler::RemovePasswordException, 96 base::Unretained(this))); 97 web_ui()->RegisterMessageCallback("removeAllSavedPasswords", 98 base::Bind(&PasswordManagerHandler::RemoveAllSavedPasswords, 99 base::Unretained(this))); 100 web_ui()->RegisterMessageCallback("removeAllPasswordExceptions", 101 base::Bind(&PasswordManagerHandler::RemoveAllPasswordExceptions, 102 base::Unretained(this))); 103} 104 105void PasswordManagerHandler::OnLoginsChanged() { 106 UpdatePasswordLists(NULL); 107} 108 109PasswordStore* PasswordManagerHandler::GetPasswordStore() { 110 return PasswordStoreFactory::GetForProfile(Profile::FromWebUI(web_ui()), 111 Profile::EXPLICIT_ACCESS).get(); 112} 113 114void PasswordManagerHandler::UpdatePasswordLists(const ListValue* args) { 115 // Reset the current lists. 116 password_list_.clear(); 117 password_exception_list_.clear(); 118 119 languages_ = Profile::FromWebUI(web_ui())->GetPrefs()-> 120 GetString(prefs::kAcceptLanguages); 121 populater_.Populate(); 122 exception_populater_.Populate(); 123} 124 125void PasswordManagerHandler::RemoveSavedPassword(const ListValue* args) { 126 PasswordStore* store = GetPasswordStore(); 127 if (!store) 128 return; 129 std::string string_value = UTF16ToUTF8(ExtractStringValue(args)); 130 int index; 131 if (base::StringToInt(string_value, &index) && index >= 0 && 132 static_cast<size_t>(index) < password_list_.size()) 133 store->RemoveLogin(*password_list_[index]); 134} 135 136void PasswordManagerHandler::RemovePasswordException( 137 const ListValue* args) { 138 PasswordStore* store = GetPasswordStore(); 139 if (!store) 140 return; 141 std::string string_value = UTF16ToUTF8(ExtractStringValue(args)); 142 int index; 143 if (base::StringToInt(string_value, &index) && index >= 0 && 144 static_cast<size_t>(index) < password_exception_list_.size()) 145 store->RemoveLogin(*password_exception_list_[index]); 146} 147 148void PasswordManagerHandler::RemoveAllSavedPasswords( 149 const ListValue* args) { 150 // TODO(jhawkins): This will cause a list refresh for every password in the 151 // list. Add PasswordStore::RemoveAllLogins(). 152 PasswordStore* store = GetPasswordStore(); 153 if (!store) 154 return; 155 for (size_t i = 0; i < password_list_.size(); ++i) 156 store->RemoveLogin(*password_list_[i]); 157} 158 159void PasswordManagerHandler::RemoveAllPasswordExceptions( 160 const ListValue* args) { 161 PasswordStore* store = GetPasswordStore(); 162 if (!store) 163 return; 164 for (size_t i = 0; i < password_exception_list_.size(); ++i) 165 store->RemoveLogin(*password_exception_list_[i]); 166} 167 168void PasswordManagerHandler::SetPasswordList() { 169 // Due to the way that handlers are (re)initialized under certain types of 170 // navigation, we may not be initialized yet. (See bugs 88986 and 86448.) 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 InitializeHandler(); 175 176 ListValue entries; 177 bool show_passwords = *show_passwords_; 178 string16 empty; 179 for (size_t i = 0; i < password_list_.size(); ++i) { 180 ListValue* entry = new ListValue(); 181 entry->Append(new StringValue(net::FormatUrl(password_list_[i]->origin, 182 languages_))); 183 entry->Append(new StringValue(password_list_[i]->username_value)); 184 entry->Append(new StringValue( 185 show_passwords ? password_list_[i]->password_value : empty)); 186 entries.Append(entry); 187 } 188 189 web_ui()->CallJavascriptFunction("PasswordManager.setSavedPasswordsList", 190 entries); 191} 192 193void PasswordManagerHandler::SetPasswordExceptionList() { 194 ListValue entries; 195 for (size_t i = 0; i < password_exception_list_.size(); ++i) { 196 entries.Append(new StringValue( 197 net::FormatUrl(password_exception_list_[i]->origin, languages_))); 198 } 199 200 web_ui()->CallJavascriptFunction("PasswordManager.setPasswordExceptionsList", 201 entries); 202} 203 204PasswordManagerHandler::ListPopulater::ListPopulater( 205 PasswordManagerHandler* page) 206 : page_(page), 207 pending_login_query_(0) { 208} 209 210PasswordManagerHandler::ListPopulater::~ListPopulater() { 211} 212 213PasswordManagerHandler::PasswordListPopulater::PasswordListPopulater( 214 PasswordManagerHandler* page) : ListPopulater(page) { 215} 216 217void PasswordManagerHandler::PasswordListPopulater::Populate() { 218 PasswordStore* store = page_->GetPasswordStore(); 219 if (store != NULL) { 220 if (pending_login_query_) 221 store->CancelRequest(pending_login_query_); 222 223 pending_login_query_ = store->GetAutofillableLogins(this); 224 } else { 225 LOG(ERROR) << "No password store! Cannot display passwords."; 226 } 227} 228 229void PasswordManagerHandler::PasswordListPopulater:: 230 OnPasswordStoreRequestDone( 231 CancelableRequestProvider::Handle handle, 232 const std::vector<content::PasswordForm*>& result) { 233 DCHECK_EQ(pending_login_query_, handle); 234 pending_login_query_ = 0; 235 page_->password_list_.clear(); 236 page_->password_list_.insert(page_->password_list_.end(), 237 result.begin(), result.end()); 238 page_->SetPasswordList(); 239} 240 241void PasswordManagerHandler::PasswordListPopulater::OnGetPasswordStoreResults( 242 const std::vector<content::PasswordForm*>& results) { 243 // TODO(kaiwang): Implement when I refactor 244 // PasswordStore::GetAutofillableLogins and PasswordStore::GetBlacklistLogins. 245 NOTIMPLEMENTED(); 246} 247 248PasswordManagerHandler::PasswordExceptionListPopulater:: 249 PasswordExceptionListPopulater(PasswordManagerHandler* page) 250 : ListPopulater(page) { 251} 252 253void PasswordManagerHandler::PasswordExceptionListPopulater::Populate() { 254 PasswordStore* store = page_->GetPasswordStore(); 255 if (store != NULL) { 256 if (pending_login_query_) 257 store->CancelRequest(pending_login_query_); 258 259 pending_login_query_ = store->GetBlacklistLogins(this); 260 } else { 261 LOG(ERROR) << "No password store! Cannot display exceptions."; 262 } 263} 264 265void PasswordManagerHandler::PasswordExceptionListPopulater:: 266 OnPasswordStoreRequestDone( 267 CancelableRequestProvider::Handle handle, 268 const std::vector<content::PasswordForm*>& result) { 269 DCHECK_EQ(pending_login_query_, handle); 270 pending_login_query_ = 0; 271 page_->password_exception_list_.clear(); 272 page_->password_exception_list_.insert(page_->password_exception_list_.end(), 273 result.begin(), result.end()); 274 page_->SetPasswordExceptionList(); 275} 276 277void PasswordManagerHandler::PasswordExceptionListPopulater:: 278 OnGetPasswordStoreResults( 279 const std::vector<content::PasswordForm*>& results) { 280 // TODO(kaiwang): Implement when I refactor 281 // PasswordStore::GetAutofillableLogins and PasswordStore::GetBlacklistLogins. 282 NOTIMPLEMENTED(); 283} 284 285} // namespace options 286