Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / profiles / profile_menu_controller_unittest.mm
blob71ef63e998453b386abcb5a5966f5f63b7b8cb88
1 // Copyright 2014 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/profiles/profile_menu_controller.h"
7 #include "base/mac/scoped_nsobject.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/threading/thread_restrictions.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/profiles/profile_manager.h"
12 #include "chrome/browser/ui/browser_list.h"
13 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
14 #include "chrome/browser/ui/cocoa/run_loop_testing.h"
15 #include "chrome/common/pref_names.h"
16 #include "chrome/grit/generated_resources.h"
17 #include "chrome/test/base/test_browser_window.h"
18 #include "chrome/test/base/testing_profile.h"
19 #include "components/syncable_prefs/pref_service_syncable.h"
20 #include "testing/gtest_mac.h"
21 #include "ui/base/l10n/l10n_util_mac.h"
23 class ProfileMenuControllerTest : public CocoaProfileTest {
24  public:
25   ProfileMenuControllerTest() {
26     item_.reset([[NSMenuItem alloc] initWithTitle:@"Users"
27                                            action:nil
28                                     keyEquivalent:@""]);
29     controller_.reset(
30         [[ProfileMenuController alloc] initWithMainMenuItem:item_]);
31   }
33   void SetUp() override {
34     CocoaProfileTest::SetUp();
35     ASSERT_TRUE(profile());
37     // Spin the runloop so |-initializeMenu| gets called.
38     chrome::testing::NSRunLoopRunAllPending();
39   }
41   void TestBottomItems() {
42     NSMenu* menu = [controller() menu];
43     NSInteger count = [menu numberOfItems];
45     ASSERT_GE(count, 4);
47     NSMenuItem* item = [menu itemAtIndex:count - 4];
48     EXPECT_TRUE([item isSeparatorItem]);
50     item = [menu itemAtIndex:count - 3];
51     EXPECT_EQ(@selector(editProfile:), [item action]);
53     item = [menu itemAtIndex:count - 2];
54     EXPECT_TRUE([item isSeparatorItem]);
56     item = [menu itemAtIndex:count - 1];
57     EXPECT_EQ(@selector(newProfile:), [item action]);
58   }
60   void VerifyProfileNamedIsActive(NSString* title, int line) {
61     for (NSMenuItem* item in [[controller() menu] itemArray]) {
62       if ([[item title] isEqualToString:title]) {
63         EXPECT_EQ(NSOnState, [item state]) << [[item title] UTF8String]
64           << " (from line " << line << ")";
65       } else {
66         EXPECT_EQ(NSOffState, [item state]) << [[item title] UTF8String]
67           << " (from line " << line << ")";
68       }
69     }
70   }
72   ProfileMenuController* controller() { return controller_.get(); }
74   NSMenuItem* menu_item() { return item_.get(); }
76  private:
77   base::scoped_nsobject<NSMenuItem> item_;
78   base::scoped_nsobject<ProfileMenuController> controller_;
81 TEST_F(ProfileMenuControllerTest, InitializeMenu) {
82   NSMenu* menu = [controller() menu];
83   // Profile, <sep>, Edit, <sep>, New.
84   ASSERT_EQ(5, [menu numberOfItems]);
86   TestBottomItems();
88   EXPECT_FALSE([menu_item() isHidden]);
91 TEST_F(ProfileMenuControllerTest, CreateItemWithTitle) {
92   NSMenuItem* item =
93       [controller() createItemWithTitle:@"Title"
94                                  action:@selector(someSelector:)];
95   EXPECT_NSEQ(@"Title", [item title]);
96   EXPECT_EQ(controller(), [item target]);
97   EXPECT_EQ(@selector(someSelector:), [item action]);
98   EXPECT_NSEQ(@"", [item keyEquivalent]);
101 TEST_F(ProfileMenuControllerTest, RebuildMenu) {
102   NSMenu* menu = [controller() menu];
103   EXPECT_EQ(5, [menu numberOfItems]);
105   EXPECT_FALSE([menu_item() isHidden]);
107   // Create some more profiles on the manager.
108   TestingProfileManager* manager = testing_profile_manager();
109   manager->CreateTestingProfile("Profile 2");
110   manager->CreateTestingProfile("Profile 3");
112   // Verify that the menu got rebuilt.
113   ASSERT_EQ(7, [menu numberOfItems]);
115   NSMenuItem* item = [menu itemAtIndex:0];
116   EXPECT_EQ(@selector(switchToProfileFromMenu:), [item action]);
118   item = [menu itemAtIndex:1];
119   EXPECT_EQ(@selector(switchToProfileFromMenu:), [item action]);
121   item = [menu itemAtIndex:2];
122   EXPECT_EQ(@selector(switchToProfileFromMenu:), [item action]);
124   TestBottomItems();
126   EXPECT_FALSE([menu_item() isHidden]);
129 TEST_F(ProfileMenuControllerTest, InsertItems) {
130   base::scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@""]);
131   ASSERT_EQ(0, [menu numberOfItems]);
133   // Even with one profile items can still be inserted.
134   BOOL result = [controller() insertItemsIntoMenu:menu
135                                          atOffset:0
136                                          fromDock:NO];
137   EXPECT_TRUE(result);
138   EXPECT_EQ(1, [menu numberOfItems]);
139   [menu removeAllItems];
141   // Same for use in building the dock menu.
142   result = [controller() insertItemsIntoMenu:menu
143                                     atOffset:0
144                                     fromDock:YES];
145   EXPECT_FALSE(result);
146   EXPECT_EQ(0, [menu numberOfItems]);
147   [menu removeAllItems];
149   // Create one more profile on the manager.
150   TestingProfileManager* manager = testing_profile_manager();
151   manager->CreateTestingProfile("Profile 2");
153   // With more than one profile, insertItems should return YES.
154   result = [controller() insertItemsIntoMenu:menu
155                                     atOffset:0
156                                     fromDock:NO];
157   EXPECT_TRUE(result);
158   ASSERT_EQ(2, [menu numberOfItems]);
160   NSMenuItem* item = [menu itemAtIndex:0];
161   EXPECT_EQ(@selector(switchToProfileFromMenu:), [item action]);
163   item = [menu itemAtIndex:1];
164   EXPECT_EQ(@selector(switchToProfileFromMenu:), [item action]);
165   [menu removeAllItems];
167   // And for the dock, the selector should be different and there should be a
168   // header item.
169   result = [controller() insertItemsIntoMenu:menu
170                                     atOffset:0
171                                     fromDock:YES];
172   EXPECT_TRUE(result);
173   ASSERT_EQ(3, [menu numberOfItems]);
175   // First item is a label item.
176   item = [menu itemAtIndex:0];
177   EXPECT_FALSE([item isEnabled]);
179   item = [menu itemAtIndex:1];
180   EXPECT_EQ(@selector(switchToProfileFromDock:), [item action]);
182   item = [menu itemAtIndex:2];
183   EXPECT_EQ(@selector(switchToProfileFromDock:), [item action]);
186 TEST_F(ProfileMenuControllerTest, InitialActiveBrowser) {
187   [controller() activeBrowserChangedTo:NULL];
188   VerifyProfileNamedIsActive(l10n_util::GetNSString(IDS_DEFAULT_PROFILE_NAME),
189                              __LINE__);
192 // Note: BrowserList::SetLastActive() is typically called as part of
193 // BrowserWindow::Show() and when a Browser becomes active. We don't need a full
194 // BrowserWindow, so it is called manually.
195 TEST_F(ProfileMenuControllerTest, SetActiveAndRemove) {
196   NSMenu* menu = [controller() menu];
197   TestingProfileManager* manager = testing_profile_manager();
198   TestingProfile* profile2 = manager->CreateTestingProfile("Profile 2");
199   TestingProfile* profile3 = manager->CreateTestingProfile("Profile 3");
200   ASSERT_EQ(7, [menu numberOfItems]);
202   // Create a browser and "show" it.
203   Browser::CreateParams profile2_params(profile2, chrome::GetActiveDesktop());
204   scoped_ptr<Browser> p2_browser(
205       chrome::CreateBrowserWithTestWindowForParams(&profile2_params));
206   BrowserList::SetLastActive(p2_browser.get());
207   VerifyProfileNamedIsActive(@"Profile 2", __LINE__);
209   // Close the browser and make sure it's still active.
210   p2_browser.reset();
211   VerifyProfileNamedIsActive(@"Profile 2", __LINE__);
213   // Open a new browser and make sure it takes effect.
214   Browser::CreateParams profile3_params(profile3, chrome::GetActiveDesktop());
215   scoped_ptr<Browser> p3_browser(
216       chrome::CreateBrowserWithTestWindowForParams(&profile3_params));
217   BrowserList::SetLastActive(p3_browser.get());
218   VerifyProfileNamedIsActive(@"Profile 3", __LINE__);
220   p3_browser.reset();
221   VerifyProfileNamedIsActive(@"Profile 3", __LINE__);
224 TEST_F(ProfileMenuControllerTest, DeleteActiveProfile) {
225   TestingProfileManager* manager = testing_profile_manager();
227   manager->CreateTestingProfile("Profile 2");
228   TestingProfile* profile3 = manager->CreateTestingProfile("Profile 3");
229   ASSERT_EQ(3U, manager->profile_manager()->GetNumberOfProfiles());
231   const base::FilePath profile3_path = profile3->GetPath();
232   manager->DeleteTestingProfile("Profile 3");
234   // Simulate an unloaded profile by setting the "last used" local state pref
235   // the profile that was just deleted.
236   PrefService* local_state = g_browser_process->local_state();
237   local_state->SetString(prefs::kProfileLastUsed,
238                          profile3_path.BaseName().MaybeAsASCII());
240   // Simulate the active browser changing to NULL and ensure a profile doesn't
241   // get created by disallowing IO operations temporarily.
242   const bool io_was_allowed = base::ThreadRestrictions::SetIOAllowed(false);
243   [controller() activeBrowserChangedTo:NULL];
244   base::ThreadRestrictions::SetIOAllowed(io_was_allowed);
247 TEST_F(ProfileMenuControllerTest, SupervisedProfile) {
248   TestingProfileManager* manager = testing_profile_manager();
249   TestingProfile* supervised_profile = manager->CreateTestingProfile(
250       "test1", scoped_ptr<syncable_prefs::PrefServiceSyncable>(),
251       base::ASCIIToUTF16("Supervised User"), 0, "TEST_ID",
252       TestingProfile::TestingFactories());
253   // The supervised profile is initially marked as omitted from the avatar menu
254   // (in non-test code, until we have confirmation that it has actually been
255   // created on the server). For the test, just tell the cache to un-hide it.
256   ProfileInfoCache* cache = manager->profile_info_cache();
257   size_t index =
258       cache->GetIndexOfProfileWithPath(supervised_profile->GetPath());
259   cache->SetIsOmittedProfileAtIndex(index, false);
261   BrowserList::SetLastActive(browser());
263   NSMenu* menu = [controller() menu];
264   // Person 1, Supervised User, <sep>, Edit, <sep>, New.
265   ASSERT_EQ(6, [menu numberOfItems]);
267   NSMenuItem* item = [menu itemAtIndex:0];
268   ASSERT_EQ(@selector(switchToProfileFromMenu:), [item action]);
269   EXPECT_TRUE([controller() validateMenuItem:item]);
271   item = [menu itemAtIndex:1];
272   ASSERT_EQ(@selector(switchToProfileFromMenu:), [item action]);
273   EXPECT_TRUE([controller() validateMenuItem:item]);
275   item = [menu itemAtIndex:5];
276   ASSERT_EQ(@selector(newProfile:), [item action]);
277   EXPECT_TRUE([controller() validateMenuItem:item]);
279   // Open a new browser for the supervised user and switch to it.
280   Browser::CreateParams supervised_profile_params(
281       supervised_profile, chrome::HOST_DESKTOP_TYPE_NATIVE);
282   scoped_ptr<Browser> supervised_browser(
283       chrome::CreateBrowserWithTestWindowForParams(&supervised_profile_params));
284   BrowserList::SetLastActive(supervised_browser.get());
286   item = [menu itemAtIndex:0];
287   ASSERT_EQ(@selector(switchToProfileFromMenu:), [item action]);
288   EXPECT_FALSE([controller() validateMenuItem:item]);
290   item = [menu itemAtIndex:1];
291   ASSERT_EQ(@selector(switchToProfileFromMenu:), [item action]);
292   EXPECT_TRUE([controller() validateMenuItem:item]);
294   item = [menu itemAtIndex:5];
295   ASSERT_EQ(@selector(newProfile:), [item action]);
296   EXPECT_FALSE([controller() validateMenuItem:item]);