// Copyright 2018 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/toolbar/adaptive_toolbar_coordinator.h"
#import "base/apple/foundation_util.h"
#import "components/ukm/ios/ukm_url_recorder.h"
#import "ios/chrome/browser/feature_engagement/model/tracker_factory.h"
#import "ios/chrome/browser/iph_for_new_chrome_user/model/tab_based_iph_browser_agent.h"
#import "ios/chrome/browser/ntp/model/new_tab_page_util.h"
#import "ios/chrome/browser/overlays/model/public/overlay_presenter.h"
#import "ios/chrome/browser/search_engines/model/template_url_service_factory.h"
#import "ios/chrome/browser/shared/coordinator/layout_guide/layout_guide_util.h"
#import "ios/chrome/browser/shared/model/browser/browser.h"
#import "ios/chrome/browser/shared/model/profile/profile_ios.h"
#import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
#import "ios/chrome/browser/shared/public/commands/activity_service_commands.h"
#import "ios/chrome/browser/shared/public/commands/application_commands.h"
#import "ios/chrome/browser/shared/public/commands/command_dispatcher.h"
#import "ios/chrome/browser/shared/public/commands/omnibox_commands.h"
#import "ios/chrome/browser/shared/public/commands/popup_menu_commands.h"
#import "ios/chrome/browser/shared/ui/symbols/symbols.h"
#import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h"
#import "ios/chrome/browser/ui/fullscreen/fullscreen_ui_updater.h"
#import "ios/chrome/browser/ui/menu/browser_action_factory.h"
#import "ios/chrome/browser/ui/toolbar/adaptive_toolbar_coordinator+subclassing.h"
#import "ios/chrome/browser/ui/toolbar/adaptive_toolbar_mediator.h"
#import "ios/chrome/browser/ui/toolbar/adaptive_toolbar_view_controller.h"
#import "ios/chrome/browser/ui/toolbar/adaptive_toolbar_view_controller_delegate.h"
#import "ios/chrome/browser/ui/toolbar/buttons/toolbar_button_actions_handler.h"
#import "ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.h"
#import "ios/chrome/browser/ui/toolbar/buttons/toolbar_button_visibility_configuration.h"
#import "ios/chrome/browser/url_loading/model/url_loading_browser_agent.h"
#import "ios/chrome/browser/web/model/web_navigation_browser_agent.h"
#import "services/metrics/public/cpp/ukm_builders.h"
@interface AdaptiveToolbarCoordinator () <AdaptiveToolbarViewControllerDelegate>
// Whether this coordinator has been started.
@property(nonatomic, assign) BOOL started;
// Mediator for updating the toolbar when the WebState changes.
@property(nonatomic, strong) AdaptiveToolbarMediator* mediator;
// Actions handler for the toolbar buttons.
@property(nonatomic, strong) ToolbarButtonActionsHandler* actionHandler;
@end
@implementation AdaptiveToolbarCoordinator {
// Observer that updates `toolbarViewController` for fullscreen events.
std::unique_ptr<FullscreenUIUpdater> _fullscreenUIUpdater;
}
#pragma mark - ChromeCoordinator
- (instancetype)initWithBrowser:(Browser*)browser {
DCHECK(browser);
return [super initWithBaseViewController:nil browser:browser];
}
- (void)start {
if (_started) {
return;
}
Browser* browser = self.browser;
_started = YES;
self.viewController.overrideUserInterfaceStyle =
browser->GetBrowserState()->IsOffTheRecord()
? UIUserInterfaceStyleDark
: UIUserInterfaceStyleUnspecified;
self.viewController.layoutGuideCenter = LayoutGuideCenterForBrowser(browser);
self.viewController.adaptiveDelegate = self;
self.mediator = [[AdaptiveToolbarMediator alloc] init];
self.mediator.incognito = browser->GetBrowserState()->IsOffTheRecord();
self.mediator.consumer = self.viewController;
self.mediator.navigationBrowserAgent =
WebNavigationBrowserAgent::FromBrowser(browser);
self.mediator.webStateList = browser->GetWebStateList();
self.mediator.webContentAreaOverlayPresenter =
OverlayPresenter::FromBrowser(browser, OverlayModality::kWebContentArea);
self.mediator.templateURLService =
ios::TemplateURLServiceFactory::GetForBrowserState(
browser->GetBrowserState());
self.mediator.actionFactory = [[BrowserActionFactory alloc]
initWithBrowser:browser
scenario:kMenuScenarioHistogramToolbarMenu];
_fullscreenUIUpdater = std::make_unique<FullscreenUIUpdater>(
FullscreenController::FromBrowser(browser), self.viewController);
self.viewController.menuProvider = self.mediator;
}
- (void)stop {
[super stop];
[self.mediator disconnect];
self.mediator = nil;
_fullscreenUIUpdater = nullptr;
_started = NO;
}
#pragma mark - Public
- (void)setLocationBarViewController:
(UIViewController*)locationBarViewController {
self.viewController.locationBarViewController = locationBarViewController;
}
- (void)updateToolbarForSideSwipeSnapshot:(web::WebState*)webState {
BOOL isNonIncognitoNTP = !self.browser->GetBrowserState()->IsOffTheRecord() &&
IsVisibleURLNewTabPage(webState);
[self.mediator updateConsumerForWebState:webState];
[self.viewController updateForSideSwipeSnapshot:isNonIncognitoNTP];
}
- (void)resetToolbarAfterSideSwipeSnapshot {
[self.mediator updateConsumerForWebState:self.browser->GetWebStateList()
->GetActiveWebState()];
[self.viewController resetAfterSideSwipeSnapshot];
}
- (void)showPrerenderingAnimation {
[self.viewController showPrerenderingAnimation];
}
#pragma mark - AdaptiveToolbarViewControllerDelegate
- (void)exitFullscreen {
FullscreenController* fullscreenController =
FullscreenController::FromBrowser(self.browser);
fullscreenController->ExitFullscreen();
web::WebState* webState =
self.browser->GetWebStateList()->GetActiveWebState();
ukm::SourceId sourceID = ukm::GetSourceIdForWebStateDocument(webState);
if (sourceID != ukm::kInvalidSourceId) {
ukm::builders::IOS_FullscreenActions(sourceID)
.SetHasExitedManually(true)
.Record(ukm::UkmRecorder::Get());
}
}
#pragma mark - NewTabPageControllerDelegate
- (void)setScrollProgressForTabletOmnibox:(CGFloat)progress {
[self.viewController setScrollProgressForTabletOmnibox:progress];
}
- (UIResponder<UITextInput>*)fakeboxScribbleForwardingTarget {
// Implemented in `ToolbarCoordinator`.
return nil;
}
- (void)didNavigateToNTPOnActiveWebState {
// Implemented in `ToolbarCoordinator`.
}
#pragma mark - ToolbarCommands
- (void)triggerToolbarSlideInAnimation {
// Implemented in primary and secondary toolbars directly.
}
- (void)setTabGridButtonIPHHighlighted:(BOOL)iphHighlighted {
[self.mediator updateConsumerWithTabGridButtonIPHHighlighted:iphHighlighted];
}
- (void)setNewTabButtonIPHHighlighted:(BOOL)iphHighlighted {
[self.mediator updateConsumerWithNewTabButtonIPHHighlighted:iphHighlighted];
}
- (void)showShareButtonIPHAfterLocationBarUnfocus {
// no-op, handled in ToolbarCoordinator.
}
#pragma mark - ToolbarCoordinatee
- (id<PopupMenuUIUpdating>)popupMenuUIUpdater {
return self.viewController;
}
#pragma mark - Protected
- (ToolbarButtonFactory*)buttonFactoryWithType:(ToolbarType)type {
BOOL isIncognito = self.browser->GetBrowserState()->IsOffTheRecord();
ToolbarStyle style =
isIncognito ? ToolbarStyle::kIncognito : ToolbarStyle::kNormal;
ToolbarButtonActionsHandler* actionHandler =
[[ToolbarButtonActionsHandler alloc]
initWithEngagementTracker:feature_engagement::TrackerFactory::
GetForBrowserState(
self.browser->GetBrowserState())];
CommandDispatcher* dispatcher = self.browser->GetCommandDispatcher();
actionHandler.applicationHandler =
HandlerForProtocol(dispatcher, ApplicationCommands);
actionHandler.activityHandler =
HandlerForProtocol(dispatcher, ActivityServiceCommands);
actionHandler.menuHandler = HandlerForProtocol(dispatcher, PopupMenuCommands);
actionHandler.omniboxHandler =
HandlerForProtocol(dispatcher, OmniboxCommands);
actionHandler.incognito = isIncognito;
actionHandler.navigationAgent =
WebNavigationBrowserAgent::FromBrowser(self.browser);
actionHandler.tabBasedIPHAgent =
TabBasedIPHBrowserAgent::FromBrowser(self.browser);
self.actionHandler = actionHandler;
ToolbarButtonFactory* buttonFactory =
[[ToolbarButtonFactory alloc] initWithStyle:style];
buttonFactory.actionHandler = actionHandler;
buttonFactory.visibilityConfiguration =
[[ToolbarButtonVisibilityConfiguration alloc] initWithType:type];
return buttonFactory;
}
@end