diff --git a/app/brave_generated_resources.grd b/app/brave_generated_resources.grd
index f3cb0ac58a4..b0b7139d0de 100644
--- a/app/brave_generated_resources.grd
+++ b/app/brave_generated_resources.grd
@@ -100,6 +100,13 @@
By installing this extension, you are agreeing to the Google Widevine Terms of Use. You agree that Brave is not responsible for any damages or losses in connection with your use of Google Widevine.
+
+
+ Brave
+
+
+ Imported From Brave
+
diff --git a/common/BUILD.gn b/common/BUILD.gn
index 9c214516a9d..0870b457526 100644
--- a/common/BUILD.gn
+++ b/common/BUILD.gn
@@ -10,6 +10,8 @@ source_set("common") {
"extensions/extension_constants.h",
"extensions/manifest_handlers/pdfjs_manifest_override.cc",
"extensions/manifest_handlers/pdfjs_manifest_override.h",
+ "importer/brave_importer_utils.cc",
+ "importer/brave_importer_utils.h",
"importer/chrome_importer_utils.cc",
"importer/chrome_importer_utils.h",
"network_constants.cc",
@@ -33,6 +35,7 @@ source_set("common") {
if (is_mac) {
sources += [
+ "importer/brave_importer_utils_mac.mm",
"importer/chrome_importer_utils_mac.mm",
]
}
@@ -41,6 +44,7 @@ source_set("common") {
sources += [
"brave_channel_info_posix.cc",
"brave_channel_info_posix.h",
+ "importer/brave_importer_utils_linux.cc",
"importer/chrome_importer_utils_linux.cc",
]
@@ -51,6 +55,7 @@ source_set("common") {
if (is_win) {
sources += [
+ "importer/brave_importer_utils_win.cc",
"importer/chrome_importer_utils_win.cc",
]
}
diff --git a/common/importer/brave_importer_utils.cc b/common/importer/brave_importer_utils.cc
new file mode 100644
index 00000000000..49d34bb79d9
--- /dev/null
+++ b/common/importer/brave_importer_utils.cc
@@ -0,0 +1,39 @@
+/* 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/common/importer/brave_importer_utils.h"
+
+#include
+#include
+
+#include "base/files/file_util.h"
+#include "base/json/json_reader.h"
+#include "base/values.h"
+#include "chrome/common/importer/importer_data_types.h"
+
+bool BraveImporterCanImport(const base::FilePath& profile,
+ uint16_t* services_supported) {
+ DCHECK(services_supported);
+ *services_supported = importer::NONE;
+
+ base::FilePath history =
+ profile.Append(base::FilePath::StringType(FILE_PATH_LITERAL("History")));
+ base::FilePath session_store =
+ profile.Append(base::FilePath::StringType(FILE_PATH_LITERAL("session-store-1")));
+ base::FilePath passwords =
+ profile.Append(base::FilePath::StringType(FILE_PATH_LITERAL("Login Data")));
+ base::FilePath cookies =
+ profile.Append(base::FilePath::StringType(FILE_PATH_LITERAL("Cookies")));
+
+ if (base::PathExists(history))
+ *services_supported |= importer::HISTORY;
+ if (base::PathExists(session_store))
+ *services_supported |= importer::FAVORITES;
+ if (base::PathExists(passwords))
+ *services_supported |= importer::PASSWORDS;
+ if (base::PathExists(cookies))
+ *services_supported |= importer::COOKIES;
+
+ return *services_supported != importer::NONE;
+}
diff --git a/common/importer/brave_importer_utils.h b/common/importer/brave_importer_utils.h
new file mode 100644
index 00000000000..ee902a27528
--- /dev/null
+++ b/common/importer/brave_importer_utils.h
@@ -0,0 +1,26 @@
+/* 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_COMMON_IMPORTER_BRAVE_IMPORTER_UTILS_H_
+#define BRAVE_COMMON_IMPORTER_BRAVE_IMPORTER_UTILS_H_
+
+#include
+
+#include
+
+namespace base {
+class DictionaryValue;
+class FilePath;
+class ListValue;
+}
+
+base::FilePath GetBraveUserDataFolder();
+
+base::ListValue* GetBraveSourceProfiles(
+ const base::FilePath& user_data_folder);
+
+bool BraveImporterCanImport(const base::FilePath& profile,
+ uint16_t* services_supported);
+
+#endif // BRAVE_COMMON_IMPORTER_BRAVE_IMPORTER_UTILS_H_
diff --git a/common/importer/brave_importer_utils_linux.cc b/common/importer/brave_importer_utils_linux.cc
new file mode 100644
index 00000000000..28ba6e91050
--- /dev/null
+++ b/common/importer/brave_importer_utils_linux.cc
@@ -0,0 +1,25 @@
+/* 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/common/importer/brave_importer_utils.h"
+
+#include "base/base_paths.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/path_service.h"
+
+base::FilePath GetBraveUserDataFolder() {
+ base::FilePath home;
+ if (!PathService::Get(base::DIR_HOME, &home))
+ return base::FilePath();
+
+ base::FilePath result = home;
+
+ // If Brave is installed via Snap, use the sandboxed home directory.
+ if (base::PathExists(base::FilePath("/snap/bin/brave"))) {
+ result = result.Append("snap").Append("brave").Append("current");
+ }
+
+ return result.Append(".config").Append("brave");
+}
diff --git a/common/importer/brave_importer_utils_mac.mm b/common/importer/brave_importer_utils_mac.mm
new file mode 100644
index 00000000000..886b28eb0ea
--- /dev/null
+++ b/common/importer/brave_importer_utils_mac.mm
@@ -0,0 +1,16 @@
+/* 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
+#include
+
+#include "brave/common/importer/brave_importer_utils.h"
+
+#include "base/files/file_util.h"
+#include "base/mac/foundation_util.h"
+
+base::FilePath GetBraveUserDataFolder() {
+ base::FilePath result = base::mac::GetUserLibraryPath();
+ return result.Append("Application Support").Append("brave");
+}
diff --git a/common/importer/brave_importer_utils_win.cc b/common/importer/brave_importer_utils_win.cc
new file mode 100644
index 00000000000..b1c3b4438d9
--- /dev/null
+++ b/common/importer/brave_importer_utils_win.cc
@@ -0,0 +1,19 @@
+/* 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/common/importer/brave_importer_utils.h"
+
+#include "base/files/file_util.h"
+#include "base/path_service.h"
+#include "base/strings/string16.h"
+
+base::FilePath GetBraveUserDataFolder() {
+ base::FilePath result;
+ if (!PathService::Get(base::DIR_APP_DATA, &result))
+ return base::FilePath();
+
+ result = result.AppendASCII("brave");
+
+ return result;
+}
diff --git a/patches/chrome-browser-importer-external_process_importer_client.cc.patch b/patches/chrome-browser-importer-external_process_importer_client.cc.patch
new file mode 100644
index 00000000000..087f7852f4e
--- /dev/null
+++ b/patches/chrome-browser-importer-external_process_importer_client.cc.patch
@@ -0,0 +1,22 @@
+diff --git a/chrome/browser/importer/external_process_importer_client.cc b/chrome/browser/importer/external_process_importer_client.cc
+index 429c16dc6a56fcd0ea1d674508c1927a387e1905..0f29ba75ffce20b1104e36b4ba1aa78fd28fc50a 100644
+--- a/chrome/browser/importer/external_process_importer_client.cc
++++ b/chrome/browser/importer/external_process_importer_client.cc
+@@ -8,6 +8,7 @@
+
+ #include "base/bind.h"
+ #include "base/strings/string_number_conversions.h"
++#include "brave/grit/generated_resources.h"
+ #include "build/build_config.h"
+ #include "chrome/browser/importer/external_process_importer_host.h"
+ #include "chrome/browser/importer/in_process_importer_bridge.h"
+@@ -71,6 +72,9 @@ void ExternalProcessImporterClient::Start() {
+ localized_strings.SetKey(
+ base::IntToString(IDS_BOOKMARK_BAR_FOLDER_NAME),
+ base::Value(l10n_util::GetStringUTF8(IDS_BOOKMARK_BAR_FOLDER_NAME)));
++ localized_strings.SetKey(
++ base::IntToString(IDS_IMPORT_FROM_BRAVE),
++ base::Value(l10n_util::GetStringUTF8(IDS_IMPORT_FROM_BRAVE)));
+
+ // If the utility process hasn't started yet the message will queue until it
+ // does.
diff --git a/patches/chrome-browser-importer-importer_list.cc.patch b/patches/chrome-browser-importer-importer_list.cc.patch
index c16da570a38..537cd087a0a 100644
--- a/patches/chrome-browser-importer-importer_list.cc.patch
+++ b/patches/chrome-browser-importer-importer_list.cc.patch
@@ -1,8 +1,8 @@
diff --git a/chrome/browser/importer/importer_list.cc b/chrome/browser/importer/importer_list.cc
-index 3bf47fa746e2a417f89201f3e3800d8639f2e323..122e9daf552834db4d41c77a320332305320696b 100644
+index 3bf47fa746e2a417f89201f3e3800d8639f2e323..80d681f20de36650d2d2b3fb000c71687656140e 100644
--- a/chrome/browser/importer/importer_list.cc
+++ b/chrome/browser/importer/importer_list.cc
-@@ -7,9 +7,12 @@
+@@ -7,9 +7,14 @@
#include
#include "base/bind.h"
@@ -11,11 +11,13 @@ index 3bf47fa746e2a417f89201f3e3800d8639f2e323..122e9daf552834db4d41c77a32033230
#include "base/task_scheduler/task_traits.h"
#include "base/threading/thread_restrictions.h"
+#include "base/values.h"
++#include "brave/common/importer/brave_importer_utils.h"
+#include "brave/common/importer/chrome_importer_utils.h"
++#include "brave/grit/generated_resources.h"
#include "build/build_config.h"
#include "chrome/browser/shell_integration.h"
#include "chrome/common/importer/firefox_importer_utils.h"
-@@ -124,6 +127,61 @@ void DetectFirefoxProfiles(const std::string locale,
+@@ -124,6 +129,79 @@ void DetectFirefoxProfiles(const std::string locale,
profiles->push_back(firefox);
}
@@ -73,27 +75,50 @@ index 3bf47fa746e2a417f89201f3e3800d8639f2e323..122e9daf552834db4d41c77a32033230
+ AddChromeToProfiles(profiles, chromium_profiles, chromium_user_data_folder,
+ brandChromium);
+}
++
++void DetectBraveProfiles(std::vector* profiles) {
++ base::AssertBlockingAllowed();
++
++ base::FilePath brave_user_data_folder = GetBraveUserDataFolder();
++
++ uint16_t items = importer::NONE;
++ if (!BraveImporterCanImport(brave_user_data_folder, &items))
++ return;
++
++ importer::SourceProfile brave;
++ brave.importer_name =
++ l10n_util::GetStringUTF16(IDS_IMPORT_FROM_BRAVE);
++ brave.importer_type = importer::TYPE_BRAVE;
++ brave.services_supported = items;
++ brave.source_path = brave_user_data_folder;
++ profiles->push_back(brave);
++}
+
std::vector DetectSourceProfilesWorker(
const std::string& locale,
bool include_interactive_profiles) {
-@@ -137,20 +195,30 @@ std::vector DetectSourceProfilesWorker(
+@@ -136,21 +214,37 @@ std::vector DetectSourceProfilesWorker(
+ #if defined(OS_WIN)
if (shell_integration::IsFirefoxDefaultBrowser()) {
DetectFirefoxProfiles(locale, &profiles);
++ DetectBraveProfiles(&profiles);
DetectBuiltinWindowsProfiles(&profiles);
+ DetectChromeProfiles(&profiles);
} else {
DetectBuiltinWindowsProfiles(&profiles);
++ DetectBraveProfiles(&profiles);
DetectFirefoxProfiles(locale, &profiles);
+ DetectChromeProfiles(&profiles);
}
#elif defined(OS_MACOSX)
if (shell_integration::IsFirefoxDefaultBrowser()) {
DetectFirefoxProfiles(locale, &profiles);
++ DetectBraveProfiles(&profiles);
DetectSafariProfiles(&profiles);
+ DetectChromeProfiles(&profiles);
} else {
DetectSafariProfiles(&profiles);
++ DetectBraveProfiles(&profiles);
DetectFirefoxProfiles(locale, &profiles);
+ DetectChromeProfiles(&profiles);
}
@@ -101,8 +126,10 @@ index 3bf47fa746e2a417f89201f3e3800d8639f2e323..122e9daf552834db4d41c77a32033230
- DetectFirefoxProfiles(locale, &profiles);
+ if (shell_integration::IsFirefoxDefaultBrowser()) {
+ DetectFirefoxProfiles(locale, &profiles);
++ DetectBraveProfiles(&profiles);
+ DetectChromeProfiles(&profiles);
+ } else {
++ DetectBraveProfiles(&profiles);
+ DetectChromeProfiles(&profiles);
+ DetectFirefoxProfiles(locale, &profiles);
+ }
diff --git a/patches/chrome-browser-importer-importer_uma.cc.patch b/patches/chrome-browser-importer-importer_uma.cc.patch
index 7c227f864b5..a19bb587731 100644
--- a/patches/chrome-browser-importer-importer_uma.cc.patch
+++ b/patches/chrome-browser-importer-importer_uma.cc.patch
@@ -1,13 +1,16 @@
diff --git a/chrome/browser/importer/importer_uma.cc b/chrome/browser/importer/importer_uma.cc
-index da87e84ffe7c2193ea16d24f1ee1174c51c9503f..261dd432b1759b4e62c5ee2b2b0a6e27a688700d 100644
+index da87e84ffe7c2193ea16d24f1ee1174c51c9503f..fb80acdfd3997df06189334a8575f39431bf9bd9 100644
--- a/chrome/browser/importer/importer_uma.cc
+++ b/chrome/browser/importer/importer_uma.cc
-@@ -59,6 +59,9 @@ void LogImporterUseToMetrics(const std::string& metric_postfix,
+@@ -59,6 +59,12 @@ void LogImporterUseToMetrics(const std::string& metric_postfix,
case TYPE_BOOKMARKS_FILE:
metrics_type = IMPORTER_METRICS_BOOKMARKS_FILE;
break;
+ case TYPE_CHROME:
+ // TODO: Wire this up if we want to record metrics on users who import from Chrome
++ break;
++ case TYPE_BRAVE:
++ // TODO: Wire this up if we want to record metrics on users who import from Brave
+ break;
}
diff --git a/patches/chrome-browser-importer-in_process_importer_bridge.cc.patch b/patches/chrome-browser-importer-in_process_importer_bridge.cc.patch
index 911841d2683..9828b119149 100644
--- a/patches/chrome-browser-importer-in_process_importer_bridge.cc.patch
+++ b/patches/chrome-browser-importer-in_process_importer_bridge.cc.patch
@@ -1,13 +1,15 @@
diff --git a/chrome/browser/importer/in_process_importer_bridge.cc b/chrome/browser/importer/in_process_importer_bridge.cc
-index 5832fa66c715fe82a3e865c7bde490ef6f6b14b6..5e345a533beef357ee9e0e5509074ec997daa9fa 100644
+index 5832fa66c715fe82a3e865c7bde490ef6f6b14b6..acebdad31c6c1b53b8d51b37daa1a9373f4a9158 100644
--- a/chrome/browser/importer/in_process_importer_bridge.cc
+++ b/chrome/browser/importer/in_process_importer_bridge.cc
-@@ -59,6 +59,8 @@ history::VisitSource ConvertImporterVisitSourceToHistoryVisitSource(
+@@ -59,6 +59,10 @@ history::VisitSource ConvertImporterVisitSourceToHistoryVisitSource(
return history::SOURCE_IE_IMPORTED;
case importer::VISIT_SOURCE_SAFARI_IMPORTED:
return history::SOURCE_SAFARI_IMPORTED;
+ case importer::VISIT_SOURCE_CHROME_IMPORTED:
+ return history::SOURCE_CHROME_IMPORTED;
++ case importer::VISIT_SOURCE_BRAVE_IMPORTED:
++ return history::SOURCE_BRAVE_IMPORTED;
}
NOTREACHED();
return history::SOURCE_SYNCED;
diff --git a/patches/chrome-common-importer-importer_data_types.h.patch b/patches/chrome-common-importer-importer_data_types.h.patch
index 59ec6f09b21..d219322d875 100644
--- a/patches/chrome-common-importer-importer_data_types.h.patch
+++ b/patches/chrome-common-importer-importer_data_types.h.patch
@@ -1,12 +1,13 @@
diff --git a/chrome/common/importer/importer_data_types.h b/chrome/common/importer/importer_data_types.h
-index 0fc90c62398a93eb89568ce78c8ded2bc9b232b6..50a7d3c0079b7e9c5bc38a4ae3b25eef6d024169 100644
+index 0fc90c62398a93eb89568ce78c8ded2bc9b232b6..cd3301cdbab878231050dbdf66d4572852d0a331 100644
--- a/chrome/common/importer/importer_data_types.h
+++ b/chrome/common/importer/importer_data_types.h
-@@ -83,6 +83,7 @@ enum VisitSource {
+@@ -83,6 +83,8 @@ enum VisitSource {
VISIT_SOURCE_FIREFOX_IMPORTED = 1,
VISIT_SOURCE_IE_IMPORTED = 2,
VISIT_SOURCE_SAFARI_IMPORTED = 3,
+ VISIT_SOURCE_CHROME_IMPORTED = 4,
++ VISIT_SOURCE_BRAVE_IMPORTED = 5,
};
} // namespace importer
diff --git a/patches/chrome-common-importer-importer_type.h.patch b/patches/chrome-common-importer-importer_type.h.patch
index bff88819eec..78b8ff5431a 100644
--- a/patches/chrome-common-importer-importer_type.h.patch
+++ b/patches/chrome-common-importer-importer_type.h.patch
@@ -1,8 +1,8 @@
diff --git a/chrome/common/importer/importer_type.h b/chrome/common/importer/importer_type.h
-index c172f8a5bc534465ff4d063a52f9bb510b7e36af..f1252eb63f413e2135202236ca40d05f129a6c7a 100644
+index c172f8a5bc534465ff4d063a52f9bb510b7e36af..88d54c3bcc91f6d2975a3c3e040cb14d20bfbfeb 100644
--- a/chrome/common/importer/importer_type.h
+++ b/chrome/common/importer/importer_type.h
-@@ -19,6 +19,8 @@ enum ImporterType {
+@@ -19,11 +19,15 @@ enum ImporterType {
TYPE_IE = 0,
#endif
// Value 1 was the (now deleted) Firefox 2 profile importer.
@@ -11,3 +11,10 @@ index c172f8a5bc534465ff4d063a52f9bb510b7e36af..f1252eb63f413e2135202236ca40d05f
TYPE_FIREFOX = 2,
#if defined(OS_MACOSX)
TYPE_SAFARI = 3,
+ #endif
+ // Value 4 was the (now deleted) Google Toolbar importer.
++ // We use it for the Brave profile importer now.
++ TYPE_BRAVE = 4,
+ TYPE_BOOKMARKS_FILE = 5, // Identifies a 'bookmarks.html' file.
+ #if defined(OS_WIN)
+ TYPE_EDGE = 6,
diff --git a/patches/chrome-utility-importer-importer_creator.cc.patch b/patches/chrome-utility-importer-importer_creator.cc.patch
index 108cb3bf137..c657d857f9f 100644
--- a/patches/chrome-utility-importer-importer_creator.cc.patch
+++ b/patches/chrome-utility-importer-importer_creator.cc.patch
@@ -1,21 +1,24 @@
diff --git a/chrome/utility/importer/importer_creator.cc b/chrome/utility/importer/importer_creator.cc
-index 2bef627aa890484a3fb75fa9bd04b2994f997305..90214ae7659f57971f66119bede4bd7dd34a30f3 100644
+index 2bef627aa890484a3fb75fa9bd04b2994f997305..48b0ce819af1ad86b5ae19ba778dcae79560bae9 100644
--- a/chrome/utility/importer/importer_creator.cc
+++ b/chrome/utility/importer/importer_creator.cc
-@@ -5,6 +5,7 @@
+@@ -5,6 +5,8 @@
#include "chrome/utility/importer/importer_creator.h"
#include "base/logging.h"
++#include "brave/utility/importer/brave_importer.h"
+#include "brave/utility/importer/chrome_importer.h"
#include "build/build_config.h"
#include "chrome/utility/importer/bookmarks_file_importer.h"
#include "chrome/utility/importer/firefox_importer.h"
-@@ -43,6 +44,8 @@ scoped_refptr CreateImporterByType(ImporterType type) {
+@@ -43,6 +45,10 @@ scoped_refptr CreateImporterByType(ImporterType type) {
case TYPE_SAFARI:
return new SafariImporter(base::mac::GetUserLibraryPath());
#endif
+ case TYPE_CHROME:
+ return new ChromeImporter();
++ case TYPE_BRAVE:
++ return new BraveImporter();
default:
NOTREACHED();
return nullptr;
diff --git a/patches/chrome-utility-importer-profile_import_impl.cc.patch b/patches/chrome-utility-importer-profile_import_impl.cc.patch
index ac625a1f413..49bb202b5d3 100644
--- a/patches/chrome-utility-importer-profile_import_impl.cc.patch
+++ b/patches/chrome-utility-importer-profile_import_impl.cc.patch
@@ -1,5 +1,5 @@
diff --git a/chrome/utility/importer/profile_import_impl.cc b/chrome/utility/importer/profile_import_impl.cc
-index 1cbcc2fcb663c43daad9e6ad86f97e74b964aa11..2910707b7f569cb87947c81d8522f1d9fad82014 100644
+index 1cbcc2fcb663c43daad9e6ad86f97e74b964aa11..ec1c8c3d159c84e8e757dcb84a2766dc7f54851a 100644
--- a/chrome/utility/importer/profile_import_impl.cc
+++ b/chrome/utility/importer/profile_import_impl.cc
@@ -2,12 +2,16 @@
@@ -19,7 +19,7 @@ index 1cbcc2fcb663c43daad9e6ad86f97e74b964aa11..2910707b7f569cb87947c81d8522f1d9
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
-@@ -39,6 +43,16 @@ void ProfileImportImpl::StartImport(
+@@ -39,6 +43,19 @@ void ProfileImportImpl::StartImport(
items_to_import_ = items;
@@ -31,12 +31,15 @@ index 1cbcc2fcb663c43daad9e6ad86f97e74b964aa11..2910707b7f569cb87947c81d8522f1d9
+ } else if (base::StartsWith(base::UTF16ToUTF8(source_profile.importer_name),
+ "Chromium", base::CompareCase::SENSITIVE)) {
+ command_line->AppendSwitch("import-chromium");
++ } else if (base::StartsWith(base::UTF16ToUTF8(source_profile.importer_name),
++ "Brave", base::CompareCase::SENSITIVE)) {
++ command_line->AppendSwitch("import-brave");
+ }
+
// Create worker thread in which importer runs.
import_thread_.reset(new base::Thread("import_thread"));
#if defined(OS_WIN)
-@@ -48,7 +62,7 @@ void ProfileImportImpl::StartImport(
+@@ -48,7 +65,7 @@ void ProfileImportImpl::StartImport(
NOTREACHED();
ImporterCleanup();
}
diff --git a/patches/components-history-core-browser-history_types.h.patch b/patches/components-history-core-browser-history_types.h.patch
index 67c12779a07..54e60a44e38 100644
--- a/patches/components-history-core-browser-history_types.h.patch
+++ b/patches/components-history-core-browser-history_types.h.patch
@@ -1,12 +1,13 @@
diff --git a/components/history/core/browser/history_types.h b/components/history/core/browser/history_types.h
-index ff27b0d74068df5f661bdb6ceb25cff6f61f1ed6..49738a07a4ae0faa11ee73b6004e8869322bdff5 100644
+index ff27b0d74068df5f661bdb6ceb25cff6f61f1ed6..356614a0949e13c0864ea9a8ee96adcc542d9421 100644
--- a/components/history/core/browser/history_types.h
+++ b/components/history/core/browser/history_types.h
-@@ -55,6 +55,7 @@ enum VisitSource {
+@@ -55,6 +55,8 @@ enum VisitSource {
SOURCE_FIREFOX_IMPORTED = 3,
SOURCE_IE_IMPORTED = 4,
SOURCE_SAFARI_IMPORTED = 5,
+ SOURCE_CHROME_IMPORTED = 6,
++ SOURCE_BRAVE_IMPORTED = 7,
};
typedef int64_t VisitID;
diff --git a/patches/components-os_crypt-key_storage_keyring.cc.patch b/patches/components-os_crypt-key_storage_keyring.cc.patch
index 6e8ecf3b51f..e4e3ec3f239 100644
--- a/patches/components-os_crypt-key_storage_keyring.cc.patch
+++ b/patches/components-os_crypt-key_storage_keyring.cc.patch
@@ -1,5 +1,5 @@
diff --git a/components/os_crypt/key_storage_keyring.cc b/components/os_crypt/key_storage_keyring.cc
-index af2f64b34ddb8e49d72dd0dd22ffd2418a422efb..9db6e47b35e6cac14168908a4385120fe44cb8d0 100644
+index af2f64b34ddb8e49d72dd0dd22ffd2418a422efb..ba7380e307740690ea2f3b626d24715e2c707fc0 100644
--- a/components/os_crypt/key_storage_keyring.cc
+++ b/components/os_crypt/key_storage_keyring.cc
@@ -6,6 +6,7 @@
@@ -19,7 +19,7 @@ index af2f64b34ddb8e49d72dd0dd22ffd2418a422efb..9db6e47b35e6cac14168908a4385120f
#endif
const GnomeKeyringPasswordSchema kSchema = {
-@@ -45,9 +46,18 @@ std::string KeyStorageKeyring::GetKeyImpl() {
+@@ -45,9 +46,19 @@ std::string KeyStorageKeyring::GetKeyImpl() {
std::string password;
gchar* password_c = nullptr;
@@ -27,7 +27,8 @@ index af2f64b34ddb8e49d72dd0dd22ffd2418a422efb..9db6e47b35e6cac14168908a4385120f
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch("import-chrome")) {
+ application_name = "chrome";
-+ } else if (command_line->HasSwitch("import-chromium")) {
++ } else if (command_line->HasSwitch("import-chromium") ||
++ command_line->HasSwitch("import-brave")) {
+ application_name = "chromium";
+ } else {
+ application_name = kApplicationName;
diff --git a/patches/components-os_crypt-key_storage_kwallet.cc.patch b/patches/components-os_crypt-key_storage_kwallet.cc.patch
index 755545287b3..b2c8eb90ac1 100644
--- a/patches/components-os_crypt-key_storage_kwallet.cc.patch
+++ b/patches/components-os_crypt-key_storage_kwallet.cc.patch
@@ -1,5 +1,5 @@
diff --git a/components/os_crypt/key_storage_kwallet.cc b/components/os_crypt/key_storage_kwallet.cc
-index aa4b3d4a6b5c7b1f725d6446ea5e573094ec935b..4c4c7191a57afc7a42dfa87701578bd99d417d94 100644
+index aa4b3d4a6b5c7b1f725d6446ea5e573094ec935b..8e1ac53bccaf2213466af3daf685ee88f3253f11 100644
--- a/components/os_crypt/key_storage_kwallet.cc
+++ b/components/os_crypt/key_storage_kwallet.cc
@@ -7,6 +7,7 @@
@@ -10,7 +10,7 @@ index aa4b3d4a6b5c7b1f725d6446ea5e573094ec935b..4c4c7191a57afc7a42dfa87701578bd9
#include "base/rand_util.h"
#include "components/os_crypt/kwallet_dbus.h"
#include "dbus/bus.h"
-@@ -90,11 +91,24 @@ std::string KeyStorageKWallet::GetKeyImpl() {
+@@ -90,11 +91,25 @@ std::string KeyStorageKWallet::GetKeyImpl() {
if (!InitFolder())
return std::string();
@@ -19,7 +19,8 @@ index aa4b3d4a6b5c7b1f725d6446ea5e573094ec935b..4c4c7191a57afc7a42dfa87701578bd9
+ if (command_line->HasSwitch("import-chrome")) {
+ folder_name = "Chrome Keys";
+ key = "Chrome Safe Storage";
-+ } else if (command_line->HasSwitch("import-chromium")) {
++ } else if (command_line->HasSwitch("import-chromium") ||
++ command_line->HasSwitch("import-brave")) {
+ folder_name = "Chromium Keys";
+ key = "Chromium Safe Storage";
+ } else {
@@ -37,7 +38,7 @@ index aa4b3d4a6b5c7b1f725d6446ea5e573094ec935b..4c4c7191a57afc7a42dfa87701578bd9
if (error)
return std::string();
-@@ -114,8 +128,17 @@ std::string KeyStorageKWallet::GetKeyImpl() {
+@@ -114,8 +129,18 @@ std::string KeyStorageKWallet::GetKeyImpl() {
bool KeyStorageKWallet::InitFolder() {
bool has_folder = false;
@@ -45,7 +46,8 @@ index aa4b3d4a6b5c7b1f725d6446ea5e573094ec935b..4c4c7191a57afc7a42dfa87701578bd9
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch("import-chrome")) {
+ folder_name = "Chrome Keys";
-+ } else if (command_line->HasSwitch("import-chromium")) {
++ } else if (command_line->HasSwitch("import-chromium") ||
++ command_line->HasSwitch("import-brave")) {
+ folder_name = "Chromium Keys";
+ } else {
+ folder_name = KeyStorageLinux::kFolderName;
diff --git a/patches/components-os_crypt-key_storage_libsecret.cc.patch b/patches/components-os_crypt-key_storage_libsecret.cc.patch
index 0e2c8f416b0..076f5ac4449 100644
--- a/patches/components-os_crypt-key_storage_libsecret.cc.patch
+++ b/patches/components-os_crypt-key_storage_libsecret.cc.patch
@@ -1,5 +1,5 @@
diff --git a/components/os_crypt/key_storage_libsecret.cc b/components/os_crypt/key_storage_libsecret.cc
-index a1b5b975bc89c4891643adab17ce0b00ba2a8032..9d4be365463d2555101a96006ca4c68a61b7e886 100644
+index a1b5b975bc89c4891643adab17ce0b00ba2a8032..7d5b3200f1b6ac3f99b536767281f761b9ad8193 100644
--- a/components/os_crypt/key_storage_libsecret.cc
+++ b/components/os_crypt/key_storage_libsecret.cc
@@ -5,6 +5,7 @@
@@ -19,7 +19,7 @@ index a1b5b975bc89c4891643adab17ce0b00ba2a8032..9d4be365463d2555101a96006ca4c68a
#endif
// Deprecated in M55 (crbug.com/639298)
-@@ -73,7 +74,16 @@ std::string KeyStorageLibsecret::AddRandomPasswordInLibsecret() {
+@@ -73,7 +74,17 @@ std::string KeyStorageLibsecret::AddRandomPasswordInLibsecret() {
std::string KeyStorageLibsecret::GetKeyImpl() {
LibsecretAttributesBuilder attrs;
@@ -28,7 +28,8 @@ index a1b5b975bc89c4891643adab17ce0b00ba2a8032..9d4be365463d2555101a96006ca4c68a
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch("import-chrome")) {
+ application_name = "chrome";
-+ } else if (command_line->HasSwitch("import-chromium")) {
++ } else if (command_line->HasSwitch("import-chromium") ||
++ command_line->HasSwitch("import-brave")) {
+ application_name = "chromium";
+ } else {
+ application_name = kApplicationName;
diff --git a/patches/components-os_crypt-keychain_password_mac.mm.patch b/patches/components-os_crypt-keychain_password_mac.mm.patch
index cb47d14fca1..7df4b0de008 100644
--- a/patches/components-os_crypt-keychain_password_mac.mm.patch
+++ b/patches/components-os_crypt-keychain_password_mac.mm.patch
@@ -1,5 +1,5 @@
diff --git a/components/os_crypt/keychain_password_mac.mm b/components/os_crypt/keychain_password_mac.mm
-index 2b38db266f9aa1f4141c8649c021042ede4e5589..4b14f15e5091b251be53eff29139beaa59a93dbc 100644
+index 2b38db266f9aa1f4141c8649c021042ede4e5589..442defb6f2d9ee129ca5c01ccd360d626934a9d3 100644
--- a/components/os_crypt/keychain_password_mac.mm
+++ b/components/os_crypt/keychain_password_mac.mm
@@ -7,6 +7,7 @@
@@ -10,7 +10,7 @@ index 2b38db266f9aa1f4141c8649c021042ede4e5589..4b14f15e5091b251be53eff29139beaa
#include "base/mac/mac_logging.h"
#include "base/rand_util.h"
#include "crypto/apple_keychain.h"
-@@ -54,11 +55,23 @@ std::string AddRandomPasswordToKeychain(const AppleKeychain& keychain,
+@@ -54,11 +55,24 @@
const char KeychainPassword::service_name[] = "Chrome Safe Storage";
const char KeychainPassword::account_name[] = "Chrome";
#else
@@ -26,7 +26,8 @@ index 2b38db266f9aa1f4141c8649c021042ede4e5589..4b14f15e5091b251be53eff29139beaa
+ if (command_line->HasSwitch("import-chrome")) {
+ service_name = "Chrome Safe Storage";
+ account_name = "Chrome";
-+ } else if (command_line->HasSwitch("import-chromium")) {
++ } else if (command_line->HasSwitch("import-chromium") ||
++ command_line->HasSwitch("import-brave")) {
+ service_name = "Chromium Safe Storage";
+ account_name = "Chromium";
+ } else {
diff --git a/test/BUILD.gn b/test/BUILD.gn
index 6726a6b936c..8b02269565c 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -41,6 +41,7 @@ test("brave_unit_tests") {
"//chrome/common/importer/mock_importer_bridge.h",
"../browser/importer/chrome_profile_lock_unittest.cc",
"../utility/importer/chrome_importer_unittest.cc",
+ "../utility/importer/brave_importer_unittest.cc",
]
# On Windows, brave_install_static_unittests covers channel test.
diff --git a/test/data/import/brave-browser-laptop/README b/test/data/import/brave-browser-laptop/README
new file mode 100644
index 00000000000..1a84c20b032
--- /dev/null
+++ b/test/data/import/brave-browser-laptop/README
@@ -0,0 +1,9 @@
+Since Brave browser-laptop is based on Chromium (via Muon/Electron), most of the notes from the ChromeImporter test data README (`../chrome/README`) are also applicable here.
+
+# Generating test data
+
+Unlike Chrome/Chromium, Brave browser-laptop does not support multiple profiles, so if you use Brave as your regular web browser, it may not be immediately obvious how you can create a separate profile for the purpose of generating test data. I found the least obtrusive method to be setting the CHROME_USER_DATA_DIR environment variable, e.g. on macOS:
+
+ TEST_UDD=/path/to/test/user/data/dir
+ mkdir -p $TEST_UDD
+ CHROME_USER_DATA_DIR=$TEST_UDD /Applications/Brave.app/Contents/MacOS/Brave
\ No newline at end of file
diff --git a/test/data/import/brave-browser-laptop/default/Cookies b/test/data/import/brave-browser-laptop/default/Cookies
new file mode 100644
index 00000000000..a5c10daad67
Binary files /dev/null and b/test/data/import/brave-browser-laptop/default/Cookies differ
diff --git a/test/data/import/brave-browser-laptop/default/History b/test/data/import/brave-browser-laptop/default/History
new file mode 100644
index 00000000000..299dadc33af
Binary files /dev/null and b/test/data/import/brave-browser-laptop/default/History differ
diff --git a/test/data/import/brave-browser-laptop/default/Login Data b/test/data/import/brave-browser-laptop/default/Login Data
new file mode 100644
index 00000000000..4c9b5f570f6
Binary files /dev/null and b/test/data/import/brave-browser-laptop/default/Login Data differ
diff --git a/test/data/import/brave-browser-laptop/default/session-store-1 b/test/data/import/brave-browser-laptop/default/session-store-1
new file mode 100644
index 00000000000..6cb7df4f2d2
--- /dev/null
+++ b/test/data/import/brave-browser-laptop/default/session-store-1
@@ -0,0 +1 @@
+{"createdFaviconDirectory":true,"cache":{"bookmarkLocation":{"https://brave.com/":["https://brave.com/|0|0"],"https://brave.com/features/":["https://brave.com/features/|0|1"],"https://brave.com/publishers/":["https://brave.com/publishers/|0|-1"],"https://brave.com/blog/":["https://brave.com/blog/|0|3"]},"bookmarkOrder":{"0":[{"key":"1","order":0,"type":"bookmark-folder"},{"key":"https://brave.com/|0|0","order":1,"type":"bookmark"}],"1":[{"key":"2","order":0,"type":"bookmark-folder"},{"key":"https://brave.com/features/|0|1","order":1,"type":"bookmark"}],"3":[{"key":"4","order":0,"type":"bookmark-folder"},{"key":"https://brave.com/blog/|0|3","order":1,"type":"bookmark"}],"-1":[{"key":"3","order":0,"type":"bookmark-folder"},{"key":"https://brave.com/publishers/|0|-1","order":1,"type":"bookmark"}]},"ledgerVideos":{}},"settings":{"general.download-default-path":"/Users/garrettr/Downloads","general.is-default-browser":true,"security.flash.installed":false,"advanced.payments-allow-promotions":false,"bookmarks.toolbar.show":true},"windows":[],"swipeRightPercent":0,"perWindowState":[{"frames":[{"showOnRight":false,"src":"http://localhost:8080/","lastAccessedTime":1528749821459,"computedThemeColor":null,"partition":"persist:default","findDetail":{"searchString":"","caseSensitivity":false},"hasBeenActivated":true,"endLoadTime":1528749832955,"tabStripWindowId":2,"navbar":{"urlbar":{"location":"http://localhost:8080/","suggestions":{"selectedIndex":null,"searchResults":[],"suggestionList":null,"shouldRender":false,"autocompleteEnabled":false,"urlSuffix":"","hasSuggestionMatch":false},"focused":false,"active":false}},"zoomLevel":0,"partitionNumber":0,"history":["http://localhost:8080/","http://localhost:8080/","http://localhost:8080/"],"startLoadTime":1528749832905,"provisionalLocation":"http://localhost:8080/","location":"http://localhost:8080/","fingerprintingProtection":{},"title":"localhost:8080","icon":null,"isPrivate":false,"hrefPreview":"","unloaded":false,"key":3}],"debugStoreActions":false,"closedFrames":[{"showOnRight":false,"src":"https://en.wikipedia.org/wiki/Year_2038_problem","lastAccessedTime":1528745691842,"computedThemeColor":"rgb(246, 246, 246)","partition":"persist:default","findDetail":{"searchString":"","caseSensitivity":false},"hasBeenActivated":true,"endLoadTime":1528745696973,"tabStripWindowId":2,"navbar":{"urlbar":{"location":"https://en.wikipedia.org/wiki/Year_2038_problem","suggestions":{"selectedIndex":null,"searchResults":[],"suggestionList":null,"shouldRender":false,"urlSuffix":"","hasSuggestionMatch":false,"autocompleteEnabled":false},"focused":false,"active":false}},"zoomLevel":0,"closedAtIndex":1,"partitionNumber":0,"history":["https://www.google.com/search?q=year%202048%20bug","https://en.wikipedia.org/wiki/Year_2038_problem"],"startLoadTime":1528745695504,"provisionalLocation":"https://en.wikipedia.org/wiki/Year_2038_problem","location":"https://en.wikipedia.org/wiki/Year_2038_problem","fingerprintingProtection":{},"title":"Year 2038 problem - Wikipedia","icon":"https://en.wikipedia.org/static/favicon/wikipedia.ico","isPrivate":false,"hrefPreview":"","unloaded":true,"key":1},{"showOnRight":false,"src":"about:preferences#security","lastAccessedTime":1528749628784,"computedThemeColor":null,"partition":"persist:default","findDetail":{"searchString":"","caseSensitivity":false},"hasBeenActivated":true,"endLoadTime":1528749631084,"tabStripWindowId":2,"navbar":{"urlbar":{"location":"about:preferences#security","suggestions":{"selectedIndex":null,"searchResults":[],"suggestionList":null,"shouldRender":false,"autocompleteEnabled":false,"urlSuffix":"","hasSuggestionMatch":false},"focused":false,"active":false}},"zoomLevel":0,"closedAtIndex":1,"partitionNumber":0,"history":[],"startLoadTime":1528749631079,"provisionalLocation":"chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/about-preferences.html#security","location":"about:preferences#security","fingerprintingProtection":{},"title":"Preferences","icon":"chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/img/favicon.ico","isPrivate":false,"themeColor":"#FF5000","hrefPreview":"","unloaded":true,"key":2}],"ui":{"siteInfo":{"isVisible":false},"tabs":{"tabPageIndex":0,"intersectionRatio":1,"hoverTabIndex":1,"previewMode":false},"bookmarksToolbar":{},"contextMenu":{"selectedIndex":null},"menubar":{"isVisible":false}},"activeFrameKey":3,"debugTabEvents":false,"windowInfo":{"focusTime":1528749892210,"width":1299,"left":108,"height":858,"windowId":2,"state":"normal","top":449,"focused":true,"type":"normal","id":2},"tabs":[]}],"swipeLeftPercent":0,"visits":[],"notifications":[],"ledger":{"about":{"synopsis":[],"synopsisOptions":{"_a":7000,"_b":1000,"scorekeeper":"concave","_d":0.000033333333333333335,"numFrames":30,"frameSize":86400000,"emptyScores":{"concave":0,"visits":0},"_b2":1000000,"scorekeepers":["concave","visits"],"_a2":14000,"_a4":28000,"minPublisherVisits":1,"minPublisherDuration":8000}},"info":{"hasBitcoinHandler":false},"promotion":{"promotionId":"4669fe31-a76e-4fd9-ae69-9ed1a9ab5f17","stateWallet":{"disabledWallet":{"notification":{"options":{"persist":false,"style":"greetingStyle"},"messageAction":"optInPromotion","greeting":"Hello!","message":"Ready to support your favorite sites? Brave will fill your wallet with tokens to get you started!","buttons":[{"buttonActionId":"remindLater","text":"Maybe later"},{"className":"primaryButton","buttonActionId":"optInPromotion","text":"I'm ready"}],"firstShowTimestamp":1528742048970},"panel":{"optedInButton":"Claim my free tokens","optInMarkup":{"title":"Brave has created a simple way for you to contribute to the sites you use most.","message":["Now, for a limited time, Brave will fund your wallet with tokens to get you started!","To start using Brave Payments and accept your tokens, simply flip the switch at the top of this window and then choose \"Claim my free Tokens\".","The rest is easy."]},"disclaimer":"If these tokens are not used within 90 days to support content creators, they will automatically return to the Brave User Growth Pool."}},"emptyWallet":{"notification":{"options":{"persist":false,"style":"greetingStyle"},"messageAction":"optInPromotion","greeting":"Hello!","message":"Brave is offering you free tokens to get you started with Brave Payments!","buttons":[{"buttonActionId":"remindLater","text":"Maybe later"},{"className":"primaryButton","buttonActionId":"optInPromotion","text":"Claim my tokens..."}]},"panel":{"optedInButton":"Claim my free tokens","successText":{"title":"Bravo!","message":"It's your lucky day. Your token grant is on its way."},"disclaimer":"Your new tokens will appear in your account shortly. If these tokens are not used within 90 days to support content creators, they will automatically return to the Brave User Growth Pool."}},"fundedWallet":{"notification":{"options":{"persist":false,"style":"greetingStyle"},"messageAction":"optInPromotion","greeting":"Hello!","message":"Thank you for being a great contributor! Here are some BAT tokens, on us!","buttons":[{"buttonActionId":"remindLater","text":"Maybe later"},{"className":"primaryButton","buttonActionId":"optInPromotion","text":"Claim my tokens..."}]},"panel":{"optedInButton":"Claim my free tokens","successText":{"greeting":"Bravo!","message":"It's your lucky day. Your token grant is on its way."},"disclaimer":"Your new tokens will appear in your account shortly. If these tokens are not used within 90 days to support content creators, they will automatically return to the Brave User Growth Pool."}}},"minimumReconcileTimestamp":1529452800000,"remindTimestamp":-1,"activeState":"disabledWallet"},"synopsis":{"options":{"_a":7000,"_b":1000,"scorekeeper":"concave","_d":0.000033333333333333335,"numFrames":30,"frameSize":86400000,"emptyScores":{"concave":0,"visits":0},"_b2":1000000,"scorekeepers":["concave","visits"],"_a2":14000,"_a4":28000,"minPublisherVisits":1,"minPublisherDuration":8000},"publishers":{}}},"fingerprintingProtectionAll":{"enabled":false},"siteSettings":{"https://www.youtube.com":{"autoplay":true},"https://www.twitch.tv":{"autoplay":true},"https?://uphold.com":{"fingerprintingProtection":"allowAllFingerprinting"}},"updates":{"verbose":false,"lastCheckTimestamp":1528745781338,"weekOfInstallation":"2018-06-11","referralHeaders":[{"domains":["marketwatch.com","barrons.com"],"headers":{"X-Brave-Partner":"dowjones"},"cookieNames":[],"expiration":31536000000},{"domains":["townsquareblogs.com","tasteofcountry.com","ultimateclassicrock.com","xxlmag.com","popcrush.com"],"headers":{"X-Brave-Partner":"townsquare"},"cookieNames":[],"expiration":31536000000}],"firstCheckMade":true,"lastCheckMonth":6,"lastCheckWOY":159,"status":"update-none","promoCode":"none","lastCheckYMD":"2018-06-11"},"adblock":{"count":9,"etag":"\"bc9de127048019d82664929814e47775\"","lastCheckVersion":3,"lastCheckDate":1528742042971},"lastAppVersion":"0.22.808","defaultSiteSettingsListImported":true,"about":{"newtab":{"gridLayoutSize":"small","sites":[{"key":"https://twitter.com/brave/|0","count":0,"favicon":"chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/img/newtab/defaultTopSitesIcon/twitter.png","location":"https://twitter.com/brave/","themeColor":"rgb(255, 255, 255)","title":"Brave Software (@brave) | Twitter"},{"lastAccessedTime":1528749833205,"title":"localhost:8080","location":"http://localhost:8080/","partitionNumber":0,"count":24,"key":"http://localhost:8080/|0","bookmarked":false},{"lastAccessedTime":1528742534232,"title":"Example Domain","location":"https://example.com/","partitionNumber":0,"count":2,"themeColor":"rgb(240, 240, 242)","key":"https://example.com/|0","bookmarked":false},{"lastAccessedTime":1528742510286,"title":"127.0.0.1:8080/trigger_password_save_prompt.html","location":"http://127.0.0.1:8080/trigger_password_save_prompt.html","partitionNumber":0,"count":2,"key":"http://127.0.0.1:8080/trigger_password_save_prompt.html|0","bookmarked":false},{"lastAccessedTime":1528745697224,"count":1,"partitionNumber":0,"favicon":"https://en.wikipedia.org/static/favicon/wikipedia.ico","bookmarked":false,"location":"https://en.wikipedia.org/wiki/Year_2038_problem","title":"Year 2038 problem - Wikipedia","skipSync":null,"objectId":null,"themeColor":"rgb(246, 246, 246)","key":"https://en.wikipedia.org/wiki/Year_2038_problem|0"},{"lastAccessedTime":1528745695067,"count":1,"partitionNumber":0,"favicon":"https://www.google.com/images/branding/product/ico/googleg_lodp.ico","bookmarked":false,"location":"https://www.google.com/search?q=year%202048%20bug","title":"year 2048 bug - Google Search","skipSync":null,"objectId":null,"themeColor":"rgb(250, 250, 250)","key":"https://www.google.com/search?q=year%202048%20bug|0"},{"lastAccessedTime":1528742231066,"count":1,"partitionNumber":0,"favicon":"https://brave.com/blog/images/brave_appicon_release.png","bookmarked":"https://brave.com/blog/|0|3","location":"https://brave.com/blog/","title":"Blog About Privacy, Adblocks & Best Browsers | Brave Browser","skipSync":null,"objectId":null,"key":"https://brave.com/blog/|0"},{"key":"https://www.facebook.com/BraveSoftware/|0","count":0,"favicon":"chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/img/newtab/defaultTopSitesIcon/facebook.png","location":"https://www.facebook.com/BraveSoftware/","themeColor":"rgb(59, 89, 152)","title":"Brave Software | Facebook","bookmarked":false},{"key":"https://www.youtube.com/bravesoftware/|0","count":0,"favicon":"chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/img/newtab/defaultTopSitesIcon/youtube.png","location":"https://www.youtube.com/bravesoftware/","themeColor":"#E62117","title":"Brave Browser - YouTube","bookmarked":false},{"key":"https://brave.com/|0","count":0,"favicon":"chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/img/newtab/defaultTopSitesIcon/brave.ico","location":"https://brave.com/","themeColor":"rgb(255, 255, 255)","title":"Brave Software | Building a Better Web","bookmarked":"https://brave.com/|0|0"},{"key":"https://itunes.apple.com/app/brave-web-browser/id1052879175?mt=8|0","count":0,"favicon":"chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/img/newtab/defaultTopSitesIcon/appstore.png","location":"https://itunes.apple.com/app/brave-web-browser/id1052879175?mt=8","themeColor":"rgba(255, 255, 255, 1)","title":"Brave Web Browser: Fast with built-in adblock on the App Store","bookmarked":false},{"key":"https://play.google.com/store/apps/details?id=com.brave.browser|0","count":0,"favicon":"chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/img/newtab/defaultTopSitesIcon/playstore.png","location":"https://play.google.com/store/apps/details?id=com.brave.browser","themeColor":"rgb(241, 241, 241)","title":"Brave Browser: Fast AdBlock – Apps para Android no Google Play","bookmarked":false}],"ignoredTopSites":[],"pinnedTopSites":[{"key":"https://twitter.com/brave/|0","count":0,"favicon":"chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/img/newtab/defaultTopSitesIcon/twitter.png","location":"https://twitter.com/brave/","themeColor":"rgb(255, 255, 255)","title":"Brave Software (@brave) | Twitter"}],"useAlternativePrivateSearchEngine":false,"updatedStamp":1528749838215},"preferences":{},"welcome":{"showOnLoad":false},"brave":{"versionInformation":{"Brave":"0.22.808","V8":"6.7.288.43","rev":"2572bd3b79216358858cecf63428ef610ca0fc00","Muon":"7.0.4","OS Release":"17.6.0","Update Channel":"Release","OS Architecture":"x64","OS Platform":"macOS","Node.js":"7.9.0","Brave Sync":"v1.4.2","libchromiumcontent":"67.0.3396.71"}},"history":{"entries":[{"lastAccessedTime":1528749833205,"title":"localhost:8080","location":"http://localhost:8080/","partitionNumber":0,"count":24,"key":"http://localhost:8080/|0"},{"lastAccessedTime":1528745697224,"count":1,"partitionNumber":0,"favicon":"https://en.wikipedia.org/static/favicon/wikipedia.ico","location":"https://en.wikipedia.org/wiki/Year_2038_problem","title":"Year 2038 problem - Wikipedia","skipSync":null,"objectId":null,"themeColor":"rgb(246, 246, 246)","key":"https://en.wikipedia.org/wiki/Year_2038_problem|0"},{"lastAccessedTime":1528745695067,"count":1,"partitionNumber":0,"favicon":"https://www.google.com/images/branding/product/ico/googleg_lodp.ico","location":"https://www.google.com/search?q=year%202048%20bug","title":"year 2048 bug - Google Search","skipSync":null,"objectId":null,"themeColor":"rgb(250, 250, 250)","key":"https://www.google.com/search?q=year%202048%20bug|0"},{"lastAccessedTime":1528742534232,"title":"Example Domain","location":"https://example.com/","partitionNumber":0,"count":2,"themeColor":"rgb(240, 240, 242)","key":"https://example.com/|0"},{"lastAccessedTime":1528742522624,"count":1,"partitionNumber":0,"favicon":null,"location":"http://127.0.0.1:8081/trigger_password_save_prompt.html","title":"127.0.0.1:8081/trigger_password_save_prompt.html","skipSync":null,"objectId":null,"themeColor":null,"key":"http://127.0.0.1:8081/trigger_password_save_prompt.html|0"},{"lastAccessedTime":1528742510286,"title":"127.0.0.1:8080/trigger_password_save_prompt.html","location":"http://127.0.0.1:8080/trigger_password_save_prompt.html","partitionNumber":0,"count":2,"key":"http://127.0.0.1:8080/trigger_password_save_prompt.html|0"},{"lastAccessedTime":1528742231066,"count":1,"partitionNumber":0,"favicon":"https://brave.com/blog/images/brave_appicon_release.png","location":"https://brave.com/blog/","title":"Blog About Privacy, Adblocks & Best Browsers | Brave Browser","skipSync":null,"objectId":null,"key":"https://brave.com/blog/|0"},{"lastAccessedTime":1528742146846,"count":1,"partitionNumber":0,"favicon":"https://brave.com/features/images/brave_appicon_release.png","location":"https://brave.com/features/","title":"Features | Brave Browser","skipSync":null,"objectId":null,"key":"https://brave.com/features/|0"},{"lastAccessedTime":1528742146791,"count":1,"partitionNumber":0,"favicon":"https://brave.com/publishers/images/brave_appicon_release.png","location":"https://brave.com/publishers/","title":"Make Money as a Publisher with Brave Payments | Brave Browser","skipSync":null,"objectId":null,"key":"https://brave.com/publishers/|0"},{"lastAccessedTime":1528742052183,"count":1,"partitionNumber":0,"favicon":"https://brave.com/images/brave_appicon_release.png","location":"https://brave.com/","title":"Secure, Fast & Private Web Browser with Adblocker | Brave Browser","skipSync":null,"objectId":null,"themeColor":"rgb(0, 0, 0)","key":"https://brave.com/|0"}],"updatedStamp":1528749833206}},"searchResults":[],"bookmarkFolders":{"1":{"title":"Nested Folder 1","folderId":1,"key":"1","parentFolderId":0,"partitionNumber":0,"objectId":null,"type":"bookmark-folder","skipSync":null},"2":{"title":"Nested Folder 2 (Empty)","folderId":2,"key":"2","parentFolderId":1,"partitionNumber":0,"objectId":null,"type":"bookmark-folder","skipSync":null},"3":{"title":"Nested Folder 1","folderId":3,"key":"3","parentFolderId":-1,"partitionNumber":0,"objectId":null,"type":"bookmark-folder","skipSync":null},"4":{"title":"Nested Folder 2 (Empty)","folderId":4,"key":"4","parentFolderId":3,"partitionNumber":0,"objectId":null,"type":"bookmark-folder","skipSync":null}},"trackingProtection":{"count":0,"etag":"\"62754234a65e26bc939b1f6f2e727581\"","lastCheckVersion":"1","lastCheckDate":1528742035313},"autofill":{"addresses":{"guid":[],"timestamp":0},"creditCards":{"guid":[],"timestamp":0}},"extensions":{"mnojpmjdmbbfmejpflffifhffcmidifd":{"enabled":true,"filePath":"/Applications/Brave.app/Contents/Resources/extensions/brave","name":"brave","url":"chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/","manifest":{"content_scripts":[{"all_frames":true,"css":["content/styles/siteHack-marketwatch.com.css"],"matches":["https://www.marketwatch.com/*"],"run_at":"document_start"},{"all_frames":true,"js":["content/scripts/siteHack-glennbeck.com.js"],"matches":["http://www.glennbeck.com/*"],"run_at":"document_start"},{"all_frames":true,"css":["content/styles/removeEmptyElements.css"],"matches":["https://www.washingtonpost.com/*","https://www.youtube.com/*","https://coinmarketcap.com/*"],"run_at":"document_start"},{"all_frames":true,"css":["brave-default.css"],"exclude_globs":["chrome://brave/Applications/Brave.app/Contents/Resources/app.asar/app/extensions/brave/index.html"],"include_globs":["http://*/*","https://*/*","file://*","data:*","about:srcdoc"],"js":["content/scripts/util.js","content/scripts/navigator.js","content/scripts/blockFlash.js","content/scripts/blockCanvasFingerprinting.js","content/scripts/block3rdPartyContent.js","content/scripts/inputHandler.js"],"match_about_blank":true,"matches":[""],"run_at":"document_start"},{"all_frames":true,"exclude_globs":["chrome://brave/Applications/Brave.app/Contents/Resources/app.asar/app/extensions/brave/index.html"],"include_globs":["http://*/*","https://*/*","file://*","data:*","about:srcdoc"],"js":["content/scripts/adInsertion.js","content/scripts/pageInformation.js","content/scripts/flashListener.js"],"matches":[""],"run_at":"document_end"},{"all_frames":false,"exclude_globs":["chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/about-blank.html","chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/about-blank.html#*"],"include_globs":["http://*/*","https://*/*","file://*","data:*","about:srcdoc","chrome://brave/Applications/Brave.app/Contents/Resources/app.asar/app/extensions/brave/index.html","chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/about-*.html","chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/about-*.html#*"],"js":["content/scripts/themeColor.js"],"matches":[""],"run_at":"document_end"},{"exclude_globs":["chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/about-blank.html","chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/about-blank.html#*"],"include_globs":["chrome://brave/Applications/Brave.app/Contents/Resources/app.asar/app/extensions/brave/index.html","chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/about-*.html","chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/about-*.html#*"],"js":["content/scripts/util.js","content/scripts/inputHandler.js"],"matches":[""],"run_at":"document_start"},{"all_frames":true,"exclude_globs":["chrome://brave/Applications/Brave.app/Contents/Resources/app.asar/app/extensions/brave/index.html","chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/*"],"js":["content/scripts/dndHandler.js"],"matches":[""],"run_at":"document_start"},{"all_frames":true,"exclude_globs":["chrome://brave/Applications/Brave.app/Contents/Resources/app.asar/app/extensions/brave/index.html","chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/*"],"include_globs":["http://*/*","https://*/*","file://*"],"js":["content/scripts/dappListener.js"],"matches":[""],"run_at":"document_start"}],"permissions":["externally_connectable.all_urls","tabs","","contentSettings","idle"],"web_accessible_resources":["img/favicon.ico"],"manifest_version":2,"name":"brave","content_security_policy":"default-src 'self'; form-action 'none'; style-src 'self' 'unsafe-inline'; font-src 'self' data:; img-src * data: file://*; connect-src 'self' https://www.youtube.com; frame-src 'self' https://brave.com;","incognito":"split","background":{"persistent":true,"scripts":["content/scripts/metaScraper.js","content/scripts/requestHandler.js","content/scripts/idleHandler.js"]},"version":"1.0","externally_connectable":{"matches":[""]},"key":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAupOLMy5Fd4dCSOtjcApsAQOnuBdTs+OvBVt/3P93noIrf068x0xXkvxbn+fpigcqfNamiJ5CjGyfx9zAIs7zcHwbxjOw0Uih4SllfgtK+svNTeE0r5atMWE0xR489BvsqNuPSxYJUmW28JqhaSZ4SabYrRx114KcU6ko7hkjyPkjQa3P+chStJjIKYgu5tWBiMJp5QVLelKoM+xkY6S7efvJ8AfajxCViLGyDQPDviGr2D0VvIBob0D1ZmAoTvYOWafcNCaqaejPDybFtuLFX3pZBqfyOCyyzGhucyCmfBXJALKbhjRAqN5glNsUmGhhPK87TuGATQfVuZtenMvXMQIDAQAB"},"base_path":"file:///Applications/Brave.app/Contents/Resources/extensions/brave","version":"1.0","id":"mnojpmjdmbbfmejpflffifhffcmidifd","description":""},"kmendfapggjehodndflmmgagdbamhnfd":{"enabled":true,"filePath":"/Applications/Brave.app/Contents/Frameworks/Brave Framework.framework/Resources/cryptotoken","name":"CryptoTokenExtension","url":"chrome-extension://kmendfapggjehodndflmmgagdbamhnfd/","manifest":{"permissions":["hid","u2fDevices","usb","cryptotokenPrivate","externally_connectable.all_urls","tabs","https://*/*","http://*/*",{"usbDevices":[{"productId":529,"vendorId":4176}]}],"manifest_version":2,"name":"CryptoTokenExtension","incognito":"split","background":{"persistent":false,"scripts":["util.js","b64.js","sha256.js","timer.js","countdown.js","countdowntimer.js","devicestatuscodes.js","approvedorigins.js","errorcodes.js","webrequest.js","messagetypes.js","factoryregistry.js","closeable.js","requesthelper.js","asn1.js","enroller.js","requestqueue.js","signer.js","origincheck.js","textfetcher.js","appid.js","watchdog.js","logging.js","webrequestsender.js","window-timer.js","cryptotokenorigincheck.js","cryptotokenapprovedorigins.js","gnubbydevice.js","hidgnubbydevice.js","usbgnubbydevice.js","gnubbies.js","gnubby.js","gnubby-u2f.js","gnubbyfactory.js","singlesigner.js","multiplesigner.js","generichelper.js","inherits.js","individualattest.js","devicefactoryregistry.js","usbhelper.js","usbenrollhandler.js","usbsignhandler.js","usbgnubbyfactory.js","googlecorpindividualattest.js","cryptotokenbackground.js"]},"version":"0.9.73","description":"CryptoToken Component Extension","externally_connectable":{"accepts_tls_channel_id":true,"ids":["fjajfjhkeibgmiggdfehjplbhmfkialk"],"matches":["https://*/*"]},"key":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq7zRobvA+AVlvNqkHSSVhh1sEWsHSqz4oR/XptkDe/Cz3+gW9ZGumZ20NCHjaac8j1iiesdigp8B1LJsd/2WWv2Dbnto4f8GrQ5MVphKyQ9WJHwejEHN2K4vzrTcwaXqv5BSTXwxlxS/mXCmXskTfryKTLuYrcHEWK8fCHb+0gvr8b/kvsi75A1aMmb6nUnFJvETmCkOCPNX5CHTdy634Ts/x0fLhRuPlahk63rdf7agxQv5viVjQFk+tbgv6aa9kdSd11Js/RZ9yZjrFgHOBWgP4jTBqud4+HUglrzu8qynFipyNRLCZsaxhm+NItTyNgesxLdxZcwOz56KD1Q4IQIDAQAB"},"base_path":"file:///Applications/Brave.app/Contents/Frameworks/Brave%20Framework.framework/Resources/cryptotoken","version":"0.9.73","id":"kmendfapggjehodndflmmgagdbamhnfd","description":"CryptoToken Component Extension"},"cjnmeadmgmiihncdidmfiabhenbggfjm":{"enabled":true,"filePath":"/Applications/Brave.app/Contents/Resources/extensions/brave","name":"Brave Sync","url":"chrome-extension://cjnmeadmgmiihncdidmfiabhenbggfjm/","manifest":{"content_scripts":[],"manifest_version":2,"name":"Brave Sync","content_security_policy":"default-src 'self'; form-action 'none'; connect-src 'self' https://sync.brave.com https://brave-sync.s3.dualstack.us-west-2.amazonaws.com;","incognito":"not_allowed","background":{"scripts":["content/scripts/sync.js"]},"version":"1.0","icons":{"16":"img/sync-16.png","48":"img/sync-48.png","128":"img/sync-128.png"},"key":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxOmBmOVzntEY6zrcrGSAyrhzL2FJt4FaP12nb899+SrV0LgpOgyqDjytuXT5IlHS74j7ZK2zTOTQy5/E9hqo6ioi1GA3PQU8E71DTaN6kW+XzP+VyZmgPoQHIxPg8jkYk/H4erfP9kMhkVOtu/XqDTqluNhOT0BvVlBpWd4unTQFWdgpCYlPrI6PsYya4FSuIDe6rCKtJABfuKFEr7U9d9MNAOJEnRS8vdBHWCuhWHqsfAaAPyKHQhnwFSFZ4eB+JznBQf7cQtB3EpOoBElyR9QvmbWFrYu87eGL5XxsojKHCrxlQ4X5ANsALa1Mdd2DHDMVqLMIiEEU42DVB0ZDewIDAQAB"},"base_path":"file:///Applications/Brave.app/Contents/Resources/extensions/brave","version":"1.0","id":"cjnmeadmgmiihncdidmfiabhenbggfjm","description":""},"fmdpfempfmekjkcfdehndghogpnpjeno":{"enabled":true,"filePath":"/Applications/Brave.app/Contents/Resources/extensions/torrent","name":"Torrent Viewer","url":"chrome-extension://fmdpfempfmekjkcfdehndghogpnpjeno/","manifest":{"content_scripts":[],"permissions":["externally_connectable.all_urls","tabs",""],"manifest_version":2,"name":"Torrent Viewer","content_security_policy":"default-src 'self'; connect-src 'self' https://example.com; media-src 'self' http://localhost:*; form-action 'none'; style-src 'self' 'unsafe-inline'; frame-src 'self' http://localhost:*;","incognito":"split","version":"1.0","icons":{"16":"img/webtorrent-16.png","48":"img/webtorrent-48.png","128":"img/webtorrent-128.png"},"description":"torrentDesc","externally_connectable":{"matches":[""]},"key":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyWl+wMvL0wZX3JUs7GeZAvxMP+LWEh2bwMV1HyuBra/lGZIq3Fmh0+AFnvFPXz1NpQkbLS3QWyqhdIn/lepGwuc2ma0glPzzmieqwctUurMGSGManApGO1MkcbSPhb+R1mx8tMam5+wbme4WoW37PI3oATgOs2NvHYuP60qol3U7b/zB3IWuqtwtqKe2Q1xY17btvPuz148ygWWIHneedt0jwfr6Zp+CSLARB9Heq/jqGXV4dPSVZ5ebBHLQ452iZkHxS6fm4Z+IxjKdYs3HNj/s8xbfEZ2ydnArGdJ0lpSK9jkDGYyUBugq5Qp3FH6zV89WqBvoV1dqUmL9gxbHsQIDAQAB"},"base_path":"file:///Applications/Brave.app/Contents/Resources/extensions/torrent","version":"1.0","id":"fmdpfempfmekjkcfdehndghogpnpjeno","description":"torrentDesc"},"jdbefljfgobbmcidnmpjamcbhnbphjnb":{"enabled":true,"filePath":"/Users/garrettr/brave-test-user-data-dir/Extensions/jdbefljfgobbmcidnmpjamcbhnbphjnb/1.9.459","name":"PDF Viewer","url":"chrome-extension://jdbefljfgobbmcidnmpjamcbhnbphjnb/","manifest":{"permissions":["storage",""],"manifest_version":2,"name":"PDF Viewer","content_security_policy":"script-src 'self'; object-src 'self'","incognito":"split","version":"1.9.459","icons":{"16":"icon16.png","48":"icon48.png","128":"icon128.png"},"description":"Uses HTML5 to display PDF files directly in the browser.","key":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqmqh6Kxmj00IjKvjPsCtw6g2BHvKipjS3fBD0IInXZZ57u5oZfw6q42L7tgWDLrNDPvu3XDH0vpECr+IcgBjkM+w6+2VdTyPj5ubngTwvBqCIPItetpsZNJOJfrFw0OIgmyekZYsI+BsK7wiMtHczwfKSTi0JKgrwIRhHbEhpUnCxFhi+zI61p9jwMb2EBFwxru7MtpP21jG7pVznFeLV9W9BkNL1Th9QBvVs7GvZwtIIIniQkKtqT1wp4IY9/mDeM5SgggKakumCnT9D37ZxDnM2K13BKAXOkeH6JLGrZCl3aXmqDO9OhLwoch+LGb5IaXwOZyGnhdhm9MNA3hgEwIDAQAB"},"base_path":"file:///Users/garrettr/brave-test-user-data-dir/Extensions/jdbefljfgobbmcidnmpjamcbhnbphjnb/1.9.459","version":"1.9.459","id":"jdbefljfgobbmcidnmpjamcbhnbphjnb","description":"Uses HTML5 to display PDF files directly in the browser."}},"pinnedSites":{},"menubar":{},"safeBrowsing":{"etag":"\"81dfdeea341d03f400c3c5f0d345065c\"","lastCheckVersion":3,"lastCheckDate":1528742036129},"httpsEverywhere":{"count":0,"etag":"\"d3ebe6feb72e08351166d62b2776794b\"","lastCheckVersion":"6.0","lastCheckDate":1528742038314},"defaultWindowParams":{"width":1299,"height":858,"maximized":false},"passwords":[],"historySites":{"https://brave.com/publishers/|0":{"lastAccessedTime":1528742146791,"count":1,"partitionNumber":0,"favicon":"https://brave.com/publishers/images/brave_appicon_release.png","location":"https://brave.com/publishers/","title":"Make Money as a Publisher with Brave Payments | Brave Browser","skipSync":null,"objectId":null,"key":"https://brave.com/publishers/|0"},"https://www.google.com/search?q=year%202048%20bug|0":{"lastAccessedTime":1528745695067,"count":1,"partitionNumber":0,"favicon":"https://www.google.com/images/branding/product/ico/googleg_lodp.ico","location":"https://www.google.com/search?q=year%202048%20bug","title":"year 2048 bug - Google Search","skipSync":null,"objectId":null,"themeColor":"rgb(250, 250, 250)","key":"https://www.google.com/search?q=year%202048%20bug|0"},"https://en.wikipedia.org/wiki/Year_2038_problem|0":{"lastAccessedTime":1528745697224,"count":1,"partitionNumber":0,"favicon":"https://en.wikipedia.org/static/favicon/wikipedia.ico","location":"https://en.wikipedia.org/wiki/Year_2038_problem","title":"Year 2038 problem - Wikipedia","skipSync":null,"objectId":null,"themeColor":"rgb(246, 246, 246)","key":"https://en.wikipedia.org/wiki/Year_2038_problem|0"},"http://127.0.0.1:8080/trigger_password_save_prompt.html|0":{"lastAccessedTime":1528742510286,"title":"127.0.0.1:8080/trigger_password_save_prompt.html","location":"http://127.0.0.1:8080/trigger_password_save_prompt.html","partitionNumber":0,"count":2,"key":"http://127.0.0.1:8080/trigger_password_save_prompt.html|0"},"https://example.com/|0":{"lastAccessedTime":1528742534232,"title":"Example Domain","location":"https://example.com/","partitionNumber":0,"count":2,"themeColor":"rgb(240, 240, 242)","key":"https://example.com/|0"},"http://127.0.0.1:8081/trigger_password_save_prompt.html|0":{"lastAccessedTime":1528742522624,"count":1,"partitionNumber":0,"favicon":null,"location":"http://127.0.0.1:8081/trigger_password_save_prompt.html","title":"127.0.0.1:8081/trigger_password_save_prompt.html","skipSync":null,"objectId":null,"themeColor":null,"key":"http://127.0.0.1:8081/trigger_password_save_prompt.html|0"},"https://brave.com/blog/|0":{"lastAccessedTime":1528742231066,"count":1,"partitionNumber":0,"favicon":"https://brave.com/blog/images/brave_appicon_release.png","location":"https://brave.com/blog/","title":"Blog About Privacy, Adblocks & Best Browsers | Brave Browser","skipSync":null,"objectId":null,"key":"https://brave.com/blog/|0"},"http://localhost:8080/|0":{"lastAccessedTime":1528749833205,"title":"localhost:8080","location":"http://localhost:8080/","partitionNumber":0,"count":24,"key":"http://localhost:8080/|0"},"https://brave.com/features/|0":{"lastAccessedTime":1528742146846,"count":1,"partitionNumber":0,"favicon":"https://brave.com/features/images/brave_appicon_release.png","location":"https://brave.com/features/","title":"Features | Brave Browser","skipSync":null,"objectId":null,"key":"https://brave.com/features/|0"},"https://brave.com/|0":{"lastAccessedTime":1528742052183,"count":1,"partitionNumber":0,"favicon":"https://brave.com/images/brave_appicon_release.png","location":"https://brave.com/","title":"Secure, Fast & Private Web Browser with Adblocker | Brave Browser","skipSync":null,"objectId":null,"themeColor":"rgb(0, 0, 0)","key":"https://brave.com/|0"}},"searchDetail":{"searchURL":"https://www.google.com/search?q={searchTerms}","autocompleteURL":"https://suggestqueries.google.com/complete/search?client=chrome&q={searchTerms}"},"temporarySiteSettings":{},"firstRunTimestamp":1528742034112,"sync":{"devices":{},"lastFetchTimestamp":0,"setupError":null,"pendingRecords":{},"lastConfirmedRecordTimestamp":0},"cleanedOnShutdown":true,"bookmarks":{"https://brave.com/|0|0":{"parentFolderId":0,"partitionNumber":0,"favicon":"https://brave.com/images/brave_appicon_release.png","location":"https://brave.com/","title":"Secure, Fast & Private Web Browser with Adblocker | Brave Browser","skipSync":null,"objectId":null,"themeColor":"rgb(0, 0, 0)","type":"bookmark","key":"https://brave.com/|0|0"},"https://brave.com/features/|0|1":{"parentFolderId":1,"partitionNumber":0,"favicon":"https://brave.com/features/images/brave_appicon_release.png","location":"https://brave.com/features/","title":"Features | Brave Browser","skipSync":null,"objectId":null,"type":"bookmark","key":"https://brave.com/features/|0|1"},"https://brave.com/publishers/|0|-1":{"parentFolderId":-1,"partitionNumber":0,"favicon":"https://brave.com/publishers/images/brave_appicon_release.png","location":"https://brave.com/publishers/","title":"Make Money as a Publisher with Brave Payments | Brave Browser","skipSync":null,"objectId":null,"type":"bookmark","key":"https://brave.com/publishers/|0|-1"},"https://brave.com/blog/|0|3":{"parentFolderId":3,"partitionNumber":0,"favicon":"https://brave.com/blog/images/brave_appicon_release.png","location":"https://brave.com/blog/","title":"Blog About Privacy, Adblocks & Best Browsers | Brave Browser","skipSync":null,"objectId":null,"type":"bookmark","key":"https://brave.com/blog/|0|3"}},"tabs":[]}
\ No newline at end of file
diff --git a/test/data/import/chrome/cookies_server.js b/test/data/import/chrome/cookies_server.js
index 78d00396f7c..6e96616602d 100644
--- a/test/data/import/chrome/cookies_server.js
+++ b/test/data/import/chrome/cookies_server.js
@@ -3,7 +3,17 @@ const port = 8080
const requestHandler = (request, response) => {
console.log(request.url)
- response.setHeader('Set-Cookie', ['test=test'])
+ // Cookie needs Expires or Max-Age attribute to be a persistent
+ // cookie; otherwise, the browser will treat it as an ephemeral
+ // session cookie and may delete it when the browser is closed.
+ //
+ // The maximum allowable Expires date is used to avoid any potential
+ // issues with the test browser clearing the cookie upon load if the
+ // tests are run after the cookie's expiration date. The choice of
+ // date and the decision to use an absolute date with Expires rather
+ // than a relative one with Max-Age are based on this Stack Overflow
+ // answer: https://stackoverflow.com/a/22479460.
+ response.setHeader('Set-Cookie', ['test=test; Expires=Tue, 19 Jan 2038 03:14:07 GMT'])
response.end('Cookie set')
}
@@ -15,4 +25,4 @@ server.listen(port, (err) => {
}
console.log(`server is listening on ${port}`)
-})
\ No newline at end of file
+})
diff --git a/utility/BUILD.gn b/utility/BUILD.gn
index de0e47d7c7e..22681250c6c 100644
--- a/utility/BUILD.gn
+++ b/utility/BUILD.gn
@@ -7,6 +7,8 @@ source_set("utility") {
"brave_content_utility_client.h",
"importer/brave_external_process_importer_bridge.cc",
"importer/brave_external_process_importer_bridge.h",
+ "importer/brave_importer.cc",
+ "importer/brave_importer.h",
"importer/chrome_importer.cc",
"importer/chrome_importer.h",
]
diff --git a/utility/importer/brave_importer.cc b/utility/importer/brave_importer.cc
new file mode 100644
index 00000000000..ac6e77825da
--- /dev/null
+++ b/utility/importer/brave_importer.cc
@@ -0,0 +1,440 @@
+/* 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/utility/importer/brave_importer.h"
+
+#include
+#include
+
+#include "base/files/file_util.h"
+#include "base/json/json_reader.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "brave/grit/generated_resources.h"
+#include "chrome/common/importer/importer_bridge.h"
+#include "components/autofill/core/common/password_form.h"
+#include "components/cookie_config/cookie_store_util.h"
+#include "components/os_crypt/os_crypt.h"
+#include "components/password_manager/core/browser/login_database.h"
+#include "components/password_manager/core/common/password_manager_pref_names.h"
+#include "components/prefs/json_pref_store.h"
+#include "components/prefs/pref_filter.h"
+#include "net/cookies/canonical_cookie.h"
+#include "net/cookies/cookie_constants.h"
+#include "net/extras/sqlite/cookie_crypto_delegate.h"
+#include "net/extras/sqlite/sqlite_persistent_cookie_store.h"
+#include "sql/connection.h"
+#include "sql/statement.h"
+#include "url/gurl.h"
+
+#if defined(OS_LINUX)
+#include "components/os_crypt/key_storage_config_linux.h"
+#endif
+
+#if defined(USE_X11)
+#if defined(USE_LIBSECRET)
+#include "chrome/browser/password_manager/native_backend_libsecret.h"
+#endif
+#include "chrome/browser/password_manager/native_backend_kwallet_x.h"
+#include "chrome/browser/password_manager/password_store_x.h"
+#include "components/os_crypt/key_storage_util_linux.h"
+
+base::nix::DesktopEnvironment BraveImporter::GetDesktopEnvironment() {
+ std::unique_ptr env(base::Environment::Create());
+ return base::nix::GetDesktopEnvironment(env.get());
+}
+#endif
+
+using base::Time;
+
+BraveImporter::BraveImporter() {
+}
+
+BraveImporter::~BraveImporter() {
+}
+
+void BraveImporter::StartImport(const importer::SourceProfile& source_profile,
+ uint16_t items,
+ ImporterBridge* bridge) {
+ bridge_ = bridge;
+ source_path_ = source_profile.source_path;
+
+ // The order here is important!
+ bridge_->NotifyStarted();
+
+ if ((items & importer::HISTORY) && !cancelled()) {
+ bridge_->NotifyItemStarted(importer::HISTORY);
+ ImportHistory();
+ bridge_->NotifyItemEnded(importer::HISTORY);
+ }
+
+ if ((items & importer::FAVORITES) && !cancelled()) {
+ bridge_->NotifyItemStarted(importer::FAVORITES);
+ ImportBookmarks();
+ bridge_->NotifyItemEnded(importer::FAVORITES);
+ }
+
+ if ((items & importer::PASSWORDS) && !cancelled()) {
+ bridge_->NotifyItemStarted(importer::PASSWORDS);
+ ImportPasswords();
+ bridge_->NotifyItemEnded(importer::PASSWORDS);
+ }
+
+ if ((items & importer::COOKIES) && !cancelled()) {
+ bridge_->NotifyItemStarted(importer::COOKIES);
+ ImportCookies();
+ bridge_->NotifyItemEnded(importer::COOKIES);
+ }
+
+ bridge_->NotifyEnded();
+}
+
+// Returns true if |url| has a valid scheme that we allow to import. We
+// filter out the URL with a unsupported scheme.
+bool CanImportURL(const GURL& url) {
+ // The URL is not valid.
+ if (!url.is_valid())
+ return false;
+
+ // Filter out the URLs with unsupported schemes.
+ const char* const kInvalidSchemes[] = {"chrome-extension"};
+ for (size_t i = 0; i < arraysize(kInvalidSchemes); ++i) {
+ if (url.SchemeIs(kInvalidSchemes[i]))
+ return false;
+ }
+
+ return true;
+}
+
+void BraveImporter::ImportHistory() {
+ base::FilePath history_path =
+ source_path_.Append(
+ base::FilePath::StringType(FILE_PATH_LITERAL("History")));
+ if (!base::PathExists(history_path))
+ return;
+
+ sql::Connection db;
+ if (!db.Open(history_path))
+ return;
+
+ const char query[] =
+ "SELECT url, title, last_visit_time, typed_count, visit_count "
+ "FROM urls WHERE hidden = 0";
+
+ sql::Statement s(db.GetUniqueStatement(query));
+
+ std::vector rows;
+ while (s.Step() && !cancelled()) {
+ GURL url(s.ColumnString(0));
+
+ // Filter out unwanted URLs.
+ if (!CanImportURL(url))
+ continue;
+
+ ImporterURLRow row(url);
+ row.title = s.ColumnString16(1);
+ row.last_visit =
+ base::Time::FromDoubleT(chromeTimeToDouble((s.ColumnInt64(2))));
+ row.hidden = false;
+ row.typed_count = s.ColumnInt(3);
+ row.visit_count = s.ColumnInt(4);
+
+ rows.push_back(row);
+ }
+
+ if (!rows.empty() && !cancelled())
+ bridge_->SetHistoryItems(rows, importer::VISIT_SOURCE_BRAVE_IMPORTED);
+}
+
+void BraveImporter::ParseBookmarks(
+ std::vector* bookmarks) {
+ base::FilePath session_store_path =
+ source_path_.Append(
+ base::FilePath::StringType(FILE_PATH_LITERAL("session-store-1")));
+ std::string session_store_content;
+ if (!ReadFileToString(session_store_path, &session_store_content)) {
+ LOG(ERROR) << "Reading Brave session store file failed";
+ return;
+ }
+
+ std::unique_ptr session_store_json =
+ base::JSONReader::Read(session_store_content);
+ if (!session_store_json) {
+ LOG(ERROR) << "Parsing Brave session store JSON failed";
+ return;
+ }
+
+ base::Value* bookmark_folders_dict =
+ session_store_json->FindKeyOfType("bookmarkFolders",
+ base::Value::Type::DICTIONARY);
+ base::Value* bookmarks_dict =
+ session_store_json->FindKeyOfType("bookmarks",
+ base::Value::Type::DICTIONARY);
+ base::Value* bookmark_order_dict =
+ session_store_json->FindPathOfType({"cache", "bookmarkOrder"},
+ base::Value::Type::DICTIONARY);
+ if (!(bookmark_folders_dict && bookmarks_dict && bookmark_order_dict))
+ return;
+
+ // Recursively load bookmarks from each of the top-level bookmarks
+ // folders: "Bookmarks Toolbar" and "Other Bookmarks"
+ std::vector path;
+ RecursiveReadBookmarksFolder(base::UTF8ToUTF16("Bookmarks Toolbar"),
+ "0",
+ path,
+ true,
+ bookmark_folders_dict,
+ bookmarks_dict,
+ bookmark_order_dict,
+ bookmarks);
+
+ RecursiveReadBookmarksFolder(base::UTF8ToUTF16("Other Bookmarks"),
+ "-1",
+ path,
+ false,
+ bookmark_folders_dict,
+ bookmarks_dict,
+ bookmark_order_dict,
+ bookmarks);
+}
+
+void BraveImporter::RecursiveReadBookmarksFolder(
+ const base::string16 name,
+ const std::string key,
+ std::vector path,
+ const bool in_toolbar,
+ base::Value* bookmark_folders_dict,
+ base::Value* bookmarks_dict,
+ base::Value* bookmark_order_dict,
+ std::vector* bookmarks) {
+ // Add the name of the current folder to the path
+ path.push_back(name);
+
+ base::Value* bookmark_order =
+ bookmark_order_dict->FindKeyOfType(key, base::Value::Type::LIST);
+ if (!bookmark_order)
+ return;
+
+ for (const auto& entry : bookmark_order->GetList()) {
+ auto& type = entry.FindKeyOfType("type", base::Value::Type::STRING)->GetString();
+ auto& key = entry.FindKeyOfType("key", base::Value::Type::STRING)->GetString();
+
+ if (type == "bookmark-folder") {
+ base::Value* bookmark_folder =
+ bookmark_folders_dict->FindKeyOfType(key, base::Value::Type::DICTIONARY);
+ auto& title =
+ bookmark_folder->FindKeyOfType("title", base::Value::Type::STRING)->GetString();
+
+ // Empty folders don't have a corresponding entry in bookmark_order_dict,
+ // which provides an easy way to test whether a folder is empty.
+ base::Value* bookmark_order_entry =
+ bookmark_order_dict->FindKeyOfType(key, base::Value::Type::LIST);
+
+ if (bookmark_order_entry) {
+ // Recurse into non-empty folder.
+ RecursiveReadBookmarksFolder(base::UTF8ToUTF16(title),
+ key,
+ path,
+ in_toolbar,
+ bookmark_folders_dict,
+ bookmarks_dict,
+ bookmark_order_dict,
+ bookmarks);
+ } else {
+ // Add ImportedBookmarkEntry for empty folder.
+ ImportedBookmarkEntry imported_bookmark_folder;
+ imported_bookmark_folder.is_folder = true;
+ imported_bookmark_folder.in_toolbar = in_toolbar;
+ imported_bookmark_folder.url = GURL();
+ imported_bookmark_folder.path = path;
+ imported_bookmark_folder.title = base::UTF8ToUTF16(title);
+ // Brave doesn't specify a creation time for the folder.
+ imported_bookmark_folder.creation_time = base::Time::Now();
+ bookmarks->push_back(imported_bookmark_folder);
+ }
+ } else if (type == "bookmark") {
+ base::Value* bookmark =
+ bookmarks_dict->FindKeyOfType(key, base::Value::Type::DICTIONARY);
+ auto& title =
+ bookmark->FindKeyOfType("title", base::Value::Type::STRING)->GetString();
+ auto& location =
+ bookmark->FindKeyOfType("location", base::Value::Type::STRING)->GetString();
+
+ ImportedBookmarkEntry imported_bookmark;
+ imported_bookmark.is_folder = false;
+ imported_bookmark.in_toolbar = in_toolbar;
+ imported_bookmark.url = GURL(location);
+ imported_bookmark.path = path;
+ imported_bookmark.title = base::UTF8ToUTF16(title);
+ // Brave doesn't specify a creation time for the bookmark.
+ imported_bookmark.creation_time = base::Time::Now();
+ bookmarks->push_back(imported_bookmark);
+ }
+ }
+}
+
+void BraveImporter::ImportBookmarks() {
+ std::vector bookmarks;
+ ParseBookmarks(&bookmarks);
+
+ if (!bookmarks.empty() && !cancelled()) {
+ const base::string16& first_folder_name =
+ bridge_->GetLocalizedString(IDS_BOOKMARK_GROUP_FROM_BRAVE);
+ bridge_->AddBookmarks(bookmarks, first_folder_name);
+ }
+}
+
+double BraveImporter::chromeTimeToDouble(int64_t time) {
+ return ((time * 10 - 0x19DB1DED53E8000) / 10000) / 1000;
+}
+
+void BraveImporter::ImportPasswords() {
+#if !defined(USE_X11)
+ base::FilePath passwords_path =
+ source_path_.Append(
+ base::FilePath::StringType(FILE_PATH_LITERAL("Login Data")));
+
+ password_manager::LoginDatabase database(passwords_path);
+ if (!database.Init()) {
+ LOG(ERROR) << "LoginDatabase Init() failed";
+ return;
+ }
+
+ std::vector> forms;
+ bool success = database.GetAutofillableLogins(&forms);
+ if (success) {
+ for (size_t i = 0; i < forms.size(); ++i) {
+ bridge_->SetPasswordForm(*forms[i].get());
+ }
+ }
+ std::vector> blacklist;
+ success = database.GetBlacklistLogins(&blacklist);
+ if (success) {
+ for (size_t i = 0; i < blacklist.size(); ++i) {
+ bridge_->SetPasswordForm(*blacklist[i].get());
+ }
+ }
+#else
+ base::FilePath prefs_path =
+ source_path_.Append(
+ base::FilePath::StringType(FILE_PATH_LITERAL("UserPrefs")));
+ const base::Value *value;
+ scoped_refptr prefs = new JsonPrefStore(prefs_path);
+ int local_profile_id;
+ if (prefs->ReadPrefs() != PersistentPrefStore::PREF_READ_ERROR_NONE) {
+ return;
+ }
+ if (!prefs->GetValue(password_manager::prefs::kLocalProfileId, &value)) {
+ return;
+ }
+ if (!value->GetAsInteger(&local_profile_id)) {
+ return;
+ }
+
+ std::unique_ptr backend;
+ base::nix::DesktopEnvironment desktop_env = GetDesktopEnvironment();
+
+ // WIP proper kEnableEncryptionSelection
+ os_crypt::SelectedLinuxBackend selected_backend =
+ os_crypt::SelectBackend(std::string(), true, desktop_env);
+ if (!backend &&
+ (selected_backend == os_crypt::SelectedLinuxBackend::KWALLET ||
+ selected_backend == os_crypt::SelectedLinuxBackend::KWALLET5)) {
+ base::nix::DesktopEnvironment used_desktop_env =
+ selected_backend == os_crypt::SelectedLinuxBackend::KWALLET
+ ? base::nix::DESKTOP_ENVIRONMENT_KDE4
+ : base::nix::DESKTOP_ENVIRONMENT_KDE5;
+ backend.reset(new NativeBackendKWallet(local_profile_id,
+ used_desktop_env));
+ } else if (selected_backend == os_crypt::SelectedLinuxBackend::GNOME_ANY ||
+ selected_backend ==
+ os_crypt::SelectedLinuxBackend::GNOME_KEYRING ||
+ selected_backend ==
+ os_crypt::SelectedLinuxBackend::GNOME_LIBSECRET) {
+#if defined(USE_LIBSECRET)
+ if (!backend &&
+ (selected_backend == os_crypt::SelectedLinuxBackend::GNOME_ANY ||
+ selected_backend == os_crypt::SelectedLinuxBackend::GNOME_LIBSECRET)) {
+ backend.reset(new NativeBackendLibsecret(local_profile_id));
+ }
+#endif
+ }
+ if (backend && backend->Init()) {
+ std::vector> forms;
+ bool success = backend->GetAutofillableLogins(&forms);
+ if (success) {
+ for (size_t i = 0; i < forms.size(); ++i) {
+ bridge_->SetPasswordForm(*forms[i].get());
+ }
+ }
+ std::vector> blacklist;
+ success = backend->GetBlacklistLogins(&blacklist);
+ if (success) {
+ for (size_t i = 0; i < blacklist.size(); ++i) {
+ bridge_->SetPasswordForm(*blacklist[i].get());
+ }
+ }
+ }
+#endif
+}
+
+void BraveImporter::ImportCookies() {
+ base::FilePath cookies_path =
+ source_path_.Append(
+ base::FilePath::StringType(FILE_PATH_LITERAL("Cookies")));
+ if (!base::PathExists(cookies_path))
+ return;
+
+ sql::Connection db;
+ if (!db.Open(cookies_path))
+ return;
+
+ const char query[] =
+ "SELECT creation_utc, host_key, name, value, encrypted_value, path, "
+ "expires_utc, is_secure, is_httponly, firstpartyonly, last_access_utc, "
+ "has_expires, is_persistent, priority FROM cookies";
+
+ sql::Statement s(db.GetUniqueStatement(query));
+
+ net::CookieCryptoDelegate* delegate =
+ cookie_config::GetCookieCryptoDelegate();
+#if defined(OS_LINUX)
+ OSCrypt::SetConfig(std::make_unique());
+#endif
+
+ std::vector cookies;
+ while (s.Step() && !cancelled()) {
+ std::string encrypted_value = s.ColumnString(4);
+ std::string value;
+ if (!encrypted_value.empty() && delegate) {
+ if (!delegate->DecryptString(encrypted_value, &value)) {
+ continue;
+ }
+ } else {
+ value = s.ColumnString(3);
+ }
+
+ auto cookie = net::CanonicalCookie(
+ s.ColumnString(2), // name
+ value, // value
+ s.ColumnString(1), // domain
+ s.ColumnString(5), // path
+ Time::FromInternalValue(s.ColumnInt64(0)), // creation_utc
+ Time::FromInternalValue(s.ColumnInt64(6)), // expires_utc
+ Time::FromInternalValue(s.ColumnInt64(10)), // last_access_utc
+ s.ColumnBool(7), // secure
+ s.ColumnBool(8), // http_only
+ static_cast(s.ColumnInt(9)), // samesite
+ static_cast(s.ColumnInt(13))); // priority
+ if (cookie.IsCanonical()) {
+ cookies.push_back(cookie);
+ }
+ }
+
+ if (!cookies.empty() && !cancelled()) {
+ bridge_->SetCookies(cookies);
+ }
+}
diff --git a/utility/importer/brave_importer.h b/utility/importer/brave_importer.h
new file mode 100644
index 00000000000..5fbb80727d4
--- /dev/null
+++ b/utility/importer/brave_importer.h
@@ -0,0 +1,58 @@
+/* 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_UTILITY_IMPORTER_BRAVE_IMPORTER_H_
+#define BRAVE_UTILITY_IMPORTER_BRAVE_IMPORTER_H_
+
+#include
+
+#include