diff --git a/patches/chrome-browser-resources-settings-people_page-import_data_dialog.js.patch b/patches/chrome-browser-resources-settings-people_page-import_data_dialog.js.patch
index fd816cdbe08e..48bd85a4ce92 100644
--- a/patches/chrome-browser-resources-settings-people_page-import_data_dialog.js.patch
+++ b/patches/chrome-browser-resources-settings-people_page-import_data_dialog.js.patch
@@ -1,8 +1,8 @@
diff --git a/chrome/browser/resources/settings/people_page/import_data_dialog.js b/chrome/browser/resources/settings/people_page/import_data_dialog.js
-index f59448f4b4a25ab8b5e13c23feafa7957e83fa82..2d331bf9a60643ca0d92cba645acd3854d6af415 100644
+index f59448f4b4a25ab8b5e13c23feafa7957e83fa82..c6b7510e288db3dc6259ca80730f62235b1220d3 100644
--- a/chrome/browser/resources/settings/people_page/import_data_dialog.js
+++ b/chrome/browser/resources/settings/people_page/import_data_dialog.js
-@@ -84,7 +84,13 @@ Polymer({
+@@ -84,7 +84,15 @@ Polymer({
!(this.getPref('import_dialog_search_engine').value &&
this.selected_.search) &&
!(this.getPref('import_dialog_autofill_form_data').value &&
@@ -13,7 +13,9 @@ index f59448f4b4a25ab8b5e13c23feafa7957e83fa82..2d331bf9a60643ca0d92cba645acd385
+ !(this.getPref('import_dialog_stats').value &&
+ this.selected_.stats) &&
+ !(this.getPref('import_dialog_ledger').value &&
-+ this.selected_.ledger);
++ this.selected_.ledger) &&
++ !(this.getPref('import_dialog_windows').value &&
++ this.selected_.windows);
},
/**
diff --git a/patches/chrome-browser-ui-webui-settings-settings_import_data_handler.cc.patch b/patches/chrome-browser-ui-webui-settings-settings_import_data_handler.cc.patch
index 15a4e640e1e2..2e3e69ff5c52 100644
--- a/patches/chrome-browser-ui-webui-settings-settings_import_data_handler.cc.patch
+++ b/patches/chrome-browser-ui-webui-settings-settings_import_data_handler.cc.patch
@@ -1,5 +1,5 @@
diff --git a/chrome/browser/ui/webui/settings/settings_import_data_handler.cc b/chrome/browser/ui/webui/settings/settings_import_data_handler.cc
-index 32deebd14fb3383010af01381af9b34442d19b6e..ad94e6f86baa371f8c0fd4a976cfac28e612969d 100644
+index 32deebd14fb3383010af01381af9b34442d19b6e..823ce59a8e13a49965cb5d7026fa9d7f426de740 100644
--- a/chrome/browser/ui/webui/settings/settings_import_data_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_import_data_handler.cc
@@ -18,6 +18,8 @@
@@ -26,7 +26,7 @@ index 32deebd14fb3383010af01381af9b34442d19b6e..ad94e6f86baa371f8c0fd4a976cfac28
importer::LogImporterUseToMetrics("ImportDataHandler",
source_profile.importer_type);
-@@ -126,6 +128,12 @@ void ImportDataHandler::ImportData(const base::ListValue* args) {
+@@ -126,6 +128,14 @@ void ImportDataHandler::ImportData(const base::ListValue* args) {
selected_items |= importer::PASSWORDS;
if (prefs->GetBoolean(prefs::kImportDialogSearchEngine))
selected_items |= importer::SEARCH_ENGINES;
@@ -36,10 +36,12 @@ index 32deebd14fb3383010af01381af9b34442d19b6e..ad94e6f86baa371f8c0fd4a976cfac28
+ selected_items |= importer::STATS;
+ if (prefs->GetBoolean(prefs::kImportDialogLedger))
+ selected_items |= importer::LEDGER;
++ if (prefs->GetBoolean(prefs::kImportDialogWindows))
++ selected_items |= importer::WINDOWS;
const importer::SourceProfile& source_profile =
importer_list_->GetSourceProfileAt(browser_index);
-@@ -179,6 +187,12 @@ void ImportDataHandler::SendBrowserProfileData(const std::string& callback_id) {
+@@ -179,6 +189,14 @@ void ImportDataHandler::SendBrowserProfileData(const std::string& callback_id) {
browser_profile->SetBoolean(
"autofillFormData",
(browser_services & importer::AUTOFILL_FORM_DATA) != 0);
@@ -49,6 +51,8 @@ index 32deebd14fb3383010af01381af9b34442d19b6e..ad94e6f86baa371f8c0fd4a976cfac28
+ (browser_services & importer::STATS) != 0);
+ browser_profile->SetBoolean("ledger",
+ (browser_services & importer::LEDGER) != 0);
++ browser_profile->SetBoolean("windows",
++ (browser_services & importer::WINDOWS) != 0);
browser_profiles.Append(std::move(browser_profile));
}
diff --git a/patches/chrome-common-importer-importer_bridge.h.patch b/patches/chrome-common-importer-importer_bridge.h.patch
index 4ef322a4631d..a0a06243a342 100644
--- a/patches/chrome-common-importer-importer_bridge.h.patch
+++ b/patches/chrome-common-importer-importer_bridge.h.patch
@@ -1,8 +1,8 @@
diff --git a/chrome/common/importer/importer_bridge.h b/chrome/common/importer/importer_bridge.h
-index b4250c91d1b83ea920b3de9cd6b1a7929b30ffc5..9cc21253653ca8add3fac72462ed1010bb97f988 100644
+index b4250c91d1b83ea920b3de9cd6b1a7929b30ffc5..d36edb5a93f0d0117bb368c15693e8fc91272d3c 100644
--- a/chrome/common/importer/importer_bridge.h
+++ b/chrome/common/importer/importer_bridge.h
-@@ -58,6 +58,18 @@ class ImporterBridge : public base::RefCountedThreadSafe
{
+@@ -58,6 +58,21 @@ class ImporterBridge : public base::RefCountedThreadSafe {
virtual void SetAutofillFormData(
const std::vector& entries) = 0;
@@ -17,6 +17,9 @@ index b4250c91d1b83ea920b3de9cd6b1a7929b30ffc5..9cc21253653ca8add3fac72462ed1010
+
+ virtual void UpdateReferral(
+ const BraveReferral& referral) {};
++
++ virtual void UpdateWindows(
++ const ImportedWindowState& windowState) {};
+
// Notifies the coordinator that the import operation has begun.
virtual void NotifyStarted() = 0;
diff --git a/patches/chrome-common-importer-importer_data_types.h.patch b/patches/chrome-common-importer-importer_data_types.h.patch
index 62d833680de9..38b42847f6cc 100644
--- a/patches/chrome-common-importer-importer_data_types.h.patch
+++ b/patches/chrome-common-importer-importer_data_types.h.patch
@@ -1,19 +1,20 @@
diff --git a/chrome/common/importer/importer_data_types.h b/chrome/common/importer/importer_data_types.h
-index 0fc90c62398a93eb89568ce78c8ded2bc9b232b6..e27ec2fe408eea77390a080abf697a393a9cd517 100644
+index 0fc90c62398a93eb89568ce78c8ded2bc9b232b6..91632164e1b45fafb5befb71557993c87fe29462 100644
--- a/chrome/common/importer/importer_data_types.h
+++ b/chrome/common/importer/importer_data_types.h
-@@ -31,7 +31,9 @@ enum ImportItem {
+@@ -31,7 +31,10 @@ enum ImportItem {
SEARCH_ENGINES = 1 << 4,
HOME_PAGE = 1 << 5,
AUTOFILL_FORM_DATA = 1 << 6,
- ALL = (1 << 7) - 1 // All the bits should be 1, hence the -1.
+ STATS = 1 << 7,
+ LEDGER = 1 << 8,
-+ ALL = (1 << 9) - 1 // All the bits should be 1, hence the -1.
++ WINDOWS = 1 << 9,
++ ALL = (1 << 10) - 1 // All the bits should be 1, hence the -1.
};
// Information about a profile needed by an importer to do import work.
-@@ -83,6 +85,8 @@ enum VisitSource {
+@@ -83,6 +86,8 @@ enum VisitSource {
VISIT_SOURCE_FIREFOX_IMPORTED = 1,
VISIT_SOURCE_IE_IMPORTED = 2,
VISIT_SOURCE_SAFARI_IMPORTED = 3,
diff --git a/patches/chrome-common-importer-profile_import.mojom.patch b/patches/chrome-common-importer-profile_import.mojom.patch
index efdea516c94b..fc13ba3d9240 100644
--- a/patches/chrome-common-importer-profile_import.mojom.patch
+++ b/patches/chrome-common-importer-profile_import.mojom.patch
@@ -1,5 +1,5 @@
diff --git a/chrome/common/importer/profile_import.mojom b/chrome/common/importer/profile_import.mojom
-index 081955be7142f8a1ffdd68e19e30baa3b303586e..f60a769d673136f5037c565e08d221a39f06de32 100644
+index 081955be7142f8a1ffdd68e19e30baa3b303586e..f73b88a374a18a69b9551cf3f702ebdd5992d11d 100644
--- a/chrome/common/importer/profile_import.mojom
+++ b/chrome/common/importer/profile_import.mojom
@@ -6,6 +6,7 @@ module chrome.mojom;
@@ -10,7 +10,7 @@ index 081955be7142f8a1ffdd68e19e30baa3b303586e..f60a769d673136f5037c565e08d221a3
import "url/mojom/url.mojom";
const string kProfileImportServiceName = "profile_import";
-@@ -31,6 +32,15 @@ struct FaviconUsageDataList;
+@@ -31,6 +32,24 @@ struct FaviconUsageDataList;
[Native]
struct ImporterIE7PasswordInfo;
@@ -22,11 +22,20 @@ index 081955be7142f8a1ffdd68e19e30baa3b303586e..f60a769d673136f5037c565e08d221a3
+
+[Native]
+struct BraveReferral;
++
++[Native]
++struct ImportedBrowserTab;
++
++[Native]
++struct ImportedBrowserWindow;
++
++[Native]
++struct ImportedWindowState;
+
[Native]
enum ImportItem;
-@@ -64,6 +74,11 @@ interface ProfileImportObserver {
+@@ -64,6 +83,12 @@ interface ProfileImportObserver {
OnAutofillFormDataImportStart(uint32 total_autofill_form_data_entry_count);
OnAutofillFormDataImportGroup(
array autofill_form_data_entry_group);
@@ -35,6 +44,7 @@ index 081955be7142f8a1ffdd68e19e30baa3b303586e..f60a769d673136f5037c565e08d221a3
+ OnStatsImportReady(BraveStats stats);
+ OnLedgerImportReady(BraveLedger ledger);
+ OnReferralImportReady(BraveReferral referral);
++ OnWindowsImportReady(ImportedWindowState window_state);
};
// This interface is used to control the import process.
diff --git a/patches/chrome-common-importer-profile_import.typemap.patch b/patches/chrome-common-importer-profile_import.typemap.patch
index 0989dcef6a23..afe973b45cbb 100644
--- a/patches/chrome-common-importer-profile_import.typemap.patch
+++ b/patches/chrome-common-importer-profile_import.typemap.patch
@@ -1,18 +1,19 @@
diff --git a/chrome/common/importer/profile_import.typemap b/chrome/common/importer/profile_import.typemap
-index 6283f2bf6871a10f710694772b5da0bc9b70c2ad..aff217801c7c8a2d6c1bdeeded1c266122a66302 100644
+index 6283f2bf6871a10f710694772b5da0bc9b70c2ad..e11821c72ba2d1adc36c6ca6d362f10a5f501b66 100644
--- a/chrome/common/importer/profile_import.typemap
+++ b/chrome/common/importer/profile_import.typemap
-@@ -4,6 +4,9 @@
+@@ -4,6 +4,10 @@
mojom = "//chrome/common/importer/profile_import.mojom"
public_headers = [
+ "//brave/common/importer/brave_ledger.h",
+ "//brave/common/importer/brave_stats.h",
+ "//brave/common/importer/brave_referral.h",
++ "//brave/common/importer/imported_browser_window.h",
"//chrome/common/importer/imported_bookmark_entry.h",
"//chrome/common/importer/importer_autofill_form_data_entry.h",
"//chrome/common/importer/importer_data_types.h",
-@@ -13,6 +16,7 @@ public_headers = [
+@@ -13,6 +17,7 @@ public_headers = [
traits_headers =
[ "//chrome/common/importer/profile_import_process_param_traits.h" ]
deps = [
@@ -20,11 +21,14 @@ index 6283f2bf6871a10f710694772b5da0bc9b70c2ad..aff217801c7c8a2d6c1bdeeded1c2661
"//chrome/common",
"//components/favicon_base",
"//ipc",
-@@ -26,4 +30,7 @@ type_mappings = [
+@@ -26,4 +31,10 @@ type_mappings = [
"chrome.mojom.SearchEngineInfo=::importer::SearchEngineInfo",
"chrome.mojom.SourceProfile=::importer::SourceProfile",
"chrome.mojom.ImportItem=::importer::ImportItem",
+ "chrome.mojom.BraveStats=::BraveStats",
+ "chrome.mojom.BraveLedger=::BraveLedger",
+ "chrome.mojom.BraveReferral=::BraveReferral",
++ "chrome.mojom.ImportedBrowserTab=::ImportedBrowserTab",
++ "chrome.mojom.ImportedBrowserWindow=::ImportedBrowserWindow",
++ "chrome.mojom.ImportedWindowState=::ImportedWindowState",
]
diff --git a/utility/importer/brave_external_process_importer_bridge.cc b/utility/importer/brave_external_process_importer_bridge.cc
index b3dea84b2020..c221c52d423b 100644
--- a/utility/importer/brave_external_process_importer_bridge.cc
+++ b/utility/importer/brave_external_process_importer_bridge.cc
@@ -54,6 +54,11 @@ void BraveExternalProcessImporterBridge::UpdateReferral(
(*observer_)->OnReferralImportReady(referral);
}
+void BraveExternalProcessImporterBridge::UpdateWindows(
+ const ImportedWindowState& windowState) {
+ (*observer_)->OnWindowsImportReady(windowState);
+}
+
BraveExternalProcessImporterBridge::BraveExternalProcessImporterBridge(
const base::flat_map& localized_strings,
scoped_refptr observer)
diff --git a/utility/importer/brave_external_process_importer_bridge.h b/utility/importer/brave_external_process_importer_bridge.h
index 45d76cd3f7a9..4e4a25bee135 100644
--- a/utility/importer/brave_external_process_importer_bridge.h
+++ b/utility/importer/brave_external_process_importer_bridge.h
@@ -23,6 +23,7 @@ class BraveExternalProcessImporterBridge :
void UpdateStats(const BraveStats& stats) override;
void UpdateLedger(const BraveLedger& ledger) override;
void UpdateReferral(const BraveReferral& referral) override;
+ void UpdateWindows(const ImportedWindowState& windowState) override;
private:
~BraveExternalProcessImporterBridge() override;
diff --git a/utility/importer/brave_importer.cc b/utility/importer/brave_importer.cc
index f0ae9679eb74..5daa976feb3f 100644
--- a/utility/importer/brave_importer.cc
+++ b/utility/importer/brave_importer.cc
@@ -4,6 +4,7 @@
#include "brave/utility/importer/brave_importer.h"
+#include
#include
#include
#include
@@ -18,6 +19,7 @@
#include "brave/common/importer/brave_ledger.h"
#include "brave/common/importer/brave_stats.h"
#include "brave/common/importer/brave_referral.h"
+#include "brave/common/importer/imported_browser_window.h"
#include "chrome/common/importer/importer_bridge.h"
#include "chrome/grit/generated_resources.h"
#include "components/autofill/core/common/password_form.h"
@@ -101,6 +103,12 @@ void BraveImporter::StartImport(const importer::SourceProfile& source_profile,
bridge_->NotifyItemEnded(importer::STATS);
}
+ if ((items & importer::WINDOWS) && !cancelled()) {
+ bridge_->NotifyItemStarted(importer::WINDOWS);
+ ImportWindows();
+ bridge_->NotifyItemEnded(importer::WINDOWS);
+ }
+
if ((items & importer::LEDGER) && !cancelled()) {
bridge_->NotifyItemStarted(importer::LEDGER);
// NOTE: RecoverWallet is async.
@@ -653,3 +661,151 @@ void BraveImporter::ImportReferral() {
bridge_->UpdateReferral(referral);
}
+
+std::vector ParseTabs(const base::Value* frames) {
+ std::vector tabs;
+
+ for (const auto& frame : frames->GetList()) {
+ auto* key = frame.FindKeyOfType("key",
+ base::Value::Type::INTEGER);
+ auto* location = frame.FindKeyOfType("location",
+ base::Value::Type::STRING);
+
+ if (!(key && location))
+ continue;
+
+ ImportedBrowserTab tab;
+ tab.key = key->GetInt();
+ // TODO filter locations that won't work in b-c, e.g. about:preferences, about:newtab, chrome-extension:// (for PDFs), etc.
+ tab.location = GURL(location->GetString());
+
+ tabs.push_back(tab);
+ }
+
+ return tabs;
+}
+
+std::vector ParseWindows(
+ const base::Value* perWindowState) {
+ std::vector windows;
+
+ for (const auto& entry : perWindowState->GetList()) {
+ ImportedBrowserWindow window;
+
+ auto* windowInfo = entry.FindKeyOfType("windowInfo",
+ base::Value::Type::DICTIONARY);
+ auto* activeFrameKey = entry.FindKeyOfType("activeFrameKey",
+ base::Value::Type::INTEGER);
+ auto* frames = entry.FindKeyOfType("frames",
+ base::Value::Type::LIST);
+
+ if (!(frames && activeFrameKey && windowInfo))
+ continue;
+
+ // Window info
+ auto* top = windowInfo->FindKeyOfType("top",
+ base::Value::Type::INTEGER);
+ auto* left = windowInfo->FindKeyOfType("left",
+ base::Value::Type::INTEGER);
+ auto* width = windowInfo->FindKeyOfType("width",
+ base::Value::Type::INTEGER);
+ auto* height = windowInfo->FindKeyOfType("height",
+ base::Value::Type::INTEGER);
+ auto* focused = windowInfo->FindKeyOfType("focused",
+ base::Value::Type::BOOLEAN);
+ auto* type = windowInfo->FindKeyOfType("type",
+ base::Value::Type::STRING);
+ auto* state = windowInfo->FindKeyOfType("state",
+ base::Value::Type::STRING);
+
+ if (!(top && left && width && height && focused && type && state)) {
+ LOG(WARNING) << "windowInfo failed validation, skipping window";
+ continue;
+ }
+
+ // "type" is one of: "normal", "popup", or "devtools"
+ if (type->GetString() != "normal") {
+ LOG(INFO) << "windowInfo type not normal, skipping window";
+ continue;
+ }
+
+ window.top = top->GetInt();
+ window.left = left->GetInt();
+ window.width = width->GetInt();
+ window.height = height->GetInt();
+ window.focused = focused->GetBool();
+ window.state = state->GetString();
+ window.activeFrameKey = activeFrameKey->GetInt();
+
+ window.tabs = ParseTabs(frames);
+
+ windows.push_back(window);
+ }
+
+ return windows;
+}
+
+std::vector ParsePinnedTabs(
+ const base::Value* pinnedSites) {
+ std::vector pinnedTabs;
+
+ for (const auto& item : pinnedSites->DictItems()) {
+ const auto& value = item.second;
+ if (!value.is_dict())
+ continue;
+
+ const base::Value* location =
+ value.FindKeyOfType("location",
+ base::Value::Type::STRING);
+ const base::Value* order =
+ value.FindKeyOfType("order",
+ base::Value::Type::INTEGER);
+
+ if (!(location && order))
+ continue;
+
+ ImportedBrowserTab tab;
+ tab.key = order->GetInt();
+ tab.location = GURL(location->GetString());
+ pinnedTabs.push_back(tab);
+ }
+
+ // Sort pinned tabs by key, which corresponds to a 0-indexed ordering from
+ // left to right.
+ std::sort(std::begin(pinnedTabs), std::end(pinnedTabs),
+ [](auto a, auto b) { return a.key < b.key; });
+
+ return pinnedTabs;
+}
+
+void BraveImporter::ImportWindows() {
+ std::unique_ptr session_store_json = ParseBraveStateFile(
+ "session-store-1");
+ if (!session_store_json)
+ return;
+
+ base::Value* perWindowState =
+ session_store_json->FindKeyOfType("perWindowState",
+ base::Value::Type::LIST);
+ base::Value* pinnedSites =
+ session_store_json->FindKeyOfType("pinnedSites",
+ base::Value::Type::DICTIONARY);
+ if (!(perWindowState && pinnedSites)) {
+ LOG(ERROR) << "perWindowState and/or pinnedSites not found";
+ return;
+ }
+
+ std::vector windows = ParseWindows(perWindowState);
+
+ // Pinned tabs are global in browser-laptop, while they are per-tab in
+ // brave-core. To manage this transition, import all pinned tabs into the
+ // first imported window only.
+ std::vector pinnedTabs = ParsePinnedTabs(pinnedSites);
+
+ if (!windows.empty() && !cancelled()) {
+ ImportedWindowState windowState;
+ windowState.windows = windows;
+ windowState.pinnedTabs = pinnedTabs;
+ bridge_->UpdateWindows(windowState);
+ }
+}
diff --git a/utility/importer/brave_importer.h b/utility/importer/brave_importer.h
index 804076c9e364..97fe8dabc0cb 100644
--- a/utility/importer/brave_importer.h
+++ b/utility/importer/brave_importer.h
@@ -34,6 +34,7 @@ class BraveImporter : public ChromeImporter {
void ImportHistory() override;
void ImportStats();
void ImportLedger();
+ void ImportWindows();
void ImportReferral();
std::unique_ptr ParseBraveStateFile(
diff --git a/utility/importer/brave_importer_unittest.cc b/utility/importer/brave_importer_unittest.cc
index 8a902806bd78..b0095da5c8ca 100644
--- a/utility/importer/brave_importer_unittest.cc
+++ b/utility/importer/brave_importer_unittest.cc
@@ -243,3 +243,7 @@ TEST_F(BraveImporterTest, ImportStats) {
TEST_F(BraveImporterTest, ImportLedger) {
// TODO
}
+
+TEST_F(BraveImporterTest, ImportWindows) {
+ // TODO
+}