summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm')
-rw-r--r--chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm141
1 files changed, 120 insertions, 21 deletions
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm b/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm
index c8c0e22..a01111c 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm
@@ -68,6 +68,96 @@ enum ViewID {
VIEW_ID_COUNT,
};
+// Checks that no views draw on top of the supposedly exposed view.
+class ViewExposedChecker {
+ public:
+ ViewExposedChecker() : below_exposed_view_(YES) {}
+ ~ViewExposedChecker() {}
+
+ void SetExceptions(NSArray* exceptions) {
+ exceptions_.reset([exceptions retain]);
+ }
+
+ // Checks that no views draw in front of |view|, with the exception of
+ // |exceptions|.
+ void CheckViewExposed(NSView* view) {
+ below_exposed_view_ = YES;
+ exposed_view_.reset([view retain]);
+ CheckViewsDoNotObscure([[[view window] contentView] superview]);
+ }
+
+ private:
+ // Checks that |view| does not draw on top of |exposed_view_|.
+ void CheckViewDoesNotObscure(NSView* view) {
+ NSRect viewWindowFrame = [view convertRect:[view bounds] toView:nil];
+ NSRect viewBeingVerifiedWindowFrame =
+ [exposed_view_ convertRect:[exposed_view_ bounds] toView:nil];
+
+ // The views do not intersect.
+ if (!NSIntersectsRect(viewBeingVerifiedWindowFrame, viewWindowFrame))
+ return;
+
+ // No view can be above the view being checked.
+ EXPECT_TRUE(below_exposed_view_);
+
+ // If |view| is a parent of |exposed_view_|, then there's nothing else
+ // to check.
+ NSView* parent = exposed_view_;
+ while (parent != nil) {
+ parent = [parent superview];
+ if (parent == view)
+ return;
+ }
+
+ if ([exposed_view_ layer])
+ return;
+
+ // If the view being verified doesn't have a layer, then no views that
+ // intersect it can have a layer.
+ if ([exceptions_ containsObject:view]) {
+ EXPECT_FALSE([view isOpaque]);
+ return;
+ }
+
+ EXPECT_TRUE(![view layer]) << [[view description] UTF8String] << " " <<
+ [NSStringFromRect(viewWindowFrame) UTF8String];
+ }
+
+ // Recursively checks that |view| and its subviews do not draw on top of
+ // |exposed_view_|. The recursion passes through all views in order of
+ // back-most in Z-order to front-most in Z-order.
+ void CheckViewsDoNotObscure(NSView* view) {
+ // If this is the view being checked, don't recurse into its subviews. All
+ // future views encountered in the recursion are in front of the view being
+ // checked.
+ if (view == exposed_view_) {
+ below_exposed_view_ = NO;
+ return;
+ }
+
+ CheckViewDoesNotObscure(view);
+
+ // Perform the recursion.
+ for (NSView* subview in [view subviews])
+ CheckViewsDoNotObscure(subview);
+ }
+
+ // The method CheckViewExposed() recurses through the views in the view
+ // hierarchy and checks that none of the views obscure |exposed_view_|.
+ base::scoped_nsobject<NSView> exposed_view_;
+
+ // While this flag is true, the views being recursed through are below
+ // |exposed_view_| in Z-order. After the recursion passes |exposed_view_|,
+ // this flag is set to false.
+ BOOL below_exposed_view_;
+
+ // Exceptions are allowed to overlap |exposed_view_|. Exceptions must still
+ // be Z-order behind |exposed_view_|.
+ base::scoped_nsobject<NSArray> exceptions_;
+
+ DISALLOW_COPY_AND_ASSIGN(ViewExposedChecker);
+};
+
} // namespace
@interface InfoBarContainerController(TestingAPI)
@@ -223,22 +313,29 @@ class BrowserWindowControllerTest : public InProcessBrowserTest {
return icon_bottom.y - info_bar_top.y;
}
- // The traffic lights should always be in front of the content view and the
- // tab strip view. Since the traffic lights change across OSX versions, this
- // test verifies that the contentView is in the back, and if the tab strip
- // view is a sibling, it is directly in front of the content view.
- void VerifyTrafficLightZOrder() const {
- NSView* contentView = [[controller() window] contentView];
- NSView* rootView = [contentView superview];
- NSArray* subviews = [rootView subviews];
-
- EXPECT_EQ([controller() tabStripBackgroundView],
- [subviews objectAtIndex:0]);
- EXPECT_EQ(contentView, [subviews objectAtIndex:1]);
-
- NSView* tabStripView = [controller() tabStripView];
- if ([subviews containsObject:tabStripView])
- EXPECT_EQ(tabStripView, [subviews objectAtIndex:2]);
+ // Nothing should draw on top of the window controls.
+ void VerifyWindowControlsZOrder() {
+ NSWindow* window = [controller() window];
+ ViewExposedChecker checker;
+
+ // The exceptions are the contentView, chromeContentView and tabStripView,
+ // which are layer backed but transparent.
+ NSArray* exceptions = @[
+ [window contentView],
+ controller().chromeContentView,
+ controller().tabStripView
+ ];
+ checker.SetExceptions(exceptions);
+
+ checker.CheckViewExposed([window standardWindowButton:NSWindowCloseButton]);
+ checker.CheckViewExposed(
+ [window standardWindowButton:NSWindowMiniaturizeButton]);
+ checker.CheckViewExposed([window standardWindowButton:NSWindowZoomButton]);
+
+ // There is no fullscreen button on OSX 10.6 or OSX 10.10+.
+ NSView* view = [window standardWindowButton:NSWindowFullScreenButton];
+ if (view)
+ checker.CheckViewExposed(view);
}
private:
@@ -500,15 +597,17 @@ IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, TrafficLightZOrder) {
// Verify z order immediately after creation.
- VerifyTrafficLightZOrder();
+ VerifyWindowControlsZOrder();
- // Toggle overlay, then verify z order.
+ // Verify z order in and out of overlay.
[controller() showOverlay];
+ VerifyWindowControlsZOrder();
[controller() removeOverlay];
- VerifyTrafficLightZOrder();
+ VerifyWindowControlsZOrder();
- // Toggle immersive fullscreen, then verify z order.
+ // Toggle immersive fullscreen, then verify z order. In immersive fullscreen,
+ // there are no window controls.
[controller() enterImmersiveFullscreen];
[controller() exitImmersiveFullscreen];
- VerifyTrafficLightZOrder();
+ VerifyWindowControlsZOrder();
}