[M120 Migration]Fix for crash during chrome exit
[platform/framework/web/chromium-efl.git] / chrome / browser / app_controller_mac_browsertest.mm
1 // Copyright 2012 The Chromium Authors
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 <Cocoa/Cocoa.h>
6 #import <Foundation/Foundation.h>
7 #import <objc/runtime.h>
8 #include <stddef.h>
9
10 #include <string>
11
12 #include "base/apple/foundation_util.h"
13 #include "base/apple/scoped_objc_class_swizzler.h"
14 #include "base/command_line.h"
15 #include "base/functional/bind.h"
16 #include "base/functional/callback_helpers.h"
17 #include "base/memory/raw_ptr.h"
18 #include "base/path_service.h"
19 #include "base/run_loop.h"
20 #include "base/scoped_observation.h"
21 #include "base/strings/string_util.h"
22 #include "base/strings/sys_string_conversions.h"
23 #include "base/strings/utf_string_conversions.h"
24 #include "base/test/metrics/histogram_tester.h"
25 #include "base/test/scoped_feature_list.h"
26 #include "base/threading/thread_restrictions.h"
27 #include "chrome/app/chrome_command_ids.h"
28 #import "chrome/browser/app_controller_mac.h"
29 #include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
30 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
31 #include "chrome/browser/browser_features.h"
32 #include "chrome/browser/browser_process.h"
33 #include "chrome/browser/first_run/first_run.h"
34 #include "chrome/browser/history/history_service_factory.h"
35 #include "chrome/browser/lifetime/application_lifetime.h"
36 #include "chrome/browser/lifetime/application_lifetime_desktop.h"
37 #include "chrome/browser/prefs/incognito_mode_prefs.h"
38 #include "chrome/browser/profiles/delete_profile_helper.h"
39 #include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h"
40 #include "chrome/browser/profiles/profile_attributes_entry.h"
41 #include "chrome/browser/profiles/profile_attributes_init_params.h"
42 #include "chrome/browser/profiles/profile_attributes_storage.h"
43 #include "chrome/browser/profiles/profile_manager.h"
44 #include "chrome/browser/profiles/profile_metrics.h"
45 #include "chrome/browser/profiles/profile_observer.h"
46 #include "chrome/browser/profiles/profile_test_util.h"
47 #include "chrome/browser/signin/signin_features.h"
48 #include "chrome/browser/signin/signin_util.h"
49 #include "chrome/browser/ui/browser.h"
50 #include "chrome/browser/ui/browser_finder.h"
51 #include "chrome/browser/ui/browser_list.h"
52 #include "chrome/browser/ui/browser_navigator_params.h"
53 #include "chrome/browser/ui/browser_window.h"
54 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.h"
55 #include "chrome/browser/ui/cocoa/history_menu_bridge.h"
56 #include "chrome/browser/ui/cocoa/last_active_browser_cocoa.h"
57 #include "chrome/browser/ui/cocoa/test/run_loop_testing.h"
58 #include "chrome/browser/ui/profiles/profile_picker.h"
59 #include "chrome/browser/ui/profiles/profile_ui_test_utils.h"
60 #include "chrome/browser/ui/search/ntp_test_utils.h"
61 #include "chrome/browser/ui/startup/first_run_service.h"
62 #include "chrome/browser/ui/tabs/tab_enums.h"
63 #include "chrome/browser/ui/tabs/tab_strip_model.h"
64 #include "chrome/browser/ui/ui_features.h"
65 #include "chrome/browser/ui/webui/welcome/helpers.h"
66 #include "chrome/common/chrome_constants.h"
67 #include "chrome/common/chrome_features.h"
68 #include "chrome/common/chrome_paths.h"
69 #include "chrome/common/chrome_switches.h"
70 #include "chrome/common/pref_names.h"
71 #include "chrome/common/url_constants.h"
72 #include "chrome/test/base/in_process_browser_test.h"
73 #include "chrome/test/base/ui_test_utils.h"
74 #include "components/account_id/account_id.h"
75 #include "components/bookmarks/browser/bookmark_model.h"
76 #include "components/bookmarks/test/bookmark_test_helpers.h"
77 #include "components/policy/core/common/policy_pref_names.h"
78 #include "components/prefs/pref_service.h"
79 #include "content/public/browser/navigation_controller.h"
80 #include "content/public/browser/web_contents.h"
81 #include "content/public/test/browser_test.h"
82 #include "content/public/test/browser_test_utils.h"
83 #include "content/public/test/prerender_test_util.h"
84 #include "content/public/test/test_navigation_observer.h"
85 #include "extensions/browser/app_window/app_window_registry.h"
86 #include "extensions/browser/extension_dialog_auto_confirm.h"
87 #include "extensions/common/extension.h"
88 #include "extensions/test/extension_test_message_listener.h"
89 #include "net/base/mac/url_conversions.h"
90 #include "net/dns/mock_host_resolver.h"
91 #include "net/test/embedded_test_server/embedded_test_server.h"
92 #include "third_party/blink/public/common/features.h"
93 #import "ui/events/test/cocoa_test_event_utils.h"
94 #include "ui/views/test/dialog_test.h"
95 #include "ui/views/widget/any_widget_observer.h"
96 #include "ui/views/widget/widget.h"
97
98 namespace {
99
100 GURL g_open_shortcut_url = GURL::EmptyGURL();
101
102 // Instructs the NSApp's delegate to open |url|.
103 void SendOpenUrlToAppController(const GURL& url) {
104   [NSApp.delegate application:NSApp openURLs:@[ net::NSURLWithGURL(url) ]];
105 }
106
107 Profile& CreateAndWaitForProfile(const base::FilePath& profile_dir) {
108   Profile& profile = profiles::testing::CreateProfileSync(
109       g_browser_process->profile_manager(), profile_dir);
110   return profile;
111 }
112
113 void CreateAndWaitForSystemProfile() {
114   CreateAndWaitForProfile(ProfileManager::GetSystemProfilePath());
115 }
116
117 Profile& CreateAndWaitForGuestProfile() {
118   return CreateAndWaitForProfile(ProfileManager::GetGuestProfilePath());
119 }
120
121 void SetGuestProfileAsLastProfile() {
122   AppController* app_controller = AppController.sharedController;
123
124   // Create the guest profile, and set it as the last used profile.
125   Profile& guest_profile = CreateAndWaitForGuestProfile();
126   [app_controller setLastProfile:&guest_profile];
127
128   Profile* profile = [app_controller lastProfileIfLoaded];
129   ASSERT_TRUE(profile);
130   EXPECT_EQ(guest_profile.GetPath(), profile->GetPath());
131   EXPECT_TRUE(profile->IsGuestSession());
132
133   // Also set the last used profile path preference. If the profile does need to
134   // be read from disk for some reason this acts as a backstop.
135   g_browser_process->local_state()->SetString(
136       prefs::kProfileLastUsed, guest_profile.GetPath().BaseName().value());
137 }
138
139 // Key for ProfileDestroyedData user data.
140 const char kProfileDestructionWaiterUserDataKey = 0;
141
142 // Waits until the Profile instance is destroyed.
143 class ProfileDestructionWaiter {
144  public:
145   explicit ProfileDestructionWaiter(Profile* profile) {
146     profile->SetUserData(
147         &kProfileDestructionWaiterUserDataKey,
148         std::make_unique<ProfileDestroyedData>(run_loop_.QuitClosure()));
149   }
150
151   void Wait() { run_loop_.Run(); }
152
153  private:
154   // Simple user data that calls a callback at destruction.
155   class ProfileDestroyedData : public base::SupportsUserData::Data {
156    public:
157     explicit ProfileDestroyedData(base::OnceClosure callback)
158         : scoped_closure_runner_(std::move(callback)) {}
159
160    private:
161     base::ScopedClosureRunner scoped_closure_runner_;
162   };
163
164   base::RunLoop run_loop_;
165 };
166
167 }  // namespace
168
169 @interface TestOpenShortcutOnStartup : NSObject
170 - (void)applicationWillFinishLaunching:(NSNotification*)notification;
171 @end
172
173 @implementation TestOpenShortcutOnStartup
174
175 - (void)applicationWillFinishLaunching:(NSNotification*)notification {
176   if (!g_open_shortcut_url.is_valid())
177     return;
178
179   SendOpenUrlToAppController(g_open_shortcut_url);
180 }
181
182 @end
183
184 namespace {
185
186 using AppControllerBrowserTest = InProcessBrowserTest;
187
188 // Returns whether a window's pixels are actually on the screen, which is the
189 // case when it and all of its parents are marked visible.
190 bool IsReallyVisible(NSWindow* window) {
191   while (window) {
192     if (!window.visible)
193       return false;
194     window = [window parentWindow];
195   }
196   return true;
197 }
198
199 size_t CountVisibleWindows() {
200   size_t count = 0;
201   for (NSWindow* w in [NSApp windows])
202     count = count + (IsReallyVisible(w) ? 1 : 0);
203   return count;
204 }
205
206 // Returns how many visible NSWindows are expected for a given count of browser
207 // windows.
208 size_t ExpectedWindowCountForBrowserCount(size_t browsers) {
209   return browsers;
210 }
211
212 // Test browser shutdown with a command in the message queue.
213 IN_PROC_BROWSER_TEST_F(AppControllerBrowserTest, CommandDuringShutdown) {
214   EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
215   EXPECT_EQ(ExpectedWindowCountForBrowserCount(1), CountVisibleWindows());
216
217   chrome::AttemptExit();  // Set chrome::IsTryingToQuit and close all windows.
218
219   // Opening a new window here is fine (unload handlers can also interrupt
220   // exit). But closing the window posts an autorelease on
221   // BrowserWindowController, which calls ~Browser() and, if that was the last
222   // Browser, it invokes applicationWillTerminate: (because IsTryingToQuit is
223   // set). So, verify assumptions then process that autorelease.
224
225   EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
226   EXPECT_EQ(ExpectedWindowCountForBrowserCount(0), CountVisibleWindows());
227
228   base::RunLoop().RunUntilIdle();
229
230   EXPECT_EQ(0u, chrome::GetTotalBrowserCount());
231   EXPECT_EQ(ExpectedWindowCountForBrowserCount(0), CountVisibleWindows());
232
233   NSEvent* cmd_n = cocoa_test_event_utils::KeyEventWithKeyCode(
234       'n', 'n', NSEventTypeKeyDown, NSEventModifierFlagCommand);
235   [[NSApp mainMenu] performSelector:@selector(performKeyEquivalent:)
236                          withObject:cmd_n
237                          afterDelay:0];
238   // Let the run loop get flushed, during process cleanup and try not to crash.
239 }
240
241 // Regression test for https://crbug.com/1236073
242 // TODO(crbug.com/1373692): Extremely flaky on the mac12-arm64-rel bot.
243 IN_PROC_BROWSER_TEST_F(AppControllerBrowserTest,
244                        DISABLED_DeleteEphemeralProfile) {
245   EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
246   Profile* profile = browser()->profile();
247   // Activate the first profile.
248   [NSNotificationCenter.defaultCenter
249       postNotificationName:NSWindowDidBecomeMainNotification
250                     object:browser()
251                                ->window()
252                                ->GetNativeWindow()
253                                .GetNativeNSWindow()];
254   AppController* app_controller = AppController.sharedController;
255   ASSERT_EQ(profile, app_controller.lastProfileIfLoaded);
256
257   // Mark the profile as ephemeral.
258   profile->GetPrefs()->SetBoolean(prefs::kForceEphemeralProfiles, true);
259   ProfileManager* profile_manager = g_browser_process->profile_manager();
260   ProfileAttributesStorage& storage =
261       profile_manager->GetProfileAttributesStorage();
262   ProfileAttributesEntry* entry =
263       storage.GetProfileAttributesWithPath(profile->GetPath());
264   EXPECT_TRUE(entry->IsEphemeral());
265
266   // Add sentinel data to observe profile destruction. Ephemeral profiles are
267   // destroyed immediately upon browser close.
268   ProfileDestructionWaiter waiter(profile);
269
270   // Close browser and wait for the profile to be deleted.
271   CloseBrowserSynchronously(browser());
272   waiter.Wait();
273   EXPECT_EQ(0u, chrome::GetTotalBrowserCount());
274
275   // Create a new profile and activate it.
276   Profile& profile2 = CreateAndWaitForProfile(
277       profile_manager->user_data_dir().AppendASCII("Profile 2"));
278   Browser* browser2 = CreateBrowser(&profile2);
279   // This should not crash.
280   [[NSNotificationCenter defaultCenter]
281       postNotificationName:NSWindowDidBecomeMainNotification
282                     object:browser2->window()
283                                ->GetNativeWindow()
284                                .GetNativeNSWindow()];
285   ASSERT_EQ(&profile2, app_controller.lastProfileIfLoaded);
286 }
287
288 class AppControllerKeepAliveBrowserTest : public InProcessBrowserTest {
289  protected:
290   AppControllerKeepAliveBrowserTest() {
291     features_.InitAndEnableFeature(features::kDestroyProfileOnBrowserClose);
292   }
293
294   base::test::ScopedFeatureList features_;
295 };
296
297 class AppControllerPlatformAppBrowserTest
298     : public extensions::PlatformAppBrowserTest {
299  protected:
300   AppControllerPlatformAppBrowserTest()
301       : active_browser_list_(BrowserList::GetInstance()) {}
302
303   void SetUpCommandLine(base::CommandLine* command_line) override {
304     PlatformAppBrowserTest::SetUpCommandLine(command_line);
305     command_line->AppendSwitchASCII(switches::kAppId,
306                                     "1234");
307   }
308
309   raw_ptr<const BrowserList> active_browser_list_;
310 };
311
312 // Test that if only a platform app window is open and no browser windows are
313 // open then a reopen event does nothing.
314 IN_PROC_BROWSER_TEST_F(AppControllerPlatformAppBrowserTest,
315                        DISABLED_PlatformAppReopenWithWindows) {
316   NSUInteger old_window_count = NSApp.windows.count;
317   EXPECT_EQ(1u, active_browser_list_->size());
318   [AppController.sharedController applicationShouldHandleReopen:NSApp
319                                               hasVisibleWindows:YES];
320   // We do not EXPECT_TRUE the result here because the method
321   // deminiaturizes windows manually rather than return YES and have
322   // AppKit do it.
323
324   EXPECT_EQ(old_window_count, NSApp.windows.count);
325   EXPECT_EQ(1u, active_browser_list_->size());
326 }
327
328 IN_PROC_BROWSER_TEST_F(AppControllerPlatformAppBrowserTest,
329                        DISABLED_ActivationFocusesBrowserWindow) {
330   ExtensionTestMessageListener listener("Launched");
331   const extensions::Extension* app =
332       InstallAndLaunchPlatformApp("minimal");
333   ASSERT_TRUE(listener.WaitUntilSatisfied());
334
335   NSWindow* app_window = extensions::AppWindowRegistry::Get(profile())
336                              ->GetAppWindowsForApp(app->id())
337                              .front()
338                              ->GetNativeWindow()
339                              .GetNativeNSWindow();
340   NSWindow* browser_window =
341       browser()->window()->GetNativeWindow().GetNativeNSWindow();
342
343   chrome::testing::NSRunLoopRunAllPending();
344   EXPECT_LE([NSApp.orderedWindows indexOfObject:app_window],
345             [NSApp.orderedWindows indexOfObject:browser_window]);
346   [AppController.sharedController applicationShouldHandleReopen:NSApp
347                                               hasVisibleWindows:YES];
348   chrome::testing::NSRunLoopRunAllPending();
349   EXPECT_LE([NSApp.orderedWindows indexOfObject:browser_window],
350             [NSApp.orderedWindows indexOfObject:app_window]);
351 }
352
353 class AppControllerWebAppBrowserTest : public InProcessBrowserTest {
354  protected:
355   AppControllerWebAppBrowserTest()
356       : active_browser_list_(BrowserList::GetInstance()) {}
357
358   void SetUpCommandLine(base::CommandLine* command_line) override {
359     command_line->AppendSwitchASCII(switches::kApp, GetAppURL());
360   }
361
362   std::string GetAppURL() const {
363     return "http://example.com/";
364   }
365
366   raw_ptr<const BrowserList> active_browser_list_;
367 };
368
369 // Test that in web app mode a reopen event opens the app URL.
370 IN_PROC_BROWSER_TEST_F(AppControllerWebAppBrowserTest,
371                        WebAppReopenWithNoWindows) {
372   EXPECT_EQ(1u, active_browser_list_->size());
373   BOOL result =
374       [AppController.sharedController applicationShouldHandleReopen:NSApp
375                                                   hasVisibleWindows:NO];
376
377   EXPECT_FALSE(result);
378   EXPECT_EQ(2u, active_browser_list_->size());
379
380   Browser* browser = active_browser_list_->get(0);
381   GURL current_url =
382       browser->tab_strip_model()->GetActiveWebContents()->GetURL();
383   EXPECT_EQ(GetAppURL(), current_url.spec());
384 }
385
386 class AppControllerProfilePickerBrowserTest : public InProcessBrowserTest {
387  public:
388   AppControllerProfilePickerBrowserTest()
389       : active_browser_list_(BrowserList::GetInstance()) {}
390   ~AppControllerProfilePickerBrowserTest() override = default;
391
392   void SetUpOnMainThread() override {
393     InProcessBrowserTest::SetUpOnMainThread();
394
395     // Flag the profile picker as already shown in the past, to avoid additional
396     // feature onboarding logic.
397     g_browser_process->local_state()->SetBoolean(
398         prefs::kBrowserProfilePickerShown, true);
399   }
400
401   const BrowserList* active_browser_list() const {
402     return active_browser_list_;
403   }
404
405  private:
406   raw_ptr<const BrowserList> active_browser_list_;
407 };
408
409 // Test that for a guest last profile, commandDispatch should open UserManager
410 // if guest mode is disabled. Note that this test might be flaky under ASAN
411 // due to https://crbug.com/674475. Please disable this test under ASAN
412 // as the tests below if that happened.
413 IN_PROC_BROWSER_TEST_F(AppControllerProfilePickerBrowserTest,
414                        OpenGuestProfileOnlyIfGuestModeIsEnabled) {
415   SetGuestProfileAsLastProfile();
416
417   PrefService* local_state = g_browser_process->local_state();
418   local_state->SetBoolean(prefs::kBrowserGuestModeEnabled, false);
419   AppController* app_controller = AppController.sharedController;
420   NSMenu* menu = [app_controller applicationDockMenu:NSApp];
421   ASSERT_TRUE(menu);
422   NSMenuItem* item = [menu itemWithTag:IDC_NEW_WINDOW];
423   ASSERT_TRUE(item);
424   EXPECT_EQ(1u, active_browser_list()->size());
425
426   [app_controller commandDispatch:item];
427
428   base::RunLoop().RunUntilIdle();
429
430   EXPECT_EQ(1u, active_browser_list()->size());
431   EXPECT_TRUE(ProfilePicker::IsOpen());
432   ProfilePicker::Hide();
433
434   local_state->SetBoolean(prefs::kBrowserGuestModeEnabled, true);
435   [app_controller commandDispatch:item];
436   base::RunLoop().RunUntilIdle();
437   EXPECT_EQ(2u, active_browser_list()->size());
438   EXPECT_FALSE(ProfilePicker::IsOpen());
439 }
440
441 IN_PROC_BROWSER_TEST_F(AppControllerProfilePickerBrowserTest,
442                        AboutChromeGuestDisallowed) {
443   SetGuestProfileAsLastProfile();
444
445   // Disallow guest by policy and make sure "About Chrome" is not available
446   // in the menu.
447   PrefService* local_state = g_browser_process->local_state();
448   local_state->SetBoolean(prefs::kBrowserGuestModeEnabled, false);
449   NSMenuItem* about_menu_item = [[[NSApp.mainMenu itemWithTag:IDC_CHROME_MENU]
450       submenu] itemWithTag:IDC_ABOUT];
451   EXPECT_FALSE([AppController.sharedController
452       validateUserInterfaceItem:about_menu_item]);
453 }
454
455 // Test that for a regular last profile, a reopen event opens a browser.
456 IN_PROC_BROWSER_TEST_F(AppControllerProfilePickerBrowserTest,
457                        RegularProfileReopenWithNoWindows) {
458   EXPECT_EQ(1u, active_browser_list()->size());
459   BOOL result =
460       [AppController.sharedController applicationShouldHandleReopen:NSApp
461                                                   hasVisibleWindows:NO];
462
463   EXPECT_FALSE(result);
464   EXPECT_EQ(2u, active_browser_list()->size());
465   EXPECT_FALSE(ProfilePicker::IsOpen());
466 }
467
468 // Test that for a locked last profile, a reopen event opens the ProfilePicker.
469 IN_PROC_BROWSER_TEST_F(AppControllerProfilePickerBrowserTest,
470                        LockedProfileReopenWithNoWindows) {
471   signin_util::ScopedForceSigninSetterForTesting signin_setter(true);
472   // The User Manager uses the system profile as its underlying profile. To
473   // minimize flakiness due to the scheduling/descheduling of tasks on the
474   // different threads, pre-initialize the guest profile before it is needed.
475   CreateAndWaitForSystemProfile();
476   AppController* app_controller = AppController.sharedController;
477
478   // Lock the active profile.
479   Profile* profile = [app_controller lastProfileIfLoaded];
480   ProfileAttributesEntry* entry =
481       g_browser_process->profile_manager()
482           ->GetProfileAttributesStorage()
483           .GetProfileAttributesWithPath(profile->GetPath());
484   ASSERT_NE(entry, nullptr);
485   entry->LockForceSigninProfile(true);
486   EXPECT_TRUE(entry->IsSigninRequired());
487
488   EXPECT_EQ(1u, active_browser_list()->size());
489   BOOL result = [app_controller applicationShouldHandleReopen:NSApp
490                                             hasVisibleWindows:NO];
491   EXPECT_FALSE(result);
492
493   base::RunLoop().RunUntilIdle();
494   EXPECT_EQ(1u, active_browser_list()->size());
495   EXPECT_TRUE(ProfilePicker::IsOpen());
496   ProfilePicker::Hide();
497 }
498
499 // "About Chrome" does not unlock the profile (regression test for
500 // https://crbug.com/1226844).
501 IN_PROC_BROWSER_TEST_F(AppControllerProfilePickerBrowserTest,
502                        AboutPanelDoesNotUnlockProfile) {
503   signin_util::ScopedForceSigninSetterForTesting signin_setter(true);
504   // The User Manager uses the system profile as its underlying profile. To
505   // minimize flakiness due to the scheduling/descheduling of tasks on the
506   // different threads, pre-initialize the guest profile before it is needed.
507   CreateAndWaitForSystemProfile();
508   AppController* app_controller = AppController.sharedController;
509   // Lock the active profile.
510   Profile* profile = [app_controller lastProfileIfLoaded];
511   ProfileAttributesEntry* entry =
512       g_browser_process->profile_manager()
513           ->GetProfileAttributesStorage()
514           .GetProfileAttributesWithPath(profile->GetPath());
515   ASSERT_NE(entry, nullptr);
516   entry->LockForceSigninProfile(true);
517   EXPECT_TRUE(entry->IsSigninRequired());
518   EXPECT_EQ(1u, active_browser_list()->size());
519   Browser* browser = active_browser_list()->get(0);
520   EXPECT_FALSE(browser->profile()->IsGuestSession());
521   // "About Chrome" is not available in the menu.
522   NSMenu* chrome_submenu =
523       [[NSApp.mainMenu itemWithTag:IDC_CHROME_MENU] submenu];
524   NSMenuItem* about_menu_item = [chrome_submenu itemWithTag:IDC_ABOUT];
525   EXPECT_FALSE([app_controller validateUserInterfaceItem:about_menu_item]);
526   [chrome_submenu update];
527   EXPECT_FALSE([about_menu_item isEnabled]);
528 }
529
530 // Test that for a guest last profile, a reopen event opens the ProfilePicker.
531 IN_PROC_BROWSER_TEST_F(AppControllerProfilePickerBrowserTest,
532                        GuestProfileReopenWithNoWindows) {
533   SetGuestProfileAsLastProfile();
534
535   EXPECT_EQ(1u, active_browser_list()->size());
536   BOOL result =
537       [AppController.sharedController applicationShouldHandleReopen:NSApp
538                                                   hasVisibleWindows:NO];
539   EXPECT_FALSE(result);
540
541   base::RunLoop().RunUntilIdle();
542
543   EXPECT_EQ(1u, active_browser_list()->size());
544   EXPECT_TRUE(ProfilePicker::IsOpen());
545   ProfilePicker::Hide();
546 }
547
548 // Test that the ProfilePicker is shown when there are multiple profiles.
549 IN_PROC_BROWSER_TEST_F(AppControllerProfilePickerBrowserTest,
550                        MultiProfilePickerShown) {
551   CreateAndWaitForSystemProfile();
552
553   // Add a profile in the cache (simulate another profile on disk).
554   ProfileManager* profile_manager = g_browser_process->profile_manager();
555   ProfileAttributesStorage* profile_storage =
556       &profile_manager->GetProfileAttributesStorage();
557   const base::FilePath profile_path =
558       profile_manager->GenerateNextProfileDirectoryPath();
559   ProfileAttributesInitParams params;
560   params.profile_path = profile_path;
561   params.profile_name = u"name_1";
562   profile_storage->AddProfile(std::move(params));
563
564   EXPECT_EQ(1u, active_browser_list()->size());
565   BOOL result =
566       [AppController.sharedController applicationShouldHandleReopen:NSApp
567                                                   hasVisibleWindows:NO];
568   EXPECT_FALSE(result);
569
570   base::RunLoop().RunUntilIdle();
571   EXPECT_EQ(1u, active_browser_list()->size());
572   EXPECT_TRUE(ProfilePicker::IsOpen());
573   ProfilePicker::Hide();
574 }
575
576 // Checks that menu items and commands work when the profile picker is open.
577 IN_PROC_BROWSER_TEST_F(AppControllerProfilePickerBrowserTest, MenuCommands) {
578   // Show the profile picker.
579   ProfilePicker::Show(ProfilePicker::Params::FromEntryPoint(
580       ProfilePicker::EntryPoint::kProfileMenuManageProfiles));
581
582   AppController* app_controller = AppController.sharedController;
583
584   // Unhandled menu items are disabled.
585   NSMenu* file_submenu = [[NSApp.mainMenu itemWithTag:IDC_FILE_MENU] submenu];
586   NSMenuItem* close_tab_menu_item = [file_submenu itemWithTag:IDC_CLOSE_TAB];
587   EXPECT_FALSE([app_controller validateUserInterfaceItem:close_tab_menu_item]);
588   [file_submenu update];
589   EXPECT_FALSE([close_tab_menu_item isEnabled]);
590
591   // Enabled menu items work.
592   NSMenuItem* new_window_menu_item = [file_submenu itemWithTag:IDC_NEW_WINDOW];
593   EXPECT_TRUE([new_window_menu_item isEnabled]);
594   EXPECT_TRUE([app_controller validateUserInterfaceItem:new_window_menu_item]);
595   // Click on the item and checks that a new browser is opened.
596   ui_test_utils::BrowserChangeObserver browser_added_observer(
597       nullptr, ui_test_utils::BrowserChangeObserver::ChangeType::kAdded);
598   [file_submenu
599       performActionForItemAtIndex:[file_submenu
600                                       indexOfItemWithTag:IDC_NEW_WINDOW]];
601   EXPECT_TRUE(browser_added_observer.Wait());
602 }
603
604 class AppControllerFirstRunBrowserTest : public AppControllerBrowserTest {
605  public:
606   void SetUpDefaultCommandLine(base::CommandLine* command_line) override {
607     InProcessBrowserTest::SetUpDefaultCommandLine(command_line);
608     command_line->RemoveSwitch(switches::kNoFirstRun);
609   }
610
611  private:
612   base::test::ScopedFeatureList scoped_feature_list_{kForYouFre};
613 };
614
615 IN_PROC_BROWSER_TEST_F(AppControllerFirstRunBrowserTest,
616                        OpenNewWindowWhileFreIsRunning) {
617   EXPECT_TRUE(ProfilePicker::IsFirstRunOpen());
618   EXPECT_EQ(BrowserList::GetInstance()->size(), 0u);
619   AppController* app_controller = AppController.sharedController;
620   NSMenu* menu = [app_controller applicationDockMenu:NSApp];
621   ASSERT_TRUE(menu);
622
623   NSMenuItem* item = [menu itemWithTag:IDC_NEW_WINDOW];
624   ASSERT_TRUE(item);
625   [app_controller commandDispatch:item];
626
627   profiles::testing::WaitForPickerClosed();
628   EXPECT_FALSE(ProfilePicker::IsFirstRunOpen());
629   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
630 }
631
632 IN_PROC_BROWSER_TEST_F(AppControllerFirstRunBrowserTest,
633                        ClickingChromeDockIconDoesNotOpenBrowser) {
634   EXPECT_TRUE(ProfilePicker::IsFirstRunOpen());
635   EXPECT_EQ(BrowserList::GetInstance()->size(), 0u);
636   [AppController.sharedController applicationShouldHandleReopen:NSApp
637                                               hasVisibleWindows:NO];
638
639   EXPECT_EQ(BrowserList::GetInstance()->size(), 0u);
640   ProfilePicker::Hide();
641 }
642
643 class AppControllerOpenShortcutBrowserTest : public InProcessBrowserTest {
644  protected:
645   AppControllerOpenShortcutBrowserTest()
646       : AppControllerOpenShortcutBrowserTest(/*enable_fre=*/false) {}
647
648   AppControllerOpenShortcutBrowserTest(bool enable_fre) {
649     std::vector<base::test::FeatureRef> enabled_features = {
650         welcome::kForceEnabled};
651     std::vector<base::test::FeatureRef> disabled_features = {};
652     if (enable_fre) {
653       enabled_features.push_back(kForYouFre);
654     } else {
655       disabled_features.push_back(kForYouFre);
656     }
657
658     scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
659   }
660
661   void SetUpInProcessBrowserTestFixture() override {
662     // In order to mimic opening shortcut during browser startup, we need to
663     // send the event before -applicationDidFinishLaunching is called, but
664     // after AppController is loaded.
665     //
666     // Since -applicationWillFinishLaunching does nothing now, we swizzle it to
667     // our function to send the event. We need to do this early before running
668     // the main message loop.
669     //
670     // NSApp does not exist yet. We need to get the AppController using
671     // reflection.
672     Class appControllerClass = NSClassFromString(@"AppController");
673     Class openShortcutClass = NSClassFromString(@"TestOpenShortcutOnStartup");
674
675     ASSERT_TRUE(appControllerClass != nil);
676     ASSERT_TRUE(openShortcutClass != nil);
677
678     SEL targetMethod = @selector(applicationWillFinishLaunching:);
679     Method original = class_getInstanceMethod(appControllerClass,
680         targetMethod);
681     Method destination = class_getInstanceMethod(openShortcutClass,
682         targetMethod);
683
684     ASSERT_TRUE(original);
685     ASSERT_TRUE(destination);
686
687     method_exchangeImplementations(original, destination);
688
689     ASSERT_TRUE(embedded_test_server()->Start());
690     g_open_shortcut_url = embedded_test_server()->GetURL("/simple.html");
691   }
692
693   void SetUpCommandLine(base::CommandLine* command_line) override {
694     // If the arg is empty, PrepareTestCommandLine() after this function will
695     // append about:blank as default url.
696     command_line->AppendArg(chrome::kChromeUINewTabURL);
697   }
698
699  private:
700   base::test::ScopedFeatureList scoped_feature_list_;
701 };
702
703 IN_PROC_BROWSER_TEST_F(AppControllerOpenShortcutBrowserTest,
704                        OpenShortcutOnStartup) {
705   // The two tabs expected are the Welcome page and the desired URL.
706   EXPECT_EQ(2, browser()->tab_strip_model()->count());
707   EXPECT_EQ(g_open_shortcut_url, browser()
708                                      ->tab_strip_model()
709                                      ->GetActiveWebContents()
710                                      ->GetLastCommittedURL());
711 }
712
713 class AppControllerOpenShortcutWithFreBrowserTest
714     : public AppControllerOpenShortcutBrowserTest {
715  protected:
716   AppControllerOpenShortcutWithFreBrowserTest()
717       : AppControllerOpenShortcutBrowserTest(/*enable_fre=*/true) {}
718 };
719
720 IN_PROC_BROWSER_TEST_F(AppControllerOpenShortcutWithFreBrowserTest,
721                        OpenShortcutOnStartup) {
722   // The Welcome page is not expected.
723   EXPECT_EQ(1, browser()->tab_strip_model()->count());
724
725   EXPECT_EQ(g_open_shortcut_url,
726       browser()->tab_strip_model()->GetActiveWebContents()
727           ->GetLastCommittedURL());
728 }
729
730 class AppControllerReplaceNTPBrowserTest : public InProcessBrowserTest {
731  protected:
732   AppControllerReplaceNTPBrowserTest() = default;
733
734   void SetUpInProcessBrowserTestFixture() override {
735     ASSERT_TRUE(embedded_test_server()->Start());
736   }
737
738   void SetUpCommandLine(base::CommandLine* command_line) override {
739     // If the arg is empty, PrepareTestCommandLine() after this function will
740     // append about:blank as default url.
741     command_line->AppendArg(chrome::kChromeUINewTabURL);
742   }
743 };
744
745 // Tests that when a GURL is opened after startup, it replaces the NTP.
746 // Flaky. See crbug.com/1234765.
747 IN_PROC_BROWSER_TEST_F(AppControllerReplaceNTPBrowserTest,
748                        DISABLED_ReplaceNTPAfterStartup) {
749   // Depending on network connectivity, the NTP URL can either be
750   // chrome://newtab/ or chrome://new-tab-page-third-party. See
751   // ntp_test_utils::GetFinalNtpUrl for more details.
752   std::string expected_url =
753       ntp_test_utils::GetFinalNtpUrl(browser()->profile()).spec();
754
755   // Ensure that there is exactly 1 tab showing, and the tab is the NTP.
756   GURL ntp(expected_url);
757   EXPECT_EQ(1, browser()->tab_strip_model()->count());
758   browser()->tab_strip_model()->GetActiveWebContents()->GetController().LoadURL(
759       GURL(expected_url), content::Referrer(),
760       ui::PageTransition::PAGE_TRANSITION_LINK, std::string());
761
762   // Wait for one navigation on the active web contents.
763   content::TestNavigationObserver ntp_navigation_observer(
764       browser()->tab_strip_model()->GetActiveWebContents());
765   ntp_navigation_observer.Wait();
766
767   EXPECT_EQ(ntp,
768             browser()
769                 ->tab_strip_model()
770                 ->GetActiveWebContents()
771                 ->GetLastCommittedURL());
772
773   GURL simple(embedded_test_server()->GetURL("/simple.html"));
774   SendOpenUrlToAppController(simple);
775
776   EXPECT_EQ(1, browser()->tab_strip_model()->count());
777   content::TestNavigationObserver event_navigation_observer(
778       browser()->tab_strip_model()->GetActiveWebContents());
779   event_navigation_observer.Wait();
780
781   EXPECT_EQ(simple,
782             browser()
783                 ->tab_strip_model()
784                 ->GetActiveWebContents()
785                 ->GetLastCommittedURL());
786 }
787
788 // Tests that, even if an incognito browser is the last active browser, a GURL
789 // is opened in a regular (non-incognito) browser.
790 // Regression test for https://crbug.com/757253, https://crbug.com/1444747
791 IN_PROC_BROWSER_TEST_F(AppControllerBrowserTest, OpenInRegularBrowser) {
792   ASSERT_TRUE(embedded_test_server()->Start());
793   AppController* ac =
794       base::apple::ObjCCastStrict<AppController>([NSApp delegate]);
795   ASSERT_TRUE(ac);
796   // Create an incognito browser and make it the last active browser.
797   Browser* incognito_browser = CreateIncognitoBrowser(browser()->profile());
798   EXPECT_EQ(1, browser()->tab_strip_model()->count());
799   EXPECT_EQ(1, incognito_browser->tab_strip_model()->count());
800   EXPECT_TRUE(incognito_browser->profile()->IsIncognitoProfile());
801   EXPECT_EQ(incognito_browser, chrome::GetLastActiveBrowser());
802   // Assure that `windowDidBecomeMain` is called even if this browser process
803   // lost focus because of other browser processes in other shards taking
804   // focus. It prevents flakiness.
805   // See: https://crrev.com/c/4530255/comments/2aadb9cf_9a39d4bf
806   [[NSNotificationCenter defaultCenter]
807       postNotificationName:NSWindowDidBecomeMainNotification
808                     object:incognito_browser->window()
809                                ->GetNativeWindow()
810                                .GetNativeNSWindow()];
811   // Open a url.
812   GURL simple(embedded_test_server()->GetURL("/simple.html"));
813   content::TestNavigationObserver event_navigation_observer(simple);
814   event_navigation_observer.StartWatchingNewWebContents();
815   SendOpenUrlToAppController(simple);
816   event_navigation_observer.Wait();
817   // It should be opened in the regular browser.
818   EXPECT_EQ(2, browser()->tab_strip_model()->count());
819   EXPECT_EQ(1, incognito_browser->tab_strip_model()->count());
820   EXPECT_EQ(simple, browser()
821                         ->tab_strip_model()
822                         ->GetActiveWebContents()
823                         ->GetLastCommittedURL());
824 }
825
826 // Tests that, even if only an incognito browser is currently opened, a GURL
827 // is opened in a regular (non-incognito) browser.
828 // Regression test for https://crbug.com/757253, https://crbug.com/1444747
829 IN_PROC_BROWSER_TEST_F(AppControllerBrowserTest,
830                        OpenInRegularBrowserWhenOnlyIncognitoBrowserIsOpened) {
831   ASSERT_TRUE(embedded_test_server()->Start());
832   AppController* ac =
833       base::apple::ObjCCastStrict<AppController>([NSApp delegate]);
834   ASSERT_TRUE(ac);
835   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
836   // Close the current browser.
837   Profile* profile = browser()->profile();
838   chrome::CloseAllBrowsers();
839   ui_test_utils::WaitForBrowserToClose();
840   EXPECT_TRUE(BrowserList::GetInstance()->empty());
841   // Create an incognito browser and check that it is the last active browser.
842   Browser* incognito_browser = CreateIncognitoBrowser(profile);
843   EXPECT_TRUE(incognito_browser->profile()->IsIncognitoProfile());
844   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
845   EXPECT_EQ(incognito_browser, chrome::GetLastActiveBrowser());
846   // Assure that `windowDidBecomeMain` is called even if this browser process
847   // lost focus because of other browser processes in other shards taking
848   // focus. It prevents flakiness.
849   // See: https://crrev.com/c/4530255/comments/2aadb9cf_9a39d4bf
850   [[NSNotificationCenter defaultCenter]
851       postNotificationName:NSWindowDidBecomeMainNotification
852                     object:incognito_browser->window()
853                                ->GetNativeWindow()
854                                .GetNativeNSWindow()];
855   // Open a url.
856   GURL simple(embedded_test_server()->GetURL("/simple.html"));
857   content::TestNavigationObserver event_navigation_observer(simple);
858   event_navigation_observer.StartWatchingNewWebContents();
859   SendOpenUrlToAppController(simple);
860   event_navigation_observer.Wait();
861   // Check that a new regular browser is opened
862   // and the url is opened in the regular browser.
863   Browser* new_browser = chrome::GetLastActiveBrowser();
864   EXPECT_EQ(BrowserList::GetInstance()->size(), 2u);
865   EXPECT_TRUE(new_browser->profile()->IsRegularProfile());
866   EXPECT_EQ(profile, new_browser->profile());
867   EXPECT_EQ(simple, new_browser->tab_strip_model()
868                         ->GetActiveWebContents()
869                         ->GetLastCommittedURL());
870 }
871
872 // Tests that, if a guest browser is the last active browser, a GURL is opened
873 // in the guest browser.
874 IN_PROC_BROWSER_TEST_F(AppControllerBrowserTest, OpenUrlInGuestBrowser) {
875   ASSERT_TRUE(embedded_test_server()->Start());
876   AppController* ac =
877       base::apple::ObjCCastStrict<AppController>([NSApp delegate]);
878   ASSERT_TRUE(ac);
879   // Create a guest browser and make it the last active browser.
880   Browser* guest_browser = CreateGuestBrowser();
881   EXPECT_EQ(1, browser()->tab_strip_model()->count());
882   EXPECT_EQ(1, guest_browser->tab_strip_model()->count());
883   EXPECT_TRUE(guest_browser->profile()->IsGuestSession());
884   guest_browser->window()->Show();
885   EXPECT_EQ(guest_browser, chrome::GetLastActiveBrowser());
886   // Assure that `windowDidBecomeMain` is called even if this browser process
887   // lost focus because of other browser processes in other shards taking
888   // focus. It prevents flakiness.
889   // See: https://crrev.com/c/4530255/comments/2aadb9cf_9a39d4bf
890   [[NSNotificationCenter defaultCenter]
891       postNotificationName:NSWindowDidBecomeMainNotification
892                     object:guest_browser->window()
893                                ->GetNativeWindow()
894                                .GetNativeNSWindow()];
895   // Open a url.
896   GURL simple(embedded_test_server()->GetURL("/simple.html"));
897   content::TestNavigationObserver event_navigation_observer(simple);
898   event_navigation_observer.StartWatchingNewWebContents();
899   SendOpenUrlToAppController(simple);
900   event_navigation_observer.Wait();
901   // It should be opened in the guest browser.
902   EXPECT_EQ(1, browser()->tab_strip_model()->count());
903   EXPECT_EQ(2, guest_browser->tab_strip_model()->count());
904   EXPECT_EQ(simple, guest_browser->tab_strip_model()
905                         ->GetActiveWebContents()
906                         ->GetLastCommittedURL());
907 }
908
909 // Tests that when a GURL is opened while incognito forced and there is no
910 // browser opened, it is opened in a new incognito browser.
911 // Test for https://crbug.com/1444747#c8
912 IN_PROC_BROWSER_TEST_F(AppControllerBrowserTest, OpenUrlWhenForcedIncognito) {
913   ASSERT_TRUE(embedded_test_server()->Start());
914   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
915   // Close the current non-incognito browser.
916   Profile* profile = browser()->profile();
917   chrome::CloseAllBrowsers();
918   ui_test_utils::WaitForBrowserToClose();
919   EXPECT_TRUE(BrowserList::GetInstance()->empty());
920   // Force incognito mode.
921   IncognitoModePrefs::SetAvailability(
922       profile->GetPrefs(), policy::IncognitoModeAvailability::kForced);
923   // Open a url.
924   GURL simple(embedded_test_server()->GetURL("/simple.html"));
925   content::TestNavigationObserver event_navigation_observer(simple);
926   event_navigation_observer.StartWatchingNewWebContents();
927   SendOpenUrlToAppController(simple);
928   event_navigation_observer.Wait();
929   // Check that a new incognito browser is opened
930   // and the url is opened in the incognito browser.
931   Browser* new_browser = chrome::GetLastActiveBrowser();
932   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
933   EXPECT_TRUE(new_browser->profile()->IsIncognitoProfile());
934   EXPECT_TRUE(new_browser->profile()->IsPrimaryOTRProfile());
935   EXPECT_EQ(profile, new_browser->profile()->GetOriginalProfile());
936   EXPECT_EQ(simple, new_browser->tab_strip_model()
937                         ->GetActiveWebContents()
938                         ->GetLastCommittedURL());
939 }
940
941 // Tests that when a GURL is opened while incognito forced and an incognito
942 // browser is opened, it is opened in the already opened incognito browser.
943 // Test for https://crbug.com/1444747#c8
944 IN_PROC_BROWSER_TEST_F(AppControllerBrowserTest,
945                        OpenUrlWhenForcedIncognitoAndIncognitoBrowserIsOpened) {
946   ASSERT_TRUE(embedded_test_server()->Start());
947   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
948   // Close the current non-incognito browser.
949   Profile* profile = browser()->profile();
950   chrome::CloseAllBrowsers();
951   ui_test_utils::WaitForBrowserToClose();
952   EXPECT_TRUE(BrowserList::GetInstance()->empty());
953   // Force incognito mode.
954   IncognitoModePrefs::SetAvailability(
955       profile->GetPrefs(), policy::IncognitoModeAvailability::kForced);
956   // Create an incognito browser.
957   Browser* incognito_browser = CreateIncognitoBrowser(profile);
958   EXPECT_TRUE(incognito_browser->profile()->IsIncognitoProfile());
959   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
960   EXPECT_EQ(1, incognito_browser->tab_strip_model()->count());
961   EXPECT_EQ(incognito_browser, chrome::GetLastActiveBrowser());
962   // Assure that `windowDidBecomeMain` is called even if this browser process
963   // lost focus because of other browser processes in other shards taking
964   // focus. It prevents flakiness.
965   // See: https://crrev.com/c/4530255/comments/2aadb9cf_9a39d4bf
966   [[NSNotificationCenter defaultCenter]
967       postNotificationName:NSWindowDidBecomeMainNotification
968                     object:incognito_browser->window()
969                                ->GetNativeWindow()
970                                .GetNativeNSWindow()];
971   // Open a url.
972   GURL simple(embedded_test_server()->GetURL("/simple.html"));
973   content::TestNavigationObserver event_navigation_observer(simple);
974   event_navigation_observer.StartWatchingNewWebContents();
975   SendOpenUrlToAppController(simple);
976   event_navigation_observer.Wait();
977   // Check the url is opened in the already opened incognito browser.
978   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
979   EXPECT_EQ(2, incognito_browser->tab_strip_model()->count());
980   EXPECT_EQ(simple, incognito_browser->tab_strip_model()
981                         ->GetActiveWebContents()
982                         ->GetLastCommittedURL());
983 }
984
985 class AppControllerMainMenuBrowserTest : public InProcessBrowserTest {
986  protected:
987   AppControllerMainMenuBrowserTest() = default;
988 };
989
990 IN_PROC_BROWSER_TEST_F(AppControllerMainMenuBrowserTest,
991     HistoryMenuResetAfterProfileDeletion) {
992   ProfileManager* profile_manager = g_browser_process->profile_manager();
993   AppController* app_controller = AppController.sharedController;
994
995   // Use the existing profile as profile 1.
996   Profile* profile1 = browser()->profile();
997
998   // Create profile 2.
999   base::FilePath profile2_path =
1000       profile_manager->GenerateNextProfileDirectoryPath();
1001   Profile& profile2 =
1002       profiles::testing::CreateProfileSync(profile_manager, profile2_path);
1003
1004   // Load profile1's History Service backend so it will be assigned to the
1005   // HistoryMenuBridge when setLastProfile is called, or else this test will
1006   // fail flaky.
1007   ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
1008       profile1, ServiceAccessType::EXPLICIT_ACCESS));
1009   // Switch the controller to profile1.
1010   [app_controller setLastProfile:profile1];
1011   base::RunLoop().RunUntilIdle();
1012
1013   // Verify the controller's History Menu corresponds to profile1.
1014   EXPECT_TRUE([app_controller historyMenuBridge]->service());
1015   EXPECT_EQ([app_controller historyMenuBridge]->service(),
1016             HistoryServiceFactory::GetForProfile(
1017                 profile1, ServiceAccessType::EXPLICIT_ACCESS));
1018
1019   // Load profile2's History Service backend so it will be assigned to the
1020   // HistoryMenuBridge when setLastProfile is called, or else this test will
1021   // fail flaky.
1022   ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
1023       &profile2, ServiceAccessType::EXPLICIT_ACCESS));
1024   // Switch the controller to profile2.
1025   [app_controller setLastProfile:&profile2];
1026   base::RunLoop().RunUntilIdle();
1027
1028   // Verify the controller's History Menu has changed.
1029   EXPECT_TRUE([app_controller historyMenuBridge]->service());
1030   EXPECT_EQ([app_controller historyMenuBridge]->service(),
1031             HistoryServiceFactory::GetForProfile(
1032                 &profile2, ServiceAccessType::EXPLICIT_ACCESS));
1033   EXPECT_NE(HistoryServiceFactory::GetForProfile(
1034                 profile1, ServiceAccessType::EXPLICIT_ACCESS),
1035             HistoryServiceFactory::GetForProfile(
1036                 &profile2, ServiceAccessType::EXPLICIT_ACCESS));
1037
1038   // Delete profile2.
1039   profile_manager->GetDeleteProfileHelper().MaybeScheduleProfileForDeletion(
1040       profile2.GetPath(), base::DoNothing(),
1041       ProfileMetrics::DELETE_PROFILE_USER_MANAGER);
1042   content::RunAllTasksUntilIdle();
1043
1044   // Verify the controller's history is back to profile1.
1045   EXPECT_EQ([app_controller historyMenuBridge]->service(),
1046             HistoryServiceFactory::GetForProfile(
1047                 profile1, ServiceAccessType::EXPLICIT_ACCESS));
1048 }
1049
1050 // Disabled because of flakiness. See crbug.com/1278031.
1051 IN_PROC_BROWSER_TEST_F(AppControllerMainMenuBrowserTest,
1052                        DISABLED_ReloadingDestroyedProfileDoesNotCrash) {
1053   ProfileManager* profile_manager = g_browser_process->profile_manager();
1054   AppController* app_controller = AppController.sharedController;
1055
1056   Profile* profile = browser()->profile();
1057   base::FilePath profile_path = profile->GetPath();
1058
1059   // Switch the controller to |profile|.
1060   [app_controller setLastProfile:profile];
1061   base::RunLoop().RunUntilIdle();
1062   EXPECT_EQ(profile, [app_controller lastProfileIfLoaded]);
1063
1064   // Trigger Profile* destruction. Note that this event (destruction from
1065   // memory) is a separate event from profile deletion (from disk).
1066   chrome::CloseAllBrowsers();
1067   ProfileDestructionWaiter(profile).Wait();
1068   EXPECT_EQ(nullptr, [app_controller lastProfileIfLoaded]);
1069
1070   // Re-open the profile. Since the Profile* is destroyed, this involves loading
1071   // it from disk.
1072   base::ScopedAllowBlockingForTesting allow_blocking;
1073   profile = profile_manager->GetProfile(profile_path);
1074   [app_controller setLastProfile:profile];
1075   base::RunLoop().RunUntilIdle();
1076
1077   // We mostly want to make sure re-loading the same profile didn't cause a
1078   // crash. This means we didn't have e.g. a dangling ProfilePrefRegistrar, or
1079   // observers pointing to the old (now dead) Profile.
1080   EXPECT_EQ(profile, [app_controller lastProfileIfLoaded]);
1081 }
1082
1083 IN_PROC_BROWSER_TEST_F(AppControllerMainMenuBrowserTest,
1084     BookmarksMenuIsRestoredAfterProfileSwitch) {
1085   ProfileManager* profile_manager = g_browser_process->profile_manager();
1086   AppController* app_controller = AppController.sharedController;
1087
1088   [app_controller mainMenuCreated];
1089
1090   // Constants for bookmarks that we will create later.
1091   const std::u16string title1(u"Dinosaur Comics");
1092   const GURL url1("http://qwantz.com//");
1093
1094   const std::u16string title2(u"XKCD");
1095   const GURL url2("https://www.xkcd.com/");
1096
1097   // Use the existing profile as profile 1.
1098   Profile* profile1 = browser()->profile();
1099   bookmarks::test::WaitForBookmarkModelToLoad(
1100       BookmarkModelFactory::GetForBrowserContext(profile1));
1101
1102   // Create profile 2.
1103   base::ScopedAllowBlockingForTesting allow_blocking;
1104   base::FilePath path2 = profile_manager->GenerateNextProfileDirectoryPath();
1105   std::unique_ptr<Profile> profile2 =
1106       Profile::CreateProfile(path2, nullptr, Profile::CREATE_MODE_SYNCHRONOUS);
1107   Profile* profile2_ptr = profile2.get();
1108   profile_manager->RegisterTestingProfile(std::move(profile2), false);
1109   bookmarks::test::WaitForBookmarkModelToLoad(
1110       BookmarkModelFactory::GetForBrowserContext(profile2_ptr));
1111
1112   // Switch to profile 1, create bookmark 1 and force the menu to build.
1113   [app_controller setLastProfile:profile1];
1114   [app_controller bookmarkMenuBridge]->GetBookmarkModel()
1115       -> AddURL([app_controller bookmarkMenuBridge]->GetBookmarkModel()
1116                     -> bookmark_bar_node(),
1117                 0, title1, url1);
1118   NSMenu* profile1_submenu =
1119       [app_controller bookmarkMenuBridge]->BookmarkMenu();
1120   [[profile1_submenu delegate] menuNeedsUpdate:profile1_submenu];
1121
1122   // Switch to profile 2, create bookmark 2 and force the menu to build.
1123   [app_controller setLastProfile:profile2_ptr];
1124   [app_controller bookmarkMenuBridge]->GetBookmarkModel()
1125       -> AddURL([app_controller bookmarkMenuBridge]->GetBookmarkModel()
1126                     -> bookmark_bar_node(),
1127                 0, title2, url2);
1128   NSMenu* profile2_submenu =
1129       [app_controller bookmarkMenuBridge]->BookmarkMenu();
1130   [[profile2_submenu delegate] menuNeedsUpdate:profile2_submenu];
1131   EXPECT_NE(profile1_submenu, profile2_submenu);
1132
1133   // Test that only bookmark 2 is shown.
1134   EXPECT_FALSE([[app_controller bookmarkMenuBridge]->BookmarkMenu()
1135       itemWithTitle:base::SysUTF16ToNSString(title1)]);
1136   EXPECT_TRUE([[app_controller bookmarkMenuBridge]->BookmarkMenu()
1137       itemWithTitle:base::SysUTF16ToNSString(title2)]);
1138
1139   // Switch *back* to profile 1 and *don't* force the menu to build.
1140   [app_controller setLastProfile:profile1];
1141
1142   // Test that only bookmark 1 is shown in the restored menu.
1143   EXPECT_TRUE([[app_controller bookmarkMenuBridge]->BookmarkMenu()
1144       itemWithTitle:base::SysUTF16ToNSString(title1)]);
1145   EXPECT_FALSE([[app_controller bookmarkMenuBridge]->BookmarkMenu()
1146       itemWithTitle:base::SysUTF16ToNSString(title2)]);
1147
1148   // Ensure a cached menu was used.
1149   EXPECT_EQ(profile1_submenu,
1150             [app_controller bookmarkMenuBridge]->BookmarkMenu());
1151 }
1152
1153 // Tests opening a new window from a browser command while incognito is forced.
1154 // Regression test for https://crbug.com/1206726
1155 IN_PROC_BROWSER_TEST_F(AppControllerMainMenuBrowserTest,
1156                        ForcedIncognito_NewWindow) {
1157   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
1158   // Close the current non-incognito browser.
1159   Profile* profile = browser()->profile();
1160   chrome::CloseAllBrowsers();
1161   ui_test_utils::WaitForBrowserToClose();
1162   EXPECT_TRUE(BrowserList::GetInstance()->empty());
1163   // Force incognito mode.
1164   IncognitoModePrefs::SetAvailability(
1165       profile->GetPrefs(), policy::IncognitoModeAvailability::kForced);
1166   // Simulate click on "New window".
1167   ui_test_utils::BrowserChangeObserver browser_added_observer(
1168       nullptr, ui_test_utils::BrowserChangeObserver::ChangeType::kAdded);
1169   AppController* app_controller = AppController.sharedController;
1170   NSMenu* menu = [app_controller applicationDockMenu:NSApp];
1171   ASSERT_TRUE(menu);
1172   NSMenuItem* item = [menu itemWithTag:IDC_NEW_WINDOW];
1173   ASSERT_TRUE(item);
1174   [app_controller commandDispatch:item];
1175   // Check that a new incognito browser is opened.
1176   Browser* new_browser = browser_added_observer.Wait();
1177   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
1178   EXPECT_TRUE(new_browser->profile()->IsPrimaryOTRProfile());
1179   EXPECT_EQ(profile, new_browser->profile()->GetOriginalProfile());
1180 }
1181
1182 // Tests opening a new window from dock menu while incognito browser is opened.
1183 // Regression test for https://crbug.com/1371923
1184 IN_PROC_BROWSER_TEST_F(AppControllerMainMenuBrowserTest,
1185                        WhileIncognitoBrowserIsOpened_NewWindow) {
1186   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
1187
1188   // Close the current browser.
1189   Profile* profile = browser()->profile();
1190   chrome::CloseAllBrowsers();
1191   ui_test_utils::WaitForBrowserToClose();
1192   EXPECT_TRUE(BrowserList::GetInstance()->empty());
1193
1194   // Create an incognito browser.
1195   Browser* incognito_browser = CreateIncognitoBrowser(profile);
1196   EXPECT_TRUE(incognito_browser->profile()->IsIncognitoProfile());
1197   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
1198   EXPECT_EQ(incognito_browser, chrome::GetLastActiveBrowser());
1199   // Assure that `windowDidBecomeMain` is called even if this browser process
1200   // lost focus because of other browser processes in other shards taking
1201   // focus. It prevents flakiness.
1202   // See: https://crbug.com/1450491
1203   [[NSNotificationCenter defaultCenter]
1204       postNotificationName:NSWindowDidBecomeMainNotification
1205                     object:incognito_browser->window()
1206                                ->GetNativeWindow()
1207                                .GetNativeNSWindow()];
1208
1209   // Simulate click on "New Window".
1210   ui_test_utils::BrowserChangeObserver browser_added_observer(
1211       nullptr, ui_test_utils::BrowserChangeObserver::ChangeType::kAdded);
1212   AppController* app_controller = AppController.sharedController;
1213   NSMenu* menu = [app_controller applicationDockMenu:NSApp];
1214   ASSERT_TRUE(menu);
1215   NSMenuItem* item = [menu itemWithTag:IDC_NEW_WINDOW];
1216   ASSERT_TRUE(item);
1217   [app_controller commandDispatch:item];
1218
1219   // Check that a new non-incognito browser is opened.
1220   Browser* new_browser = browser_added_observer.Wait();
1221   EXPECT_EQ(BrowserList::GetInstance()->size(), 2u);
1222   EXPECT_TRUE(new_browser->profile()->IsRegularProfile());
1223   EXPECT_EQ(profile, new_browser->profile());
1224 }
1225
1226 // Test switching from Regular to OTR profiles updates the history menu.
1227 IN_PROC_BROWSER_TEST_F(AppControllerMainMenuBrowserTest,
1228                        SwitchToIncognitoRemovesHistoryItems) {
1229   ASSERT_TRUE(embedded_test_server()->Start());
1230   AppController* app_controller = AppController.sharedController;
1231
1232   GURL simple(embedded_test_server()->GetURL("/simple.html"));
1233   SendOpenUrlToAppController(simple);
1234
1235   Profile* profile = browser()->profile();
1236   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
1237
1238   // Load profile's History Service backend so it will be assigned to the
1239   // HistoryMenuBridge, or else this test will fail flaky.
1240   ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
1241       profile, ServiceAccessType::EXPLICIT_ACCESS));
1242
1243   // Verify that history bridge service is available for regular profiles.
1244   EXPECT_TRUE([app_controller historyMenuBridge]->service());
1245
1246   // Open a URL in Incognito window.
1247   ui_test_utils::NavigateToURLWithDisposition(
1248       browser(), simple, WindowOpenDisposition::OFF_THE_RECORD,
1249       ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER);
1250
1251   // Check that there are exactly 2 browsers (regular and incognito).
1252   BrowserList* active_browser_list = BrowserList::GetInstance();
1253   EXPECT_EQ(2u, active_browser_list->size());
1254
1255   // Verify that history bridge service is not available in Incognito.
1256   EXPECT_FALSE([app_controller historyMenuBridge]->service());
1257
1258   // Switch back to the regular profile window.
1259   Browser* browser1 = active_browser_list->get(0);
1260   browser1->window()->Show();
1261
1262   // Verify that history bridge service is available again.
1263   EXPECT_TRUE([app_controller historyMenuBridge]->service());
1264 }
1265
1266 class AppControllerIncognitoSwitchTest : public InProcessBrowserTest {
1267  public:
1268   void SetUpCommandLine(base::CommandLine* command_line) override {
1269     InProcessBrowserTest::SetUpCommandLine(command_line);
1270     command_line->AppendSwitch(switches::kIncognito);
1271   }
1272 };
1273
1274 // Regression test for https://crbug.com/1248661
1275 IN_PROC_BROWSER_TEST_F(AppControllerIncognitoSwitchTest,
1276                        ObserveProfileDestruction) {
1277   // Chrome is launched in incognito.
1278   Profile* otr_profile = browser()->profile();
1279   EXPECT_EQ(otr_profile,
1280             otr_profile->GetPrimaryOTRProfile(/*create_if_needed=*/false));
1281   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
1282   AppController* app_controller = AppController.sharedController;
1283   [[NSNotificationCenter defaultCenter]
1284       postNotificationName:NSWindowDidBecomeMainNotification
1285                     object:browser()
1286                                ->window()
1287                                ->GetNativeWindow()
1288                                .GetNativeNSWindow()];
1289   // The last profile is the incognito profile.
1290   EXPECT_EQ([app_controller lastProfileIfLoaded], otr_profile);
1291   // Destroy the incognito profile.
1292   ProfileDestructionWaiter waiter(otr_profile);
1293   CloseBrowserSynchronously(browser());
1294   waiter.Wait();
1295   // Check that |-lastProfileIfLoaded| is not pointing to released memory.
1296   EXPECT_NE([app_controller lastProfileIfLoaded], otr_profile);
1297 }
1298
1299 }  // namespace
1300
1301 //--------------------------AppControllerHandoffBrowserTest---------------------
1302
1303 static GURL g_handoff_url;
1304 static std::u16string g_handoff_title;
1305
1306 @interface AppController (BrowserTest)
1307 - (void)new_updateHandoffManagerWithURL:(const GURL&)handoffURL
1308                                   title:(const std::u16string&)handoffTitle;
1309 @end
1310
1311 @implementation AppController (BrowserTest)
1312 - (void)new_updateHandoffManagerWithURL:(const GURL&)handoffURL
1313                                   title:(const std::u16string&)handoffTitle {
1314   g_handoff_url = handoffURL;
1315   g_handoff_title = handoffTitle;
1316 }
1317 @end
1318
1319 namespace {
1320
1321 class AppControllerHandoffBrowserTest : public InProcessBrowserTest {
1322  protected:
1323   // Swizzle Handoff related implementations.
1324   void SetUpInProcessBrowserTestFixture() override {
1325     // This swizzle intercepts the URL that would be sent to the Handoff
1326     // Manager, and instead puts it into a variable accessible to this test.
1327     swizzler_ = std::make_unique<base::apple::ScopedObjCClassSwizzler>(
1328         [AppController class], @selector(updateHandoffManagerWithURL:title:),
1329         @selector(new_updateHandoffManagerWithURL:title:));
1330   }
1331
1332   void TearDownInProcessBrowserTestFixture() override { swizzler_.reset(); }
1333   // Closes the tab, and waits for the close to finish.
1334   void CloseTab(Browser* browser, int index) {
1335     content::WebContentsDestroyedWatcher destroyed_watcher(
1336         browser->tab_strip_model()->GetWebContentsAt(index));
1337     browser->tab_strip_model()->CloseWebContentsAt(
1338         index, TabCloseTypes::CLOSE_CREATE_HISTORICAL_TAB);
1339     destroyed_watcher.Wait();
1340   }
1341
1342  private:
1343   std::unique_ptr<base::apple::ScopedObjCClassSwizzler> swizzler_;
1344 };
1345
1346 // Tests that as a user switches between tabs, navigates within a tab, and
1347 // switches between browser windows, the correct URL is being passed to the
1348 // Handoff.
1349 IN_PROC_BROWSER_TEST_F(AppControllerHandoffBrowserTest, TestHandoffURLs) {
1350   ASSERT_TRUE(embedded_test_server()->Start());
1351   EXPECT_EQ(g_handoff_url, GURL(url::kAboutBlankURL));
1352   EXPECT_EQ(g_handoff_title, u"about:blank");
1353
1354   // Test that navigating to a URL updates the handoff manager.
1355   GURL test_url1 = embedded_test_server()->GetURL("/title1.html");
1356   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_url1));
1357   EXPECT_EQ(g_handoff_url, test_url1);
1358   EXPECT_TRUE(base::EndsWith(g_handoff_title, u"title1.html"));
1359
1360   // Test that opening a new tab updates the handoff URL.
1361   GURL test_url2 = embedded_test_server()->GetURL("/title2.html");
1362   NavigateParams params(browser(), test_url2, ui::PAGE_TRANSITION_LINK);
1363   params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
1364   ui_test_utils::NavigateToURL(&params);
1365   EXPECT_EQ(g_handoff_url, test_url2);
1366
1367   // Test that switching tabs updates the handoff URL.
1368   browser()->tab_strip_model()->ActivateTabAt(
1369       0, TabStripUserGestureDetails(
1370              TabStripUserGestureDetails::GestureType::kOther));
1371   EXPECT_EQ(g_handoff_url, test_url1);
1372   EXPECT_TRUE(base::EndsWith(g_handoff_title, u"title1.html"));
1373
1374   // Test that closing the current tab updates the handoff URL.
1375   CloseTab(browser(), 0);
1376   EXPECT_EQ(g_handoff_url, test_url2);
1377   EXPECT_EQ(g_handoff_title, u"Title Of Awesomeness");
1378
1379   // Test that opening a new browser window updates the handoff URL.
1380   GURL test_url3 = embedded_test_server()->GetURL("/title3.html");
1381   ui_test_utils::NavigateToURLWithDisposition(
1382       browser(), GURL(test_url3), WindowOpenDisposition::NEW_WINDOW,
1383       ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
1384   EXPECT_EQ(g_handoff_url, test_url3);
1385   EXPECT_EQ(g_handoff_title, u"Title Of More Awesomeness");
1386
1387   // Check that there are exactly 2 browsers.
1388   BrowserList* active_browser_list = BrowserList::GetInstance();
1389   EXPECT_EQ(2u, active_browser_list->size());
1390
1391   // Close the second browser window (which only has 1 tab left).
1392   Browser* browser2 = active_browser_list->get(1);
1393   CloseBrowserSynchronously(browser2);
1394   EXPECT_EQ(g_handoff_url, test_url2);
1395   EXPECT_EQ(g_handoff_title, u"Title Of Awesomeness");
1396
1397   // The URLs of incognito windows should not be passed to Handoff.
1398   GURL test_url4 = embedded_test_server()->GetURL("/simple.html");
1399   ui_test_utils::NavigateToURLWithDisposition(
1400       browser(), GURL(test_url4), WindowOpenDisposition::OFF_THE_RECORD,
1401       ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER);
1402   EXPECT_EQ(g_handoff_url, GURL());
1403   EXPECT_EQ(g_handoff_title, u"");
1404
1405   // Open a new tab in the incognito window.
1406   EXPECT_EQ(2u, active_browser_list->size());
1407   Browser* browser3 = active_browser_list->get(1);
1408   ui_test_utils::NavigateToURLWithDisposition(
1409       browser3, test_url4, WindowOpenDisposition::NEW_FOREGROUND_TAB,
1410       ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
1411   EXPECT_EQ(g_handoff_url, GURL());
1412   EXPECT_EQ(g_handoff_title, u"");
1413
1414   // Navigate the current tab in the incognito window.
1415   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser3, test_url1));
1416   EXPECT_EQ(g_handoff_url, GURL());
1417   EXPECT_EQ(g_handoff_title, u"");
1418
1419   // Activate the original browser window.
1420   Browser* browser1 = active_browser_list->get(0);
1421   browser1->window()->Show();
1422   EXPECT_EQ(g_handoff_url, test_url2);
1423   EXPECT_EQ(g_handoff_title, u"Title Of Awesomeness");
1424 }
1425
1426 class AppControllerHandoffPrerenderBrowserTest
1427     : public AppControllerHandoffBrowserTest {
1428  public:
1429   void SetUpOnMainThread() override {
1430     prerender_helper_.RegisterServerRequestMonitor(embedded_test_server());
1431     host_resolver()->AddRule("*", "127.0.0.1");
1432     embedded_test_server()->ServeFilesFromDirectory(
1433         base::PathService::CheckedGet(chrome::DIR_TEST_DATA));
1434     ASSERT_TRUE(embedded_test_server()->Start());
1435   }
1436
1437   content::WebContents* GetActiveWebContents() {
1438     return browser()->tab_strip_model()->GetActiveWebContents();
1439   }
1440
1441   content::test::PrerenderTestHelper& prerender_helper() {
1442     return prerender_helper_;
1443   }
1444
1445  protected:
1446   AppControllerHandoffPrerenderBrowserTest()
1447       : prerender_helper_(base::BindRepeating(
1448             &AppControllerHandoffPrerenderBrowserTest::GetActiveWebContents,
1449             // Unretained is safe here, as this class owns PrerenderTestHelper
1450             // object, which holds the callback being constructed here, so the
1451             // callback will be destructed before this class.
1452             base::Unretained(this))) {}
1453
1454  private:
1455   content::test::PrerenderTestHelper prerender_helper_;
1456 };
1457
1458 // Tests that as a user switches from main page to prerendered page, the correct
1459 // URL is being passed to the Handoff.
1460 IN_PROC_BROWSER_TEST_F(AppControllerHandoffPrerenderBrowserTest,
1461                        TestHandoffURLs) {
1462   // Navigate to an initial page.
1463   GURL url = embedded_test_server()->GetURL("/empty.html");
1464   ASSERT_TRUE(content::NavigateToURL(GetActiveWebContents(), url));
1465
1466   // Start a prerender.
1467   GURL prerender_url = embedded_test_server()->GetURL("/simple.html");
1468   prerender_helper().AddPrerender(prerender_url);
1469   EXPECT_EQ(g_handoff_url, url);
1470
1471   // Activate.
1472   content::TestActivationManager navigation_manager(GetActiveWebContents(),
1473                                                     prerender_url);
1474   ASSERT_TRUE(
1475       content::ExecJs(GetActiveWebContents()->GetPrimaryMainFrame(),
1476                       content::JsReplace("location = $1", prerender_url)));
1477   navigation_manager.WaitForNavigationFinished();
1478   EXPECT_TRUE(navigation_manager.was_activated());
1479   EXPECT_TRUE(navigation_manager.was_successful());
1480   EXPECT_EQ(g_handoff_url, prerender_url);
1481 }
1482
1483 }  // namespace