0

standalone_browser: Extract lacros selection handling from browser_util

This CL extracts lacros selection related methods/constants from
browser_util to //chromeos/ash/components/standalone_browser.

This is a part of an effort to cut the chrome dependency.

Bug: 336839132
Change-Id: I170ff1d68eb0aedcbd29902235b6fd1e9490e95d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5504636
Reviewed-by: Hidehiko Abe <hidehiko@chromium.org>
Reviewed-by: Nicolas Dossou-Gbété <dgn@chromium.org>
Commit-Queue: Eriko Kurimoto <elkurin@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1295382}
This commit is contained in:
Eriko Kurimoto
2024-05-02 11:46:49 +00:00
committed by Chromium LUCI CQ
parent 74e46efd79
commit fa028d71dd
24 changed files with 484 additions and 339 deletions

@ -288,6 +288,7 @@
#include "chromeos/ash/components/assistant/buildflags.h"
#include "chromeos/ash/components/memory/swap_configuration.h"
#include "chromeos/ash/components/standalone_browser/lacros_availability.h"
#include "chromeos/ash/components/standalone_browser/lacros_selection.h"
#include "chromeos/ash/components/standalone_browser/standalone_browser_features.h"
#include "chromeos/ash/services/assistant/public/cpp/features.h"
#include "chromeos/constants/chromeos_switches.h"
@ -1074,11 +1075,11 @@ const char kProjectorServerSideSpeechRecognition[] =
const FeatureEntry::Choice kLacrosSelectionChoices[] = {
{flags_ui::kGenericExperimentChoiceDefault, "", ""},
{flag_descriptions::kLacrosSelectionStatefulDescription,
crosapi::browser_util::kLacrosSelectionSwitch,
crosapi::browser_util::kLacrosSelectionStateful},
ash::standalone_browser::kLacrosSelectionSwitch,
ash::standalone_browser::kLacrosSelectionStateful},
{flag_descriptions::kLacrosSelectionRootfsDescription,
crosapi::browser_util::kLacrosSelectionSwitch,
crosapi::browser_util::kLacrosSelectionRootfs},
ash::standalone_browser::kLacrosSelectionSwitch,
ash::standalone_browser::kLacrosSelectionRootfs},
};
const char kLacrosSelectionPolicyIgnoreInternalName[] =
@ -11335,8 +11336,8 @@ bool ShouldSkipConditionalFeatureEntry(const flags_ui::FlagsStorage* storage,
}
// Skip lacros-selection if it is controlled by LacrosSelection policy.
if (!strcmp(kLacrosSelectionInternalName, entry.internal_name)) {
return crosapi::browser_util::GetCachedLacrosSelectionPolicy() !=
crosapi::browser_util::LacrosSelectionPolicy::kUserChoice;
return ash::standalone_browser::GetCachedLacrosSelectionPolicy() !=
ash::standalone_browser::LacrosSelectionPolicy::kUserChoice;
}
if (!strcmp(kPreferDcheckInternalName, entry.internal_name)) {

@ -49,6 +49,7 @@
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/logging_chrome.h"
#include "chromeos/ash/components/standalone_browser/lacros_selection.h"
#include "chromeos/crosapi/cpp/crosapi_constants.h"
#include "chromeos/crosapi/mojom/crosapi.mojom-shared.h"
#include "chromeos/dbus/constants/dbus_switches.h"
@ -376,7 +377,7 @@ base::LaunchOptions CreateLaunchOptions() {
return options;
}
void SetUpEnvironment(browser_util::LacrosSelection lacros_selection,
void SetUpEnvironment(ash::standalone_browser::LacrosSelection lacros_selection,
base::LaunchOptions& options) {
// If Ash is an unknown channel then this is not a production build and we
// should be using an unknown channel for Lacros as well. This prevents Lacros
@ -702,12 +703,13 @@ std::vector<base::FilePath> BrowserLauncher::GetPreloadFiles(
return paths;
}
void BrowserLauncher::Launch(const base::FilePath& chrome_path,
bool launching_at_login_screen,
browser_util::LacrosSelection lacros_selection,
base::OnceClosure mojo_disconnection_cb,
bool is_keep_alive_enabled,
LaunchCompletionCallback callback) {
void BrowserLauncher::Launch(
const base::FilePath& chrome_path,
bool launching_at_login_screen,
ash::standalone_browser::LacrosSelection lacros_selection,
base::OnceClosure mojo_disconnection_cb,
bool is_keep_alive_enabled,
LaunchCompletionCallback callback) {
auto* params = new LaunchParamsFromBackground();
// Represents the number of tasks to complete before starting launch. If we
@ -801,7 +803,7 @@ LaunchParams BrowserLauncher::CreateLaunchParamsForTesting(
std::optional<int> startup_fd,
std::optional<int> read_pipe_fd,
mojo::PlatformChannel& channel,
browser_util::LacrosSelection lacros_selection) {
ash::standalone_browser::LacrosSelection lacros_selection) {
return CreateLaunchParams(chrome_path, params, launching_at_login_screen,
startup_fd, read_pipe_fd, channel,
lacros_selection);
@ -880,7 +882,7 @@ void BrowserLauncher::LaunchProcess(
const base::FilePath& chrome_path,
std::unique_ptr<LaunchParamsFromBackground> params,
bool launching_at_login_screen,
browser_util::LacrosSelection lacros_selection,
ash::standalone_browser::LacrosSelection lacros_selection,
base::OnceClosure mojo_disconnection_cb,
bool is_keep_alive_enabled,
LaunchCompletionCallback callback) {
@ -949,7 +951,7 @@ LaunchParams BrowserLauncher::CreateLaunchParams(
std::optional<int> startup_fd,
std::optional<int> read_pipe_fd,
mojo::PlatformChannel& channel,
browser_util::LacrosSelection lacros_selection) {
ash::standalone_browser::LacrosSelection lacros_selection) {
// Static configuration should be enabled from Lacros rather than Ash. This
// vector should only be used for dynamic configuration.
// TODO(crbug.com/40729628): Remove existing static configuration.

@ -18,9 +18,9 @@
#include "base/process/process.h"
#include "base/time/time.h"
#include "base/types/expected.h"
#include "chrome/browser/ash/crosapi/browser_util.h"
#include "chrome/browser/ash/crosapi/crosapi_id.h"
#include "chrome/common/channel_info.h"
#include "chromeos/ash/components/standalone_browser/lacros_selection.h"
#include "components/nacl/common/buildflags.h"
#include "components/policy/core/common/values_util.h"
#include "mojo/public/cpp/platform/platform_channel.h"
@ -144,7 +144,7 @@ class BrowserLauncher {
// completion.
void Launch(const base::FilePath& chrome_path,
bool launching_at_login_screen,
browser_util::LacrosSelection lacros_selection,
ash::standalone_browser::LacrosSelection lacros_selection,
base::OnceClosure mojo_disconnection_cb,
bool is_keep_alive_enabled,
LaunchCompletionCallback callback);
@ -190,7 +190,7 @@ class BrowserLauncher {
std::optional<int> startup_fd,
std::optional<int> read_pipe_fd,
mojo::PlatformChannel& channel,
browser_util::LacrosSelection lacros_selection);
ash::standalone_browser::LacrosSelection lacros_selection);
// Creates postlogin pipe fd and returns the read fd. This is used to test
// ResumeLaunch. Note that the reader is on the same process and does not
@ -244,7 +244,7 @@ class BrowserLauncher {
void LaunchProcess(const base::FilePath& chrome_path,
std::unique_ptr<LaunchParamsFromBackground> params,
bool launching_at_login_screen,
browser_util::LacrosSelection lacros_selection,
ash::standalone_browser::LacrosSelection lacros_selection,
base::OnceClosure mojo_disconnection_cb,
bool is_keep_alive_enabled,
LaunchCompletionCallback callback);
@ -256,7 +256,7 @@ class BrowserLauncher {
std::optional<int> startup_fd,
std::optional<int> read_pipe_fd,
mojo::PlatformChannel& channel,
browser_util::LacrosSelection lacros_selection);
ash::standalone_browser::LacrosSelection lacros_selection);
// Launches a process , which is executed in `LaunchProcess`.
// This is also used for unittest.

@ -33,6 +33,7 @@
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "chromeos/ash/components/login/login_state/login_state.h"
#include "chromeos/ash/components/standalone_browser/lacros_selection.h"
#include "chromeos/ash/components/system/fake_statistics_provider.h"
#include "chromeos/ash/components/system/statistics_provider.h"
#include "chromeos/crosapi/cpp/crosapi_constants.h"
@ -253,7 +254,7 @@ TEST_F(BrowserLauncherTest, Launch) {
constexpr bool launching_at_login_screen = false;
browser_launcher()->Launch(lacros_path, launching_at_login_screen,
browser_util::LacrosSelection::kRootfs,
ash::standalone_browser::LacrosSelection::kRootfs,
/*mojo_disconneciton_cb=*/{},
/*is_keep_alive_enabled=*/false,
future.GetCallback());
@ -284,7 +285,7 @@ TEST_F(BrowserLauncherTest, LaunchAtLoginScreen) {
constexpr bool launching_at_login_screen = true;
browser_launcher()->Launch(lacros_path, launching_at_login_screen,
browser_util::LacrosSelection::kRootfs,
ash::standalone_browser::LacrosSelection::kRootfs,
/*mojo_disconneciton_cb=*/{},
/*is_keep_alive_enabled=*/false,
future.GetCallback());
@ -347,7 +348,7 @@ TEST_F(BrowserLauncherTest, ShutdownRequestedDuringLaunch) {
// screen.
constexpr bool launching_at_login_screen = false;
browser_launcher()->Launch(base::FilePath(), launching_at_login_screen,
browser_util::LacrosSelection::kRootfs,
ash::standalone_browser::LacrosSelection::kRootfs,
/*mojo_disconneciton_cb=*/{},
/*is_keep_alive_enabled=*/false,
future.GetCallback());

@ -20,7 +20,6 @@
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/values.h"
#include "chrome/browser/ash/crosapi/browser_util.h"
#include "chrome/browser/ash/crosapi/lacros_selection_loader.h"
#include "chrome/browser/ash/crosapi/lacros_selection_loader_factory.h"
#include "chrome/browser/ash/crosapi/rootfs_lacros_loader.h"
@ -95,9 +94,9 @@ bool BrowserLoader::WillLoadStatefulComponentBuilds() {
// If the lacros selection is forced by the user or by policy to rootfs it
// will always be loaded and stateful component manager builds are ignored.
std::optional<browser_util::LacrosSelection> lacros_selection =
browser_util::DetermineLacrosSelection();
if (lacros_selection == browser_util::LacrosSelection::kRootfs) {
std::optional<ash::standalone_browser::LacrosSelection> lacros_selection =
ash::standalone_browser::DetermineLacrosSelection();
if (lacros_selection == ash::standalone_browser::LacrosSelection::kRootfs) {
return false;
}
@ -181,21 +180,21 @@ void BrowserLoader::LoadNow(LoadCompletionCallback callback) {
// If the LacrosSelection policy or the user have specified to force using
// stateful or rootfs lacros-chrome binary, force the selection. Otherwise,
// load the newest available binary.
if (std::optional<browser_util::LacrosSelection> lacros_selection =
browser_util::DetermineLacrosSelection()) {
if (std::optional<ash::standalone_browser::LacrosSelection> lacros_selection =
ash::standalone_browser::DetermineLacrosSelection()) {
// TODO(crbug.com/40213424): We should check the version compatibility here,
// too.
switch (lacros_selection.value()) {
case browser_util::LacrosSelection::kRootfs:
case ash::standalone_browser::LacrosSelection::kRootfs:
rootfs_lacros_loader_ = factory_->CreateRootfsLacrosLoader();
SelectRootfsLacros(std::move(callback), LacrosSelectionSource::kForced);
return;
case browser_util::LacrosSelection::kStateful:
case ash::standalone_browser::LacrosSelection::kStateful:
stateful_lacros_loader_ = factory_->CreateStatefulLacrosLoader();
SelectStatefulLacros(std::move(callback),
LacrosSelectionSource::kForced);
return;
case browser_util::LacrosSelection::kDeployedLocally:
case ash::standalone_browser::LacrosSelection::kDeployedLocally:
NOTREACHED();
std::move(callback).Run(base::FilePath(),
LacrosSelection::kDeployedLocally,

@ -17,7 +17,7 @@
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "base/version.h"
#include "chrome/browser/ash/crosapi/browser_util.h"
#include "chromeos/ash/components/standalone_browser/lacros_selection.h"
namespace component_updater {
class CrOSComponentManager;
@ -27,7 +27,7 @@ namespace crosapi {
class LacrosSelectionLoader;
class LacrosSelectionLoaderFactory;
using browser_util::LacrosSelection;
using ash::standalone_browser::LacrosSelection;
// Manages download of the lacros-chrome binary.
// This class is a part of ash-chrome.

@ -19,11 +19,11 @@
#include "base/test/scoped_command_line.h"
#include "base/test/test_future.h"
#include "base/version.h"
#include "chrome/browser/ash/crosapi/browser_util.h"
#include "chrome/browser/ash/crosapi/lacros_selection_loader.h"
#include "chrome/browser/ash/crosapi/lacros_selection_loader_factory.h"
#include "chrome/browser/component_updater/cros_component_manager.h"
#include "chromeos/ash/components/standalone_browser/browser_support.h"
#include "chromeos/ash/components/standalone_browser/lacros_selection.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/policy_constants.h"
#include "content/public/test/browser_task_environment.h"
@ -189,25 +189,25 @@ class FakeLacrosSelectionLoaderFactory : public LacrosSelectionLoaderFactory {
class ScopedLacrosSelectionCache {
public:
explicit ScopedLacrosSelectionCache(
browser_util::LacrosSelectionPolicy lacros_selection) {
ash::standalone_browser::LacrosSelectionPolicy lacros_selection) {
SetLacrosSelection(lacros_selection);
}
ScopedLacrosSelectionCache(const ScopedLacrosSelectionCache&) = delete;
ScopedLacrosSelectionCache& operator=(const ScopedLacrosSelectionCache&) =
delete;
~ScopedLacrosSelectionCache() {
browser_util::ClearLacrosSelectionCacheForTest();
ash::standalone_browser::ClearLacrosSelectionCacheForTest();
}
private:
void SetLacrosSelection(
browser_util::LacrosSelectionPolicy lacros_selection) {
ash::standalone_browser::LacrosSelectionPolicy lacros_selection) {
policy::PolicyMap policy;
policy.Set(policy::key::kLacrosSelection, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(GetLacrosSelectionPolicyName(lacros_selection)),
/*external_data_fetcher=*/nullptr);
browser_util::CacheLacrosSelection(policy);
ash::standalone_browser::CacheLacrosSelection(policy);
}
};
@ -321,11 +321,11 @@ TEST_F(BrowserLoaderTest, OnLoadVersionSelectionSameVersions) {
TEST_F(BrowserLoaderTest, OnLoadSelectionPolicyIsRootfs) {
ScopedLacrosSelectionCache cache(
browser_util::LacrosSelectionPolicy::kRootfs);
ash::standalone_browser::LacrosSelectionPolicy::kRootfs);
base::test::ScopedCommandLine command_line;
command_line.GetProcessCommandLine()->AppendSwitchASCII(
browser_util::kLacrosSelectionSwitch,
browser_util::kLacrosSelectionStateful);
ash::standalone_browser::kLacrosSelectionSwitch,
ash::standalone_browser::kLacrosSelectionStateful);
// Set stateful lacros version newer than rootfs to test that the selection
// policy is prioritized higher.
@ -350,11 +350,11 @@ TEST_F(BrowserLoaderTest, OnLoadSelectionPolicyIsRootfs) {
TEST_F(BrowserLoaderTest,
OnLoadSelectionPolicyIsUserChoiceAndCommandLineIsRootfs) {
ScopedLacrosSelectionCache cache(
browser_util::LacrosSelectionPolicy::kUserChoice);
ash::standalone_browser::LacrosSelectionPolicy::kUserChoice);
base::test::ScopedCommandLine command_line;
command_line.GetProcessCommandLine()->AppendSwitchASCII(
browser_util::kLacrosSelectionSwitch,
browser_util::kLacrosSelectionRootfs);
ash::standalone_browser::kLacrosSelectionSwitch,
ash::standalone_browser::kLacrosSelectionRootfs);
// Set stateful lacros version newer than rootfs to test that the user choice
// is prioritized higher.
@ -379,11 +379,11 @@ TEST_F(BrowserLoaderTest,
TEST_F(BrowserLoaderTest,
OnLoadSelectionPolicyIsUserChoiceAndCommandLineIsStateful) {
ScopedLacrosSelectionCache cache(
browser_util::LacrosSelectionPolicy::kUserChoice);
ash::standalone_browser::LacrosSelectionPolicy::kUserChoice);
base::test::ScopedCommandLine command_line;
command_line.GetProcessCommandLine()->AppendSwitchASCII(
browser_util::kLacrosSelectionSwitch,
browser_util::kLacrosSelectionStateful);
ash::standalone_browser::kLacrosSelectionSwitch,
ash::standalone_browser::kLacrosSelectionStateful);
// Set rootfs lacros version newer than rootfs to test that the user choice
// is prioritized higher.

@ -85,6 +85,7 @@
#include "chrome/common/chrome_paths.h"
#include "chromeos/ash/components/browser_context_helper/browser_context_helper.h"
#include "chromeos/ash/components/standalone_browser/browser_support.h"
#include "chromeos/ash/components/standalone_browser/lacros_selection.h"
#include "chromeos/ash/components/standalone_browser/migrator_util.h"
#include "chromeos/crosapi/cpp/crosapi_constants.h"
#include "chromeos/crosapi/cpp/lacros_startup_state.h"
@ -1196,7 +1197,8 @@ void BrowserManager::ResumeLaunch() {
// If Lacros selection (rootfs/stateful) for this user is forced to a
// different value than the Lacros that was launched at login screen,
// we need to reload and relaunch the correct version of Lacros.
auto user_lacros_selection = browser_util::DetermineLacrosSelection();
auto user_lacros_selection =
ash::standalone_browser::DetermineLacrosSelection();
if (user_lacros_selection.has_value() &&
lacros_selection_ != LacrosSelection::kDeployedLocally &&
lacros_selection_ != user_lacros_selection) {

@ -31,6 +31,7 @@
#include "chrome/browser/ash/crosapi/crosapi_id.h"
#include "chrome/browser/ui/browser_navigator_params.h"
#include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
#include "chromeos/ash/components/standalone_browser/lacros_selection.h"
#include "chromeos/crosapi/mojom/browser_service.mojom.h"
#include "chromeos/crosapi/mojom/desk_template.mojom.h"
#include "components/component_updater/component_updater_service.h"
@ -91,7 +92,7 @@ class FilesAppLauncher;
class PersistentForcedExtensionKeepAlive;
class TestMojoConnectionManager;
using browser_util::LacrosSelection;
using ash::standalone_browser::LacrosSelection;
using component_updater::ComponentUpdateService;
// Manages the lifetime of lacros-chrome, and its loading status. Observes the

@ -25,6 +25,7 @@
#include "chromeos/ash/components/standalone_browser/browser_support.h"
#include "chromeos/ash/components/standalone_browser/feature_refs.h"
#include "chromeos/ash/components/standalone_browser/lacros_availability.h"
#include "chromeos/ash/components/standalone_browser/lacros_selection.h"
#include "chromeos/ash/components/standalone_browser/migrator_util.h"
#include "chromeos/crosapi/mojom/browser_service.mojom-test-utils.h"
#include "chromeos/crosapi/mojom/browser_service.mojom.h"
@ -300,9 +301,10 @@ class BrowserManagerTest : public testing::Test {
EXPECT_TRUE(browser_util::IsLacrosAllowedToLaunch());
}
void ExpectCallingLoad(browser_util::LacrosSelection load_selection =
browser_util::LacrosSelection::kRootfs,
const std::string& lacros_path = "/run/lacros") {
void ExpectCallingLoad(
ash::standalone_browser::LacrosSelection load_selection =
ash::standalone_browser::LacrosSelection::kRootfs,
const std::string& lacros_path = "/run/lacros") {
EXPECT_CALL(*browser_loader_, Load(_))
.WillOnce([load_selection, lacros_path](
BrowserLoader::LoadCompletionCallback callback) {
@ -402,7 +404,7 @@ TEST_F(BrowserManagerTest, LacrosKeepAliveReloadsWhenUpdateAvailable) {
std::unique_ptr<BrowserManagerScopedKeepAlive> keep_alive =
fake_browser_manager_->KeepAlive(BrowserManager::Feature::kTestOnly);
ExpectCallingLoad(browser_util::LacrosSelection::kStateful,
ExpectCallingLoad(ash::standalone_browser::LacrosSelection::kStateful,
kSampleLacrosPath);
// On simulated termination, KeepAlive restarts Lacros. Since there is an

@ -78,10 +78,6 @@ std::optional<LacrosAvailability> g_lacros_availability_cache;
std::optional<LacrosDataBackwardMigrationMode>
g_lacros_data_backward_migration_mode;
// At session start the value for LacrosSelection logic is applied and the
// result is stored in this variable which is used after that as a cache.
std::optional<LacrosSelectionPolicy> g_lacros_selection_cache;
// The rootfs lacros-chrome metadata keys.
constexpr char kLacrosMetadataContentKey[] = "content";
constexpr char kLacrosMetadataVersionKey[] = "version";
@ -100,14 +96,6 @@ constexpr auto kLacrosDataBackwardMigrationModeMap =
LacrosDataBackwardMigrationMode::kKeepAll},
});
// The conversion map for LacrosSelection policy data. The values must match
// the ones from LacrosSelection.yaml.
constexpr auto kLacrosSelectionPolicyMap =
base::MakeFixedFlatMap<std::string_view, LacrosSelectionPolicy>({
{"user_choice", LacrosSelectionPolicy::kUserChoice},
{"rootfs", LacrosSelectionPolicy::kRootfs},
});
// Returns primary user's User instance.
const user_manager::User* GetPrimaryUser() {
// TODO(crbug.com/40753373): TaskManagerImplTest is not ready to run with
@ -238,10 +226,6 @@ const ComponentInfo kLacrosDogfoodStableInfo = {
const Channel kLacrosDefaultChannel = Channel::DEV;
const char kLacrosSelectionSwitch[] = "lacros-selection";
const char kLacrosSelectionRootfs[] = "rootfs";
const char kLacrosSelectionStateful[] = "stateful";
const char kLaunchOnLoginPref[] = "lacros.launch_on_login";
const char kProfileDataBackwardMigrationCompletedForUserPref[] =
"lacros.profile_data_backward_migration_completed_for_user";
@ -478,58 +462,6 @@ void CacheLacrosDataBackwardMigrationMode(const policy::PolicyMap& map) {
value ? value->GetString() : std::string_view());
}
void CacheLacrosSelection(const policy::PolicyMap& map) {
if (g_lacros_selection_cache.has_value()) {
// Some browser tests might call this multiple times.
LOG(ERROR) << "Trying to cache LacrosSelection and the value was set";
return;
}
// Users can set this switch in chrome://flags to disable the effect of the
// lacros-selection policy. This should only be allows for googlers.
const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
if (cmdline->HasSwitch(ash::switches::kLacrosSelectionPolicyIgnore) &&
IsGoogleInternal(UserManager::Get()->GetPrimaryUser())) {
LOG(WARNING) << "LacrosSelection policy is ignored due to the ignore flag";
return;
}
const base::Value* value =
map.GetValue(policy::key::kLacrosSelection, base::Value::Type::STRING);
g_lacros_selection_cache = ParseLacrosSelectionPolicy(
value ? value->GetString() : std::string_view());
}
LacrosSelectionPolicy GetCachedLacrosSelectionPolicy() {
return g_lacros_selection_cache.value_or(LacrosSelectionPolicy::kUserChoice);
}
std::optional<LacrosSelection> DetermineLacrosSelection() {
switch (GetCachedLacrosSelectionPolicy()) {
case LacrosSelectionPolicy::kRootfs:
return LacrosSelection::kRootfs;
case LacrosSelectionPolicy::kUserChoice:
break;
}
const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
if (!cmdline->HasSwitch(browser_util::kLacrosSelectionSwitch)) {
return std::nullopt;
}
auto value =
cmdline->GetSwitchValueASCII(browser_util::kLacrosSelectionSwitch);
if (value == browser_util::kLacrosSelectionRootfs) {
return LacrosSelection::kRootfs;
}
if (value == browser_util::kLacrosSelectionStateful) {
return LacrosSelection::kStateful;
}
return std::nullopt;
}
ComponentInfo GetLacrosComponentInfoForChannel(version_info::Channel channel) {
// We default to the Dev component for UNKNOWN channels.
static constexpr auto kChannelToComponentInfoMap =
@ -547,17 +479,18 @@ ComponentInfo GetLacrosComponentInfo() {
return GetLacrosComponentInfoForChannel(GetStatefulLacrosChannel());
}
Channel GetLacrosSelectionUpdateChannel(LacrosSelection selection) {
Channel GetLacrosSelectionUpdateChannel(
ash::standalone_browser::LacrosSelection selection) {
switch (selection) {
case LacrosSelection::kRootfs:
case ash::standalone_browser::LacrosSelection::kRootfs:
// For 'rootfs' Lacros use the same channel as ash/OS. Obtained from
// the LSB's release track property.
return chrome::GetChannel();
case LacrosSelection::kStateful:
case ash::standalone_browser::LacrosSelection::kStateful:
// For 'stateful' Lacros directly check the channel of stateful-lacros
// that the user is on.
return GetStatefulLacrosChannel();
case LacrosSelection::kDeployedLocally:
case ash::standalone_browser::LacrosSelection::kDeployedLocally:
// For locally deployed Lacros there is no channel so return unknown.
return Channel::UNKNOWN;
}
@ -607,10 +540,6 @@ void ClearLacrosDataBackwardMigrationModeCacheForTest() {
g_lacros_data_backward_migration_mode.reset();
}
void ClearLacrosSelectionCacheForTest() {
g_lacros_selection_cache.reset();
}
std::optional<MigrationStatus> GetMigrationStatus() {
PrefService* local_state = g_browser_process->local_state();
if (!local_state) {
@ -727,16 +656,6 @@ LacrosLaunchSwitchSource GetLacrosLaunchSwitchSource() {
: LacrosLaunchSwitchSource::kForcedByPolicy;
}
std::optional<LacrosSelectionPolicy> ParseLacrosSelectionPolicy(
std::string_view value) {
auto it = kLacrosSelectionPolicyMap.find(value);
if (it != kLacrosSelectionPolicyMap.end())
return it->second;
LOG(ERROR) << "Unknown LacrosSelection policy value is passed: " << value;
return std::nullopt;
}
std::optional<LacrosDataBackwardMigrationMode>
ParseLacrosDataBackwardMigrationMode(std::string_view value) {
auto it = kLacrosDataBackwardMigrationModeMap.find(value);
@ -761,17 +680,6 @@ std::string_view GetLacrosDataBackwardMigrationModeName(
return std::string_view();
}
std::string_view GetLacrosSelectionPolicyName(LacrosSelectionPolicy value) {
for (const auto& entry : kLacrosSelectionPolicyMap) {
if (entry.second == value) {
return entry.first;
}
}
NOTREACHED();
return std::string_view();
}
bool IsAshBrowserSyncEnabled() {
// Turn off sync from Ash if Lacros is enabled and Ash web browser is
// disabled.

@ -13,6 +13,7 @@
#include "base/feature_list.h"
#include "base/time/time.h"
#include "chromeos/ash/components/standalone_browser/lacros_availability.h"
#include "chromeos/ash/components/standalone_browser/lacros_selection.h"
class PrefRegistrySimple;
class PrefService;
@ -68,29 +69,6 @@ enum class LacrosLaunchSwitchSource {
kForcedByPolicy = 3
};
// Represents the policy indicating which Lacros browser to launch, named
// LacrosSelection. The values shall be consistent with the controlling
// policy. Unlike `LacrosSelection` representing which lacros to select,
// `LacrosSelectionPolicy` represents how to decide which lacros to select.
// Stateful option from `LacrosSelection` is omitted due to a breakage risks in
// case of version skew (e.g. when the latest stateful Lacros available in omaha
// is older than the rootfs Lacros on the device).
enum class LacrosSelectionPolicy {
// Indicates that the user decides which Lacros browser to launch: rootfs or
// stateful.
kUserChoice = 0,
// Indicates that rootfs Lacros will always be launched.
kRootfs = 1,
};
// Represents the different options available for lacros selection.
enum class LacrosSelection {
kRootfs = 0,
kStateful = 1,
kDeployedLocally = 2,
kMaxValue = kDeployedLocally,
};
// Represents the values of the LacrosDataBackwardMigrationMode string enum
// policy. It controls what happens when we switch from Lacros back to Ash.
// The values shall be consistent with the policy description.
@ -147,12 +125,6 @@ extern const char kLacrosStabilityChannelDev[];
extern const char kLacrosStabilityChannelBeta[];
extern const char kLacrosStabilityChannelStable[];
// A command-line switch that can also be set from chrome://flags that chooses
// which selection of Lacros to use.
extern const char kLacrosSelectionSwitch[];
extern const char kLacrosSelectionRootfs[];
extern const char kLacrosSelectionStateful[];
// The internal name in about_flags.cc for the `LacrosDataBackwardMigrationMode`
// policy.
inline constexpr const char
@ -259,20 +231,6 @@ void CacheLacrosAvailability(const policy::PolicyMap& map);
// LacrosDataBackwardMigrationMode policy.
void CacheLacrosDataBackwardMigrationMode(const policy::PolicyMap& map);
// To be called at primary user login, to cache the policy value for
// LacrosSelection policy. The effective value of the policy does not
// change for the duration of the user session, so cached value shall be
// checked.
void CacheLacrosSelection(const policy::PolicyMap& map);
// Returns cached value of LacrosSelection policy. See `CacheLacrosSelection`
// for details.
LacrosSelectionPolicy GetCachedLacrosSelectionPolicy();
// Returns lacros selection option according to LarcrosSelectionPolicy and
// lacros-selection flag. Returns nullopt if there is no preference.
std::optional<LacrosSelection> DetermineLacrosSelection();
// Returns the lacros ComponentInfo for a given channel.
ComponentInfo GetLacrosComponentInfoForChannel(version_info::Channel channel);
@ -281,7 +239,7 @@ ComponentInfo GetLacrosComponentInfo();
// Returns the update channel associated with the given loaded lacros selection.
version_info::Channel GetLacrosSelectionUpdateChannel(
LacrosSelection selection);
ash::standalone_browser::LacrosSelection selection);
// Returns the currently installed version of lacros-chrome managed by the
// component updater. Will return an empty / invalid version if no lacros
@ -308,9 +266,6 @@ void ClearLacrosAvailabilityCacheForTest();
// Clears the cached value for LacrosDataBackwardMigrationMode.
void ClearLacrosDataBackwardMigrationModeCacheForTest();
// Clears the cached value for LacrosSelection policy.
void ClearLacrosSelectionCacheForTest();
// Returns true if profile migraiton is enabled. If profile migration is
// enabled, the completion of it is required to enable Lacros.
bool IsProfileMigrationEnabled(const user_manager::User* user,
@ -370,11 +325,6 @@ LacrosLaunchSwitchSource GetLacrosLaunchSwitchSource();
void SetLacrosLaunchSwitchSourceForTest(
ash::standalone_browser::LacrosAvailability test_value);
// Parses the string representation of LacrosSelection policy value into the
// enum value. Returns nullopt on unknown value.
std::optional<LacrosSelectionPolicy> ParseLacrosSelectionPolicy(
std::string_view value);
// Parses the string representation of LacrosDataBackwardMigrationMode policy
// value into the enum value. Returns nullopt on unknown value.
std::optional<LacrosDataBackwardMigrationMode>
@ -384,10 +334,6 @@ ParseLacrosDataBackwardMigrationMode(std::string_view value);
std::string_view GetLacrosDataBackwardMigrationModeName(
LacrosDataBackwardMigrationMode value);
// Returns the LacrosSelection policy value name from the given value. Returned
// std::string_view is guaranteed to never be invalidated.
std::string_view GetLacrosSelectionPolicyName(LacrosSelectionPolicy value);
// Stores that "Go to files button" on the migration error screen is clicked.
void SetGotoFilesClicked(PrefService* local_state,
const std::string& user_id_hash);

@ -24,6 +24,7 @@
#include "chrome/test/base/testing_browser_process.h"
#include "chromeos/ash/components/standalone_browser/browser_support.h"
#include "chromeos/ash/components/standalone_browser/lacros_availability.h"
#include "chromeos/ash/components/standalone_browser/lacros_selection.h"
#include "chromeos/ash/components/standalone_browser/migrator_util.h"
#include "chromeos/ash/components/standalone_browser/standalone_browser_features.h"
#include "chromeos/crosapi/mojom/crosapi.mojom.h"
@ -37,7 +38,6 @@
using ash::standalone_browser::LacrosAvailability;
using crosapi::browser_util::LacrosLaunchSwitchSource;
using crosapi::browser_util::LacrosSelection;
using user_manager::User;
using version_info::Channel;
@ -78,33 +78,6 @@ class ScopedLacrosAvailabilityCache {
}
};
// This implementation of RAII for LacrosSelection is to make it easy reset
// the state between runs.
class ScopedLacrosSelectionCache {
public:
explicit ScopedLacrosSelectionCache(
browser_util::LacrosSelectionPolicy lacros_selection) {
SetLacrosSelection(lacros_selection);
}
ScopedLacrosSelectionCache(const ScopedLacrosSelectionCache&) = delete;
ScopedLacrosSelectionCache& operator=(const ScopedLacrosSelectionCache&) =
delete;
~ScopedLacrosSelectionCache() {
browser_util::ClearLacrosSelectionCacheForTest();
}
private:
void SetLacrosSelection(
browser_util::LacrosSelectionPolicy lacros_selection) {
policy::PolicyMap policy;
policy.Set(policy::key::kLacrosSelection, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(GetLacrosSelectionPolicyName(lacros_selection)),
/*external_data_fetcher=*/nullptr);
browser_util::CacheLacrosSelection(policy);
}
};
} // namespace
class BrowserUtilTest : public testing::Test {
@ -551,16 +524,18 @@ TEST_F(BrowserUtilTest, GetRootfsLacrosVersionMayBlockBadJson) {
TEST_F(BrowserUtilTest, StatefulLacrosSelectionUpdateChannel) {
// Assert that when no Lacros stability switch is specified, we return the
// "unknown" channel.
ASSERT_EQ(Channel::UNKNOWN, browser_util::GetLacrosSelectionUpdateChannel(
LacrosSelection::kStateful));
ASSERT_EQ(Channel::UNKNOWN,
browser_util::GetLacrosSelectionUpdateChannel(
ash::standalone_browser::LacrosSelection::kStateful));
// Assert that when a Lacros stability switch is specified, we return the
// relevant channel name associated to that switch value.
base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
cmdline->AppendSwitchNative(browser_util::kLacrosStabilitySwitch,
browser_util::kLacrosStabilityChannelBeta);
ASSERT_EQ(Channel::BETA, browser_util::GetLacrosSelectionUpdateChannel(
LacrosSelection::kStateful));
ASSERT_EQ(Channel::BETA,
browser_util::GetLacrosSelectionUpdateChannel(
ash::standalone_browser::LacrosSelection::kStateful));
cmdline->RemoveSwitch(browser_util::kLacrosStabilitySwitch);
}
@ -797,89 +772,6 @@ TEST_F(BrowserUtilTest, LacrosGoogleRolloutOnly) {
user, browser_util::PolicyInitState::kAfterInit));
}
TEST_F(BrowserUtilTest, LacrosSelection) {
// Neither policy nor command line have any preference on Lacros selection.
EXPECT_FALSE(browser_util::DetermineLacrosSelection());
{
// LacrosSelection policy has precedence over command line.
ScopedLacrosSelectionCache cache(
browser_util::LacrosSelectionPolicy::kRootfs);
base::test::ScopedCommandLine cmd_line;
cmd_line.GetProcessCommandLine()->AppendSwitchASCII(
browser_util::kLacrosSelectionSwitch,
browser_util::kLacrosSelectionStateful);
EXPECT_EQ(browser_util::DetermineLacrosSelection(),
LacrosSelection::kRootfs);
}
{
// LacrosSelection allows command line check, but command line is not set.
ScopedLacrosSelectionCache cache(
browser_util::LacrosSelectionPolicy::kUserChoice);
EXPECT_FALSE(browser_util::DetermineLacrosSelection());
}
{
// LacrosSelection allows command line check.
ScopedLacrosSelectionCache cache(
browser_util::LacrosSelectionPolicy::kUserChoice);
base::test::ScopedCommandLine cmd_line;
cmd_line.GetProcessCommandLine()->AppendSwitchASCII(
browser_util::kLacrosSelectionSwitch,
browser_util::kLacrosSelectionRootfs);
EXPECT_EQ(browser_util::DetermineLacrosSelection(),
LacrosSelection::kRootfs);
}
{
// LacrosSelection allows command line check.
ScopedLacrosSelectionCache cache(
browser_util::LacrosSelectionPolicy::kUserChoice);
base::test::ScopedCommandLine cmd_line;
cmd_line.GetProcessCommandLine()->AppendSwitchASCII(
browser_util::kLacrosSelectionSwitch,
browser_util::kLacrosSelectionStateful);
EXPECT_EQ(browser_util::DetermineLacrosSelection(),
LacrosSelection::kStateful);
}
}
// LacrosSelection has no effect on non-googlers.
TEST_F(BrowserUtilTest, LacrosSelectionPolicyIgnoreNonGoogle) {
AddRegularUser("user@random.com");
base::test::ScopedCommandLine cmd_line;
cmd_line.GetProcessCommandLine()->AppendSwitch(
ash::switches::kLacrosSelectionPolicyIgnore);
{
ScopedLacrosSelectionCache cache(
browser_util::LacrosSelectionPolicy::kRootfs);
EXPECT_EQ(browser_util::GetCachedLacrosSelectionPolicy(),
browser_util::LacrosSelectionPolicy::kRootfs);
EXPECT_EQ(browser_util::DetermineLacrosSelection(),
LacrosSelection::kRootfs);
}
}
// LacrosSelection has an effect on googlers.
TEST_F(BrowserUtilTest, LacrosSelectionPolicyIgnoreGoogleDisableToUserChoice) {
AddRegularUser("user@google.com");
base::test::ScopedCommandLine cmd_line;
cmd_line.GetProcessCommandLine()->AppendSwitch(
ash::switches::kLacrosSelectionPolicyIgnore);
{
ScopedLacrosSelectionCache cache(
browser_util::LacrosSelectionPolicy::kRootfs);
EXPECT_EQ(browser_util::GetCachedLacrosSelectionPolicy(),
browser_util::LacrosSelectionPolicy::kUserChoice);
EXPECT_FALSE(browser_util::DetermineLacrosSelection());
}
}
// Lacros Only flag is hidden in guest sessions
TEST_F(BrowserUtilTest, HidingLacrosFlagsForAllGuestUsers) {
const User* user = fake_user_manager_->AddGuestUser();

@ -605,17 +605,17 @@ crosapi::mojom::BrowserInitParams::DeviceType ConvertDeviceType(
}
crosapi::mojom::BrowserInitParams::LacrosSelection GetLacrosSelection(
std::optional<browser_util::LacrosSelection> selection) {
std::optional<ash::standalone_browser::LacrosSelection> selection) {
if (!selection.has_value()) {
return crosapi::mojom::BrowserInitParams::LacrosSelection::kUnspecified;
}
switch (selection.value()) {
case browser_util::LacrosSelection::kRootfs:
case ash::standalone_browser::LacrosSelection::kRootfs:
return crosapi::mojom::BrowserInitParams::LacrosSelection::kRootfs;
case browser_util::LacrosSelection::kStateful:
case ash::standalone_browser::LacrosSelection::kStateful:
return crosapi::mojom::BrowserInitParams::LacrosSelection::kStateful;
case browser_util::LacrosSelection::kDeployedLocally:
case ash::standalone_browser::LacrosSelection::kDeployedLocally:
return crosapi::mojom::BrowserInitParams::LacrosSelection::kUnspecified;
}
}
@ -736,7 +736,7 @@ InitialBrowserAction::~InitialBrowserAction() = default;
void InjectBrowserInitParams(
mojom::BrowserInitParams* params,
bool is_keep_alive_enabled,
std::optional<browser_util::LacrosSelection> lacros_selection) {
std::optional<ash::standalone_browser::LacrosSelection> lacros_selection) {
params->crosapi_version = crosapi::mojom::Crosapi::Version_;
params->deprecated_ash_metrics_enabled_has_value = true;
PrefService* local_state = g_browser_process->local_state();
@ -993,7 +993,7 @@ void InjectBrowserPostLoginParams(BrowserParams* params,
mojom::BrowserInitParamsPtr GetBrowserInitParams(
InitialBrowserAction initial_browser_action,
bool is_keep_alive_enabled,
std::optional<browser_util::LacrosSelection> lacros_selection,
std::optional<ash::standalone_browser::LacrosSelection> lacros_selection,
bool include_post_login_params) {
mojom::BrowserInitParamsPtr params = mojom::BrowserInitParams::New();
InjectBrowserInitParams(params.get(), is_keep_alive_enabled,
@ -1016,7 +1016,7 @@ mojom::BrowserPostLoginParamsPtr GetBrowserPostLoginParams(
base::ScopedFD CreateStartupData(
InitialBrowserAction initial_browser_action,
bool is_keep_alive_enabled,
std::optional<LacrosSelection> lacros_selection,
std::optional<ash::standalone_browser::LacrosSelection> lacros_selection,
bool include_post_login_params) {
const auto& data = GetBrowserInitParams(
std::move(initial_browser_action), is_keep_alive_enabled,

@ -14,6 +14,7 @@
#include "base/files/scoped_file.h"
#include "base/token.h"
#include "chrome/browser/ash/crosapi/browser_util.h"
#include "chromeos/ash/components/standalone_browser/lacros_selection.h"
#include "chromeos/crosapi/mojom/crosapi.mojom.h"
#include "components/policy/core/common/cloud/cloud_policy_core.h"
#include "components/policy/core/common/cloud/component_cloud_policy_service.h"
@ -59,7 +60,7 @@ struct InitialBrowserAction {
mojom::BrowserInitParamsPtr GetBrowserInitParams(
InitialBrowserAction initial_browser_action,
bool is_keep_alive_enabled,
std::optional<browser_util::LacrosSelection> lacros_selection,
std::optional<ash::standalone_browser::LacrosSelection> lacros_selection,
bool include_post_login_params = true);
// Creates a memory backed file containing the serialized |params|,
@ -70,7 +71,7 @@ mojom::BrowserInitParamsPtr GetBrowserInitParams(
base::ScopedFD CreateStartupData(
InitialBrowserAction initial_browser_action,
bool is_keep_alive_enabled,
std::optional<browser_util::LacrosSelection> lacros_selection,
std::optional<ash::standalone_browser::LacrosSelection> lacros_selection,
bool include_post_login_params = true);
// Serializes and writes post-login parameters into the given FD.

@ -34,7 +34,7 @@ void LacrosSelectionPolicyHandler::ApplyPolicySettings(
prefs->SetInteger(prefs::kLacrosSelection, static_cast<int>(*enum_value));
}
std::optional<crosapi::browser_util::LacrosSelectionPolicy>
std::optional<ash::standalone_browser::LacrosSelectionPolicy>
LacrosSelectionPolicyHandler::GetValue(const PolicyMap& policies,
PolicyErrorMap* errors) {
const base::Value* value;
@ -43,7 +43,7 @@ LacrosSelectionPolicyHandler::GetValue(const PolicyMap& policies,
return std::nullopt;
auto parsed =
crosapi::browser_util::ParseLacrosSelectionPolicy(value->GetString());
ash::standalone_browser::ParseLacrosSelectionPolicy(value->GetString());
if (!parsed.has_value() && errors) {
errors->AddError(policy_name(), IDS_POLICY_INVALID_SELECTION_ERROR,
"LacrosSelection value");

@ -8,7 +8,7 @@
#include <optional>
#include "build/chromeos_buildflags.h"
#include "chrome/browser/ash/crosapi/browser_util.h"
#include "chromeos/ash/components/standalone_browser/lacros_selection.h"
#include "components/policy/core/browser/configuration_policy_handler.h"
class PrefValueMap;
@ -31,7 +31,7 @@ class LacrosSelectionPolicyHandler : public TypeCheckingPolicyHandler {
PrefValueMap* prefs) override;
private:
std::optional<crosapi::browser_util::LacrosSelectionPolicy> GetValue(
std::optional<ash::standalone_browser::LacrosSelectionPolicy> GetValue(
const PolicyMap& policies,
PolicyErrorMap* errors);
};

@ -60,6 +60,7 @@
#include "chromeos/ash/components/settings/cros_settings.h"
#include "chromeos/ash/components/settings/cros_settings_names.h"
#include "chromeos/ash/components/standalone_browser/lacros_availability.h"
#include "chromeos/ash/components/standalone_browser/lacros_selection.h"
#include "chromeos/ash/components/system/statistics_provider.h"
#include "chromeos/ash/components/timezone/timezone_resolver.h"
#include "chromeos/components/disks/disks_prefs.h"
@ -159,7 +160,7 @@ void Preferences::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterIntegerPref(
::prefs::kLacrosSelection,
static_cast<int>(
crosapi::browser_util::LacrosSelectionPolicy::kUserChoice));
ash::standalone_browser::LacrosSelectionPolicy::kUserChoice));
registry->RegisterStringPref(::prefs::kLacrosDataBackwardMigrationMode, "");
registry->RegisterBooleanPref(prefs::kDeviceSystemWideTracingEnabled, true);
registry->RegisterBooleanPref(

@ -200,6 +200,7 @@
#include "chrome/browser/signin/chrome_device_id_helper.h"
#include "chromeos/ash/components/account_manager/account_manager_factory.h"
#include "chromeos/ash/components/standalone_browser/browser_support.h"
#include "chromeos/ash/components/standalone_browser/lacros_selection.h"
#include "components/account_manager_core/chromeos/account_manager.h"
#include "components/session_manager/core/session_manager.h"
#include "components/user_manager/user.h"
@ -669,7 +670,7 @@ void ProfileImpl::LoadPrefsForNormalStartup(bool async_prefs) {
map, IsNewProfile(), IsRegularProfile());
crosapi::browser_util::CacheLacrosAvailability(map);
crosapi::browser_util::CacheLacrosDataBackwardMigrationMode(map);
crosapi::browser_util::CacheLacrosSelection(map);
ash::standalone_browser::CacheLacrosSelection(map);
}
#endif
}
@ -1185,7 +1186,7 @@ void ProfileImpl::OnPrefsLoaded(CreateMode create_mode, bool success) {
map, IsNewProfile(), IsRegularProfile());
crosapi::browser_util::CacheLacrosAvailability(map);
crosapi::browser_util::CacheLacrosDataBackwardMigrationMode(map);
crosapi::browser_util::CacheLacrosSelection(map);
ash::standalone_browser::CacheLacrosSelection(map);
}
ash::UserSessionManager::GetInstance()->RespectLocalePreferenceWrapper(

@ -15,6 +15,8 @@ component("standalone_browser") {
"browser_support.h",
"lacros_availability.cc",
"lacros_availability.h",
"lacros_selection.cc",
"lacros_selection.h",
"migrator_util.cc",
"migrator_util.h",
"standalone_browser_features.cc",
@ -39,6 +41,7 @@ source_set("unit_tests") {
sources = [
"lacros_availability_unittest.cc",
"lacros_selection_unittest.cc",
"migrator_util_unittest.cc",
"test_util_unittest.cc",
]
@ -48,8 +51,12 @@ source_set("unit_tests") {
":test_support",
"//ash/constants:constants",
"//base/test:test_support",
"//components/account_id",
"//components/policy:generated",
"//components/policy/core/common",
"//components/prefs:test_support",
"//components/user_manager:test_support",
"//content/test:test_support",
"//testing/gtest:gtest",
]
}

@ -4,6 +4,11 @@ specific_include_rules = {
"+components/policy/policy_constants.h",
"+components/user_manager/user.h",
],
"lacros_selection\.cc": [
"+components/policy/core/common/policy_map.h",
"+components/policy/policy_constants.h",
"+components/user_manager/user_manager.h",
],
"browser_support\.cc": [
"+ash/constants/ash_switches.h",
"+components/user_manager/user.h",
@ -13,4 +18,13 @@ specific_include_rules = {
"lacros_availability_unittest\.cc": [
"+components/user_manager/fake_user_manager.h",
],
"lacros_selection_unittest\.cc": [
"+ash/constants/ash_switches.h",
"+components/account_id/account_id.h",
"+components/policy/core/common/policy_map.h",
"+components/policy/policy_constants.h",
"+components/user_manager/fake_user_manager.h",
"+components/user_manager/scoped_user_manager.h",
"+components/user_manager/user.h",
]
}

@ -0,0 +1,115 @@
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/ash/components/standalone_browser/lacros_selection.h"
#include "ash/constants/ash_switches.h"
#include "base/command_line.h"
#include "base/containers/fixed_flat_map.h"
#include "base/containers/flat_map.h"
#include "base/logging.h"
#include "base/notreached.h"
#include "chromeos/ash/components/standalone_browser/lacros_availability.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/policy_constants.h"
#include "components/user_manager/user_manager.h"
namespace ash::standalone_browser {
namespace {
// At session start the value for LacrosSelection logic is applied and the
// result is stored in this variable which is used after that as a cache.
// TODO(crbug.com/336839132): Move cache related methods to a wrapper class
// instead of global functions + global variables.
std::optional<LacrosSelectionPolicy> g_lacros_selection_cache;
// The conversion map for LacrosSelection policy data. The values must match
// the ones from LacrosSelection.yaml.
constexpr auto kLacrosSelectionPolicyMap =
base::MakeFixedFlatMap<std::string_view, LacrosSelectionPolicy>({
{"user_choice", LacrosSelectionPolicy::kUserChoice},
{"rootfs", LacrosSelectionPolicy::kRootfs},
});
} // namespace
void CacheLacrosSelection(const policy::PolicyMap& map) {
if (g_lacros_selection_cache.has_value()) {
// Some browser tests might call this multiple times.
LOG(ERROR) << "Trying to cache LacrosSelection and the value was set";
return;
}
// Users can set this switch in chrome://flags to disable the effect of the
// lacros-selection policy. This should only be allows for googlers.
const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
if (cmdline->HasSwitch(ash::switches::kLacrosSelectionPolicyIgnore) &&
IsGoogleInternal(user_manager::UserManager::Get()->GetPrimaryUser())) {
LOG(WARNING) << "LacrosSelection policy is ignored due to the ignore flag";
return;
}
const base::Value* value =
map.GetValue(policy::key::kLacrosSelection, base::Value::Type::STRING);
g_lacros_selection_cache = ParseLacrosSelectionPolicy(
value ? value->GetString() : std::string_view());
}
LacrosSelectionPolicy GetCachedLacrosSelectionPolicy() {
return g_lacros_selection_cache.value_or(LacrosSelectionPolicy::kUserChoice);
}
std::optional<LacrosSelection> DetermineLacrosSelection() {
switch (GetCachedLacrosSelectionPolicy()) {
case LacrosSelectionPolicy::kRootfs:
return LacrosSelection::kRootfs;
case LacrosSelectionPolicy::kUserChoice:
break;
}
const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
if (!cmdline->HasSwitch(kLacrosSelectionSwitch)) {
return std::nullopt;
}
auto value = cmdline->GetSwitchValueASCII(kLacrosSelectionSwitch);
if (value == kLacrosSelectionRootfs) {
return LacrosSelection::kRootfs;
}
if (value == kLacrosSelectionStateful) {
return LacrosSelection::kStateful;
}
return std::nullopt;
}
std::optional<LacrosSelectionPolicy> ParseLacrosSelectionPolicy(
std::string_view value) {
auto it = kLacrosSelectionPolicyMap.find(value);
if (it != kLacrosSelectionPolicyMap.end()) {
return it->second;
}
LOG(ERROR) << "Unknown LacrosSelection policy value is passed: " << value;
return std::nullopt;
}
std::string_view GetLacrosSelectionPolicyName(LacrosSelectionPolicy value) {
for (const auto& entry : kLacrosSelectionPolicyMap) {
if (entry.second == value) {
return entry.first;
}
}
NOTREACHED();
return std::string_view();
}
void ClearLacrosSelectionCacheForTest() {
g_lacros_selection_cache.reset();
}
} // namespace ash::standalone_browser

@ -0,0 +1,82 @@
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_ASH_COMPONENTS_STANDALONE_BROWSER_LACROS_SELECTION_H_
#define CHROMEOS_ASH_COMPONENTS_STANDALONE_BROWSER_LACROS_SELECTION_H_
#include <optional>
#include <string_view>
#include "base/component_export.h"
namespace policy {
class PolicyMap;
} // namespace policy
namespace ash::standalone_browser {
// Represents the policy indicating which Lacros browser to launch, named
// LacrosSelection. The values shall be consistent with the controlling
// policy. Unlike `LacrosSelection` representing which lacros to select,
// `LacrosSelectionPolicy` represents how to decide which lacros to select.
// Stateful option from `LacrosSelection` is omitted due to a breakage risks in
// case of version skew (e.g. when the latest stateful Lacros available in omaha
// is older than the rootfs Lacros on the device).
enum class LacrosSelectionPolicy {
// Indicates that the user decides which Lacros browser to launch: rootfs or
// stateful.
kUserChoice = 0,
// Indicates that rootfs Lacros will always be launched.
kRootfs = 1,
};
// Represents the different options available for lacros selection.
enum class LacrosSelection {
kRootfs = 0,
kStateful = 1,
kDeployedLocally = 2,
kMaxValue = kDeployedLocally,
};
// A command-line switch that can also be set from chrome://flags that chooses
// which selection of Lacros to use.
inline constexpr char kLacrosSelectionSwitch[] = "lacros-selection";
inline constexpr char kLacrosSelectionRootfs[] = "rootfs";
inline constexpr char kLacrosSelectionStateful[] = "stateful";
// To be called at primary user login, to cache the policy value for
// LacrosSelection policy. The effective value of the policy does not
// change for the duration of the user session, so cached value shall be
// checked.
COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_STANDALONE_BROWSER)
void CacheLacrosSelection(const policy::PolicyMap& map);
// Returns cached value of LacrosSelection policy. See `CacheLacrosSelection`
// for details.
COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_STANDALONE_BROWSER)
LacrosSelectionPolicy GetCachedLacrosSelectionPolicy();
// Returns lacros selection option according to LarcrosSelectionPolicy and
// lacros-selection flag. Returns nullopt if there is no preference.
COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_STANDALONE_BROWSER)
std::optional<LacrosSelection> DetermineLacrosSelection();
// Parses the string representation of LacrosSelection policy value into the
// enum value. Returns nullopt on unknown value.
COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_STANDALONE_BROWSER)
std::optional<LacrosSelectionPolicy> ParseLacrosSelectionPolicy(
std::string_view value);
// Returns the LacrosSelection policy value name from the given value. Returned
// std::string_view is guaranteed to never be invalidated.
COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_STANDALONE_BROWSER)
std::string_view GetLacrosSelectionPolicyName(LacrosSelectionPolicy value);
// Clears the cached value for LacrosSelection policy.
COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_STANDALONE_BROWSER)
void ClearLacrosSelectionCacheForTest();
} // namespace ash::standalone_browser
#endif // CHROMEOS_ASH_COMPONENTS_STANDALONE_BROWSER_LACROS_SELECTION_H_

@ -0,0 +1,170 @@
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/ash/components/standalone_browser/lacros_selection.h"
#include <memory>
#include <optional>
#include "ash/constants/ash_switches.h"
#include "base/test/scoped_command_line.h"
#include "base/values.h"
#include "chromeos/ash/components/standalone_browser/browser_support.h"
#include "components/account_id/account_id.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/policy_constants.h"
#include "components/user_manager/fake_user_manager.h"
#include "components/user_manager/scoped_user_manager.h"
#include "components/user_manager/user.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
// This implementation of RAII for LacrosSelection is to make it easy reset
// the state between runs.
class ScopedLacrosSelectionCache {
public:
explicit ScopedLacrosSelectionCache(
ash::standalone_browser::LacrosSelectionPolicy lacros_selection) {
SetLacrosSelection(lacros_selection);
}
ScopedLacrosSelectionCache(const ScopedLacrosSelectionCache&) = delete;
ScopedLacrosSelectionCache& operator=(const ScopedLacrosSelectionCache&) =
delete;
~ScopedLacrosSelectionCache() {
ash::standalone_browser::ClearLacrosSelectionCacheForTest();
}
private:
void SetLacrosSelection(
ash::standalone_browser::LacrosSelectionPolicy lacros_selection) {
policy::PolicyMap policy;
policy.Set(policy::key::kLacrosSelection, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(GetLacrosSelectionPolicyName(lacros_selection)),
/*external_data_fetcher=*/nullptr);
ash::standalone_browser::CacheLacrosSelection(policy);
}
};
class LacrosSelectionTest : public testing::Test {
public:
LacrosSelectionTest() = default;
~LacrosSelectionTest() override = default;
void SetUp() override {
fake_user_manager_.Reset(std::make_unique<user_manager::FakeUserManager>());
}
void TearDown() override {
if (ash::standalone_browser::BrowserSupport::
IsInitializedForPrimaryUser()) {
ash::standalone_browser::BrowserSupport::Shutdown();
}
fake_user_manager_.Reset();
ash::standalone_browser::BrowserSupport::SetCpuSupportedForTesting(
std::nullopt);
}
const user_manager::User* AddRegularUser(const std::string& email) {
AccountId account_id = AccountId::FromUserEmail(email);
const user_manager::User* user = fake_user_manager_->AddUser(account_id);
fake_user_manager_->UserLoggedIn(account_id, user->username_hash(),
/*browser_restart=*/false,
/*is_child=*/false);
ash::standalone_browser::BrowserSupport::InitializeForPrimaryUser(
policy::PolicyMap(), false, false);
return user;
}
private:
user_manager::TypedScopedUserManager<user_manager::FakeUserManager>
fake_user_manager_;
};
TEST_F(LacrosSelectionTest, LacrosSelection) {
// Neither policy nor command line have any preference on Lacros selection.
EXPECT_FALSE(ash::standalone_browser::DetermineLacrosSelection());
{
// LacrosSelection policy has precedence over command line.
ScopedLacrosSelectionCache cache(
ash::standalone_browser::LacrosSelectionPolicy::kRootfs);
base::test::ScopedCommandLine cmd_line;
cmd_line.GetProcessCommandLine()->AppendSwitchASCII(
ash::standalone_browser::kLacrosSelectionSwitch,
ash::standalone_browser::kLacrosSelectionStateful);
EXPECT_EQ(ash::standalone_browser::DetermineLacrosSelection(),
ash::standalone_browser::LacrosSelection::kRootfs);
}
{
// LacrosSelection allows command line check, but command line is not set.
ScopedLacrosSelectionCache cache(
ash::standalone_browser::LacrosSelectionPolicy::kUserChoice);
EXPECT_FALSE(ash::standalone_browser::DetermineLacrosSelection());
}
{
// LacrosSelection allows command line check.
ScopedLacrosSelectionCache cache(
ash::standalone_browser::LacrosSelectionPolicy::kUserChoice);
base::test::ScopedCommandLine cmd_line;
cmd_line.GetProcessCommandLine()->AppendSwitchASCII(
ash::standalone_browser::kLacrosSelectionSwitch,
ash::standalone_browser::kLacrosSelectionRootfs);
EXPECT_EQ(ash::standalone_browser::DetermineLacrosSelection(),
ash::standalone_browser::LacrosSelection::kRootfs);
}
{
// LacrosSelection allows command line check.
ScopedLacrosSelectionCache cache(
ash::standalone_browser::LacrosSelectionPolicy::kUserChoice);
base::test::ScopedCommandLine cmd_line;
cmd_line.GetProcessCommandLine()->AppendSwitchASCII(
ash::standalone_browser::kLacrosSelectionSwitch,
ash::standalone_browser::kLacrosSelectionStateful);
EXPECT_EQ(ash::standalone_browser::DetermineLacrosSelection(),
ash::standalone_browser::LacrosSelection::kStateful);
}
}
// LacrosSelection has no effect on non-googlers.
TEST_F(LacrosSelectionTest, LacrosSelectionPolicyIgnoreNonGoogle) {
AddRegularUser("user@random.com");
base::test::ScopedCommandLine cmd_line;
cmd_line.GetProcessCommandLine()->AppendSwitch(
ash::switches::kLacrosSelectionPolicyIgnore);
{
ScopedLacrosSelectionCache cache(
ash::standalone_browser::LacrosSelectionPolicy::kRootfs);
EXPECT_EQ(ash::standalone_browser::GetCachedLacrosSelectionPolicy(),
ash::standalone_browser::LacrosSelectionPolicy::kRootfs);
EXPECT_EQ(ash::standalone_browser::DetermineLacrosSelection(),
ash::standalone_browser::LacrosSelection::kRootfs);
}
}
// LacrosSelection has an effect on googlers.
TEST_F(LacrosSelectionTest,
LacrosSelectionPolicyIgnoreGoogleDisableToUserChoice) {
AddRegularUser("user@google.com");
base::test::ScopedCommandLine cmd_line;
cmd_line.GetProcessCommandLine()->AppendSwitch(
ash::switches::kLacrosSelectionPolicyIgnore);
{
ScopedLacrosSelectionCache cache(
ash::standalone_browser::LacrosSelectionPolicy::kRootfs);
EXPECT_EQ(ash::standalone_browser::GetCachedLacrosSelectionPolicy(),
ash::standalone_browser::LacrosSelectionPolicy::kUserChoice);
EXPECT_FALSE(ash::standalone_browser::DetermineLacrosSelection());
}
}
} // namespace