Index: chrome/browser/ui/webui/options/password_manager_handler.cc |
diff --git a/chrome/browser/ui/webui/options/password_manager_handler.cc b/chrome/browser/ui/webui/options/password_manager_handler.cc |
index 2b10eb8ec8d69bb7dd8c9f2719c909f1d20e517e..89349bbda703b9b5bd0736a31ea25d32c29a3fa8 100644 |
--- a/chrome/browser/ui/webui/options/password_manager_handler.cc |
+++ b/chrome/browser/ui/webui/options/password_manager_handler.cc |
@@ -6,25 +6,32 @@ |
#include "base/bind.h" |
#include "base/command_line.h" |
+#include "base/files/file_path.h" |
+#include "base/metrics/histogram.h" |
#include "base/prefs/pref_service.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 "chrome/browser/chrome_notification_types.h" |
+#include "chrome/browser/password_manager/sync_metrics.h" |
#include "chrome/browser/profiles/profile.h" |
#include "chrome/browser/sync/profile_sync_service.h" |
#include "chrome/browser/sync/profile_sync_service_factory.h" |
#if defined(OS_WIN) && defined(USE_ASH) |
#include "chrome/browser/ui/ash/ash_util.h" |
#endif |
+#include "chrome/browser/ui/chrome_select_file_policy.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/password_manager/core/browser/affiliation_utils.h" |
+#include "components/password_manager/core/browser/export/password_exporter.h" |
#include "components/password_manager/core/browser/password_bubble_experiment.h" |
+#include "components/password_manager/core/browser/password_store.h" |
#include "components/password_manager/core/common/experiments.h" |
+#include "content/public/browser/browser_thread.h" |
#include "content/public/browser/notification_details.h" |
#include "content/public/browser/notification_source.h" |
#include "content/public/browser/user_metrics.h" |
@@ -36,8 +43,25 @@ |
namespace options { |
-PasswordManagerHandler::PasswordManagerHandler() |
- : password_manager_presenter_(this) {} |
+namespace { |
+ |
+// Enumeration of different callers of SelectFile. Starting count at 1 so |
+// accidental call of SelectFile with params=NULL will error out. |
+enum FileSelectorCaller { |
+ IMPORT_FILE_SELECTED = 1, |
+ EXPORT_FILE_SELECTED, |
+}; |
+ |
+} // namespace |
+ |
+PasswordManagerHandler::PasswordManagerHandler() { |
+ password_manager_presenter_.reset(new PasswordManagerPresenter(this)); |
+} |
+ |
+PasswordManagerHandler::PasswordManagerHandler( |
+ PasswordManagerPresenter* presenter) { |
+ password_manager_presenter_.reset(presenter); |
+} |
PasswordManagerHandler::~PasswordManagerHandler() {} |
@@ -56,24 +80,23 @@ void PasswordManagerHandler::GetLocalizedValues( |
DCHECK(localized_strings); |
static const OptionsStringResource resources[] = { |
- { "autoSigninTitle", |
- IDS_PASSWORDS_AUTO_SIGNIN_TITLE }, |
- { "autoSigninDescription", |
- IDS_PASSWORDS_AUTO_SIGNIN_DESCRIPTION }, |
- { "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 }, |
+ {"autoSigninTitle", IDS_PASSWORDS_AUTO_SIGNIN_TITLE}, |
+ {"autoSigninDescription", IDS_PASSWORDS_AUTO_SIGNIN_DESCRIPTION}, |
+ {"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}, |
+ {"passwordManagerImportPasswordButtonText", |
+ IDS_PASSWORD_MANAGER_IMPORT_BUTTON}, |
+ {"passwordManagerExportPasswordButtonText", |
+ IDS_PASSWORD_MANAGER_EXPORT_BUTTON}, |
+ {"importPasswordCompletedMessage", |
+ IDS_PASSWORD_MANAGER_IMPORT_COMPLETED_MESSAGE}, |
}; |
RegisterStrings(localized_strings, resources, arraysize(resources)); |
@@ -141,10 +164,18 @@ void PasswordManagerHandler::RegisterMessages() { |
"requestShowPassword", |
base::Bind(&PasswordManagerHandler::HandleRequestShowPassword, |
base::Unretained(this))); |
+ web_ui()->RegisterMessageCallback( |
+ "importPassword", |
+ base::Bind(&PasswordManagerHandler::HandlePasswordImport, |
+ base::Unretained(this))); |
+ web_ui()->RegisterMessageCallback( |
+ "exportPassword", |
+ base::Bind(&PasswordManagerHandler::HandlePasswordExport, |
+ base::Unretained(this))); |
} |
void PasswordManagerHandler::InitializeHandler() { |
- password_manager_presenter_.Initialize(); |
+ password_manager_presenter_->Initialize(); |
} |
void PasswordManagerHandler::InitializePage() { |
@@ -152,6 +183,8 @@ void PasswordManagerHandler::InitializePage() { |
password_manager::ManageAccountLinkExperimentEnabled()); |
web_ui()->CallJavascriptFunction( |
"PasswordManager.setManageAccountLinkVisibility", visible); |
+ if (password_manager::ImportExportExperimentEnabled()) |
+ web_ui()->CallJavascriptFunction("PasswordManager.showImportExportButton"); |
} |
void PasswordManagerHandler::HandleRemoveSavedPassword( |
@@ -159,7 +192,8 @@ void PasswordManagerHandler::HandleRemoveSavedPassword( |
std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args)); |
int index; |
if (base::StringToInt(string_value, &index) && index >= 0) { |
- password_manager_presenter_.RemoveSavedPassword(static_cast<size_t>(index)); |
+ password_manager_presenter_->RemoveSavedPassword( |
+ static_cast<size_t>(index)); |
} |
} |
@@ -168,7 +202,7 @@ void PasswordManagerHandler::HandleRemovePasswordException( |
std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args)); |
int index; |
if (base::StringToInt(string_value, &index) && index >= 0) { |
- password_manager_presenter_.RemovePasswordException( |
+ password_manager_presenter_->RemovePasswordException( |
static_cast<size_t>(index)); |
} |
} |
@@ -179,7 +213,7 @@ void PasswordManagerHandler::HandleRequestShowPassword( |
if (!ExtractIntegerValue(args, &index)) |
NOTREACHED(); |
- password_manager_presenter_.RequestShowPassword(static_cast<size_t>(index)); |
+ password_manager_presenter_->RequestShowPassword(static_cast<size_t>(index)); |
} |
void PasswordManagerHandler::ShowPassword( |
@@ -196,7 +230,7 @@ void PasswordManagerHandler::ShowPassword( |
void PasswordManagerHandler::HandleUpdatePasswordLists( |
const base::ListValue* args) { |
- password_manager_presenter_.UpdatePasswordLists(); |
+ password_manager_presenter_->UpdatePasswordLists(); |
} |
void PasswordManagerHandler::SetPasswordList( |
@@ -242,4 +276,115 @@ void PasswordManagerHandler::SetPasswordExceptionList( |
entries); |
} |
+void PasswordManagerHandler::FileSelected(const base::FilePath& path, |
+ int index, |
+ void* params) { |
+ switch (static_cast<FileSelectorCaller>(reinterpret_cast<intptr_t>(params))) { |
+ case IMPORT_FILE_SELECTED: |
+ ImportPasswordFileSelected(path); |
+ break; |
+ case EXPORT_FILE_SELECTED: |
+ ExportPasswordFileSelected(path); |
+ break; |
+ } |
+} |
+ |
+void PasswordManagerHandler::HandlePasswordImport(const base::ListValue* args) { |
+#if !defined(OS_ANDROID) // This is never called on Android. |
+ ui::SelectFileDialog::FileTypeInfo file_type_info; |
+ file_type_info.extensions = |
+ password_manager::PasswordImporter::GetSupportedFileExtensions(); |
+ DCHECK(!file_type_info.extensions.empty() && |
+ !file_type_info.extensions[0].empty()); |
+ file_type_info.include_all_files = true; |
+ selected_file_dialog_ = ui::SelectFileDialog::Create( |
+ this, new ChromeSelectFilePolicy(web_ui()->GetWebContents())); |
+ selected_file_dialog_->SelectFile( |
+ ui::SelectFileDialog::SELECT_OPEN_FILE, |
+ l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_IMPORT_DIALOG_TITLE), |
+ base::FilePath(), &file_type_info, 1, file_type_info.extensions[0][0], |
+ web_ui()->GetWebContents()->GetTopLevelNativeWindow(), |
+ reinterpret_cast<void*>(IMPORT_FILE_SELECTED)); |
+#endif |
+} |
+ |
+void PasswordManagerHandler::ImportPasswordFileSelected( |
+ const base::FilePath& path) { |
+ password_manager::PasswordImporter::Import( |
+ path, content::BrowserThread::GetMessageLoopProxyForThread( |
+ content::BrowserThread::FILE).get(), |
+ base::Bind(&PasswordManagerHandler::ImportPasswordFileRead, |
+ base::Unretained(this))); |
+} |
+ |
+void PasswordManagerHandler::ImportPasswordFileRead( |
+ password_manager::PasswordImporter::Result result, |
+ const std::vector<autofill::PasswordForm>& forms) { |
+ UMA_HISTOGRAM_ENUMERATION("PasswordManager.ImportPasswordFromCSVResult", |
+ result, |
+ password_manager::PasswordImporter::SEMANTIC_ERROR); |
+ if (result != password_manager::PasswordImporter::SUCCESS) |
+ return; |
+ |
+ UMA_HISTOGRAM_COUNTS("PasswordManager.ImportedPasswordsPerUserInCSV", |
+ forms.size()); |
+ |
+ password_manager::PasswordStore* store = |
+ password_manager_presenter_->GetPasswordStore(); |
+ if (store) { |
+ for (const autofill::PasswordForm& form : forms) { |
+ store->AddLogin(form); |
+ } |
+ |
+ // Display Feedback UI |
+ base::FundamentalValue visible(true); |
+ web_ui()->CallJavascriptFunction( |
+ "PasswordManager.setImportCompleteUiVisibility", visible); |
+ } else { |
+ UMA_HISTOGRAM_COUNTS("PasswordManager.FailToStorePasswordImportedFromCSV", |
+ 1); |
+ } |
+} |
+ |
+void PasswordManagerHandler::HandlePasswordExport(const base::ListValue* args) { |
+#if !defined(OS_ANDROID) // This is never called on Android. |
+ if (!password_manager_presenter_->IsUserAuthenticated()) { |
+ return; |
+ } |
+ ui::SelectFileDialog::FileTypeInfo file_type_info; |
+ file_type_info.extensions = |
+ password_manager::PasswordExporter::GetSupportedFileExtensions(); |
+ DCHECK(!file_type_info.extensions.empty() && |
+ !file_type_info.extensions[0].empty()); |
+ file_type_info.include_all_files = true; |
+ selected_file_dialog_ = ui::SelectFileDialog::Create( |
+ this, new ChromeSelectFilePolicy(web_ui()->GetWebContents())); |
+ selected_file_dialog_->SelectFile( |
+ ui::SelectFileDialog::SELECT_SAVEAS_FILE, |
+ l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EXPORT_DIALOG_TITLE), |
+ base::FilePath(), &file_type_info, 1, file_type_info.extensions[0][0], |
+ GetNativeWindow(), reinterpret_cast<void*>(EXPORT_FILE_SELECTED)); |
+#endif |
+} |
+ |
+void PasswordManagerHandler::ExportPasswordFileSelected( |
+ const base::FilePath& path) { |
+ ScopedVector<autofill::PasswordForm> password_list = |
+ password_manager_presenter_->GetAllPasswords().Pass(); |
+ UMA_HISTOGRAM_COUNTS("PasswordManager.ExportedPasswordsPerUserInCSV", |
+ password_list.size()); |
+ password_manager::PasswordExporter::Export( |
+ path, password_list.Pass(), |
+ content::BrowserThread::GetMessageLoopProxyForThread( |
+ content::BrowserThread::FILE).get(), |
+ base::Closure()); |
+} |
+ |
+void PasswordManagerHandler::ExportPasswordFileWritten() { |
Evan Stade
2015/07/11 00:28:42
is this used?
xunlu
2015/07/13 21:30:26
Removed
|
+ // We do not plan to give any UI feedback for export at this moment as it |
+ // will almost always succeed. If the plan changes, make this function the |
+ // callback of password_manager::PasswordExporter::Export and put the feedback |
+ // logic here. |
+} |
+ |
} // namespace options |