migration: Preserve backward migration policy across restarts

Preserve the value of LacrosDataBackwardMigrationMode across Chrome
restarts. We need access to the value before the policy stack is
available.

Bug: b:244572632
TEST: tast run <ip> lacros.BackwardMigratePolicy
Change-Id: I0d0450351eff69a2082a7ab1bcf3a575e67c69db
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4075690
Reviewed-by: Jana Grill <janagrill@google.com>
Reviewed-by: Hidehiko Abe <hidehiko@chromium.org>
Commit-Queue: Victor-Gabriel Savu <vsavu@google.com>
Cr-Commit-Position: refs/heads/main@{#1081412}
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index c144068..f8ae7f7 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -978,6 +978,22 @@
      crosapi::browser_util::kLacrosAvailabilityPolicyLacrosOnly},
 };
 
+const FeatureEntry::Choice kLacrosDataBackwardMigrationModePolicyChoices[] = {
+    {flags_ui::kGenericExperimentChoiceDefault, "", ""},
+    {crosapi::browser_util::kLacrosDataBackwardMigrationModePolicyNone,
+     crosapi::browser_util::kLacrosDataBackwardMigrationModePolicySwitch,
+     crosapi::browser_util::kLacrosDataBackwardMigrationModePolicyNone},
+    {crosapi::browser_util::kLacrosDataBackwardMigrationModePolicyKeepNone,
+     crosapi::browser_util::kLacrosDataBackwardMigrationModePolicySwitch,
+     crosapi::browser_util::kLacrosDataBackwardMigrationModePolicyKeepNone},
+    {crosapi::browser_util::kLacrosDataBackwardMigrationModePolicyKeepSafeData,
+     crosapi::browser_util::kLacrosDataBackwardMigrationModePolicySwitch,
+     crosapi::browser_util::kLacrosDataBackwardMigrationModePolicyKeepSafeData},
+    {crosapi::browser_util::kLacrosDataBackwardMigrationModePolicyKeepAll,
+     crosapi::browser_util::kLacrosDataBackwardMigrationModePolicySwitch,
+     crosapi::browser_util::kLacrosDataBackwardMigrationModePolicyKeepAll},
+};
+
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 const FeatureEntry::Choice kForceUIDirectionChoices[] = {
@@ -3774,6 +3790,10 @@
     // Used to carry the policy value crossing the Chrome process lifetime.
     {crosapi::browser_util::kLacrosAvailabilityPolicyInternalName, "", "",
      kOsCrOS, MULTI_VALUE_TYPE(kLacrosAvailabilityPolicyChoices)},
+    // Used to carry the policy value crossing the Chrome process lifetime.
+    {crosapi::browser_util::kLacrosDataBackwardMigrationModePolicyInternalName,
+     "", "", kOsCrOS,
+     MULTI_VALUE_TYPE(kLacrosDataBackwardMigrationModePolicyChoices)},
     {kLacrosSupportInternalName, flag_descriptions::kLacrosSupportName,
      flag_descriptions::kLacrosSupportDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(ash::features::kLacrosSupport)},
@@ -9670,6 +9690,14 @@
     return true;
   }
 
+  // Skip lacros-backward-data-migration-policy always. This is a pseudo entry
+  // and used to carry the policy value crossing the Chrome's lifetime.
+  if (!strcmp(crosapi::browser_util::
+                  kLacrosDataBackwardMigrationModePolicyInternalName,
+              entry.internal_name)) {
+    return true;
+  }
+
   if (!strcmp(kPreferDcheckInternalName, entry.internal_name)) {
     return !crosapi::browser_util::IsLacrosAllowedToBeEnabled();
   }
diff --git a/chrome/browser/ash/chrome_browser_main_parts_ash.cc b/chrome/browser/ash/chrome_browser_main_parts_ash.cc
index ffccefa..6694a82 100644
--- a/chrome/browser/ash/chrome_browser_main_parts_ash.cc
+++ b/chrome/browser/ash/chrome_browser_main_parts_ash.cc
@@ -60,6 +60,7 @@
 #include "chrome/browser/ash/crosapi/browser_manager.h"
 #include "chrome/browser/ash/crosapi/crosapi_manager.h"
 #include "chrome/browser/ash/crosapi/lacros_availability_policy_observer.h"
+#include "chrome/browser/ash/crosapi/lacros_data_backward_migration_mode_policy_observer.h"
 #include "chrome/browser/ash/crostini/crostini_unsupported_action_notifier.h"
 #include "chrome/browser/ash/dbus/ash_dbus_helper.h"
 #include "chrome/browser/ash/dbus/chrome_features_service_provider.h"
@@ -995,6 +996,8 @@
   browser_manager_->AddObserver(SessionControllerClientImpl::Get());
   lacros_availability_policy_observer_ =
       std::make_unique<crosapi::LacrosAvailabilityPolicyObserver>();
+  lacros_data_backward_migration_mode_policy_observer_ = std::make_unique<
+      crosapi::LacrosDataBackwardMigrationModePolicyObserver>();
 
   chromeos::machine_learning::ServiceConnection::GetInstance()->Initialize();
 
@@ -1560,10 +1563,12 @@
   // Cleans up dbus services depending on ash.
   dbus_services_->PreAshShutdown();
 
-  // LacrosAvailabilityPolicyObserver has the dependency to ProfileManager,
-  // so it needs to be destroyed before ProfileManager destruction,
-  // which happens inside PostMainMessageLoop below.
+  // LacrosAvailabilityPolicyObserver and
+  // LacrosDataBackwardMigrationModePolicyObserver have the dependency to
+  // ProfileManager, so they need to be destroyed before ProfileManager
+  // destruction, which happens inside PostMainMessageLoop below.
   lacros_availability_policy_observer_.reset();
+  lacros_data_backward_migration_mode_policy_observer_.reset();
 
   multi_capture_notification_.reset();
 
diff --git a/chrome/browser/ash/chrome_browser_main_parts_ash.h b/chrome/browser/ash/chrome_browser_main_parts_ash.h
index 24aa5882..45cee61 100644
--- a/chrome/browser/ash/chrome_browser_main_parts_ash.h
+++ b/chrome/browser/ash/chrome_browser_main_parts_ash.h
@@ -41,6 +41,7 @@
 class BrowserManager;
 class CrosapiManager;
 class LacrosAvailabilityPolicyObserver;
+class LacrosDataBackwardMigrationModePolicyObserver;
 }  // namespace crosapi
 
 namespace crostini {
@@ -220,6 +221,8 @@
   std::unique_ptr<crosapi::BrowserManager> browser_manager_;
   std::unique_ptr<crosapi::LacrosAvailabilityPolicyObserver>
       lacros_availability_policy_observer_;
+  std::unique_ptr<crosapi::LacrosDataBackwardMigrationModePolicyObserver>
+      lacros_data_backward_migration_mode_policy_observer_;
 
   std::unique_ptr<power::SmartChargingManager> smart_charging_manager_;
 
diff --git a/chrome/browser/ash/crosapi/BUILD.gn b/chrome/browser/ash/crosapi/BUILD.gn
index de0ac9c..899cd25 100644
--- a/chrome/browser/ash/crosapi/BUILD.gn
+++ b/chrome/browser/ash/crosapi/BUILD.gn
@@ -147,6 +147,8 @@
     "kiosk_session_service_ash.h",
     "lacros_availability_policy_observer.cc",
     "lacros_availability_policy_observer.h",
+    "lacros_data_backward_migration_mode_policy_observer.cc",
+    "lacros_data_backward_migration_mode_policy_observer.h",
     "local_printer_ash.cc",
     "local_printer_ash.h",
     "login_ash.cc",
@@ -423,6 +425,7 @@
     "geolocation_service_ash_unittest.cc",
     "keystore_service_ash_unittest.cc",
     "lacros_availability_policy_observer_unittest.cc",
+    "lacros_data_backward_migration_mode_policy_observer_unittest.cc",
     "local_printer_ash_unittest.cc",
     "login_screen_storage_ash_unittest.cc",
     "login_state_ash_unittest.cc",
diff --git a/chrome/browser/ash/crosapi/OWNERS b/chrome/browser/ash/crosapi/OWNERS
index 895395d8..c3aebf3 100644
--- a/chrome/browser/ash/crosapi/OWNERS
+++ b/chrome/browser/ash/crosapi/OWNERS
@@ -2,4 +2,7 @@
 
 per-file browser_data_back_migrator.cc=janagrill@google.com,vsavu@google.com
 per-file browser_data_back_migrator.h=janagrill@google.com,vsavu@google.com
-per-file browser_data_back_migrator_unittest.cc=janagrill@google.com,vsavu@google.com
\ No newline at end of file
+per-file browser_data_back_migrator_unittest.cc=janagrill@google.com,vsavu@google.com
+per-file lacros_data_backward_migration_mode_policy_observer.cc=janagrill@google.com,vsavu@google.com
+per-file lacros_data_backward_migration_mode_policy_observer.h=janagrill@google.com,vsavu@google.com
+per-file lacros_data_backward_migration_mode_policy_observer_unittest.cc=janagrill@google.com,vsavu@google.com
diff --git a/chrome/browser/ash/crosapi/browser_data_back_migrator.cc b/chrome/browser/ash/crosapi/browser_data_back_migrator.cc
index a776344b..2eef17ff 100644
--- a/chrome/browser/ash/crosapi/browser_data_back_migrator.cc
+++ b/chrome/browser/ash/crosapi/browser_data_back_migrator.cc
@@ -1105,7 +1105,15 @@
       crosapi::browser_util::LacrosDataBackwardMigrationMode::kNone;
   if (policy_init_state ==
       crosapi::browser_util::PolicyInitState::kBeforeInit) {
-    // TODO(b/244572632): Read cached flag.
+    auto parsed = crosapi::browser_util::ParseLacrosDataBackwardMigrationMode(
+        base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+            crosapi::browser_util::
+                kLacrosDataBackwardMigrationModePolicySwitch));
+
+    migration_mode =
+        parsed.has_value()
+            ? parsed.value()
+            : crosapi::browser_util::LacrosDataBackwardMigrationMode::kNone;
   } else {
     DCHECK_EQ(policy_init_state,
               crosapi::browser_util::PolicyInitState::kAfterInit);
diff --git a/chrome/browser/ash/crosapi/browser_data_back_migrator_unittest.cc b/chrome/browser/ash/crosapi/browser_data_back_migrator_unittest.cc
index a66c8b2..e261ddf 100644
--- a/chrome/browser/ash/crosapi/browser_data_back_migrator_unittest.cc
+++ b/chrome/browser/ash/crosapi/browser_data_back_migrator_unittest.cc
@@ -338,6 +338,7 @@
 }
 
 namespace {
+
 // This implementation of RAII for LacrosDataBackwardMigrationMode is intended
 // to make it easy reset the state between runs.
 class ScopedLacrosDataBackwardMigrationModeCache {
@@ -366,6 +367,29 @@
     crosapi::browser_util::CacheLacrosDataBackwardMigrationMode(policy);
   }
 };
+
+// This implementation of RAII for the backward migration flag to make it easy
+// to reset state between tests.
+class ScopedLacrosDataBackwardMigrationModeCommandLine {
+ public:
+  explicit ScopedLacrosDataBackwardMigrationModeCommandLine(
+      crosapi::browser_util::LacrosDataBackwardMigrationMode mode) {
+    base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
+    cmdline->AppendSwitchASCII(
+        crosapi::browser_util::kLacrosDataBackwardMigrationModePolicySwitch,
+        GetLacrosDataBackwardMigrationModeName(mode));
+  }
+  ScopedLacrosDataBackwardMigrationModeCommandLine(
+      const ScopedLacrosDataBackwardMigrationModeCommandLine&) = delete;
+  ScopedLacrosDataBackwardMigrationModeCommandLine& operator=(
+      const ScopedLacrosDataBackwardMigrationModeCommandLine&) = delete;
+  ~ScopedLacrosDataBackwardMigrationModeCommandLine() {
+    base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
+    cmdline->RemoveSwitch(
+        crosapi::browser_util::kLacrosDataBackwardMigrationModePolicySwitch);
+  }
+};
+
 }  // namespace
 
 class BrowserDataBackMigratorTriggeringTest : public testing::Test {
@@ -407,6 +431,15 @@
       crosapi::browser_util::PolicyInitState::kAfterInit));
 }
 
+TEST_F(BrowserDataBackMigratorTriggeringTest, PolicyEnabledBeforeInit) {
+  // Simulate the flag being set by session_manager.
+  ScopedLacrosDataBackwardMigrationModeCommandLine scoped_cmdline(
+      crosapi::browser_util::LacrosDataBackwardMigrationMode::kKeepAll);
+
+  EXPECT_TRUE(BrowserDataBackMigrator::IsBackMigrationEnabled(
+      crosapi::browser_util::PolicyInitState::kBeforeInit));
+}
+
 TEST_F(BrowserDataBackMigratorTriggeringTest, PolicyEnabledAfterInit) {
   ScopedLacrosDataBackwardMigrationModeCache scoped_policy(
       crosapi::browser_util::LacrosDataBackwardMigrationMode::kKeepAll);
diff --git a/chrome/browser/ash/crosapi/lacros_data_backward_migration_mode_policy_observer.cc b/chrome/browser/ash/crosapi/lacros_data_backward_migration_mode_policy_observer.cc
new file mode 100644
index 0000000..9fdc7e89
--- /dev/null
+++ b/chrome/browser/ash/crosapi/lacros_data_backward_migration_mode_policy_observer.cc
@@ -0,0 +1,81 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/crosapi/lacros_data_backward_migration_mode_policy_observer.h"
+
+#include "base/bind.h"
+#include "base/check.h"
+#include "base/command_line.h"
+#include "chrome/browser/ash/profiles/profile_helper.h"
+#include "chrome/browser/ash/settings/about_flags.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/common/pref_names.h"
+#include "components/flags_ui/pref_service_flags_storage.h"
+#include "components/prefs/pref_service.h"
+#include "content/public/common/content_switches.h"
+
+namespace crosapi {
+
+LacrosDataBackwardMigrationModePolicyObserver::
+    LacrosDataBackwardMigrationModePolicyObserver()
+    : profile_manager_(g_browser_process->profile_manager()),
+      local_state_(g_browser_process->local_state()) {
+  DCHECK(profile_manager_);
+  DCHECK(local_state_);
+  profile_manager_->AddObserver(this);
+}
+
+LacrosDataBackwardMigrationModePolicyObserver::
+    ~LacrosDataBackwardMigrationModePolicyObserver() {
+  profile_manager_->RemoveObserver(this);
+}
+
+void LacrosDataBackwardMigrationModePolicyObserver::OnProfileAdded(
+    Profile* profile) {
+  // Skip handling browser_tests.
+  // The main target of this class is to send a message to session_manager
+  // to preserve the lacros-backward-data-migration-policy policy. browser_tests
+  // is out of scope, and actually there will be multiple initialization of
+  // "Primary" Profile in a process, so it won't work as designed.
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kBrowserTest)) {
+    return;
+  }
+  if (!ash::ProfileHelper::IsPrimaryProfile(profile) ||
+      profile->IsOffTheRecord()) {
+    return;
+  }
+
+  // Start observing local_state since here. Even if we observe the local_state
+  // change (and actually it can happen though), we cannot send it to
+  // session_manager, because we have to send it with primary profile's feature
+  // flags together.
+  DCHECK(!primary_profile_);
+  primary_profile_ = profile;
+  pref_change_registrar_.Init(local_state_);
+  pref_change_registrar_.Add(
+      prefs::kLacrosDataBackwardMigrationMode,
+      base::BindRepeating(
+          &LacrosDataBackwardMigrationModePolicyObserver::OnChanged,
+          weak_factory_.GetWeakPtr()));
+  // And so, the value may be set earlier (on creation of profile), so invoke
+  // the callback synchronously here, if necessary.
+  if (local_state_->IsManagedPreference(
+          prefs::kLacrosDataBackwardMigrationMode))
+    OnChanged();
+}
+
+void LacrosDataBackwardMigrationModePolicyObserver::OnChanged() {
+  // Notify session_manager. The actual value for the
+  // kLacrosDataBackwardMigrationMode is calculated in FeatureFlagsUpdate.
+  DCHECK(primary_profile_);
+  PrefService* prefs = primary_profile_->GetPrefs();
+  flags_ui::PrefServiceFlagsStorage flags_storage(prefs);
+  ash::about_flags::FeatureFlagsUpdate update(flags_storage, prefs);
+  update.UpdateSessionManager();
+}
+
+}  // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/lacros_data_backward_migration_mode_policy_observer.h b/chrome/browser/ash/crosapi/lacros_data_backward_migration_mode_policy_observer.h
new file mode 100644
index 0000000..83c35d0
--- /dev/null
+++ b/chrome/browser/ash/crosapi/lacros_data_backward_migration_mode_policy_observer.h
@@ -0,0 +1,52 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_CROSAPI_LACROS_DATA_BACKWARD_MIGRATION_MODE_POLICY_OBSERVER_H_
+#define CHROME_BROWSER_ASH_CROSAPI_LACROS_DATA_BACKWARD_MIGRATION_MODE_POLICY_OBSERVER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/profiles/profile_manager_observer.h"
+#include "components/prefs/pref_change_registrar.h"
+
+class Profile;
+class PrefService;
+class ProfileManager;
+
+namespace crosapi {
+
+// Watches LacrosDataBackwardMigrationMode per_profile:False policy.
+// On its value update, send the message to session_manager to
+// preserve the update if it is restarted.
+// Specifically, this is designed to be used only for BrowserDataBackMigrator,
+// because it requires to run under very early stage (before policy
+// initialization) to avoid session data breakage.
+class LacrosDataBackwardMigrationModePolicyObserver
+    : public ProfileManagerObserver {
+ public:
+  LacrosDataBackwardMigrationModePolicyObserver();
+  LacrosDataBackwardMigrationModePolicyObserver(
+      const LacrosDataBackwardMigrationModePolicyObserver&) = delete;
+  LacrosDataBackwardMigrationModePolicyObserver& operator=(
+      const LacrosDataBackwardMigrationModePolicyObserver&) = delete;
+  ~LacrosDataBackwardMigrationModePolicyObserver() override;
+
+  // ProfileManagerObserver override.
+  void OnProfileAdded(Profile* profile) override;
+
+ private:
+  // Called when LacrosDataBackwardMigrationMode policy value is updated.
+  void OnChanged();
+
+  ProfileManager* const profile_manager_;
+  PrefService* const local_state_;
+  Profile* primary_profile_ = nullptr;
+
+  PrefChangeRegistrar pref_change_registrar_;
+  base::WeakPtrFactory<LacrosDataBackwardMigrationModePolicyObserver>
+      weak_factory_{this};
+};
+
+}  // namespace crosapi
+
+#endif  // CHROME_BROWSER_ASH_CROSAPI_LACROS_DATA_BACKWARD_MIGRATION_MODE_POLICY_OBSERVER_H_
diff --git a/chrome/browser/ash/crosapi/lacros_data_backward_migration_mode_policy_observer_unittest.cc b/chrome/browser/ash/crosapi/lacros_data_backward_migration_mode_policy_observer_unittest.cc
new file mode 100644
index 0000000..f55e460
--- /dev/null
+++ b/chrome/browser/ash/crosapi/lacros_data_backward_migration_mode_policy_observer_unittest.cc
@@ -0,0 +1,179 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/crosapi/lacros_data_backward_migration_mode_policy_observer.h"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/json/json_reader.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
+#include "chrome/browser/ash/profiles/profile_helper.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/testing_profile_manager.h"
+#include "chromeos/ash/components/cryptohome/cryptohome_parameters.h"
+#include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
+#include "components/account_id/account_id.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/user_manager/scoped_user_manager.h"
+#include "components/user_manager/user.h"
+#include "components/user_manager/user_manager.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/cros_system_api/switches/chrome_switches.h"
+
+namespace crosapi {
+
+class LacrosDataBackwardMigrationModePolicyObserverTest : public testing::Test {
+ public:
+  LacrosDataBackwardMigrationModePolicyObserverTest() = default;
+  LacrosDataBackwardMigrationModePolicyObserverTest(
+      const LacrosDataBackwardMigrationModePolicyObserverTest&) = delete;
+  LacrosDataBackwardMigrationModePolicyObserverTest& operator=(
+      const LacrosDataBackwardMigrationModePolicyObserverTest&) = delete;
+  ~LacrosDataBackwardMigrationModePolicyObserverTest() override = default;
+
+  void SetUp() override {
+    ash::SessionManagerClient::InitializeFake();
+    profile_manager_ = std::make_unique<TestingProfileManager>(
+        TestingBrowserProcess::GetGlobal());
+    // Add primary user.
+    auto* user_manager = static_cast<ash::FakeChromeUserManager*>(
+        user_manager::UserManager::Get());
+    test_user_ = user_manager->AddPublicAccountUser(
+        AccountId::FromUserEmailGaiaId("test@test.com", "test_user"));
+
+    ASSERT_TRUE(profile_manager_->SetUp());
+
+    // Set up ProfileHelper so that profile creation is always interpreted
+    // as if it is Primary profile creation.
+    ash::ProfileHelper::SetAlwaysReturnPrimaryUserForTesting(true);
+  }
+
+  void TearDown() override {
+    profile_manager_->DeleteAllTestingProfiles();
+    profile_manager_.reset();
+    ash::SessionManagerClient::Shutdown();
+  }
+
+  void CreatePrimaryProfile() {
+    if (!primary_profile_) {
+      auto* user_manager = static_cast<ash::FakeChromeUserManager*>(
+          user_manager::UserManager::Get());
+      user_manager->LoginUser(test_user_->GetAccountId(),
+                              /*set_profile_created_flag=*/true);
+      user_manager->SwitchActiveUser(test_user_->GetAccountId());
+      primary_profile_ = profile_manager_->CreateTestingProfile("test-profile");
+    }
+  }
+
+  std::vector<std::string> GetFeatureFlagsForPrimaryUser() {
+    auto account_id = cryptohome::CreateAccountIdentifierFromAccountId(
+        test_user_->GetAccountId());
+    std::vector<std::string> flags;
+    if (!ash::FakeSessionManagerClient::Get()->GetFlagsForUser(account_id,
+                                                               &flags))
+      return {};
+
+    const std::string prefix =
+        base::StringPrintf("--%s=", chromeos::switches::kFeatureFlags);
+    for (const std::string& flag : flags) {
+      if (base::StartsWith(flag, prefix)) {
+        base::StringPiece flag_value(flag);
+        flag_value.remove_prefix(prefix.size());
+        absl::optional<base::Value> parsed = base::JSONReader::Read(flag_value);
+        std::vector<std::string> result;
+        if (parsed && parsed->is_list()) {
+          for (const auto& element : parsed->GetList()) {
+            result.push_back(element.GetString());
+          }
+        }
+        return result;
+      }
+    }
+
+    // Not found.
+    return {};
+  }
+
+  TestingPrefServiceSimple* local_state() {
+    return profile_manager_->local_state()->Get();
+  }
+
+  content::BrowserTaskEnvironment task_environment_;
+  user_manager::ScopedUserManager scoped_user_manager_{
+      std::make_unique<user_manager::FakeUserManager>()};
+  std::unique_ptr<TestingProfileManager> profile_manager_;
+  user_manager::User* test_user_ = nullptr;
+  TestingProfile* primary_profile_ = nullptr;
+};
+
+TEST_F(LacrosDataBackwardMigrationModePolicyObserverTest, OnPolicyUpdate) {
+  LacrosDataBackwardMigrationModePolicyObserver observer;
+  CreatePrimaryProfile();
+
+  {
+    auto feature_flags = GetFeatureFlagsForPrimaryUser();
+    EXPECT_TRUE(feature_flags.empty());
+  }
+
+  local_state()->SetManagedPref(prefs::kLacrosDataBackwardMigrationMode,
+                                base::Value("keep_all"));
+
+  {
+    auto feature_flags = GetFeatureFlagsForPrimaryUser();
+    ASSERT_EQ(1u, feature_flags.size());
+    // Please find about_flags.cc for actual mapping of the enum value
+    // to the index.
+    EXPECT_EQ("lacros-data-backward-migration-policy@4", feature_flags[0]);
+  }
+
+  local_state()->SetManagedPref(prefs::kLacrosDataBackwardMigrationMode,
+                                base::Value("none"));
+
+  {
+    auto feature_flags = GetFeatureFlagsForPrimaryUser();
+    ASSERT_EQ(1u, feature_flags.size());
+    // Please find about_flags.cc for actual mapping of the enum value
+    // to the index.
+    EXPECT_EQ("lacros-data-backward-migration-policy@1", feature_flags[0]);
+  }
+}
+
+TEST_F(LacrosDataBackwardMigrationModePolicyObserverTest,
+       AroundPrimaryProfileCreation) {
+  LacrosDataBackwardMigrationModePolicyObserver observer;
+  {
+    auto feature_flags = GetFeatureFlagsForPrimaryUser();
+    EXPECT_TRUE(feature_flags.empty());
+  }
+
+  local_state()->SetManagedPref(prefs::kLacrosDataBackwardMigrationMode,
+                                base::Value("keep_all"));
+  // Do not update the feature_flags in session_manger, until primary profile
+  // is created.
+  {
+    auto feature_flags = GetFeatureFlagsForPrimaryUser();
+    EXPECT_TRUE(feature_flags.empty());
+  }
+
+  CreatePrimaryProfile();
+
+  // After the primary profile creation, then feature flag should set.
+  {
+    auto feature_flags = GetFeatureFlagsForPrimaryUser();
+    ASSERT_EQ(1u, feature_flags.size());
+    // Please find about_flags.cc for actual mapping of the enum value
+    // to the index.
+    EXPECT_EQ("lacros-data-backward-migration-policy@4", feature_flags[0]);
+  }
+}
+
+}  // namespace crosapi
diff --git a/chrome/browser/ash/settings/about_flags.cc b/chrome/browser/ash/settings/about_flags.cc
index 6d0acae..73fd594 100644
--- a/chrome/browser/ash/settings/about_flags.cc
+++ b/chrome/browser/ash/settings/about_flags.cc
@@ -229,6 +229,28 @@
     }
   }
 
+  const PrefService::Preference* lacros_data_backward_migration_mode_pref =
+      g_browser_process->local_state()->FindPreference(
+          ::prefs::kLacrosDataBackwardMigrationMode);
+  if (lacros_data_backward_migration_mode_pref->IsManaged()) {
+    auto value =
+        lacros_data_backward_migration_mode_pref->GetValue()->GetString();
+    auto* entry = ::about_flags::GetCurrentFlagsState()->FindFeatureEntryByName(
+        crosapi::browser_util::
+            kLacrosDataBackwardMigrationModePolicyInternalName);
+    DCHECK(entry);
+    int index;
+    for (index = 0; index < entry->NumOptions(); ++index) {
+      if (value == entry->ChoiceForOption(index).command_line_value)
+        break;
+    }
+    if (static_cast<size_t>(index) != entry->choices.size()) {
+      LOG(ERROR) << "Updating the lacros_data_backward_migration_mode: "
+                 << index;
+      flags.insert(entry->NameForOption(index));
+    }
+  }
+
   auto account_id = cryptohome::CreateAccountIdentifierFromAccountId(
       primary_user->GetAccountId());
   SessionManagerClient::Get()->SetFeatureFlagsForUser(
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 560f36b..cd3f52f 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -4371,6 +4371,15 @@
     "expiry_milestone": 120
   },
   {
+    "name": "lacros-data-backward-migration-policy",
+    "owners": [ "vsavu", "lacros-team@google.com" ],
+    // Once Lacros is launched, and all users switch to use lacros fully,
+    // this flag can be removed. Backward migration itself will be removed
+    // when Ash is no longer a browser.
+    // TODO(https://crbug.com/1148474).
+    "expiry_milestone": 130
+  },
+  {
     "name": "lacros-merge-icu-data-file",
     "owners": [ "andreaorru", "hidehiko", "lacros-team@google.com" ],
     "expiry_milestone": 130
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index d337e158..18f7844 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -56928,6 +56928,8 @@
   <int value="-2075870708" label="MediaRemotingEncrypted:disabled"/>
   <int value="-2075807193" label="enable-webusb-on-any-origin"/>
   <int value="-2075725205" label="disable-new-zip-unpacker"/>
+  <int value="-2075720567"
+      label="lacros-data-backward-migration-policy:disabled"/>
   <int value="-2075607807" label="CSSOverflowForReplacedElements:disabled"/>
   <int value="-2074936999" label="AutoDisableAccessibilityV2:disabled"/>
   <int value="-2074080173" label="NightLight:disabled"/>
@@ -64093,6 +64095,7 @@
   <int value="2104439359"
       label="OmniboxDefaultTypedNavigationsToHttps:enabled"/>
   <int value="2104788328" label="use-winrt-midi-api"/>
+  <int value="2106254561" label="lacros-data-backward-migration-policy"/>
   <int value="2106798283" label="SafetyTip:disabled"/>
   <int value="2106855416" label="HostWindowsInAppShimProcess:enabled"/>
   <int value="2107406401" label="UseDnsHttpsSvcb:disabled"/>
@@ -64115,6 +64118,8 @@
   <int value="2121056855" label="IncreaseInputAudioBufferSize:disabled"/>
   <int value="2121550859" label="PreferHtmlOverPlugins:enabled"/>
   <int value="2121776031" label="auto-virtual-keyboard"/>
+  <int value="2121870664"
+      label="lacros-data-backward-migration-policy:enabled"/>
   <int value="2122023503" label="enable-win32k-lockdown-mimetypes"/>
   <int value="2122863344" label="WebViewSurfaceControl:disabled"/>
   <int value="2122876605" label="enable-bleeding-edge-rendering-fast-paths"/>