Index: ios/chrome/app/application_delegate/user_activity_handler_unittest.mm |
diff --git a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..da1fc34bce9c28d69ba6e7b2c29166c8940f5ebb |
--- /dev/null |
+++ b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm |
@@ -0,0 +1,625 @@ |
+// 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. |
+ |
+#include "ios/chrome/app/application_delegate/user_activity_handler.h" |
+ |
+#include <memory> |
+ |
+#import <CoreSpotlight/CoreSpotlight.h> |
+ |
+#include "base/ios/ios_util.h" |
+#include "base/mac/scoped_block.h" |
+#include "base/mac/scoped_nsobject.h" |
+#include "base/strings/sys_string_conversions.h" |
+#include "base/test/scoped_command_line.h" |
+#include "components/handoff/handoff_utility.h" |
+#include "ios/chrome/app/application_delegate/fake_startup_information.h" |
+#include "ios/chrome/app/application_delegate/mock_tab_opener.h" |
+#include "ios/chrome/app/application_delegate/startup_information.h" |
+#include "ios/chrome/app/application_delegate/tab_opening.h" |
+#include "ios/chrome/app/application_mode.h" |
+#include "ios/chrome/app/main_controller.h" |
+#include "ios/chrome/app/spotlight/actions_spotlight_manager.h" |
+#import "ios/chrome/app/spotlight/spotlight_util.h" |
+#include "ios/chrome/browser/app_startup_parameters.h" |
+#include "ios/chrome/browser/chrome_switches.h" |
+#include "ios/chrome/browser/chrome_url_constants.h" |
+#import "ios/chrome/browser/tabs/tab.h" |
+#import "ios/chrome/browser/tabs/tab_model.h" |
+#import "ios/chrome/browser/tabs/tab_model_observer.h" |
+#import "ios/chrome/browser/u2f/u2f_controller.h" |
+#import "ios/chrome/test/base/scoped_block_swizzler.h" |
+#import "net/base/mac/url_conversions.h" |
+#include "net/test/gtest_util.h" |
+#include "testing/platform_test.h" |
+#import "third_party/ocmock/OCMock/OCMock.h" |
+#include "third_party/ocmock/gtest_support.h" |
+#include "ui/base/page_transition_types.h" |
+#include "url/gurl.h" |
+ |
+#pragma mark - Tab Mock |
+ |
+// Tab mock for using in UserActivity tests. |
+@interface UserActivityHandlerTabMock : NSObject |
+ |
+@property(nonatomic, readonly) GURL url; |
+@property(nonatomic, readonly) NSString* tabId; |
+ |
+@end |
+ |
+@implementation UserActivityHandlerTabMock |
+@synthesize url = _url; |
+@synthesize tabId = _tabId; |
+ |
+- (void)evaluateU2FResultFromURL:(const GURL&)url { |
+ _url = url; |
+} |
+ |
+@end |
+ |
+#pragma mark - TabModel Mock |
+ |
+// TabModel mock for using in UserActivity tests. |
+@interface UserActivityHandlerTabModelMock : NSObject<NSFastEnumeration> { |
+ @private |
+ base::scoped_nsobject<NSMutableArray> _tabs; |
+} |
+ |
+- (void)addTab:(Tab*)tab; |
+- (void)addObserver:(id<TabModelObserver>)observer; |
+- (void)removeObserver:(id<TabModelObserver>)observer; |
+ |
+@end |
+ |
+@implementation UserActivityHandlerTabModelMock |
+ |
+- (instancetype)init { |
+ if ((self = [super init])) { |
+ _tabs.reset([[NSMutableArray alloc] init]); |
+ } |
+ return self; |
+} |
+ |
+- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState*)state |
+ objects:(id*)stackbuf |
+ count:(NSUInteger)len { |
+ return [_tabs countByEnumeratingWithState:state objects:stackbuf count:len]; |
+} |
+ |
+- (void)addTab:(Tab*)tab { |
+ [_tabs addObject:tab]; |
+} |
+ |
+- (void)addObserver:(id<TabModelObserver>)observer { |
+ // Empty. |
+} |
+ |
+- (void)removeObserver:(id<TabModelObserver>)observer { |
+ // Empty. |
+} |
+ |
+@end |
+ |
+#pragma mark - Test class. |
+ |
+// A block that takes as arguments the caller and the arguments from |
+// UserActivityHandler +handleStartupParameters and returns nothing. |
+typedef void (^startupParameterBlock)(id, |
+ id<TabOpening>, |
+ id<StartupInformation>, |
+ id<BrowserViewInformation>); |
+ |
+// A block that takes a BOOL argument and returns nothing. |
+typedef void (^conditionBlock)(BOOL); |
+ |
+class UserActivityHandlerTest : public PlatformTest { |
+ protected: |
+ void swizzleHandleStartupParameters() { |
+ handle_startup_parameters_has_been_called_ = NO; |
+ swizzle_block_.reset([^(id self) { |
+ handle_startup_parameters_has_been_called_ = YES; |
+ } copy]); |
+ user_activity_handler_swizzler_.reset(new ScopedBlockSwizzler( |
+ [UserActivityHandler class], |
+ @selector(handleStartupParametersWithTabOpener: |
+ startupInformation: |
+ browserViewInformation:), |
+ swizzle_block_)); |
+ } |
+ |
+ BOOL getHandleStartupParametersHasBeenCalled() { |
+ return handle_startup_parameters_has_been_called_; |
+ } |
+ |
+ void resetHandleStartupParametersHasBeenCalled() { |
+ handle_startup_parameters_has_been_called_ = NO; |
+ } |
+ |
+ conditionBlock getCompletionHandler() { |
+ if (!completion_block_) { |
+ block_executed_ = NO; |
+ completion_block_.reset([^(BOOL arg) { |
+ block_executed_ = YES; |
+ block_argument_ = arg; |
+ } copy]); |
+ } |
+ return completion_block_; |
+ } |
+ |
+ BOOL completionHandlerExecuted() { return block_executed_; } |
+ |
+ BOOL completionHandlerArgument() { return block_argument_; } |
+ |
+ private: |
+ __block BOOL block_executed_; |
+ __block BOOL block_argument_; |
+ std::unique_ptr<ScopedBlockSwizzler> user_activity_handler_swizzler_; |
+ base::mac::ScopedBlock<startupParameterBlock> swizzle_block_; |
+ base::mac::ScopedBlock<conditionBlock> completion_block_; |
+ __block BOOL handle_startup_parameters_has_been_called_; |
+}; |
+ |
+#pragma mark - Tests. |
+ |
+// Tests that Chrome notifies the user if we are passing a correct |
+// userActivityType. |
+TEST(UserActivityHandlerNoFixtureTest, |
+ willContinueUserActivityCorrectActivity) { |
+ EXPECT_TRUE([UserActivityHandler |
+ willContinueUserActivityWithType:handoff::kChromeHandoffActivityType]); |
+ |
+ if (spotlight::IsSpotlightAvailable()) { |
+ EXPECT_TRUE([UserActivityHandler |
+ willContinueUserActivityWithType:CSSearchableItemActionType]); |
+ } |
+} |
+ |
+// Tests that Chrome does not notifies the user if we are passing an incorrect |
+// userActivityType. |
+TEST(UserActivityHandlerNoFixtureTest, |
+ willContinueUserActivityIncorrectActivity) { |
+ EXPECT_FALSE([UserActivityHandler |
+ willContinueUserActivityWithType:[handoff::kChromeHandoffActivityType |
+ stringByAppendingString:@"test"]]); |
+ |
+ EXPECT_FALSE([UserActivityHandler |
+ willContinueUserActivityWithType:@"it.does.not.work"]); |
+ |
+ EXPECT_FALSE([UserActivityHandler willContinueUserActivityWithType:@""]); |
+ |
+ EXPECT_FALSE([UserActivityHandler willContinueUserActivityWithType:nil]); |
+} |
+ |
+// Tests that Chrome does not continue the activity is the activity type is |
+// random. |
+TEST(UserActivityHandlerNoFixtureTest, continueUserActivityFromGarbage) { |
+ // Setup. |
+ NSString* handoffWithSuffix = |
+ [handoff::kChromeHandoffActivityType stringByAppendingString:@"test"]; |
+ NSString* handoffWithPrefix = |
+ [@"test" stringByAppendingString:handoff::kChromeHandoffActivityType]; |
+ NSArray* userActivityTypes = @[ |
+ @"thisIsGarbage", @"it.does.not.work", handoffWithSuffix, handoffWithPrefix |
+ ]; |
+ for (NSString* userActivityType in userActivityTypes) { |
+ base::scoped_nsobject<NSUserActivity> userActivity( |
+ [[NSUserActivity alloc] initWithActivityType:userActivityType]); |
+ [userActivity setWebpageURL:[NSURL URLWithString:@"http://www.google.com"]]; |
+ |
+ // The test will fail is a method of those objects is called. |
+ id tabOpenerMock = [OCMockObject mockForProtocol:@protocol(TabOpening)]; |
+ id startupInformationMock = |
+ [OCMockObject mockForProtocol:@protocol(StartupInformation)]; |
+ |
+ // Action. |
+ BOOL result = |
+ [UserActivityHandler continueUserActivity:userActivity |
+ applicationIsActive:NO |
+ tabOpener:tabOpenerMock |
+ startupInformation:startupInformationMock]; |
+ |
+ // Tests. |
+ EXPECT_FALSE(result); |
+ } |
+} |
+ |
+// Tests that Chrome does not continue the activity if the webpage url is not |
+// set. |
+TEST(UserActivityHandlerNoFixtureTest, continueUserActivityNoWebpage) { |
+ // Setup. |
+ base::scoped_nsobject<NSUserActivity> userActivity([[NSUserActivity alloc] |
+ initWithActivityType:handoff::kChromeHandoffActivityType]); |
+ |
+ // The test will fail is a method of those objects is called. |
+ id tabOpenerMock = [OCMockObject mockForProtocol:@protocol(TabOpening)]; |
+ id startupInformationMock = |
+ [OCMockObject mockForProtocol:@protocol(StartupInformation)]; |
+ |
+ // Action. |
+ BOOL result = |
+ [UserActivityHandler continueUserActivity:userActivity |
+ applicationIsActive:NO |
+ tabOpener:tabOpenerMock |
+ startupInformation:startupInformationMock]; |
+ |
+ // Tests. |
+ EXPECT_FALSE(result); |
+} |
+ |
+// Tests that Chrome does not continue the activity if the activity is a |
+// Spotlight action of an unknown type. |
+TEST(UserActivityHandlerNoFixtureTest, |
+ continueUserActivitySpotlightActionFromGarbage) { |
+ // Only test Spotlight if it is enabled and available on the device. |
+ if (!spotlight::IsSpotlightAvailable()) { |
+ return; |
+ } |
+ // Setup. |
+ base::scoped_nsobject<NSUserActivity> userActivity( |
+ [[NSUserActivity alloc] initWithActivityType:CSSearchableItemActionType]); |
+ NSString* invalidAction = |
+ [NSString stringWithFormat:@"%@.invalidAction", |
+ spotlight::StringFromSpotlightDomain( |
+ spotlight::DOMAIN_ACTIONS)]; |
+ NSDictionary* userInfo = |
+ @{CSSearchableItemActivityIdentifier : invalidAction}; |
+ [userActivity addUserInfoEntriesFromDictionary:userInfo]; |
+ |
+ // Enable the SpotlightActions experiment. |
+ base::test::ScopedCommandLine scoped_command_line; |
+ scoped_command_line.GetProcessCommandLine()->AppendSwitch( |
+ switches::kEnableSpotlightActions); |
+ |
+ id tabOpenerMock = [OCMockObject mockForProtocol:@protocol(TabOpening)]; |
+ id startupInformationMock = |
+ [OCMockObject mockForProtocol:@protocol(StartupInformation)]; |
+ |
+ // Action. |
+ BOOL result = |
+ [UserActivityHandler continueUserActivity:userActivity |
+ applicationIsActive:NO |
+ tabOpener:tabOpenerMock |
+ startupInformation:startupInformationMock]; |
+ |
+ // Tests. |
+ EXPECT_FALSE(result); |
+} |
+ |
+// Tests that Chrome continues the activity if the application is in background |
+// by saving the url to startupParameters. |
+TEST(UserActivityHandlerNoFixtureTest, continueUserActivityBackground) { |
+ // Setup. |
+ base::scoped_nsobject<NSUserActivity> userActivity([[NSUserActivity alloc] |
+ initWithActivityType:handoff::kChromeHandoffActivityType]); |
+ NSURL* nsurl = [NSURL URLWithString:@"http://www.google.com"]; |
+ [userActivity setWebpageURL:nsurl]; |
+ |
+ id startupInformationMock = |
+ [OCMockObject niceMockForProtocol:@protocol(StartupInformation)]; |
+ [[startupInformationMock expect] |
+ setStartupParameters:[OCMArg checkWithBlock:^BOOL(id value) { |
+ EXPECT_TRUE([value isKindOfClass:[AppStartupParameters class]]); |
+ |
+ AppStartupParameters* startupParameters = (AppStartupParameters*)value; |
+ const GURL calledURL = startupParameters.externalURL; |
+ return calledURL == net::GURLWithNSURL(nsurl); |
+ }]]; |
+ |
+ // The test will fail is a method of this object is called. |
+ id tabOpenerMock = [OCMockObject mockForProtocol:@protocol(TabOpening)]; |
+ |
+ // Action. |
+ BOOL result = |
+ [UserActivityHandler continueUserActivity:userActivity |
+ applicationIsActive:NO |
+ tabOpener:tabOpenerMock |
+ startupInformation:startupInformationMock]; |
+ |
+ // Test. |
+ EXPECT_OCMOCK_VERIFY(startupInformationMock); |
+ EXPECT_TRUE(result); |
+} |
+ |
+// Tests that Chrome continues the activity if the application is in foreground |
+// by opening a new tab. |
+TEST(UserActivityHandlerNoFixtureTest, continueUserActivityForeground) { |
+ // Setup. |
+ base::scoped_nsobject<NSUserActivity> userActivity([[NSUserActivity alloc] |
+ initWithActivityType:handoff::kChromeHandoffActivityType]); |
+ NSURL* nsurl = [NSURL URLWithString:@"http://www.google.com"]; |
+ [userActivity setWebpageURL:nsurl]; |
+ |
+ base::scoped_nsobject<MockTabOpener> tabOpener([[MockTabOpener alloc] init]); |
+ |
+ id startupInformationMock = |
+ [OCMockObject mockForProtocol:@protocol(StartupInformation)]; |
+ [[[startupInformationMock stub] andReturnValue:@NO] isPresentingFirstRunUI]; |
+ |
+ base::scoped_nsobject<AppStartupParameters> startupParams( |
+ [[AppStartupParameters alloc] |
+ initWithExternalURL:(GURL("http://www.google.com"))]); |
+ [[[startupInformationMock stub] andReturn:startupParams] startupParameters]; |
+ |
+ // Action. |
+ BOOL result = |
+ [UserActivityHandler continueUserActivity:userActivity |
+ applicationIsActive:YES |
+ tabOpener:tabOpener |
+ startupInformation:startupInformationMock]; |
+ |
+ // Test. |
+ EXPECT_EQ(net::GURLWithNSURL(nsurl), [tabOpener url]); |
+ EXPECT_TRUE(result); |
+} |
+ |
+// Tests that a new tab is created when application is started via Universal |
+// Link. |
+TEST_F(UserActivityHandlerTest, continueUserActivityBrowsingWeb) { |
+ base::scoped_nsobject<NSUserActivity> userActivity([[NSUserActivity alloc] |
+ initWithActivityType:NSUserActivityTypeBrowsingWeb]); |
+ // This URL is passed to application by iOS but is not used in this part |
+ // of application logic. |
+ NSURL* nsurl = [NSURL URLWithString:@"http://goo.gl/foo/bar"]; |
+ [userActivity setWebpageURL:nsurl]; |
+ |
+ base::scoped_nsobject<MockTabOpener> tabOpener([[MockTabOpener alloc] init]); |
+ |
+ // Use an object to capture the startup paramters set by UserActivityHandler. |
+ base::scoped_nsobject<FakeStartupInformation> fakeStartupInformation( |
+ [[FakeStartupInformation alloc] init]); |
+ [fakeStartupInformation setIsPresentingFirstRunUI:NO]; |
+ |
+ BOOL result = |
+ [UserActivityHandler continueUserActivity:userActivity |
+ applicationIsActive:YES |
+ tabOpener:tabOpener |
+ startupInformation:fakeStartupInformation]; |
+ |
+ GURL newTabURL(kChromeUINewTabURL); |
+ EXPECT_EQ(newTabURL, [tabOpener url]); |
+ // AppStartupParameters default to opening pages in non-Incognito mode. |
+ EXPECT_EQ(ApplicationMode::NORMAL, [tabOpener applicationMode]); |
+ EXPECT_TRUE(result); |
+ // Verifies that a new tab is being requested. |
+ EXPECT_EQ(newTabURL, |
+ [[fakeStartupInformation startupParameters] externalURL]); |
+} |
+ |
+// Tests that continueUserActivity sets startupParameters accordingly to the |
+// Spotlight action used. |
+TEST_F(UserActivityHandlerTest, continueUserActivityShortcutActions) { |
+ // Only test Spotlight if it is enabled and available on the device. |
+ if (!spotlight::IsSpotlightAvailable()) { |
+ return; |
+ } |
+ // Setup. |
+ GURL gurlNewTab(kChromeUINewTabURL); |
+ base::scoped_nsobject<FakeStartupInformation> fakeStartupInformation( |
+ [[FakeStartupInformation alloc] init]); |
+ |
+ NSArray* parametersToTest = @[ |
+ @[ |
+ base::SysUTF8ToNSString(spotlight::kSpotlightActionNewTab), @NO, @NO, @NO |
+ ], |
+ @[ |
+ base::SysUTF8ToNSString(spotlight::kSpotlightActionNewIncognitoTab), @YES, |
+ @NO, @NO |
+ ], |
+ @[ |
+ base::SysUTF8ToNSString(spotlight::kSpotlightActionVoiceSearch), @NO, |
+ @YES, @NO |
+ ], |
+ @[ |
+ base::SysUTF8ToNSString(spotlight::kSpotlightActionQRScanner), @NO, @NO, |
+ @YES |
+ ] |
+ ]; |
+ |
+ // Enable the QR Scanner and Spotlight Actions experiments. |
+ base::test::ScopedCommandLine scoped_command_line; |
+ scoped_command_line.GetProcessCommandLine()->AppendSwitch( |
+ switches::kEnableQRScanner); |
+ scoped_command_line.GetProcessCommandLine()->AppendSwitch( |
+ switches::kEnableSpotlightActions); |
+ |
+ for (id parameters in parametersToTest) { |
+ base::scoped_nsobject<NSUserActivity> userActivity([[NSUserActivity alloc] |
+ initWithActivityType:CSSearchableItemActionType]); |
+ NSString* action = [NSString |
+ stringWithFormat:@"%@.%@", spotlight::StringFromSpotlightDomain( |
+ spotlight::DOMAIN_ACTIONS), |
+ parameters[0]]; |
+ NSDictionary* userInfo = @{CSSearchableItemActivityIdentifier : action}; |
+ [userActivity addUserInfoEntriesFromDictionary:userInfo]; |
+ |
+ id tabOpenerMock = [OCMockObject mockForProtocol:@protocol(TabOpening)]; |
+ |
+ // Action. |
+ BOOL result = |
+ [UserActivityHandler continueUserActivity:userActivity |
+ applicationIsActive:NO |
+ tabOpener:tabOpenerMock |
+ startupInformation:fakeStartupInformation]; |
+ |
+ // Tests. |
+ EXPECT_TRUE(result); |
+ EXPECT_EQ(gurlNewTab, |
+ [fakeStartupInformation startupParameters].externalURL); |
+ EXPECT_EQ([parameters[1] boolValue], |
+ [fakeStartupInformation startupParameters].launchInIncognito); |
+ EXPECT_EQ([parameters[2] boolValue], |
+ [fakeStartupInformation startupParameters].launchVoiceSearch); |
+ EXPECT_EQ([parameters[3] boolValue], |
+ [fakeStartupInformation startupParameters].launchQRScanner); |
+ } |
+} |
+ |
+// Tests that handleStartupParameters with a non-U2F url opens a new tab. |
+TEST(UserActivityHandlerNoFixtureTest, handleStartupParamsNonU2F) { |
+ // Setup. |
+ GURL gurl("http://www.google.com"); |
+ |
+ base::scoped_nsobject<AppStartupParameters> startupParams( |
+ [[AppStartupParameters alloc] initWithExternalURL:gurl]); |
+ [startupParams setLaunchInIncognito:YES]; |
+ |
+ id startupInformationMock = |
+ [OCMockObject mockForProtocol:@protocol(StartupInformation)]; |
+ [[[startupInformationMock stub] andReturnValue:@NO] isPresentingFirstRunUI]; |
+ [[[startupInformationMock stub] andReturn:startupParams] startupParameters]; |
+ [[startupInformationMock expect] setStartupParameters:nil]; |
+ |
+ base::scoped_nsobject<MockTabOpener> tabOpener([[MockTabOpener alloc] init]); |
+ |
+ // The test will fail is a method of this object is called. |
+ id browserViewMock = |
+ [OCMockObject mockForProtocol:@protocol(BrowserViewInformation)]; |
+ |
+ // Action. |
+ [UserActivityHandler |
+ handleStartupParametersWithTabOpener:tabOpener |
+ startupInformation:startupInformationMock |
+ browserViewInformation:browserViewMock]; |
+ [tabOpener completionBlock](); |
+ |
+ // Tests. |
+ EXPECT_OCMOCK_VERIFY(startupInformationMock); |
+ EXPECT_EQ(gurl, [tabOpener url]); |
+ EXPECT_EQ(ApplicationMode::INCOGNITO, [tabOpener applicationMode]); |
+} |
+ |
+// Tests that handleStartupParameters with a U2F url opens in the correct tab. |
+TEST(UserActivityHandlerNoFixtureTest, handleStartupParamsU2F) { |
+ // Setup. |
+ GURL gurl("chromium://u2f-callback?isU2F=1&tabID=B05B1860"); |
+ NSString* tabID = [U2FController tabIDFromResponseURL:gurl]; |
+ |
+ base::scoped_nsobject<AppStartupParameters> startupParams( |
+ [[AppStartupParameters alloc] initWithExternalURL:gurl]); |
+ [startupParams setLaunchInIncognito:YES]; |
+ |
+ base::scoped_nsobject<UserActivityHandlerTabMock> tabMock( |
+ [[UserActivityHandlerTabMock alloc] init]); |
+ id tabOCMock = [OCMockObject partialMockForObject:tabMock]; |
+ [[[tabOCMock stub] andReturn:tabID] tabId]; |
+ |
+ base::scoped_nsobject<UserActivityHandlerTabModelMock> tabModel( |
+ [[UserActivityHandlerTabModelMock alloc] init]); |
+ [tabModel addTab:(Tab*)tabMock.get()]; |
+ |
+ id startupInformationMock = |
+ [OCMockObject mockForProtocol:@protocol(StartupInformation)]; |
+ [[[startupInformationMock stub] andReturnValue:@NO] isPresentingFirstRunUI]; |
+ [[[startupInformationMock stub] andReturn:startupParams] startupParameters]; |
+ [[startupInformationMock expect] setStartupParameters:nil]; |
+ |
+ id browserViewInformationMock = |
+ [OCMockObject mockForProtocol:@protocol(BrowserViewInformation)]; |
+ [[[browserViewInformationMock stub] andReturn:(TabModel*)tabModel.get()] |
+ mainTabModel]; |
+ [[[browserViewInformationMock stub] andReturn:(TabModel*)tabModel.get()] |
+ otrTabModel]; |
+ |
+ base::scoped_nsobject<MockTabOpener> tabOpener([[MockTabOpener alloc] init]); |
+ |
+ // Action. |
+ [UserActivityHandler |
+ handleStartupParametersWithTabOpener:tabOpener |
+ startupInformation:startupInformationMock |
+ browserViewInformation:browserViewInformationMock]; |
+ |
+ // Tests. |
+ EXPECT_OCMOCK_VERIFY(startupInformationMock); |
+ EXPECT_EQ(gurl, [tabMock url]); |
+} |
+ |
+// Tests that performActionForShortcutItem set startupParameters accordingly to |
+// the shortcut used |
+TEST_F(UserActivityHandlerTest, performActionForShortcutItemWithRealShortcut) { |
+ // Setup. |
+ GURL gurlNewTab("chrome://newtab/"); |
+ |
+ base::scoped_nsobject<FakeStartupInformation> fakeStartupInformation( |
+ [[FakeStartupInformation alloc] init]); |
+ [fakeStartupInformation setIsPresentingFirstRunUI:NO]; |
+ |
+ NSArray* parametersToTest = @[ |
+ @[ @"OpenNewTab", @NO, @NO, @NO ], @[ @"OpenIncognitoTab", @YES, @NO, @NO ], |
+ @[ @"OpenVoiceSearch", @NO, @YES, @NO ], |
+ @[ @"OpenQRScanner", @NO, @NO, @YES ] |
+ ]; |
+ |
+ // Enable the QR Scanner experiment. |
+ base::test::ScopedCommandLine scoped_command_line; |
+ scoped_command_line.GetProcessCommandLine()->AppendSwitch( |
+ switches::kEnableQRScanner); |
+ |
+ swizzleHandleStartupParameters(); |
+ |
+ for (id parameters in parametersToTest) { |
+ base::scoped_nsobject<UIApplicationShortcutItem> shortcut( |
+ [[UIApplicationShortcutItem alloc] initWithType:parameters[0] |
+ localizedTitle:parameters[0]]); |
+ |
+ resetHandleStartupParametersHasBeenCalled(); |
+ |
+ // The test will fail is a method of those objects is called. |
+ id tabOpenerMock = [OCMockObject mockForProtocol:@protocol(TabOpening)]; |
+ id browserViewInformationMock = |
+ [OCMockObject mockForProtocol:@protocol(BrowserViewInformation)]; |
+ |
+ // Action. |
+ [UserActivityHandler |
+ performActionForShortcutItem:shortcut |
+ completionHandler:getCompletionHandler() |
+ tabOpener:tabOpenerMock |
+ startupInformation:fakeStartupInformation |
+ browserViewInformation:browserViewInformationMock]; |
+ |
+ // Tests. |
+ EXPECT_EQ(gurlNewTab, |
+ [fakeStartupInformation startupParameters].externalURL); |
+ EXPECT_EQ([[parameters objectAtIndex:1] boolValue], |
+ [fakeStartupInformation startupParameters].launchInIncognito); |
+ EXPECT_EQ([[parameters objectAtIndex:2] boolValue], |
+ [fakeStartupInformation startupParameters].launchVoiceSearch); |
+ EXPECT_EQ([[parameters objectAtIndex:3] boolValue], |
+ [fakeStartupInformation startupParameters].launchQRScanner); |
+ EXPECT_TRUE(completionHandlerExecuted()); |
+ EXPECT_TRUE(completionHandlerArgument()); |
+ EXPECT_TRUE(getHandleStartupParametersHasBeenCalled()); |
+ } |
+} |
+ |
+// Tests that performActionForShortcutItem just executes the completionHandler |
+// with NO if the firstRunUI is present. |
+TEST_F(UserActivityHandlerTest, performActionForShortcutItemWithFirstRunUI) { |
+ // Setup. |
+ id startupInformationMock = |
+ [OCMockObject mockForProtocol:@protocol(StartupInformation)]; |
+ [[[startupInformationMock stub] andReturnValue:@YES] isPresentingFirstRunUI]; |
+ |
+ base::scoped_nsobject<UIApplicationShortcutItem> shortcut( |
+ [[UIApplicationShortcutItem alloc] initWithType:@"OpenNewTab" |
+ localizedTitle:@""]); |
+ |
+ swizzleHandleStartupParameters(); |
+ |
+ // The test will fail is a method of those objects is called. |
+ id tabOpenerMock = [OCMockObject mockForProtocol:@protocol(TabOpening)]; |
+ id browserViewInformationMock = |
+ [OCMockObject mockForProtocol:@protocol(BrowserViewInformation)]; |
+ |
+ // Action. |
+ [UserActivityHandler performActionForShortcutItem:shortcut |
+ completionHandler:getCompletionHandler() |
+ tabOpener:tabOpenerMock |
+ startupInformation:startupInformationMock |
+ browserViewInformation:browserViewInformationMock]; |
+ |
+ // Tests. |
+ EXPECT_TRUE(completionHandlerExecuted()); |
+ EXPECT_FALSE(completionHandlerArgument()); |
+ EXPECT_FALSE(getHandleStartupParametersHasBeenCalled()); |
+} |