// Copyright 2013 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/feature_list.h" #include "base/macros.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "build/build_config.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "chrome/grit/generated_resources.h" #include "components/autofill/core/common/password_form.h" #include "components/browser_sync/browser/profile_sync_service.h" #include "components/password_manager/core/browser/password_bubble_experiment.h" #include "components/password_manager/core/browser/password_manager_constants.h" #include "components/password_manager/core/browser/password_ui_utils.h" #include "components/password_manager/core/common/experiments.h" #include "components/prefs/pref_service.h" #include "components/strings/grit/components_strings.h" #include "components/url_formatter/url_formatter.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_source.h" #include "content/public/browser/user_metrics.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" #include "content/public/common/content_features.h" #include "content/public/common/origin_util.h" #include "ui/base/l10n/l10n_util.h" #if defined(OS_WIN) && defined(USE_ASH) #include "chrome/browser/ui/ash/ash_util.h" #endif namespace options { namespace { // The following constants should be synchronized with the constants in // chrome/browser/resources/options/password_manager_list.js. const char kOriginField[] = "origin"; const char kShownUrlField[] = "shownUrl"; const char kIsAndroidUriField[] = "isAndroidUri"; const char kIsSecureField[] = "isSecure"; const char kUsernameField[] = "username"; const char kPasswordField[] = "password"; const char kFederationField[] = "federation"; // Copies from |form| to |entry| the origin, shown origin, whether the origin is // Android URI, and whether the origin is secure. void CopyOriginInfoOfPasswordForm(const autofill::PasswordForm& form, const std::string& languages, base::DictionaryValue* entry) { entry->SetString( kOriginField, url_formatter::FormatUrl( form.origin, languages, url_formatter::kFormatUrlOmitNothing, net::UnescapeRule::SPACES, nullptr, nullptr, nullptr)); bool is_android_uri = false; entry->SetString(kShownUrlField, password_manager::GetShownOrigin( form, languages, &is_android_uri)); entry->SetBoolean(kIsAndroidUriField, is_android_uri); entry->SetBoolean(kIsSecureField, content::IsOriginSecure(form.origin)); } } // namespace PasswordManagerHandler::PasswordManagerHandler() : password_manager_presenter_(this) {} PasswordManagerHandler::~PasswordManagerHandler() {} Profile* PasswordManagerHandler::GetProfile() { return Profile::FromWebUI(web_ui()); } #if !defined(OS_ANDROID) gfx::NativeWindow PasswordManagerHandler::GetNativeWindow() const { return web_ui()->GetWebContents()->GetTopLevelNativeWindow(); } #endif void PasswordManagerHandler::GetLocalizedValues( base::DictionaryValue* localized_strings) { DCHECK(localized_strings); static const OptionsStringResource resources[] = { {"autoSigninTitle", IDS_PASSWORDS_AUTO_SIGNIN_TITLE}, {"autoSigninDescription", IDS_PASSWORDS_AUTO_SIGNIN_DESCRIPTION}, {"savedPasswordsTitle", IDS_PASSWORD_MANAGER_SHOW_PASSWORDS_TAB_TITLE}, {"passwordExceptionsTitle", IDS_PASSWORD_MANAGER_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)); const ProfileSyncService* sync_service = ProfileSyncServiceFactory::GetForProfile(GetProfile()); int title_id = password_bubble_experiment::IsSmartLockBrandingEnabled(sync_service) ? IDS_PASSWORD_MANAGER_SMART_LOCK_FOR_PASSWORDS : IDS_PASSWORDS_EXCEPTIONS_WINDOW_TITLE; RegisterTitle(localized_strings, "passwordsPage", title_id); localized_strings->SetString("passwordManagerLearnMoreURL", chrome::kPasswordManagerLearnMoreURL); localized_strings->SetString( "passwordsManagePasswordsLink", password_manager::kPasswordManagerAccountDashboardURL); std::string management_hostname = GURL(password_manager::kPasswordManagerAccountDashboardURL).host(); base::string16 link_text = base::UTF8ToUTF16(management_hostname); size_t offset; base::string16 full_text = l10n_util::GetStringFUTF16( IDS_MANAGE_PASSWORDS_REMOTE_TEXT, link_text, &offset); localized_strings->SetString("passwordsManagePasswordsBeforeLinkText", full_text.substr(0, offset)); localized_strings->SetString("passwordsManagePasswordsLinkText", full_text.substr(offset, link_text.size())); localized_strings->SetString("passwordsManagePasswordsAfterLinkText", full_text.substr(offset + link_text.size())); bool disable_show_passwords = false; #if defined(OS_WIN) && defined(USE_ASH) // We disable the ability to show passwords when running in Windows Metro // interface. This is because we cannot pop native Win32 dialogs from the // Metro process. // TODO(wfh): Revisit this if Metro usage grows. if (chrome::IsNativeWindowInAsh(GetNativeWindow())) disable_show_passwords = true; #endif localized_strings->SetBoolean("disableShowPasswords", disable_show_passwords); localized_strings->SetBoolean( "enableCredentialManagerAPI", base::FeatureList::IsEnabled(features::kCredentialManagementAPI)); } void PasswordManagerHandler::RegisterMessages() { web_ui()->RegisterMessageCallback( "updatePasswordLists", base::Bind(&PasswordManagerHandler::HandleUpdatePasswordLists, base::Unretained(this))); web_ui()->RegisterMessageCallback( "removeSavedPassword", base::Bind(&PasswordManagerHandler::HandleRemoveSavedPassword, base::Unretained(this))); web_ui()->RegisterMessageCallback( "removePasswordException", base::Bind(&PasswordManagerHandler::HandleRemovePasswordException, base::Unretained(this))); web_ui()->RegisterMessageCallback( "requestShowPassword", base::Bind(&PasswordManagerHandler::HandleRequestShowPassword, base::Unretained(this))); } void PasswordManagerHandler::InitializeHandler() { password_manager_presenter_.Initialize(); } void PasswordManagerHandler::HandleRemoveSavedPassword( const base::ListValue* args) { std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args)); int index; if (base::StringToInt(string_value, &index) && index >= 0) { password_manager_presenter_.RemoveSavedPassword(static_cast(index)); } } void PasswordManagerHandler::HandleRemovePasswordException( const base::ListValue* args) { std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args)); int index; if (base::StringToInt(string_value, &index) && index >= 0) { password_manager_presenter_.RemovePasswordException( static_cast(index)); } } void PasswordManagerHandler::HandleRequestShowPassword( const base::ListValue* args) { int index; if (!ExtractIntegerValue(args, &index)) NOTREACHED(); password_manager_presenter_.RequestShowPassword(static_cast(index)); } void PasswordManagerHandler::ShowPassword( size_t index, const std::string& origin_url, const std::string& username, const base::string16& password_value) { // Call back the front end to reveal the password. web_ui()->CallJavascriptFunction( "PasswordManager.showPassword", base::FundamentalValue(static_cast(index)), base::StringValue(password_value)); } void PasswordManagerHandler::HandleUpdatePasswordLists( const base::ListValue* args) { password_manager_presenter_.UpdatePasswordLists(); } void PasswordManagerHandler::SetPasswordList( const std::vector>& password_list, bool show_passwords) { base::ListValue entries; languages_ = GetProfile()->GetPrefs()->GetString(prefs::kAcceptLanguages); base::string16 placeholder(base::ASCIIToUTF16(" ")); for (const auto& saved_password : password_list) { scoped_ptr entry(new base::DictionaryValue); CopyOriginInfoOfPasswordForm(*saved_password, languages_, entry.get()); entry->SetString(kUsernameField, saved_password->username_value); if (show_passwords) { entry->SetString(kPasswordField, saved_password->password_value); } else { // Use a placeholder value with the same length as the password. entry->SetString( kPasswordField, base::string16(saved_password->password_value.length(), ' ')); } if (!saved_password->federation_origin.unique()) { entry->SetString( kFederationField, l10n_util::GetStringFUTF16( IDS_PASSWORDS_VIA_FEDERATION, base::UTF8ToUTF16(saved_password->federation_origin.host()))); } entries.Append(entry.release()); } web_ui()->CallJavascriptFunction("PasswordManager.setSavedPasswordsList", entries); } void PasswordManagerHandler::SetPasswordExceptionList( const std::vector>& password_exception_list) { base::ListValue entries; for (const auto& exception : password_exception_list) { scoped_ptr entry(new base::DictionaryValue); CopyOriginInfoOfPasswordForm(*exception, languages_, entry.get()); entries.Append(entry.release()); } web_ui()->CallJavascriptFunction("PasswordManager.setPasswordExceptionsList", entries); } } // namespace options