Added parallel import (#15674)

* Added opportunity to make multiple import requests in parallel
This commit is contained in:
Cepera
2022-11-01 13:52:26 +03:00
committed by GitHub
parent 43ac272df1
commit 45904ffc9c
15 changed files with 652 additions and 206 deletions
@@ -199,4 +199,13 @@ void BraveExternalProcessImporterHost::SetInstallExtensionCallbackForTesting(
install_extension_callback_for_testing_ = std::move(callback);
}
void BraveExternalProcessImporterHost::NotifyImportEndedForTesting() {
ExternalProcessImporterHost::NotifyImportEnded();
}
importer::ImporterProgressObserver*
BraveExternalProcessImporterHost::GetObserverForTesting() {
return observer_;
}
#endif
@@ -30,6 +30,9 @@ class BraveExternalProcessImporterHost : public ExternalProcessImporterHost {
friend class ExternalProcessImporterHost;
friend class BraveExternalProcessImporterHostUnitTest;
FRIEND_TEST_ALL_PREFIXES(BraveImporterObserverUnitTest, ImportEvents);
FRIEND_TEST_ALL_PREFIXES(BraveImporterObserverUnitTest, DestroyObserverEarly);
~BraveExternalProcessImporterHost() override;
void OnExtensionInstalled(const std::string& extension_id,
bool success,
@@ -42,6 +45,8 @@ class BraveExternalProcessImporterHost : public ExternalProcessImporterHost {
void DoNotLaunchImportForTesting();
void SetInstallExtensionCallbackForTesting(MockedInstallCallback callback);
void SetSettingsRemovedCallbackForTesting(base::RepeatingClosure callback);
void NotifyImportEndedForTesting();
importer::ImporterProgressObserver* GetObserverForTesting();
// ExternalProcessImporterHost overrides:
void NotifyImportEnded() override;
+9 -3
View File
@@ -139,7 +139,10 @@ source_set("ui") {
"webui/settings/brave_adblock_handler.h",
"webui/settings/brave_appearance_handler.cc",
"webui/settings/brave_appearance_handler.h",
"webui/settings/brave_import_data_handler.cc",
"webui/settings/brave_import_data_handler.h",
"webui/settings/brave_importer_observer.cc",
"webui/settings/brave_importer_observer.h",
"webui/settings/brave_privacy_handler.cc",
"webui/settings/brave_privacy_handler.h",
"webui/settings/brave_search_engines_handler.cc",
@@ -152,6 +155,8 @@ source_set("ui") {
"webui/settings/brave_wallet_handler.h",
"webui/settings/default_brave_shields_handler.cc",
"webui/settings/default_brave_shields_handler.h",
"webui/settings/import_feature.cc",
"webui/settings/import_feature.h",
"webui/speedreader/speedreader_panel_data_handler_impl.cc",
"webui/speedreader/speedreader_panel_data_handler_impl.h",
"webui/speedreader/speedreader_panel_handler_impl.cc",
@@ -168,9 +173,10 @@ source_set("ui") {
}
if (is_mac) {
sources += [ "webui/settings/brave_import_data_handler_mac.mm" ]
} else {
sources += [ "webui/settings/brave_import_data_handler.cc" ]
sources += [
"webui/settings/brave_full_disk_access_confirm_dialog_delegate.h",
"webui/settings/brave_full_disk_access_confirm_dialog_delegate_mac.mm",
]
}
if (enable_sparkle) {
+21
View File
@@ -0,0 +1,21 @@
# Copyright (c) 2022 The Brave Authors. All rights reserved.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
source_set("unittests") {
if (!is_android) {
testonly = true
sources = [ "brave_importer_observer_unittest.cc" ]
deps = [
"//base/test:test_support",
"//brave/browser/ui",
"//chrome/browser",
"//chrome/browser/ui",
"//content/test:test_support",
"//testing/gtest",
]
}
}
@@ -0,0 +1,44 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef BRAVE_BROWSER_UI_WEBUI_SETTINGS_BRAVE_FULL_DISK_ACCESS_CONFIRM_DIALOG_DELEGATE_H_
#define BRAVE_BROWSER_UI_WEBUI_SETTINGS_BRAVE_FULL_DISK_ACCESS_CONFIRM_DIALOG_DELEGATE_H_
#include <string>
#include "base/memory/raw_ptr.h"
#include "chrome/browser/ui/tab_modal_confirm_dialog_delegate.h"
namespace content {
class WebContents;
} // namespace content
class Browser;
class FullDiskAccessConfirmDialogDelegate
: public TabModalConfirmDialogDelegate {
public:
FullDiskAccessConfirmDialogDelegate(content::WebContents* web_contents,
Browser* browser);
~FullDiskAccessConfirmDialogDelegate() override;
FullDiskAccessConfirmDialogDelegate(
const FullDiskAccessConfirmDialogDelegate&) = delete;
FullDiskAccessConfirmDialogDelegate& operator=(
const FullDiskAccessConfirmDialogDelegate&) = delete;
private:
// TabModalConfirmDialogDelegate overrides:
std::u16string GetTitle() override;
std::u16string GetDialogMessage() override;
std::u16string GetLinkText() const override;
std::u16string GetAcceptButtonTitle() override;
void OnAccepted() override;
void OnLinkClicked(WindowOpenDisposition disposition) override;
raw_ptr<Browser> browser_;
};
#endif // BRAVE_BROWSER_UI_WEBUI_SETTINGS_BRAVE_FULL_DISK_ACCESS_CONFIRM_DIALOG_DELEGATE_H_
@@ -0,0 +1,66 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "brave/browser/ui/webui/settings/brave_full_disk_access_confirm_dialog_delegate.h"
#import <AppKit/AppKit.h>
#include "base/bind.h"
#include "base/values.h"
#include "brave/components/constants/url_constants.h"
#include "brave/components/l10n/common/localization_util.h"
#include "chrome/browser/importer/external_process_importer_host.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/tab_modal_confirm_dialog.h"
#include "chrome/browser/ui/tab_modal_confirm_dialog_delegate.h"
#include "chrome/common/importer/importer_data_types.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/web_ui.h"
#include "ui/base/ui_base_types.h"
#include "url/gurl.h"
FullDiskAccessConfirmDialogDelegate::FullDiskAccessConfirmDialogDelegate(
content::WebContents* web_contents,
Browser* browser)
: TabModalConfirmDialogDelegate(web_contents), browser_(browser) {}
FullDiskAccessConfirmDialogDelegate::~FullDiskAccessConfirmDialogDelegate() =
default;
std::u16string FullDiskAccessConfirmDialogDelegate::GetTitle() {
return brave_l10n::GetLocalizedResourceUTF16String(
IDS_FULL_DISK_ACCESS_CONFIRM_DIALOG_TITLE);
}
std::u16string FullDiskAccessConfirmDialogDelegate::GetDialogMessage() {
return brave_l10n::GetLocalizedResourceUTF16String(
IDS_FULL_DISK_ACCESS_CONFIRM_DIALOG_MESSAGE);
}
std::u16string FullDiskAccessConfirmDialogDelegate::GetLinkText() const {
return brave_l10n::GetLocalizedResourceUTF16String(
IDS_FULL_DISK_ACCESS_CONFIRM_DIALOG_LINK_TEXT);
}
std::u16string FullDiskAccessConfirmDialogDelegate::GetAcceptButtonTitle() {
return brave_l10n::GetLocalizedResourceUTF16String(
IDS_FULL_DISK_ACCESS_CONFIRM_DIALOG_OPEN_PREFS_BUTTON_TEXT);
}
void FullDiskAccessConfirmDialogDelegate::OnAccepted() {
[[NSWorkspace sharedWorkspace]
openURL:[NSURL URLWithString:
@"x-apple.systempreferences:com.apple.preference."
@"security?Privacy_AllFiles"]]; // NOLINT
}
void FullDiskAccessConfirmDialogDelegate::OnLinkClicked(
WindowOpenDisposition disposition) {
const int target_index = browser_->tab_strip_model()->active_index() + 1;
// Add import help tab right after current settings tab.
chrome::AddTabAt(browser_, GURL(kImportDataHelpURL), target_index,
true /* foreground */);
}
@@ -5,9 +5,181 @@
#include "brave/browser/ui/webui/settings/brave_import_data_handler.h"
#include <memory>
#include <string>
#include <unordered_map>
#include "brave/browser/ui/webui/settings/import_feature.h"
#include "chrome/browser/importer/external_process_importer_host.h"
#include "chrome/browser/importer/profile_writer.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/browser_task_traits.h"
#if BUILDFLAG(IS_MAC)
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/mac/foundation_util.h"
#include "base/task/thread_pool.h"
#include "brave/browser/ui/webui/settings/brave_full_disk_access_confirm_dialog_delegate.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/tab_modal_confirm_dialog.h"
#include "content/public/browser/browser_thread.h"
#endif // BUILDFLAG(IS_MAC)
namespace {
#if BUILDFLAG(IS_MAC)
bool HasProperDiskAccessPermission(uint16_t imported_items) {
DCHECK(imported_items);
const base::FilePath& library_dir = base::mac::GetUserLibraryPath();
const base::FilePath safari_dir = library_dir.Append("Safari");
if (imported_items & importer::FAVORITES) {
const base::FilePath bookmarks_path = safari_dir.Append("Bookmarks.plist");
if (!PathIsWritable(bookmarks_path)) {
LOG(ERROR) << __func__ << " " << bookmarks_path << " is not accessible."
<< " Please check full disk access permission.";
return false;
}
}
if (imported_items & importer::HISTORY) {
const base::FilePath history_path = safari_dir.Append("History.plist");
if (!PathIsWritable(history_path)) {
LOG(ERROR) << __func__ << " " << history_path << " is not accessible."
<< " Please check full disk access permission.";
return false;
}
}
return true;
}
#endif // BUILDFLAG(IS_MAC)
} // namespace
namespace settings {
BraveImportDataHandler::BraveImportDataHandler() = default;
BraveImportDataHandler::~BraveImportDataHandler() = default;
void BraveImportDataHandler::StartImport(
const importer::SourceProfile& source_profile,
uint16_t imported_items) {
if (!imported_items)
return;
#if BUILDFLAG(IS_MAC)
CheckDiskAccess(source_profile, imported_items);
#else
StartImportImpl(source_profile, imported_items);
#endif
}
void BraveImportDataHandler::StartImportImpl(
const importer::SourceProfile& source_profile,
uint16_t imported_items) {
// Temporary flag to keep old way until
// https://github.com/brave/brave-core/pull/15637 landed.
// Should be removed in that PR.
if (!IsParallelImportEnabled()) {
ImportDataHandler::StartImport(source_profile, imported_items);
return;
}
// If another import is already ongoing, let it finish silently.
if (import_observers_.count(source_profile.source_path))
import_observers_.erase(source_profile.source_path);
// Using weak pointers because it destroys itself when finshed.
auto* importer_host = new ExternalProcessImporterHost();
import_observers_[source_profile.source_path] =
std::make_unique<BraveImporterObserver>(
importer_host, source_profile, imported_items,
base::BindRepeating(&BraveImportDataHandler::NotifyImportProgress,
weak_factory_.GetWeakPtr()));
Profile* profile = Profile::FromWebUI(web_ui());
importer_host->StartImportSettings(source_profile, profile, imported_items,
new ProfileWriter(profile));
}
void BraveImportDataHandler::NotifyImportProgress(
const importer::SourceProfile& source_profile,
const base::Value& info) {
FireWebUIListener("brave-import-data-status-changed", info);
const std::string* event = info.FindStringKey("event");
if (event && *event == "ImportEnded") {
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(&BraveImportDataHandler::OnImportEnded,
weak_factory_.GetWeakPtr(), source_profile.source_path));
}
}
void BraveImportDataHandler::OnImportEnded(const base::FilePath& source_path) {
import_observers_.erase(source_path);
}
#if BUILDFLAG(IS_MAC)
void BraveImportDataHandler::CheckDiskAccess(
const importer::SourceProfile& source_profile,
uint16_t imported_items) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
guide_dialog_is_requested_ = false;
if (!imported_items)
return;
if (source_profile.importer_type == importer::TYPE_SAFARI) {
// Start import if Brave has full disk access permission.
// If not, show dialog that has infos about that permission.
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock()},
base::BindOnce(&HasProperDiskAccessPermission, imported_items),
base::BindOnce(&BraveImportDataHandler::OnGetDiskAccessPermission,
weak_factory_.GetWeakPtr(), source_profile,
imported_items));
return;
}
StartImportImpl(source_profile, imported_items);
}
void BraveImportDataHandler::OnGetDiskAccessPermission(
const importer::SourceProfile& source_profile,
uint16_t imported_items,
bool allowed) {
if (!allowed) {
// Notify to webui to finish import process and launch tab modal dialog
// to guide full disk access information to users.
// Guide dialog will be opened after import dialog is closed.
FireWebUIListener("import-data-status-changed", base::Value("failed"));
if (IsParallelImportEnabled()) {
import_observers_[source_profile.source_path]->ImportEnded();
}
// Observing web_contents is started here to know the closing timing of
// import dialog.
Observe(web_ui()->GetWebContents());
guide_dialog_is_requested_ = true;
return;
}
StartImportImpl(source_profile, imported_items);
}
void BraveImportDataHandler::DidStopLoading() {
Observe(nullptr);
if (!guide_dialog_is_requested_)
return;
guide_dialog_is_requested_ = false;
auto* web_contents = web_ui()->GetWebContents();
TabModalConfirmDialog::Create(
std::make_unique<FullDiskAccessConfirmDialogDelegate>(
web_contents, chrome::FindBrowserWithWebContents(web_contents)),
web_contents);
}
#endif
} // namespace settings
@@ -6,7 +6,11 @@
#ifndef BRAVE_BROWSER_UI_WEBUI_SETTINGS_BRAVE_IMPORT_DATA_HANDLER_H_
#define BRAVE_BROWSER_UI_WEBUI_SETTINGS_BRAVE_IMPORT_DATA_HANDLER_H_
#include <memory>
#include <unordered_map>
#include "base/memory/weak_ptr.h"
#include "brave/browser/ui/webui/settings/brave_importer_observer.h"
#include "build/build_config.h"
#include "chrome/browser/ui/webui/settings/import_data_handler.h"
#include "content/public/browser/web_contents_observer.h"
@@ -25,8 +29,6 @@ namespace settings {
// new navigation start and tab is newly loaded for closing webui import dialog.
// The reason why native tab modal dialog is used here is to avoid modifying
// upstream import html/js source code.
// NOTE: This is no-op class for other platforms except macOS.
class BraveImportDataHandler : public ImportDataHandler,
content::WebContentsObserver {
public:
@@ -37,11 +39,18 @@ class BraveImportDataHandler : public ImportDataHandler,
BraveImportDataHandler& operator=(const BraveImportDataHandler&) = delete;
private:
#if BUILDFLAG(IS_MAC)
// ImportDataHandler overrides:
void StartImport(const importer::SourceProfile& source_profile,
uint16_t imported_items) override;
void StartImportImpl(const importer::SourceProfile& source_profile,
uint16_t imported_items);
void NotifyImportProgress(const importer::SourceProfile& source_profile,
const base::Value& info);
void OnImportEnded(const base::FilePath& source_path);
#if BUILDFLAG(IS_MAC)
void CheckDiskAccess(const importer::SourceProfile& source_profile,
uint16_t imported_items);
void OnGetDiskAccessPermission(const importer::SourceProfile& source_profile,
uint16_t imported_items,
bool allowed);
@@ -50,9 +59,11 @@ class BraveImportDataHandler : public ImportDataHandler,
void DidStopLoading() override;
bool guide_dialog_is_requested_ = false;
base::WeakPtrFactory<BraveImportDataHandler> weak_factory_;
#endif
std::unordered_map<base::FilePath, std::unique_ptr<BraveImporterObserver>>
import_observers_;
base::WeakPtrFactory<BraveImportDataHandler> weak_factory_{this};
};
} // namespace settings
@@ -1,198 +0,0 @@
/* Copyright (c) 2020 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "brave/browser/ui/webui/settings/brave_import_data_handler.h"
#import <AppKit/AppKit.h>
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/mac/foundation_util.h"
#include "base/task/thread_pool.h"
#include "base/values.h"
#include "brave/components/constants/url_constants.h"
#include "brave/components/l10n/common/localization_util.h"
#include "chrome/browser/importer/external_process_importer_host.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/tab_modal_confirm_dialog.h"
#include "chrome/browser/ui/tab_modal_confirm_dialog_delegate.h"
#include "chrome/common/importer/importer_data_types.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_ui.h"
#include "ui/base/ui_base_types.h"
#include "url/gurl.h"
namespace {
using content::BrowserThread;
class FullDiskAccessConfirmDialogDelegate
: public TabModalConfirmDialogDelegate {
public:
FullDiskAccessConfirmDialogDelegate(content::WebContents* web_contents,
Browser* browser);
~FullDiskAccessConfirmDialogDelegate() override;
FullDiskAccessConfirmDialogDelegate(
const FullDiskAccessConfirmDialogDelegate&) = delete;
FullDiskAccessConfirmDialogDelegate& operator=(
const FullDiskAccessConfirmDialogDelegate&) = delete;
private:
// TabModalConfirmDialogDelegate overrides:
std::u16string GetTitle() override;
std::u16string GetDialogMessage() override;
std::u16string GetLinkText() const override;
std::u16string GetAcceptButtonTitle() override;
void OnAccepted() override;
void OnLinkClicked(WindowOpenDisposition disposition) override;
Browser* browser_;
};
FullDiskAccessConfirmDialogDelegate::FullDiskAccessConfirmDialogDelegate(
content::WebContents* web_contents,
Browser* browser)
: TabModalConfirmDialogDelegate(web_contents),
browser_(browser) {}
FullDiskAccessConfirmDialogDelegate::
~FullDiskAccessConfirmDialogDelegate() = default;
std::u16string FullDiskAccessConfirmDialogDelegate::GetTitle() {
return brave_l10n::GetLocalizedResourceUTF16String(
IDS_FULL_DISK_ACCESS_CONFIRM_DIALOG_TITLE);
}
std::u16string FullDiskAccessConfirmDialogDelegate::GetDialogMessage() {
return brave_l10n::GetLocalizedResourceUTF16String(
IDS_FULL_DISK_ACCESS_CONFIRM_DIALOG_MESSAGE);
}
std::u16string FullDiskAccessConfirmDialogDelegate::GetLinkText() const {
return brave_l10n::GetLocalizedResourceUTF16String(
IDS_FULL_DISK_ACCESS_CONFIRM_DIALOG_LINK_TEXT);
}
std::u16string FullDiskAccessConfirmDialogDelegate::GetAcceptButtonTitle() {
return brave_l10n::GetLocalizedResourceUTF16String(
IDS_FULL_DISK_ACCESS_CONFIRM_DIALOG_OPEN_PREFS_BUTTON_TEXT);
}
void FullDiskAccessConfirmDialogDelegate::OnAccepted() {
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:
@"x-apple.systempreferences:com.apple.preference.security?Privacy_AllFiles"]]; // NOLINT
}
void FullDiskAccessConfirmDialogDelegate::OnLinkClicked(
WindowOpenDisposition disposition) {
const int target_index =
browser_->tab_strip_model()->active_index() + 1;
// Add import help tab right after current settings tab.
chrome::AddTabAt(browser_, GURL(kImportDataHelpURL),
target_index, true /* foreground */);
}
bool HasProperDiskAccessPermission(uint16_t imported_items) {
DCHECK(imported_items);
const base::FilePath& library_dir = base::mac::GetUserLibraryPath();
const base::FilePath safari_dir = library_dir.Append("Safari");
if (imported_items & importer::FAVORITES) {
const base::FilePath bookmarks_path = safari_dir.Append("Bookmarks.plist");
if(!PathIsWritable(bookmarks_path)) {
LOG(ERROR) << __func__ << " " << bookmarks_path << " is not accessible."
<< " Please check full disk access permission.";
return false;
}
}
if (imported_items & importer::HISTORY) {
const base::FilePath history_path = safari_dir.Append("History.plist");
if(!PathIsWritable(history_path)) {
LOG(ERROR) << __func__ << " " << history_path << " is not accessible."
<< " Please check full disk access permission.";
return false;
}
}
return true;
}
} // namespace
namespace settings {
BraveImportDataHandler::BraveImportDataHandler() : weak_factory_(this) {}
BraveImportDataHandler::~BraveImportDataHandler() = default;
void BraveImportDataHandler::StartImport(
const importer::SourceProfile& source_profile,
uint16_t imported_items) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
guide_dialog_is_requested_ = false;
if (!imported_items)
return;
if (source_profile.importer_type == importer::TYPE_SAFARI) {
// Start import if Brave has full disk access permission.
// If not, show dialog that has infos about that permission.
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock()},
base::BindOnce(&HasProperDiskAccessPermission, imported_items),
base::BindOnce(&BraveImportDataHandler::OnGetDiskAccessPermission,
weak_factory_.GetWeakPtr(), source_profile,
imported_items));
return;
}
ImportDataHandler::StartImport(source_profile, imported_items);
}
void BraveImportDataHandler::OnGetDiskAccessPermission(
const importer::SourceProfile& source_profile,
uint16_t imported_items,
bool allowed) {
if (!allowed) {
// Notify to webui to finish import process and launch tab modal dialog
// to guide full disk access information to users.
// Guide dialog will be opened after import dialog is closed.
FireWebUIListener("import-data-status-changed", base::Value("failed"));
// Observing web_contents is started here to know the closing timing of
// import dialog.
Observe(web_ui()->GetWebContents());
guide_dialog_is_requested_ = true;
return;
}
return ImportDataHandler::StartImport(source_profile, imported_items);
}
void BraveImportDataHandler::DidStopLoading() {
Observe(nullptr);
if (!guide_dialog_is_requested_)
return;
guide_dialog_is_requested_ = false;
auto* web_contents = web_ui()->GetWebContents();
TabModalConfirmDialog::Create(
std::make_unique<FullDiskAccessConfirmDialogDelegate>(
web_contents,
chrome::FindBrowserWithWebContents(web_contents)),
web_contents);
}
} // namespace settings
@@ -0,0 +1,83 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "brave/browser/ui/webui/settings/brave_importer_observer.h"
#include <utility>
#include "base/logging.h"
#include "chrome/browser/importer/external_process_importer_host.h"
BraveImporterObserver::BraveImporterObserver(
ExternalProcessImporterHost* importer_host,
const importer::SourceProfile& source_profile,
uint16_t imported_items,
ReportProgressCallback callback)
: source_profile_(source_profile),
imported_items_(imported_items),
callback_(std::move(callback)),
importer_host_(importer_host) {
DCHECK(importer_host);
importer_host->set_observer(this);
}
BraveImporterObserver::~BraveImporterObserver() {
if (importer_host_)
importer_host_->set_observer(nullptr);
}
// importer::ImporterProgressObserver:
void BraveImporterObserver::ImportStarted() {
if (import_started_called_)
return;
import_started_called_ = true;
base::Value::Dict data;
data.Set("importer_name", source_profile_.importer_name);
data.Set("importer_type", source_profile_.importer_type);
data.Set("items_to_import", imported_items_);
data.Set("event", "ImportStarted");
callback_.Run(source_profile_, base::Value(std::move(data)));
}
void BraveImporterObserver::ImportItemStarted(importer::ImportItem item) {
base::Value::Dict data;
data.Set("importer_name", source_profile_.importer_name);
data.Set("importer_type", source_profile_.importer_type);
data.Set("items_to_import", imported_items_);
data.Set("event", "ImportItemStarted");
data.Set("item", item);
callback_.Run(source_profile_, base::Value(std::move(data)));
}
void BraveImporterObserver::ImportItemEnded(importer::ImportItem item) {
base::Value::Dict data;
data.Set("importer_name", source_profile_.importer_name);
data.Set("importer_type", source_profile_.importer_type);
data.Set("items_to_import", imported_items_);
data.Set("event", "ImportItemEnded");
data.Set("item", item);
callback_.Run(source_profile_, base::Value(std::move(data)));
}
void BraveImporterObserver::ImportEnded() {
base::Value::Dict data;
data.Set("importer_name", source_profile_.importer_name);
data.Set("importer_type", source_profile_.importer_type);
data.Set("items_to_import", imported_items_);
data.Set("event", "ImportEnded");
DCHECK(importer_host_);
if (importer_host_)
importer_host_->set_observer(nullptr);
importer_host_ = nullptr;
callback_.Run(source_profile_, base::Value(std::move(data)));
}
ExternalProcessImporterHost*
BraveImporterObserver::GetImporterHostForTesting() {
return importer_host_.get();
}
@@ -0,0 +1,48 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef BRAVE_BROWSER_UI_WEBUI_SETTINGS_BRAVE_IMPORTER_OBSERVER_H_
#define BRAVE_BROWSER_UI_WEBUI_SETTINGS_BRAVE_IMPORTER_OBSERVER_H_
#include "base/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/values.h"
#include "chrome/browser/importer/importer_progress_observer.h"
class ExternalProcessImporterHost;
class BraveImporterObserver : public importer::ImporterProgressObserver {
public:
using ReportProgressCallback = base::RepeatingCallback<
void(const importer::SourceProfile& source_profile, const base::Value&)>;
BraveImporterObserver(ExternalProcessImporterHost* host,
const importer::SourceProfile& source_profile,
uint16_t imported_items,
ReportProgressCallback callback);
~BraveImporterObserver() override;
void ImportStarted() override;
void ImportItemStarted(importer::ImportItem item) override;
void ImportItemEnded(importer::ImportItem item) override;
void ImportEnded() override;
private:
FRIEND_TEST_ALL_PREFIXES(BraveImporterObserverUnitTest, ImportEvents);
ExternalProcessImporterHost* GetImporterHostForTesting();
importer::SourceProfile source_profile_;
uint16_t imported_items_ = 0;
ReportProgressCallback callback_;
// By some reasons ImportStarted event is called few times from different
// places, we expect only one call.
bool import_started_called_ = false;
// If non-null it means importing is in progress. ImporterHost takes care
// of deleting itself when import is complete.
raw_ptr<ExternalProcessImporterHost> importer_host_; // weak
};
#endif // BRAVE_BROWSER_UI_WEBUI_SETTINGS_BRAVE_IMPORTER_OBSERVER_H_
@@ -0,0 +1,141 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "brave/browser/ui/webui/settings/brave_importer_observer.h"
#include <memory>
#include <utility>
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/test/bind.h"
#include "brave/browser/importer/brave_external_process_importer_host.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
class BraveImporterObserverUnitTest : public testing::Test {
public:
BraveImporterObserverUnitTest() {}
void SetExpectedInfo(base::Value value) { expected_info_ = std::move(value); }
void SetExpectedCalls(int value) { expected_calls_ = value; }
int GetExpectedCalls() { return expected_calls_; }
void NotifyImportProgress(const importer::SourceProfile& source_profile,
const base::Value& info) {
EXPECT_EQ(expected_info_, info);
expected_calls_++;
}
private:
content::BrowserTaskEnvironment task_environment_;
base::Value expected_info_;
int expected_calls_ = 0;
raw_ptr<BraveExternalProcessImporterHost> _ = nullptr;
};
TEST_F(BraveImporterObserverUnitTest, ImportEvents) {
auto* importer_host = new BraveExternalProcessImporterHost();
importer::SourceProfile source_profile;
source_profile.importer_name = u"importer_name";
source_profile.importer_type = importer::TYPE_CHROME;
source_profile.source_path = base::FilePath(FILE_PATH_LITERAL("test"));
auto imported_items = importer::AUTOFILL_FORM_DATA | importer::PASSWORDS;
std::unique_ptr<BraveImporterObserver> observer =
std::make_unique<BraveImporterObserver>(
importer_host, source_profile, imported_items,
base::BindRepeating(
&BraveImporterObserverUnitTest::NotifyImportProgress,
base::Unretained(this)));
EXPECT_EQ(importer_host->GetObserverForTesting(), observer.get());
EXPECT_EQ(GetExpectedCalls(), 0);
// Multiple calls for same profile.
SetExpectedInfo(*base::JSONReader::Read(R"({
"event": "ImportStarted",
"importer_name": "importer_name",
"importer_type": 1,
"items_to_import": 72
})"));
observer->ImportStarted();
observer->ImportStarted();
observer->ImportStarted();
EXPECT_EQ(GetExpectedCalls(), 1);
// ImportItemStarted event.
SetExpectedCalls(0);
EXPECT_EQ(GetExpectedCalls(), 0);
SetExpectedInfo(*base::JSONReader::Read(R"({
"event": "ImportItemStarted",
"importer_name": "importer_name",
"importer_type": 1,
"item": 8,
"items_to_import": 72
})"));
observer->ImportItemStarted(importer::PASSWORDS);
EXPECT_EQ(GetExpectedCalls(), 1);
// ImportItemEnded event.
SetExpectedCalls(0);
EXPECT_EQ(GetExpectedCalls(), 0);
SetExpectedInfo(*base::JSONReader::Read(R"({
"event": "ImportItemEnded",
"importer_name": "importer_name",
"importer_type": 1,
"item": 8,
"items_to_import": 72
})"));
observer->ImportItemEnded(importer::PASSWORDS);
EXPECT_EQ(GetExpectedCalls(), 1);
// ImportEnded event.
SetExpectedCalls(0);
EXPECT_EQ(GetExpectedCalls(), 0);
SetExpectedInfo(*base::JSONReader::Read(R"({
"event": "ImportEnded",
"importer_name": "importer_name",
"importer_type": 1,
"items_to_import": 72
})"));
observer->ImportEnded();
EXPECT_EQ(GetExpectedCalls(), 1);
EXPECT_EQ(observer->GetImporterHostForTesting(), nullptr);
// The observer should be removed on ImportEnded event.
EXPECT_EQ(importer_host->GetObserverForTesting(), nullptr);
// ImportEnded event should not be called anymore.
SetExpectedCalls(0);
EXPECT_EQ(GetExpectedCalls(), 0);
// Destroy host.
importer_host->NotifyImportEndedForTesting();
EXPECT_EQ(GetExpectedCalls(), 0);
}
TEST_F(BraveImporterObserverUnitTest, DestroyObserverEarly) {
auto* importer_host = new BraveExternalProcessImporterHost();
importer::SourceProfile source_profile;
source_profile.importer_name = u"importer_name";
source_profile.importer_type = importer::TYPE_CHROME;
source_profile.source_path = base::FilePath(FILE_PATH_LITERAL("test"));
auto imported_items = importer::AUTOFILL_FORM_DATA | importer::PASSWORDS;
std::unique_ptr<BraveImporterObserver> observer =
std::make_unique<BraveImporterObserver>(
importer_host, source_profile, imported_items,
base::BindRepeating(
&BraveImporterObserverUnitTest::NotifyImportProgress,
base::Unretained(this)));
EXPECT_EQ(importer_host->GetObserverForTesting(), observer.get());
EXPECT_EQ(GetExpectedCalls(), 0);
observer.reset();
EXPECT_EQ(importer_host->GetObserverForTesting(), nullptr);
// ImportEnded event should not be called anymore.
SetExpectedCalls(0);
EXPECT_EQ(GetExpectedCalls(), 0);
// Destroy host.
importer_host->NotifyImportEndedForTesting();
EXPECT_EQ(GetExpectedCalls(), 0);
}
@@ -0,0 +1,22 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "brave/browser/ui/webui/settings/import_feature.h"
#include "base/feature_list.h"
#include "base/metrics/field_trial_params.h"
namespace settings {
const base::Feature kParallelImports{"ParallelImports",
base::FEATURE_ENABLED_BY_DEFAULT};
// Temporary flag to keep old way until
// https://github.com/brave/brave-core/pull/15637 landed.
bool IsParallelImportEnabled() {
return base::FeatureList::IsEnabled(kParallelImports);
}
} // namespace settings
@@ -0,0 +1,15 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef BRAVE_BROWSER_UI_WEBUI_SETTINGS_IMPORT_FEATURE_H_
#define BRAVE_BROWSER_UI_WEBUI_SETTINGS_IMPORT_FEATURE_H_
#include "base/feature_list.h"
namespace settings {
bool IsParallelImportEnabled();
} // namespace settings
#endif // BRAVE_BROWSER_UI_WEBUI_SETTINGS_IMPORT_FEATURE_H_
+1
View File
@@ -381,6 +381,7 @@ test("brave_unit_tests") {
"//brave/app:brave_generated_resources_grit",
"//brave/browser/ui/color:unit_tests",
"//brave/browser/ui/toolbar:brave_app_menu_unit_test",
"//brave/browser/ui/webui/settings:unittests",
"//brave/components/brave_shields/common:mojom",
"//brave/components/brave_wallet/browser:pref_names",
"//brave/components/brave_wallet/browser:utils",