Skip to content

Commit

Permalink
Add PasswordManagerPorter class for password import/export
Browse files Browse the repository at this point in the history
This class provides functionality to import and export
passwords from and to the Password Manager as part of
a change to enable password importing/exporting from
the new Material Design Password Manager settings.

Cq-Include-Trybots: master.tryserver.chromium.linux:closure_compilation
Change-Id: Idbf3cad46b9ef62c2bd4ff923d208833ef3b03ac
Reviewed-on: https://chromium-review.googlesource.com/668448
Commit-Queue: Nathanael Alcock <varkor@google.com>
Reviewed-by: Vasilii Sukhanov <vasilii@chromium.org>
Reviewed-by: Ilya Sherman <isherman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#503223}
  • Loading branch information
Nathanael Alcock authored and Commit Bot committed Sep 20, 2017
1 parent 108e612 commit 226d0ee
Show file tree
Hide file tree
Showing 11 changed files with 441 additions and 9 deletions.
4 changes: 2 additions & 2 deletions chrome/app/generated_resources.grd
Original file line number Diff line number Diff line change
Expand Up @@ -5579,10 +5579,10 @@ the Bookmarks menu.">
<message name="IDS_PASSWORD_MANAGER_EXPORT_BUTTON" desc="The label of the button for exporting passwords. The button appears next to the list of saved passwords in Chrome's settings.">
Export
</message>
<message name="IDS_PASSWORD_MANAGER_IMPORT_DIALOG_TITLE" desc="The Title of the file selection dialog for importing password">
<message name="IDS_PASSWORD_MANAGER_IMPORT_DIALOG_TITLE" desc="The title of the file selection dialog for importing passwords">
Import Passwords To Chrome
</message>
<message name="IDS_PASSWORD_MANAGER_EXPORT_DIALOG_TITLE" desc="The Title of the file selection dialog for exporting password">
<message name="IDS_PASSWORD_MANAGER_EXPORT_DIALOG_TITLE" desc="The title of the file selection dialog for exporting passwords">
Export Passwords From Chrome
</message>
</if>
Expand Down
3 changes: 3 additions & 0 deletions chrome/browser/ui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,13 @@ split_static_library("ui") {
"page_info/page_info_ui.h",
"passwords/account_avatar_fetcher.cc",
"passwords/account_avatar_fetcher.h",
"passwords/credential_provider_interface.h",
"passwords/manage_passwords_state.cc",
"passwords/manage_passwords_state.h",
"passwords/manage_passwords_view_utils.cc",
"passwords/manage_passwords_view_utils.h",
"passwords/password_manager_porter.cc",
"passwords/password_manager_porter.h",
"passwords/password_manager_presenter.cc",
"passwords/password_manager_presenter.h",
"passwords/password_ui_view.h",
Expand Down
24 changes: 24 additions & 0 deletions chrome/browser/ui/passwords/credential_provider_interface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2017 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.

#ifndef CHROME_BROWSER_UI_PASSWORDS_CREDENTIAL_PROVIDER_INTERFACE_H_
#define CHROME_BROWSER_UI_PASSWORDS_CREDENTIAL_PROVIDER_INTERFACE_H_

namespace autofill {
struct PasswordForm;
}

// Provides an interface for getting credentials, such as passwords, from some
// form of provider.
class CredentialProviderInterface {
public:
// Gets all password entries.
virtual std::vector<std::unique_ptr<autofill::PasswordForm>>
GetAllPasswords() = 0;

protected:
virtual ~CredentialProviderInterface() {}
};

#endif // CHROME_BROWSER_UI_PASSWORDS_CREDENTIAL_PROVIDER_INTERFACE_H_
167 changes: 167 additions & 0 deletions chrome/browser/ui/passwords/password_manager_porter.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// Copyright 2017 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/passwords/password_manager_porter.h"

#include "base/metrics/histogram_macros.h"
#include "base/path_service.h"
#include "build/build_config.h"
#include "chrome/browser/password_manager/password_store_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/chrome_select_file_policy.h"
#include "chrome/browser/ui/passwords/credential_provider_interface.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/grit/generated_resources.h"
#include "components/password_manager/core/browser/export/password_exporter.h"
#include "components/password_manager/core/browser/password_store.h"
#include "content/public/browser/web_contents.h"
#include "net/base/filename_util.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"

namespace {
// The following are not used on Android due to the |SelectFileDialog| being
// unused.
#if !defined(OS_ANDROID)
// The default name of the password file when exporting.
constexpr base::FilePath::CharType kDefaultFileName[] =
FILE_PATH_LITERAL("chrome_passwords");

// The default directory and filename when importing and exporting passwords.
base::FilePath GetDefaultFilepathForPasswordFile(
const base::FilePath::StringType& default_extension) {
base::FilePath default_path;
PathService::Get(chrome::DIR_USER_DOCUMENTS, &default_path);
return default_path.Append(kDefaultFileName).AddExtension(default_extension);
}
#endif

// A helper class for reading the passwords that have been imported.
class PasswordImportConsumer {
public:
explicit PasswordImportConsumer(Profile* profile);

void ConsumePassword(password_manager::PasswordImporter::Result result,
const std::vector<autofill::PasswordForm>& forms);

private:
Profile* profile_;
SEQUENCE_CHECKER(sequence_checker_);

DISALLOW_COPY_AND_ASSIGN(PasswordImportConsumer);
};

PasswordImportConsumer::PasswordImportConsumer(Profile* profile)
: profile_(profile) {}

void PasswordImportConsumer::ConsumePassword(
password_manager::PasswordImporter::Result result,
const std::vector<autofill::PasswordForm>& forms) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

UMA_HISTOGRAM_ENUMERATION(
"PasswordManager.ImportPasswordFromCSVResult", result,
password_manager::PasswordImporter::NUM_IMPORT_RESULTS);

if (result != password_manager::PasswordImporter::SUCCESS)
return;

UMA_HISTOGRAM_COUNTS("PasswordManager.ImportedPasswordsPerUserInCSV",
forms.size());
scoped_refptr<password_manager::PasswordStore> store(
PasswordStoreFactory::GetForProfile(profile_,
ServiceAccessType::EXPLICIT_ACCESS));
if (store) {
for (const autofill::PasswordForm& form : forms)
store->AddLogin(form);
}
}
} // namespace

PasswordManagerPorter::PasswordManagerPorter(
CredentialProviderInterface* credential_provider_interface)
: credential_provider_interface_(credential_provider_interface) {}

PasswordManagerPorter::~PasswordManagerPorter() {}

void PasswordManagerPorter::PresentFileSelector(
content::WebContents* web_contents,
Type type) {
// This method should never be called on Android (as there is no file selector),
// and the relevant IDS constants are not present for Android.
#if !defined(OS_ANDROID)
DCHECK(web_contents);
profile_ = Profile::FromBrowserContext(web_contents->GetBrowserContext());

// Get the default file extension for password files.
ui::SelectFileDialog::FileTypeInfo file_type_info;
file_type_info.extensions =
password_manager::PasswordExporter::GetSupportedFileExtensions();
DCHECK(!file_type_info.extensions.empty());
DCHECK(!file_type_info.extensions[0].empty());
file_type_info.include_all_files = true;

// Present the file selector dialogue.
select_file_dialog_ = ui::SelectFileDialog::Create(
this, std::make_unique<ChromeSelectFilePolicy>(web_contents));

ui::SelectFileDialog::Type file_selector_mode =
ui::SelectFileDialog::SELECT_NONE;
unsigned title = 0;
switch (type) {
case PASSWORD_IMPORT:
file_selector_mode = ui::SelectFileDialog::SELECT_OPEN_FILE;
title = IDS_PASSWORD_MANAGER_IMPORT_DIALOG_TITLE;
break;
case PASSWORD_EXPORT:
file_selector_mode = ui::SelectFileDialog::SELECT_SAVEAS_FILE;
title = IDS_PASSWORD_MANAGER_EXPORT_DIALOG_TITLE;
break;
}
// Check that a valid action has been chosen.
DCHECK(file_selector_mode);
DCHECK(title);

select_file_dialog_->SelectFile(
file_selector_mode, l10n_util::GetStringUTF16(title),
GetDefaultFilepathForPasswordFile(file_type_info.extensions[0][0]),
&file_type_info, 1, file_type_info.extensions[0][0],
web_contents->GetTopLevelNativeWindow(), reinterpret_cast<void*>(type));
#endif
}

void PasswordManagerPorter::FileSelected(const base::FilePath& path,
int index,
void* params) {
// We are unable to cast directly from void* to Type: reinterpret_cast will
// only convert between pointers and static_cast only from integral types to
// enums (for those types that are relevant to this example), which
// necessitates the use of two casts.
switch (static_cast<Type>(reinterpret_cast<uintptr_t>(params))) {
case PASSWORD_IMPORT:
ImportPasswordsFromPath(path);
break;
case PASSWORD_EXPORT:
ExportPasswordsToPath(path);
break;
}
}

void PasswordManagerPorter::ImportPasswordsFromPath(
const base::FilePath& path) {
// Set up a |PasswordImportConsumer| to process each password entry.
std::unique_ptr<PasswordImportConsumer> form_consumer(
new PasswordImportConsumer(profile_));
password_manager::PasswordImporter::Import(
path, base::Bind(&PasswordImportConsumer::ConsumePassword,
std::move(form_consumer)));
}

void PasswordManagerPorter::ExportPasswordsToPath(const base::FilePath& path) {
std::vector<std::unique_ptr<autofill::PasswordForm>> password_list =
credential_provider_interface_->GetAllPasswords();
UMA_HISTOGRAM_COUNTS("PasswordManager.ExportedPasswordsPerUserInCSV",
password_list.size());
password_manager::PasswordExporter::Export(path, std::move(password_list));
}
55 changes: 55 additions & 0 deletions chrome/browser/ui/passwords/password_manager_porter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2017 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.

#ifndef CHROME_BROWSER_UI_PASSWORDS_PASSWORD_MANAGER_PORTER_H_
#define CHROME_BROWSER_UI_PASSWORDS_PASSWORD_MANAGER_PORTER_H_

#include "components/password_manager/core/browser/import/password_importer.h"
#include "ui/shell_dialogs/select_file_dialog.h"

namespace content {
class WebContents;
}

class CredentialProviderInterface;
class Profile;

// Handles the exporting of passwords to a file, and the importing of such a
// file to the Password Manager.
class PasswordManagerPorter : public ui::SelectFileDialog::Listener {
public:
enum Type {
PASSWORD_IMPORT,
PASSWORD_EXPORT,
};

explicit PasswordManagerPorter(
CredentialProviderInterface* credential_provider_interface);

~PasswordManagerPorter() override;

// Display the file-picker dialogue for either importing or exporting
// passwords.
void PresentFileSelector(content::WebContents* web_contents, Type type);

private:
// Callback from the file selector dialogue when a file has been picked (for
// either import or export).
// ui::SelectFileDialog::Listener:
void FileSelected(const base::FilePath& path,
int index,
void* params) override;

virtual void ImportPasswordsFromPath(const base::FilePath& path);

virtual void ExportPasswordsToPath(const base::FilePath& path);

CredentialProviderInterface* credential_provider_interface_;
scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
Profile* profile_;

DISALLOW_COPY_AND_ASSIGN(PasswordManagerPorter);
};

#endif // CHROME_BROWSER_UI_PASSWORDS_PASSWORD_MANAGER_PORTER_H_
Loading

0 comments on commit 226d0ee

Please sign in to comment.