Commit 0ca65b4b authored by Gauthier Ambard's avatar Gauthier Ambard Committed by Commit Bot

Merge GoogleLandingMediator into NTPHomeMediator

This CL removes GoogleLandingMediator/Consumer and moves their
functionalities in NTPHomeMediator/Consumer.

Bug: 764720
Cq-Include-Trybots: master.tryserver.chromium.mac:ios-simulator-cronet;master.tryserver.chromium.mac:ios-simulator-full-configs
Change-Id: Iae7ca5707afd04933c189391a50e384940303eb2
Reviewed-on: https://chromium-review.googlesource.com/801012Reviewed-by: default avatarOlivier Robin <olivierrobin@chromium.org>
Commit-Queue: Gauthier Ambard <gambard@chromium.org>
Cr-Commit-Position: refs/heads/master@{#521642}
parent 6ed69ac8
......@@ -43,8 +43,10 @@ source_set("content_suggestions") {
"//ios/chrome/browser/ntp_snippets",
"//ios/chrome/browser/ntp_tiles",
"//ios/chrome/browser/reading_list",
"//ios/chrome/browser/search_engines",
"//ios/chrome/browser/tabs",
"//ios/chrome/browser/ui",
"//ios/chrome/browser/ui:notifications",
"//ios/chrome/browser/ui/alert_coordinator",
"//ios/chrome/browser/ui/collection_view/cells",
"//ios/chrome/browser/ui/commands",
......@@ -66,6 +68,7 @@ source_set("content_suggestions") {
"//ios/chrome/common/app_group",
"//ios/public/provider/chrome/browser",
"//ios/public/provider/chrome/browser/images",
"//ios/public/provider/chrome/browser/ui",
"//ios/public/provider/chrome/browser/voice",
"//ios/web",
"//ui/base",
......@@ -77,11 +80,29 @@ source_set("unit_tests") {
testonly = true
sources = [
"content_suggestions_category_wrapper_unittest.mm",
"ntp_home_mediator_unittest.mm",
]
deps = [
":content_suggestions",
"//components/ntp_snippets",
"//ios/chrome/browser",
"//ios/chrome/browser/browser_state:test_support",
"//ios/chrome/browser/ntp_snippets",
"//ios/chrome/browser/search_engines",
"//ios/chrome/browser/ui",
"//ios/chrome/browser/ui:notifications",
"//ios/chrome/browser/ui/collection_view",
"//ios/chrome/browser/ui/commands",
"//ios/chrome/browser/ui/content_suggestions",
"//ios/chrome/browser/ui/content_suggestions/cells",
"//ios/chrome/browser/ui/toolbar/test",
"//ios/chrome/browser/web_state_list",
"//ios/chrome/browser/web_state_list:test_support",
"//ios/public/provider/chrome/browser/ui",
"//ios/web/public/test",
"//ios/web/public/test/fakes",
"//testing/gtest",
"//third_party/ocmock",
]
configs += [ "//build/config/compiler:enable_arc" ]
}
......@@ -21,6 +21,7 @@
#include "ios/chrome/browser/ntp_tiles/ios_most_visited_sites_factory.h"
#include "ios/chrome/browser/pref_names.h"
#include "ios/chrome/browser/reading_list/reading_list_model_factory.h"
#include "ios/chrome/browser/search_engines/template_url_service_factory.h"
#import "ios/chrome/browser/ui/commands/browser_commands.h"
#import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_data_sink.h"
......@@ -28,12 +29,13 @@
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller_audience.h"
#import "ios/chrome/browser/ui/content_suggestions/ntp_home_constant.h"
#import "ios/chrome/browser/ui/ntp/google_landing_mediator.h"
#import "ios/chrome/browser/ui/ntp/new_tab_page_header_constants.h"
#import "ios/chrome/browser/ui/ntp/notification_promo_whats_new.h"
#import "ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h"
#import "ios/chrome/browser/ui/uikit_ui_util.h"
#import "ios/chrome/browser/web_state_list/web_state_list.h"
#include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
#import "ios/public/provider/chrome/browser/voice/voice_search_provider.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
......@@ -47,7 +49,6 @@
ContentSuggestionsViewController* suggestionsViewController;
@property(nonatomic, strong)
ContentSuggestionsMediator* contentSuggestionsMediator;
@property(nonatomic, strong) GoogleLandingMediator* googleLandingMediator;
@property(nonatomic, strong)
ContentSuggestionsHeaderSynchronizer* headerCollectionInteractionHandler;
@property(nonatomic, strong) ContentSuggestionsMetricsRecorder* metricsRecorder;
......@@ -69,7 +70,6 @@
@synthesize headerCollectionInteractionHandler =
_headerCollectionInteractionHandler;
@synthesize headerController = _headerController;
@synthesize googleLandingMediator = _googleLandingMediator;
@synthesize webStateList = _webStateList;
@synthesize dispatcher = _dispatcher;
@synthesize delegate = _delegate;
......@@ -104,22 +104,24 @@
ntp_home::RecordNTPImpression(ntp_home::LOCAL_SUGGESTIONS);
}
self.NTPMediator = [[NTPHomeMediator alloc] init];
self.headerController = [[ContentSuggestionsHeaderViewController alloc] init];
self.NTPMediator = [[NTPHomeMediator alloc]
initWithWebStateList:self.webStateList
templateURLService:ios::TemplateURLServiceFactory::GetForBrowserState(
self.browserState)
logoVendor:ios::GetChromeBrowserProvider()->CreateLogoVendor(
self.browserState, self.dispatcher)];
BOOL voiceSearchEnabled = ios::GetChromeBrowserProvider()
->GetVoiceSearchProvider()
->IsVoiceSearchEnabled();
self.headerController = [[ContentSuggestionsHeaderViewController alloc]
initWithVoiceSearchEnabled:voiceSearchEnabled];
self.headerController.dispatcher = self.dispatcher;
self.headerController.commandHandler = self.NTPMediator;
self.headerController.delegate = self.NTPMediator;
self.headerController.readingListModel =
ReadingListModelFactory::GetForBrowserState(self.browserState);
self.googleLandingMediator =
[[GoogleLandingMediator alloc] initWithBrowserState:self.browserState
webStateList:self.webStateList];
self.googleLandingMediator.consumer = self.headerController;
self.googleLandingMediator.dispatcher = self.dispatcher;
[self.googleLandingMediator setUp];
favicon::LargeIconService* largeIconService =
IOSChromeLargeIconServiceFactory::GetForBrowserState(self.browserState);
LargeIconCache* cache =
......@@ -151,7 +153,7 @@
self.suggestionsViewController.containsToolbar = YES;
self.suggestionsViewController.dispatcher = self.dispatcher;
self.NTPMediator.webState = self.webStateList->GetActiveWebState();
self.NTPMediator.consumer = self.headerController;
self.NTPMediator.dispatcher = self.dispatcher;
self.NTPMediator.NTPMetrics =
[[NTPHomeMetrics alloc] initWithBrowserState:self.browserState];
......@@ -176,8 +178,6 @@
self.NTPMediator = nil;
self.contentSuggestionsMediator = nil;
self.headerController = nil;
[self.googleLandingMediator shutdown];
self.googleLandingMediator = nil;
_visible = NO;
}
......
......@@ -9,7 +9,7 @@
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_header_controlling.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_header_provider.h"
#import "ios/chrome/browser/ui/ntp/google_landing_consumer.h"
#import "ios/chrome/browser/ui/content_suggestions/ntp_home_consumer.h"
#import "ios/chrome/browser/ui/toolbar/toolbar_owner.h"
#import "ios/public/provider/chrome/browser/voice/logo_animation_controller.h"
......@@ -28,10 +28,19 @@ class ReadingListModel;
@interface ContentSuggestionsHeaderViewController
: UIViewController<ContentSuggestionsHeaderControlling,
ContentSuggestionsHeaderProvider,
GoogleLandingConsumer,
NTPHomeConsumer,
ToolbarOwner,
LogoAnimationControllerOwnerOwner>
// Whether |voiceSearchIsEnabled|.
- (instancetype)initWithVoiceSearchEnabled:(BOOL)voiceSearchIsEnabled
NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithNibName:(NSString*)nibNameOrNil
bundle:(NSBundle*)nibBundleOrNil NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
- (instancetype)init NS_UNAVAILABLE;
@property(nonatomic, weak)
id<ApplicationCommands, BrowserCommands, OmniboxFocuser, UrlLoader>
dispatcher;
......
......@@ -18,12 +18,12 @@
#import "ios/chrome/browser/ui/content_suggestions/ntp_home_constant.h"
#import "ios/chrome/browser/ui/ntp/new_tab_page_header_constants.h"
#import "ios/chrome/browser/ui/ntp/new_tab_page_header_view.h"
//#import "ios/chrome/browser/ui/toolbar/web_toolbar_controller.h"
#import "ios/chrome/browser/ui/toolbar/omnibox_focuser.h"
#import "ios/chrome/browser/ui/uikit_ui_util.h"
#import "ios/chrome/browser/ui/url_loader.h"
#import "ios/chrome/browser/ui/util/constraints_ui_util.h"
#include "ios/chrome/grit/ios_strings.h"
#include "ios/public/provider/chrome/browser/ui/logo_vendor.h"
#include "ui/base/l10n/l10n_util.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
......@@ -103,6 +103,14 @@ const CGFloat kHintLabelSidePadding = 12;
#pragma mark - Public
- (instancetype)initWithVoiceSearchEnabled:(BOOL)voiceSearchIsEnabled {
self = [super initWithNibName:nil bundle:nil];
if (self) {
_voiceSearchIsEnabled = voiceSearchIsEnabled;
}
return self;
}
- (UIView*)toolBarView {
return self.headerView.toolBarView;
}
......
......@@ -15,20 +15,20 @@ namespace ntp_snippets {
class ContentSuggestionsService;
}
namespace web {
class WebState;
}
@protocol ApplicationCommands;
@protocol BrowserCommands;
@class ContentSuggestionsHeaderViewController;
@class ContentSuggestionsMediator;
@class ContentSuggestionsMetricsRecorder;
@class ContentSuggestionsViewController;
@protocol LogoVendor;
@protocol OmniboxFocuser;
@protocol NTPHomeConsumer;
@class NTPHomeMetrics;
class TemplateURLService;
@protocol SnackbarCommands;
@protocol UrlLoader;
class WebStateList;
// Mediator for the NTP Home panel, handling the interactions with the
// suggestions.
......@@ -37,23 +37,34 @@ class WebState;
ContentSuggestionsGestureCommands,
ContentSuggestionsHeaderViewControllerDelegate>
// The web state associated with this NTP.
@property(nonatomic, assign) web::WebState* webState;
- (nullable instancetype)
initWithWebStateList:(nonnull WebStateList*)webStateList
templateURLService:(nonnull TemplateURLService*)templateURLService
logoVendor:(nonnull id<LogoVendor>)logoVendor
NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)init NS_UNAVAILABLE;
// Dispatcher.
@property(nonatomic, weak) id<BrowserCommands, SnackbarCommands, UrlLoader>
@property(nonatomic, weak, nullable)
id<BrowserCommands, SnackbarCommands, UrlLoader>
dispatcher;
// Suggestions service used to get the suggestions.
@property(nonatomic, assign)
@property(nonatomic, assign, nonnull)
ntp_snippets::ContentSuggestionsService* suggestionsService;
// Recorder for the metrics related to ContentSuggestions.
@property(nonatomic, strong) ContentSuggestionsMetricsRecorder* metricsRecorder;
@property(nonatomic, strong, nullable)
ContentSuggestionsMetricsRecorder* metricsRecorder;
// Recorder for the metrics related to the NTP.
@property(nonatomic, strong) NTPHomeMetrics* NTPMetrics;
@property(nonatomic, strong, nullable) NTPHomeMetrics* NTPMetrics;
// View Controller displaying the suggestions.
@property(nonatomic, weak)
@property(nonatomic, weak, nullable)
ContentSuggestionsViewController* suggestionsViewController;
// Mediator for the ContentSuggestions.
@property(nonatomic, weak) ContentSuggestionsMediator* suggestionsMediator;
@property(nonatomic, strong, nonnull)
ContentSuggestionsMediator* suggestionsMediator;
// Consumer for this mediator.
@property(nonatomic, weak, nullable) id<NTPHomeConsumer> consumer;
// Inits the mediator.
- (void)setUp;
......
......@@ -15,6 +15,7 @@
#import "ios/chrome/browser/content_suggestions/content_suggestions_metrics_recorder.h"
#import "ios/chrome/browser/content_suggestions/ntp_home_metrics.h"
#import "ios/chrome/browser/metrics/new_tab_page_uma.h"
#import "ios/chrome/browser/search_engines/search_engine_observer_bridge.h"
#import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h"
#import "ios/chrome/browser/ui/commands/browser_commands.h"
#import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
......@@ -24,12 +25,16 @@
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller_audience.h"
#import "ios/chrome/browser/ui/content_suggestions/ntp_home_consumer.h"
#import "ios/chrome/browser/ui/favicon/favicon_attributes.h"
#import "ios/chrome/browser/ui/location_bar_notification_names.h"
#include "ios/chrome/browser/ui/ntp/metrics.h"
#import "ios/chrome/browser/ui/ntp/new_tab_page_header_constants.h"
#import "ios/chrome/browser/ui/ntp/notification_promo_whats_new.h"
#import "ios/chrome/browser/ui/uikit_ui_util.h"
#import "ios/chrome/browser/ui/url_loader.h"
#import "ios/chrome/browser/web_state_list/web_state_list.h"
#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h"
#include "ios/chrome/grit/ios_strings.h"
#import "ios/third_party/material_components_ios/src/components/Snackbar/src/MaterialSnackbar.h"
#import "ios/web/public/navigation_item.h"
......@@ -55,17 +60,33 @@ const char kBookmarkCommand[] = "bookmark";
const char kRateThisAppCommand[] = "ratethisapp";
} // namespace
@interface NTPHomeMediator ()<CRWWebStateObserver> {
@interface NTPHomeMediator ()<CRWWebStateObserver,
SearchEngineObserving,
WebStateListObserving> {
std::unique_ptr<web::WebStateObserverBridge> _webStateObserver;
// Observes the WebStateList so that this mediator can update the UI when the
// active WebState changes.
std::unique_ptr<WebStateListObserverBridge> _webStateListObserver;
// Listen for default search engine changes.
std::unique_ptr<SearchEngineObserverBridge> _searchEngineObserver;
}
@property(nonatomic, strong) AlertCoordinator* alertCoordinator;
// The WebStateList that is being observed by this mediator.
@property(nonatomic, assign, readonly) WebStateList* webStateList;
// TemplateURL used to get the search engine.
@property(nonatomic, assign) TemplateURLService* templateURLService;
// Logo vendor to display the doodle on the NTP.
@property(nonatomic, strong) id<LogoVendor> logoVendor;
// The web state associated with this NTP.
@property(nonatomic, assign) web::WebState* webState;
@end
@implementation NTPHomeMediator
@synthesize webState = _webState;
@synthesize consumer = _consumer;
@synthesize dispatcher = _dispatcher;
@synthesize suggestionsService = _suggestionsService;
@synthesize NTPMetrics = _NTPMetrics;
......@@ -73,6 +94,26 @@ const char kRateThisAppCommand[] = "ratethisapp";
@synthesize suggestionsMediator = _suggestionsMediator;
@synthesize alertCoordinator = _alertCoordinator;
@synthesize metricsRecorder = _metricsRecorder;
@synthesize logoVendor = _logoVendor;
@synthesize templateURLService = _templateURLService;
@synthesize webStateList = _webStateList;
- (instancetype)initWithWebStateList:(WebStateList*)webStateList
templateURLService:(TemplateURLService*)templateURLService
logoVendor:(id<LogoVendor>)logoVendor {
self = [super init];
if (self) {
_webStateList = webStateList;
_webStateListObserver = base::MakeUnique<WebStateListObserverBridge>(self);
_webStateList->AddObserver(_webStateListObserver.get());
_templateURLService = templateURLService;
// Listen for default search engine changes.
_searchEngineObserver = std::make_unique<SearchEngineObserverBridge>(
self, self.templateURLService);
_logoVendor = logoVendor;
}
return self;
}
- (void)dealloc {
if (_webState && _webStateObserver) {
......@@ -86,13 +127,39 @@ const char kRateThisAppCommand[] = "ratethisapp";
DCHECK(!_webStateObserver);
DCHECK(self.suggestionsService);
[self.consumer setTabCount:self.webStateList->count()];
self.webState = self.webStateList->GetActiveWebState();
_webStateObserver = std::make_unique<web::WebStateObserverBridge>(self);
if (_webState) {
_webState->AddObserver(_webStateObserver.get());
if (self.webState) {
self.webState->AddObserver(_webStateObserver.get());
web::NavigationManager* navigationManager =
self.webState->GetNavigationManager();
[self.consumer setCanGoForward:navigationManager->CanGoForward()];
[self.consumer setCanGoBack:navigationManager->CanGoBack()];
}
[self.consumer setLogoVendor:self.logoVendor];
self.templateURLService->Load();
[self searchEngineChanged];
// Set up notifications;
NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
[defaultCenter addObserver:self.consumer
selector:@selector(locationBarBecomesFirstResponder)
name:kLocationBarBecomesFirstResponderNotification
object:nil];
[defaultCenter addObserver:self.consumer
selector:@selector(locationBarResignsFirstResponder)
name:kLocationBarResignsFirstResponderNotification
object:nil];
}
- (void)shutdown {
_webStateList->RemoveObserver(_webStateListObserver.get());
[[NSNotificationCenter defaultCenter] removeObserver:self.consumer];
_searchEngineObserver.reset();
DCHECK(_webStateObserver);
if (_webState) {
_webState->RemoveObserver(_webStateObserver.get());
......@@ -138,9 +205,8 @@ const char kRateThisAppCommand[] = "ratethisapp";
}
- (void)webStateDestroyed:(web::WebState*)webState {
DCHECK_EQ(_webState, webState);
_webState->RemoveObserver(_webStateObserver.get());
_webState = nullptr;
DCHECK_EQ(self.webState, webState);
self.webState = nullptr;
}
#pragma mark - ContentSuggestionsCommands
......@@ -236,7 +302,7 @@ const char kRateThisAppCommand[] = "ratethisapp";
self.alertCoordinator = nil;
}
// TODO(crbug.com/761096) : Promo handling should be DRY and tested.
// TODO(crbug.com/761096) : Promo handling should be tested.
- (void)handlePromoTapped {
NotificationPromoWhatsNew* notificationPromo =
[self.suggestionsMediator notificationPromo];
......@@ -365,6 +431,53 @@ const char kRateThisAppCommand[] = "ratethisapp";
return self.suggestionsViewController.scrolledToTop;
}
#pragma mark - WebStateListObserving
- (void)webStateList:(WebStateList*)webStateList
didInsertWebState:(web::WebState*)webState
atIndex:(int)index
activating:(BOOL)activating {
[self.consumer setTabCount:self.webStateList->count()];
}
- (void)webStateList:(WebStateList*)webStateList
didDetachWebState:(web::WebState*)webState
atIndex:(int)atIndex {
[self.consumer setTabCount:self.webStateList->count()];
}
// If the actual webState associated with this mediator were passed in, this
// would not be necessary. However, since the active webstate can change when
// the new tab page is created (and animated in), listen for changes here and
// always display what's active.
- (void)webStateList:(WebStateList*)webStateList
didChangeActiveWebState:(web::WebState*)newWebState
oldWebState:(web::WebState*)oldWebState
atIndex:(int)atIndex
userAction:(BOOL)userAction {
if (newWebState) {
self.webState = newWebState;
web::NavigationManager* navigationManager =
newWebState->GetNavigationManager();
[self.consumer setCanGoForward:navigationManager->CanGoForward()];
[self.consumer setCanGoBack:navigationManager->CanGoBack()];
}
}
#pragma mark - SearchEngineObserving
- (void)searchEngineChanged {
BOOL showLogo = NO;
const TemplateURL* defaultURL =
self.templateURLService->GetDefaultSearchProvider();
if (defaultURL) {
showLogo = defaultURL->GetEngineType(
self.templateURLService->search_terms_data()) ==
SEARCH_ENGINE_GOOGLE;
}
[self.consumer setLogoIsShowing:showLogo];
}
#pragma mark - Private
// Opens the |URL| in a new tab |incognito| or not.
......
// Copyright 2017 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/content_suggestions/ntp_home_mediator.h"
#include "base/memory/ptr_util.h"
#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
#include "ios/chrome/browser/chrome_url_constants.h"
#include "ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.h"
#include "ios/chrome/browser/search_engines/template_url_service_factory.h"
#import "ios/chrome/browser/ui/collection_view/collection_view_controller.h"
#import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
#import "ios/chrome/browser/ui/commands/browser_commands.h"
#import "ios/chrome/browser/ui/commands/snackbar_commands.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h"
#import "ios/chrome/browser/ui/content_suggestions/ntp_home_consumer.h"
#import "ios/chrome/browser/ui/location_bar_notification_names.h"
#import "ios/chrome/browser/ui/toolbar/test/toolbar_test_navigation_manager.h"
#import "ios/chrome/browser/ui/url_loader.h"
#include "ios/chrome/browser/web_state_list/fake_web_state_list_delegate.h"
#include "ios/chrome/browser/web_state_list/web_state_list.h"
#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h"
#import "ios/chrome/browser/web_state_list/web_state_opener.h"
#import "ios/public/provider/chrome/browser/ui/logo_vendor.h"
#import "ios/web/public/test/fakes/test_web_state.h"
#include "ios/web/public/test/test_web_thread_bundle.h"
#import "testing/platform_test.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#include "third_party/ocmock/gtest_support.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@protocol
NTPHomeMediatorDispatcher<BrowserCommands, SnackbarCommands, UrlLoader>
@end
namespace {
static const int kNumberOfWebStates = 3;
}
class NTPHomeMediatorTest : public PlatformTest {
public:
NTPHomeMediatorTest() {
TestChromeBrowserState::Builder test_cbs_builder;
test_cbs_builder.AddTestingFactory(
ios::TemplateURLServiceFactory::GetInstance(),
ios::TemplateURLServiceFactory::GetDefaultFactory());
test_cbs_builder.AddTestingFactory(
IOSChromeContentSuggestionsServiceFactory::GetInstance(),
IOSChromeContentSuggestionsServiceFactory::GetDefaultFactory());
chrome_browser_state_ = test_cbs_builder.Build();
std::unique_ptr<ToolbarTestNavigationManager> navigation_manager =
base::MakeUnique<ToolbarTestNavigationManager>();
navigation_manager_ = navigation_manager.get();
test_web_state_ = std::make_unique<web::TestWebState>();
test_web_state_->SetNavigationManager(std::move(navigation_manager));
web_state_ = test_web_state_.get();
SetUpWebStateList();
logo_vendor_ = OCMProtocolMock(@protocol(LogoVendor));
dispatcher_ = OCMProtocolMock(@protocol(NTPHomeMediatorDispatcher));
suggestions_view_controller_ =
OCMClassMock([ContentSuggestionsViewController class]);
mediator_ = [[NTPHomeMediator alloc]
initWithWebStateList:web_state_list_.get()
templateURLService:ios::TemplateURLServiceFactory::GetForBrowserState(
chrome_browser_state_.get())
logoVendor:logo_vendor_];
mediator_.suggestionsService =
IOSChromeContentSuggestionsServiceFactory::GetForBrowserState(
chrome_browser_state_.get());
mediator_.dispatcher = dispatcher_;
mediator_.suggestionsViewController = suggestions_view_controller_;
consumer_ = OCMProtocolMock(@protocol(NTPHomeConsumer));
mediator_.consumer = consumer_;
}
// Explicitly disconnect the mediator so there won't be any WebStateList
// observers when web_state_list_ gets dealloc.
~NTPHomeMediatorTest() override { [mediator_ shutdown]; }
protected:
void SetUpWebStateList() {
web_state_list_ = base::MakeUnique<WebStateList>(&web_state_list_delegate_);
web_state_list_->InsertWebState(0, std::move(test_web_state_),
WebStateList::INSERT_FORCE_INDEX,
WebStateOpener());
web_state_list_->ActivateWebStateAt(0);
for (int i = 1; i < kNumberOfWebStates; i++) {
auto web_state = base::MakeUnique<web::TestWebState>();
GURL url("http://test/" + std::to_string(i));
web_state->SetCurrentURL(url);
web_state_list_->InsertWebState(i, std::move(web_state),
WebStateList::INSERT_FORCE_INDEX,
WebStateOpener());
}
}
web::TestWebThreadBundle thread_bundle_;
std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
id consumer_;
id logo_vendor_;
id dispatcher_;
id suggestions_view_controller_;
NTPHomeMediator* mediator_;
web::TestWebState* web_state_;
ToolbarTestNavigationManager* navigation_manager_;
std::unique_ptr<WebStateList> web_state_list_;
FakeWebStateListDelegate web_state_list_delegate_;
private:
std::unique_ptr<web::TestWebState> test_web_state_;
};
// Tests that the consumer has the right value set up.
TEST_F(NTPHomeMediatorTest, TestConsumerSetup) {
// Setup.
navigation_manager_->set_can_go_forward(true);
navigation_manager_->set_can_go_back(false);
OCMExpect([consumer_ setTabCount:kNumberOfWebStates]);
OCMExpect([consumer_ setLogoVendor:logo_vendor_]);
OCMExpect([consumer_ setCanGoForward:YES]);
OCMExpect([consumer_ setCanGoBack:NO]);
OCMExpect([consumer_ setLogoIsShowing:YES]);
// Action.
[mediator_ setUp];
// Tests.
EXPECT_OCMOCK_VERIFY(consumer_);
}
// Tests that the consumer is notified when the location bar is focused.
TEST_F(NTPHomeMediatorTest, TestConsumerNotificationFocus) {
// Setup.
[mediator_ setUp];
OCMExpect([consumer_ locationBarBecomesFirstResponder]);
// Action.
[[NSNotificationCenter defaultCenter]
postNotificationName:kLocationBarBecomesFirstResponderNotification
object:nil];
// Test.
EXPECT_OCMOCK_VERIFY(consumer_);
}
// Tests that the consumer is notified when the location bar is unfocused.
TEST_F(NTPHomeMediatorTest, TestConsumerNotificationUnfocus) {
// Setup.
[mediator_ setUp];
OCMExpect([consumer_ locationBarResignsFirstResponder]);
// Action.
[[NSNotificationCenter defaultCenter]
postNotificationName:kLocationBarResignsFirstResponderNotification
object:nil];
// Test.
EXPECT_OCMOCK_VERIFY(consumer_);
}
// Tests that the consumer is notified when the number of tab increases.
TEST_F(NTPHomeMediatorTest, TestTabCountInsert) {
// Setup.
[mediator_ setUp];
OCMExpect([consumer_ setTabCount:kNumberOfWebStates + 1]);
// Action.
auto web_state = base::MakeUnique<web::TestWebState>();
web_state_list_->InsertWebState(1, std::move(web_state),
WebStateList::INSERT_FORCE_INDEX,
WebStateOpener());
// Test.
EXPECT_OCMOCK_VERIFY(consumer_);
}
// Tests that the consumer is notified when the number of tab decreases.
TEST_F(NTPHomeMediatorTest, TestTabCountDetach) {
// Setup.
[mediator_ setUp];
OCMExpect([consumer_ setTabCount:kNumberOfWebStates - 1]);
// Action.
web_state_list_->DetachWebStateAt(1);
// Test.
EXPECT_OCMOCK_VERIFY(consumer_);
}
// Tests that the consumer is notified when the active web state changes.
TEST_F(NTPHomeMediatorTest, TestChangeActiveWebState) {
// Setup.
[mediator_ setUp];
std::unique_ptr<ToolbarTestNavigationManager> navigation_manager =
base::MakeUnique<ToolbarTestNavigationManager>();
ToolbarTestNavigationManager* nav = navigation_manager.get();
std::unique_ptr<web::TestWebState> web_state =
std::make_unique<web::TestWebState>();
web_state->SetNavigationManager(std::move(navigation_manager));
nav->set_can_go_back(true);
nav->set_can_go_forward(false);
web_state_list_->InsertWebState(1, std::move(web_state),
WebStateList::INSERT_FORCE_INDEX,
WebStateOpener());
OCMExpect([consumer_ setCanGoForward:NO]);
OCMExpect([consumer_ setCanGoBack:YES]);
// Action.
web_state_list_->ActivateWebStateAt(1);
// Test.
EXPECT_OCMOCK_VERIFY(consumer_);
}
// Tests that the command is sent to the dispatcher when opening the Reading
// List.
TEST_F(NTPHomeMediatorTest, TestOpenReadingList) {
// Setup.
[mediator_ setUp];
OCMExpect([dispatcher_ showReadingList]);
// Action.
[mediator_ openReadingList];
// Test.
EXPECT_OCMOCK_VERIFY(dispatcher_);
}
// Tests that the command is sent to the dispatcher when opening a suggestion.
TEST_F(NTPHomeMediatorTest, TestOpenPage) {
// Setup.
[mediator_ setUp];
GURL url = GURL("http://chromium.org");
NSIndexPath* indexPath = [NSIndexPath indexPathForItem:0 inSection:0];
ContentSuggestionsItem* item =
[[ContentSuggestionsItem alloc] initWithType:0
title:@"test item"
url:url];
id model = OCMClassMock([CollectionViewModel class]);
OCMStub([suggestions_view_controller_ collectionViewModel]).andReturn(model);
OCMStub([model itemAtIndexPath:indexPath]).andReturn(item);
OCMExpect([[dispatcher_ ignoringNonObjectArgs]
loadURL:url
referrer:web::Referrer()
transition:ui::PAGE_TRANSITION_AUTO_BOOKMARK
rendererInitiated:NO]);
// Action.
[mediator_ openPageForItemAtIndexPath:indexPath];
// Test.
EXPECT_OCMOCK_VERIFY(dispatcher_);
}
// Tests that the command is sent to the dispatcher when opening a most visited.
TEST_F(NTPHomeMediatorTest, TestOpenMostVisited) {
// Setup.
[mediator_ setUp];
GURL url = GURL("http://chromium.org");
ContentSuggestionsMostVisitedItem* item =
[[ContentSuggestionsMostVisitedItem alloc] initWithType:0];
item.URL = url;
OCMExpect([[dispatcher_ ignoringNonObjectArgs]
loadURL:url
referrer:web::Referrer()
transition:ui::PAGE_TRANSITION_AUTO_BOOKMARK
rendererInitiated:NO]);
// Action.
[mediator_ openMostVisitedItem:item atIndex:0];
// Test.
EXPECT_OCMOCK_VERIFY(dispatcher_);
}
......@@ -25,6 +25,7 @@ source_set("content_suggestions") {
"content_suggestions_view_controller.h",
"content_suggestions_view_controller.mm",
"content_suggestions_view_controller_audience.h",
"ntp_home_consumer.h",
]
deps = [
":content_suggestions_constant",
......
......@@ -2,18 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_CHROME_BROWSER_UI_NTP_GOOGLE_LANDING_CONSUMER_H_
#define IOS_CHROME_BROWSER_UI_NTP_GOOGLE_LANDING_CONSUMER_H_
#ifndef IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_NTP_HOME_CONSUMER_H_
#define IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_NTP_HOME_CONSUMER_H_
#import <Foundation/Foundation.h>
// TODO(crbug.com/694750): Remove these two when the types below are changed.
#include "components/ntp_tiles/ntp_tile.h"
#include "ios/public/provider/chrome/browser/images/whats_new_icon.h"
#include "ios/public/provider/chrome/browser/ui/logo_vendor.h"
@protocol LogoVendor;
// Handles google landing controller update notifications.
@protocol GoogleLandingConsumer<NSObject>
// Handles NTP Home update notifications.
@protocol NTPHomeConsumer<NSObject>
// Whether the Google logo or doodle is being shown.
- (void)setLogoIsShowing:(BOOL)logoIsShowing;
......@@ -21,19 +18,15 @@
// Exposes view and methods to drive the doodle.
- (void)setLogoVendor:(id<LogoVendor>)logoVendor;
// |YES| if this consumer is has voice search enabled.
- (void)setVoiceSearchIsEnabled:(BOOL)voiceSearchIsEnabled;
// The number of tabs to show in the google landing fake toolbar.
// The number of tabs to show in the NTP fake toolbar.
- (void)setTabCount:(int)tabCount;
// |YES| if the google landing toolbar can show the forward arrow.
// |YES| if the NTP toolbar can show the forward arrow.
- (void)setCanGoForward:(BOOL)canGoForward;
// |YES| if the google landing toolbar can show the back arrow.
// |YES| if the NTP toolbar can show the back arrow.
- (void)setCanGoBack:(BOOL)canGoBack;
// TODO(crbug.com/694750): These two calls can be made with dispatcher instead.
// The location bar has lost focus.
- (void)locationBarResignsFirstResponder;
......@@ -42,4 +35,4 @@
@end
#endif // IOS_CHROME_BROWSER_UI_NTP_GOOGLE_LANDING_CONSUMER_H_
#endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_NTP_HOME_CONSUMER_H_
......@@ -80,9 +80,6 @@ source_set("ntp_internal") {
sources = [
"centering_scrollview.h",
"centering_scrollview.mm",
"google_landing_consumer.h",
"google_landing_mediator.h",
"google_landing_mediator.mm",
"incognito_view.h",
"incognito_view.mm",
"incognito_view_controller.h",
......
// Copyright 2017 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.
#ifndef IOS_CHROME_BROWSER_UI_NTP_GOOGLE_LANDING_MEDIATOR_H_
#define IOS_CHROME_BROWSER_UI_NTP_GOOGLE_LANDING_MEDIATOR_H_
#import <Foundation/Foundation.h>
@protocol BrowserCommands;
@protocol GoogleLandingConsumer;
@protocol OmniboxFocuser;
@protocol UrlLoader;
class WebStateList;
namespace ios {
class ChromeBrowserState;
}
// A mediator object that provides various data sources for google landing.
@interface GoogleLandingMediator : NSObject
- (nullable instancetype)
initWithBrowserState:(nonnull ios::ChromeBrowserState*)browserState
webStateList:(nonnull WebStateList*)webStateList
NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)init NS_UNAVAILABLE;
// Consumer to handle google landing update notifications.
@property(nonatomic, weak, nullable) id<GoogleLandingConsumer> consumer;
// The dispatcher for this mediator.
@property(nonatomic, weak, nullable) id<BrowserCommands, UrlLoader> dispatcher;
// Perform initial setup. Needs to be called before using this object.
- (void)setUp;
// Stop listening to any observers and other cleanup functionality.
- (void)shutdown;
@end
#endif // IOS_CHROME_BROWSER_UI_NTP_GOOGLE_LANDING_MEDIATOR_H_
// Copyright 2017 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/google_landing_mediator.h"
#include "base/mac/bind_objc_block.h"
#include "base/metrics/user_metrics.h"
#include "base/metrics/user_metrics_action.h"
#include "base/strings/sys_string_conversions.h"
#include "base/task/cancelable_task_tracker.h"
#include "components/favicon/core/fallback_url_util.h"
#include "components/favicon/core/large_icon_service.h"
#include "components/favicon_base/fallback_icon_style.h"
#include "components/ntp_tiles/metrics.h"
#include "components/ntp_tiles/most_visited_sites.h"
#include "components/ntp_tiles/ntp_tile.h"
#include "components/search_engines/template_url_service.h"
#include "components/search_engines/template_url_service_observer.h"
#include "ios/chrome/browser/application_context.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#include "ios/chrome/browser/favicon/ios_chrome_large_icon_cache_factory.h"
#include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h"
#include "ios/chrome/browser/favicon/large_icon_cache.h"
#import "ios/chrome/browser/metrics/new_tab_page_uma.h"
#include "ios/chrome/browser/ntp_tiles/ios_most_visited_sites_factory.h"
#import "ios/chrome/browser/ntp_tiles/most_visited_sites_observer_bridge.h"
#include "ios/chrome/browser/reading_list/reading_list_model_factory.h"
#import "ios/chrome/browser/search_engines/search_engine_observer_bridge.h"
#include "ios/chrome/browser/search_engines/template_url_service_factory.h"
#import "ios/chrome/browser/ui/browser_view_controller.h"
#include "ios/chrome/browser/ui/commands/browser_commands.h"
#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
#import "ios/chrome/browser/ui/favicon/favicon_attributes_with_payload.h"
#import "ios/chrome/browser/ui/location_bar_notification_names.h"
#import "ios/chrome/browser/ui/ntp/google_landing_consumer.h"
#include "ios/chrome/browser/ui/ntp/metrics.h"
#import "ios/chrome/browser/ui/ntp/notification_promo_whats_new.h"
#include "ios/chrome/browser/ui/ntp/ntp_tile_saver.h"
#import "ios/chrome/browser/ui/url_loader.h"
#import "ios/chrome/browser/web_state_list/web_state_list.h"
#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h"
#include "ios/chrome/common/app_group/app_group_constants.h"
#include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
#include "ios/public/provider/chrome/browser/voice/voice_search_provider.h"
#include "ios/web/public/web_state/web_state.h"
#include "skia/ext/skia_utils_ios.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface GoogleLandingMediator ()<SearchEngineObserving,
WebStateListObserving> {
// The ChromeBrowserState associated with this mediator.
ios::ChromeBrowserState* _browserState; // Weak.
// Controller to fetch and show doodles or a default Google logo.
id<LogoVendor> _doodleController;
// Listen for default search engine changes.
std::unique_ptr<SearchEngineObserverBridge> _observer;
TemplateURLService* _templateURLService; // weak
// Observes the WebStateList so that this mediator can update the UI when the
// active WebState changes.
std::unique_ptr<WebStateListObserverBridge> _webStateListObserver;
}
// The WebStateList that is being observed by this mediator.
@property(nonatomic, assign, readonly) WebStateList* webStateList;
@end
@implementation GoogleLandingMediator
@synthesize webStateList = _webStateList;
@synthesize consumer = _consumer;
@synthesize dispatcher = _dispatcher;
- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState
webStateList:(WebStateList*)webStateList {
self = [super init];
if (self) {
_browserState = browserState;
_webStateList = webStateList;
_webStateListObserver = base::MakeUnique<WebStateListObserverBridge>(self);
_webStateList->AddObserver(_webStateListObserver.get());
}
return self;
}
- (void)shutdown {
_webStateList->RemoveObserver(_webStateListObserver.get());
[[NSNotificationCenter defaultCenter] removeObserver:self.consumer];
_observer.reset();
}
- (void)setUp {
[self.consumer setVoiceSearchIsEnabled:ios::GetChromeBrowserProvider()
->GetVoiceSearchProvider()
->IsVoiceSearchEnabled()];
[self.consumer setTabCount:self.webStateList->count()];
web::WebState* webState = _webStateList->GetActiveWebState();
if (webState) {
web::NavigationManager* nav = webState->GetNavigationManager();
[self.consumer setCanGoForward:nav->CanGoForward()];
[self.consumer setCanGoBack:nav->CanGoBack()];
}
// Set up template URL service to listen for default search engine changes.
_templateURLService =
ios::TemplateURLServiceFactory::GetForBrowserState(_browserState);
_observer =
std::make_unique<SearchEngineObserverBridge>(self, _templateURLService);
_templateURLService->Load();
_doodleController = ios::GetChromeBrowserProvider()->CreateLogoVendor(
_browserState, self.dispatcher);
[_consumer setLogoVendor:_doodleController];
[self searchEngineChanged];
// Set up notifications;
NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
[defaultCenter addObserver:self.consumer
selector:@selector(locationBarBecomesFirstResponder)
name:kLocationBarBecomesFirstResponderNotification
object:nil];
[defaultCenter addObserver:self.consumer
selector:@selector(locationBarResignsFirstResponder)
name:kLocationBarResignsFirstResponderNotification
object:nil];
}
- (void)searchEngineChanged {
BOOL showLogo = NO;
const TemplateURL* defaultURL =
_templateURLService->GetDefaultSearchProvider();
if (defaultURL) {
showLogo =
defaultURL->GetEngineType(_templateURLService->search_terms_data()) ==
SEARCH_ENGINE_GOOGLE;
}
[self.consumer setLogoIsShowing:showLogo];
}
#pragma mark - WebStateListObserving
- (void)webStateList:(WebStateList*)webStateList
didInsertWebState:(web::WebState*)webState
atIndex:(int)index
activating:(BOOL)activating {
[self.consumer setTabCount:self.webStateList->count()];
}
- (void)webStateList:(WebStateList*)webStateList
didDetachWebState:(web::WebState*)webState
atIndex:(int)atIndex {
[self.consumer setTabCount:self.webStateList->count()];
}
// If the actual webState associated with this mediator were passed in, this
// would not be necessary. However, since the active webstate can change when
// the new tab page is created (and animated in), listen for changes here and
// always display what's active.
- (void)webStateList:(WebStateList*)webStateList
didChangeActiveWebState:(web::WebState*)newWebState
oldWebState:(web::WebState*)oldWebState
atIndex:(int)atIndex
userAction:(BOOL)userAction {
if (newWebState) {
web::NavigationManager* nav = newWebState->GetNavigationManager();
[self.consumer setCanGoForward:nav->CanGoForward()];
[self.consumer setCanGoBack:nav->CanGoBack()];
}
}
@end
......@@ -27,7 +27,6 @@
#import "ios/chrome/browser/ui/bookmarks/bookmark_home_tablet_ntp_controller.h"
#import "ios/chrome/browser/ui/commands/browser_commands.h"
#import "ios/chrome/browser/ui/content_suggestions/ntp_home_constant.h"
#import "ios/chrome/browser/ui/ntp/google_landing_mediator.h"
#import "ios/chrome/browser/ui/ntp/incognito_view_controller.h"
#import "ios/chrome/browser/ui/ntp/modal_ntp.h"
#import "ios/chrome/browser/ui/ntp/new_tab_page_bar_item.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment