# ProfileManager and UserManager in Ash Profile and User is a key concept in Chrome. Each of them are managed by ProfileManager and UserManager class. Since ProfileManager, UserManager, Profile, User... are very huge features, this doc won't cover everything, just going through roughly. ## Profile and User Both of [Profile](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/profiles/profile.h;l=74;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d) and [User](https://source.chromium.org/chromium/chromium/src/+/main:components/user_manager/user.h;l=55;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d) represent the current device user. [User](https://source.chromium.org/chromium/chromium/src/+/main:components/user_manager/user.h;l=55;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d) represents information about the logged in user as AccounId containing username (email) and other info. Profile can be obtained by the user like this: ```cpp= user_manager::UserManager* manager = user_manager::UserManager::Get(); const auto* user = manager->GetActiveUser(); Profile* profile = profile_manager->GetProfileByPath( ash::BrowserContextHelper::Get()->GetBrowserContextPathByUserIdHash( user->username_hash())); ``` IIUC, one User and one Profile correspond to each other <- TODO(hidehiko): Is this correct? ## ProfileManager [ProfileManager](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/profiles/profile_manager.h;l=56;drc=91e4f81f6fb6452b3e3d1d9ec261d6253cd80c69) is a class used to manage the lifecycle of [Profile](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/profiles/profile.h;l=74;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d) object. ProfileManager class defined a static method to get a profile. [GetProfile](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/profiles/profile_manager.h;l=137;drc=91e4f81f6fb6452b3e3d1d9ec261d6253cd80c69) returns Profile corresponding to the profile dirctory path. [GetLastUsedProfile](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/profiles/profile_manager.h;l=80;drc=91e4f81f6fb6452b3e3d1d9ec261d6253cd80c69) returns a last used profile without any additional parameters required. Last used profile can be calculated from the [kProfileLastUsed](https://source.chromium.org/chromium/chromium/src/+/main:chrome/common/pref_names.h;l=1879;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d) value stored in local_state. ## UserManager [UserManager](https://source.chromium.org/chromium/chromium/src/+/main:components/user_manager/user_manager.h;l=45;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d) is a class to manager ChromeOS user. UserManager stores all known users who have logged into this ChromeOS device before. The base implementation is in [UserManagerBase](https://source.chromium.org/chromium/chromium/src/+/main:components/user_manager/user_manager_base.h;l=42;drc=76d2477cc32edc81df39c1bde9a15b16bb7ee2c0). It holds several UserList [`users_`](https://source.chromium.org/chromium/chromium/src/+/main:components/user_manager/user_manager_base.h;l=332;drc=76d2477cc32edc81df39c1bde9a15b16bb7ee2c0), [logged_in_users_](https://source.chromium.org/chromium/chromium/src/+/main:components/user_manager/user_manager_base.h;l=336;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d) and [lru_logged_in_users_](https://source.chromium.org/chromium/chromium/src/+/main:components/user_manager/user_manager_base.cc;l=1304;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d). UserList is `std::vector<User*>`. When there is a new user logged in, [UserLoggedIn](https://source.chromium.org/chromium/chromium/src/+/main:components/user_manager/user_manager_base.cc;l=207;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d) is called and the new user is pushed back to `logged_in_users_` and also set to `lru_logged_in_users_` in the LRU cache mananer via [SetLRUUser](https://source.chromium.org/chromium/chromium/src/+/main:components/user_manager/user_manager_base.cc;l=1304;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d). [SetActiveUser](https://source.chromium.org/chromium/chromium/src/+/main:components/user_manager/user_manager_base.cc;l=304;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d), on the other hand, only changes the order of LRU cache, so does not append to `logged_in_users_` and just call SetLRUUser. Also, there is a unique [`owner_account_id_`](https://source.chromium.org/chromium/chromium/src/+/main:components/user_manager/user_manager_base.h;l=415;drc=76d2477cc32edc81df39c1bde9a15b16bb7ee2c0), [`active_user_`](https://source.chromium.org/chromium/chromium/src/+/main:components/user_manager/user_manager_base.h;l=323;drc=76d2477cc32edc81df39c1bde9a15b16bb7ee2c0) and [`primary_user_`](https://source.chromium.org/chromium/chromium/src/+/main:components/user_manager/user_manager_base.h;l=327;drc=76d2477cc32edc81df39c1bde9a15b16bb7ee2c0). UserManager holds these special users info as well. ## Initialization in Ash Let's see how it's initialized in Ash-chrome. ProfileManager and UserManager are initialized in [ChromeBrowserMainPartsAsh::PreProfileInit](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/ash/chrome_browser_main_parts_ash.cc;l=875;drc=aedfccdca8513a865d8014894d2dce6ba00a50c9). PreProfileInit runs just before creating Profile. The caller is [ChromeBrowserMain::PreMainMessageLoopRunImpl](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/chrome_browser_main.cc;l=1631;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d). Soon after PreProfileInit is called, it runs [CreateInitilProfile](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/chrome_browser_main.cc;l=1642;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d) which initializes a initial profile. UserManager is stored as a private member of `chrome_user_manager_`. It is owned by BrowserProcessPlatformPartsAsh. It can be accessed via [`user_manager::UserManager::Get()`](https://source.chromium.org/chromium/chromium/src/+/main:components/user_manager/user_manager.cc;l=88;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d). Note that this function returns the object as UserManager type so you need to cast it to whatever the class you intend to receive. On the other hand, ProfileManager is stored as a private member `profile_manager_` in [BrowserProcessImpl](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/browser_process_impl.h;l=268;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d). It can be accessed via [`g_browser_process->profile_manager()`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/browser_process.h;l=142;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d). [ChromeUserManagerImpl](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/ash/login/users/chrome_user_manager_impl.h;l=53;drc=8354cc102a9585b723bb23d36f5dd8ac92ae5585) is a implementation of UserManager specific to Chrome, and this is used in Ash as well. [CreateChromeUserManager](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/ash/login/users/chrome_user_manager_impl.cc;l=285;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d) calls ChromeUserManagerImpl constructor. Here, there is a method accessing ProfileManager. ```cpp= if (ProfileManager* profile_manager = g_browser_process->profile_manager()) { profile_manager_observation_.Observe(profile_manager); } ``` ProfileManager uses lazy initialization technique. As you can see in [`g_browser_process->profile_manager()`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/browser_process.h;l=142;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d), if `created_profile_manager_` is false, it creates ProfileManager. If not, it immediately returns exising ProfileManager object. In the production code, this `profile_manager()` in CreateChromeUserManager is the first call which means ProfileManager is initialized insite ChromeUserManager constructor. Note: As ChromeUserManager already initializes ProfileManager, `profile_manager()` call [here](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/ash/chrome_browser_main_parts_ash.cc;l=903-905;drc=aedfccdca8513a865d8014894d2dce6ba00a50c9) does not have any affect. Probably we can remove it? ## TestingProfileManager [TestingProfileManager](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/base/testing_profile_manager.h;l=43;drc=679f23e8fbb29ca4dd569dff0bba0977516926ae) is a TestingProfile factory used in testing. This is a substitue of ProfileManager for testing so that we can register Profile created from [CreateTestingProfile](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/base/testing_profile_manager.h;l=71;drc=679f23e8fbb29ca4dd569dff0bba0977516926ae). TestingProfileManager holds a [weak ptr to ProfileManager](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/base/testing_profile_manager.h;l=183;drc=679f23e8fbb29ca4dd569dff0bba0977516926ae). This is not ProfileManager but [FakeProfileManager](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/base/fake_profile_manager.h;l=28;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d) derived from [ProfileManagerWithoutInit](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/profiles/profile_manager.h;l=627;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d) which, as the name says, skips initializing. Instead, you can set it via [TestingBrowserProcess::SetProfileManager](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/base/testing_browser_process.cc;l=255;drc=23b4d41ca6ed99085c2c06889be1c1d765afdc2d). It uses [TestingBrowserProcess](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/base/testing_profile_manager.h;l=174;drc=679f23e8fbb29ca4dd569dff0bba0977516926ae) and [ScopedTestingLocalState](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/base/testing_profile_manager.h;l=177;drc=679f23e8fbb29ca4dd569dff0bba0977516926ae).