// Copyright 2020 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_BROWSER_MANAGER_H_
#define CHROME_BROWSER_ASH_CROSAPI_BROWSER_MANAGER_H_
#include <memory>
#include <optional>
#include <set>
#include <utility>
#include <vector>
#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "chrome/browser/ash/crosapi/browser_action_queue.h"
#include "chrome/browser/ash/crosapi/browser_launcher.h"
#include "chrome/browser/ash/crosapi/browser_manager_feature.h"
#include "chrome/browser/ash/crosapi/browser_manager_observer.h"
#include "chrome/browser/ash/crosapi/browser_manager_scoped_keep_alive.h"
#include "chrome/browser/ash/crosapi/browser_service_host_observer.h"
#include "chrome/browser/ash/crosapi/browser_util.h"
#include "chrome/browser/ash/crosapi/browser_version_service_ash.h"
#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"
#include "components/policy/core/common/cloud/cloud_policy_core.h"
#include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler_observer.h"
#include "components/policy/core/common/cloud/cloud_policy_store.h"
#include "components/policy/core/common/cloud/component_cloud_policy_service_observer.h"
#include "components/policy/core/common/policy_namespace.h"
#include "components/policy/core/common/values_util.h"
#include "components/session_manager/core/session_manager_observer.h"
#include "components/tab_groups/tab_group_info.h"
#include "components/user_manager/user_manager.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "ui/base/ui_base_types.h"
namespace component_updater {
class ComponentManagerAsh;
} // namespace component_updater
namespace apps {
class AppServiceProxyAsh;
class StandaloneBrowserExtensionApps;
} // namespace apps
namespace ash {
class ApkWebAppService;
namespace login {
class SecurityTokenSessionController;
}
} // namespace ash
namespace drive {
class DriveIntegrationService;
}
namespace extensions {
class AutotestPrivateGetLacrosInfoFunction;
}
namespace policy {
class CloudPolicyCore;
}
namespace user_manager {
class DeviceOwnershipWaiter;
} // namespace user_manager
namespace crosapi {
namespace mojom {
enum class CreationResult;
class Crosapi;
} // namespace mojom
class BrowserAction;
class BrowserLoader;
class FilesAppLauncher;
class PersistentForcedExtensionKeepAlive;
class TestMojoConnectionManager;
using ash::standalone_browser::LacrosSelection;
using component_updater::ComponentUpdateService;
// Manages the lifetime of lacros-chrome, and its loading status. Observes the
// component updater for future updates. This class is a part of ash-chrome.
class BrowserManager : public session_manager::SessionManagerObserver,
public ash::SessionManagerClient::Observer,
public BrowserServiceHostObserver,
public policy::CloudPolicyCore::Observer,
public policy::CloudPolicyStore::Observer,
public policy::ComponentCloudPolicyServiceObserver,
public policy::CloudPolicyRefreshSchedulerObserver,
public user_manager::UserManager::Observer {
public:
// Static getter of BrowserManager instance. In real use cases,
// BrowserManager instance should be unique in the process.
static BrowserManager* Get();
explicit BrowserManager(
scoped_refptr<component_updater::ComponentManagerAsh> manager);
// Constructor for testing.
BrowserManager(std::unique_ptr<BrowserLoader> browser_loader,
ComponentUpdateService* update_service);
BrowserManager(const BrowserManager&) = delete;
BrowserManager& operator=(const BrowserManager&) = delete;
~BrowserManager() override;
// Returns true if Lacros is in running state.
// Virtual for testing.
virtual bool IsRunning() const;
// Return true if Lacros is running, launching or terminating.
// We do not want the multi-signin to be available when Lacros is
// running; therefore, we also have to exclude other states (e.g. if
// Lacros is launched and multi-signin is enabled, we would have
// Lacros running and multiple users signed in simultaneously).
// Virtual for testing.
virtual bool IsRunningOrWillRun() const;
bool IsInitialized() const;
// Returns true if Lacros is terminated.
bool IsTerminated() const { return is_terminated_; }
// Opens the browser window in lacros-chrome.
// If lacros-chrome is not yet launched, it triggers to launch.
// This needs to be called after loading.
// TODO(crbug.com/40703695): Notify callers the result of opening window
// request. Because of asynchronous operations crossing processes,
// there's no guarantee that the opening window request succeeds.
// Currently, its condition and result are completely hidden behind this
// class, so there's no way for callers to handle such error cases properly.
// This design often leads the flakiness behavior of the product and testing,
// so should be avoided.
// If `should_trigger_session_restore` is true, a new window opening should be
// treated like the start of a new session (with potential session restore,
// startup URLs, etc). Otherwise, don't restore the session and instead open a
// new window with the default blank tab.
void NewWindow(bool incognito, bool should_trigger_session_restore);
// Performs a full restore of the lacros browser. This must be done after
// Lacros has been launched from a background state. If `skip_crash_restore`
// is true lacros will perform a full restore and skip any restore prompts.
void OpenForFullRestore(bool skip_crash_restore);
// Returns true if crosapi interface supports NewWindowForDetachingTab API.
bool NewWindowForDetachingTabSupported() const;
// NOTE on callbacks:
// An action's callback (e.g. the last parameter to NewWindowForDetachingTab
// below) will never be invoked with a CreationResult value of
// kBrowserShutdown. In the case of a Lacros shutdown (rather than system
// shutdown), BrowserManager will try to perform the action again later.
using NewWindowForDetachingTabCallback =
base::OnceCallback<void(crosapi::mojom::CreationResult,
const std::string&)>;
// Opens a new window in the browser and transfers the given tab (or group)
// to it.
// NOTE: This method is used by Chrome OS WebUI in tablet mode as a response
// to a drag'n drop operation from the user.
void NewWindowForDetachingTab(const std::u16string& tab_id,
const std::u16string& group_id,
NewWindowForDetachingTabCallback closure);
// Returns true if crosapi interface supports NewFullscreenWindow API.
bool NewFullscreenWindowSupported() const;
using NewFullscreenWindowCallback =
base::OnceCallback<void(crosapi::mojom::CreationResult)>;
// Open a fullscreen browser window in lacros-chrome. The only tab will be
// navigated to the given `url` once the window is launched.
// NOTE: This method is used by Chrome OS web Kiosk session only. The behavior
// may change and it shouldn't be used by anybody else.
// Virtual for testing.
virtual void NewFullscreenWindow(const GURL& url,
NewFullscreenWindowCallback callback);
// Opens a new window in lacros-chrome with the Guest profile if the Guest
// mode is enabled.
void NewGuestWindow();
// Similar to NewWindow(), but opens a tab instead if there already is a
// window. See crosapi::mojom::BrowserService::NewTab for more details.
void NewTab();
// Similar to NewWindow and NewTab. If a suitable window exists, a new tab is
// added. Otherwise a new window is created with session restore (no new tab
// is added to that).
void Launch();
// Opens the specified URL in lacros-chrome. If it is not running,
// it launches lacros-chrome with the given URL.
// See crosapi::mojom::BrowserService::OpenUrl for more details.
void OpenUrl(
const GURL& url,
crosapi::mojom::OpenUrlFrom from,
crosapi::mojom::OpenUrlParams::WindowOpenDisposition disposition,
NavigateParams::PathBehavior path_behavior = NavigateParams::RESPECT);
// Opens the captive portal signin window in lacros-chrome.
void OpenCaptivePortalSignin(const GURL& url);
// If there's already a tab opening the URL in lacros-chrome, in some window
// of the primary profile, activate the tab. Otherwise, opens a tab for
// the given URL. `path_behavior` will be assigned to the variable of the same
// name in the `NavigateParams` struct that's used to perform the actual
// navigation downstream.
void SwitchToTab(const GURL& url, NavigateParams::PathBehavior path_behavior);
// Similar to NewWindow(), but restores a tab recently closed.
// See crosapi::mojom::BrowserService::RestoreTab for more details
void RestoreTab();
// Triggers tab switching in Lacros via horizontal 3-finger swipes.
//
// |x_offset| is in DIP coordinates.
void HandleTabScrubbing(float x_offset, bool is_fling_scroll_event);
// Create a browser with the restored data containing `urls`,
// `bounds`,`tab_group_infos`, `show_state`, `active_tab_index`,
// `first_non_pinned_tab_index`, and `app_name`. Note an non-empty `app_name`
// indicates that the browser window is an app type browser window. Also
// note that` first_non_pinned_tab_indexes` with negative values are ignored
// type constraints for the `first_non_pinned_tab_index` and are enforced on
// the browser side and are dropped if they don't comply with said restraints.
void CreateBrowserWithRestoredData(
const std::vector<GURL>& urls,
const gfx::Rect& bounds,
const std::vector<tab_groups::TabGroupInfo>& tab_group_infos,
const ui::WindowShowState show_state,
int32_t active_tab_index,
int32_t first_non_pinned_tab_index,
const std::string& app_name,
int32_t restore_window_id,
uint64_t lacros_profile_id);
// Opens the profile manager window in lacros-chrome.
void OpenProfileManager();
// Ensures Lacros launches.
// Returns true if Lacros could be launched, resumed, or is already in the
// process of launching. Returns false if Lacros could not be launched.
// NOTE: this method requires the user profile to be already initialized.
bool EnsureLaunch();
// Initialize resources and start Lacros.
//
// NOTE: If InitializeAndStartIfNeeded finds Lacros disabled, it unloads
// Lacros via BrowserLoader::Unload, which also deletes the user data
// directory.
virtual void InitializeAndStartIfNeeded();
// Returns true if keep-alive is enabled.
bool IsKeepAliveEnabled() const;
using GetFeedbackDataCallback = base::OnceCallback<void(base::Value::Dict)>;
// Gathers Lacros feedback data.
// Virtual for testing.
virtual void GetFeedbackData(GetFeedbackDataCallback callback);
// Returns true if crosapi interface supports GetHistograms API.
bool GetHistogramsSupported() const;
using GetHistogramsCallback = base::OnceCallback<void(const std::string&)>;
// Gets Lacros histograms.
void GetHistograms(GetHistogramsCallback callback);
// Returns true if crosapi interface supports GetActiveTabUrl API.
bool GetActiveTabUrlSupported() const;
using GetActiveTabUrlCallback =
base::OnceCallback<void(const std::optional<GURL>&)>;
// Gets Url of the active tab from lacros if there is any.
void GetActiveTabUrl(GetActiveTabUrlCallback callback);
using GetBrowserInformationCallback =
base::OnceCallback<void(crosapi::mojom::DeskTemplateStatePtr)>;
// Gets URLs and active indices of the tab strip models from the Lacros
// browser window.
// Virtual for testing.
virtual void GetBrowserInformation(const std::string& window_unique_id,
GetBrowserInformationCallback callback);
void AddObserver(BrowserManagerObserver* observer);
void RemoveObserver(BrowserManagerObserver* observer);
const std::string& browser_version() const { return browser_version_; }
void set_browser_version(const std::string& version) {
browser_version_ = version;
}
const base::FilePath& lacros_path() const { return lacros_path_; }
// Set the data of device account policy. It is the serialized blob of
// PolicyFetchResponse received from the server, or parsed from the file after
// is was validated by Ash.
void SetDeviceAccountPolicy(const std::string& policy_blob);
// Notifies the BrowserManager that it should prepare for shutdown. This is
// called in the early stages of ash shutdown to give Lacros sufficient time
// for a graceful exit.
void Shutdown();
const BrowserVersionServiceAsh::Delegate* version_service_delegate() const {
return version_service_delegate_.get();
}
void set_version_service_delegate_for_testing(
std::unique_ptr<BrowserVersionServiceAsh::Delegate>
version_service_delegate) {
version_service_delegate_ = std::move(version_service_delegate);
}
// TODO(crbug.com/40275396): Remove this once we refactored to use the
// constructor.
void set_device_ownership_waiter_for_testing(
std::unique_ptr<user_manager::DeviceOwnershipWaiter>
device_ownership_waiter);
void set_relaunch_requested_for_testing(bool relaunch_requested);
// Disable most of BrowserManager's functionality such that it never tries to
// launch Lacros. This is used e.g. by test_ash_chrome.
static void DisableForTesting();
static void EnableForTesting();
void KillLacrosForTesting();
protected:
// The actual Lacros launch mode.
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class LacrosLaunchMode {
// Indicates that Lacros is disabled.
kLacrosDisabled = 0,
// Lacros is the only browser and Ash is disabled.
kLacrosOnly = 3,
kMaxValue = kLacrosOnly
};
// The actual Lacros launch mode.
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class LacrosLaunchModeAndSource {
// Either set by user or system/flags, indicates that Lacros is disabled.
kPossiblySetByUserLacrosDisabled = 0,
// Either set by user or system/flags, Lacros is the only browser and Ash is
// disabled.
kPossiblySetByUserLacrosOnly = 3,
// Enforced by the user, indicates that Lacros is disabled.
kForcedByUserLacrosDisabled = 4 + kPossiblySetByUserLacrosDisabled,
// Enforced by the user, Lacros is the only browser and Ash is disabled.
kForcedByUserLacrosOnly = 4 + kPossiblySetByUserLacrosOnly,
// Enforced by policy, indicates that Lacros is disabled.
kForcedByPolicyLacrosDisabled = 8 + kPossiblySetByUserLacrosDisabled,
// Enforced by policy, Lacros is the only browser and Ash is disabled.
kForcedByPolicyLacrosOnly = 8 + kPossiblySetByUserLacrosOnly,
kMaxValue = kForcedByPolicyLacrosOnly
};
// NOTE: You may have to update tests if you make changes to State, as state_
// is exposed via autotest_private.
enum class State {
// Lacros is not initialized yet.
// Lacros-chrome loading depends on user type, so it needs to wait
// for user session.
NOT_INITIALIZED,
// Lacros-chrome is reloading, because the wrong version was
// pre-launched at login screen.
RELOADING,
// User session started, and now it's mounting lacros-chrome.
MOUNTING,
// Lacros-chrome is unavailable. I.e., failed to load for some reason
// or disabled.
UNAVAILABLE,
// Lacros-chrome is loaded and ready for launching.
STOPPED,
// Params for lacros-chrome are parepared on a background thread.
PREPARING_FOR_LAUNCH,
// Lacros-chrome has been pre-launched at login screen, and it's waiting to
// be unblocked post-login.
PRE_LAUNCHED,
// Lacros-chrome is launching, or resuming a pre-launched instance.
STARTING,
// Mojo connection to lacros-chrome is established so, it's in
// the running state.
RUNNING,
// Following two states represent the Lacros-chrome termination related
// state. There are two types of Lacros-chrome termination. It proceeds in
// the following ways from Ash perspective.
//
// Ash initiated termination:
// 1. Ash requests Lacros to terminate.
// 2. Wait for mojo disconnection. (NOTE: If Ash is shutdown, we skip this
// step since the main message loop may be stopped before receiving mojo
// disconnection.)
// 3. Wait for the process to be terminated.
// The state should be set to WAITING_FOR_MOJO_DISCONNECTED on 1, set to
// WAITING_FOR_PROCESS_TERMINATED on 2 completed and then move forward to
// the next task scheduled after the termination on 3 completed.
// If Ash is shutdown, we skip the step 2, so we immediately enter
// WAITING_FOR_PROCESS_TERMINATED state on 1.
//
// Lacros initiated termination:
// 1. Ash receives mojo disconnection.
// 2. Wait for the process to be terminated
//
// Lacros-chrome is requested to terminate from Ash.
WAITING_FOR_MOJO_DISCONNECTED,
// Mojo connection is disconnected and Lacros-chrome is being terminated
// soon.
// Waiting for the process to be terminated. This is usually set after
// WAITING_FOR_MOJO_DISCONNECTED on mojo disconnected except for the
// scenario when Ash is shutdown, in other word, when Ash skips
// WAITING_FOR_MOJO_DISCONNECTED phase.
WAITING_FOR_PROCESS_TERMINATED,
};
// Changes |state| value and potentially notify observers of the change.
void SetState(State state);
// Posts CreateLogFile() and StartWithLogFile() to the thread pool.
// Also takes care of loading an update first, if available.
// Virtual for tests.
virtual void Start(bool launching_at_login_screen = false);
// BrowserServiceHostObserver:
void OnBrowserServiceConnected(CrosapiId id,
mojo::RemoteSetElementId mojo_id,
mojom::BrowserService* browser_service,
uint32_t browser_service_version) override;
void OnBrowserServiceDisconnected(CrosapiId id,
mojo::RemoteSetElementId mojo_id) override;
// Called when the Mojo connection to lacros-chrome is disconnected. It may be
// "just a Mojo error" or "lacros-chrome crash". This method posts a
// shutdown-blocking async task that waits lacros-chrome to exit, giving it a
// chance to gracefully exit. The task will send a terminate signal to
// lacros-chrome if the process has not terminated within the graceful
// shutdown window.
void OnMojoDisconnected();
// Called when lacros-chrome is terminated and successfully wait(2)ed.
void OnLacrosChromeTerminated();
// Called as soon as the login prompt is visible.
void OnLoginPromptVisible();
// ID for the current Crosapi connection.
// Available only when lacros-chrome is running.
std::optional<CrosapiId> crosapi_id_;
// Proxy to BrowserService mojo service in lacros-chrome.
// Available only when lacros-chrome is running.
struct BrowserServiceInfo {
BrowserServiceInfo(mojo::RemoteSetElementId mojo_id,
mojom::BrowserService* service,
uint32_t interface_version);
BrowserServiceInfo(const BrowserServiceInfo&);
BrowserServiceInfo& operator=(const BrowserServiceInfo&);
~BrowserServiceInfo();
// ID managed in BrowserServiceHostAsh, which is tied to the |service|.
mojo::RemoteSetElementId mojo_id;
// BrowserService proxy connected to lacros-chrome.
raw_ptr<mojom::BrowserService, DanglingUntriaged> service;
// Supported interface version of the BrowserService in Lacros-chrome.
uint32_t interface_version;
};
std::optional<BrowserServiceInfo> browser_service_;
private:
FRIEND_TEST_ALL_PREFIXES(BrowserManagerTest, LacrosKeepAlive);
FRIEND_TEST_ALL_PREFIXES(BrowserManagerTest,
LacrosKeepAliveReloadsWhenUpdateAvailable);
FRIEND_TEST_ALL_PREFIXES(BrowserManagerTest,
LacrosKeepAliveDoesNotBlockRestart);
FRIEND_TEST_ALL_PREFIXES(BrowserManagerTest,
NewWindowReloadsWhenUpdateAvailable);
FRIEND_TEST_ALL_PREFIXES(BrowserManagerTest, OnLacrosUserDataDirRemoved);
friend class apps::StandaloneBrowserExtensionApps;
friend class BrowserManagerScopedKeepAlive;
// App service require the lacros-chrome to keep alive for web apps to:
// 1. Have lacros-chrome running before user open the browser so we can
// have web apps info showing on the app list, shelf, etc..
// 2. Able to interact with web apps (e.g. uninstall) at any time.
// 3. Have notifications.
// TODO(crbug.com/40167449): This is a short term solution to integrate
// web apps in Lacros. Need to decouple the App Platform systems from
// needing lacros-chrome running all the time.
friend class apps::AppServiceProxyAsh;
// TODO(crbug.com/40220252): ApkWebAppService does not yet support app
// installation when lacros-chrome starts at arbitrary points of time, so it
// needs to be kept alive.
friend class ash::ApkWebAppService;
// Only for exposing state_ to Tast tests.
friend class extensions::AutotestPrivateGetLacrosInfoFunction;
// In LacrosOnly mode, certificate provider and smart card connector
// extensions will be running in Lacros, but policy implementation stays in
// Ash. Thus, session controller needs to keep Lacros alive to keep track of
// smart card status.
friend class ash::login::SecurityTokenSessionController;
// Registers a KeepAlive if there is a force-installed extension that should
// always be running.
friend class PersistentForcedExtensionKeepAlive;
friend class PersistentForcedExtensionKeepAliveTest;
// DriveFS requires Lacros to be alive so it can connect to the Docs Offline
// extension. This allows Files App to make Docs files available offline.
friend class drive::DriveIntegrationService;
// Processes the action depending on the current state.
// Ignoring a few exceptional cases, the logic is as follows:
// - If Lacros is ready, the action is performed.
// - If Lacros is not ready and the action is queueable, the action is queued
// (and Lacros started if necessary).
// - Otherwise, the action is cancelled.
void PerformOrEnqueue(std::unique_ptr<BrowserAction> action);
void OnActionPerformed(std::unique_ptr<BrowserAction> action, bool retry);
// Remembers lacros launch mode and migration status by calling
// `SetLacrosMigrationStatus()` and `SetLacrosLaunchMode()`, then kicks off
// the daily reporting for the metrics.
void RecordLacrosLaunchModeAndMigrationStatus();
// Sets `migration_mode_`.
void SetLacrosMigrationStatus();
// Sets `lacros_mode_` and `lacros_mode_and_source_`.
void SetLacrosLaunchMode();
using Feature = BrowserManagerFeature;
// De-registers any already existing KeepAlive features for testing.
class ScopedUnsetAllKeepAliveForTesting {
public:
explicit ScopedUnsetAllKeepAliveForTesting(BrowserManager* manager);
~ScopedUnsetAllKeepAliveForTesting();
private:
raw_ptr<BrowserManager> manager_;
std::set<BrowserManager::Feature> previous_keep_alive_features_;
};
// Ash features that want Lacros to stay running in the background must be
// marked as friends of this class so that lacros owners can audit usage.
std::unique_ptr<BrowserManagerScopedKeepAlive> KeepAlive(Feature feature);
void StartIfNeeded(bool launching_at_login_screen = false);
// This may be called synchronously by the BrowserManager following a
// Terminate() signal during shutdown, or following a call to
// OnMojoDisconnected(). This posts a shutdown blocking task that waits for
// lacros-chrome to cleanly exit for `timeout` duration before forcefully
// killing the process.
void EnsureLacrosChromeTermination(base::TimeDelta timeout);
// Reload and possibly relaunch Lacros.
void HandleReload();
// session_manager::SessionManagerObserver:
void OnSessionStateChanged() override;
// Pre-launch Lacros at login screen. (Can be overridden by tests).
virtual void PrelaunchAtLoginScreen();
// Called on launch process completed.
void OnLaunchComplete(
bool lauching_at_login_screen,
base::expected<BrowserLauncher::LaunchResults,
BrowserLauncher::LaunchFailureReason> launch_results);
// Resume Lacros startup process after login.
void ResumeLaunch();
// Called on ResumeLaunch completed.
void OnResumeLaunchComplete(
base::expected<base::TimeTicks, BrowserLauncher::LaunchFailureReason>
resume_time);
// Launch "Go to files" if the migration error page was clicked.
void HandleGoToFiles();
// ash::SessionManagerClient::Observer:
void EmitLoginPromptVisibleCalled() override;
// BrowserServiceHostObserver:
void OnBrowserRelaunchRequested(CrosapiId id) override;
// CloudPolicyCore::Observer:
void OnCoreConnected(policy::CloudPolicyCore* core) override;
void OnRefreshSchedulerStarted(policy::CloudPolicyCore* core) override;
void OnCoreDisconnecting(policy::CloudPolicyCore* core) override;
void OnCoreDestruction(policy::CloudPolicyCore* core) override;
// policy::CloudPolicyStore::Observer:
void OnStoreLoaded(policy::CloudPolicyStore* store) override;
void OnStoreError(policy::CloudPolicyStore* store) override;
void OnStoreDestruction(policy::CloudPolicyStore* store) override;
// policy::ComponentCloudPolicyService::Observer:
// Updates the component policy for given namespace. The policy blob is JSON
// value received from the server, or parsed from the file after is was
// validated.
void OnComponentPolicyUpdated(
const policy::ComponentPolicyMap& component_policy) override;
void OnComponentPolicyServiceDestruction(
policy::ComponentCloudPolicyService* service) override;
// policy::CloudPolicyRefreshScheduler::Observer:
void OnFetchAttempt(policy::CloudPolicyRefreshScheduler* scheduler) override;
void OnRefreshSchedulerDestruction(
policy::CloudPolicyRefreshScheduler* scheduler) override;
// user_manager::UserManager::Observer:
void OnUserProfileCreated(const user_manager::User& user) override;
// crosapi::BrowserManagerObserver:
void OnLoadComplete(bool launching_at_login_screen,
const base::FilePath& path,
LacrosSelection selection,
base::Version version);
// Methods for features to register and de-register for needing to keep Lacros
// alive.
void StartKeepAlive(Feature feature);
void StopKeepAlive(Feature feature);
// Notifies browser to update its keep-alive status.
// Disabling keep-alive here may shut down the browser in background.
// (i.e., if there's no browser window opened, it may be shut down).
void UpdateKeepAliveInBrowserIfNecessary(bool enabled);
// Shared implementation of OpenUrl and SwitchToTab.
void OpenUrlImpl(
const GURL& url,
crosapi::mojom::OpenUrlParams::WindowOpenDisposition disposition,
crosapi::mojom::OpenUrlFrom from,
NavigateParams::PathBehavior path_behavior);
// Creates windows from template data.
void RestoreWindowsFromTemplate();
// Sending the LaunchMode and MigrationStatus state at least once a day.
// multiple events will get de-duped on the server side.
void OnDailyLaunchModeAndMigrationStatusTimer();
void PerformAction(std::unique_ptr<BrowserAction> action);
// Start a sequence to clear Lacros related data. It posts a task to remove
// Lacros user data directory and if that is successful, calls
// `OnLacrosUserDataDirRemoved()` to clear some prefs set by Lacros in Ash.
// Call if Lacros is disabled and not running.
void ClearLacrosData();
// Called as a callback to `RemoveLacrosUserDataDir()`. `cleared` is set to
// true if the directory existed and was removed successfully.
void OnLacrosUserDataDirRemoved(bool cleared);
base::ObserverList<BrowserManagerObserver> observers_;
// NOTE: The state is exposed to tests via autotest_private.
State state_ = State::NOT_INITIALIZED;
crosapi::BrowserLauncher browser_launcher_;
std::unique_ptr<crosapi::BrowserLoader> browser_loader_;
// Delegate handling various concerns regarding the version service.
std::unique_ptr<BrowserVersionServiceAsh::Delegate> version_service_delegate_;
// Path to the lacros-chrome disk image directory.
base::FilePath lacros_path_;
// Whether we are starting "rootfs" or "stateful" lacros.
std::optional<LacrosSelection> lacros_selection_;
// Version of the browser (e.g. lacros-chrome) displayed to user in feedback
// report, etc. It includes both browser version and channel in the format of:
// {browser version} {channel}
// For example, "87.0.0.1 dev", "86.0.4240.38 beta".
std::string browser_version_;
// Time when the lacros process was launched.
base::TimeTicks lacros_launch_time_;
// Time when the lacros process was resumed (when pre-launching at login
// screen).
base::TimeTicks lacros_resume_time_;
// Remembers the request from Lacros-chrome whether it needs to be
// relaunched. Reset on new process start in any cases.
bool relaunch_requested_ = false;
// Tracks whether Shutdown() has been signalled by ash. This flag ensures any
// new or existing lacros startup tasks are not executed during shutdown.
bool shutdown_requested_ = false;
// Tracks whether unloading Lacros was requested. Used to unload
// Lacros after terminating it in case pre-loading at login screen
// was unnecessary (e.g. because the user doesn't have Lacros enabled).
bool unload_requested_ = false;
// Tracks whether reloading Lacros was requested. Used to reload the right
// Lacros selection (rootfs/stateful) in case the wrong version was pre-loaded
// at login screen.
bool reload_requested_ = false;
// Tracks whether BrowserManager should attempt to load a newer lacros-chrome
// browser version (if an update is possible and a new version is available).
// This helps to avoid re-trying an update multiple times should lacros-chrome
// fail to uprev on a reload.
bool should_attempt_update_ = true;
// Tracks whether lacros-chrome is terminated.
bool is_terminated_ = false;
// Whether a shutdown request was received while Lacros was in prelaunched
// state.
bool shutdown_requested_while_prelaunched_ = false;
// Helps set up and manage the mojo connections between lacros-chrome and
// ash-chrome in testing environment. Only applicable when
// '--lacros-mojo-socket-for-testing' is present in the command line.
std::unique_ptr<TestMojoConnectionManager> test_mojo_connection_manager_;
// The features that are currently registered to keep Lacros alive.
std::set<Feature> keep_alive_features_;
const bool launch_at_login_screen_;
const bool disabled_for_testing_;
// Used to launch files.app when user clicked "Go to files" on the migration
// error screen.
std::unique_ptr<FilesAppLauncher> files_app_launcher_;
// The queue of actions to be performed when Lacros becomes ready.
BrowserActionQueue pending_actions_;
// The timer used to periodically check if the daily event should be
// triggered.
base::RepeatingTimer daily_event_timer_;
// The launch mode and the launch mode with source which were used after
// deciding if Lacros should be used or not.
std::optional<LacrosLaunchMode> lacros_mode_;
std::optional<LacrosLaunchModeAndSource> lacros_mode_and_source_;
// The migration status used to emit UMA reports.
std::optional<browser_util::MigrationStatus> migration_status_;
base::ScopedObservation<user_manager::UserManager,
user_manager::UserManager::Observer>
user_manager_observation_{this};
base::WeakPtrFactory<BrowserManager> weak_factory_{this};
};
} // namespace crosapi
#endif // CHROME_BROWSER_ASH_CROSAPI_BROWSER_MANAGER_H_