Skip to content

Commit

Permalink
Added parallel import (#15674)
Browse files Browse the repository at this point in the history
* Added opportunity to make multiple import requests in parallel
  • Loading branch information
spylogsster authored Nov 1, 2022
1 parent 43ac272 commit 45904ff
Show file tree
Hide file tree
Showing 15 changed files with 652 additions and 206 deletions.
9 changes: 9 additions & 0 deletions browser/importer/brave_external_process_importer_host.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
5 changes: 5 additions & 0 deletions browser/importer/brave_external_process_importer_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;
Expand Down
12 changes: 9 additions & 3 deletions browser/ui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand All @@ -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) {
Expand Down
21 changes: 21 additions & 0 deletions browser/ui/webui/settings/BUILD.gn
Original file line number Diff line number Diff line change
@@ -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",
]
}
}
Original file line number Diff line number Diff line change
@@ -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_
Original file line number Diff line number Diff line change
@@ -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 */);
}
172 changes: 172 additions & 0 deletions browser/ui/webui/settings/brave_import_data_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading

0 comments on commit 45904ff

Please sign in to comment.