blob: 313b3554440b5bcc71ccb173d30f4208e41fbc44 [file] [log] [blame]
[email protected]fc44f242012-02-14 16:54:391// Copyright (c) 2012 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
[email protected]66791aff2014-04-29 09:45:385#import <Carbon/Carbon.h>
[email protected]fc44f242012-02-14 16:54:396#import <Cocoa/Cocoa.h>
[email protected]66791aff2014-04-29 09:45:387#import <Foundation/Foundation.h>
8#import <Foundation/NSAppleEventDescriptor.h>
9#import <objc/message.h>
10#import <objc/runtime.h>
avie4d7b6f2015-12-26 00:59:1811#include <stddef.h>
[email protected]fc44f242012-02-14 16:54:3912
Sebastien Marchandf1349f52019-01-25 03:16:4113#include "base/bind.h"
David Roger51797642018-03-20 13:29:1614#include "base/bind_helpers.h"
[email protected]fc44f242012-02-14 16:54:3915#include "base/command_line.h"
[email protected]66791aff2014-04-29 09:45:3816#include "base/mac/foundation_util.h"
[email protected]a8522032013-06-24 22:51:4617#include "base/mac/scoped_nsobject.h"
thestigaf7f4152014-10-31 23:19:1518#include "base/run_loop.h"
lgarron9e6dee22014-11-18 01:03:3919#include "base/strings/sys_string_conversions.h"
20#include "base/strings/utf_string_conversions.h"
jam3f2d3932017-04-26 20:28:5121#include "base/threading/thread_restrictions.h"
[email protected]fc44f242012-02-14 16:54:3922#include "chrome/app/chrome_command_ids.h"
23#import "chrome/browser/app_controller_mac.h"
Dominick Ng6ff51052018-07-06 05:30:2024#include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
lgarron9e6dee22014-11-18 01:03:3925#include "chrome/browser/bookmarks/bookmark_model_factory.h"
[email protected]dbb03fb2014-02-15 05:36:3326#include "chrome/browser/browser_process.h"
mlerman8ae56aa2015-04-24 13:56:2727#include "chrome/browser/history/history_service_factory.h"
Trent Apted45d9ae22017-11-09 23:12:3228#include "chrome/browser/lifetime/application_lifetime.h"
lwchkg498e92492016-04-23 11:04:1229#include "chrome/browser/profiles/profile_attributes_entry.h"
30#include "chrome/browser/profiles/profile_attributes_storage.h"
[email protected]7108d912014-01-30 08:10:4531#include "chrome/browser/profiles/profile_manager.h"
[email protected]52877dbc62012-06-29 22:22:0332#include "chrome/browser/ui/browser.h"
Trent Apted45d9ae22017-11-09 23:12:3233#include "chrome/browser/ui/browser_finder.h"
[email protected]52877dbc62012-06-29 22:22:0334#include "chrome/browser/ui/browser_list.h"
thestige80821242015-09-30 23:46:0835#include "chrome/browser/ui/browser_navigator_params.h"
[email protected]ee9ccfd42013-07-23 02:31:4736#include "chrome/browser/ui/browser_window.h"
lgarron9e6dee22014-11-18 01:03:3937#include "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.h"
mlerman8ae56aa2015-04-24 13:56:2738#include "chrome/browser/ui/cocoa/history_menu_bridge.h"
Christian Dullweber820ee5f2018-04-26 13:24:3139#include "chrome/browser/ui/cocoa/last_active_browser_cocoa.h"
lgrey92aad3c2016-12-10 01:22:1840#include "chrome/browser/ui/cocoa/test/run_loop_testing.h"
kristiparka34b247a2018-03-09 19:05:3441#include "chrome/browser/ui/search/local_ntp_test_utils.h"
[email protected]617ee962013-01-29 20:49:1242#include "chrome/browser/ui/tabs/tab_strip_model.h"
mlermane29d0032014-09-24 19:31:2643#include "chrome/browser/ui/user_manager.h"
Hector Carmona1e62e352019-06-24 19:18:1744#include "chrome/browser/ui/webui/welcome/nux_helper.h"
[email protected]7108d912014-01-30 08:10:4545#include "chrome/common/chrome_constants.h"
46#include "chrome/common/chrome_switches.h"
47#include "chrome/common/pref_names.h"
[email protected]66791aff2014-04-29 09:45:3848#include "chrome/common/url_constants.h"
[email protected]fc44f242012-02-14 16:54:3949#include "chrome/test/base/in_process_browser_test.h"
erikchen600f7962014-12-12 00:17:3850#include "chrome/test/base/ui_test_utils.h"
tapted574f09c2015-05-19 13:08:0851#include "components/bookmarks/browser/bookmark_model.h"
lgarron9e6dee22014-11-18 01:03:3952#include "components/bookmarks/test/bookmark_test_helpers.h"
brettwb1fc1b82016-02-02 00:19:0853#include "components/prefs/pref_service.h"
tmartino82e55782017-01-10 22:30:1754#include "content/public/browser/navigation_controller.h"
[email protected]fc44f242012-02-14 16:54:3955#include "content/public/browser/web_contents.h"
erikchen600f7962014-12-12 00:17:3856#include "content/public/test/browser_test_utils.h"
erikchen19ee3922014-10-31 19:14:2257#include "content/public/test/test_navigation_observer.h"
hashimotoad3c6872014-08-29 09:46:5758#include "extensions/browser/app_window/app_window_registry.h"
[email protected]e4452d32013-11-15 23:07:4159#include "extensions/common/extension.h"
lfg910f2f92014-09-19 05:31:0960#include "extensions/test/extension_test_message_listener.h"
[email protected]66791aff2014-04-29 09:45:3861#include "net/test/embedded_test_server/embedded_test_server.h"
Trent Apted45d9ae22017-11-09 23:12:3262#import "ui/events/test/cocoa_test_event_utils.h"
[email protected]66791aff2014-04-29 09:45:3863
Adam Riceff26dcf2017-08-14 05:01:5264using base::SysUTF16ToNSString;
65
[email protected]66791aff2014-04-29 09:45:3866namespace {
67
Scott Violet1f106b582017-07-12 15:49:5868GURL g_open_shortcut_url = GURL::EmptyGURL();
[email protected]66791aff2014-04-29 09:45:3869
erikchen19ee3922014-10-31 19:14:2270// Returns an Apple Event that instructs the application to open |url|.
71NSAppleEventDescriptor* AppleEventToOpenUrl(const GURL& url) {
72 NSAppleEventDescriptor* shortcut_event = [[[NSAppleEventDescriptor alloc]
73 initWithEventClass:kASAppleScriptSuite
74 eventID:kASSubroutineEvent
75 targetDescriptor:nil
76 returnID:kAutoGenerateReturnID
77 transactionID:kAnyTransactionID] autorelease];
78 NSString* url_string = [NSString stringWithUTF8String:url.spec().c_str()];
79 [shortcut_event setParamDescriptor:[NSAppleEventDescriptor
80 descriptorWithString:url_string]
81 forKeyword:keyDirectObject];
82 return shortcut_event;
83}
84
85// Instructs the NSApp's delegate to open |url|.
86void SendAppleEventToOpenUrlToAppController(const GURL& url) {
87 AppController* controller =
88 base::mac::ObjCCast<AppController>([NSApp delegate]);
89 Method get_url =
90 class_getInstanceMethod([controller class], @selector(getUrl:withReply:));
91
92 ASSERT_TRUE(get_url);
93
94 NSAppleEventDescriptor* shortcut_event = AppleEventToOpenUrl(url);
95
96 method_invoke(controller, get_url, shortcut_event, NULL);
97}
98
mlerman8ae56aa2015-04-24 13:56:2799void RunClosureWhenProfileInitialized(const base::Closure& closure,
100 Profile* profile,
101 Profile::CreateStatus status) {
102 if (status == Profile::CREATE_STATUS_INITIALIZED)
103 closure.Run();
104}
105
[email protected]66791aff2014-04-29 09:45:38106} // namespace
107
108@interface TestOpenShortcutOnStartup : NSObject
109- (void)applicationWillFinishLaunching:(NSNotification*)notification;
110@end
111
112@implementation TestOpenShortcutOnStartup
113
114- (void)applicationWillFinishLaunching:(NSNotification*)notification {
Scott Violet1f106b582017-07-12 15:49:58115 if (!g_open_shortcut_url.is_valid())
116 return;
117
erikchen19ee3922014-10-31 19:14:22118 SendAppleEventToOpenUrlToAppController(g_open_shortcut_url);
[email protected]66791aff2014-04-29 09:45:38119}
120
121@end
[email protected]fc44f242012-02-14 16:54:39122
123namespace {
124
Trent Apted45d9ae22017-11-09 23:12:32125using AppControllerBrowserTest = InProcessBrowserTest;
126
Elly Fong-Jones85046032018-04-19 19:15:28127// Returns whether a window's pixels are actually on the screen, which is the
128// case when it and all of its parents are marked visible.
129bool IsReallyVisible(NSWindow* window) {
130 while (window) {
131 if (!window.visible)
132 return false;
133 window = [window parentWindow];
134 }
135 return true;
136}
137
Trent Apted45d9ae22017-11-09 23:12:32138size_t CountVisibleWindows() {
139 size_t count = 0;
140 for (NSWindow* w in [NSApp windows])
Elly Fong-Jones85046032018-04-19 19:15:28141 count = count + (IsReallyVisible(w) ? 1 : 0);
Trent Apted45d9ae22017-11-09 23:12:32142 return count;
143}
144
Elly Fong-Jones85046032018-04-19 19:15:28145// Returns how many visible NSWindows are expected for a given count of browser
Sidney San Martínb247d53f2018-05-23 02:31:21146// windows.
Elly Fong-Jones85046032018-04-19 19:15:28147size_t ExpectedWindowCountForBrowserCount(size_t browsers) {
Elly Fong-Jones85046032018-04-19 19:15:28148 return browsers;
149}
150
Trent Apted45d9ae22017-11-09 23:12:32151// Test browser shutdown with a command in the message queue.
152IN_PROC_BROWSER_TEST_F(AppControllerBrowserTest, CommandDuringShutdown) {
153 EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
Elly Fong-Jones85046032018-04-19 19:15:28154 EXPECT_EQ(ExpectedWindowCountForBrowserCount(1), CountVisibleWindows());
Trent Apted45d9ae22017-11-09 23:12:32155
156 chrome::AttemptExit(); // Set chrome::IsTryingToQuit and close all windows.
157
158 // Opening a new window here is fine (unload handlers can also interrupt
159 // exit). But closing the window posts an autorelease on
160 // BrowserWindowController, which calls ~Browser() and, if that was the last
161 // Browser, it invokes applicationWillTerminate: (because IsTryingToQuit is
162 // set). So, verify assumptions then process that autorelease.
163
164 EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
Elly Fong-Jones85046032018-04-19 19:15:28165 EXPECT_EQ(ExpectedWindowCountForBrowserCount(0), CountVisibleWindows());
Trent Apted45d9ae22017-11-09 23:12:32166
167 base::RunLoop().RunUntilIdle();
168
169 EXPECT_EQ(0u, chrome::GetTotalBrowserCount());
Elly Fong-Jones85046032018-04-19 19:15:28170 EXPECT_EQ(ExpectedWindowCountForBrowserCount(0), CountVisibleWindows());
Trent Apted45d9ae22017-11-09 23:12:32171
172 NSEvent* cmd_n = cocoa_test_event_utils::KeyEventWithKeyCode(
173 'n', 'n', NSKeyDown, NSCommandKeyMask);
174 [[NSApp mainMenu] performSelector:@selector(performKeyEquivalent:)
175 withObject:cmd_n
176 afterDelay:0];
177 // Let the run loop get flushed, during process cleanup and try not to crash.
178}
179
[email protected]ee9ccfd42013-07-23 02:31:47180class AppControllerPlatformAppBrowserTest
181 : public extensions::PlatformAppBrowserTest {
[email protected]fc44f242012-02-14 16:54:39182 protected:
[email protected]b4207c42013-02-12 06:44:20183 AppControllerPlatformAppBrowserTest()
scottmg0d8e4ab2016-01-28 00:34:55184 : active_browser_list_(BrowserList::GetInstance()) {}
[email protected]fc44f242012-02-14 16:54:39185
avi3ef9ec9e2014-12-22 22:50:17186 void SetUpCommandLine(base::CommandLine* command_line) override {
[email protected]ee9ccfd42013-07-23 02:31:47187 PlatformAppBrowserTest::SetUpCommandLine(command_line);
[email protected]fc44f242012-02-14 16:54:39188 command_line->AppendSwitchASCII(switches::kAppId,
189 "1234");
190 }
[email protected]b4207c42013-02-12 06:44:20191
[email protected]7d1a810b2013-06-26 19:51:59192 const BrowserList* active_browser_list_;
[email protected]fc44f242012-02-14 16:54:39193};
194
195// Test that if only a platform app window is open and no browser windows are
196// open then a reopen event does nothing.
197IN_PROC_BROWSER_TEST_F(AppControllerPlatformAppBrowserTest,
198 PlatformAppReopenWithWindows) {
Owen Minb6e1bf292018-03-15 18:31:52199 AppController* ac = base::mac::ObjCCast<AppController>(
200 [[NSApplication sharedApplication] delegate]);
201 ASSERT_TRUE(ac);
202
[email protected]fc44f242012-02-14 16:54:39203 NSUInteger old_window_count = [[NSApp windows] count];
[email protected]7d1a810b2013-06-26 19:51:59204 EXPECT_EQ(1u, active_browser_list_->size());
[email protected]a25920ee2013-09-05 19:38:49205 [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:YES];
206 // We do not EXPECT_TRUE the result here because the method
207 // deminiaturizes windows manually rather than return YES and have
208 // AppKit do it.
[email protected]fc44f242012-02-14 16:54:39209
[email protected]fc44f242012-02-14 16:54:39210 EXPECT_EQ(old_window_count, [[NSApp windows] count]);
[email protected]7d1a810b2013-06-26 19:51:59211 EXPECT_EQ(1u, active_browser_list_->size());
[email protected]fc44f242012-02-14 16:54:39212}
213
[email protected]2e29e2232013-07-26 10:40:59214IN_PROC_BROWSER_TEST_F(AppControllerPlatformAppBrowserTest,
215 ActivationFocusesBrowserWindow) {
Owen Minb6e1bf292018-03-15 18:31:52216 AppController* app_controller = base::mac::ObjCCast<AppController>(
217 [[NSApplication sharedApplication] delegate]);
218 ASSERT_TRUE(app_controller);
[email protected]2e29e2232013-07-26 10:40:59219
220 ExtensionTestMessageListener listener("Launched", false);
221 const extensions::Extension* app =
222 InstallAndLaunchPlatformApp("minimal");
223 ASSERT_TRUE(listener.WaitUntilSatisfied());
224
hashimotoad3c6872014-08-29 09:46:57225 NSWindow* app_window = extensions::AppWindowRegistry::Get(profile())
[email protected]dbb03fb2014-02-15 05:36:33226 ->GetAppWindowsForApp(app->id())
227 .front()
Christopher Cameron359c61e22018-10-18 08:06:20228 ->GetNativeWindow()
229 .GetNativeNSWindow();
230 NSWindow* browser_window =
231 browser()->window()->GetNativeWindow().GetNativeNSWindow();
[email protected]2e29e2232013-07-26 10:40:59232
andybons346c7c62015-08-13 15:18:03233 chrome::testing::NSRunLoopRunAllPending();
[email protected]2e29e2232013-07-26 10:40:59234 EXPECT_LE([[NSApp orderedWindows] indexOfObject:app_window],
235 [[NSApp orderedWindows] indexOfObject:browser_window]);
236 [app_controller applicationShouldHandleReopen:NSApp
237 hasVisibleWindows:YES];
andybons346c7c62015-08-13 15:18:03238 chrome::testing::NSRunLoopRunAllPending();
[email protected]2e29e2232013-07-26 10:40:59239 EXPECT_LE([[NSApp orderedWindows] indexOfObject:browser_window],
240 [[NSApp orderedWindows] indexOfObject:app_window]);
241}
242
[email protected]fc44f242012-02-14 16:54:39243class AppControllerWebAppBrowserTest : public InProcessBrowserTest {
244 protected:
[email protected]b4207c42013-02-12 06:44:20245 AppControllerWebAppBrowserTest()
scottmg0d8e4ab2016-01-28 00:34:55246 : active_browser_list_(BrowserList::GetInstance()) {}
[email protected]fc44f242012-02-14 16:54:39247
avi3ef9ec9e2014-12-22 22:50:17248 void SetUpCommandLine(base::CommandLine* command_line) override {
[email protected]90ca44272012-07-18 18:15:48249 command_line->AppendSwitchASCII(switches::kApp, GetAppURL());
[email protected]fc44f242012-02-14 16:54:39250 }
251
252 std::string GetAppURL() const {
253 return "http://example.com/";
254 }
[email protected]b4207c42013-02-12 06:44:20255
[email protected]7d1a810b2013-06-26 19:51:59256 const BrowserList* active_browser_list_;
[email protected]fc44f242012-02-14 16:54:39257};
258
259// Test that in web app mode a reopen event opens the app URL.
260IN_PROC_BROWSER_TEST_F(AppControllerWebAppBrowserTest,
261 WebAppReopenWithNoWindows) {
Owen Minb6e1bf292018-03-15 18:31:52262 AppController* ac = base::mac::ObjCCast<AppController>(
263 [[NSApplication sharedApplication] delegate]);
264 ASSERT_TRUE(ac);
265
[email protected]7d1a810b2013-06-26 19:51:59266 EXPECT_EQ(1u, active_browser_list_->size());
[email protected]fc44f242012-02-14 16:54:39267 BOOL result = [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:NO];
268
269 EXPECT_FALSE(result);
[email protected]7d1a810b2013-06-26 19:51:59270 EXPECT_EQ(2u, active_browser_list_->size());
[email protected]fc44f242012-02-14 16:54:39271
[email protected]7d1a810b2013-06-26 19:51:59272 Browser* browser = active_browser_list_->get(0);
[email protected]617ee962013-01-29 20:49:12273 GURL current_url =
274 browser->tab_strip_model()->GetActiveWebContents()->GetURL();
[email protected]fc44f242012-02-14 16:54:39275 EXPECT_EQ(GetAppURL(), current_url.spec());
276}
277
[email protected]7108d912014-01-30 08:10:45278// Called when the ProfileManager has created a profile.
279void CreateProfileCallback(const base::Closure& quit_closure,
280 Profile* profile,
281 Profile::CreateStatus status) {
282 EXPECT_TRUE(profile);
283 EXPECT_NE(Profile::CREATE_STATUS_LOCAL_FAIL, status);
284 EXPECT_NE(Profile::CREATE_STATUS_REMOTE_FAIL, status);
285 // This will be called multiple times. Wait until the profile is initialized
286 // fully to quit the loop.
287 if (status == Profile::CREATE_STATUS_INITIALIZED)
288 quit_closure.Run();
289}
290
mlermanb8df6e82015-01-23 19:55:34291void CreateAndWaitForSystemProfile() {
[email protected]7108d912014-01-30 08:10:45292 ProfileManager::CreateCallback create_callback =
293 base::Bind(&CreateProfileCallback,
Gabriel Charette87f2bef72018-05-17 20:37:53294 base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
[email protected]7108d912014-01-30 08:10:45295 g_browser_process->profile_manager()->CreateProfileAsync(
mlermanb8df6e82015-01-23 19:55:34296 ProfileManager::GetSystemProfilePath(),
[email protected]7108d912014-01-30 08:10:45297 create_callback,
298 base::string16(),
[email protected]7108d912014-01-30 08:10:45299 std::string());
300 base::RunLoop().Run();
301}
302
303class AppControllerNewProfileManagementBrowserTest
304 : public InProcessBrowserTest {
305 protected:
306 AppControllerNewProfileManagementBrowserTest()
scottmg0d8e4ab2016-01-28 00:34:55307 : active_browser_list_(BrowserList::GetInstance()) {}
[email protected]7108d912014-01-30 08:10:45308
[email protected]7108d912014-01-30 08:10:45309 const BrowserList* active_browser_list_;
310};
311
312// Test that for a regular last profile, a reopen event opens a browser.
313IN_PROC_BROWSER_TEST_F(AppControllerNewProfileManagementBrowserTest,
314 RegularProfileReopenWithNoWindows) {
Owen Minb6e1bf292018-03-15 18:31:52315 AppController* ac = base::mac::ObjCCast<AppController>(
316 [[NSApplication sharedApplication] delegate]);
317 ASSERT_TRUE(ac);
318
[email protected]7108d912014-01-30 08:10:45319 EXPECT_EQ(1u, active_browser_list_->size());
320 BOOL result = [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:NO];
321
322 EXPECT_FALSE(result);
323 EXPECT_EQ(2u, active_browser_list_->size());
mlermane29d0032014-09-24 19:31:26324 EXPECT_FALSE(UserManager::IsShowing());
[email protected]7108d912014-01-30 08:10:45325}
326
327// Test that for a locked last profile, a reopen event opens the User Manager.
328IN_PROC_BROWSER_TEST_F(AppControllerNewProfileManagementBrowserTest,
329 LockedProfileReopenWithNoWindows) {
mlermanb8df6e82015-01-23 19:55:34330 // The User Manager uses the system profile as its underlying profile. To
[email protected]7108d912014-01-30 08:10:45331 // minimize flakiness due to the scheduling/descheduling of tasks on the
332 // different threads, pre-initialize the guest profile before it is needed.
mlermanb8df6e82015-01-23 19:55:34333 CreateAndWaitForSystemProfile();
Owen Minb6e1bf292018-03-15 18:31:52334 AppController* ac = base::mac::ObjCCast<AppController>(
335 [[NSApplication sharedApplication] delegate]);
336 ASSERT_TRUE(ac);
[email protected]7108d912014-01-30 08:10:45337
338 // Lock the active profile.
Francois Doraye6fb2d02017-10-18 21:29:13339 base::ScopedAllowBlockingForTesting allow_blocking;
[email protected]7108d912014-01-30 08:10:45340 Profile* profile = [ac lastProfile];
lwchkg9c183942016-03-13 06:29:54341 ProfileAttributesEntry* entry;
342 ASSERT_TRUE(g_browser_process->profile_manager()->
343 GetProfileAttributesStorage().
344 GetProfileAttributesWithPath(profile->GetPath(), &entry));
345 entry->SetIsSigninRequired(true);
346 EXPECT_TRUE(entry->IsSigninRequired());
[email protected]7108d912014-01-30 08:10:45347
348 EXPECT_EQ(1u, active_browser_list_->size());
349 BOOL result = [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:NO];
350 EXPECT_FALSE(result);
351
352 base::RunLoop().RunUntilIdle();
353 EXPECT_EQ(1u, active_browser_list_->size());
mlermane29d0032014-09-24 19:31:26354 EXPECT_TRUE(UserManager::IsShowing());
355 UserManager::Hide();
[email protected]7108d912014-01-30 08:10:45356}
357
Owen Minb6e1bf292018-03-15 18:31:52358// Test that for a guest last profile, commandDispatch should open UserManager
359// if guest mode is disabled. Note that this test might be flaky under ASAN
360// due to https://crbug.com/674475. Please disable this test under ASAN
361// as the tests below if that happened.
362IN_PROC_BROWSER_TEST_F(AppControllerNewProfileManagementBrowserTest,
363 OpenGuestProfileOnlyIfGuestModeIsEnabled) {
364 CreateAndWaitForSystemProfile();
365 PrefService* local_state = g_browser_process->local_state();
366 local_state->SetString(prefs::kProfileLastUsed, chrome::kGuestProfileDir);
367 local_state->SetBoolean(prefs::kBrowserGuestModeEnabled, false);
368
369 AppController* ac = base::mac::ObjCCast<AppController>(
370 [[NSApplication sharedApplication] delegate]);
371 ASSERT_TRUE(ac);
372
373 base::ScopedAllowBlockingForTesting allow_blocking;
374 Profile* profile = [ac lastProfile];
375 EXPECT_TRUE(profile->IsGuestSession());
376
377 NSMenu* menu = [ac applicationDockMenu:NSApp];
378 ASSERT_TRUE(menu);
379 NSMenuItem* item = [menu itemWithTag:IDC_NEW_WINDOW];
380 ASSERT_TRUE(item);
381 EXPECT_EQ(1u, active_browser_list_->size());
382
383 [ac commandDispatch:item];
384
385 base::RunLoop().RunUntilIdle();
386
387 EXPECT_EQ(1u, active_browser_list_->size());
388 EXPECT_TRUE(UserManager::IsShowing());
389 UserManager::Hide();
390
391 local_state->SetBoolean(prefs::kBrowserGuestModeEnabled, true);
392 [ac commandDispatch:item];
393 base::RunLoop().RunUntilIdle();
394 EXPECT_EQ(2u, active_browser_list_->size());
395 EXPECT_FALSE(UserManager::IsShowing());
396}
397
guidoubbb4787a2016-12-15 12:34:43398#if defined(ADDRESS_SANITIZER)
399// Flaky under ASAN. See https://crbug.com/674475.
400#define MAYBE_GuestProfileReopenWithNoWindows DISABLED_GuestProfileReopenWithNoWindows
401#else
402#define MAYBE_GuestProfileReopenWithNoWindows GuestProfileReopenWithNoWindows
403#endif
[email protected]7108d912014-01-30 08:10:45404// Test that for a guest last profile, a reopen event opens the User Manager.
405IN_PROC_BROWSER_TEST_F(AppControllerNewProfileManagementBrowserTest,
guidoubbb4787a2016-12-15 12:34:43406 MAYBE_GuestProfileReopenWithNoWindows) {
mlermanb8df6e82015-01-23 19:55:34407 // Create the system profile. Set the guest as the last used profile so the
[email protected]7108d912014-01-30 08:10:45408 // app controller can use it on init.
mlermanb8df6e82015-01-23 19:55:34409 CreateAndWaitForSystemProfile();
[email protected]7108d912014-01-30 08:10:45410 PrefService* local_state = g_browser_process->local_state();
411 local_state->SetString(prefs::kProfileLastUsed, chrome::kGuestProfileDir);
412
Owen Minb6e1bf292018-03-15 18:31:52413 AppController* ac = base::mac::ObjCCast<AppController>(
414 [[NSApplication sharedApplication] delegate]);
415 ASSERT_TRUE(ac);
[email protected]7108d912014-01-30 08:10:45416
Francois Doraye6fb2d02017-10-18 21:29:13417 base::ScopedAllowBlockingForTesting allow_blocking;
[email protected]7108d912014-01-30 08:10:45418 Profile* profile = [ac lastProfile];
419 EXPECT_EQ(ProfileManager::GetGuestProfilePath(), profile->GetPath());
420 EXPECT_TRUE(profile->IsGuestSession());
421
422 EXPECT_EQ(1u, active_browser_list_->size());
423 BOOL result = [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:NO];
424 EXPECT_FALSE(result);
425
426 base::RunLoop().RunUntilIdle();
427
428 EXPECT_EQ(1u, active_browser_list_->size());
mlermane29d0032014-09-24 19:31:26429 EXPECT_TRUE(UserManager::IsShowing());
430 UserManager::Hide();
[email protected]7108d912014-01-30 08:10:45431}
432
guidoubbb4787a2016-12-15 12:34:43433#if defined(ADDRESS_SANITIZER)
434// Flaky under ASAN. See https://crbug.com/674475.
435#define MAYBE_AboutChromeForcesUserManager DISABLED_AboutChromeForcesUserManager
436#else
437#define MAYBE_AboutChromeForcesUserManager AboutChromeForcesUserManager
438#endif
mlermane6e040a2014-10-31 00:53:21439IN_PROC_BROWSER_TEST_F(AppControllerNewProfileManagementBrowserTest,
guidoubbb4787a2016-12-15 12:34:43440 MAYBE_AboutChromeForcesUserManager) {
Owen Minb6e1bf292018-03-15 18:31:52441 AppController* ac = base::mac::ObjCCast<AppController>(
442 [[NSApplication sharedApplication] delegate]);
443 ASSERT_TRUE(ac);
mlermane6e040a2014-10-31 00:53:21444
445 // Create the guest profile, and set it as the last used profile so the
446 // app controller can use it on init.
mlermanb8df6e82015-01-23 19:55:34447 CreateAndWaitForSystemProfile();
mlermane6e040a2014-10-31 00:53:21448 PrefService* local_state = g_browser_process->local_state();
449 local_state->SetString(prefs::kProfileLastUsed, chrome::kGuestProfileDir);
450
451 // Prohibiting guest mode forces the user manager flow for About Chrome.
452 local_state->SetBoolean(prefs::kBrowserGuestModeEnabled, false);
453
Francois Doraye6fb2d02017-10-18 21:29:13454 base::ScopedAllowBlockingForTesting allow_blocking;
mlermane6e040a2014-10-31 00:53:21455 Profile* guest_profile = [ac lastProfile];
456 EXPECT_EQ(ProfileManager::GetGuestProfilePath(), guest_profile->GetPath());
457 EXPECT_TRUE(guest_profile->IsGuestSession());
458
459 // Tell the browser to open About Chrome.
460 EXPECT_EQ(1u, active_browser_list_->size());
461 [ac orderFrontStandardAboutPanel:NSApp];
462
463 base::RunLoop().RunUntilIdle();
464
465 // No new browser is opened; the User Manager opens instead.
466 EXPECT_EQ(1u, active_browser_list_->size());
467 EXPECT_TRUE(UserManager::IsShowing());
468
469 UserManager::Hide();
470}
471
[email protected]66791aff2014-04-29 09:45:38472class AppControllerOpenShortcutBrowserTest : public InProcessBrowserTest {
473 protected:
474 AppControllerOpenShortcutBrowserTest() {
Hector Carmona1e62e352019-06-24 19:18:17475 scoped_feature_list_.InitWithFeatures({nux::kNuxOnboardingForceEnabled},
476 {});
[email protected]66791aff2014-04-29 09:45:38477 }
478
Daniel Chenga542fca2014-10-21 09:51:29479 void SetUpInProcessBrowserTestFixture() override {
[email protected]66791aff2014-04-29 09:45:38480 // In order to mimic opening shortcut during browser startup, we need to
481 // send the event before -applicationDidFinishLaunching is called, but
482 // after AppController is loaded.
483 //
484 // Since -applicationWillFinishLaunching does nothing now, we swizzle it to
485 // our function to send the event. We need to do this early before running
486 // the main message loop.
487 //
488 // NSApp does not exist yet. We need to get the AppController using
489 // reflection.
490 Class appControllerClass = NSClassFromString(@"AppController");
491 Class openShortcutClass = NSClassFromString(@"TestOpenShortcutOnStartup");
492
493 ASSERT_TRUE(appControllerClass != nil);
494 ASSERT_TRUE(openShortcutClass != nil);
495
496 SEL targetMethod = @selector(applicationWillFinishLaunching:);
497 Method original = class_getInstanceMethod(appControllerClass,
498 targetMethod);
499 Method destination = class_getInstanceMethod(openShortcutClass,
500 targetMethod);
501
502 ASSERT_TRUE(original != NULL);
503 ASSERT_TRUE(destination != NULL);
504
505 method_exchangeImplementations(original, destination);
Scott Violet1f106b582017-07-12 15:49:58506
507 ASSERT_TRUE(embedded_test_server()->Start());
508 g_open_shortcut_url = embedded_test_server()->GetURL("/simple.html");
[email protected]66791aff2014-04-29 09:45:38509 }
510
avi3ef9ec9e2014-12-22 22:50:17511 void SetUpCommandLine(base::CommandLine* command_line) override {
[email protected]66791aff2014-04-29 09:45:38512 // If the arg is empty, PrepareTestCommandLine() after this function will
513 // append about:blank as default url.
514 command_line->AppendArg(chrome::kChromeUINewTabURL);
515 }
Hector Carmona1e62e352019-06-24 19:18:17516
517 private:
518 base::test::ScopedFeatureList scoped_feature_list_;
[email protected]66791aff2014-04-29 09:45:38519};
520
521IN_PROC_BROWSER_TEST_F(AppControllerOpenShortcutBrowserTest,
522 OpenShortcutOnStartup) {
tmartino82e55782017-01-10 22:30:17523 // The two tabs expected are the Welcome page and the desired URL.
524 EXPECT_EQ(2, browser()->tab_strip_model()->count());
[email protected]66791aff2014-04-29 09:45:38525 EXPECT_EQ(g_open_shortcut_url,
526 browser()->tab_strip_model()->GetActiveWebContents()
527 ->GetLastCommittedURL());
528}
529
erikchen19ee3922014-10-31 19:14:22530class AppControllerReplaceNTPBrowserTest : public InProcessBrowserTest {
531 protected:
532 AppControllerReplaceNTPBrowserTest() {}
533
534 void SetUpInProcessBrowserTestFixture() override {
svaldeza01f7d92015-11-18 17:47:56535 ASSERT_TRUE(embedded_test_server()->Start());
erikchen19ee3922014-10-31 19:14:22536 }
537
avi3ef9ec9e2014-12-22 22:50:17538 void SetUpCommandLine(base::CommandLine* command_line) override {
erikchen19ee3922014-10-31 19:14:22539 // If the arg is empty, PrepareTestCommandLine() after this function will
540 // append about:blank as default url.
541 command_line->AppendArg(chrome::kChromeUINewTabURL);
542 }
543};
544
545// Tests that when a GURL is opened after startup, it replaces the NTP.
546IN_PROC_BROWSER_TEST_F(AppControllerReplaceNTPBrowserTest,
547 ReplaceNTPAfterStartup) {
kristiparka34b247a2018-03-09 19:05:34548 // Depending on network connectivity, the NTP URL can either be
549 // chrome://newtab/ or chrome-search://local-ntp/local-ntp.html. See
550 // local_ntp_test_utils::GetFinalNtpUrl for more details.
551 std::string expected_url =
552 local_ntp_test_utils::GetFinalNtpUrl(browser()->profile()).spec();
553
erikchen19ee3922014-10-31 19:14:22554 // Ensure that there is exactly 1 tab showing, and the tab is the NTP.
kristiparka34b247a2018-03-09 19:05:34555 GURL ntp(expected_url);
erikchen19ee3922014-10-31 19:14:22556 EXPECT_EQ(1, browser()->tab_strip_model()->count());
tmartino82e55782017-01-10 22:30:17557 browser()->tab_strip_model()->GetActiveWebContents()->GetController().LoadURL(
kristiparka34b247a2018-03-09 19:05:34558 GURL(expected_url), content::Referrer(),
tmartino82e55782017-01-10 22:30:17559 ui::PageTransition::PAGE_TRANSITION_LINK, std::string());
560
561 // Wait for one navigation on the active web contents.
562 content::TestNavigationObserver ntp_navigation_observer(
563 browser()->tab_strip_model()->GetActiveWebContents());
564 ntp_navigation_observer.Wait();
565
erikchen19ee3922014-10-31 19:14:22566 EXPECT_EQ(ntp,
567 browser()
568 ->tab_strip_model()
569 ->GetActiveWebContents()
570 ->GetLastCommittedURL());
571
572 GURL simple(embedded_test_server()->GetURL("/simple.html"));
573 SendAppleEventToOpenUrlToAppController(simple);
574
erikchen19ee3922014-10-31 19:14:22575 EXPECT_EQ(1, browser()->tab_strip_model()->count());
tmartino82e55782017-01-10 22:30:17576 content::TestNavigationObserver event_navigation_observer(
577 browser()->tab_strip_model()->GetActiveWebContents());
578 event_navigation_observer.Wait();
erikchen19ee3922014-10-31 19:14:22579
580 EXPECT_EQ(simple,
581 browser()
582 ->tab_strip_model()
583 ->GetActiveWebContents()
584 ->GetLastCommittedURL());
585}
586
Christian Dullweber820ee5f2018-04-26 13:24:31587// Tests that when a GURL is opened, it is not opened in incognito mode.
588IN_PROC_BROWSER_TEST_F(AppControllerBrowserTest, OpenInRegularBrowser) {
589 ASSERT_TRUE(embedded_test_server()->Start());
590 // Create an incognito browser.
591 Browser* incognito_browser = CreateIncognitoBrowser(browser()->profile());
592 EXPECT_EQ(incognito_browser, chrome::GetLastActiveBrowser());
593 EXPECT_EQ(1, browser()->tab_strip_model()->count());
594 EXPECT_EQ(1, incognito_browser->tab_strip_model()->count());
595 // Open a url.
596 GURL simple(embedded_test_server()->GetURL("/simple.html"));
597 SendAppleEventToOpenUrlToAppController(simple);
598 // It should be opened in the regular browser.
599 content::TestNavigationObserver event_navigation_observer(
600 browser()->tab_strip_model()->GetActiveWebContents());
601 event_navigation_observer.Wait();
602 EXPECT_EQ(2, browser()->tab_strip_model()->count());
603 EXPECT_EQ(1, incognito_browser->tab_strip_model()->count());
604 EXPECT_EQ(simple, browser()
605 ->tab_strip_model()
606 ->GetActiveWebContents()
607 ->GetLastCommittedURL());
608}
609
lgarron9e6dee22014-11-18 01:03:39610class AppControllerMainMenuBrowserTest : public InProcessBrowserTest {
611 protected:
612 AppControllerMainMenuBrowserTest() {
613 }
614};
615
616IN_PROC_BROWSER_TEST_F(AppControllerMainMenuBrowserTest,
mlerman8ae56aa2015-04-24 13:56:27617 HistoryMenuResetAfterProfileDeletion) {
618 ProfileManager* profile_manager = g_browser_process->profile_manager();
tapted676995d2016-04-18 11:32:29619 AppController* ac =
620 base::mac::ObjCCastStrict<AppController>([NSApp delegate]);
mlerman8ae56aa2015-04-24 13:56:27621
622 // Use the existing profile as profile 1.
623 Profile* profile1 = browser()->profile();
624
625 // Create profile 2.
626 base::FilePath profile2_path =
627 profile_manager->GenerateNextProfileDirectoryPath();
628 base::RunLoop run_loop;
629 profile_manager->CreateProfileAsync(
630 profile2_path,
631 base::Bind(&RunClosureWhenProfileInitialized,
632 run_loop.QuitClosure()),
lwchkg1f62d242015-10-29 00:50:43633 base::string16(),
lwchkg1f62d242015-10-29 00:50:43634 std::string());
mlerman8ae56aa2015-04-24 13:56:27635 run_loop.Run();
636 Profile* profile2 = profile_manager->GetProfileByPath(profile2_path);
637 ASSERT_TRUE(profile2);
638
Sidney San Martínaa3b48f2018-06-03 08:10:05639 // Load profile1's History Service backend so it will be assigned to the
640 // HistoryMenuBridge when windowChangedToProfile is called, or else this test
641 // will fail flaky.
642 ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
643 profile1, ServiceAccessType::EXPLICIT_ACCESS));
mlerman8ae56aa2015-04-24 13:56:27644 // Switch the controller to profile1.
645 [ac windowChangedToProfile:profile1];
646 base::RunLoop().RunUntilIdle();
647
648 // Verify the controller's History Menu corresponds to profile1.
649 EXPECT_TRUE([ac historyMenuBridge]->service());
650 EXPECT_EQ([ac historyMenuBridge]->service(),
651 HistoryServiceFactory::GetForProfile(profile1,
652 ServiceAccessType::EXPLICIT_ACCESS));
653
654 // Load profile2's History Service backend so it will be assigned to the
655 // HistoryMenuBridge when windowChangedToProfile is called, or else this test
656 // will fail flaky.
657 ui_test_utils::WaitForHistoryToLoad(
658 HistoryServiceFactory::GetForProfile(profile2,
659 ServiceAccessType::EXPLICIT_ACCESS));
660 // Switch the controller to profile2.
661 [ac windowChangedToProfile:profile2];
662 base::RunLoop().RunUntilIdle();
663
664 // Verify the controller's History Menu has changed.
665 EXPECT_TRUE([ac historyMenuBridge]->service());
666 EXPECT_EQ([ac historyMenuBridge]->service(),
667 HistoryServiceFactory::GetForProfile(profile2,
668 ServiceAccessType::EXPLICIT_ACCESS));
669 EXPECT_NE(
670 HistoryServiceFactory::GetForProfile(profile1,
671 ServiceAccessType::EXPLICIT_ACCESS),
672 HistoryServiceFactory::GetForProfile(profile2,
673 ServiceAccessType::EXPLICIT_ACCESS));
674
675 // Delete profile2.
David Roger51797642018-03-20 13:29:16676 profile_manager->ScheduleProfileForDeletion(profile2->GetPath(),
677 base::DoNothing());
mlerman8ae56aa2015-04-24 13:56:27678 base::RunLoop().RunUntilIdle();
679
680 // Verify the controller's history is back to profile1.
681 EXPECT_EQ([ac historyMenuBridge]->service(),
682 HistoryServiceFactory::GetForProfile(profile1,
683 ServiceAccessType::EXPLICIT_ACCESS));
684}
685
686IN_PROC_BROWSER_TEST_F(AppControllerMainMenuBrowserTest,
lgarron9e6dee22014-11-18 01:03:39687 BookmarksMenuIsRestoredAfterProfileSwitch) {
688 ProfileManager* profile_manager = g_browser_process->profile_manager();
Owen Minb6e1bf292018-03-15 18:31:52689 AppController* ac = base::mac::ObjCCast<AppController>(
690 [[NSApplication sharedApplication] delegate]);
691 ASSERT_TRUE(ac);
692
Robert Sesek124f80f92018-07-24 20:31:29693 [ac mainMenuCreated];
lgarron9e6dee22014-11-18 01:03:39694
695 // Constants for bookmarks that we will create later.
696 const base::string16 title1(base::ASCIIToUTF16("Dinosaur Comics"));
697 const GURL url1("http://qwantz.com//");
698
699 const base::string16 title2(base::ASCIIToUTF16("XKCD"));
700 const GURL url2("https://www.xkcd.com/");
701
702 // Use the existing profile as profile 1.
703 Profile* profile1 = browser()->profile();
704 bookmarks::test::WaitForBookmarkModelToLoad(
pke3e0d5c92016-08-08 09:07:30705 BookmarkModelFactory::GetForBrowserContext(profile1));
lgarron9e6dee22014-11-18 01:03:39706
707 // Create profile 2.
Francois Doraye6fb2d02017-10-18 21:29:13708 base::ScopedAllowBlockingForTesting allow_blocking;
lgarron9e6dee22014-11-18 01:03:39709 base::FilePath path2 = profile_manager->GenerateNextProfileDirectoryPath();
Daniel Hosseinian8f0b7482019-06-07 18:21:04710 std::unique_ptr<Profile> profile2 =
711 Profile::CreateProfile(path2, NULL, Profile::CREATE_MODE_SYNCHRONOUS);
712 Profile* profile2_ptr = profile2.get();
713 profile_manager->RegisterTestingProfile(std::move(profile2), false, true);
lgarron9e6dee22014-11-18 01:03:39714 bookmarks::test::WaitForBookmarkModelToLoad(
Daniel Hosseinian8f0b7482019-06-07 18:21:04715 BookmarkModelFactory::GetForBrowserContext(profile2_ptr));
lgarron9e6dee22014-11-18 01:03:39716
717 // Switch to profile 1, create bookmark 1 and force the menu to build.
718 [ac windowChangedToProfile:profile1];
719 [ac bookmarkMenuBridge]->GetBookmarkModel()->AddURL(
720 [ac bookmarkMenuBridge]->GetBookmarkModel()->bookmark_bar_node(),
721 0, title1, url1);
Trent Aptedcf95689a2017-11-22 00:01:10722 NSMenu* profile1_submenu = [ac bookmarkMenuBridge]->BookmarkMenu();
723 [[profile1_submenu delegate] menuNeedsUpdate:profile1_submenu];
lgarron9e6dee22014-11-18 01:03:39724
725 // Switch to profile 2, create bookmark 2 and force the menu to build.
Daniel Hosseinian8f0b7482019-06-07 18:21:04726 [ac windowChangedToProfile:profile2_ptr];
lgarron9e6dee22014-11-18 01:03:39727 [ac bookmarkMenuBridge]->GetBookmarkModel()->AddURL(
728 [ac bookmarkMenuBridge]->GetBookmarkModel()->bookmark_bar_node(),
729 0, title2, url2);
Trent Aptedcf95689a2017-11-22 00:01:10730 NSMenu* profile2_submenu = [ac bookmarkMenuBridge]->BookmarkMenu();
731 [[profile2_submenu delegate] menuNeedsUpdate:profile2_submenu];
732 EXPECT_NE(profile1_submenu, profile2_submenu);
lgarron9e6dee22014-11-18 01:03:39733
734 // Test that only bookmark 2 is shown.
735 EXPECT_FALSE([[ac bookmarkMenuBridge]->BookmarkMenu() itemWithTitle:
736 SysUTF16ToNSString(title1)]);
737 EXPECT_TRUE([[ac bookmarkMenuBridge]->BookmarkMenu() itemWithTitle:
738 SysUTF16ToNSString(title2)]);
739
740 // Switch *back* to profile 1 and *don't* force the menu to build.
741 [ac windowChangedToProfile:profile1];
742
743 // Test that only bookmark 1 is shown in the restored menu.
744 EXPECT_TRUE([[ac bookmarkMenuBridge]->BookmarkMenu() itemWithTitle:
745 SysUTF16ToNSString(title1)]);
746 EXPECT_FALSE([[ac bookmarkMenuBridge]->BookmarkMenu() itemWithTitle:
747 SysUTF16ToNSString(title2)]);
Trent Aptedcf95689a2017-11-22 00:01:10748
749 // Ensure a cached menu was used.
750 EXPECT_EQ(profile1_submenu, [ac bookmarkMenuBridge]->BookmarkMenu());
lgarron9e6dee22014-11-18 01:03:39751}
752
[email protected]fc44f242012-02-14 16:54:39753} // namespace
erikchen600f7962014-12-12 00:17:38754
755//--------------------------AppControllerHandoffBrowserTest---------------------
756
757static GURL g_handoff_url;
758
759@interface AppController (BrowserTest)
erikchen600f7962014-12-12 00:17:38760- (void)new_passURLToHandoffManager:(const GURL&)handoffURL;
761@end
762
763@implementation AppController (BrowserTest)
erikchen600f7962014-12-12 00:17:38764- (void)new_passURLToHandoffManager:(const GURL&)handoffURL {
765 g_handoff_url = handoffURL;
766}
767@end
768
769namespace {
770
771class AppControllerHandoffBrowserTest : public InProcessBrowserTest {
772 protected:
773 AppControllerHandoffBrowserTest() {}
774
775 // Exchanges the implementations of the two selectors on the class
776 // AppController.
777 void ExchangeSelectors(SEL originalMethod, SEL newMethod) {
778 Class appControllerClass = NSClassFromString(@"AppController");
779
780 ASSERT_TRUE(appControllerClass != nil);
781
782 Method original =
783 class_getInstanceMethod(appControllerClass, originalMethod);
784 Method destination = class_getInstanceMethod(appControllerClass, newMethod);
785
786 ASSERT_TRUE(original != NULL);
787 ASSERT_TRUE(destination != NULL);
788
789 method_exchangeImplementations(original, destination);
790 }
791
792 // Swizzle Handoff related implementations.
793 void SetUpInProcessBrowserTestFixture() override {
erikchen600f7962014-12-12 00:17:38794 // This swizzle intercepts the URL that would be sent to the Handoff
795 // Manager, and instead puts it into a variable accessible to this test.
Avi Drissman438827be2019-06-06 18:46:11796 SEL originalMethod = @selector(passURLToHandoffManager:);
797 SEL newMethod = @selector(new_passURLToHandoffManager:);
erikchen600f7962014-12-12 00:17:38798 ExchangeSelectors(originalMethod, newMethod);
799 }
800
801 // Closes the tab, and waits for the close to finish.
802 void CloseTab(Browser* browser, int index) {
803 content::WebContentsDestroyedWatcher destroyed_watcher(
804 browser->tab_strip_model()->GetWebContentsAt(index));
805 browser->tab_strip_model()->CloseWebContentsAt(
806 index, TabStripModel::CLOSE_CREATE_HISTORICAL_TAB);
807 destroyed_watcher.Wait();
808 }
809};
810
811// Tests that as a user switches between tabs, navigates within a tab, and
812// switches between browser windows, the correct URL is being passed to the
813// Handoff.
814IN_PROC_BROWSER_TEST_F(AppControllerHandoffBrowserTest, TestHandoffURLs) {
svaldeza01f7d92015-11-18 17:47:56815 ASSERT_TRUE(embedded_test_server()->Start());
erikchen600f7962014-12-12 00:17:38816 EXPECT_EQ(g_handoff_url, GURL(url::kAboutBlankURL));
817
818 // Test that navigating to a URL updates the handoff URL.
819 GURL test_url1 = embedded_test_server()->GetURL("/title1.html");
820 ui_test_utils::NavigateToURL(browser(), test_url1);
821 EXPECT_EQ(g_handoff_url, test_url1);
822
823 // Test that opening a new tab updates the handoff URL.
824 GURL test_url2 = embedded_test_server()->GetURL("/title2.html");
cm.sanchi2522bc92017-12-04 08:04:13825 NavigateParams params(browser(), test_url2, ui::PAGE_TRANSITION_LINK);
nick3b04f322016-08-31 19:29:19826 params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
erikchen600f7962014-12-12 00:17:38827 ui_test_utils::NavigateToURL(&params);
828 EXPECT_EQ(g_handoff_url, test_url2);
829
830 // Test that switching tabs updates the handoff URL.
Edwin Joe6f6fc1e2019-02-27 20:00:37831 browser()->tab_strip_model()->ActivateTabAt(
832 0, {TabStripModel::GestureType::kOther});
erikchen600f7962014-12-12 00:17:38833 EXPECT_EQ(g_handoff_url, test_url1);
834
835 // Test that closing the current tab updates the handoff URL.
836 CloseTab(browser(), 0);
837 EXPECT_EQ(g_handoff_url, test_url2);
838
839 // Test that opening a new browser window updates the handoff URL.
840 GURL test_url3 = embedded_test_server()->GetURL("/title3.html");
841 ui_test_utils::NavigateToURLWithDisposition(
nick3b04f322016-08-31 19:29:19842 browser(), GURL(test_url3), WindowOpenDisposition::NEW_WINDOW,
erikchen600f7962014-12-12 00:17:38843 ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER);
844 EXPECT_EQ(g_handoff_url, test_url3);
845
846 // Check that there are exactly 2 browsers.
scottmg0d8e4ab2016-01-28 00:34:55847 BrowserList* active_browser_list = BrowserList::GetInstance();
erikchen600f7962014-12-12 00:17:38848 EXPECT_EQ(2u, active_browser_list->size());
849
erikchen64a6d442015-07-10 19:38:20850 // Close the second browser window (which only has 1 tab left).
erikchen600f7962014-12-12 00:17:38851 Browser* browser2 = active_browser_list->get(1);
erikchen64a6d442015-07-10 19:38:20852 CloseBrowserSynchronously(browser2);
erikchen600f7962014-12-12 00:17:38853 EXPECT_EQ(g_handoff_url, test_url2);
854
855 // The URLs of incognito windows should not be passed to Handoff.
856 GURL test_url4 = embedded_test_server()->GetURL("/simple.html");
857 ui_test_utils::NavigateToURLWithDisposition(
nick3b04f322016-08-31 19:29:19858 browser(), GURL(test_url4), WindowOpenDisposition::OFF_THE_RECORD,
erikchen600f7962014-12-12 00:17:38859 ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER);
860 EXPECT_EQ(g_handoff_url, GURL());
861
862 // Open a new tab in the incognito window.
863 EXPECT_EQ(2u, active_browser_list->size());
864 Browser* browser3 = active_browser_list->get(1);
865 ui_test_utils::NavigateToURLWithDisposition(
nick3b04f322016-08-31 19:29:19866 browser3, test_url4, WindowOpenDisposition::NEW_FOREGROUND_TAB,
erikchen600f7962014-12-12 00:17:38867 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
868 EXPECT_EQ(g_handoff_url, GURL());
869
870 // Navigate the current tab in the incognito window.
thestig53986dc2014-12-16 06:09:18871 ui_test_utils::NavigateToURL(browser3, test_url1);
erikchen600f7962014-12-12 00:17:38872 EXPECT_EQ(g_handoff_url, GURL());
873
874 // Activate the original browser window.
875 Browser* browser1 = active_browser_list->get(0);
876 browser1->window()->Show();
877 EXPECT_EQ(g_handoff_url, test_url2);
878}
879
880} // namespace