Commit 11df9fa2 authored by Olivier Robin's avatar Olivier Robin Committed by Commit Bot

Fix safe mode exit crash

Scene UI is not initialized in safe mode.
When exiting safe mode, initialize the UI of the sceneState
before continuing the startup sequence.

Bug: 1137310
Change-Id: I61c4a3faeed8d7728a8ecbb1b191e8621e72e4f2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2476280
Commit-Queue: Olivier Robin <olivierrobin@chromium.org>
Reviewed-by: default avatarStepan Khapugin <stkhapugin@chromium.org>
Reviewed-by: default avatarMark Cogan <marq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#818898}
parent 04474306
...@@ -32,9 +32,9 @@ class ChromeBrowserState; ...@@ -32,9 +32,9 @@ class ChromeBrowserState;
// On iOS 12, called when the mainSceneState is set. // On iOS 12, called when the mainSceneState is set.
- (void)appState:(AppState*)appState sceneConnected:(SceneState*)sceneState; - (void)appState:(AppState*)appState sceneConnected:(SceneState*)sceneState;
// Called when the first scene becomes active. // Called when the first scene initializes its UI.
- (void)appState:(AppState*)appState - (void)appState:(AppState*)appState
firstSceneActivated:(SceneState*)sceneState; firstSceneHasInitializedUI:(SceneState*)sceneState;
// Called after the app exits safe mode. // Called after the app exits safe mode.
- (void)appStateDidExitSafeMode:(AppState*)appState; - (void)appStateDidExitSafeMode:(AppState*)appState;
......
...@@ -139,6 +139,9 @@ NSString* const kStartupAttemptReset = @"StartupAttempReset"; ...@@ -139,6 +139,9 @@ NSString* const kStartupAttemptReset = @"StartupAttempReset";
// never reset. // never reset.
@property(nonatomic, assign) BOOL firstSceneHasActivated; @property(nonatomic, assign) BOOL firstSceneHasActivated;
// This flag is set when the first scene has initialized its UI and never reset.
@property(nonatomic, assign) BOOL firstSceneHasInitializedUI;
// The current blocker target if any. // The current blocker target if any.
@property(nonatomic, weak, readwrite) id<UIBlockerTarget> uiBlockerTarget; @property(nonatomic, weak, readwrite) id<UIBlockerTarget> uiBlockerTarget;
...@@ -698,14 +701,21 @@ initWithBrowserLauncher:(id<BrowserLauncher>)browserLauncher ...@@ -698,14 +701,21 @@ initWithBrowserLauncher:(id<BrowserLauncher>)browserLauncher
return self.uiBlockerTarget; return self.uiBlockerTarget;
} }
#pragma mark - SceneStateObserver
- (void)sceneStateHasInitializedUI:(SceneState*)sceneState {
if (self.firstSceneHasInitializedUI) {
return;
}
self.firstSceneHasInitializedUI = YES;
[self.observers appState:self firstSceneHasInitializedUI:sceneState];
}
- (void)sceneState:(SceneState*)sceneState - (void)sceneState:(SceneState*)sceneState
transitionedToActivationLevel:(SceneActivationLevel)level { transitionedToActivationLevel:(SceneActivationLevel)level {
if (level >= SceneActivationLevelForegroundActive) { if (level >= SceneActivationLevelForegroundActive) {
if (!self.firstSceneHasActivated) { if (!self.firstSceneHasActivated) {
self.firstSceneHasActivated = YES; self.firstSceneHasActivated = YES;
[self.observers appState:self firstSceneActivated:sceneState];
if (self.isInSafeMode) { if (self.isInSafeMode) {
// Safe mode can only be started when there's a window, so the actual // Safe mode can only be started when there's a window, so the actual
// safe mode has been postponed until now. // safe mode has been postponed until now.
......
...@@ -603,14 +603,8 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData( ...@@ -603,14 +603,8 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
// Called when the first scene becomes active. // Called when the first scene becomes active.
- (void)appState:(AppState*)appState - (void)appState:(AppState*)appState
firstSceneActivated:(SceneState*)sceneState { firstSceneHasInitializedUI:(SceneState*)sceneState {
if (appState.isInSafeMode) { DCHECK(!appState.isInSafeMode);
return;
}
[self startUpAfterFirstWindowCreated];
}
- (void)appStateDidExitSafeMode:(AppState*)appState {
[self startUpAfterFirstWindowCreated]; [self startUpAfterFirstWindowCreated];
} }
......
...@@ -153,9 +153,6 @@ const char kMultiWindowOpenInNewWindowHistogram[] = ...@@ -153,9 +153,6 @@ const char kMultiWindowOpenInNewWindowHistogram[] =
// browser state level UrlLoadingService instances. // browser state level UrlLoadingService instances.
@property(nonatomic, assign) SceneUrlLoadingService* sceneURLLoadingService; @property(nonatomic, assign) SceneUrlLoadingService* sceneURLLoadingService;
// A flag that keeps track of the UI initialization for the controlled scene.
@property(nonatomic, assign) BOOL hasInitializedUI;
// Returns YES if the settings are presented, either from // Returns YES if the settings are presented, either from
// self.settingsNavigationController or from SigninCoordinator. // self.settingsNavigationController or from SigninCoordinator.
@property(nonatomic, assign, readonly, getter=isSettingsViewPresented) @property(nonatomic, assign, readonly, getter=isSettingsViewPresented)
...@@ -306,8 +303,8 @@ const char kMultiWindowOpenInNewWindowHistogram[] = ...@@ -306,8 +303,8 @@ const char kMultiWindowOpenInNewWindowHistogram[] =
// ends. // ends.
return; return;
} }
BOOL initializingUIInColdStart = BOOL initializingUIInColdStart = level > SceneActivationLevelBackground &&
level > SceneActivationLevelBackground && !self.hasInitializedUI; !self.sceneState.hasInitializedUI;
if (initializingUIInColdStart) { if (initializingUIInColdStart) {
[self initializeUI]; [self initializeUI];
if (IsMultiwindowSupported()) { if (IsMultiwindowSupported()) {
...@@ -362,7 +359,8 @@ const char kMultiWindowOpenInNewWindowHistogram[] = ...@@ -362,7 +359,8 @@ const char kMultiWindowOpenInNewWindowHistogram[] =
} }
} }
if (self.hasInitializedUI && level == SceneActivationLevelUnattached) { if (self.sceneState.hasInitializedUI &&
level == SceneActivationLevelUnattached) {
if (IsMultiwindowSupported()) { if (IsMultiwindowSupported()) {
if (@available(iOS 13, *)) { if (@available(iOS 13, *)) {
if (IsMultipleScenesSupported()) { if (IsMultipleScenesSupported()) {
...@@ -551,12 +549,12 @@ const char kMultiWindowOpenInNewWindowHistogram[] = ...@@ -551,12 +549,12 @@ const char kMultiWindowOpenInNewWindowHistogram[] =
#pragma mark - private #pragma mark - private
- (void)initializeUI { - (void)initializeUI {
if (self.hasInitializedUI) { if (self.sceneState.hasInitializedUI) {
return; return;
} }
[self startUpChromeUI]; [self startUpChromeUI];
self.hasInitializedUI = YES; self.sceneState.hasInitializedUI = YES;
} }
// Returns YES if restore prompt can be shown. // Returns YES if restore prompt can be shown.
...@@ -745,7 +743,7 @@ const char kMultiWindowOpenInNewWindowHistogram[] = ...@@ -745,7 +743,7 @@ const char kMultiWindowOpenInNewWindowHistogram[] =
// This method completely destroys all of the UI. It should be called when the // This method completely destroys all of the UI. It should be called when the
// scene is disconnected. // scene is disconnected.
- (void)teardownUI { - (void)teardownUI {
if (!self.hasInitializedUI) { if (!self.sceneState.hasInitializedUI) {
return; // Nothing to do. return; // Nothing to do.
} }
...@@ -776,7 +774,7 @@ const char kMultiWindowOpenInNewWindowHistogram[] = ...@@ -776,7 +774,7 @@ const char kMultiWindowOpenInNewWindowHistogram[] =
[self.browserViewWrangler shutdown]; [self.browserViewWrangler shutdown];
self.browserViewWrangler = nil; self.browserViewWrangler = nil;
self.hasInitializedUI = NO; self.sceneState.hasInitializedUI = NO;
[self.sceneState.appState removeObserver:self]; [self.sceneState.appState removeObserver:self];
} }
......
...@@ -100,6 +100,9 @@ typedef NS_ENUM(NSUInteger, SceneActivationLevel) { ...@@ -100,6 +100,9 @@ typedef NS_ENUM(NSUInteger, SceneActivationLevel) {
// |UISceneDelegate scene:continueUserActivity:| and needs to be opened. // |UISceneDelegate scene:continueUserActivity:| and needs to be opened.
@property(nonatomic) NSUserActivity* pendingUserActivity; @property(nonatomic) NSUserActivity* pendingUserActivity;
// A flag that keeps track of the UI initialization for the controlled scene.
@property(nonatomic, assign) BOOL hasInitializedUI;
// Adds an observer to this scene state. The observers will be notified about // Adds an observer to this scene state. The observers will be notified about
// scene state changes per SceneStateObserver protocol. // scene state changes per SceneStateObserver protocol.
- (void)addObserver:(id<SceneStateObserver>)observer; - (void)addObserver:(id<SceneStateObserver>)observer;
......
...@@ -113,6 +113,16 @@ ...@@ -113,6 +113,16 @@
[self.observers sceneState:self transitionedToActivationLevel:newLevel]; [self.observers sceneState:self transitionedToActivationLevel:newLevel];
} }
- (void)setHasInitializedUI:(BOOL)hasInitializedUI {
if (_hasInitializedUI == hasInitializedUI) {
return;
}
_hasInitializedUI = hasInitializedUI;
if (hasInitializedUI) {
[self.observers sceneStateHasInitializedUI:self];
}
}
- (id<BrowserInterfaceProvider>)interfaceProvider { - (id<BrowserInterfaceProvider>)interfaceProvider {
return self.controller.interfaceProvider; return self.controller.interfaceProvider;
} }
......
...@@ -26,6 +26,8 @@ enum SceneActivationLevel : NSUInteger; ...@@ -26,6 +26,8 @@ enum SceneActivationLevel : NSUInteger;
- (void)sceneStateWillHideModalOverlay:(SceneState*)sceneState; - (void)sceneStateWillHideModalOverlay:(SceneState*)sceneState;
// Notifies when presentingModalOverlay has been set to false. // Notifies when presentingModalOverlay has been set to false.
- (void)sceneStateDidHideModalOverlay:(SceneState*)sceneState; - (void)sceneStateDidHideModalOverlay:(SceneState*)sceneState;
// Notifies when hasInitializedUI has been set.
- (void)sceneStateHasInitializedUI:(SceneState*)sceneState;
// Notifies when URLContexts have been added to |URLContextsToOpen|. // Notifies when URLContexts have been added to |URLContextsToOpen|.
- (void)sceneState:(SceneState*)sceneState - (void)sceneState:(SceneState*)sceneState
hasPendingURLs:(NSSet<UIOpenURLContext*>*)URLContexts hasPendingURLs:(NSSet<UIOpenURLContext*>*)URLContexts
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment