chromium/ios/chrome/app/application_delegate/app_state.h

// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef IOS_CHROME_APP_APPLICATION_DELEGATE_APP_STATE_H_
#define IOS_CHROME_APP_APPLICATION_DELEGATE_APP_STATE_H_

#import <UIKit/UIKit.h>

#import "ios/chrome/app/application_delegate/app_state_agent.h"
#import "ios/chrome/app/application_delegate/app_state_observer.h"
#import "ios/chrome/browser/shared/coordinator/scene/scene_state_observer.h"
#import "ios/chrome/browser/ui/scoped_iphone_portrait_only/iphone_portrait_only_manager.h"
#import "ios/chrome/browser/ui/scoped_ui_blocker/ui_blocker_manager.h"

@class CommandDispatcher;
@class SceneState;
@class MemoryWarningHelper;
@class MetricsMediator;
@class ProfileState;
@protocol StartupInformation;

namespace base {
class TimeTicks;
}

// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class PostCrashAction {
  // Restore tabs normally after a clean shutdown.
  kRestoreTabsCleanShutdown = 0,
  // Restore tabs normally after an unclean shutdown.
  kRestoreTabsUncleanShutdown = 1,
  // kStashTabsAndShowNTP is no longer used, but the value 2 cannot be reused
  // as it would break histograms.
  // Restore tabs with `return to previous tab` NTP.
  kShowNTPWithReturnToTab = 3,
  // Show safe mode.
  kShowSafeMode = 4,
  kMaxValue = kShowSafeMode,
};

// Represents the application state and responds to application state changes
// and system events.
@interface AppState
    : NSObject <IphonePortraitOnlyManager, SceneStateObserver, UIBlockerManager>

- (instancetype)init NS_UNAVAILABLE;

- (instancetype)initWithStartupInformation:
    (id<StartupInformation>)startupInformation NS_DESIGNATED_INITIALIZER;

// Dispatcher for app-level commands for multiwindow use cases.
// Most features should use the browser-level dispatcher instead.
@property(nonatomic, strong) CommandDispatcher* appCommandDispatcher;

// The ProfileState associated with the main Profile.
// TODO(crbug.com/324417250) remove this property.
@property(nonatomic, weak) ProfileState* mainProfile;

// Container for startup information.
@property(nonatomic, weak) id<StartupInformation> startupInformation;

// YES if the user has ever interacted with the application. May be NO if the
// application has been woken up by the system for background work.
@property(nonatomic, readonly) BOOL userInteracted;

// YES if the sign-in upgrade promo has been presented to the user, once.
@property(nonatomic) BOOL signinUpgradePromoPresentedOnce;

// YES if the sign-out prompt should be shown to the user when the scene becomes
// active and enters the foreground. This can happen if the policies have
// changed since the last cold start, meaning the user was signed out during
// startup.
@property(nonatomic) BOOL shouldShowForceSignOutPrompt;

// Indicates what action, if any, is taken after a crash (stash tabs, show NTP,
// show safe mode).
@property(nonatomic, assign) PostCrashAction postCrashAction;

// YES if the app is resuming from safe mode.
@property(nonatomic) BOOL resumingFromSafeMode;

// Timestamp of when a scene was last becoming active. Can be null.
@property(nonatomic, assign) base::TimeTicks lastTimeInForeground;

// The initialization stage the app is currently at.
@property(nonatomic, readonly) InitStage initStage;

// This flag is set when the first scene has initialized its UI and never
// resets.
@property(nonatomic, readonly) BOOL firstSceneHasInitializedUI;

// YES if the views being presented should only support the portrait
// orientation.
@property(nonatomic, readonly) BOOL portraitOnly;

// YES if the application is getting terminated.
@property(nonatomic, readonly) BOOL appIsTerminating;
@property(nonatomic, assign, readwrite) BOOL overridePortraitOnly;

// All agents that have been attached. Use -addAgent: and -removeAgent: to
// add and remove agents.
@property(nonatomic, readonly) NSArray<id<AppStateAgent>>* connectedAgents;

// Logs duration of the session and records that chrome is no longer in cold
// start.
- (void)willResignActive;

// Called when the application is getting terminated. It stops all outgoing
// requests, config updates, clears the device sharing manager and stops the
// mainChrome instance.
- (void)applicationWillTerminate:(UIApplication*)application;

// Called when the application discards set of scene sessions, these sessions
// can no longer be accessed and all their associated data should be destroyed.
- (void)application:(UIApplication*)application
    didDiscardSceneSessions:(NSSet<UISceneSession*>*)sceneSessions;

// Called when going into the background. iOS already broadcasts, so
// stakeholders can register for it directly.
- (void)applicationDidEnterBackground:(UIApplication*)application
                         memoryHelper:(MemoryWarningHelper*)memoryHelper;

// Called when returning to the foreground. Resets and uploads the metrics.
// Starts the browser to foreground if needed.
- (void)applicationWillEnterForeground:(UIApplication*)application
                       metricsMediator:(MetricsMediator*)metricsMediator
                          memoryHelper:(MemoryWarningHelper*)memoryHelper;

// Returns the foreground and active scene, if there is one.
- (SceneState*)foregroundActiveScene;

// Returns a list of all connected scenes.
- (NSArray<SceneState*>*)connectedScenes;

// Returns a list of all scenes in the foreground that are not necessarly
// active.
- (NSArray<SceneState*>*)foregroundScenes;

// Adds an observer to this app state. The observers will be notified about
// app state changes per AppStateObserver protocol.
// The observer will be *immediately* notified about the latest init stage
// transition, if any such transitions happened (didTransitionFromInitStage),
// before this method returns.
- (void)addObserver:(id<AppStateObserver>)observer;
// Removes the observer. It's safe to call this at any time, including from
// AppStateObserver callbacks.
- (void)removeObserver:(id<AppStateObserver>)observer;

// Adds a new agent. Agents are owned by the app state.
// This automatically sets the app state on the `agent`.
- (void)addAgent:(id<AppStateAgent>)agent;
// Removes an agent.
- (void)removeAgent:(id<AppStateAgent>)agent;

// Queue the transition to the next app initialization stage. Will stop
// transitioning when the Final stage is reached.
// All observers will be notified about each transition until the next
// transition takes place. If an observer calls this method from a transition
// notification, the method will return, the observers will be notified of the
// prior change, and then transition will take place. Then this method will
// finally return to the runloop. It is an error to queue more than one
// transition at once.
- (void)queueTransitionToNextInitStage;

// Queue the transition (as defined above) to the very first initialization
// stage.
- (void)startInitialization;

@end

#endif  // IOS_CHROME_APP_APPLICATION_DELEGATE_APP_STATE_H_