Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(170)

Unified Diff: chrome/browser/ui/webui/options/password_manager_handler.cc

Issue 1193143003: Enable import/export of passwords into/from Password Manager (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase and comments Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698