1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #import "chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac.h"
7 #import <Cocoa/Cocoa.h>
9 #include "apps/app_window_registry.h"
10 #include "apps/ui/native_app_window.h"
11 #include "base/command_line.h"
12 #include "base/mac/scoped_nsobject.h"
13 #include "base/strings/sys_string_conversions.h"
14 #include "chrome/browser/apps/app_browsertest_util.h"
15 #include "chrome/browser/extensions/extension_service.h"
16 #include "chrome/browser/extensions/extension_test_message_listener.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/browser_iterator.h"
19 #include "chrome/browser/ui/browser_window.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "extensions/common/extension.h"
25 class AppShimMenuControllerBrowserTest
26 : public extensions::PlatformAppBrowserTest {
28 AppShimMenuControllerBrowserTest()
31 initial_menu_item_count_(0) {}
33 virtual ~AppShimMenuControllerBrowserTest() {}
35 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
36 PlatformAppBrowserTest::SetUpCommandLine(command_line);
39 // Start two apps and wait for them to be launched.
41 ExtensionTestMessageListener listener_1("Launched", false);
42 app_1_ = InstallAndLaunchPlatformApp("minimal_id");
43 ASSERT_TRUE(listener_1.WaitUntilSatisfied());
44 ExtensionTestMessageListener listener_2("Launched", false);
45 app_2_ = InstallAndLaunchPlatformApp("minimal");
46 ASSERT_TRUE(listener_2.WaitUntilSatisfied());
48 initial_menu_item_count_ = [[[NSApp mainMenu] itemArray] count];
51 void CheckHasAppMenus(const extensions::Extension* app) const {
52 const int kExtraTopLevelItems = 4;
53 NSArray* item_array = [[NSApp mainMenu] itemArray];
54 EXPECT_EQ(initial_menu_item_count_ + kExtraTopLevelItems,
56 for (NSUInteger i = 0; i < initial_menu_item_count_; ++i)
57 EXPECT_TRUE([[item_array objectAtIndex:i] isHidden]);
58 NSMenuItem* app_menu = [item_array objectAtIndex:initial_menu_item_count_];
59 EXPECT_EQ(app->id(), base::SysNSStringToUTF8([app_menu title]));
60 EXPECT_EQ(app->name(),
61 base::SysNSStringToUTF8([[app_menu submenu] title]));
62 for (NSUInteger i = initial_menu_item_count_;
63 i < initial_menu_item_count_ + kExtraTopLevelItems;
65 NSMenuItem* menu = [item_array objectAtIndex:i];
66 EXPECT_GT([[menu submenu] numberOfItems], 0);
67 EXPECT_FALSE([menu isHidden]);
71 void CheckNoAppMenus() const {
72 NSArray* item_array = [[NSApp mainMenu] itemArray];
73 EXPECT_EQ(initial_menu_item_count_, [item_array count]);
74 for (NSUInteger i = 0; i < initial_menu_item_count_; ++i)
75 EXPECT_FALSE([[item_array objectAtIndex:i] isHidden]);
78 const extensions::Extension* app_1_;
79 const extensions::Extension* app_2_;
80 NSUInteger initial_menu_item_count_;
83 DISALLOW_COPY_AND_ASSIGN(AppShimMenuControllerBrowserTest);
86 // Test that focusing an app window changes the menu bar.
87 IN_PROC_BROWSER_TEST_F(AppShimMenuControllerBrowserTest,
88 PlatformAppFocusUpdatesMenuBar) {
90 // When an app is focused, all Chrome menu items should be hidden, and a menu
91 // item for the app should be added.
92 apps::AppWindow* app_1_app_window = apps::AppWindowRegistry::Get(profile())
93 ->GetAppWindowsForApp(app_1_->id())
95 [[NSNotificationCenter defaultCenter]
96 postNotificationName:NSWindowDidBecomeMainNotification
97 object:app_1_app_window->GetNativeWindow()];
98 CheckHasAppMenus(app_1_);
100 // When another app is focused, the menu item for the app should change.
101 apps::AppWindow* app_2_app_window = apps::AppWindowRegistry::Get(profile())
102 ->GetAppWindowsForApp(app_2_->id())
104 [[NSNotificationCenter defaultCenter]
105 postNotificationName:NSWindowDidBecomeMainNotification
106 object:app_2_app_window->GetNativeWindow()];
107 CheckHasAppMenus(app_2_);
109 // When a browser window is focused, the menu items for the app should be
111 BrowserWindow* chrome_window = chrome::BrowserIterator()->window();
112 [[NSNotificationCenter defaultCenter]
113 postNotificationName:NSWindowDidBecomeMainNotification
114 object:chrome_window->GetNativeWindow()];
117 // When an app window is closed and there are no other app windows, the menu
118 // items for the app should be removed.
119 app_1_app_window->GetBaseWindow()->Close();
120 chrome_window->Close();
121 [[NSNotificationCenter defaultCenter]
122 postNotificationName:NSWindowWillCloseNotification
123 object:app_2_app_window->GetNativeWindow()];
127 IN_PROC_BROWSER_TEST_F(AppShimMenuControllerBrowserTest,
128 ExtensionUninstallUpdatesMenuBar) {
131 // This essentially tests that a NSWindowWillCloseNotification gets fired when
132 // an app is uninstalled. We need to close the other windows first since the
133 // menu only changes on a NSWindowWillCloseNotification if there are no other
135 apps::AppWindow* app_2_app_window = apps::AppWindowRegistry::Get(profile())
136 ->GetAppWindowsForApp(app_2_->id())
138 app_2_app_window->GetBaseWindow()->Close();
140 chrome::BrowserIterator()->window()->Close();
142 apps::AppWindow* app_1_app_window = apps::AppWindowRegistry::Get(profile())
143 ->GetAppWindowsForApp(app_1_->id())
145 [[NSNotificationCenter defaultCenter]
146 postNotificationName:NSWindowDidBecomeMainNotification
147 object:app_1_app_window->GetNativeWindow()];
149 CheckHasAppMenus(app_1_);
150 ExtensionService::UninstallExtensionHelper(extension_service(), app_1_->id());