// 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.
#import "ios/chrome/browser/browser_state_metrics/model/browser_state_activity_app_agent.h"
#import "base/time/time.h"
#import "components/signin/core/browser/active_primary_accounts_metrics_recorder.h"
#import "components/signin/public/identity_manager/identity_manager.h"
#import "ios/chrome/app/application_delegate/app_state.h"
#import "ios/chrome/app/profile/profile_state.h"
#import "ios/chrome/browser/shared/coordinator/scene/scene_state.h"
#import "ios/chrome/browser/shared/model/application_context/application_context.h"
#import "ios/chrome/browser/shared/model/browser/browser.h"
#import "ios/chrome/browser/shared/model/browser/browser_provider.h"
#import "ios/chrome/browser/shared/model/browser/browser_provider_interface.h"
#import "ios/chrome/browser/shared/model/profile/profile_attributes_ios.h"
#import "ios/chrome/browser/shared/model/profile/profile_attributes_storage_ios.h"
#import "ios/chrome/browser/shared/model/profile/profile_ios.h"
#import "ios/chrome/browser/shared/model/profile/profile_manager_ios.h"
#import "ios/chrome/browser/signin/model/identity_manager_factory.h"
@implementation BrowserStateActivityAppAgent
#pragma mark - Private methods
- (void)recordActivationForSceneState:(SceneState*)sceneState {
ChromeBrowserState* browserState =
sceneState.appState.mainProfile.browserState;
// Update the ProfileIOS's last-active time stored in the preferences.
GetApplicationContext()
->GetProfileManager()
->GetProfileAttributesStorage()
->UpdateAttributesForProfileWithName(
browserState->GetBrowserStateName(),
base::BindOnce([](ProfileAttributesIOS attr) {
attr.SetLastActiveTime(base::Time::Now());
return attr;
}));
// Update the primary account's last-active time (if there is a primary
// account).
signin::IdentityManager* identityManager =
IdentityManagerFactory::GetForBrowserState(browserState);
signin::ActivePrimaryAccountsMetricsRecorder* activeAccountsTracker =
GetApplicationContext()->GetActivePrimaryAccountsMetricsRecorder();
// IdentityManager is null for incognito profiles.
if (activeAccountsTracker && identityManager &&
identityManager->HasPrimaryAccount(signin::ConsentLevel::kSignin)) {
CoreAccountInfo accountInfo =
identityManager->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin);
activeAccountsTracker->MarkAccountAsActiveNow(accountInfo.gaia);
}
}
#pragma mark - AppStateObserver
- (void)appState:(AppState*)appState
didTransitionFromInitStage:(InitStage)previousInitStage {
[super appState:appState didTransitionFromInitStage:previousInitStage];
if (appState.initStage != InitStageBrowserObjectsForUI) {
return;
}
// Check if any scene has already reached foreground active state.
for (SceneState* sceneState in appState.connectedScenes) {
if (sceneState.activationLevel == SceneActivationLevelForegroundActive) {
[self recordActivationForSceneState:sceneState];
}
}
}
#pragma mark - SceneStateObserver
- (void)sceneState:(SceneState*)sceneState
transitionedToActivationLevel:(SceneActivationLevel)level {
[super sceneState:sceneState transitionedToActivationLevel:level];
// Ignore if the app has not loaded the ChromeBrowserState yet.
if (sceneState.appState.initStage < InitStageBrowserObjectsForUI) {
return;
}
if (level == SceneActivationLevelForegroundActive) {
[self recordActivationForSceneState:sceneState];
}
}
@end