Skip to content

Commit

Permalink
Show dialog when Brave tries to import Safari data w/o disk permission
Browse files Browse the repository at this point in the history
  • Loading branch information
simonhong committed Feb 12, 2020
1 parent ad8f5db commit 219206f
Show file tree
Hide file tree
Showing 11 changed files with 347 additions and 43 deletions.
9 changes: 9 additions & 0 deletions app/brave_generated_resources.grd
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,15 @@ By installing this extension, you are agreeing to the Google Widevine Terms of U
<message name="IDS_BRAVE_BOOKMARK_MANAGER_EMPTY_LIST" desc="">
To add a bookmark, click the bookmark button next to the address bar
</message>
<message name="IDS_FULL_DISK_ACCESS_CONFIRM_DIALOG_TITLE" desc="The label for full disk access dialog title">
Full Disk access required
</message>
<message name="IDS_FULL_DISK_ACCESS_CONFIRM_DIALOG_MESSAGE" desc="The label for full disk access dialog message">
Brave needs full disk access to import browsing data from Safari.
</message>
<message name="IDS_FULL_DISK_ACCESS_CONFIRM_DIALOG_LINK_TEXT" desc="The label for full disk access dialog link text">
Learn how to grant Full Disk Access
</message>
</messages>
</release>
</grit>
8 changes: 8 additions & 0 deletions browser/ui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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
Expand Down
55 changes: 55 additions & 0 deletions browser/ui/webui/settings/brave_settings_import_data_handler.h
Original file line number Diff line number Diff line change
@@ -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<BraveImportDataHandler> weak_factory_;
};

} // namespace settings

#endif // BRAVE_BROWSER_UI_WEBUI_SETTINGS_BRAVE_SETTINGS_IMPORT_DATA_HANDLER_H_
186 changes: 186 additions & 0 deletions browser/ui/webui/settings/brave_settings_import_data_handler.mm
Original file line number Diff line number Diff line change
@@ -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<FullDiskAccessConfirmDialogDelegate>(
web_contents,
chrome::FindBrowserWithWebContents(web_contents)),
web_contents);
}

} // namespace settings
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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_
13 changes: 13 additions & 0 deletions chromium_src/chrome/browser/ui/webui/settings/settings_ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 2 additions & 0 deletions common/url_constants.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions common/url_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Loading

0 comments on commit 219206f

Please sign in to comment.