Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "ios/chrome/browser/ui/activity_services/activity_service_controller.h" | 5 #import "ios/chrome/browser/ui/activity_services/activity_service_controller.h" |
| 6 | 6 |
| 7 #import <MobileCoreServices/MobileCoreServices.h> | 7 #import <MobileCoreServices/MobileCoreServices.h> |
| 8 | 8 |
| 9 #include "base/mac/scoped_nsobject.h" | |
| 10 #import "base/test/ios/wait_util.h" | 9 #import "base/test/ios/wait_util.h" |
| 11 #include "components/reading_list/core/reading_list_switches.h" | 10 #include "components/reading_list/core/reading_list_switches.h" |
| 12 #import "ios/chrome/browser/ui/activity_services/activity_type_util.h" | 11 #import "ios/chrome/browser/ui/activity_services/activity_type_util.h" |
| 13 #import "ios/chrome/browser/ui/activity_services/appex_constants.h" | 12 #import "ios/chrome/browser/ui/activity_services/appex_constants.h" |
| 14 #import "ios/chrome/browser/ui/activity_services/chrome_activity_item_source.h" | 13 #import "ios/chrome/browser/ui/activity_services/chrome_activity_item_source.h" |
| 15 #import "ios/chrome/browser/ui/activity_services/print_activity.h" | 14 #import "ios/chrome/browser/ui/activity_services/print_activity.h" |
| 16 #import "ios/chrome/browser/ui/activity_services/share_to_data.h" | 15 #import "ios/chrome/browser/ui/activity_services/share_to_data.h" |
| 17 #include "ios/web/public/test/test_web_thread_bundle.h" | 16 #include "ios/web/public/test/test_web_thread_bundle.h" |
| 18 #include "testing/gtest_mac.h" | 17 #include "testing/gtest_mac.h" |
| 19 #include "testing/platform_test.h" | 18 #include "testing/platform_test.h" |
| 20 #import "third_party/ocmock/OCMock/OCMock.h" | 19 #import "third_party/ocmock/OCMock/OCMock.h" |
| 21 #import "third_party/ocmock/gtest_support.h" | 20 #import "third_party/ocmock/gtest_support.h" |
| 22 | 21 |
| 22 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
| 23 #error "This file requires ARC support." | |
| 24 #endif | |
| 25 | |
| 23 @interface ActivityServiceController (CrVisibleForTesting) | 26 @interface ActivityServiceController (CrVisibleForTesting) |
| 24 - (NSArray*)activityItemsForData:(ShareToData*)data; | 27 - (NSArray*)activityItemsForData:(ShareToData*)data; |
| 25 - (NSArray*)applicationActivitiesForData:(ShareToData*)data | 28 - (NSArray*)applicationActivitiesForData:(ShareToData*)data |
| 26 controller:(UIViewController*)controller; | 29 controller:(UIViewController*)controller; |
| 27 - (BOOL)processItemsReturnedFromActivity:(NSString*)activityType | 30 - (BOOL)processItemsReturnedFromActivity:(NSString*)activityType |
| 28 status:(ShareTo::ShareResult)result | 31 status:(ShareTo::ShareResult)result |
| 29 items:(NSArray*)extensionItems; | 32 items:(NSArray*)extensionItems; |
| 30 // Setter function for mocking during testing | 33 // Setter function for mocking during testing |
| 31 - (void)setShareToDelegateForTesting:(id<ShareToDelegate>)delegate; | 34 - (void)setShareToDelegateForTesting:(id<ShareToDelegate>)delegate; |
| 32 @end | 35 @end |
| 33 | 36 |
| 34 namespace { | 37 namespace { |
| 35 | 38 |
| 36 class ActivityServiceControllerTest : public PlatformTest { | 39 class ActivityServiceControllerTest : public PlatformTest { |
| 37 protected: | 40 protected: |
| 38 void SetUp() override { | 41 void SetUp() override { |
| 39 PlatformTest::SetUp(); | 42 PlatformTest::SetUp(); |
| 40 parentController_.reset( | 43 parentController_ = |
| 41 [[UIViewController alloc] initWithNibName:nil bundle:nil]); | 44 [[UIViewController alloc] initWithNibName:nil bundle:nil]; |
| 42 [[UIApplication sharedApplication] keyWindow].rootViewController = | 45 [[UIApplication sharedApplication] keyWindow].rootViewController = |
| 43 parentController_; | 46 parentController_; |
| 44 shareToDelegate_.reset( | 47 shareToDelegate_ = |
| 45 [[OCMockObject mockForProtocol:@protocol(ShareToDelegate)] retain]); | 48 [OCMockObject mockForProtocol:@protocol(ShareToDelegate)]; |
| 46 shareData_.reset([[ShareToData alloc] | 49 shareData_ = |
| 47 initWithURL:GURL("https://chromium.org") | 50 [[ShareToData alloc] initWithURL:GURL("https://chromium.org") |
| 48 title:@"" | 51 title:@"" |
| 49 isOriginalTitle:YES | 52 isOriginalTitle:YES |
| 50 isPagePrintable:YES | 53 isPagePrintable:YES |
| 51 thumbnailGenerator:DummyThumbnailGeneratorBlock()]); | 54 thumbnailGenerator:DummyThumbnailGeneratorBlock()]; |
| 52 } | 55 } |
| 53 | 56 |
| 54 void TearDown() override { | 57 void TearDown() override { |
| 55 [[UIApplication sharedApplication] keyWindow].rootViewController = nil; | 58 [[UIApplication sharedApplication] keyWindow].rootViewController = nil; |
| 56 PlatformTest::TearDown(); | 59 PlatformTest::TearDown(); |
| 57 } | 60 } |
| 58 | 61 |
| 59 ThumbnailGeneratorBlock DummyThumbnailGeneratorBlock() { | 62 ThumbnailGeneratorBlock DummyThumbnailGeneratorBlock() { |
| 60 return ^UIImage*(CGSize const& size) { return nil; }; | 63 return ^UIImage*(CGSize const& size) { return nil; }; |
| 61 } | 64 } |
| 62 | 65 |
| 63 id<ShareToDelegate> GetShareToDelegate() { | 66 id<ShareToDelegate> GetShareToDelegate() { |
| 64 return static_cast<id<ShareToDelegate>>(shareToDelegate_.get()); | 67 return static_cast<id<ShareToDelegate>>(shareToDelegate_); |
| 65 } | 68 } |
| 66 | 69 |
| 67 CGRect AnchorRect() { | 70 CGRect AnchorRect() { |
| 68 // On iPad, UIPopovers must be anchored to rectangles that have a non zero | 71 // On iPad, UIPopovers must be anchored to rectangles that have a non zero |
| 69 // size. | 72 // size. |
| 70 return CGRectMake(0, 0, 1, 1); | 73 return CGRectMake(0, 0, 1, 1); |
| 71 } | 74 } |
| 72 | 75 |
| 73 UIView* AnchorView() { | 76 UIView* AnchorView() { |
| 74 // On iPad, UIPopovers must be anchored to non nil views. | 77 // On iPad, UIPopovers must be anchored to non nil views. |
| 75 return [parentController_.get() view]; | 78 return [parentController_ view]; |
| 76 } | 79 } |
| 77 | 80 |
| 78 BOOL ArrayContainsImageSource(NSArray* array) { | 81 BOOL ArrayContainsImageSource(NSArray* array) { |
| 79 for (NSObject* item in array) { | 82 for (NSObject* item in array) { |
| 80 if ([item class] == [UIActivityImageSource class]) { | 83 if ([item class] == [UIActivityImageSource class]) { |
| 81 return YES; | 84 return YES; |
| 82 } | 85 } |
| 83 } | 86 } |
| 84 return NO; | 87 return NO; |
| 85 } | 88 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 135 [result addObject:item]; | 138 [result addObject:item]; |
| 136 } | 139 } |
| 137 } | 140 } |
| 138 return result; | 141 return result; |
| 139 } | 142 } |
| 140 | 143 |
| 141 // Calls -processItemsReturnedFromActivity:status:items: with the provided | 144 // Calls -processItemsReturnedFromActivity:status:items: with the provided |
| 142 // |extensionItem| and expects failure. | 145 // |extensionItem| and expects failure. |
| 143 void ProcessItemsReturnedFromActivityFailure(NSArray* extensionItems, | 146 void ProcessItemsReturnedFromActivityFailure(NSArray* extensionItems, |
| 144 BOOL expectedResetUI) { | 147 BOOL expectedResetUI) { |
| 145 base::scoped_nsobject<ActivityServiceController> activityController( | 148 ActivityServiceController* activityController = |
| 146 [[ActivityServiceController alloc] init]); | 149 [[ActivityServiceController alloc] init]; |
| 147 | 150 |
| 148 // Sets up a Mock ShareToDelegate object to check that the ShareToDelegate | 151 // Sets up a Mock ShareToDelegate object to check that the ShareToDelegate |
| 149 // callback function is not called. | 152 // callback function is not called. |
| 150 OCMockObject* shareToDelegateMock = | 153 OCMockObject* shareToDelegateMock = |
| 151 [OCMockObject mockForProtocol:@protocol(ShareToDelegate)]; | 154 [OCMockObject mockForProtocol:@protocol(ShareToDelegate)]; |
| 152 __block bool blockCalled = false; | 155 __block bool blockCalled = false; |
| 153 void (^validationBlock)(NSInvocation*) = ^(NSInvocation* invocation) { | 156 void (^validationBlock)(NSInvocation*) = ^(NSInvocation* invocation) { |
| 154 blockCalled = true; | 157 blockCalled = true; |
| 155 }; | 158 }; |
| 156 // OCMock does not allow "any" specification for non-object parameters. | 159 // OCMock does not allow "any" specification for non-object parameters. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 192 status:result | 195 status:result |
| 193 items:extensionItems]; | 196 items:extensionItems]; |
| 194 ASSERT_EQ(expectedResetUI, resetUI); | 197 ASSERT_EQ(expectedResetUI, resetUI); |
| 195 base::test::ios::WaitUntilCondition(^{ | 198 base::test::ios::WaitUntilCondition(^{ |
| 196 return blockCalled; | 199 return blockCalled; |
| 197 }); | 200 }); |
| 198 EXPECT_OCMOCK_VERIFY(shareToDelegateMock); | 201 EXPECT_OCMOCK_VERIFY(shareToDelegateMock); |
| 199 } | 202 } |
| 200 | 203 |
| 201 web::TestWebThreadBundle thread_bundle_; | 204 web::TestWebThreadBundle thread_bundle_; |
| 202 base::scoped_nsobject<UIViewController> parentController_; | 205 UIViewController* parentController_; |
| 203 base::scoped_nsobject<OCMockObject> shareToDelegate_; | 206 OCMockObject* shareToDelegate_; |
| 204 base::scoped_nsobject<ShareToData> shareData_; | 207 ShareToData* shareData_; |
| 205 }; | 208 }; |
| 206 | 209 |
| 207 TEST_F(ActivityServiceControllerTest, PresentAndDismissController) { | 210 TEST_F(ActivityServiceControllerTest, PresentAndDismissController) { |
| 208 [[shareToDelegate_ expect] shareDidComplete:ShareTo::ShareResult::SHARE_CANCEL | 211 [[shareToDelegate_ expect] shareDidComplete:ShareTo::ShareResult::SHARE_CANCEL |
| 209 successMessage:[OCMArg isNil]]; | 212 successMessage:[OCMArg isNil]]; |
| 210 | 213 |
| 211 UIViewController* parentController = | 214 UIViewController* parentController = |
| 212 static_cast<UIViewController*>(parentController_.get()); | 215 static_cast<UIViewController*>(parentController_); |
| 213 base::scoped_nsobject<ActivityServiceController> activityController( | 216 ActivityServiceController* activityController = |
| 214 [[ActivityServiceController alloc] init]); | 217 [[ActivityServiceController alloc] init]; |
| 215 EXPECT_FALSE([activityController isActive]); | 218 EXPECT_FALSE([activityController isActive]); |
| 216 | 219 |
| 217 // Test sharing. | 220 // Test sharing. |
| 218 [activityController shareWithData:shareData_ | 221 [activityController shareWithData:shareData_ |
| 219 controller:parentController | 222 controller:parentController |
| 220 browserState:nullptr | 223 browserState:nullptr |
| 221 shareToDelegate:GetShareToDelegate() | 224 shareToDelegate:GetShareToDelegate() |
| 222 fromRect:AnchorRect() | 225 fromRect:AnchorRect() |
| 223 inView:AnchorView()]; | 226 inView:AnchorView()]; |
| 224 EXPECT_TRUE([activityController isActive]); | 227 EXPECT_TRUE([activityController isActive]); |
| 225 | 228 |
| 226 // Cancels sharing and isActive flag should be turned off. | 229 // Cancels sharing and isActive flag should be turned off. |
| 227 [activityController cancelShareAnimated:NO]; | 230 [activityController cancelShareAnimated:NO]; |
| 228 base::test::ios::WaitUntilCondition(^bool() { | 231 base::test::ios::WaitUntilCondition(^bool() { |
| 229 return ![activityController isActive]; | 232 return ![activityController isActive]; |
| 230 }); | 233 }); |
| 231 EXPECT_OCMOCK_VERIFY(shareToDelegate_); | 234 EXPECT_OCMOCK_VERIFY(shareToDelegate_); |
| 232 } | 235 } |
| 233 | 236 |
| 234 // Verifies that an UIActivityImageSource is sent to the | 237 // Verifies that an UIActivityImageSource is sent to the |
| 235 // UIActivityViewController if and only if the ShareToData contains an image. | 238 // UIActivityViewController if and only if the ShareToData contains an image. |
| 236 TEST_F(ActivityServiceControllerTest, ActivityItemsForData) { | 239 TEST_F(ActivityServiceControllerTest, ActivityItemsForData) { |
| 237 base::scoped_nsobject<ActivityServiceController> activityController( | 240 ActivityServiceController* activityController = |
| 238 [[ActivityServiceController alloc] init]); | 241 [[ActivityServiceController alloc] init]; |
| 239 | 242 |
| 240 // ShareToData does not contain an image, so the result items array will not | 243 // ShareToData does not contain an image, so the result items array will not |
| 241 // contain an image source. | 244 // contain an image source. |
| 242 base::scoped_nsobject<ShareToData> data([[ShareToData alloc] | 245 ShareToData* data = |
| 243 initWithURL:GURL("https://chromium.org") | 246 [[ShareToData alloc] initWithURL:GURL("https://chromium.org") |
| 244 title:@"foo" | 247 title:@"foo" |
| 245 isOriginalTitle:YES | 248 isOriginalTitle:YES |
| 246 isPagePrintable:YES | 249 isPagePrintable:YES |
| 247 thumbnailGenerator:DummyThumbnailGeneratorBlock()]); | 250 thumbnailGenerator:DummyThumbnailGeneratorBlock()]; |
| 248 NSArray* items = [activityController activityItemsForData:data]; | 251 NSArray* items = [activityController activityItemsForData:data]; |
| 249 EXPECT_FALSE(ArrayContainsImageSource(items)); | 252 EXPECT_FALSE(ArrayContainsImageSource(items)); |
| 250 | 253 |
| 251 // Adds an image to the ShareToData object and call -activityItemsForData: | 254 // Adds an image to the ShareToData object and call -activityItemsForData: |
| 252 // again. Verifies that the result items array contains an image source. | 255 // again. Verifies that the result items array contains an image source. |
| 253 [data setImage:[UIImage imageNamed:@"activity_services_print"]]; | 256 [data setImage:[UIImage imageNamed:@"activity_services_print"]]; |
| 254 items = [activityController activityItemsForData:data]; | 257 items = [activityController activityItemsForData:data]; |
| 255 EXPECT_TRUE(ArrayContainsImageSource(items)); | 258 EXPECT_TRUE(ArrayContainsImageSource(items)); |
| 256 } | 259 } |
| 257 | 260 |
| 258 // Verifies that when App Extension support is enabled, the URL string is | 261 // Verifies that when App Extension support is enabled, the URL string is |
| 259 // passed in a dictionary as part of the Activity Items to the App Extension. | 262 // passed in a dictionary as part of the Activity Items to the App Extension. |
| 260 TEST_F(ActivityServiceControllerTest, ActivityItemsForDataWithPasswordAppEx) { | 263 TEST_F(ActivityServiceControllerTest, ActivityItemsForDataWithPasswordAppEx) { |
| 261 base::scoped_nsobject<ActivityServiceController> activityController( | 264 ActivityServiceController* activityController = |
| 262 [[ActivityServiceController alloc] init]); | 265 [[ActivityServiceController alloc] init]; |
| 263 base::scoped_nsobject<ShareToData> data([[ShareToData alloc] | 266 ShareToData* data = |
| 264 initWithURL:GURL("https://chromium.org/login.html") | 267 [[ShareToData alloc] initWithURL:GURL("https://chromium.org/login.html") |
| 265 title:@"kung fu fighting" | 268 title:@"kung fu fighting" |
| 266 isOriginalTitle:YES | 269 isOriginalTitle:YES |
| 267 isPagePrintable:YES | 270 isPagePrintable:YES |
| 268 thumbnailGenerator:DummyThumbnailGeneratorBlock()]); | 271 thumbnailGenerator:DummyThumbnailGeneratorBlock()]; |
| 269 NSArray* items = [activityController activityItemsForData:data]; | 272 NSArray* items = [activityController activityItemsForData:data]; |
| 270 NSString* findLoginAction = | 273 NSString* findLoginAction = |
| 271 (NSString*)activity_services::kUTTypeAppExtensionFindLoginAction; | 274 (NSString*)activity_services::kUTTypeAppExtensionFindLoginAction; |
| 272 // Gets the list of NSExtensionItem objects returned by the array of | 275 // Gets the list of NSExtensionItem objects returned by the array of |
| 273 // id<UIActivityItemSource> objects returned by -activityItemsForData:. | 276 // id<UIActivityItemSource> objects returned by -activityItemsForData:. |
| 274 NSArray* extensionItems = FindItemsForActivityType( | 277 NSArray* extensionItems = FindItemsForActivityType( |
| 275 items, activity_services::kAppExtensionOnePassword); | 278 items, activity_services::kAppExtensionOnePassword); |
| 276 ASSERT_EQ(1U, [extensionItems count]); | 279 ASSERT_EQ(1U, [extensionItems count]); |
| 277 NSExtensionItem* item = extensionItems[0]; | 280 NSExtensionItem* item = extensionItems[0]; |
| 278 EXPECT_EQ(1U, item.attachments.count); | 281 EXPECT_EQ(1U, item.attachments.count); |
| 279 NSItemProvider* itemProvider = item.attachments[0]; | 282 NSItemProvider* itemProvider = item.attachments[0]; |
| 280 // Extracts the dictionary back from the ItemProvider and then check that | 283 // Extracts the dictionary back from the ItemProvider and then check that |
| 281 // it has the expected version and the page's URL. | 284 // it has the expected version and the page's URL. |
| 282 __block base::scoped_nsobject<NSDictionary> result; | 285 __block NSDictionary* result; |
| 283 [itemProvider | 286 [itemProvider |
| 284 loadItemForTypeIdentifier:findLoginAction | 287 loadItemForTypeIdentifier:findLoginAction |
| 285 options:nil | 288 options:nil |
| 286 completionHandler:^(id item, NSError* error) { | 289 completionHandler:^(id item, NSError* error) { |
| 287 if (error || ![item isKindOfClass:[NSDictionary class]]) { | 290 if (error || ![item isKindOfClass:[NSDictionary class]]) { |
| 288 result.reset([[NSDictionary dictionary] retain]); | 291 result = [NSDictionary dictionary]; |
|
sdefresne
2017/02/09 16:05:05
nit: result = @{};
lody
2017/02/09 16:18:19
Done.
| |
| 289 } else { | 292 } else { |
| 290 result.reset([item retain]); | 293 result = item; |
| 291 } | 294 } |
| 292 }]; | 295 }]; |
| 293 base::test::ios::WaitUntilCondition(^{ | 296 base::test::ios::WaitUntilCondition(^{ |
| 294 return result.get() != nil; | 297 return result != nil; |
| 295 }); | 298 }); |
| 296 EXPECT_EQ(2U, [result count]); | 299 EXPECT_EQ(2U, [result count]); |
| 297 // Checks version. | 300 // Checks version. |
| 298 NSNumber* version = | 301 NSNumber* version = |
| 299 [result objectForKey:activity_services::kPasswordAppExVersionNumberKey]; | 302 [result objectForKey:activity_services::kPasswordAppExVersionNumberKey]; |
| 300 EXPECT_NSEQ(activity_services::kPasswordAppExVersionNumber, version); | 303 EXPECT_NSEQ(activity_services::kPasswordAppExVersionNumber, version); |
| 301 // Checks URL. | 304 // Checks URL. |
| 302 NSString* appExUrlString = | 305 NSString* appExUrlString = |
| 303 [result objectForKey:activity_services::kPasswordAppExURLStringKey]; | 306 [result objectForKey:activity_services::kPasswordAppExURLStringKey]; |
| 304 EXPECT_NSEQ(@"https://chromium.org/login.html", appExUrlString); | 307 EXPECT_NSEQ(@"https://chromium.org/login.html", appExUrlString); |
| 305 | 308 |
| 306 // Checks that the list includes the page's title. | 309 // Checks that the list includes the page's title. |
| 307 NSArray* sources = | 310 NSArray* sources = |
| 308 FindItemsOfClass(items, [UIActivityFindLoginActionSource class]); | 311 FindItemsOfClass(items, [UIActivityFindLoginActionSource class]); |
| 309 EXPECT_EQ(1U, [sources count]); | 312 EXPECT_EQ(1U, [sources count]); |
| 310 UIActivityFindLoginActionSource* actionSource = sources[0]; | 313 UIActivityFindLoginActionSource* actionSource = sources[0]; |
| 311 id mockActivityViewController = | 314 id mockActivityViewController = |
| 312 [OCMockObject niceMockForClass:[UIActivityViewController class]]; | 315 [OCMockObject niceMockForClass:[UIActivityViewController class]]; |
| 313 NSString* title = [actionSource | 316 NSString* title = [actionSource |
| 314 activityViewController:mockActivityViewController | 317 activityViewController:mockActivityViewController |
| 315 subjectForActivityType:activity_services::kAppExtensionOnePassword]; | 318 subjectForActivityType:activity_services::kAppExtensionOnePassword]; |
| 316 EXPECT_NSEQ(@"kung fu fighting", title); | 319 EXPECT_NSEQ(@"kung fu fighting", title); |
| 317 } | 320 } |
| 318 | 321 |
| 319 // Verifies that a Share extension can fetch a URL when Password App Extension | 322 // Verifies that a Share extension can fetch a URL when Password App Extension |
| 320 // is enabled. | 323 // is enabled. |
| 321 TEST_F(ActivityServiceControllerTest, | 324 TEST_F(ActivityServiceControllerTest, |
| 322 ActivityItemsForDataWithPasswordAppExReturnsURL) { | 325 ActivityItemsForDataWithPasswordAppExReturnsURL) { |
| 323 base::scoped_nsobject<ActivityServiceController> activityController( | 326 ActivityServiceController* activityController = |
| 324 [[ActivityServiceController alloc] init]); | 327 [[ActivityServiceController alloc] init]; |
| 325 base::scoped_nsobject<ShareToData> data([[ShareToData alloc] | 328 ShareToData* data = |
| 326 initWithURL:GURL("https://chromium.org/login.html") | 329 [[ShareToData alloc] initWithURL:GURL("https://chromium.org/login.html") |
| 327 title:@"kung fu fighting" | 330 title:@"kung fu fighting" |
| 328 isOriginalTitle:YES | 331 isOriginalTitle:YES |
| 329 isPagePrintable:YES | 332 isPagePrintable:YES |
| 330 thumbnailGenerator:DummyThumbnailGeneratorBlock()]); | 333 thumbnailGenerator:DummyThumbnailGeneratorBlock()]; |
| 331 NSArray* items = [activityController activityItemsForData:data]; | 334 NSArray* items = [activityController activityItemsForData:data]; |
| 332 NSString* shareAction = @"com.apple.UIKit.activity.PostToFacebook"; | 335 NSString* shareAction = @"com.apple.UIKit.activity.PostToFacebook"; |
| 333 NSArray* urlItems = | 336 NSArray* urlItems = |
| 334 FindItemsEqualsToUTType(items, shareAction, @"public.url"); | 337 FindItemsEqualsToUTType(items, shareAction, @"public.url"); |
| 335 ASSERT_EQ(1U, [urlItems count]); | 338 ASSERT_EQ(1U, [urlItems count]); |
| 336 id<UIActivityItemSource> itemSource = urlItems[0]; | 339 id<UIActivityItemSource> itemSource = urlItems[0]; |
| 337 id mockActivityViewController = | 340 id mockActivityViewController = |
| 338 [OCMockObject niceMockForClass:[UIActivityViewController class]]; | 341 [OCMockObject niceMockForClass:[UIActivityViewController class]]; |
| 339 id item = [itemSource activityViewController:mockActivityViewController | 342 id item = [itemSource activityViewController:mockActivityViewController |
| 340 itemForActivityType:shareAction]; | 343 itemForActivityType:shareAction]; |
| 341 ASSERT_TRUE([item isKindOfClass:[NSURL class]]); | 344 ASSERT_TRUE([item isKindOfClass:[NSURL class]]); |
| 342 EXPECT_NSEQ(@"https://chromium.org/login.html", [item absoluteString]); | 345 EXPECT_NSEQ(@"https://chromium.org/login.html", [item absoluteString]); |
| 343 } | 346 } |
| 344 | 347 |
| 345 // Verifies that -processItemsReturnedFromActivity:status:item: contains | 348 // Verifies that -processItemsReturnedFromActivity:status:item: contains |
| 346 // the username and password. | 349 // the username and password. |
| 347 TEST_F(ActivityServiceControllerTest, ProcessItemsReturnedSuccessfully) { | 350 TEST_F(ActivityServiceControllerTest, ProcessItemsReturnedSuccessfully) { |
| 348 base::scoped_nsobject<ActivityServiceController> activityController( | 351 ActivityServiceController* activityController = |
| 349 [[ActivityServiceController alloc] init]); | 352 [[ActivityServiceController alloc] init]; |
| 350 | 353 |
| 351 // Sets up a Mock ShareToDelegate object to check that the callback function | 354 // Sets up a Mock ShareToDelegate object to check that the callback function |
| 352 // -passwordAppExDidFinish:username:password:successMessage: | 355 // -passwordAppExDidFinish:username:password:successMessage: |
| 353 // is correct with the correct username and password. | 356 // is correct with the correct username and password. |
| 354 OCMockObject* shareToDelegateMock = | 357 OCMockObject* shareToDelegateMock = |
| 355 [OCMockObject mockForProtocol:@protocol(ShareToDelegate)]; | 358 [OCMockObject mockForProtocol:@protocol(ShareToDelegate)]; |
| 356 NSString* const kSecretUsername = @"john.doe"; | 359 NSString* const kSecretUsername = @"john.doe"; |
| 357 NSString* const kSecretPassword = @"super!secret"; | 360 NSString* const kSecretPassword = @"super!secret"; |
| 358 __block bool blockCalled = false; | 361 __block bool blockCalled = false; |
| 359 void (^validationBlock)(NSInvocation*) = ^(NSInvocation* invocation) { | 362 void (^validationBlock)(NSInvocation*) = ^(NSInvocation* invocation) { |
| 360 NSString* username; | 363 __unsafe_unretained NSString* username; |
| 361 NSString* password; | 364 __unsafe_unretained NSString* password; |
| 362 // Skips 0 and 1 index because they are |self| and |cmd|. | 365 // Skips 0 and 1 index because they are |self| and |cmd|. |
| 363 [invocation getArgument:&username atIndex:3]; | 366 [invocation getArgument:&username atIndex:3]; |
| 364 [invocation getArgument:&password atIndex:4]; | 367 [invocation getArgument:&password atIndex:4]; |
| 365 EXPECT_NSEQ(kSecretUsername, username); | 368 EXPECT_NSEQ(kSecretUsername, username); |
| 366 EXPECT_NSEQ(kSecretPassword, password); | 369 EXPECT_NSEQ(kSecretPassword, password); |
| 367 blockCalled = true; | 370 blockCalled = true; |
| 368 }; | 371 }; |
| 369 [[[shareToDelegateMock stub] andDo:validationBlock] | 372 [[[shareToDelegateMock stub] andDo:validationBlock] |
| 370 passwordAppExDidFinish:ShareTo::ShareResult::SHARE_SUCCESS | 373 passwordAppExDidFinish:ShareTo::ShareResult::SHARE_SUCCESS |
| 371 username:OCMOCK_ANY | 374 username:OCMOCK_ANY |
| 372 password:OCMOCK_ANY | 375 password:OCMOCK_ANY |
| 373 successMessage:OCMOCK_ANY]; | 376 successMessage:OCMOCK_ANY]; |
| 374 [activityController setShareToDelegateForTesting:(id)shareToDelegateMock]; | 377 [activityController setShareToDelegateForTesting:(id)shareToDelegateMock]; |
| 375 | 378 |
| 376 // Sets up the returned item from a Password Management App Extension. | 379 // Sets up the returned item from a Password Management App Extension. |
| 377 NSString* activityType = @"com.software.find-login-action.extension"; | 380 NSString* activityType = @"com.software.find-login-action.extension"; |
| 378 ShareTo::ShareResult result = ShareTo::ShareResult::SHARE_SUCCESS; | 381 ShareTo::ShareResult result = ShareTo::ShareResult::SHARE_SUCCESS; |
| 379 NSDictionary* dictionaryFromAppEx = | 382 NSDictionary* dictionaryFromAppEx = |
| 380 @{ @"username" : kSecretUsername, | 383 @{ @"username" : kSecretUsername, |
| 381 @"password" : kSecretPassword }; | 384 @"password" : kSecretPassword }; |
| 382 base::scoped_nsobject<NSItemProvider> itemProvider([[NSItemProvider alloc] | 385 NSItemProvider* itemProvider = |
| 383 initWithItem:dictionaryFromAppEx | 386 [[NSItemProvider alloc] initWithItem:dictionaryFromAppEx |
| 384 typeIdentifier:(NSString*)kUTTypePropertyList]); | 387 typeIdentifier:(NSString*)kUTTypePropertyList]; |
| 385 base::scoped_nsobject<NSExtensionItem> extensionItem( | 388 NSExtensionItem* extensionItem = [[NSExtensionItem alloc] init]; |
| 386 [[NSExtensionItem alloc] init]); | 389 [extensionItem setAttachments:@[ itemProvider ]]; |
| 387 [extensionItem setAttachments:@[ itemProvider.get() ]]; | |
| 388 | 390 |
| 389 BOOL resetUI = | 391 BOOL resetUI = |
| 390 [activityController processItemsReturnedFromActivity:activityType | 392 [activityController processItemsReturnedFromActivity:activityType |
| 391 status:result | 393 status:result |
| 392 items:@[ extensionItem ]]; | 394 items:@[ extensionItem ]]; |
| 393 ASSERT_FALSE(resetUI); | 395 ASSERT_FALSE(resetUI); |
| 394 // Wait for -passwordAppExDidFinish:username:password:successMessage: | 396 // Wait for -passwordAppExDidFinish:username:password:successMessage: |
| 395 // to be called. | 397 // to be called. |
| 396 base::test::ios::WaitUntilCondition(^{ | 398 base::test::ios::WaitUntilCondition(^{ |
| 397 return blockCalled; | 399 return blockCalled; |
| 398 }); | 400 }); |
| 399 EXPECT_OCMOCK_VERIFY(shareToDelegateMock); | 401 EXPECT_OCMOCK_VERIFY(shareToDelegateMock); |
| 400 } | 402 } |
| 401 | 403 |
| 402 // Verifies that -processItemsReturnedFromActivity:status:item: fails when | 404 // Verifies that -processItemsReturnedFromActivity:status:item: fails when |
| 403 // called with invalid NSExtensionItem. | 405 // called with invalid NSExtensionItem. |
| 404 TEST_F(ActivityServiceControllerTest, ProcessItemsReturnedFailures) { | 406 TEST_F(ActivityServiceControllerTest, ProcessItemsReturnedFailures) { |
| 405 ProcessItemsReturnedFromActivityFailure(@[], YES); | 407 ProcessItemsReturnedFromActivityFailure(@[], YES); |
| 406 | 408 |
| 407 // Extension Item is empty. | 409 // Extension Item is empty. |
| 408 base::scoped_nsobject<NSExtensionItem> extensionItem( | 410 NSExtensionItem* extensionItem = [[NSExtensionItem alloc] init]; |
| 409 [[NSExtensionItem alloc] init]); | |
| 410 [extensionItem setAttachments:@[]]; | 411 [extensionItem setAttachments:@[]]; |
| 411 ProcessItemsReturnedFromActivityFailure(@[ extensionItem ], YES); | 412 ProcessItemsReturnedFromActivityFailure(@[ extensionItem ], YES); |
| 412 | 413 |
| 413 // Extension Item does not have a property list provider as the first | 414 // Extension Item does not have a property list provider as the first |
| 414 // attachment. | 415 // attachment. |
| 415 base::scoped_nsobject<NSItemProvider> itemProvider([[NSItemProvider alloc] | 416 NSItemProvider* itemProvider = |
| 416 initWithItem:@"some arbitrary garbage" | 417 [[NSItemProvider alloc] initWithItem:@"some arbitrary garbage" |
| 417 typeIdentifier:(NSString*)kUTTypeText]); | 418 typeIdentifier:(NSString*)kUTTypeText]; |
| 418 [extensionItem setAttachments:@[ itemProvider.get() ]]; | 419 [extensionItem setAttachments:@[ itemProvider ]]; |
| 419 ProcessItemsReturnedFromActivityFailure(@[ extensionItem ], YES); | 420 ProcessItemsReturnedFromActivityFailure(@[ extensionItem ], YES); |
| 420 | 421 |
| 421 // Property list provider did not return a dictionary object. | 422 // Property list provider did not return a dictionary object. |
| 422 itemProvider.reset([[NSItemProvider alloc] | 423 itemProvider = |
| 423 initWithItem:@[ @"foo", @"bar" ] | 424 [[NSItemProvider alloc] initWithItem:@[ @"foo", @"bar" ] |
| 424 typeIdentifier:(NSString*)kUTTypePropertyList]); | 425 typeIdentifier:(NSString*)kUTTypePropertyList]; |
| 425 [extensionItem setAttachments:@[ itemProvider.get() ]]; | 426 [extensionItem setAttachments:@[ itemProvider ]]; |
| 426 ProcessItemsReturnedFromActivityFailure(@[ extensionItem ], NO); | 427 ProcessItemsReturnedFromActivityFailure(@[ extensionItem ], NO); |
| 427 } | 428 } |
| 428 | 429 |
| 429 // Verifies that the PrintActivity is sent to the UIActivityViewController if | 430 // Verifies that the PrintActivity is sent to the UIActivityViewController if |
| 430 // and only if the activity is "printable". | 431 // and only if the activity is "printable". |
| 431 TEST_F(ActivityServiceControllerTest, ApplicationActivitiesForData) { | 432 TEST_F(ActivityServiceControllerTest, ApplicationActivitiesForData) { |
| 432 base::scoped_nsobject<ActivityServiceController> activityController( | 433 ActivityServiceController* activityController = |
| 433 [[ActivityServiceController alloc] init]); | 434 [[ActivityServiceController alloc] init]; |
| 434 | 435 |
| 435 // Verify printable data. | 436 // Verify printable data. |
| 436 base::scoped_nsobject<ShareToData> data([[ShareToData alloc] | 437 ShareToData* data = |
| 437 initWithURL:GURL("https://chromium.org/printable") | 438 [[ShareToData alloc] initWithURL:GURL("https://chromium.org/printable") |
| 438 title:@"bar" | 439 title:@"bar" |
| 439 isOriginalTitle:YES | 440 isOriginalTitle:YES |
| 440 isPagePrintable:YES | 441 isPagePrintable:YES |
| 441 thumbnailGenerator:DummyThumbnailGeneratorBlock()]); | 442 thumbnailGenerator:DummyThumbnailGeneratorBlock()]; |
| 442 | 443 |
| 443 NSArray* items = | 444 NSArray* items = |
| 444 [activityController applicationActivitiesForData:data controller:nil]; | 445 [activityController applicationActivitiesForData:data controller:nil]; |
| 445 NSUInteger expected_items_count = | 446 NSUInteger expected_items_count = |
| 446 reading_list::switches::IsReadingListEnabled() ? 2U : 1U; | 447 reading_list::switches::IsReadingListEnabled() ? 2U : 1U; |
| 447 ASSERT_EQ(expected_items_count, [items count]); | 448 ASSERT_EQ(expected_items_count, [items count]); |
| 448 EXPECT_EQ([PrintActivity class], [[items objectAtIndex:0] class]); | 449 EXPECT_EQ([PrintActivity class], [[items objectAtIndex:0] class]); |
| 449 | 450 |
| 450 // Verify non-printable data. | 451 // Verify non-printable data. |
| 451 data.reset([[ShareToData alloc] | 452 data = |
| 452 initWithURL:GURL("https://chromium.org/unprintable") | 453 [[ShareToData alloc] initWithURL:GURL("https://chromium.org/unprintable") |
| 453 title:@"baz" | 454 title:@"baz" |
| 454 isOriginalTitle:YES | 455 isOriginalTitle:YES |
| 455 isPagePrintable:NO | 456 isPagePrintable:NO |
| 456 thumbnailGenerator:DummyThumbnailGeneratorBlock()]); | 457 thumbnailGenerator:DummyThumbnailGeneratorBlock()]; |
| 457 items = [activityController applicationActivitiesForData:data controller:nil]; | 458 items = [activityController applicationActivitiesForData:data controller:nil]; |
| 458 EXPECT_EQ(expected_items_count - 1, [items count]); | 459 EXPECT_EQ(expected_items_count - 1, [items count]); |
| 459 } | 460 } |
| 460 | 461 |
| 461 TEST_F(ActivityServiceControllerTest, FindLoginActionTypeConformsToPublicURL) { | 462 TEST_F(ActivityServiceControllerTest, FindLoginActionTypeConformsToPublicURL) { |
| 462 // If this test fails, it is probably due to missing or incorrect | 463 // If this test fails, it is probably due to missing or incorrect |
| 463 // UTImportedTypeDeclarations in Info.plist. Note that there are | 464 // UTImportedTypeDeclarations in Info.plist. Note that there are |
| 464 // two Info.plist, | 465 // two Info.plist, |
| 465 // - ios/chrome/app/resources/Info.plist for Chrome app | 466 // - ios/chrome/app/resources/Info.plist for Chrome app |
| 466 // - testing/gtest_ios/unittest-Info.plist for ios_chrome_unittests | 467 // - testing/gtest_ios/unittest-Info.plist for ios_chrome_unittests |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 481 // public.url UTType in order to allow Share actions (e.g. Facebook, Twitter, | 482 // public.url UTType in order to allow Share actions (e.g. Facebook, Twitter, |
| 482 // etc) to appear on UIActivityViewController opened by Chrome). | 483 // etc) to appear on UIActivityViewController opened by Chrome). |
| 483 CFStringRef chromeFindLoginAction = reinterpret_cast<CFStringRef>( | 484 CFStringRef chromeFindLoginAction = reinterpret_cast<CFStringRef>( |
| 484 activity_services::kUTTypeAppExtensionFindLoginAction); | 485 activity_services::kUTTypeAppExtensionFindLoginAction); |
| 485 EXPECT_TRUE(UTTypeConformsTo(chromeFindLoginAction, kUTTypeURL)); | 486 EXPECT_TRUE(UTTypeConformsTo(chromeFindLoginAction, kUTTypeURL)); |
| 486 EXPECT_TRUE( | 487 EXPECT_TRUE( |
| 487 UTTypeConformsTo(chromeFindLoginAction, onePasswordFindLoginAction)); | 488 UTTypeConformsTo(chromeFindLoginAction, onePasswordFindLoginAction)); |
| 488 } | 489 } |
| 489 | 490 |
| 490 } // namespace | 491 } // namespace |
| OLD | NEW |