blob: 51b9be0ada474bf16b089a6c6c2460172b13658e [file] [log] [blame]
// Copyright 2018 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/browser/ui/history/history_coordinator.h"
#include "components/history/core/browser/browsing_history_service.h"
#include "components/keyed_service/core/service_access_type.h"
#include "components/sync/driver/sync_service.h"
#include "ios/chrome/browser/history/history_service_factory.h"
#import "ios/chrome/browser/main/browser.h"
#include "ios/chrome/browser/sync/profile_sync_service_factory.h"
#import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h"
#import "ios/chrome/browser/ui/history/history_clear_browsing_data_coordinator.h"
#import "ios/chrome/browser/ui/history/history_mediator.h"
#include "ios/chrome/browser/ui/history/history_menu_provider.h"
#include "ios/chrome/browser/ui/history/history_table_view_controller.h"
#import "ios/chrome/browser/ui/history/history_transitioning_delegate.h"
#include "ios/chrome/browser/ui/history/history_ui_delegate.h"
#include "ios/chrome/browser/ui/history/ios_browsing_history_driver.h"
#import "ios/chrome/browser/ui/menu/action_factory.h"
#import "ios/chrome/browser/ui/menu/menu_histograms.h"
#import "ios/chrome/browser/ui/table_view/feature_flags.h"
#import "ios/chrome/browser/ui/table_view/table_view_navigation_controller.h"
#include "ios/chrome/browser/ui/util/ui_util.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface HistoryCoordinator () <HistoryMenuProvider, HistoryUIDelegate> {
// Provides dependencies and funnels callbacks from BrowsingHistoryService.
std::unique_ptr<IOSBrowsingHistoryDriver> _browsingHistoryDriver;
// Abstraction to communicate with HistoryService and WebHistoryService.
std::unique_ptr<history::BrowsingHistoryService> _browsingHistoryService;
}
// ViewController being managed by this Coordinator.
@property(nonatomic, strong)
TableViewNavigationController* historyNavigationController;
@property(nonatomic, strong)
HistoryTableViewController* historyTableViewController;
// Mediator being managed by this Coordinator.
@property(nonatomic, strong) HistoryMediator* mediator;
// The transitioning delegate used by the history view controller.
@property(nonatomic, strong)
HistoryTransitioningDelegate* historyTransitioningDelegate;
// The coordinator that will present Clear Browsing Data.
@property(nonatomic, strong)
HistoryClearBrowsingDataCoordinator* historyClearBrowsingDataCoordinator;
@end
@implementation HistoryCoordinator
@synthesize historyClearBrowsingDataCoordinator =
_historyClearBrowsingDataCoordinator;
@synthesize historyNavigationController = _historyNavigationController;
@synthesize historyTransitioningDelegate = _historyTransitioningDelegate;
@synthesize mediator = _mediator;
@synthesize presentationDelegate = _presentationDelegate;
- (void)start {
// Initialize and configure HistoryTableViewController.
self.historyTableViewController = [[HistoryTableViewController alloc] init];
self.historyTableViewController.browser = self.browser;
self.historyTableViewController.loadStrategy = self.loadStrategy;
if (@available(iOS 13.0, *)) {
self.historyTableViewController.menuProvider = self;
}
// Initialize and set HistoryMediator
self.mediator = [[HistoryMediator alloc]
initWithBrowserState:self.browser->GetBrowserState()];
self.historyTableViewController.imageDataSource = self.mediator;
// Initialize and configure HistoryServices.
_browsingHistoryDriver = std::make_unique<IOSBrowsingHistoryDriver>(
self.browser->GetBrowserState(), self.historyTableViewController);
_browsingHistoryService = std::make_unique<history::BrowsingHistoryService>(
_browsingHistoryDriver.get(),
ios::HistoryServiceFactory::GetForBrowserState(
self.browser->GetBrowserState(), ServiceAccessType::EXPLICIT_ACCESS),
ProfileSyncServiceFactory::GetForBrowserState(
self.browser->GetBrowserState()));
self.historyTableViewController.historyService =
_browsingHistoryService.get();
// Configure and present HistoryNavigationController.
self.historyNavigationController = [[TableViewNavigationController alloc]
initWithTable:self.historyTableViewController];
self.historyNavigationController.toolbarHidden = NO;
self.historyTableViewController.delegate = self;
self.historyTableViewController.presentationDelegate =
self.presentationDelegate;
BOOL useCustomPresentation = YES;
if (IsCollectionsCardPresentationStyleEnabled()) {
if (@available(iOS 13, *)) {
[self.historyNavigationController
setModalPresentationStyle:UIModalPresentationFormSheet];
self.historyNavigationController.presentationController.delegate =
self.historyTableViewController;
useCustomPresentation = NO;
}
}
if (useCustomPresentation) {
self.historyTransitioningDelegate =
[[HistoryTransitioningDelegate alloc] init];
self.historyNavigationController.transitioningDelegate =
self.historyTransitioningDelegate;
[self.historyNavigationController
setModalPresentationStyle:UIModalPresentationCustom];
}
[self.baseViewController
presentViewController:self.historyNavigationController
animated:YES
completion:nil];
}
- (void)stop {
[self stopWithCompletion:nil];
}
// This method should always execute the |completionHandler|.
- (void)stopWithCompletion:(ProceduralBlock)completionHandler {
if (self.historyNavigationController) {
void (^dismissHistoryNavigation)(void) = ^void() {
// Make sure to stop
// |self.historyTableViewController.contextMenuCoordinator| before
// dismissing, or |self.historyNavigationController| will dismiss that
// instead of itself.
[self.historyTableViewController.contextMenuCoordinator stop];
[self.historyNavigationController
dismissViewControllerAnimated:YES
completion:completionHandler];
self.historyNavigationController = nil;
_browsingHistoryDriver = nullptr;
_browsingHistoryService = nullptr;
};
if (self.historyClearBrowsingDataCoordinator) {
[self.historyClearBrowsingDataCoordinator stopWithCompletion:^() {
dismissHistoryNavigation();
self.historyClearBrowsingDataCoordinator = nil;
}];
} else {
dismissHistoryNavigation();
}
} else if (completionHandler) {
completionHandler();
}
}
#pragma mark - HistoryUIDelegate
- (void)dismissHistoryWithCompletion:(ProceduralBlock)completionHandler {
[self stopWithCompletion:completionHandler];
}
- (void)displayPrivacySettings {
self.historyClearBrowsingDataCoordinator =
[[HistoryClearBrowsingDataCoordinator alloc]
initWithBaseViewController:self.historyNavigationController
browser:self.browser];
self.historyClearBrowsingDataCoordinator.delegate = self;
self.historyClearBrowsingDataCoordinator.presentationDelegate =
self.presentationDelegate;
self.historyClearBrowsingDataCoordinator.loadStrategy = self.loadStrategy;
[self.historyClearBrowsingDataCoordinator start];
}
#pragma mark - HistoryMenuProvider
- (UIContextMenuConfiguration*)contextMenuConfigurationForItem:
(HistoryEntryItem*)item
withView:(UIView*)view
API_AVAILABLE(ios(13.0)) {
__weak id<HistoryEntryItemDelegate> historyItemDelegate =
self.historyTableViewController;
UIContextMenuActionProvider actionProvider =
^(NSArray<UIMenuElement*>* suggestedActions) {
// Record that this context menu was shown to the user.
RecordMenuShown(MenuScenario::kHistoryEntry);
ActionFactory* actionFactory = [[ActionFactory alloc]
initWithScenario:MenuScenario::kHistoryEntry];
UIAction* copyAction = [actionFactory actionToCopyURL:item.URL];
UIAction* deleteAction = [actionFactory actionToDeleteWithBlock:^{
[historyItemDelegate historyEntryItemDidRequestDelete:item];
}];
return [UIMenu menuWithTitle:@""
children:@[ copyAction, deleteAction ]];
};
return
[UIContextMenuConfiguration configurationWithIdentifier:nil
previewProvider:nil
actionProvider:actionProvider];
}
@end