blob: 46ea2370bdd6f7af278289824721bbd585503930 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/webui/options/password_manager_handler.h"
#include "base/bind.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/password_manager/password_store_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "components/autofill/core/common/password_form.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/web_ui.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "net/base/net_util.h"
#include "ui/base/l10n/l10n_util.h"
namespace options {
PasswordManagerHandler::PasswordManagerHandler()
: populater_(this),
exception_populater_(this) {
}
PasswordManagerHandler::~PasswordManagerHandler() {
PasswordStore* store = GetPasswordStore();
if (store)
store->RemoveObserver(this);
}
void PasswordManagerHandler::GetLocalizedValues(
DictionaryValue* localized_strings) {
DCHECK(localized_strings);
static const OptionsStringResource resources[] = {
{ "savedPasswordsTitle",
IDS_PASSWORDS_SHOW_PASSWORDS_TAB_TITLE },
{ "passwordExceptionsTitle",
IDS_PASSWORDS_EXCEPTIONS_TAB_TITLE },
{ "passwordSearchPlaceholder",
IDS_PASSWORDS_PAGE_SEARCH_PASSWORDS },
{ "passwordShowButton",
IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON },
{ "passwordHideButton",
IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON },
{ "passwordsNoPasswordsDescription",
IDS_PASSWORDS_PAGE_VIEW_NO_PASSWORDS_DESCRIPTION },
{ "passwordsNoExceptionsDescription",
IDS_PASSWORDS_PAGE_VIEW_NO_EXCEPTIONS_DESCRIPTION },
};
RegisterStrings(localized_strings, resources, arraysize(resources));
RegisterTitle(localized_strings, "passwordsPage",
IDS_PASSWORDS_EXCEPTIONS_WINDOW_TITLE);
localized_strings->SetString("passwordManagerLearnMoreURL",
chrome::kPasswordManagerLearnMoreURL);
}
void PasswordManagerHandler::InitializeHandler() {
// Due to the way that handlers are (re)initialized under certain types of
// navigation, we may already be initialized. (See bugs 88986 and 86448.)
// If this is the case, return immediately. This is a hack.
// TODO(mdm): remove this hack once it is no longer necessary.
if (!show_passwords_.GetPrefName().empty())
return;
show_passwords_.Init(prefs::kPasswordManagerAllowShowPasswords,
Profile::FromWebUI(web_ui())->GetPrefs(),
base::Bind(&PasswordManagerHandler::UpdatePasswordLists,
base::Unretained(this),
static_cast<base::ListValue*>(NULL)));
// We should not cache web_ui()->GetProfile(). See crosbug.com/6304.
PasswordStore* store = GetPasswordStore();
if (store)
store->AddObserver(this);
}
void PasswordManagerHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback("updatePasswordLists",
base::Bind(&PasswordManagerHandler::UpdatePasswordLists,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("removeSavedPassword",
base::Bind(&PasswordManagerHandler::RemoveSavedPassword,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("removePasswordException",
base::Bind(&PasswordManagerHandler::RemovePasswordException,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("removeAllSavedPasswords",
base::Bind(&PasswordManagerHandler::RemoveAllSavedPasswords,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("removeAllPasswordExceptions",
base::Bind(&PasswordManagerHandler::RemoveAllPasswordExceptions,
base::Unretained(this)));
}
void PasswordManagerHandler::OnLoginsChanged() {
UpdatePasswordLists(NULL);
}
PasswordStore* PasswordManagerHandler::GetPasswordStore() {
return PasswordStoreFactory::GetForProfile(Profile::FromWebUI(web_ui()),
Profile::EXPLICIT_ACCESS).get();
}
void PasswordManagerHandler::UpdatePasswordLists(const ListValue* args) {
// Reset the current lists.
password_list_.clear();
password_exception_list_.clear();
languages_ = Profile::FromWebUI(web_ui())->GetPrefs()->
GetString(prefs::kAcceptLanguages);
populater_.Populate();
exception_populater_.Populate();
}
void PasswordManagerHandler::RemoveSavedPassword(const ListValue* args) {
PasswordStore* store = GetPasswordStore();
if (!store)
return;
std::string string_value = UTF16ToUTF8(ExtractStringValue(args));
int index;
if (base::StringToInt(string_value, &index) && index >= 0 &&
static_cast<size_t>(index) < password_list_.size())
store->RemoveLogin(*password_list_[index]);
}
void PasswordManagerHandler::RemovePasswordException(
const ListValue* args) {
PasswordStore* store = GetPasswordStore();
if (!store)
return;
std::string string_value = UTF16ToUTF8(ExtractStringValue(args));
int index;
if (base::StringToInt(string_value, &index) && index >= 0 &&
static_cast<size_t>(index) < password_exception_list_.size())
store->RemoveLogin(*password_exception_list_[index]);
}
void PasswordManagerHandler::RemoveAllSavedPasswords(
const ListValue* args) {
// TODO(jhawkins): This will cause a list refresh for every password in the
// list. Add PasswordStore::RemoveAllLogins().
PasswordStore* store = GetPasswordStore();
if (!store)
return;
for (size_t i = 0; i < password_list_.size(); ++i)
store->RemoveLogin(*password_list_[i]);
}
void PasswordManagerHandler::RemoveAllPasswordExceptions(
const ListValue* args) {
PasswordStore* store = GetPasswordStore();
if (!store)
return;
for (size_t i = 0; i < password_exception_list_.size(); ++i)
store->RemoveLogin(*password_exception_list_[i]);
}
void PasswordManagerHandler::SetPasswordList() {
// Due to the way that handlers are (re)initialized under certain types of
// navigation, we may not be initialized yet. (See bugs 88986 and 86448.)
// If this is the case, initialize on demand. This is a hack.
// TODO(mdm): remove this hack once it is no longer necessary.
if (show_passwords_.GetPrefName().empty())
InitializeHandler();
ListValue entries;
bool show_passwords = *show_passwords_;
string16 empty;
for (size_t i = 0; i < password_list_.size(); ++i) {
ListValue* entry = new ListValue();
entry->Append(new StringValue(net::FormatUrl(password_list_[i]->origin,
languages_)));
entry->Append(new StringValue(password_list_[i]->username_value));
entry->Append(new StringValue(
show_passwords ? password_list_[i]->password_value : empty));
entries.Append(entry);
}
web_ui()->CallJavascriptFunction("PasswordManager.setSavedPasswordsList",
entries);
}
void PasswordManagerHandler::SetPasswordExceptionList() {
ListValue entries;
for (size_t i = 0; i < password_exception_list_.size(); ++i) {
entries.Append(new StringValue(
net::FormatUrl(password_exception_list_[i]->origin, languages_)));
}
web_ui()->CallJavascriptFunction("PasswordManager.setPasswordExceptionsList",
entries);
}
PasswordManagerHandler::ListPopulater::ListPopulater(
PasswordManagerHandler* page)
: page_(page),
pending_login_query_(0) {
}
PasswordManagerHandler::ListPopulater::~ListPopulater() {
}
PasswordManagerHandler::PasswordListPopulater::PasswordListPopulater(
PasswordManagerHandler* page) : ListPopulater(page) {
}
void PasswordManagerHandler::PasswordListPopulater::Populate() {
PasswordStore* store = page_->GetPasswordStore();
if (store != NULL) {
if (pending_login_query_)
store->CancelRequest(pending_login_query_);
pending_login_query_ = store->GetAutofillableLogins(this);
} else {
LOG(ERROR) << "No password store! Cannot display passwords.";
}
}
void PasswordManagerHandler::PasswordListPopulater::
OnPasswordStoreRequestDone(
CancelableRequestProvider::Handle handle,
const std::vector<autofill::PasswordForm*>& result) {
DCHECK_EQ(pending_login_query_, handle);
pending_login_query_ = 0;
page_->password_list_.clear();
page_->password_list_.insert(page_->password_list_.end(),
result.begin(), result.end());
page_->SetPasswordList();
}
void PasswordManagerHandler::PasswordListPopulater::OnGetPasswordStoreResults(
const std::vector<autofill::PasswordForm*>& results) {
// TODO(kaiwang): Implement when I refactor
// PasswordStore::GetAutofillableLogins and PasswordStore::GetBlacklistLogins.
NOTIMPLEMENTED();
}
PasswordManagerHandler::PasswordExceptionListPopulater::
PasswordExceptionListPopulater(PasswordManagerHandler* page)
: ListPopulater(page) {
}
void PasswordManagerHandler::PasswordExceptionListPopulater::Populate() {
PasswordStore* store = page_->GetPasswordStore();
if (store != NULL) {
if (pending_login_query_)
store->CancelRequest(pending_login_query_);
pending_login_query_ = store->GetBlacklistLogins(this);
} else {
LOG(ERROR) << "No password store! Cannot display exceptions.";
}
}
void PasswordManagerHandler::PasswordExceptionListPopulater::
OnPasswordStoreRequestDone(
CancelableRequestProvider::Handle handle,
const std::vector<autofill::PasswordForm*>& result) {
DCHECK_EQ(pending_login_query_, handle);
pending_login_query_ = 0;
page_->password_exception_list_.clear();
page_->password_exception_list_.insert(page_->password_exception_list_.end(),
result.begin(), result.end());
page_->SetPasswordExceptionList();
}
void PasswordManagerHandler::PasswordExceptionListPopulater::
OnGetPasswordStoreResults(
const std::vector<autofill::PasswordForm*>& results) {
// TODO(kaiwang): Implement when I refactor
// PasswordStore::GetAutofillableLogins and PasswordStore::GetBlacklistLogins.
NOTIMPLEMENTED();
}
} // namespace options