Skip to content

Commit

Permalink
[iOS] Created MainContentCoordinator and MainContetUIState.
Browse files Browse the repository at this point in the history
These classes are infrastructure to use for the main content area for
forwarding scrolling events.

This CL also adds TestBrowserCoordinator, which is a BrowserCoordinator
subclass with a default UIViewController that can be used in tests
for BrowserCoordinator lifecycle events.

Bug: 769089
Cq-Include-Trybots: master.tryserver.chromium.mac:ios-simulator-cronet;master.tryserver.chromium.mac:ios-simulator-full-configs
Change-Id: I70c62708613f21247ac813f805620a7b0bb0a8fb
Reviewed-on: https://chromium-review.googlesource.com/735531
Commit-Queue: Kurt Horimoto <[email protected]>
Reviewed-by: Mark Cogan <[email protected]>
Reviewed-by: Kurt Horimoto <[email protected]>
Cr-Commit-Position: refs/heads/master@{#517003}
  • Loading branch information
Kurt Horimoto authored and Commit Bot committed Nov 16, 2017
1 parent 417adfb commit cc2adab
Show file tree
Hide file tree
Showing 24 changed files with 919 additions and 0 deletions.
17 changes: 17 additions & 0 deletions ios/chrome/browser/ui/broadcaster/chrome_broadcast_observer.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,35 @@
@protocol ChromeBroadcastObserver<NSObject>
@optional

#pragma mark - Tab strip UI

// Observer method for object that care about the current visibility of the tab
// strip.
- (void)broadcastTabStripVisible:(BOOL)visible;

#pragma mark - Scrolling events

// Observer method for objects that care about the current vertical (y-axis)
// scroll offset of the tab content area.
- (void)broadcastContentScrollOffset:(CGFloat)offset;

// Observer method for objects that care about whether the main content area is
// scrolling.
- (void)broadcastScrollViewIsScrolling:(BOOL)scrolling;

// Observer method for objects that care abotu whether the main content area is
// being dragged. Note that if a drag ends with residual velocity, it's
// possible for |dragging| to be NO while |scrolling| is still YES.
- (void)broadcastScrollViewIsDragging:(BOOL)dragging;

#pragma mark - NTP UI

// Observer method for objects that care about the current panel selected on the
// NTP.
- (void)broadcastSelectedNTPPanel:(ntp_home::PanelIdentifier)panelIdentifier;

#pragma mark - Omnibox UI

// Observer method for objects that care about the current omnibox frame. The
// given frame is in the window's coordinate system.
- (void)broadcastOmniboxFrame:(CGRect)frame;
Expand Down
2 changes: 2 additions & 0 deletions ios/chrome/browser/ui/coordinators/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ source_set("test_support") {
"browser_coordinator_test.mm",
"browser_coordinator_test_util.h",
"browser_coordinator_test_util.mm",
"test_browser_coordinator.h",
"test_browser_coordinator.mm",
]

configs += [ "//build/config/compiler:enable_arc" ]
Expand Down
16 changes: 16 additions & 0 deletions ios/chrome/browser/ui/coordinators/test_browser_coordinator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// 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_COORDINATORS_TEST_BROWSER_COORDINATOR_H_
#define IOS_CHROME_BROWSER_UI_COORDINATORS_TEST_BROWSER_COORDINATOR_H_

#import "ios/chrome/browser/ui/coordinators/browser_coordinator.h"

// A test version of BrowserCoordinator. This class backs its |viewController|
// property using a default UIViewController. It can be used as a parent
// coordinator with no functionality in tests for coordinator lifecycle events.
@interface TestBrowserCoordinator : BrowserCoordinator
@end

#endif // IOS_CHROME_BROWSER_UI_COORDINATORS_TEST_BROWSER_COORDINATOR_H_
35 changes: 35 additions & 0 deletions ios/chrome/browser/ui/coordinators/test_browser_coordinator.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// 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/coordinators/test_browser_coordinator.h"

#import "ios/chrome/browser/ui/coordinators/browser_coordinator+internal.h"

#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif

@interface TestBrowserCoordinator () {
// The test parent view controller.
UIViewController* _viewController;
}
@end

@implementation TestBrowserCoordinator

- (instancetype)init {
if (self = [super init])
_viewController = [[UIViewController alloc] init];
return self;
}

@end

@implementation TestBrowserCoordinator (Internal)

- (UIViewController*)viewController {
return _viewController;
}

@end
80 changes: 80 additions & 0 deletions ios/chrome/browser/ui/main_content/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# 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.

source_set("main_content") {
sources = [
"main_content_coordinator.h",
"main_content_coordinator.mm",
]

configs += [ "//build/config/compiler:enable_arc" ]

deps = [
":main_content_ui",
":main_content_ui_broadcasting_util",
"//base",
"//ios/chrome/browser/ui/browser_list",
"//ios/chrome/browser/ui/coordinators",
]
}

source_set("main_content_ui") {
sources = [
"main_content_ui.h",
"main_content_ui_state.h",
"main_content_ui_state.mm",
]

configs += [ "//build/config/compiler:enable_arc" ]

deps = [
"//base",
"//ios/chrome/browser/ui:ui_util",
"//ios/chrome/browser/ui/broadcaster",
]
}

source_set("main_content_ui_broadcasting_util") {
sources = [
"main_content_ui_broadcasting_util.h",
"main_content_ui_broadcasting_util.mm",
]

configs += [ "//build/config/compiler:enable_arc" ]

deps = [
":main_content_ui",
"//ios/chrome/browser/ui/broadcaster",
]
}

source_set("unit_tests") {
testonly = true
sources = [
"main_content_coordinator_unittest.mm",
"main_content_ui_broadcasting_util_unittest.mm",
"main_content_ui_state_unittest.mm",
]

configs += [ "//build/config/compiler:enable_arc" ]

deps = [
":main_content",
":main_content_ui",
":main_content_ui_broadcasting_util",
"//base",
"//base/test:test_support",
"//ios/chrome/browser/ui:ui_util",
"//ios/chrome/browser/ui/broadcaster",
"//ios/chrome/browser/ui/browser_list",
"//ios/chrome/browser/ui/coordinators",
"//ios/chrome/browser/ui/coordinators:test_support",
"//ios/chrome/browser/ui/main_content/test",
"//ios/chrome/browser/web_state_list",
"//ios/chrome/test/base",
"//ios/web/public/test",
"//ios/web/public/test/fakes",
"//testing/gtest",
]
}
1 change: 1 addition & 0 deletions ios/chrome/browser/ui/main_content/OWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[email protected]
23 changes: 23 additions & 0 deletions ios/chrome/browser/ui/main_content/main_content_coordinator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// 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_MAIN_CONTENT_MAIN_CONTENT_COORDINATOR_H_
#define IOS_CHROME_BROWSER_UI_MAIN_CONTENT_MAIN_CONTENT_COORDINATOR_H_

#import <UIKit/UIKit.h>

#import "ios/chrome/browser/ui/coordinators/browser_coordinator.h"
#import "ios/chrome/browser/ui/main_content/main_content_ui.h"

// A coordinator that displays the main content view of the browser. This
// should be subclassed by any coordinator that displays the scrollable content
// related to the current URL.
@interface MainContentCoordinator : BrowserCoordinator

// The view controller used to display the main content area.
@property(nonatomic, readonly) UIViewController<MainContentUI>* viewController;

@end

#endif // IOS_CHROME_BROWSER_UI_MAIN_CONTENT_MAIN_CONTENT_COORDINATOR_H_
65 changes: 65 additions & 0 deletions ios/chrome/browser/ui/main_content/main_content_coordinator.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// 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/main_content/main_content_coordinator.h"

#include "base/logging.h"
#import "ios/chrome/browser/ui/browser_list/browser.h"
#import "ios/chrome/browser/ui/coordinators/browser_coordinator+internal.h"
#import "ios/chrome/browser/ui/main_content/main_content_ui_broadcasting_util.h"

#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif

@interface MainContentCoordinator ()
// Starts or stops broadcasting UI state from |viewController|.
- (void)startBroadcastingUI;
- (void)stopBroadcastingUI;
@end

@implementation MainContentCoordinator

#pragma mark - Accessors

- (UIViewController<MainContentUI>*)viewController {
// Subclasses implement.
NOTREACHED();
return nil;
}

#pragma mark - BrowserCoordinator

- (void)start {
[super start];
[self startBroadcastingUI];
}

- (void)stop {
[self stopBroadcastingUI];
[super stop];
}

- (void)childCoordinatorDidStart:(BrowserCoordinator*)childCoordinator {
if ([childCoordinator isKindOfClass:[self class]])
[self stopBroadcastingUI];
}

- (void)childCoordinatorWillStop:(BrowserCoordinator*)childCoordinator {
if ([childCoordinator isKindOfClass:[self class]])
[self startBroadcastingUI];
}

#pragma mark - Private

- (void)startBroadcastingUI {
StartBroadcastingMainContentUI(self.viewController,
self.browser->broadcaster());
}

- (void)stopBroadcastingUI {
StopBroadcastingMainContentUI(self.browser->broadcaster());
}

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// 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/main_content/main_content_coordinator.h"

#import "base/mac/foundation_util.h"
#import "ios/chrome/browser/ui/browser_list/browser.h"
#import "ios/chrome/browser/ui/coordinators/browser_coordinator+internal.h"
#import "ios/chrome/browser/ui/coordinators/browser_coordinator_test.h"
#import "ios/chrome/browser/ui/coordinators/test_browser_coordinator.h"
#import "ios/chrome/browser/ui/main_content/main_content_ui_state.h"
#import "ios/chrome/browser/ui/main_content/test/main_content_broadcast_test_util.h"
#import "ios/chrome/browser/ui/main_content/test/test_main_content_ui_observer.h"
#import "ios/chrome/browser/ui/main_content/test/test_main_content_ui_state.h"

#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif

#pragma mark - TestMainContentViewController

// Test implementation of MainContentViewController.
@interface TestMainContentViewController : UIViewController<MainContentUI>
@property(nonatomic, readonly) TestMainContentUIState* mainContentUIState;
@end

@implementation TestMainContentViewController
@synthesize mainContentUIState = _mainContentUIState;

- (instancetype)init {
if (self = [super init])
_mainContentUIState = [[TestMainContentUIState alloc] init];
return self;
}

@end

#pragma mark - TestMainContentCoordinator

// Test version of MainContentCoordinator.
@interface TestMainContentCoordinator : MainContentCoordinator
@property(nonatomic, readonly) TestMainContentViewController* viewController;
@end

@implementation TestMainContentCoordinator
@synthesize viewController = _viewController;

- (instancetype)init {
if (self = [super init])
_viewController = [[TestMainContentViewController alloc] init];
return self;
}

@end

#pragma mark - MainContentCoordinatorTest

// Test fixture for MainContentCoordinator.
class MainContentCoordinatorTest : public BrowserCoordinatorTest {
protected:
MainContentCoordinatorTest()
: BrowserCoordinatorTest(),
parent_([[TestBrowserCoordinator alloc] init]) {
parent_.browser = GetBrowser();
}

// The coordinator to use as the parent for MainContentCoordinators.
BrowserCoordinator* parent() { return parent_; }

private:
__strong BrowserCoordinator* parent_;
DISALLOW_COPY_AND_ASSIGN(MainContentCoordinatorTest);
};

// Tests that a MainContentCoordinator's ui forwader starts broadcasting
// when started.
TEST_F(MainContentCoordinatorTest, BroadcastAfterStarting) {
// Start a MainContentCoordinator and verify that its UI is being broadcasted.
TestMainContentCoordinator* coordinator =
[[TestMainContentCoordinator alloc] init];
[parent() addChildCoordinator:coordinator];
[coordinator start];
VerifyMainContentUIBroadcast(coordinator.viewController.mainContentUIState,
GetBrowser()->broadcaster(),
true /*should_broadcast*/);
// Stop the coordinator and verify that its UI is no longer being broadcasted.
[coordinator stop];
[parent() removeChildCoordinator:coordinator];
VerifyMainContentUIBroadcast(coordinator.viewController.mainContentUIState,
GetBrowser()->broadcaster(),
false /*should_broadcast*/);
}

// Tests that a MainContentCoordinator's ui forwader stops broadcasting when
// a child MainContentCoordinator is started.
TEST_F(MainContentCoordinatorTest, StopBroadcastingForChildren) {
// Start a MainContentCoordinator and start a child MainContentCoordinator,
// then verify that the child's UI is being broadcast, not the parent's.
TestMainContentCoordinator* parentMainCoordinator =
[[TestMainContentCoordinator alloc] init];
[parent() addChildCoordinator:parentMainCoordinator];
[parentMainCoordinator start];
TestMainContentCoordinator* childMainCoordinator =
[[TestMainContentCoordinator alloc] init];
[parentMainCoordinator addChildCoordinator:childMainCoordinator];
[childMainCoordinator start];
VerifyMainContentUIBroadcast(
childMainCoordinator.viewController.mainContentUIState,
GetBrowser()->broadcaster(), true /*should_broadcast*/);
VerifyMainContentUIBroadcast(
parentMainCoordinator.viewController.mainContentUIState,
GetBrowser()->broadcaster(), false /*should_broadcast*/);
// Stop the child coordinator and verify that the parent's UI is being
// broadcast instead.
[childMainCoordinator stop];
[parentMainCoordinator removeChildCoordinator:childMainCoordinator];
VerifyMainContentUIBroadcast(
childMainCoordinator.viewController.mainContentUIState,
GetBrowser()->broadcaster(), false /*should_broadcast*/);
VerifyMainContentUIBroadcast(
parentMainCoordinator.viewController.mainContentUIState,
GetBrowser()->broadcaster(), true /*should_broadcast*/);
[parentMainCoordinator stop];
[parent() removeChildCoordinator:parentMainCoordinator];
}
Loading

0 comments on commit cc2adab

Please sign in to comment.