diff --git a/app/brave_generated_resources.grd b/app/brave_generated_resources.grd
index 35a8a5f01966..402fa640c23f 100644
--- a/app/brave_generated_resources.grd
+++ b/app/brave_generated_resources.grd
@@ -716,6 +716,15 @@ By installing this extension, you are agreeing to the Google Widevine Terms of U
To add a bookmark, click the bookmark button next to the address bar
+
+ Full Disk access required
+
+
+ Brave needs full disk access to import browsing data from Safari.
+
+
+ Learn how to grant Full Disk Access
+
diff --git a/browser/ui/BUILD.gn b/browser/ui/BUILD.gn
index 4ae7769914d5..896750a1ccde 100644
--- a/browser/ui/BUILD.gn
+++ b/browser/ui/BUILD.gn
@@ -173,6 +173,13 @@ source_set("ui") {
]
}
+ if (is_mac) {
+ sources += [
+ "webui/settings/brave_settings_import_data_handler.mm",
+ "webui/settings/brave_settings_import_data_handler.h",
+ ]
+ }
+
deps = [
"//base",
"//brave/app:command_ids",
@@ -215,6 +222,7 @@ source_set("ui") {
"//ui/base",
"//ui/gfx",
"//ui/resources",
+ "//url",
]
# This is no longer compiled into Chromium on Android, but we still
diff --git a/browser/ui/webui/settings/brave_settings_import_data_handler.h b/browser/ui/webui/settings/brave_settings_import_data_handler.h
new file mode 100644
index 000000000000..ab8aa7930b1f
--- /dev/null
+++ b/browser/ui/webui/settings/brave_settings_import_data_handler.h
@@ -0,0 +1,55 @@
+/* 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/. */
+
+#ifndef BRAVE_BROWSER_UI_WEBUI_SETTINGS_BRAVE_SETTINGS_IMPORT_DATA_HANDLER_H_
+#define BRAVE_BROWSER_UI_WEBUI_SETTINGS_BRAVE_SETTINGS_IMPORT_DATA_HANDLER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/ui/webui/settings/settings_import_data_handler.h"
+#include "content/public/browser/web_contents_observer.h"
+
+namespace settings {
+
+// This class checks whether Brave has full disk access permission to import
+// safart data. ImportDataHandler::StartImport() will be run after checking
+// disk access permission. If Brave doesn't have that permission, this will
+// launch tab modal dialog to notify users about this lack of permission.
+
+// We should display tab modal dialog after import dialog is closed from webui.
+// To do that, this observes web contents to launch dialog after import dialog
+// closed. If dialog is launched right after notifying import failure,
+// dialog will be closed immediately because tab modal dialog is closed with
+// 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.
+class BraveImportDataHandler : public ImportDataHandler,
+ content::WebContentsObserver {
+ public:
+ BraveImportDataHandler();
+ ~BraveImportDataHandler() override;
+
+ BraveImportDataHandler(const BraveImportDataHandler&) = delete;
+ BraveImportDataHandler& operator=(const BraveImportDataHandler&) = delete;
+
+ private:
+ // ImportDataHandler overrides:
+ void StartImport(const importer::SourceProfile& source_profile,
+ uint16_t imported_items) override;
+
+ void OnGetDiskAccessPermission(const importer::SourceProfile& source_profile,
+ uint16_t imported_items,
+ bool allowed);
+
+ // content::WebContentsObserver overrides:
+ void DidStopLoading() override;
+
+ bool guide_dialog_is_requested_ = false;
+
+ base::WeakPtrFactory weak_factory_;
+};
+
+} // namespace settings
+
+#endif // BRAVE_BROWSER_UI_WEBUI_SETTINGS_BRAVE_SETTINGS_IMPORT_DATA_HANDLER_H_
diff --git a/browser/ui/webui/settings/brave_settings_import_data_handler.mm b/browser/ui/webui/settings/brave_settings_import_data_handler.mm
new file mode 100644
index 000000000000..8174fc2133bc
--- /dev/null
+++ b/browser/ui/webui/settings/brave_settings_import_data_handler.mm
@@ -0,0 +1,186 @@
+/* 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_settings_import_data_handler.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/post_task.h"
+#include "base/task/task_traits.h"
+#include "base/values.h"
+#include "brave/common/url_constants.h"
+#include "chrome/browser/importer/external_process_importer_host.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/l10n/l10n_util.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:
+ base::string16 GetTitle() override;
+ base::string16 GetDialogMessage() override;
+ base::string16 GetLinkText() const override;
+ int GetDialogButtons() const override;
+ void OnLinkClicked(WindowOpenDisposition disposition) override;
+
+ Browser* browser_;
+};
+
+FullDiskAccessConfirmDialogDelegate::FullDiskAccessConfirmDialogDelegate(
+ content::WebContents* web_contents,
+ Browser* browser)
+ : TabModalConfirmDialogDelegate(web_contents),
+ browser_(browser) {}
+
+FullDiskAccessConfirmDialogDelegate::
+ ~FullDiskAccessConfirmDialogDelegate() = default;
+
+base::string16 FullDiskAccessConfirmDialogDelegate::GetTitle() {
+ return l10n_util::GetStringUTF16(IDS_FULL_DISK_ACCESS_CONFIRM_DIALOG_TITLE);
+}
+
+base::string16 FullDiskAccessConfirmDialogDelegate::GetDialogMessage() {
+ return l10n_util::GetStringUTF16(IDS_FULL_DISK_ACCESS_CONFIRM_DIALOG_MESSAGE);
+}
+
+base::string16 FullDiskAccessConfirmDialogDelegate::GetLinkText() const {
+ return l10n_util::GetStringUTF16(IDS_FULL_DISK_ACCESS_CONFIRM_DIALOG_LINK_TEXT);
+}
+
+int FullDiskAccessConfirmDialogDelegate::GetDialogButtons() const {
+ return ui::DIALOG_BUTTON_OK;
+}
+
+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::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::ThreadPool(), 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(
+ web_contents,
+ chrome::FindBrowserWithWebContents(web_contents)),
+ web_contents);
+}
+
+} // namespace settings
diff --git a/chromium_src/chrome/browser/ui/webui/settings/settings_import_data_handler.cc b/chromium_src/chrome/browser/ui/webui/settings/settings_import_data_handler.cc
new file mode 100644
index 000000000000..e9ea37bc8b8d
--- /dev/null
+++ b/chromium_src/chrome/browser/ui/webui/settings/settings_import_data_handler.cc
@@ -0,0 +1,36 @@
+/* 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/importer/brave_external_process_importer_host.h"
+#include "brave/browser/importer/brave_profile_writer.h"
+
+#define ProfileWriter BraveProfileWriter
+#define ExternalProcessImporterHost BraveExternalProcessImporterHost
+
+#define ADD_BRAVE_SPECIFIC_IMPORTER_ITEMS \
+ if (prefs->GetBoolean(prefs::kImportDialogCookies)) \
+ selected_items |= importer::COOKIES; \
+ if (prefs->GetBoolean(prefs::kImportDialogStats)) \
+ selected_items |= importer::STATS; \
+ if (prefs->GetBoolean(prefs::kImportDialogLedger)) \
+ selected_items |= importer::LEDGER; \
+ if (prefs->GetBoolean(prefs::kImportDialogWindows)) \
+ selected_items |= importer::WINDOWS;
+
+#define SET_BRAVE_SPECIFIC_IMPORTER_DATA \
+ browser_profile->SetBoolean("cookies", \
+ (browser_services & importer::COOKIES) != 0); \
+ browser_profile->SetBoolean("stats", \
+ (browser_services & importer::STATS) != 0); \
+ browser_profile->SetBoolean("ledger", \
+ (browser_services & importer::LEDGER) != 0); \
+ browser_profile->SetBoolean("windows", \
+ (browser_services & importer::WINDOWS) != 0);
+
+#include "../../../../../../../chrome/browser/ui/webui/settings/settings_import_data_handler.cc" // NOLINT
+#undef ProfileWriter
+#undef ExternalProcessImporterHost
+#undef ADD_BRAVE_SPECIFIC_IMPORTER_ITEMS
+#undef SET_BRAVE_SPECIFIC_IMPORTER_DATA
diff --git a/chromium_src/chrome/browser/ui/webui/settings/settings_import_data_handler.h b/chromium_src/chrome/browser/ui/webui/settings/settings_import_data_handler.h
new file mode 100644
index 000000000000..94326589a409
--- /dev/null
+++ b/chromium_src/chrome/browser/ui/webui/settings/settings_import_data_handler.h
@@ -0,0 +1,20 @@
+/* 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/. */
+
+#ifndef BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_WEBUI_SETTINGS_SETTINGS_IMPORT_DATA_HANDLER_H_
+#define BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_WEBUI_SETTINGS_SETTINGS_IMPORT_DATA_HANDLER_H_
+
+#define BRAVE_IMPORT_DATA_HANDLER_H \
+ private: \
+ friend class BraveImportDataHandler;
+
+#define StartImport virtual StartImport
+
+#include "../../../../../../../chrome/browser/ui/webui/settings/settings_import_data_handler.h"
+
+#undef BRAVE_IMPORT_DATA_HANDLER_H
+#undef StartImport
+
+#endif // BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_WEBUI_SETTINGS_SETTINGS_IMPORT_DATA_HANDLER_H_
diff --git a/chromium_src/chrome/browser/ui/webui/settings/settings_ui.cc b/chromium_src/chrome/browser/ui/webui/settings/settings_ui.cc
index bc6ec769e100..0e1ed608ed18 100644
--- a/chromium_src/chrome/browser/ui/webui/settings/settings_ui.cc
+++ b/chromium_src/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -6,6 +6,19 @@
#include "brave/browser/ui/webui/settings/brave_about_handler.h"
#include "chrome/browser/ui/webui/settings/about_handler.h"
+#if defined(OS_MACOSX)
+#include "brave/browser/ui/webui/settings/brave_settings_import_data_handler.h"
+#endif
+
#define AboutHandler BraveAboutHandler
+
+#if defined(OS_MACOSX)
+#define ImportDataHandler BraveImportDataHandler
+#endif
+
#include "../../../../../../../chrome/browser/ui/webui/settings/settings_ui.cc"
#undef AboutHandler
+
+#if defined(OS_MACOSX)
+#undef ImportDataHandler
+#endif
diff --git a/common/url_constants.cc b/common/url_constants.cc
index 20378d44e836..23a64e75072c 100644
--- a/common/url_constants.cc
+++ b/common/url_constants.cc
@@ -15,3 +15,5 @@ const char kWidevineTOS[] = "https://policies.google.com/terms";
const char kRewardsUpholdSupport[] = "https://uphold.com/en/brave/support";
const char kP3ALearnMoreURL[] = "https://brave.com/P3A";
const char kP3ASettingsLink[] = "chrome://settings/privacy";
+const char kImportDataHelpURL[] =
+ "https://support.brave.com/hc/en-us/articles/360019782291-How-do-I-import-or-export-browsing-data-"; // NOLINT
diff --git a/common/url_constants.h b/common/url_constants.h
index 9ac085155ff4..d532716d3978 100644
--- a/common/url_constants.h
+++ b/common/url_constants.h
@@ -16,6 +16,7 @@ extern const char kWidevineTOS[];
extern const char kRewardsUpholdSupport[];
extern const char kP3ALearnMoreURL[];
extern const char kP3ASettingsLink[];
+extern const char kImportDataHelpURL[];
// This is introduced to replace |kDownloadChromeUrl| in
// outdated_upgrade_bubble_view.cc"
diff --git a/patches/chrome-browser-ui-webui-settings-settings_import_data_handler.cc.patch b/patches/chrome-browser-ui-webui-settings-settings_import_data_handler.cc.patch
index 3ba63a7776c6..1325aedc4f85 100644
--- a/patches/chrome-browser-ui-webui-settings-settings_import_data_handler.cc.patch
+++ b/patches/chrome-browser-ui-webui-settings-settings_import_data_handler.cc.patch
@@ -1,58 +1,20 @@
diff --git a/chrome/browser/ui/webui/settings/settings_import_data_handler.cc b/chrome/browser/ui/webui/settings/settings_import_data_handler.cc
-index b2e78bd722b68c0eca2962ee1f399d1edc8114f5..c10c90eb4dc47f966b68ee54effec0b3baf8005d 100644
+index b2e78bd722b68c0eca2962ee1f399d1edc8114f5..8c3bee44ed253354668a447034c2863cca00f59e 100644
--- a/chrome/browser/ui/webui/settings/settings_import_data_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_import_data_handler.cc
-@@ -18,6 +18,8 @@
- #include "base/strings/utf_string_conversions.h"
- #include "base/threading/thread_restrictions.h"
- #include "base/values.h"
-+#include "brave/browser/importer/brave_external_process_importer_host.h"
-+#include "brave/browser/importer/brave_profile_writer.h"
- #include "chrome/browser/browser_process.h"
- #include "chrome/browser/importer/external_process_importer_host.h"
- #include "chrome/browser/importer/importer_list.h"
-@@ -96,12 +98,12 @@ void ImportDataHandler::StartImport(
- base::Value(kImportStatusInProgress));
- import_did_succeed_ = false;
-
-- importer_host_ = new ExternalProcessImporterHost();
-+ importer_host_ = new BraveExternalProcessImporterHost();
- importer_host_->set_observer(this);
- Profile* profile = Profile::FromWebUI(web_ui());
- importer_host_->StartImportSettings(source_profile, profile,
- imported_items,
-- new ProfileWriter(profile));
-+ new BraveProfileWriter(profile));
-
- importer::LogImporterUseToMetrics("ImportDataHandler",
- source_profile.importer_type);
-@@ -126,6 +128,14 @@ void ImportDataHandler::ImportData(const base::ListValue* args) {
+@@ -126,6 +126,7 @@ void ImportDataHandler::ImportData(const base::ListValue* args) {
selected_items |= importer::PASSWORDS;
if (prefs->GetBoolean(prefs::kImportDialogSearchEngine))
selected_items |= importer::SEARCH_ENGINES;
-+ if (prefs->GetBoolean(prefs::kImportDialogCookies))
-+ selected_items |= importer::COOKIES;
-+ if (prefs->GetBoolean(prefs::kImportDialogStats))
-+ selected_items |= importer::STATS;
-+ if (prefs->GetBoolean(prefs::kImportDialogLedger))
-+ selected_items |= importer::LEDGER;
-+ if (prefs->GetBoolean(prefs::kImportDialogWindows))
-+ selected_items |= importer::WINDOWS;
++ ADD_BRAVE_SPECIFIC_IMPORTER_ITEMS
const importer::SourceProfile& source_profile =
importer_list_->GetSourceProfileAt(browser_index);
-@@ -179,6 +189,14 @@ void ImportDataHandler::SendBrowserProfileData(const std::string& callback_id) {
+@@ -179,6 +180,7 @@ void ImportDataHandler::SendBrowserProfileData(const std::string& callback_id) {
browser_profile->SetBoolean(
"autofillFormData",
(browser_services & importer::AUTOFILL_FORM_DATA) != 0);
-+ browser_profile->SetBoolean("cookies",
-+ (browser_services & importer::COOKIES) != 0);
-+ browser_profile->SetBoolean("stats",
-+ (browser_services & importer::STATS) != 0);
-+ browser_profile->SetBoolean("ledger",
-+ (browser_services & importer::LEDGER) != 0);
-+ browser_profile->SetBoolean("windows",
-+ (browser_services & importer::WINDOWS) != 0);
++ SET_BRAVE_SPECIFIC_IMPORTER_DATA
browser_profiles.Append(std::move(browser_profile));
}
diff --git a/patches/chrome-browser-ui-webui-settings-settings_import_data_handler.h.patch b/patches/chrome-browser-ui-webui-settings-settings_import_data_handler.h.patch
new file mode 100644
index 000000000000..45369772c22d
--- /dev/null
+++ b/patches/chrome-browser-ui-webui-settings-settings_import_data_handler.h.patch
@@ -0,0 +1,12 @@
+diff --git a/chrome/browser/ui/webui/settings/settings_import_data_handler.h b/chrome/browser/ui/webui/settings/settings_import_data_handler.h
+index 68c9c7519e570aaa8550c2257f76e950b3cd7981..5029fb788f02fed505d607ae2f6114b0af5904fd 100644
+--- a/chrome/browser/ui/webui/settings/settings_import_data_handler.h
++++ b/chrome/browser/ui/webui/settings/settings_import_data_handler.h
+@@ -34,6 +34,7 @@ class ImportDataHandler : public SettingsPageUIHandler,
+ void OnJavascriptAllowed() override {}
+ void OnJavascriptDisallowed() override;
+
++ BRAVE_IMPORT_DATA_HANDLER_H
+ private:
+ void StartImport(const importer::SourceProfile& source_profile,
+ uint16_t imported_items);