Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / apps / app_shim_menu_controller_mac_browsertest.mm
blob55e6d82acfd26ecf0b70c6f1d443780bb06992c0
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 "base/command_line.h"
10 #import "base/mac/foundation_util.h"
11 #import "base/mac/scoped_nsobject.h"
12 #import "base/mac/scoped_objc_class_swizzler.h"
13 #include "base/strings/sys_string_conversions.h"
14 #include "chrome/app/chrome_command_ids.h"
15 #include "chrome/browser/apps/app_browsertest_util.h"
16 #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h"
17 #include "chrome/browser/extensions/extension_service.h"
18 #include "chrome/browser/extensions/launch_util.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/ui/browser_iterator.h"
21 #include "chrome/browser/ui/browser_window.h"
22 #include "chrome/common/chrome_switches.h"
23 #include "extensions/browser/app_window/app_window_registry.h"
24 #include "extensions/browser/app_window/native_app_window.h"
25 #include "extensions/browser/uninstall_reason.h"
26 #include "extensions/common/extension.h"
27 #include "extensions/test/extension_test_message_listener.h"
28 #import "ui/base/test/scoped_fake_nswindow_focus.h"
30 namespace {
32 class AppShimMenuControllerBrowserTest
33     : public extensions::PlatformAppBrowserTest {
34  protected:
35   // The apps that can be installed and launched by SetUpApps().
36   enum AvailableApps { PACKAGED_1 = 0x1, PACKAGED_2 = 0x2, HOSTED = 0x4 };
38   AppShimMenuControllerBrowserTest()
39       : app_1_(nullptr),
40         app_2_(nullptr),
41         hosted_app_(nullptr),
42         initial_menu_item_count_(0) {}
44   void SetUpCommandLine(base::CommandLine* command_line) override {
45     PlatformAppBrowserTest::SetUpCommandLine(command_line);
46     command_line->AppendSwitch(switches::kEnableNewBookmarkApps);
47   }
49   // Start testing apps and wait for them to launch. |flags| is a bitmask of
50   // AvailableApps.
51   void SetUpApps(int flags) {
53     if (flags & PACKAGED_1) {
54       ExtensionTestMessageListener listener_1("Launched", false);
55       app_1_ = InstallAndLaunchPlatformApp("minimal_id");
56       ASSERT_TRUE(listener_1.WaitUntilSatisfied());
57     }
59     if (flags & PACKAGED_2) {
60       ExtensionTestMessageListener listener_2("Launched", false);
61       app_2_ = InstallAndLaunchPlatformApp("minimal");
62       ASSERT_TRUE(listener_2.WaitUntilSatisfied());
63     }
65     if (flags & HOSTED) {
66       hosted_app_ = InstallHostedApp();
68       // Explicitly set the launch type to open in a new window.
69       extensions::SetLaunchType(profile(), hosted_app_->id(),
70                                 extensions::LAUNCH_TYPE_WINDOW);
71       LaunchHostedApp(hosted_app_);
72     }
74     initial_menu_item_count_ = [[[NSApp mainMenu] itemArray] count];
75   }
77   void CheckHasAppMenus(const extensions::Extension* app) const {
78     const int kExtraTopLevelItems = 4;
79     NSArray* item_array = [[NSApp mainMenu] itemArray];
80     ASSERT_EQ(initial_menu_item_count_ + kExtraTopLevelItems,
81               [item_array count]);
82     for (NSUInteger i = 0; i < initial_menu_item_count_; ++i)
83       EXPECT_TRUE([[item_array objectAtIndex:i] isHidden]);
84     NSMenuItem* app_menu = [item_array objectAtIndex:initial_menu_item_count_];
85     EXPECT_EQ(app->id(), base::SysNSStringToUTF8([app_menu title]));
86     EXPECT_EQ(app->name(),
87               base::SysNSStringToUTF8([[app_menu submenu] title]));
88     for (NSUInteger i = initial_menu_item_count_;
89          i < initial_menu_item_count_ + kExtraTopLevelItems;
90          ++i) {
91       NSMenuItem* menu = [item_array objectAtIndex:i];
92       EXPECT_GT([[menu submenu] numberOfItems], 0);
93       EXPECT_FALSE([menu isHidden]);
94     }
95   }
97   void CheckNoAppMenus() const {
98     NSArray* item_array = [[NSApp mainMenu] itemArray];
99     EXPECT_EQ(initial_menu_item_count_, [item_array count]);
100     for (NSUInteger i = 0; i < initial_menu_item_count_; ++i)
101       EXPECT_FALSE([[item_array objectAtIndex:i] isHidden]);
102   }
104   void CheckEditMenu(const extensions::Extension* app) const {
105     const int edit_menu_index = initial_menu_item_count_ + 2;
107     NSMenuItem* edit_menu =
108         [[[NSApp mainMenu] itemArray] objectAtIndex:edit_menu_index];
109     NSMenu* edit_submenu = [edit_menu submenu];
110     NSMenuItem* paste_match_style_menu_item =
111         [edit_submenu itemWithTag:IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE];
112     NSMenuItem* find_menu_item = [edit_submenu itemWithTag:IDC_FIND_MENU];
113     if (app->is_hosted_app()) {
114       EXPECT_FALSE([paste_match_style_menu_item isHidden]);
115       EXPECT_FALSE([find_menu_item isHidden]);
116     } else {
117       EXPECT_TRUE([paste_match_style_menu_item isHidden]);
118       EXPECT_TRUE([find_menu_item isHidden]);
119     }
120   }
122   extensions::AppWindow* FirstWindowForApp(const extensions::Extension* app) {
123     extensions::AppWindowRegistry::AppWindowList window_list =
124         extensions::AppWindowRegistry::Get(profile())
125             ->GetAppWindowsForApp(app->id());
126     EXPECT_FALSE(window_list.empty());
127     return window_list.front();
128   }
130   const extensions::Extension* app_1_;
131   const extensions::Extension* app_2_;
132   const extensions::Extension* hosted_app_;
133   NSUInteger initial_menu_item_count_;
135  private:
136   DISALLOW_COPY_AND_ASSIGN(AppShimMenuControllerBrowserTest);
139 // Test that focusing an app window changes the menu bar.
140 IN_PROC_BROWSER_TEST_F(AppShimMenuControllerBrowserTest,
141                        PlatformAppFocusUpdatesMenuBar) {
142   SetUpApps(PACKAGED_1 | PACKAGED_2);
143   // When an app is focused, all Chrome menu items should be hidden, and a menu
144   // item for the app should be added.
145   extensions::AppWindow* app_1_app_window = FirstWindowForApp(app_1_);
146   [[NSNotificationCenter defaultCenter]
147       postNotificationName:NSWindowDidBecomeMainNotification
148                     object:app_1_app_window->GetNativeWindow()];
149   CheckHasAppMenus(app_1_);
151   // When another app is focused, the menu item for the app should change.
152   extensions::AppWindow* app_2_app_window = FirstWindowForApp(app_2_);
153   [[NSNotificationCenter defaultCenter]
154       postNotificationName:NSWindowDidBecomeMainNotification
155                     object:app_2_app_window->GetNativeWindow()];
156   CheckHasAppMenus(app_2_);
158   // When a browser window is focused, the menu items for the app should be
159   // removed.
160   BrowserWindow* chrome_window = chrome::BrowserIterator()->window();
161   [[NSNotificationCenter defaultCenter]
162       postNotificationName:NSWindowDidBecomeMainNotification
163                     object:chrome_window->GetNativeWindow()];
164   CheckNoAppMenus();
166   // When an app window is closed and there are no other app windows, the menu
167   // items for the app should be removed.
168   app_1_app_window->GetBaseWindow()->Close();
169   chrome_window->Close();
170   [[NSNotificationCenter defaultCenter]
171       postNotificationName:NSWindowDidBecomeMainNotification
172                     object:app_2_app_window->GetNativeWindow()];
173   CheckHasAppMenus(app_2_);
174   [[NSNotificationCenter defaultCenter]
175       postNotificationName:NSWindowDidResignMainNotification
176                     object:app_2_app_window->GetNativeWindow()];
177   app_2_app_window->GetBaseWindow()->Close();
178   CheckNoAppMenus();
181 // Test that closing windows without main status do not update the menu.
182 IN_PROC_BROWSER_TEST_F(AppShimMenuControllerBrowserTest,
183                        ClosingBackgroundWindowLeavesMenuBar) {
184   // Start with app1 active.
185   SetUpApps(PACKAGED_1);
186   extensions::AppWindow* app_1_app_window = FirstWindowForApp(app_1_);
188   {
189     ui::test::ScopedFakeNSWindowFocus fake_focus;
190     [app_1_app_window->GetNativeWindow() makeMainWindow];
191     CheckHasAppMenus(app_1_);
193     // Closing a background window without focusing it should not change menus.
194     BrowserWindow* chrome_window = chrome::BrowserIterator()->window();
195     chrome_window->Close();
196     [[NSNotificationCenter defaultCenter]
197         postNotificationName:NSWindowWillCloseNotification
198                       object:chrome_window->GetNativeWindow()];
199     CheckHasAppMenus(app_1_);
201     // |fake_focus| going out of scope sends NSWindowWillResignMainNotification.
202   }
203   app_1_app_window->GetBaseWindow()->Close();
204   CheckNoAppMenus();
207 // Test to check that hosted apps have "Find" and "Paste and Match Style" menu
208 // items under the "Edit" menu.
209 // Disabled until tab versus window apps are properly tested
210 // http://crbug.com/517744
211 IN_PROC_BROWSER_TEST_F(AppShimMenuControllerBrowserTest,
212                        DISABLED_HostedAppHasAdditionalEditMenuItems) {
213   SetUpApps(HOSTED | PACKAGED_1);
215   // Find the first hosted app window.
216   Browser* hosted_app_browser = nullptr;
217   BrowserList* browsers =
218       BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE);
219   for (Browser* browser : *browsers) {
220     const extensions::Extension* extension =
221         apps::ExtensionAppShimHandler::MaybeGetAppForBrowser(browser);
222     if (extension && extension->is_hosted_app()) {
223       hosted_app_browser = browser;
224       break;
225     }
226   }
227   EXPECT_TRUE(hosted_app_browser);
229   // Focus the hosted app.
230   [[NSNotificationCenter defaultCenter]
231       postNotificationName:NSWindowDidBecomeMainNotification
232                     object:hosted_app_browser->window()->GetNativeWindow()];
233   CheckEditMenu(hosted_app_);
235   // Now focus a platform app, the Edit menu should not have the additional
236   // options.
237   [[NSNotificationCenter defaultCenter]
238       postNotificationName:NSWindowDidBecomeMainNotification
239                     object:FirstWindowForApp(app_1_)->GetNativeWindow()];
240   CheckEditMenu(app_1_);
243 // Test that uninstalling an app restores the main menu.
244 IN_PROC_BROWSER_TEST_F(AppShimMenuControllerBrowserTest,
245                        ExtensionUninstallUpdatesMenuBar) {
246   SetUpApps(PACKAGED_1 | PACKAGED_2);
248   FirstWindowForApp(app_2_)->GetBaseWindow()->Close();
249   chrome::BrowserIterator()->window()->Close();
250   NSWindow* app_1_window = FirstWindowForApp(app_1_)->GetNativeWindow();
252   ui::test::ScopedFakeNSWindowFocus fake_focus;
253   [app_1_window makeMainWindow];
255   CheckHasAppMenus(app_1_);
256   ExtensionService::UninstallExtensionHelper(
257       extension_service(),
258       app_1_->id(),
259       extensions::UNINSTALL_REASON_FOR_TESTING);
261   // OSX will send NSWindowWillResignMainNotification when a main window is
262   // closed.
263   [[NSNotificationCenter defaultCenter]
264       postNotificationName:NSWindowDidResignMainNotification
265                     object:app_1_window];
266   CheckNoAppMenus();
269 }  // namespace