blob: 1d453c5891b127622c6afeb1a2cad31d17322bda [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// 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>
#include "base/mac/foundation_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/sys_string_conversions.h"
#include "ios/chrome/browser/app_startup_parameters.h"
#include "ios/chrome/browser/experimental_flags.h"
#include "ios/chrome/common/app_group/app_group_constants.h"
#include "ios/chrome/grit/ios_strings.h"
#include "net/base/mac/url_conversions.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
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";
// 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,
// 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 setLaunchInIncognito:YES];
} else if ([action isEqualToString:base::SysUTF8ToNSString(
kSpotlightActionVoiceSearch)]) {
UMA_HISTOGRAM_ENUMERATION(kSpotlightActionsHistogram,
SPOTLIGHT_ACTION_VOICE_SEARCH_PRESSED,
SPOTLIGHT_ACTION_COUNT);
[startupParams setLaunchVoiceSearch:YES];
} else if ([action isEqualToString:base::SysUTF8ToNSString(
kSpotlightActionQRScanner)]) {
UMA_HISTOGRAM_ENUMERATION(kSpotlightActionsHistogram,
SPOTLIGHT_ACTION_QR_CODE_SCANNER_PRESSED,
SPOTLIGHT_ACTION_COUNT);
[startupParams setLaunchQRScanner:YES];
} else if ([action isEqualToString:base::SysUTF8ToNSString(
kSpotlightActionNewTab)]) {
UMA_HISTOGRAM_ENUMERATION(kSpotlightActionsHistogram,
SPOTLIGHT_ACTION_NEW_TAB_PRESSED,
SPOTLIGHT_ACTION_COUNT);
} else {
return NO;
}
return YES;
}
} // namespace spotlight
@interface ActionsSpotlightManager ()
// Creates a new Spotlight entry with title |title| for the given |action|.
- (CSSearchableItem*)getItemForAction:(NSString*)action title:(NSString*)title;
// Clears and re-inserts all Spotlight actions.
- (void)clearAndAddSpotlightActions;
@end
@implementation ActionsSpotlightManager
+ (ActionsSpotlightManager*)actionsSpotlightManager {
return [[ActionsSpotlightManager alloc]
initWithLargeIconService:nil
domain:spotlight::DOMAIN_ACTIONS];
}
#pragma mark public methods
- (void)indexActions {
__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 clearAndAddSpotlightActions];
});
}
#pragma mark private methods
- (void)clearAndAddSpotlightActions {
[self clearAllSpotlightItems:^(NSError* error) {
if (!experimental_flags::IsSpotlightActionsEnabled()) {
return;
}
__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;
if (!strongSelf) {
return;
}
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_NEWTAB_TITLE);
NSString* newTabAction =
base::SysUTF8ToNSString(spotlight::kSpotlightActionNewTab);
NSString* incognitoTitle = l10n_util::GetNSString(
IDS_IOS_APPLICATION_SHORTCUT_NEWINCOGNITOTAB_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);
NSArray* spotlightItems = @[
[strongSelf getItemForAction:voiceSearchAction
title:voiceSearchTitle],
[strongSelf getItemForAction:newTabAction title:newTabTitle],
[strongSelf getItemForAction:incognitoAction title:incognitoTitle],
[strongSelf getItemForAction:qrScannerAction title:qrScannerTitle],
];
[[CSSearchableIndex defaultSearchableIndex]
indexSearchableItems:spotlightItems
completionHandler:nil];
});
}];
}
- (CSSearchableItem*)getItemForAction:(NSString*)action title:(NSString*)title {
CSSearchableItemAttributeSet* attributeSet =
[[CSSearchableItemAttributeSet alloc]
initWithItemContentType:spotlight::StringFromSpotlightDomain(
spotlight::DOMAIN_ACTIONS)];
[attributeSet setTitle:title];
[attributeSet setDisplayName:title];
NSString* domainID =
spotlight::StringFromSpotlightDomain(spotlight::DOMAIN_ACTIONS);
NSString* itemID = [NSString stringWithFormat:@"%@.%@", domainID, action];
return [self spotlightItemWithItemID:itemID attributeSet:attributeSet];
}
@end