Commit ec424376 authored by Mark Cogan's avatar Mark Cogan Committed by Commit Bot

[iOS] Prevent AppState getting the BrowserInterface for zero scenes.

In some circumstances, the shutdown logic can run when there are no
connected scenes (possibly when force-quitting). Asking for the
browser interface in this situation will cause an array overflow. This
CL is a quick patch to bypass that pending a cleaner fixup.

Bug: 1113097
Change-Id: I3e14c9bbd887c7ef66ee7e6454f4484bad8cb03a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2367080
Commit-Queue: Mark Cogan <marq@chromium.org>
Reviewed-by: default avatarRohit Rao <rohitrao@chromium.org>
Cr-Commit-Position: refs/heads/master@{#801083}
parent b4349b2d
...@@ -456,8 +456,14 @@ initWithBrowserLauncher:(id<BrowserLauncher>)browserLauncher ...@@ -456,8 +456,14 @@ initWithBrowserLauncher:(id<BrowserLauncher>)browserLauncher
// Halt the tabs, so any outstanding requests get cleaned up, without actually // Halt the tabs, so any outstanding requests get cleaned up, without actually
// closing the tabs. Set the BVC to inactive to cancel all the dialogs. // closing the tabs. Set the BVC to inactive to cancel all the dialogs.
if ([_browserLauncher browserInitializationStage] >= // Don't do this if there are no scenes, since there's no defined interface
INITIALIZATION_STAGE_FOREGROUND) { // provider (and no tabs)
// TODO(crbug.com/1113097): Factor out this check by not having app layer
// logic use interface providers.
BOOL scenesAreAvailable = [self connectedScenes].count > 0;
if (scenesAreAvailable && [_browserLauncher browserInitializationStage] >=
INITIALIZATION_STAGE_FOREGROUND) {
_browserLauncher.interfaceProvider.currentInterface.userInteractionEnabled = _browserLauncher.interfaceProvider.currentInterface.userInteractionEnabled =
NO; NO;
} }
...@@ -566,8 +572,10 @@ initWithBrowserLauncher:(id<BrowserLauncher>)browserLauncher ...@@ -566,8 +572,10 @@ initWithBrowserLauncher:(id<BrowserLauncher>)browserLauncher
NSSet* connectedScenes = NSSet* connectedScenes =
[UIApplication sharedApplication].connectedScenes; [UIApplication sharedApplication].connectedScenes;
for (UIWindowScene* scene in connectedScenes) { for (UIWindowScene* scene in connectedScenes) {
if (!scene.delegate) { if (![scene.delegate isKindOfClass:[SceneDelegate class]]) {
// This might happen in tests. // This might happen in tests.
// TODO(crbug.com/1113097): This shouldn't be needed.
[sceneStates addObject:[[SceneState alloc] initWithAppState:self]];
continue; continue;
} }
...@@ -577,11 +585,11 @@ initWithBrowserLauncher:(id<BrowserLauncher>)browserLauncher ...@@ -577,11 +585,11 @@ initWithBrowserLauncher:(id<BrowserLauncher>)browserLauncher
} }
return sceneStates; return sceneStates;
} }
NOTREACHED(); } else if (self.mainSceneState) {
return @[];
} else {
return @[ self.mainSceneState ]; return @[ self.mainSceneState ];
} }
// This can happen if the app is terminating before any scenes are set up.
return @[];
} }
- (void)setLastTappedWindow:(UIWindow*)window { - (void)setLastTappedWindow:(UIWindow*)window {
......
...@@ -568,6 +568,11 @@ TEST_F(AppStateWithThreadTest, willTerminate) { ...@@ -568,6 +568,11 @@ TEST_F(AppStateWithThreadTest, willTerminate) {
startupInformation:startupInformation startupInformation:startupInformation
applicationDelegate:applicationDelegate]; applicationDelegate:applicationDelegate];
// Create a scene state so that full shutdown will run.
if (!IsSceneStartupSupported()) {
appState.mainSceneState = [[SceneState alloc] initWithAppState:appState];
}
id application = [OCMockObject mockForClass:[UIApplication class]]; id application = [OCMockObject mockForClass:[UIApplication class]];
// Action. // Action.
......
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