// Copyright 2020 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/browser/ui/sharing/activity_services/activity_service_mediator.h"
#import <MobileCoreServices/MobileCoreServices.h>
#import "base/apple/foundation_util.h"
#import "base/metrics/user_metrics.h"
#import "base/metrics/user_metrics_action.h"
#import "base/strings/string_number_conversions.h"
#import "base/strings/sys_string_conversions.h"
#import "components/prefs/pref_service.h"
#import "ios/chrome/browser/shared/coordinator/default_browser_promo/non_modal_default_browser_promo_scheduler_scene_agent.h"
#import "ios/chrome/browser/shared/model/prefs/pref_names.h"
#import "ios/chrome/browser/shared/model/url/url_util.h"
#import "ios/chrome/browser/shared/public/commands/bookmarks_commands.h"
#import "ios/chrome/browser/shared/public/commands/help_commands.h"
#import "ios/chrome/browser/shared/public/commands/qr_generation_commands.h"
#import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
#import "ios/chrome/browser/sync/model/send_tab_to_self_sync_service_factory.h"
#import "ios/chrome/browser/ui/sharing/activity_services/activities/bookmark_activity.h"
#import "ios/chrome/browser/ui/sharing/activity_services/activities/copy_activity.h"
#import "ios/chrome/browser/ui/sharing/activity_services/activities/find_in_page_activity.h"
#import "ios/chrome/browser/ui/sharing/activity_services/activities/generate_qr_code_activity.h"
#import "ios/chrome/browser/ui/sharing/activity_services/activities/print_activity.h"
#import "ios/chrome/browser/ui/sharing/activity_services/activities/reading_list_activity.h"
#import "ios/chrome/browser/ui/sharing/activity_services/activities/request_desktop_or_mobile_site_activity.h"
#import "ios/chrome/browser/ui/sharing/activity_services/activities/send_tab_to_self_activity.h"
#import "ios/chrome/browser/ui/sharing/activity_services/activity_service_histograms.h"
#import "ios/chrome/browser/ui/sharing/activity_services/activity_type_util.h"
#import "ios/chrome/browser/ui/sharing/activity_services/data/chrome_activity_file_source.h"
#import "ios/chrome/browser/ui/sharing/activity_services/data/chrome_activity_image_source.h"
#import "ios/chrome/browser/ui/sharing/activity_services/data/chrome_activity_item_source.h"
#import "ios/chrome/browser/ui/sharing/activity_services/data/chrome_activity_text_source.h"
#import "ios/chrome/browser/ui/sharing/activity_services/data/chrome_activity_url_source.h"
#import "ios/chrome/browser/ui/sharing/activity_services/data/share_file_data.h"
#import "ios/chrome/browser/ui/sharing/activity_services/data/share_image_data.h"
#import "ios/chrome/browser/ui/sharing/activity_services/data/share_to_data.h"
#import "ios/chrome/browser/ui/sharing/sharing_positioner.h"
@interface ActivityServiceMediator ()
@property(nonatomic, weak) id<BrowserCoordinatorCommands, FindInPageCommands>
handler;
@property(nonatomic, weak) id<BookmarksCommands> bookmarksHandler;
@property(nonatomic, weak) id<HelpCommands> helpHandler;
@property(nonatomic, weak) id<QRGenerationCommands> qrGenerationHandler;
@property(nonatomic, assign) PrefService* prefService;
@property(nonatomic, assign) bookmarks::BookmarkModel* bookmarkModel;
@property(nonatomic, weak) UIViewController* baseViewController;
// The navigation agent.
@property(nonatomic, readonly) WebNavigationBrowserAgent* navigationAgent;
@property(nonatomic, readonly) ReadingListBrowserAgent* readingListBrowserAgent;
@end
@implementation ActivityServiceMediator
#pragma mark - Public
- (instancetype)initWithHandler:
(id<BrowserCoordinatorCommands, FindInPageCommands>)handler
bookmarksHandler:(id<BookmarksCommands>)bookmarksHandler
helpHandler:(id<HelpCommands>)helpHandler
qrGenerationHandler:(id<QRGenerationCommands>)qrGenerationHandler
prefService:(PrefService*)prefService
bookmarkModel:(bookmarks::BookmarkModel*)bookmarkModel
baseViewController:(UIViewController*)baseViewController
navigationAgent:(WebNavigationBrowserAgent*)navigationAgent
readingListBrowserAgent:
(ReadingListBrowserAgent*)readingListBrowserAgent {
if ((self = [super init])) {
_handler = handler;
_bookmarksHandler = bookmarksHandler;
_helpHandler = helpHandler;
_qrGenerationHandler = qrGenerationHandler;
_prefService = prefService;
_bookmarkModel = bookmarkModel;
_baseViewController = baseViewController;
_navigationAgent = navigationAgent;
_readingListBrowserAgent = readingListBrowserAgent;
}
return self;
}
- (NSArray<id<ChromeActivityItemSource>>*)activityItemsForDataItems:
(NSArray<ShareToData*>*)dataItems {
NSMutableArray* items = [[NSMutableArray alloc] init];
// The `additionalText` is not added when sharing multiple URLs since items
// are not associated with each other and the `additionalText` is not likely
// be meaningful without the context of the page it came from.
if (dataItems.count == 1 && dataItems.firstObject.additionalText) {
[items addObject:[[ChromeActivityTextSource alloc]
initWithText:dataItems.firstObject.additionalText]];
}
for (ShareToData* data in dataItems) {
ChromeActivityURLSource* activityURLSource =
[[ChromeActivityURLSource alloc] initWithShareURL:data.shareNSURL
subject:data.title];
activityURLSource.thumbnailGenerator = data.thumbnailGenerator;
activityURLSource.linkMetadata = data.linkMetadata;
[items addObject:activityURLSource];
}
return items;
}
- (NSArray*)applicationActivitiesForDataItems:
(NSArray<ShareToData*>*)dataItems {
NSMutableArray* applicationActivities = [NSMutableArray array];
[applicationActivities
addObject:[[CopyActivity alloc] initWithDataItems:dataItems]];
if (dataItems.count != 1) {
return applicationActivities;
}
// The following acitivites only support a single item.
ShareToData* data = dataItems.firstObject;
if (data.shareURL.SchemeIsHTTPOrHTTPS()) {
SendTabToSelfActivity* sendTabToSelfActivity =
[[SendTabToSelfActivity alloc] initWithData:data handler:self.handler];
[applicationActivities addObject:sendTabToSelfActivity];
ReadingListActivity* readingListActivity =
[[ReadingListActivity alloc] initWithURL:data.shareURL
title:data.title
readingListBrowserAgent:self.readingListBrowserAgent];
[applicationActivities addObject:readingListActivity];
BookmarkActivity* bookmarkActivity =
[[BookmarkActivity alloc] initWithURL:data.visibleURL
title:data.title
bookmarkModel:self.bookmarkModel
handler:self.bookmarksHandler
prefService:self.prefService];
[applicationActivities addObject:bookmarkActivity];
GenerateQrCodeActivity* generateQrCodeActivity =
[[GenerateQrCodeActivity alloc] initWithURL:data.shareURL
title:data.title
handler:self.qrGenerationHandler];
[applicationActivities addObject:generateQrCodeActivity];
FindInPageActivity* findInPageActivity =
[[FindInPageActivity alloc] initWithData:data handler:self.handler];
[applicationActivities addObject:findInPageActivity];
RequestDesktopOrMobileSiteActivity* requestActivity =
[[RequestDesktopOrMobileSiteActivity alloc]
initWithUserAgent:data.userAgent
helpHandler:self.helpHandler
navigationAgent:self.navigationAgent];
[applicationActivities addObject:requestActivity];
} else if (UrlIsDownloadedFile(data.shareURL) ||
UrlIsExternalFileReference(data.shareURL)) {
FindInPageActivity* findInPageActivity =
[[FindInPageActivity alloc] initWithData:data handler:self.handler];
[applicationActivities addObject:findInPageActivity];
}
if (self.prefService->GetBoolean(prefs::kPrintingEnabled)) {
PrintActivity* printActivity =
[[PrintActivity alloc] initWithData:data
handler:self.handler
baseViewController:self.baseViewController];
[applicationActivities addObject:printActivity];
}
return applicationActivities;
}
- (NSArray<ChromeActivityFileSource*>*)activityItemsForFileData:
(ShareFileData*)data {
return @[ [[ChromeActivityFileSource alloc] initWithFilePath:data.filePath] ];
}
- (NSArray<ChromeActivityImageSource*>*)activityItemsForImageData:
(ShareImageData*)data {
return @[ [[ChromeActivityImageSource alloc] initWithImage:data.image
title:data.title] ];
}
- (NSArray*)applicationActivitiesForImageData:(ShareImageData*)data {
// For images, we only customize the print activity. Other activities use
// the native ones.
PrintActivity* printActivity =
[[PrintActivity alloc] initWithImageData:data
handler:self.handler
baseViewController:self.baseViewController];
return @[ printActivity ];
}
- (NSSet*)excludedActivityTypesForItems:
(NSArray<id<ChromeActivityItemSource>>*)items {
NSMutableSet* mutableSet = [[NSMutableSet alloc] init];
for (id<ChromeActivityItemSource> item in items) {
[mutableSet unionSet:item.excludedActivityTypes];
}
return mutableSet;
}
- (void)shareStartedWithScenario:(SharingScenario)scenario {
RecordScenarioInitiated(scenario);
}
- (void)recordShareChromeFinishedInPrefs {
PrefService* prefs = self.prefService;
DCHECK(prefs);
int count = prefs->GetInteger(prefs::kIosShareChromeCount);
prefs->SetInteger(prefs::kIosShareChromeCount, count + 1);
prefs->SetTime(prefs::kIosShareChromeLastShare, base::Time::Now());
}
- (void)shareFinishedWithScenario:(SharingScenario)scenario
activityType:(NSString*)activityType
completed:(BOOL)completed {
if (activityType && completed) {
activity_type_util::ActivityType type =
activity_type_util::TypeFromString(activityType);
activity_type_util::RecordMetricForActivity(type);
RecordActivityForScenario(type, scenario);
[self.promoScheduler logUserFinishedActivityFlow];
if (SharingScenario::ShareChrome == scenario) {
[self recordShareChromeFinishedInPrefs];
}
} else {
// Share action was cancelled.
base::RecordAction(base::UserMetricsAction("MobileShareMenuCancel"));
RecordCancelledScenario(scenario);
}
}
@end