[go: up one dir, main page]

blob: b699b591834cf31acba337feb51676e69ced028a [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.
#import "ios/chrome/browser/ui/ntp/new_tab_page_coordinator.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/user_metrics.h"
#include "base/metrics/user_metrics_action.h"
#include "components/feed/core/v2/public/ios/pref_names.h"
#import "components/pref_registry/pref_registry_syncable.h"
#import "components/prefs/ios/pref_observer_bridge.h"
#import "components/prefs/pref_change_registrar.h"
#import "components/prefs/pref_service.h"
#import "components/search_engines/default_search_manager.h"
#include "ios/chrome/app/tests_hook.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#import "ios/chrome/browser/discover_feed/discover_feed_service.h"
#import "ios/chrome/browser/discover_feed/discover_feed_service_factory.h"
#import "ios/chrome/browser/main/browser.h"
#import "ios/chrome/browser/pref_names.h"
#import "ios/chrome/browser/search_engines/template_url_service_factory.h"
#import "ios/chrome/browser/signin/authentication_service_factory.h"
#import "ios/chrome/browser/signin/chrome_account_manager_service_factory.h"
#import "ios/chrome/browser/signin/identity_manager_factory.h"
#import "ios/chrome/browser/ui/commands/application_commands.h"
#import "ios/chrome/browser/ui/commands/browser_commands.h"
#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
#import "ios/chrome/browser/ui/commands/omnibox_commands.h"
#import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_feature.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.h"
#import "ios/chrome/browser/ui/content_suggestions/discover_feed_metrics_recorder.h"
#import "ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.h"
#import "ios/chrome/browser/ui/context_menu/link_preview/link_preview_coordinator.h"
#import "ios/chrome/browser/ui/main/scene_state.h"
#import "ios/chrome/browser/ui/main/scene_state_browser_agent.h"
#import "ios/chrome/browser/ui/main/scene_state_observer.h"
#import "ios/chrome/browser/ui/ntp/discover_feed_constants.h"
#import "ios/chrome/browser/ui/ntp/discover_feed_delegate.h"
#import "ios/chrome/browser/ui/ntp/discover_feed_preview_delegate.h"
#import "ios/chrome/browser/ui/ntp/discover_feed_wrapper_view_controller.h"
#import "ios/chrome/browser/ui/ntp/incognito_view_controller.h"
#import "ios/chrome/browser/ui/ntp/new_tab_page_commands.h"
#import "ios/chrome/browser/ui/ntp/new_tab_page_content_delegate.h"
#import "ios/chrome/browser/ui/ntp/new_tab_page_feature.h"
#import "ios/chrome/browser/ui/ntp/new_tab_page_view_controller.h"
#import "ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h"
#import "ios/chrome/browser/ui/settings/utils/pref_backed_boolean.h"
#import "ios/chrome/browser/url_loading/url_loading_browser_agent.h"
#import "ios/chrome/browser/voice/voice_search_availability.h"
#import "ios/chrome/common/ui/util/constraints_ui_util.h"
#import "ios/public/provider/chrome/browser/chrome_browser_provider.h"
#import "ios/public/provider/chrome/browser/discover_feed/discover_feed_observer_bridge.h"
#import "ios/public/provider/chrome/browser/discover_feed/discover_feed_provider.h"
#import "ios/public/provider/chrome/browser/discover_feed/discover_feed_view_controller_configuration.h"
#import "ios/web/public/navigation/navigation_context.h"
#import "ios/web/public/navigation/navigation_item.h"
#import "ios/web/public/navigation/navigation_manager.h"
#import "ios/web/public/web_state_observer_bridge.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface NewTabPageCoordinator () <BooleanObserver,
DiscoverFeedDelegate,
DiscoverFeedObserverBridgeDelegate,
DiscoverFeedPreviewDelegate,
NewTabPageCommands,
NewTabPageContentDelegate,
OverscrollActionsControllerDelegate,
PrefObserverDelegate,
SceneStateObserver> {
// Helper object managing the availability of the voice search feature.
VoiceSearchAvailability _voiceSearchAvailability;
// Pref observer to track changes to prefs.
std::unique_ptr<PrefObserverBridge> _prefObserverBridge;
// Registrar for pref changes notifications.
std::unique_ptr<PrefChangeRegistrar> _prefChangeRegistrar;
// Observes changes in the DiscoverFeed.
std::unique_ptr<DiscoverFeedObserverBridge>
_discoverFeedProviderObserverBridge;
}
// Coordinator for the ContentSuggestions.
@property(nonatomic, strong)
ContentSuggestionsCoordinator* contentSuggestionsCoordinator;
// View controller for the regular NTP.
@property(nonatomic, strong) NewTabPageViewController* ntpViewController;
// Mediator owned by this Coordinator.
@property(nonatomic, strong) NTPHomeMediator* ntpMediator;
// View controller wrapping the Discover feed.
@property(nonatomic, strong)
DiscoverFeedWrapperViewController* discoverFeedWrapperViewController;
// View controller for the incognito NTP.
@property(nonatomic, strong) IncognitoViewController* incognitoViewController;
// The timetick of the last time the NTP was displayed.
@property(nonatomic, assign) base::TimeTicks didAppearTime;
// Tracks the visibility of the NTP to report NTP usage metrics.
// True if the NTP view is currently displayed to the user.
@property(nonatomic, assign) BOOL visible;
// Whether the view is new tab view is currently presented (possibly in
// background). Used to report NTP usage metrics.
@property(nonatomic, assign) BOOL viewPresented;
// Wheter the scene is currently in foreground.
@property(nonatomic, assign) BOOL sceneInForeground;
// Handles interactions with the content suggestions header and the fake
// omnibox.
@property(nonatomic, strong)
ContentSuggestionsHeaderSynchronizer* headerSynchronizer;
// The ViewController displayed by this Coordinator. This is the returned
// ViewController and will contain the |containedViewController| (Which can
// change depending on Feed visibility).
@property(nonatomic, strong) UIViewController* containerViewController;
// The coordinator contained ViewController. It can be either a
// NewTabPageViewController (When the Discover Feed is being shown) or a
// ContentSuggestionsViewController (When the Discover Feed is hidden or when
// the non refactored NTP is being used.)
// TODO(crbug.com/1114792): Update this comment when the NTP refactors launches.
@property(nonatomic, strong) UIViewController* containedViewController;
// PrefService used by this Coordinator.
@property(nonatomic, assign) PrefService* prefService;
// Whether the feed is expanded or collapsed. Collapsed
// means the feed header is shown, but not any of the feed content.
@property(nonatomic, strong) PrefBackedBoolean* discoverFeedExpanded;
// The view controller representing the Discover feed.
@property(nonatomic, weak) UIViewController* discoverFeedViewController;
// The Coordinator to display previews for Discover feed websites. It also
// handles the actions related to them.
@property(nonatomic, strong) LinkPreviewCoordinator* linkPreviewCoordinator;
@end
@implementation NewTabPageCoordinator
#pragma mark - ChromeCoordinator
- (instancetype)initWithBaseViewController:(UIViewController*)viewController
browser:(Browser*)browser {
self = [super initWithBaseViewController:viewController browser:browser];
if (self) {
_containerViewController = [[UIViewController alloc] init];
_prefService =
ChromeBrowserState::FromBrowserState(browser->GetBrowserState())
->GetPrefs();
_prefChangeRegistrar = std::make_unique<PrefChangeRegistrar>();
_prefChangeRegistrar->Init(_prefService);
_prefObserverBridge.reset(new PrefObserverBridge(self));
_prefObserverBridge->ObserveChangesForPreference(
prefs::kArticlesForYouEnabled, _prefChangeRegistrar.get());
_prefObserverBridge->ObserveChangesForPreference(
prefs::kNTPContentSuggestionsEnabled, _prefChangeRegistrar.get());
_prefObserverBridge->ObserveChangesForPreference(
DefaultSearchManager::kDefaultSearchProviderDataPrefName,
_prefChangeRegistrar.get());
_discoverFeedExpanded = [[PrefBackedBoolean alloc]
initWithPrefService:_prefService
prefName:feed::prefs::kArticlesListVisible];
[_discoverFeedExpanded setObserver:self];
_discoverFeedProviderObserverBridge =
std::make_unique<DiscoverFeedObserverBridge>(self);
}
return self;
}
- (void)start {
if (self.started)
return;
DCHECK(self.browser);
DCHECK(self.webState);
DCHECK(self.toolbarDelegate);
DCHECK(!self.contentSuggestionsCoordinator);
if (self.browser->GetBrowserState()->IsOffTheRecord()) {
DCHECK(!self.incognitoViewController);
UrlLoadingBrowserAgent* URLLoader =
UrlLoadingBrowserAgent::FromBrowser(self.browser);
self.incognitoViewController =
[[IncognitoViewController alloc] initWithUrlLoader:URLLoader];
self.started = YES;
return;
}
TemplateURLService* templateURLService =
ios::TemplateURLServiceFactory::GetForBrowserState(
self.browser->GetBrowserState());
self.ntpMediator = [[NTPHomeMediator alloc]
initWithWebState:self.webState
templateURLService:templateURLService
URLLoader:UrlLoadingBrowserAgent::FromBrowser(self.browser)
authService:AuthenticationServiceFactory::GetForBrowserState(
self.browser->GetBrowserState())
identityManager:IdentityManagerFactory::GetForBrowserState(
self.browser->GetBrowserState())
accountManagerService:ChromeAccountManagerServiceFactory::
GetForBrowserState(
self.browser->GetBrowserState())
logoVendor:ios::GetChromeBrowserProvider().CreateLogoVendor(
self.browser, self.webState)
voiceSearchAvailability:&_voiceSearchAvailability];
self.ntpMediator.browser = self.browser;
self.contentSuggestionsCoordinator = [[ContentSuggestionsCoordinator alloc]
initWithBaseViewController:nil
browser:self.browser];
self.contentSuggestionsCoordinator.webState = self.webState;
self.contentSuggestionsCoordinator.toolbarDelegate = self.toolbarDelegate;
self.contentSuggestionsCoordinator.ntpMediator = self.ntpMediator;
self.contentSuggestionsCoordinator.ntpCommandHandler = self;
self.contentSuggestionsCoordinator.bubblePresenter = self.bubblePresenter;
self.contentSuggestionsCoordinator.discoverFeedDelegate = self;
DiscoverFeedMetricsRecorder* discoverFeedMetricsRecorder;
if (IsDiscoverFeedEnabled()) {
// Creating the DiscoverFeedService will start the DiscoverFeed.
DiscoverFeedService* discoverFeedService =
DiscoverFeedServiceFactory::GetForBrowserState(
self.browser->GetBrowserState());
discoverFeedMetricsRecorder =
discoverFeedService->GetDiscoverFeedMetricsRecorder();
self.contentSuggestionsCoordinator.discoverFeedMetricsRecorder =
discoverFeedMetricsRecorder;
}
self.ntpViewController = [[NewTabPageViewController alloc] init];
// Requests a Discover feed here if the correct flags and prefs are enabled.
if ([self shouldFeedBeVisible]) {
self.discoverFeedViewController = [self discoverFeed];
}
[self.contentSuggestionsCoordinator start];
[self configureNTPAsMainViewController];
self.ntpViewController.discoverFeedMetricsRecorder =
discoverFeedMetricsRecorder;
base::RecordAction(base::UserMetricsAction("MobileNTPShowMostVisited"));
SceneState* sceneState =
SceneStateBrowserAgent::FromBrowser(self.browser)->GetSceneState();
[sceneState addObserver:self];
self.sceneInForeground =
sceneState.activationLevel >= SceneActivationLevelForegroundInactive;
self.started = YES;
}
- (void)stop {
if (!self.started)
return;
// Unfocus omnibox, to prevent it from lingering when it should be dismissed
// (for example, when navigating away or when changing feed visibility).
id<OmniboxCommands> omniboxCommandHandler =
HandlerForProtocol(self.browser->GetCommandDispatcher(), OmniboxCommands);
[omniboxCommandHandler cancelOmniboxEdit];
self.viewPresented = NO;
[self updateVisible];
[self.contentSuggestionsCoordinator stop];
SceneState* sceneState =
SceneStateBrowserAgent::FromBrowser(self.browser)->GetSceneState();
[sceneState removeObserver:self];
self.contentSuggestionsCoordinator = nil;
self.incognitoViewController = nil;
self.ntpViewController = nil;
ios::GetChromeBrowserProvider()
.GetDiscoverFeedProvider()
->RemoveFeedViewController(self.discoverFeedViewController);
self.discoverFeedWrapperViewController = nil;
self.discoverFeedViewController = nil;
[self.ntpMediator shutdown];
self.ntpMediator = nil;
[self.containedViewController willMoveToParentViewController:nil];
[self.containedViewController.view removeFromSuperview];
[self.containedViewController removeFromParentViewController];
self.started = NO;
}
- (void)disconnect {
// TODO(crbug.com/1200303): Move this to stop once we stop starting/stopping
// the Coordinator when turning the feed on/off.
[self.discoverFeedExpanded setObserver:nil];
self.discoverFeedExpanded = nil;
_prefChangeRegistrar.reset();
_prefObserverBridge.reset();
_discoverFeedProviderObserverBridge.reset();
}
// Updates the visible property based on viewPresented and sceneInForeground
// properties.
// Sends metrics when NTP becomes invisible.
- (void)updateVisible {
BOOL visible = self.viewPresented && self.sceneInForeground;
if (visible == self.visible) {
return;
}
self.visible = visible;
if (self.browser->GetBrowserState()->IsOffTheRecord()) {
// Do not report metrics on incognito NTP.
return;
}
if (visible) {
self.didAppearTime = base::TimeTicks::Now();
} else {
if (!self.didAppearTime.is_null()) {
UmaHistogramMediumTimes("NewTabPage.TimeSpent",
base::TimeTicks::Now() - self.didAppearTime);
self.didAppearTime = base::TimeTicks();
}
}
}
#pragma mark - ChromeCoordinatorHelpers
// Configures |self.ntpViewController| and sets it up as the main ViewController
// managed by this Coordinator.
- (void)configureNTPAsMainViewController {
self.contentSuggestionsCoordinator.headerController.baseViewController =
self.baseViewController;
self.ntpViewController.contentSuggestionsViewController =
self.contentSuggestionsCoordinator.viewController;
self.ntpViewController.panGestureHandler = self.panGestureHandler;
self.ntpMediator.ntpViewController = self.ntpViewController;
self.discoverFeedWrapperViewController =
[[DiscoverFeedWrapperViewController alloc]
initWithDiscoverFeedViewController:self.discoverFeedViewController];
self.headerSynchronizer = [[ContentSuggestionsHeaderSynchronizer alloc]
initWithCollectionController:self.ntpViewController
headerController:self.contentSuggestionsCoordinator
.headerController];
self.ntpViewController.discoverFeedWrapperViewController =
self.discoverFeedWrapperViewController;
self.ntpViewController.overscrollDelegate = self;
self.ntpViewController.ntpContentDelegate = self;
self.ntpViewController.identityDiscButton =
[self.contentSuggestionsCoordinator.headerController identityDiscButton];
self.ntpViewController.headerController =
self.contentSuggestionsCoordinator.headerController;
self.ntpMediator.primaryViewController = self.ntpViewController;
self.ntpMediator.headerCollectionInteractionHandler = self.headerSynchronizer;
[self configureMainViewControllerUsing:self.ntpViewController];
}
// Configures the main ViewController managed by this Coordinator.
- (void)configureMainViewControllerUsing:
(UIViewController*)containedViewController {
[containedViewController
willMoveToParentViewController:self.containerViewController];
[self.containerViewController addChildViewController:containedViewController];
[self.containerViewController.view addSubview:containedViewController.view];
[containedViewController
didMoveToParentViewController:self.containerViewController];
containedViewController.view.translatesAutoresizingMaskIntoConstraints = NO;
AddSameConstraints(containedViewController.view,
self.containerViewController.view);
self.containedViewController = containedViewController;
}
#pragma mark - Properties
- (UIViewController*)viewController {
[self start];
if (self.browser->GetBrowserState()->IsOffTheRecord()) {
return self.incognitoViewController;
} else {
return self.containerViewController;
}
}
- (id<ThumbStripSupporting>)thumbStripSupporting {
return self.ntpViewController;
}
#pragma mark - Public Methods
- (void)dismissModals {
[self.contentSuggestionsCoordinator dismissModals];
}
- (void)stopScrolling {
if (!self.contentSuggestionsCoordinator) {
return;
}
[self.ntpViewController stopScrolling];
}
- (UIEdgeInsets)contentInset {
return [self.contentSuggestionsCoordinator contentInset];
}
- (CGPoint)contentOffset {
return [self.contentSuggestionsCoordinator contentOffset];
}
- (void)willUpdateSnapshot {
if (self.contentSuggestionsCoordinator.started) {
[self.ntpViewController willUpdateSnapshot];
}
}
- (void)focusFakebox {
if (self.discoverFeedViewController) {
[self.ntpViewController focusFakebox];
} else {
[self.contentSuggestionsCoordinator.headerController focusFakebox];
}
}
- (void)reload {
if (self.browser->GetBrowserState()->IsOffTheRecord()) {
return;
}
ios::GetChromeBrowserProvider().GetDiscoverFeedProvider()->RefreshFeed();
[self reloadContentSuggestions];
}
- (void)locationBarDidBecomeFirstResponder {
[self.contentSuggestionsCoordinator locationBarDidBecomeFirstResponder];
}
- (void)locationBarDidResignFirstResponder {
[self.contentSuggestionsCoordinator locationBarDidResignFirstResponder];
}
- (void)constrainDiscoverHeaderMenuButtonNamedGuide {
[self.contentSuggestionsCoordinator
constrainDiscoverHeaderMenuButtonNamedGuide];
}
- (void)ntpDidChangeVisibility:(BOOL)visible {
if (visible) {
[self.contentSuggestionsCoordinator configureStartSurfaceIfNeeded];
}
self.viewPresented = visible;
[self updateVisible];
}
#pragma mark - NewTabPageCommands
- (void)updateNTPForDiscoverFeed {
[self stop];
[self start];
[self updateDiscoverFeedLayout];
[self.containerViewController.view setNeedsLayout];
[self.containerViewController.view layoutIfNeeded];
}
- (void)updateDiscoverFeedLayout {
// If this coordinator has not finished [self start], the below will start
// viewDidLoad before the UI is ready, failing DCHECKS.
if (self.started) {
[self.containedViewController.view setNeedsLayout];
[self.containedViewController.view layoutIfNeeded];
[self.ntpViewController updateContentSuggestionForCurrentLayout];
}
}
- (void)setContentOffsetToTop {
[self.ntpViewController setContentOffsetToTop];
}
#pragma mark - LogoAnimationControllerOwnerOwner
- (id<LogoAnimationControllerOwner>)logoAnimationControllerOwner {
return [self.contentSuggestionsCoordinator
.headerController logoAnimationControllerOwner];
}
#pragma mark - SceneStateObserver
- (void)sceneState:(SceneState*)sceneState
transitionedToActivationLevel:(SceneActivationLevel)level {
self.sceneInForeground = level >= SceneActivationLevelForegroundInactive;
[self updateVisible];
}
#pragma mark - BooleanObserver
- (void)booleanDidChange:(id<ObservableBoolean>)observableBoolean {
[self updateNTPForDiscoverFeed];
}
#pragma mark - DiscoverFeedDelegate
- (UIEdgeInsets)safeAreaInsetsForDiscoverFeed {
return [SceneStateBrowserAgent::FromBrowser(self.browser)
->GetSceneState()
.window.rootViewController.view safeAreaInsets];
}
- (void)contentSuggestionsWasUpdated {
[self updateDiscoverFeedLayout];
[self setContentOffsetToTop];
}
- (void)returnToRecentTabWasAdded {
[self updateDiscoverFeedLayout];
[self setContentOffsetToTop];
}
#pragma mark - DiscoverFeedObserverBridge
- (void)onDiscoverFeedModelRecreated {
[self updateNTPForDiscoverFeed];
}
#pragma mark - DiscoverFeedPreviewDelegate
- (UIViewController*)discoverFeedPreviewWithURL:(const GURL)URL {
std::string referrerURL = base::GetFieldTrialParamValueByFeature(
kEnableDiscoverFeedPreview, kDiscoverReferrerParameter);
if (referrerURL.empty()) {
referrerURL = kDefaultDiscoverReferrer;
}
self.linkPreviewCoordinator =
[[LinkPreviewCoordinator alloc] initWithBrowser:self.browser URL:URL];
self.linkPreviewCoordinator.referrer =
web::Referrer(GURL(referrerURL), web::ReferrerPolicyDefault);
[self.linkPreviewCoordinator start];
return [self.linkPreviewCoordinator linkPreviewViewController];
}
- (void)didTapDiscoverFeedPreview {
DCHECK(self.linkPreviewCoordinator);
[self.linkPreviewCoordinator handlePreviewAction];
[self.linkPreviewCoordinator stop];
self.linkPreviewCoordinator = nil;
}
#pragma mark - OverscrollActionsControllerDelegate
- (void)overscrollActionsController:(OverscrollActionsController*)controller
didTriggerAction:(OverscrollAction)action {
// TODO(crbug.com/1045047): Use HandlerForProtocol after commands protocol
// clean up.
id<ApplicationCommands, BrowserCommands, OmniboxCommands, SnackbarCommands>
handler = static_cast<id<ApplicationCommands, BrowserCommands,
OmniboxCommands, SnackbarCommands>>(
self.browser->GetCommandDispatcher());
switch (action) {
case OverscrollAction::NEW_TAB: {
[handler openURLInNewTab:[OpenNewTabCommand command]];
} break;
case OverscrollAction::CLOSE_TAB: {
[handler closeCurrentTab];
base::RecordAction(base::UserMetricsAction("OverscrollActionCloseTab"));
} break;
case OverscrollAction::REFRESH:
[self reload];
break;
case OverscrollAction::NONE:
NOTREACHED();
break;
}
}
- (BOOL)shouldAllowOverscrollActionsForOverscrollActionsController:
(OverscrollActionsController*)controller {
return YES;
}
- (UIView*)toolbarSnapshotViewForOverscrollActionsController:
(OverscrollActionsController*)controller {
return [[self.contentSuggestionsCoordinator.headerController toolBarView]
snapshotViewAfterScreenUpdates:NO];
}
- (UIView*)headerViewForOverscrollActionsController:
(OverscrollActionsController*)controller {
return self.discoverFeedWrapperViewController.view;
}
- (CGFloat)headerInsetForOverscrollActionsController:
(OverscrollActionsController*)controller {
CGFloat topInset =
self.discoverFeedWrapperViewController.view.safeAreaInsets.top;
return self.contentSuggestionsCoordinator.viewController.collectionView
.contentSize.height +
topInset;
}
- (CGFloat)headerHeightForOverscrollActionsController:
(OverscrollActionsController*)controller {
CGFloat height =
[self.contentSuggestionsCoordinator.headerController toolBarView]
.bounds.size.height;
CGFloat topInset =
self.discoverFeedWrapperViewController.view.safeAreaInsets.top;
return height + topInset;
}
- (FullscreenController*)fullscreenControllerForOverscrollActionsController:
(OverscrollActionsController*)controller {
// Fullscreen isn't supported here.
return nullptr;
}
#pragma mark - NewTabPageContentDelegate
- (void)reloadContentSuggestions {
[self.contentSuggestionsCoordinator reload];
}
- (BOOL)isFeedVisible {
return [self shouldFeedBeVisible] && self.discoverFeedViewController;
}
#pragma mark - PrefObserverDelegate
- (void)onPreferenceChanged:(const std::string&)preferenceName {
if (preferenceName == prefs::kArticlesForYouEnabled ||
preferenceName == prefs::kNTPContentSuggestionsEnabled) {
[self updateNTPForDiscoverFeed];
}
if (preferenceName ==
DefaultSearchManager::kDefaultSearchProviderDataPrefName) {
[self defaultSearchEngineDidChange];
}
}
#pragma mark - Private
// Determines whether the feed should be fetched based on the user prefs.
- (BOOL)shouldFeedBeVisible {
BOOL isFeedEnabled =
self.prefService->GetBoolean(prefs::kArticlesForYouEnabled) &&
self.prefService->GetBoolean(prefs::kNTPContentSuggestionsEnabled);
return isFeedEnabled && [self.discoverFeedExpanded value];
}
// Creates, configures and returns a DiscoverFeed ViewController.
- (UIViewController*)discoverFeed {
if (tests_hook::DisableDiscoverFeed())
return nil;
DiscoverFeedViewControllerConfiguration* viewControllerConfig =
[[DiscoverFeedViewControllerConfiguration alloc] init];
viewControllerConfig.browser = self.browser;
viewControllerConfig.scrollDelegate = self.ntpViewController;
viewControllerConfig.previewDelegate = self;
UIViewController* discoverFeed =
ios::GetChromeBrowserProvider()
.GetDiscoverFeedProvider()
->NewFeedViewControllerWithConfiguration(viewControllerConfig);
return discoverFeed;
}
// Handles how the NTP should react when the default search engine setting is
// changed.
- (void)defaultSearchEngineDidChange {
BOOL isScrolledToTop = [self.ntpViewController isNTPScrolledToTop];
[self updateDiscoverFeedLayout];
// Ensures doodle is visible if content suggestions height changes when
// scrolled to top. Otherwise, maintain scroll position.
if (isScrolledToTop) {
[self.ntpViewController setContentOffsetToTop];
}
}
@end