[go: nahoru, domu]

blob: 09d5ac567ac937e95b22099b8c68c6d7755db1f7 [file] [log] [blame]
// 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.
#import "ios/chrome/app/spotlight/actions_spotlight_manager.h"
#import <CoreSpotlight/CoreSpotlight.h>
#import "base/apple/foundation_util.h"
#import "base/metrics/histogram_macros.h"
#import "base/strings/sys_string_conversions.h"
#import "ios/chrome/app/app_startup_parameters.h"
#import "ios/chrome/app/spotlight/searchable_item_factory.h"
#import "ios/chrome/app/spotlight/spotlight_interface.h"
#import "ios/chrome/app/spotlight/spotlight_logger.h"
#import "ios/chrome/browser/ui/lens/lens_availability.h"
#import "ios/chrome/browser/ui/lens/lens_entrypoint.h"
#import "ios/chrome/common/app_group/app_group_constants.h"
#import "ios/chrome/grit/ios_strings.h"
#import "net/base/mac/url_conversions.h"
#import "ui/base/l10n/l10n_util.h"
#import "url/gurl.h"
namespace {
NSString* SpotlightActionFromString(NSString* query) {
NSString* domain =
[NSString stringWithFormat:@"%@.", spotlight::StringFromSpotlightDomain(
spotlight::DOMAIN_ACTIONS)];
DCHECK([query hasPrefix:domain]);
return
[query substringWithRange:NSMakeRange([domain length],
[query length] - [domain length])];
}
} // namespace
namespace spotlight {
// Constants for Spotlight action links.
const char kSpotlightActionNewTab[] = "OpenNewTab";
const char kSpotlightActionNewIncognitoTab[] = "OpenIncognitoTab";
const char kSpotlightActionVoiceSearch[] = "OpenVoiceSearch";
const char kSpotlightActionQRScanner[] = "OpenQRScanner";
const char kSpotlightActionSetDefaultBrowser[] = "SetDefaultBrowser";
const char kSpotlightActionLens[] = "OpenLensFromSpotlight";
// Enum is used to record the actions performed by the user.
enum {
// Recorded when a user pressed the New Tab spotlight action.
SPOTLIGHT_ACTION_NEW_TAB_PRESSED,
// Recorded when a user pressed the New Incognito Tab spotlight action.
SPOTLIGHT_ACTION_NEW_INCOGNITO_TAB_PRESSED,
// Recorded when a user pressed the Voice Search spotlight action.
SPOTLIGHT_ACTION_VOICE_SEARCH_PRESSED,
// Recorded when a user pressed the QR scanner spotlight action.
SPOTLIGHT_ACTION_QR_CODE_SCANNER_PRESSED,
// Recorded when a user pressed the Set Default Browser spotlight action.
SPOTLIGHT_ACTION_SET_DEFAULT_BROWSER_PRESSED,
// Recorded when a user pressed the Lens spotlight action.
SPOTLIGHT_ACTION_LENS_PRESSED,
// NOTE: Add new spotlight actions in sources only immediately above this
// line. Also, make sure the enum list for histogram `SpotlightActions` in
// histograms.xml is updated with any change in here.
SPOTLIGHT_ACTION_COUNT
};
// The histogram used to record user actions performed on the spotlight actions.
const char kSpotlightActionsHistogram[] = "IOS.Spotlight.Action";
BOOL SetStartupParametersForSpotlightAction(
NSString* query,
AppStartupParameters* startupParams) {
DCHECK(startupParams);
NSString* action = SpotlightActionFromString(query);
if ([action isEqualToString:base::SysUTF8ToNSString(
kSpotlightActionNewIncognitoTab)]) {
UMA_HISTOGRAM_ENUMERATION(kSpotlightActionsHistogram,
SPOTLIGHT_ACTION_NEW_INCOGNITO_TAB_PRESSED,
SPOTLIGHT_ACTION_COUNT);
[startupParams setApplicationMode:ApplicationModeForTabOpening::INCOGNITO];
} else if ([action isEqualToString:base::SysUTF8ToNSString(
kSpotlightActionVoiceSearch)]) {
UMA_HISTOGRAM_ENUMERATION(kSpotlightActionsHistogram,
SPOTLIGHT_ACTION_VOICE_SEARCH_PRESSED,
SPOTLIGHT_ACTION_COUNT);
[startupParams setApplicationMode:ApplicationModeForTabOpening::NORMAL];
[startupParams setPostOpeningAction:START_VOICE_SEARCH];
} else if ([action isEqualToString:base::SysUTF8ToNSString(
kSpotlightActionQRScanner)]) {
UMA_HISTOGRAM_ENUMERATION(kSpotlightActionsHistogram,
SPOTLIGHT_ACTION_QR_CODE_SCANNER_PRESSED,
SPOTLIGHT_ACTION_COUNT);
[startupParams setApplicationMode:ApplicationModeForTabOpening::NORMAL];
[startupParams setPostOpeningAction:START_QR_CODE_SCANNER];
} else if ([action isEqualToString:base::SysUTF8ToNSString(
kSpotlightActionNewTab)]) {
UMA_HISTOGRAM_ENUMERATION(kSpotlightActionsHistogram,
SPOTLIGHT_ACTION_NEW_TAB_PRESSED,
SPOTLIGHT_ACTION_COUNT);
[startupParams setApplicationMode:ApplicationModeForTabOpening::NORMAL];
} else if ([action isEqualToString:base::SysUTF8ToNSString(
kSpotlightActionSetDefaultBrowser)]) {
UMA_HISTOGRAM_ENUMERATION(kSpotlightActionsHistogram,
SPOTLIGHT_ACTION_SET_DEFAULT_BROWSER_PRESSED,
SPOTLIGHT_ACTION_COUNT);
[[UIApplication sharedApplication]
openURL:[NSURL
URLWithString:UIApplicationOpenSettingsURLString]
options:{}
completionHandler:nil];
} else if ([action isEqualToString:base::SysUTF8ToNSString(
kSpotlightActionLens)]) {
UMA_HISTOGRAM_ENUMERATION(kSpotlightActionsHistogram,
SPOTLIGHT_ACTION_LENS_PRESSED,
SPOTLIGHT_ACTION_COUNT);
[startupParams setApplicationMode:ApplicationModeForTabOpening::NORMAL];
[startupParams setPostOpeningAction:START_LENS_FROM_SPOTLIGHT];
} else {
return NO;
}
return YES;
}
} // namespace spotlight
@implementation ActionsSpotlightManager
+ (ActionsSpotlightManager*)actionsSpotlightManager {
return [[ActionsSpotlightManager alloc]
initWithSpotlightInterface:[SpotlightInterface defaultInterface]
searchableItemFactory:
[[SearchableItemFactory alloc]
initWithLargeIconService:nil
domain:spotlight::DOMAIN_ACTIONS
useTitleInIdentifiers:YES]];
}
#pragma mark public methods
- (instancetype)
initWithSpotlightInterface:(SpotlightInterface*)spotlightInterface
searchableItemFactory:(SearchableItemFactory*)searchableItemFactory {
self = [super init];
if (self) {
_spotlightInterface = spotlightInterface;
_searchableItemFactory = searchableItemFactory;
}
return self;
}
- (void)indexActionsWithIsGoogleDefaultSearchEngine:
(BOOL)isGoogleDefaultSearchEngine {
__weak ActionsSpotlightManager* weakSelf = self;
dispatch_after(
dispatch_time(DISPATCH_TIME_NOW, static_cast<int64_t>(1 * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
ActionsSpotlightManager* strongSelf = weakSelf;
[strongSelf clearAndAddSpotlightActionsWithIsGoogleDefaultSearchEngine:
isGoogleDefaultSearchEngine];
});
}
#pragma mark private methods
// Clears and re-inserts all Spotlight actions.
- (void)clearAndAddSpotlightActionsWithIsGoogleDefaultSearchEngine:
(BOOL)isGoogleDefaultSearchEngine {
__weak ActionsSpotlightManager* weakSelf = self;
[self.searchableItemFactory cancelItemsGeneration];
[self.spotlightInterface
deleteSearchableItemsWithDomainIdentifiers:@[
spotlight::StringFromSpotlightDomain(spotlight::DOMAIN_ACTIONS)
]
completionHandler:^(NSError* error) {
dispatch_after(
dispatch_time(DISPATCH_TIME_NOW,
static_cast<int64_t>(
1 * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
ActionsSpotlightManager* strongSelf =
weakSelf;
if (!strongSelf) {
return;
}
[strongSelf
reindexActionsToSpotlight:
isGoogleDefaultSearchEngine];
});
}];
}
- (void)reindexActionsToSpotlight:(BOOL)isGoogleDefaultSearchEngine {
NSString* voiceSearchTitle =
l10n_util::GetNSString(IDS_IOS_APPLICATION_SHORTCUT_VOICE_SEARCH_TITLE);
NSString* voiceSearchAction =
base::SysUTF8ToNSString(spotlight::kSpotlightActionVoiceSearch);
NSString* newTabTitle =
l10n_util::GetNSString(IDS_IOS_APPLICATION_SHORTCUT_NEWSEARCH_TITLE);
NSString* newTabAction =
base::SysUTF8ToNSString(spotlight::kSpotlightActionNewTab);
NSString* incognitoTitle = l10n_util::GetNSString(
IDS_IOS_APPLICATION_SHORTCUT_INCOGNITOSEARCH_TITLE);
NSString* incognitoAction =
base::SysUTF8ToNSString(spotlight::kSpotlightActionNewIncognitoTab);
NSString* qrScannerTitle =
l10n_util::GetNSString(IDS_IOS_APPLICATION_SHORTCUT_QR_SCANNER_TITLE);
NSString* qrScannerAction =
base::SysUTF8ToNSString(spotlight::kSpotlightActionQRScanner);
NSString* defaultBrowserTitle =
l10n_util::GetNSString(IDS_IOS_APPLICATION_SHORTCUT_SET_DEFAULT_BROWSER);
NSString* defaultBrowserAction =
base::SysUTF8ToNSString(spotlight::kSpotlightActionSetDefaultBrowser);
NSMutableArray<CSSearchableItem*>* spotlightItems = [NSMutableArray array];
[spotlightItems addObjectsFromArray:@[
[self itemForAction:voiceSearchAction title:voiceSearchTitle],
[self itemForAction:newTabAction title:newTabTitle],
[self itemForAction:incognitoAction title:incognitoTitle],
[self itemForAction:qrScannerAction title:qrScannerTitle],
[self itemForAction:defaultBrowserAction title:defaultBrowserTitle],
]];
const BOOL useLens =
lens_availability::CheckAndLogAvailabilityForLensEntryPoint(
LensEntrypoint::Spotlight, isGoogleDefaultSearchEngine);
if (useLens) {
NSString* lensTitle =
l10n_util::GetNSString(IDS_IOS_APPLICATION_SHORTCUT_LENS_TITLE);
NSString* lensAction =
base::SysUTF8ToNSString(spotlight::kSpotlightActionLens);
[spotlightItems addObject:[self itemForAction:lensAction title:lensTitle]];
}
[self.spotlightInterface indexSearchableItems:spotlightItems];
}
// Creates a new Spotlight entry with title `title` for the given `action`.
- (CSSearchableItem*)itemForAction:(NSString*)action title:(NSString*)title {
NSString* domainID =
spotlight::StringFromSpotlightDomain(spotlight::DOMAIN_ACTIONS);
NSString* itemID = [NSString stringWithFormat:@"%@.%@", domainID, action];
return [self.searchableItemFactory searchableItem:title
itemID:itemID
additionalKeywords:@[]];
}
- (void)shutdown {
[self.searchableItemFactory cancelItemsGeneration];
}
@end