• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4
5#import "chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac.h"
6
7#import <Cocoa/Cocoa.h>
8
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"
22
23namespace {
24
25class AppShimMenuControllerBrowserTest
26    : public extensions::PlatformAppBrowserTest {
27 protected:
28  AppShimMenuControllerBrowserTest()
29      : app_1_(NULL),
30        app_2_(NULL),
31        initial_menu_item_count_(0) {}
32
33  virtual ~AppShimMenuControllerBrowserTest() {}
34
35  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
36    PlatformAppBrowserTest::SetUpCommandLine(command_line);
37  }
38
39  // Start two apps and wait for them to be launched.
40  void SetUpApps() {
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());
47
48    initial_menu_item_count_ = [[[NSApp mainMenu] itemArray] count];
49  }
50
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,
55              [item_array count]);
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;
64         ++i) {
65      NSMenuItem* menu = [item_array objectAtIndex:i];
66      EXPECT_GT([[menu submenu] numberOfItems], 0);
67      EXPECT_FALSE([menu isHidden]);
68    }
69  }
70
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]);
76  }
77
78  const extensions::Extension* app_1_;
79  const extensions::Extension* app_2_;
80  NSUInteger initial_menu_item_count_;
81
82 private:
83  DISALLOW_COPY_AND_ASSIGN(AppShimMenuControllerBrowserTest);
84};
85
86// Test that focusing an app window changes the menu bar.
87IN_PROC_BROWSER_TEST_F(AppShimMenuControllerBrowserTest,
88                       PlatformAppFocusUpdatesMenuBar) {
89  SetUpApps();
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())
94                                          .front();
95  [[NSNotificationCenter defaultCenter]
96      postNotificationName:NSWindowDidBecomeMainNotification
97                    object:app_1_app_window->GetNativeWindow()];
98  CheckHasAppMenus(app_1_);
99
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())
103                                          .front();
104  [[NSNotificationCenter defaultCenter]
105      postNotificationName:NSWindowDidBecomeMainNotification
106                    object:app_2_app_window->GetNativeWindow()];
107  CheckHasAppMenus(app_2_);
108
109  // When a browser window is focused, the menu items for the app should be
110  // removed.
111  BrowserWindow* chrome_window = chrome::BrowserIterator()->window();
112  [[NSNotificationCenter defaultCenter]
113      postNotificationName:NSWindowDidBecomeMainNotification
114                    object:chrome_window->GetNativeWindow()];
115  CheckNoAppMenus();
116
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()];
124  CheckNoAppMenus();
125}
126
127IN_PROC_BROWSER_TEST_F(AppShimMenuControllerBrowserTest,
128                       ExtensionUninstallUpdatesMenuBar) {
129  SetUpApps();
130
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
134  // windows.
135  apps::AppWindow* app_2_app_window = apps::AppWindowRegistry::Get(profile())
136                                          ->GetAppWindowsForApp(app_2_->id())
137                                          .front();
138  app_2_app_window->GetBaseWindow()->Close();
139
140  chrome::BrowserIterator()->window()->Close();
141
142  apps::AppWindow* app_1_app_window = apps::AppWindowRegistry::Get(profile())
143                                          ->GetAppWindowsForApp(app_1_->id())
144                                          .front();
145  [[NSNotificationCenter defaultCenter]
146      postNotificationName:NSWindowDidBecomeMainNotification
147                    object:app_1_app_window->GetNativeWindow()];
148
149  CheckHasAppMenus(app_1_);
150  ExtensionService::UninstallExtensionHelper(extension_service(), app_1_->id());
151  CheckNoAppMenus();
152}
153
154}  // namespace
155