Commit 70f823e5 authored by Olivier Robin's avatar Olivier Robin Committed by Commit Bot

Execute external intents after scene is unblocked

If an external intent comes when Chrome shows a blocking UI, it should
be delayed until it is possible to execute it.

This CL considers the scene as not active if it is blocked.
The activities are stored in startupParameters when they are
received.
When the scene is unblocked, call handleExternalIntents to
execute it.

Bug: 1101786
Change-Id: I8117b0cd328847e03283f0d11fea825708594af5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2292475Reviewed-by: default avatarStepan Khapugin <stkhapugin@chromium.org>
Reviewed-by: default avatarMark Cogan <marq@chromium.org>
Commit-Queue: Olivier Robin <olivierrobin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#788654}
parent 55ae16c8
......@@ -51,10 +51,7 @@ const char* const kUMAMobileSessionStartFromAppsHistogram =
if (startupInformation.isPresentingFirstRunUI) {
UMA_HISTOGRAM_ENUMERATION("FirstRun.LaunchSource", [params launchSource],
first_run::LAUNCH_SIZE);
return NO;
}
if (applicationActive) {
} else if (applicationActive) {
// The app is already active so the applicationDidBecomeActive: method will
// never be called. Open the requested URL immediately and return YES if
// the parsed URL was valid.
......@@ -105,11 +102,11 @@ const char* const kUMAMobileSessionStartFromAppsHistogram =
return YES;
}
return NO;
} else {
// Don't record the first user action if application is not active.
[startupInformation resetFirstUserActionRecorder];
}
// Don't record the first user action.
[startupInformation resetFirstUserActionRecorder];
connectionInformation.startupParameters = params;
return connectionInformation.startupParameters != nil;
}
......
......@@ -396,6 +396,16 @@ TEST_F(URLOpenerTest, PresentingFirstRunUI) {
isPresentingFirstRunUI];
id connectionInformationMock =
[OCMockObject mockForProtocol:@protocol(ConnectionInformation)];
__block ChromeAppStartupParameters* params = nil;
[[connectionInformationMock expect]
setStartupParameters:[OCMArg checkWithBlock:^(
ChromeAppStartupParameters* p) {
params = p;
EXPECT_NSEQ(net::NSURLWithGURL(p.completeURL), url);
EXPECT_EQ(p.callerApp, CALLER_APP_APPLE_MOBILESAFARI);
return YES;
}]];
[[[connectionInformationMock expect] andReturn:params] startupParameters];
id appStateMock = [OCMockObject mockForClass:[AppState class]];
[[appStateMock expect] launchFromURLHandled:NO];
......
......@@ -297,78 +297,8 @@ const char kMultiWindowOpenInNewWindowHistogram[] =
[ContentSuggestionsSchedulerNotifications
notifyForeground:self.mainInterface.browserState];
}
if (IsSceneStartupSupported()) {
if (@available(iOS 13, *)) {
// Handle URL opening from
// |UIWindowSceneDelegate scene:willConnectToSession:options:|.
for (UIOpenURLContext* context in self.sceneState.connectionOptions
.URLContexts) {
URLOpenerParams* params =
[[URLOpenerParams alloc] initWithUIOpenURLContext:context];
[self openTabFromLaunchWithParams:params
startupInformation:self.mainController
appState:self.sceneState.appState];
}
if (self.sceneState.connectionOptions.shortcutItem) {
[UserActivityHandler
performActionForShortcutItem:self.sceneState.connectionOptions
.shortcutItem
completionHandler:nil
tabOpener:self
connectionInformation:self
startupInformation:self.mainController
interfaceProvider:self.interfaceProvider];
}
// See if this scene launched as part of a multiwindow URL opening.
// If so, load that URL (this also creates a new tab to load the URL
// in). No other UI will show in this case.
NSUserActivity* activityWithCompletion;
for (NSUserActivity* activity in self.sceneState.connectionOptions
.userActivities) {
if (ActivityIsURLLoad(activity)) {
UrlLoadParams params = LoadParamsFromActivity(activity);
UrlLoadingBrowserAgent::FromBrowser(self.mainInterface.browser)
->Load(params);
} else if (!activityWithCompletion) {
// Completion involves user interaction.
// Only one can be triggered.
activityWithCompletion = activity;
}
}
if (activityWithCompletion) {
[UserActivityHandler continueUserActivity:activityWithCompletion
applicationIsActive:YES
tabOpener:self
connectionInformation:self
startupInformation:self.mainController];
}
self.sceneState.connectionOptions = nil;
}
if (self.startupParameters) {
ApplicationModeForTabOpening mode =
self.startupParameters.applicationMode;
UrlLoadParams params =
UrlLoadParams::InNewTab(self.startupParameters.externalURL);
BOOL dismissOmnibox =
[self.startupParameters postOpeningAction] != FOCUS_OMNIBOX;
[self dismissModalsAndOpenSelectedTabInMode:mode
withUrlLoadParams:params
dismissOmnibox:dismissOmnibox
completion:^{
self.startupParameters = nil;
}];
}
} else {
NSDictionary* launchOptions = self.mainController.launchOptions;
URLOpenerParams* params =
[[URLOpenerParams alloc] initWithLaunchOptions:launchOptions];
[self openTabFromLaunchWithParams:params
startupInformation:self.mainController
appState:self.sceneState.appState];
}
[self handleExternalIntents];
if (!initializingUIInColdStart && self.tabSwitcherIsActive &&
[self shouldOpenNTPTabOnActivationOfBrowser:self.currentInterface
......@@ -402,6 +332,85 @@ const char kMultiWindowOpenInNewWindowHistogram[] =
}
}
- (void)handleExternalIntents {
if (self.mainController.isPresentingFirstRunUI ||
self.blockingOverlayViewController) {
return;
}
if (IsSceneStartupSupported()) {
if (@available(iOS 13, *)) {
// Handle URL opening from
// |UIWindowSceneDelegate scene:willConnectToSession:options:|.
for (UIOpenURLContext* context in self.sceneState.connectionOptions
.URLContexts) {
URLOpenerParams* params =
[[URLOpenerParams alloc] initWithUIOpenURLContext:context];
[self openTabFromLaunchWithParams:params
startupInformation:self.mainController
appState:self.sceneState.appState];
}
if (self.sceneState.connectionOptions.shortcutItem) {
[UserActivityHandler
performActionForShortcutItem:self.sceneState.connectionOptions
.shortcutItem
completionHandler:nil
tabOpener:self
connectionInformation:self
startupInformation:self.mainController
interfaceProvider:self.interfaceProvider];
}
// See if this scene launched as part of a multiwindow URL opening.
// If so, load that URL (this also creates a new tab to load the URL
// in). No other UI will show in this case.
NSUserActivity* activityWithCompletion;
for (NSUserActivity* activity in self.sceneState.connectionOptions
.userActivities) {
if (ActivityIsURLLoad(activity)) {
UrlLoadParams params = LoadParamsFromActivity(activity);
UrlLoadingBrowserAgent::FromBrowser(self.mainInterface.browser)
->Load(params);
} else if (!activityWithCompletion) {
// Completion involves user interaction.
// Only one can be triggered.
activityWithCompletion = activity;
}
}
if (activityWithCompletion) {
[UserActivityHandler continueUserActivity:activityWithCompletion
applicationIsActive:YES
tabOpener:self
connectionInformation:self
startupInformation:self.mainController];
}
self.sceneState.connectionOptions = nil;
}
if (self.startupParameters) {
ApplicationModeForTabOpening mode =
self.startupParameters.applicationMode;
UrlLoadParams params =
UrlLoadParams::InNewTab(self.startupParameters.externalURL);
BOOL dismissOmnibox =
[self.startupParameters postOpeningAction] != FOCUS_OMNIBOX;
[self dismissModalsAndOpenSelectedTabInMode:mode
withUrlLoadParams:params
dismissOmnibox:dismissOmnibox
completion:^{
self.startupParameters = nil;
}];
}
} else {
NSDictionary* launchOptions = self.mainController.launchOptions;
URLOpenerParams* params =
[[URLOpenerParams alloc] initWithLaunchOptions:launchOptions];
[self openTabFromLaunchWithParams:params
startupInformation:self.mainController
appState:self.sceneState.appState];
}
}
- (void)sceneStateWillShowModalOverlay:(SceneState*)sceneState {
[self displayBlockingOverlay];
}
......@@ -426,6 +435,10 @@ const char kMultiWindowOpenInNewWindowHistogram[] =
}
}
}
if (sceneState.activationLevel >= SceneActivationLevelForegroundActive) {
[self handleExternalIntents];
}
}
// TODO(crbug.com/1072408): factor out into a new class.
......@@ -491,6 +504,10 @@ const char kMultiWindowOpenInNewWindowHistogram[] =
}
BOOL sceneIsActive =
self.sceneState.activationLevel >= SceneActivationLevelForegroundActive;
if (self.mainController.isPresentingFirstRunUI ||
self.blockingOverlayViewController) {
sceneIsActive = NO;
}
[UserActivityHandler continueUserActivity:userActivity
applicationIsActive:sceneIsActive
tabOpener:self
......@@ -736,16 +753,8 @@ const char kMultiWindowOpenInNewWindowHistogram[] =
removeObserver:self
name:kChromeFirstRunUIWillFinishNotification
object:nil];
if (self.startupParameters) {
UrlLoadParams params =
UrlLoadParams::InNewTab(self.startupParameters.externalURL);
[self dismissModalsAndOpenSelectedTabInMode:ApplicationModeForTabOpening::
NORMAL
withUrlLoadParams:params
dismissOmnibox:YES
completion:^{
[self setStartupParameters:nil];
}];
if (self.sceneState.activationLevel >= SceneActivationLevelForegroundActive) {
[self handleExternalIntents];
}
}
......@@ -1977,6 +1986,11 @@ const char kMultiWindowOpenInNewWindowHistogram[] =
DCHECK(URLsToOpen.count == URLContexts.count || URLContexts.count == 1);
BOOL active =
_sceneState.activationLevel >= SceneActivationLevelForegroundActive;
if (self.mainController.isPresentingFirstRunUI ||
self.blockingOverlayViewController) {
active = NO;
}
for (URLOpenerParams* options : URLsToOpen) {
[URLOpener openURL:options
applicationActive:active
......
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