| Index: ios/chrome/app/spotlight/actions_spotlight_manager.mm
|
| diff --git a/ios/chrome/app/spotlight/actions_spotlight_manager.mm b/ios/chrome/app/spotlight/actions_spotlight_manager.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..6b010f21afeb0f3e1c158e63bfb11685dc2743cd
|
| --- /dev/null
|
| +++ b/ios/chrome/app/spotlight/actions_spotlight_manager.mm
|
| @@ -0,0 +1,205 @@
|
| +// 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/ios/weak_nsobject.h"
|
| +#include "base/mac/foundation_util.h"
|
| +#include "base/metrics/histogram.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"
|
| +
|
| +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] autorelease];
|
| +}
|
| +
|
| +#pragma mark public methods
|
| +
|
| +- (void)indexActions {
|
| + base::WeakNSObject<ActionsSpotlightManager> weakSelf(self);
|
| + dispatch_after(
|
| + dispatch_time(DISPATCH_TIME_NOW, static_cast<int64_t>(1 * NSEC_PER_SEC)),
|
| + dispatch_get_main_queue(), ^{
|
| + base::scoped_nsobject<ActionsSpotlightManager> strongSelf(
|
| + [weakSelf retain]);
|
| + [strongSelf clearAndAddSpotlightActions];
|
| + });
|
| +}
|
| +
|
| +#pragma mark private methods
|
| +
|
| +- (void)clearAndAddSpotlightActions {
|
| + [self clearAllSpotlightItems:^(NSError* error) {
|
| + if (!experimental_flags::IsSpotlightActionsEnabled()) {
|
| + return;
|
| + }
|
| + base::WeakNSObject<ActionsSpotlightManager> weakSelf(self);
|
| + dispatch_after(
|
| + dispatch_time(DISPATCH_TIME_NOW,
|
| + static_cast<int64_t>(1 * NSEC_PER_SEC)),
|
| + dispatch_get_main_queue(), ^{
|
| + base::scoped_nsobject<ActionsSpotlightManager> strongSelf(
|
| + [weakSelf retain]);
|
| +
|
| + 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);
|
| +
|
| + NSMutableArray* spotlightItems = [NSMutableArray
|
| + arrayWithObjects:[strongSelf getItemForAction:voiceSearchAction
|
| + title:voiceSearchTitle],
|
| + [strongSelf getItemForAction:newTabAction
|
| + title:newTabTitle],
|
| + [strongSelf getItemForAction:incognitoAction
|
| + title:incognitoTitle],
|
| + nil];
|
| +
|
| + if (experimental_flags::IsQRCodeReaderEnabled()) {
|
| + NSString* qrScannerTitle = l10n_util::GetNSString(
|
| + IDS_IOS_APPLICATION_SHORTCUT_QR_SCANNER_TITLE);
|
| + NSString* qrScannerAction =
|
| + base::SysUTF8ToNSString(spotlight::kSpotlightActionQRScanner);
|
| +
|
| + [spotlightItems
|
| + addObject:[strongSelf getItemForAction:qrScannerAction
|
| + title:qrScannerTitle]];
|
| + }
|
| +
|
| + [[CSSearchableIndex defaultSearchableIndex]
|
| + indexSearchableItems:spotlightItems
|
| + completionHandler:nil];
|
| + });
|
| + }];
|
| +}
|
| +
|
| +- (CSSearchableItem*)getItemForAction:(NSString*)action title:(NSString*)title {
|
| + base::scoped_nsobject<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
|
|
|