Commit b461eca9 authored by Chris Lu's avatar Chris Lu Committed by Commit Bot

[ios] Add Main Intent Action

This change adds a new hasPendingExternalIntent property to SceneState
to track scenes that receive an external intent. It is used in
firstSceneWillEnterForeground: to identify app opens that were not
triggered by an external intent and log a user action for it.

Change-Id: I8925457131c47162b68a9ada1c3deeba9554ee0d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2486395Reviewed-by: default avatarOlivier Robin <olivierrobin@chromium.org>
Reviewed-by: default avatarAlexei Svitkine <asvitkine@chromium.org>
Reviewed-by: default avatarMark Cogan <marq@chromium.org>
Commit-Queue: Chris Lu <thegreenfrog@chromium.org>
Cr-Commit-Position: refs/heads/master@{#825925}
parent 6f981d3d
......@@ -7,6 +7,7 @@
#include "base/ios/ios_util.h"
#include "base/ios/multi_window_buildflags.h"
#include "base/mac/foundation_util.h"
#include "base/metrics/user_metrics.h"
#import "ios/chrome/app/application_delegate/app_state.h"
#import "ios/chrome/app/application_delegate/browser_launcher.h"
#import "ios/chrome/app/application_delegate/memory_warning_helper.h"
......@@ -32,6 +33,12 @@
#error "This file requires ARC support."
#endif
namespace {
// The time delay after firstSceneWillEnterForeground: before checking for main
// intent signals.
const int kMainIntentCheckDelay = 1;
} // namespace
@interface MainApplicationDelegate () {
MainController* _mainController;
// Memory helper used to log the number of memory warnings received.
......@@ -279,6 +286,13 @@
- (void)lastSceneDidEnterBackground:(NSNotification*)notification {
DCHECK(IsSceneStartupSupported());
// Reset |startupHadExternalIntent| for all Scenes in case external intents
// were triggered while the application was in the foreground.
for (SceneState* scene in self.appState.connectedScenes) {
if (scene.startupHadExternalIntent) {
scene.startupHadExternalIntent = NO;
}
}
if (@available(iOS 13, *)) {
[_appState applicationDidEnterBackground:UIApplication.sharedApplication
memoryHelper:_memoryHelper];
......@@ -288,9 +302,36 @@
- (void)firstSceneWillEnterForeground:(NSNotification*)notification {
DCHECK(IsSceneStartupSupported());
if (@available(iOS 13, *)) {
[_appState applicationWillEnterForeground:UIApplication.sharedApplication
metricsMediator:_metricsMediator
memoryHelper:_memoryHelper];
__weak MainApplicationDelegate* weakSelf = self;
// Delay Main Intent check since signals for intents like spotlight actions
// are not guaranteed to occur before firstSceneWillEnterForeground.
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
static_cast<int64_t>(kMainIntentCheckDelay * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
MainApplicationDelegate* strongSelf = weakSelf;
if (!strongSelf) {
return;
}
BOOL appStartupFromExternalIntent = NO;
for (SceneState* scene in strongSelf.appState.connectedScenes) {
if (scene.startupHadExternalIntent) {
appStartupFromExternalIntent = YES;
scene.startupHadExternalIntent = NO;
}
}
if (!appStartupFromExternalIntent) {
base::RecordAction(
base::UserMetricsAction("IOSLaunchedBySearchInChromeIntent"));
}
[_appState
applicationWillEnterForeground:UIApplication.sharedApplication
metricsMediator:_metricsMediator
memoryHelper:_memoryHelper];
});
}
}
......
......@@ -511,6 +511,7 @@ const char kMultiWindowOpenInNewWindowHistogram[] =
- (void)performActionForShortcutItem:(UIApplicationShortcutItem*)shortcutItem
completionHandler:(void (^)(BOOL succeeded))completionHandler
API_AVAILABLE(ios(13)) {
self.sceneState.startupHadExternalIntent = YES;
[UserActivityHandler
performActionForShortcutItem:shortcutItem
completionHandler:completionHandler
......@@ -531,6 +532,7 @@ const char kMultiWindowOpenInNewWindowHistogram[] =
self.sceneState.presentingModalOverlay) {
sceneIsActive = NO;
}
self.sceneState.startupHadExternalIntent = YES;
[UserActivityHandler
continueUserActivity:userActivity
applicationIsActive:sceneIsActive
......
......@@ -64,6 +64,9 @@ NSString* const kOriginDetectedKey = @"OriginDetectedKey";
options:connectionOptions];
self.sceneState.activationLevel = SceneActivationLevelBackground;
self.sceneState.connectionOptions = connectionOptions;
if (connectionOptions.URLContexts || connectionOptions.shortcutItem) {
self.sceneState.startupHadExternalIntent = YES;
}
}
- (WindowActivityOrigin)originFromSession:(UISceneSession*)session
......@@ -126,6 +129,7 @@ NSString* const kOriginDetectedKey = @"OriginDetectedKey";
openURLContexts:(NSSet<UIOpenURLContext*>*)URLContexts
API_AVAILABLE(ios(13)) {
DCHECK(!self.sceneState.URLContextsToOpen);
self.sceneState.startupHadExternalIntent = YES;
self.sceneState.URLContextsToOpen = URLContexts;
}
......
......@@ -89,6 +89,10 @@ typedef NS_ENUM(NSUInteger, SceneActivationLevel) {
// When this is YES, the scene is showing the modal overlay.
@property(nonatomic, assign) BOOL presentingModalOverlay;
// When this is YES, the scene either resumed or started up in response to an
// external intent.
@property(nonatomic, assign) BOOL startupHadExternalIntent;
// URLs passed to |UIWindowSceneDelegate scene:openURLContexts:| that needs to
// be open next time the scene is activated.
// Setting the property to not nil will add the new URL contexts to the set.
......
......@@ -9271,6 +9271,15 @@ should be able to be added at any place in this file.
</description>
</action>
<action name="IOSOpenByMainIntent">
<owner>thegreenfrog@chromium.org</owner>
<owner>olivierrobin@chromium.org</owner>
<description>
User opened Chrome through a main intent, either by an icon open or an app
switch.
</description>
</action>
<action name="IOSPasswordsSettingsCloseWithSwipe">
<owner>djean@chromium.org</owner>
<owner>javierrobles@chromium.org</owner>
......
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