diff options
author | jackhou <jackhou@chromium.org> | 2015-08-06 22:17:21 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-08-07 05:18:11 +0000 |
commit | 24869918ffc61b2a29e7a8b23d9120e13c3404fd (patch) | |
tree | ce0dc5be1640cac5034ab132bae1592439fe31e7 | |
parent | e07acee850f48a5565c875e8806aaa126d35d22e (diff) | |
download | chromium_src-24869918ffc61b2a29e7a8b23d9120e13c3404fd.zip chromium_src-24869918ffc61b2a29e7a8b23d9120e13c3404fd.tar.gz chromium_src-24869918ffc61b2a29e7a8b23d9120e13c3404fd.tar.bz2 |
[MacViews] Fix AccessiblePaneViewTest.SetPaneFocusAndRestore.
Fake out key status to make Widget::Activate/IsActive work in the unit test.
If-def out the part that requires Widget::Deactivate as it's not supported on
Mac.
The test was also failing because Mac checks WidgetDelegate::CanActivate()
when activating whereas NativeWidgetAura defers this to `ShouldActivate`
which is only checked by wm::BaseFocusRules.
Also improve c/b/ui/test/scoped_fake_nswindow_main_status to handle
key status as well and move it to ui/base/test/.
BUG=378134
Review URL: https://codereview.chromium.org/1268293002
Cr-Commit-Position: refs/heads/master@{#342289}
-rw-r--r-- | chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac_browsertest.mm | 23 | ||||
-rw-r--r-- | chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm | 5 | ||||
-rw-r--r-- | chrome/browser/ui/test/scoped_fake_nswindow_main_status.h | 32 | ||||
-rw-r--r-- | chrome/browser/ui/test/scoped_fake_nswindow_main_status.mm | 47 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 2 | ||||
-rw-r--r-- | ui/base/BUILD.gn | 2 | ||||
-rw-r--r-- | ui/base/test/scoped_fake_nswindow_focus.h | 39 | ||||
-rw-r--r-- | ui/base/test/scoped_fake_nswindow_focus.mm | 100 | ||||
-rw-r--r-- | ui/base/ui_base.gyp | 2 | ||||
-rw-r--r-- | ui/views/accessible_pane_view_unittest.cc | 23 |
10 files changed, 176 insertions, 99 deletions
diff --git a/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac_browsertest.mm b/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac_browsertest.mm index 5959808..fb3302e 100644 --- a/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac_browsertest.mm +++ b/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac_browsertest.mm @@ -19,13 +19,13 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_iterator.h" #include "chrome/browser/ui/browser_window.h" -#import "chrome/browser/ui/test/scoped_fake_nswindow_main_status.h" #include "chrome/common/chrome_switches.h" #include "extensions/browser/app_window/app_window_registry.h" #include "extensions/browser/app_window/native_app_window.h" #include "extensions/browser/uninstall_reason.h" #include "extensions/common/extension.h" #include "extensions/test/extension_test_message_listener.h" +#import "ui/base/test/scoped_fake_nswindow_focus.h" namespace { @@ -77,7 +77,7 @@ class AppShimMenuControllerBrowserTest void CheckHasAppMenus(const extensions::Extension* app) const { const int kExtraTopLevelItems = 4; NSArray* item_array = [[NSApp mainMenu] itemArray]; - EXPECT_EQ(initial_menu_item_count_ + kExtraTopLevelItems, + ASSERT_EQ(initial_menu_item_count_ + kExtraTopLevelItems, [item_array count]); for (NSUInteger i = 0; i < initial_menu_item_count_; ++i) EXPECT_TRUE([[item_array objectAtIndex:i] isHidden]); @@ -186,11 +186,8 @@ IN_PROC_BROWSER_TEST_F(AppShimMenuControllerBrowserTest, extensions::AppWindow* app_1_app_window = FirstWindowForApp(app_1_); { - ScopedFakeNSWindowMainStatus app_1_is_main( - app_1_app_window->GetNativeWindow()); - [[NSNotificationCenter defaultCenter] - postNotificationName:NSWindowDidBecomeMainNotification - object:app_1_app_window->GetNativeWindow()]; + ui::test::ScopedFakeNSWindowFocus fake_focus; + [app_1_app_window->GetNativeWindow() makeMainWindow]; CheckHasAppMenus(app_1_); // Closing a background window without focusing it should not change menus. @@ -200,10 +197,9 @@ IN_PROC_BROWSER_TEST_F(AppShimMenuControllerBrowserTest, postNotificationName:NSWindowWillCloseNotification object:chrome_window->GetNativeWindow()]; CheckHasAppMenus(app_1_); + + // |fake_focus| going out of scope sends NSWindowWillResignMainNotification. } - [[NSNotificationCenter defaultCenter] - postNotificationName:NSWindowDidResignMainNotification - object:app_1_app_window->GetNativeWindow()]; app_1_app_window->GetBaseWindow()->Close(); CheckNoAppMenus(); } @@ -250,10 +246,9 @@ IN_PROC_BROWSER_TEST_F(AppShimMenuControllerBrowserTest, FirstWindowForApp(app_2_)->GetBaseWindow()->Close(); chrome::BrowserIterator()->window()->Close(); NSWindow* app_1_window = FirstWindowForApp(app_1_)->GetNativeWindow(); - [[NSNotificationCenter defaultCenter] - postNotificationName:NSWindowDidBecomeMainNotification - object:app_1_window]; - ScopedFakeNSWindowMainStatus app_1_is_main(app_1_window); + + ui::test::ScopedFakeNSWindowFocus fake_focus; + [app_1_window makeMainWindow]; CheckHasAppMenus(app_1_); ExtensionService::UninstallExtensionHelper( diff --git a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm index ce248ad..22f98a3 100644 --- a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm +++ b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm @@ -18,7 +18,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/extensions/app_launch_params.h" #include "chrome/browser/ui/extensions/application_launch.h" -#import "chrome/browser/ui/test/scoped_fake_nswindow_main_status.h" #include "chrome/common/chrome_switches.h" #include "content/public/browser/notification_service.h" #include "content/public/test/test_utils.h" @@ -28,6 +27,7 @@ #include "testing/gmock/include/gmock/gmock.h" #import "testing/gtest_mac.h" #import "ui/base/test/nswindow_fullscreen_notification_waiter.h" +#import "ui/base/test/scoped_fake_nswindow_focus.h" #import "ui/base/test/scoped_fake_nswindow_fullscreen.h" #import "ui/base/test/windowed_nsnotification_observer.h" #import "ui/gfx/mac/nswindow_frame_controls.h" @@ -699,7 +699,8 @@ IN_PROC_BROWSER_TEST_P(NativeAppWindowCocoaBrowserTest, FrameColor) { EXPECT_NEAR(expected_components[1], color_components[1], 0.01); EXPECT_NEAR(expected_components[2], color_components[2], 0.01); - ScopedFakeNSWindowMainStatus fake_main(ns_window); + ui::test::ScopedFakeNSWindowFocus fake_focus; + [ns_window makeMainWindow]; bitmap = ScreenshotNSWindow(ns_window); // The window is now active so it should be red (#FF0000). diff --git a/chrome/browser/ui/test/scoped_fake_nswindow_main_status.h b/chrome/browser/ui/test/scoped_fake_nswindow_main_status.h deleted file mode 100644 index 0d4df98..0000000 --- a/chrome/browser/ui/test/scoped_fake_nswindow_main_status.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2015 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 CHROME_BROWSER_UI_TEST_SCOPED_FAKE_NSWINDOW_MAIN_STATUS_H_ -#define CHROME_BROWSER_UI_TEST_SCOPED_FAKE_NSWINDOW_MAIN_STATUS_H_ - -#include "base/memory/scoped_ptr.h" - -namespace base { -namespace mac { -class ScopedObjCClassSwizzler; -} -} - -@class NSWindow; - -// Simulates a particular NSWindow to report YES for [NSWindow isMainWindow]. -// This allows test coverage of code relying on window focus changes without -// resorting to an interactive_ui_test. -class ScopedFakeNSWindowMainStatus { - public: - explicit ScopedFakeNSWindowMainStatus(NSWindow* window); - ~ScopedFakeNSWindowMainStatus(); - - private: - scoped_ptr<base::mac::ScopedObjCClassSwizzler> swizzler_; - - DISALLOW_COPY_AND_ASSIGN(ScopedFakeNSWindowMainStatus); -}; - -#endif // CHROME_BROWSER_UI_TEST_SCOPED_FAKE_NSWINDOW_MAIN_STATUS_H_ diff --git a/chrome/browser/ui/test/scoped_fake_nswindow_main_status.mm b/chrome/browser/ui/test/scoped_fake_nswindow_main_status.mm deleted file mode 100644 index 0f2c27d..0000000 --- a/chrome/browser/ui/test/scoped_fake_nswindow_main_status.mm +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2015 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 "chrome/browser/ui/test/scoped_fake_nswindow_main_status.h" - -#import <Cocoa/Cocoa.h> - -#import "base/mac/foundation_util.h" -#import "base/mac/scoped_objc_class_swizzler.h" - -namespace { - -NSWindow* g_fake_main_window = nil; - -} - -// Donates a testing implementation of [NSWindow isMainWindow]. -@interface IsMainWindowDonorForWindow : NSObject -@end - -@implementation IsMainWindowDonorForWindow -- (BOOL)isMainWindow { - NSWindow* selfAsWindow = base::mac::ObjCCastStrict<NSWindow>(self); - return selfAsWindow == g_fake_main_window; -} -@end - -ScopedFakeNSWindowMainStatus::ScopedFakeNSWindowMainStatus(NSWindow* window) - : swizzler_(new base::mac::ScopedObjCClassSwizzler( - [NSWindow class], - [IsMainWindowDonorForWindow class], - @selector(isMainWindow))) { - DCHECK(!g_fake_main_window); - g_fake_main_window = window; - [[NSNotificationCenter defaultCenter] - postNotificationName:NSWindowDidBecomeMainNotification - object:g_fake_main_window]; -} - -ScopedFakeNSWindowMainStatus::~ScopedFakeNSWindowMainStatus() { - NSWindow* window = g_fake_main_window; - g_fake_main_window = nil; - [[NSNotificationCenter defaultCenter] - postNotificationName:NSWindowDidResignMainNotification - object:window]; -} diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 9262d92..041ef6c 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -515,8 +515,6 @@ 'browser/ui/sync/profile_signin_confirmation_helper_browsertest.cc', 'browser/ui/tab_modal_confirm_dialog_browsertest.cc', 'browser/ui/tab_modal_confirm_dialog_browsertest.h', - 'browser/ui/test/scoped_fake_nswindow_main_status.h', - 'browser/ui/test/scoped_fake_nswindow_main_status.mm', 'browser/ui/toolbar/browser_actions_bar_browsertest.cc', 'browser/ui/toolbar/browser_actions_bar_browsertest.h', 'browser/ui/toolbar/component_toolbar_actions_browsertest.cc', diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index 573d72b..cc416e3 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn @@ -571,6 +571,8 @@ source_set("test_support") { "test/material_design_controller_test_api.h", "test/nswindow_fullscreen_notification_waiter.h", "test/nswindow_fullscreen_notification_waiter.mm", + "test/scoped_fake_nswindow_focus.h", + "test/scoped_fake_nswindow_focus.mm", "test/scoped_fake_nswindow_fullscreen.h", "test/scoped_fake_nswindow_fullscreen.mm", "test/test_clipboard.cc", diff --git a/ui/base/test/scoped_fake_nswindow_focus.h b/ui/base/test/scoped_fake_nswindow_focus.h new file mode 100644 index 0000000..aafd715 --- /dev/null +++ b/ui/base/test/scoped_fake_nswindow_focus.h @@ -0,0 +1,39 @@ +// Copyright 2015 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 UI_BASE_TEST_SCOPED_FAKE_NSWINDOW_FOCUS_H_ +#define UI_BASE_TEST_SCOPED_FAKE_NSWINDOW_FOCUS_H_ + +#include "base/memory/scoped_ptr.h" + +namespace base { +namespace mac { +class ScopedObjCClassSwizzler; +} +} + +namespace ui { +namespace test { + +// Simulates key and main status by listening for -makeKeyWindow and +// -makeMainWindow. This allows test coverage of code relying on window focus +// changes without resorting to an interactive_ui_test. +class ScopedFakeNSWindowFocus { + public: + ScopedFakeNSWindowFocus(); + ~ScopedFakeNSWindowFocus(); + + private: + scoped_ptr<base::mac::ScopedObjCClassSwizzler> is_main_swizzler_; + scoped_ptr<base::mac::ScopedObjCClassSwizzler> make_main_swizzler_; + scoped_ptr<base::mac::ScopedObjCClassSwizzler> is_key_swizzler_; + scoped_ptr<base::mac::ScopedObjCClassSwizzler> make_key_swizzler_; + + DISALLOW_COPY_AND_ASSIGN(ScopedFakeNSWindowFocus); +}; + +} // namespace test +} // namespace ui + +#endif // UI_BASE_TEST_SCOPED_FAKE_NSWINDOW_FOCUS_H_ diff --git a/ui/base/test/scoped_fake_nswindow_focus.mm b/ui/base/test/scoped_fake_nswindow_focus.mm new file mode 100644 index 0000000..b78680d --- /dev/null +++ b/ui/base/test/scoped_fake_nswindow_focus.mm @@ -0,0 +1,100 @@ +// Copyright 2015 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 "ui/base/test/scoped_fake_nswindow_focus.h" + +#import <Cocoa/Cocoa.h> + +#import "base/mac/foundation_util.h" +#import "base/mac/scoped_objc_class_swizzler.h" + +using base::mac::ScopedObjCClassSwizzler; + +namespace { + +NSWindow* g_fake_focused_window = nil; + +void SetFocus(NSWindow* window) { + g_fake_focused_window = window; + [[NSNotificationCenter defaultCenter] + postNotificationName:NSWindowDidBecomeMainNotification + object:g_fake_focused_window]; + [[NSNotificationCenter defaultCenter] + postNotificationName:NSWindowDidBecomeKeyNotification + object:g_fake_focused_window]; +} + +void ClearFocus() { + NSWindow* window = g_fake_focused_window; + g_fake_focused_window = nil; + [[NSNotificationCenter defaultCenter] + postNotificationName:NSWindowDidResignKeyNotification + object:window]; + + [[NSNotificationCenter defaultCenter] + postNotificationName:NSWindowDidResignMainNotification + object:window]; +} + +} // namespace + +// Donates testing implementations of NSWindow methods. +@interface FakeNSWindowFocusDonor : NSObject +@end + +@implementation FakeNSWindowFocusDonor + +- (BOOL)isKeyWindow { + NSWindow* selfAsWindow = base::mac::ObjCCastStrict<NSWindow>(self); + return selfAsWindow == g_fake_focused_window; +} + +- (BOOL)isMainWindow { + NSWindow* selfAsWindow = base::mac::ObjCCastStrict<NSWindow>(self); + return selfAsWindow == g_fake_focused_window; +} + +- (void)makeKeyWindow { + NSWindow* selfAsWindow = base::mac::ObjCCastStrict<NSWindow>(self); + if (selfAsWindow == g_fake_focused_window || + ![selfAsWindow canBecomeKeyWindow]) + return; + + ClearFocus(); + SetFocus(selfAsWindow); +} + +- (void)makeMainWindow { + [self makeKeyWindow]; +} + +@end + +namespace ui { +namespace test { + +ScopedFakeNSWindowFocus::ScopedFakeNSWindowFocus() + : is_main_swizzler_( + new ScopedObjCClassSwizzler([NSWindow class], + [FakeNSWindowFocusDonor class], + @selector(isMainWindow))), + make_main_swizzler_( + new ScopedObjCClassSwizzler([NSWindow class], + [FakeNSWindowFocusDonor class], + @selector(makeMainWindow))), + is_key_swizzler_( + new ScopedObjCClassSwizzler([NSWindow class], + [FakeNSWindowFocusDonor class], + @selector(isKeyWindow))), + make_key_swizzler_( + new ScopedObjCClassSwizzler([NSWindow class], + [FakeNSWindowFocusDonor class], + @selector(makeKeyWindow))) {} + +ScopedFakeNSWindowFocus::~ScopedFakeNSWindowFocus() { + ClearFocus(); +} + +} // namespace test +} // namespace ui diff --git a/ui/base/ui_base.gyp b/ui/base/ui_base.gyp index ed99bf0..3e8375c 100644 --- a/ui/base/ui_base.gyp +++ b/ui/base/ui_base.gyp @@ -684,6 +684,8 @@ 'ime/dummy_text_input_client.h', 'test/nswindow_fullscreen_notification_waiter.h', 'test/nswindow_fullscreen_notification_waiter.mm', + 'test/scoped_fake_nswindow_focus.h', + 'test/scoped_fake_nswindow_focus.mm', 'test/scoped_fake_nswindow_fullscreen.h', 'test/scoped_fake_nswindow_fullscreen.mm', 'test/windowed_nsnotification_observer.h', diff --git a/ui/views/accessible_pane_view_unittest.cc b/ui/views/accessible_pane_view_unittest.cc index d53fb72..16c2a32 100644 --- a/ui/views/accessible_pane_view_unittest.cc +++ b/ui/views/accessible_pane_view_unittest.cc @@ -10,6 +10,10 @@ #include "ui/views/test/views_test_base.h" #include "ui/views/widget/widget.h" +#if defined(OS_MACOSX) +#include "ui/base/test/scoped_fake_nswindow_focus.h" +#endif + namespace views { // TODO(alicet): bring pane rotation into views and add tests. @@ -98,13 +102,20 @@ TEST_F(AccessiblePaneViewTest, SimpleSetPaneFocus) { widget.reset(); } -// This test will not work properly in Windows because it uses ::GetNextWindow -// on deactivate which is rather unpredictable where the focus will land. TEST_F(AccessiblePaneViewTest, SetPaneFocusAndRestore) { +#if defined(OS_MACOSX) + // On Aura platforms, this test creates Ash windows and only interacts with + // the Ash window manager. On Mac, it creates native windows, but since unit + // tests cannot gain key status, fake it out here. + ui::test::ScopedFakeNSWindowFocus fake_focus; +#endif + View* test_view_main = new View(); scoped_ptr<Widget> widget_main(new Widget()); Widget::InitParams params_main = CreateParams(Widget::InitParams::TYPE_POPUP); params_main.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + // By default, TYPE_POPUP is not activatable. + params_main.activatable = Widget::InitParams::ACTIVATABLE_YES; params_main.bounds = gfx::Rect(0, 0, 20, 20); widget_main->Init(params_main); View* root_main = widget_main->GetRootView(); @@ -118,6 +129,7 @@ TEST_F(AccessiblePaneViewTest, SetPaneFocusAndRestore) { scoped_ptr<Widget> widget_bar(new Widget()); Widget::InitParams params_bar = CreateParams(Widget::InitParams::TYPE_POPUP); params_bar.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + params_bar.activatable = Widget::InitParams::ACTIVATABLE_YES; params_bar.bounds = gfx::Rect(50, 50, 650, 650); widget_bar->Init(params_bar); View* root_bar = widget_bar->GetRootView(); @@ -133,9 +145,16 @@ TEST_F(AccessiblePaneViewTest, SetPaneFocusAndRestore) { EXPECT_EQ(test_view_bar->child_button(), test_view_bar->GetWidget()->GetFocusManager()->GetFocusedView()); + // Deactivate() is only reliable on Ash. On Windows it uses ::GetNextWindow() + // to simply activate another window, and which one is not predictable. On + // Mac, Deactivate() is not implemented. Note that TestBarView calls + // set_allow_deactivate_on_esc(true), which is only otherwise used in Ash. +#if !defined(OS_MACOSX) || defined(USE_ASH) + // Esc should deactivate the widget. test_view_bar->AcceleratorPressed(test_view_bar->escape_key()); EXPECT_TRUE(widget_main->IsActive()); EXPECT_FALSE(widget_bar->IsActive()); +#endif widget_bar->CloseNow(); widget_bar.reset(); |