Make castv2 performance test work.
[chromium-blink-merge.git] / chrome / browser / app_controller_mac_browsertest.mm
blob52fa358be367f07ac4379687bdb787fef7de07ba
1 // 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.
5 #import <Carbon/Carbon.h>
6 #import <Cocoa/Cocoa.h>
7 #import <Foundation/Foundation.h>
8 #import <Foundation/NSAppleEventDescriptor.h>
9 #import <objc/message.h>
10 #import <objc/runtime.h>
12 #include "base/command_line.h"
13 #include "base/mac/foundation_util.h"
14 #include "base/mac/scoped_nsobject.h"
15 #include "base/prefs/pref_service.h"
16 #include "base/run_loop.h"
17 #include "base/strings/sys_string_conversions.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "chrome/app/chrome_command_ids.h"
20 #include "components/bookmarks/browser/bookmark_model.h"
21 #import "chrome/browser/app_controller_mac.h"
22 #include "chrome/browser/apps/app_browsertest_util.h"
23 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
24 #include "chrome/browser/browser_process.h"
25 #include "chrome/browser/profiles/profile_manager.h"
26 #include "chrome/browser/ui/browser.h"
27 #include "chrome/browser/ui/browser_list.h"
28 #include "chrome/browser/ui/browser_window.h"
29 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.h"
30 #include "chrome/browser/ui/host_desktop.h"
31 #include "chrome/browser/ui/tabs/tab_strip_model.h"
32 #include "chrome/browser/ui/user_manager.h"
33 #include "chrome/common/chrome_constants.h"
34 #include "chrome/common/chrome_switches.h"
35 #include "chrome/common/pref_names.h"
36 #include "chrome/common/url_constants.h"
37 #include "chrome/test/base/in_process_browser_test.h"
38 #include "chrome/test/base/ui_test_utils.h"
39 #include "components/bookmarks/test/bookmark_test_helpers.h"
40 #include "components/signin/core/common/profile_management_switches.h"
41 #include "content/public/browser/web_contents.h"
42 #include "content/public/test/browser_test_utils.h"
43 #include "content/public/test/test_navigation_observer.h"
44 #include "extensions/browser/app_window/app_window_registry.h"
45 #include "extensions/common/extension.h"
46 #include "extensions/test/extension_test_message_listener.h"
47 #include "net/test/embedded_test_server/embedded_test_server.h"
49 namespace {
51 GURL g_open_shortcut_url = GURL::EmptyGURL();
53 // Returns an Apple Event that instructs the application to open |url|.
54 NSAppleEventDescriptor* AppleEventToOpenUrl(const GURL& url) {
55   NSAppleEventDescriptor* shortcut_event = [[[NSAppleEventDescriptor alloc]
56       initWithEventClass:kASAppleScriptSuite
57                  eventID:kASSubroutineEvent
58         targetDescriptor:nil
59                 returnID:kAutoGenerateReturnID
60            transactionID:kAnyTransactionID] autorelease];
61   NSString* url_string = [NSString stringWithUTF8String:url.spec().c_str()];
62   [shortcut_event setParamDescriptor:[NSAppleEventDescriptor
63                                          descriptorWithString:url_string]
64                           forKeyword:keyDirectObject];
65   return shortcut_event;
68 // Instructs the NSApp's delegate to open |url|.
69 void SendAppleEventToOpenUrlToAppController(const GURL& url) {
70   AppController* controller =
71       base::mac::ObjCCast<AppController>([NSApp delegate]);
72   Method get_url =
73       class_getInstanceMethod([controller class], @selector(getUrl:withReply:));
75   ASSERT_TRUE(get_url);
77   NSAppleEventDescriptor* shortcut_event = AppleEventToOpenUrl(url);
79   method_invoke(controller, get_url, shortcut_event, NULL);
82 }  // namespace
84 @interface TestOpenShortcutOnStartup : NSObject
85 - (void)applicationWillFinishLaunching:(NSNotification*)notification;
86 @end
88 @implementation TestOpenShortcutOnStartup
90 - (void)applicationWillFinishLaunching:(NSNotification*)notification {
91   if (!g_open_shortcut_url.is_valid())
92     return;
94   SendAppleEventToOpenUrlToAppController(g_open_shortcut_url);
97 @end
99 namespace {
101 class AppControllerPlatformAppBrowserTest
102     : public extensions::PlatformAppBrowserTest {
103  protected:
104   AppControllerPlatformAppBrowserTest()
105       : active_browser_list_(BrowserList::GetInstance(
106                                 chrome::GetActiveDesktop())) {
107   }
109   void SetUpCommandLine(base::CommandLine* command_line) override {
110     PlatformAppBrowserTest::SetUpCommandLine(command_line);
111     command_line->AppendSwitchASCII(switches::kAppId,
112                                     "1234");
113   }
115   const BrowserList* active_browser_list_;
118 // Test that if only a platform app window is open and no browser windows are
119 // open then a reopen event does nothing.
120 IN_PROC_BROWSER_TEST_F(AppControllerPlatformAppBrowserTest,
121                        PlatformAppReopenWithWindows) {
122   base::scoped_nsobject<AppController> ac([[AppController alloc] init]);
123   NSUInteger old_window_count = [[NSApp windows] count];
124   EXPECT_EQ(1u, active_browser_list_->size());
125   [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:YES];
126   // We do not EXPECT_TRUE the result here because the method
127   // deminiaturizes windows manually rather than return YES and have
128   // AppKit do it.
130   EXPECT_EQ(old_window_count, [[NSApp windows] count]);
131   EXPECT_EQ(1u, active_browser_list_->size());
134 IN_PROC_BROWSER_TEST_F(AppControllerPlatformAppBrowserTest,
135                        ActivationFocusesBrowserWindow) {
136   base::scoped_nsobject<AppController> app_controller(
137       [[AppController alloc] init]);
139   ExtensionTestMessageListener listener("Launched", false);
140   const extensions::Extension* app =
141       InstallAndLaunchPlatformApp("minimal");
142   ASSERT_TRUE(listener.WaitUntilSatisfied());
144   NSWindow* app_window = extensions::AppWindowRegistry::Get(profile())
145                              ->GetAppWindowsForApp(app->id())
146                              .front()
147                              ->GetNativeWindow();
148   NSWindow* browser_window = browser()->window()->GetNativeWindow();
150   EXPECT_LE([[NSApp orderedWindows] indexOfObject:app_window],
151             [[NSApp orderedWindows] indexOfObject:browser_window]);
152   [app_controller applicationShouldHandleReopen:NSApp
153                               hasVisibleWindows:YES];
154   EXPECT_LE([[NSApp orderedWindows] indexOfObject:browser_window],
155             [[NSApp orderedWindows] indexOfObject:app_window]);
158 class AppControllerWebAppBrowserTest : public InProcessBrowserTest {
159  protected:
160   AppControllerWebAppBrowserTest()
161       : active_browser_list_(BrowserList::GetInstance(
162                                 chrome::GetActiveDesktop())) {
163   }
165   void SetUpCommandLine(base::CommandLine* command_line) override {
166     command_line->AppendSwitchASCII(switches::kApp, GetAppURL());
167   }
169   std::string GetAppURL() const {
170     return "http://example.com/";
171   }
173   const BrowserList* active_browser_list_;
176 // Test that in web app mode a reopen event opens the app URL.
177 IN_PROC_BROWSER_TEST_F(AppControllerWebAppBrowserTest,
178                        WebAppReopenWithNoWindows) {
179   base::scoped_nsobject<AppController> ac([[AppController alloc] init]);
180   EXPECT_EQ(1u, active_browser_list_->size());
181   BOOL result = [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:NO];
183   EXPECT_FALSE(result);
184   EXPECT_EQ(2u, active_browser_list_->size());
186   Browser* browser = active_browser_list_->get(0);
187   GURL current_url =
188       browser->tab_strip_model()->GetActiveWebContents()->GetURL();
189   EXPECT_EQ(GetAppURL(), current_url.spec());
192 // Called when the ProfileManager has created a profile.
193 void CreateProfileCallback(const base::Closure& quit_closure,
194                            Profile* profile,
195                            Profile::CreateStatus status) {
196   EXPECT_TRUE(profile);
197   EXPECT_NE(Profile::CREATE_STATUS_LOCAL_FAIL, status);
198   EXPECT_NE(Profile::CREATE_STATUS_REMOTE_FAIL, status);
199   // This will be called multiple times. Wait until the profile is initialized
200   // fully to quit the loop.
201   if (status == Profile::CREATE_STATUS_INITIALIZED)
202     quit_closure.Run();
205 void CreateAndWaitForSystemProfile() {
206   ProfileManager::CreateCallback create_callback =
207       base::Bind(&CreateProfileCallback,
208                  base::MessageLoop::current()->QuitClosure());
209   g_browser_process->profile_manager()->CreateProfileAsync(
210       ProfileManager::GetSystemProfilePath(),
211       create_callback,
212       base::string16(),
213       base::string16(),
214       std::string());
215   base::RunLoop().Run();
218 class AppControllerNewProfileManagementBrowserTest
219     : public InProcessBrowserTest {
220  protected:
221   AppControllerNewProfileManagementBrowserTest()
222       : active_browser_list_(BrowserList::GetInstance(
223                                 chrome::GetActiveDesktop())) {
224   }
226   void SetUpCommandLine(base::CommandLine* command_line) override {
227     switches::EnableNewProfileManagementForTesting(command_line);
228   }
230   const BrowserList* active_browser_list_;
233 // Test that for a regular last profile, a reopen event opens a browser.
234 IN_PROC_BROWSER_TEST_F(AppControllerNewProfileManagementBrowserTest,
235                        RegularProfileReopenWithNoWindows) {
236   base::scoped_nsobject<AppController> ac([[AppController alloc] init]);
237   EXPECT_EQ(1u, active_browser_list_->size());
238   BOOL result = [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:NO];
240   EXPECT_FALSE(result);
241   EXPECT_EQ(2u, active_browser_list_->size());
242   EXPECT_FALSE(UserManager::IsShowing());
245 // Test that for a locked last profile, a reopen event opens the User Manager.
246 IN_PROC_BROWSER_TEST_F(AppControllerNewProfileManagementBrowserTest,
247                        LockedProfileReopenWithNoWindows) {
248   // The User Manager uses the system profile as its underlying profile. To
249   // minimize flakiness due to the scheduling/descheduling of tasks on the
250   // different threads, pre-initialize the guest profile before it is needed.
251   CreateAndWaitForSystemProfile();
252   base::scoped_nsobject<AppController> ac([[AppController alloc] init]);
254   // Lock the active profile.
255   Profile* profile = [ac lastProfile];
256   ProfileInfoCache& cache =
257       g_browser_process->profile_manager()->GetProfileInfoCache();
258   size_t profile_index = cache.GetIndexOfProfileWithPath(profile->GetPath());
259   cache.SetProfileSigninRequiredAtIndex(profile_index, true);
260   EXPECT_TRUE(cache.ProfileIsSigninRequiredAtIndex(profile_index));
262   EXPECT_EQ(1u, active_browser_list_->size());
263   BOOL result = [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:NO];
264   EXPECT_FALSE(result);
266   base::RunLoop().RunUntilIdle();
267   EXPECT_EQ(1u, active_browser_list_->size());
268   EXPECT_TRUE(UserManager::IsShowing());
269   UserManager::Hide();
272 // Test that for a guest last profile, a reopen event opens the User Manager.
273 IN_PROC_BROWSER_TEST_F(AppControllerNewProfileManagementBrowserTest,
274                        GuestProfileReopenWithNoWindows) {
275   // Create the system profile. Set the guest as the last used profile so the
276   // app controller can use it on init.
277   CreateAndWaitForSystemProfile();
278   PrefService* local_state = g_browser_process->local_state();
279   local_state->SetString(prefs::kProfileLastUsed, chrome::kGuestProfileDir);
281   base::scoped_nsobject<AppController> ac([[AppController alloc] init]);
283   Profile* profile = [ac lastProfile];
284   EXPECT_EQ(ProfileManager::GetGuestProfilePath(), profile->GetPath());
285   EXPECT_TRUE(profile->IsGuestSession());
287   EXPECT_EQ(1u, active_browser_list_->size());
288   BOOL result = [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:NO];
289   EXPECT_FALSE(result);
291   base::RunLoop().RunUntilIdle();
293   EXPECT_EQ(1u, active_browser_list_->size());
294   EXPECT_TRUE(UserManager::IsShowing());
295   UserManager::Hide();
298 IN_PROC_BROWSER_TEST_F(AppControllerNewProfileManagementBrowserTest,
299                        AboutChromeForcesUserManager) {
300   base::scoped_nsobject<AppController> ac([[AppController alloc] init]);
302   // Create the guest profile, and set it as the last used profile so the
303   // app controller can use it on init.
304   CreateAndWaitForSystemProfile();
305   PrefService* local_state = g_browser_process->local_state();
306   local_state->SetString(prefs::kProfileLastUsed, chrome::kGuestProfileDir);
308   // Prohibiting guest mode forces the user manager flow for About Chrome.
309   local_state->SetBoolean(prefs::kBrowserGuestModeEnabled, false);
311   Profile* guest_profile = [ac lastProfile];
312   EXPECT_EQ(ProfileManager::GetGuestProfilePath(), guest_profile->GetPath());
313   EXPECT_TRUE(guest_profile->IsGuestSession());
315   // Tell the browser to open About Chrome.
316   EXPECT_EQ(1u, active_browser_list_->size());
317   [ac orderFrontStandardAboutPanel:NSApp];
319   base::RunLoop().RunUntilIdle();
321   // No new browser is opened; the User Manager opens instead.
322   EXPECT_EQ(1u, active_browser_list_->size());
323   EXPECT_TRUE(UserManager::IsShowing());
325   UserManager::Hide();
328 class AppControllerOpenShortcutBrowserTest : public InProcessBrowserTest {
329  protected:
330   AppControllerOpenShortcutBrowserTest() {
331   }
333   void SetUpInProcessBrowserTestFixture() override {
334     // In order to mimic opening shortcut during browser startup, we need to
335     // send the event before -applicationDidFinishLaunching is called, but
336     // after AppController is loaded.
337     //
338     // Since -applicationWillFinishLaunching does nothing now, we swizzle it to
339     // our function to send the event. We need to do this early before running
340     // the main message loop.
341     //
342     // NSApp does not exist yet. We need to get the AppController using
343     // reflection.
344     Class appControllerClass = NSClassFromString(@"AppController");
345     Class openShortcutClass = NSClassFromString(@"TestOpenShortcutOnStartup");
347     ASSERT_TRUE(appControllerClass != nil);
348     ASSERT_TRUE(openShortcutClass != nil);
350     SEL targetMethod = @selector(applicationWillFinishLaunching:);
351     Method original = class_getInstanceMethod(appControllerClass,
352         targetMethod);
353     Method destination = class_getInstanceMethod(openShortcutClass,
354         targetMethod);
356     ASSERT_TRUE(original != NULL);
357     ASSERT_TRUE(destination != NULL);
359     method_exchangeImplementations(original, destination);
361     ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
362     g_open_shortcut_url = embedded_test_server()->GetURL("/simple.html");
363   }
365   void SetUpCommandLine(base::CommandLine* command_line) override {
366     // If the arg is empty, PrepareTestCommandLine() after this function will
367     // append about:blank as default url.
368     command_line->AppendArg(chrome::kChromeUINewTabURL);
369   }
372 IN_PROC_BROWSER_TEST_F(AppControllerOpenShortcutBrowserTest,
373                        OpenShortcutOnStartup) {
374   EXPECT_EQ(1, browser()->tab_strip_model()->count());
375   EXPECT_EQ(g_open_shortcut_url,
376       browser()->tab_strip_model()->GetActiveWebContents()
377           ->GetLastCommittedURL());
380 class AppControllerReplaceNTPBrowserTest : public InProcessBrowserTest {
381  protected:
382   AppControllerReplaceNTPBrowserTest() {}
384   void SetUpInProcessBrowserTestFixture() override {
385     ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
386   }
388   void SetUpCommandLine(base::CommandLine* command_line) override {
389     // If the arg is empty, PrepareTestCommandLine() after this function will
390     // append about:blank as default url.
391     command_line->AppendArg(chrome::kChromeUINewTabURL);
392   }
395 // Tests that when a GURL is opened after startup, it replaces the NTP.
396 IN_PROC_BROWSER_TEST_F(AppControllerReplaceNTPBrowserTest,
397                        ReplaceNTPAfterStartup) {
398   // Ensure that there is exactly 1 tab showing, and the tab is the NTP.
399   GURL ntp(chrome::kChromeUINewTabURL);
400   EXPECT_EQ(1, browser()->tab_strip_model()->count());
401   EXPECT_EQ(ntp,
402             browser()
403                 ->tab_strip_model()
404                 ->GetActiveWebContents()
405                 ->GetLastCommittedURL());
407   GURL simple(embedded_test_server()->GetURL("/simple.html"));
408   SendAppleEventToOpenUrlToAppController(simple);
410   // Wait for one navigation on the active web contents.
411   EXPECT_EQ(1, browser()->tab_strip_model()->count());
412   content::TestNavigationObserver obs(
413       browser()->tab_strip_model()->GetActiveWebContents(), 1);
414   obs.Wait();
416   EXPECT_EQ(simple,
417             browser()
418                 ->tab_strip_model()
419                 ->GetActiveWebContents()
420                 ->GetLastCommittedURL());
423 class AppControllerMainMenuBrowserTest : public InProcessBrowserTest {
424  protected:
425   AppControllerMainMenuBrowserTest() {
426   }
429 IN_PROC_BROWSER_TEST_F(AppControllerMainMenuBrowserTest,
430     BookmarksMenuIsRestoredAfterProfileSwitch) {
431   ProfileManager* profile_manager = g_browser_process->profile_manager();
432   base::scoped_nsobject<AppController> ac([[AppController alloc] init]);
433   [ac awakeFromNib];
435   // Constants for bookmarks that we will create later.
436   const base::string16 title1(base::ASCIIToUTF16("Dinosaur Comics"));
437   const GURL url1("http://qwantz.com//");
439   const base::string16 title2(base::ASCIIToUTF16("XKCD"));
440   const GURL url2("https://www.xkcd.com/");
442   // Use the existing profile as profile 1.
443   Profile* profile1 = browser()->profile();
444   bookmarks::test::WaitForBookmarkModelToLoad(
445       BookmarkModelFactory::GetForProfile(profile1));
447   // Create profile 2.
448   base::FilePath path2 = profile_manager->GenerateNextProfileDirectoryPath();
449   Profile* profile2 =
450       Profile::CreateProfile(path2, NULL, Profile::CREATE_MODE_SYNCHRONOUS);
451   profile_manager->RegisterTestingProfile(profile2, false, true);
452   bookmarks::test::WaitForBookmarkModelToLoad(
453       BookmarkModelFactory::GetForProfile(profile2));
455   // Switch to profile 1, create bookmark 1 and force the menu to build.
456   [ac windowChangedToProfile:profile1];
457   [ac bookmarkMenuBridge]->GetBookmarkModel()->AddURL(
458       [ac bookmarkMenuBridge]->GetBookmarkModel()->bookmark_bar_node(),
459       0, title1, url1);
460   [ac bookmarkMenuBridge]->BuildMenu();
462   // Switch to profile 2, create bookmark 2 and force the menu to build.
463   [ac windowChangedToProfile:profile2];
464   [ac bookmarkMenuBridge]->GetBookmarkModel()->AddURL(
465       [ac bookmarkMenuBridge]->GetBookmarkModel()->bookmark_bar_node(),
466       0, title2, url2);
467   [ac bookmarkMenuBridge]->BuildMenu();
469   // Test that only bookmark 2 is shown.
470   EXPECT_FALSE([[ac bookmarkMenuBridge]->BookmarkMenu() itemWithTitle:
471       SysUTF16ToNSString(title1)]);
472   EXPECT_TRUE([[ac bookmarkMenuBridge]->BookmarkMenu() itemWithTitle:
473       SysUTF16ToNSString(title2)]);
475   // Switch *back* to profile 1 and *don't* force the menu to build.
476   [ac windowChangedToProfile:profile1];
478   // Test that only bookmark 1 is shown in the restored menu.
479   EXPECT_TRUE([[ac bookmarkMenuBridge]->BookmarkMenu() itemWithTitle:
480       SysUTF16ToNSString(title1)]);
481   EXPECT_FALSE([[ac bookmarkMenuBridge]->BookmarkMenu() itemWithTitle:
482       SysUTF16ToNSString(title2)]);
485 }  // namespace
487 //--------------------------AppControllerHandoffBrowserTest---------------------
489 static GURL g_handoff_url;
491 @interface AppController (BrowserTest)
492 - (BOOL)new_shouldUseHandoff;
493 - (void)new_passURLToHandoffManager:(const GURL&)handoffURL;
494 @end
496 @implementation AppController (BrowserTest)
497 - (BOOL)new_shouldUseHandoff {
498   return YES;
501 - (void)new_passURLToHandoffManager:(const GURL&)handoffURL {
502   g_handoff_url = handoffURL;
504 @end
506 namespace {
508 class AppControllerHandoffBrowserTest : public InProcessBrowserTest {
509  protected:
510   AppControllerHandoffBrowserTest() {}
512   // Exchanges the implementations of the two selectors on the class
513   // AppController.
514   void ExchangeSelectors(SEL originalMethod, SEL newMethod) {
515     Class appControllerClass = NSClassFromString(@"AppController");
517     ASSERT_TRUE(appControllerClass != nil);
519     Method original =
520         class_getInstanceMethod(appControllerClass, originalMethod);
521     Method destination = class_getInstanceMethod(appControllerClass, newMethod);
523     ASSERT_TRUE(original != NULL);
524     ASSERT_TRUE(destination != NULL);
526     method_exchangeImplementations(original, destination);
527   }
529   // Swizzle Handoff related implementations.
530   void SetUpInProcessBrowserTestFixture() override {
531     // Handoff is only available on OSX 10.10+. This swizzle makes the logic
532     // run on all OSX versions.
533     SEL originalMethod = @selector(shouldUseHandoff);
534     SEL newMethod = @selector(new_shouldUseHandoff);
535     ExchangeSelectors(originalMethod, newMethod);
537     // This swizzle intercepts the URL that would be sent to the Handoff
538     // Manager, and instead puts it into a variable accessible to this test.
539     originalMethod = @selector(passURLToHandoffManager:);
540     newMethod = @selector(new_passURLToHandoffManager:);
541     ExchangeSelectors(originalMethod, newMethod);
542   }
544   // Closes the tab, and waits for the close to finish.
545   void CloseTab(Browser* browser, int index) {
546     content::WebContentsDestroyedWatcher destroyed_watcher(
547         browser->tab_strip_model()->GetWebContentsAt(index));
548     browser->tab_strip_model()->CloseWebContentsAt(
549         index, TabStripModel::CLOSE_CREATE_HISTORICAL_TAB);
550     destroyed_watcher.Wait();
551   }
554 // Tests that as a user switches between tabs, navigates within a tab, and
555 // switches between browser windows, the correct URL is being passed to the
556 // Handoff.
557 IN_PROC_BROWSER_TEST_F(AppControllerHandoffBrowserTest, TestHandoffURLs) {
558   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
559   EXPECT_EQ(g_handoff_url, GURL(url::kAboutBlankURL));
561   // Test that navigating to a URL updates the handoff URL.
562   GURL test_url1 = embedded_test_server()->GetURL("/title1.html");
563   ui_test_utils::NavigateToURL(browser(), test_url1);
564   EXPECT_EQ(g_handoff_url, test_url1);
566   // Test that opening a new tab updates the handoff URL.
567   GURL test_url2 = embedded_test_server()->GetURL("/title2.html");
568   chrome::NavigateParams params(browser(), test_url2, ui::PAGE_TRANSITION_LINK);
569   params.disposition = NEW_FOREGROUND_TAB;
570   ui_test_utils::NavigateToURL(&params);
571   EXPECT_EQ(g_handoff_url, test_url2);
573   // Test that switching tabs updates the handoff URL.
574   browser()->tab_strip_model()->ActivateTabAt(0, true);
575   EXPECT_EQ(g_handoff_url, test_url1);
577   // Test that closing the current tab updates the handoff URL.
578   CloseTab(browser(), 0);
579   EXPECT_EQ(g_handoff_url, test_url2);
581   // Test that opening a new browser window updates the handoff URL.
582   GURL test_url3 = embedded_test_server()->GetURL("/title3.html");
583   ui_test_utils::NavigateToURLWithDisposition(
584       browser(), GURL(test_url3), NEW_WINDOW,
585       ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER);
586   EXPECT_EQ(g_handoff_url, test_url3);
588   // Check that there are exactly 2 browsers.
589   BrowserList* active_browser_list =
590       BrowserList::GetInstance(chrome::GetActiveDesktop());
591   EXPECT_EQ(2u, active_browser_list->size());
593   // Close the one and only tab for the second browser window.
594   Browser* browser2 = active_browser_list->get(1);
595   CloseTab(browser2, 0);
596   base::RunLoop().RunUntilIdle();
597   EXPECT_EQ(g_handoff_url, test_url2);
599   // The URLs of incognito windows should not be passed to Handoff.
600   GURL test_url4 = embedded_test_server()->GetURL("/simple.html");
601   ui_test_utils::NavigateToURLWithDisposition(
602       browser(), GURL(test_url4), OFF_THE_RECORD,
603       ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER);
604   EXPECT_EQ(g_handoff_url, GURL());
606   // Open a new tab in the incognito window.
607   EXPECT_EQ(2u, active_browser_list->size());
608   Browser* browser3 = active_browser_list->get(1);
609   ui_test_utils::NavigateToURLWithDisposition(
610       browser3, test_url4, NEW_FOREGROUND_TAB,
611       ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
612   EXPECT_EQ(g_handoff_url, GURL());
614   // Navigate the current tab in the incognito window.
615   ui_test_utils::NavigateToURL(browser3, test_url1);
616   EXPECT_EQ(g_handoff_url, GURL());
618   // Activate the original browser window.
619   Browser* browser1 = active_browser_list->get(0);
620   browser1->window()->Show();
621   EXPECT_EQ(g_handoff_url, test_url2);
624 }  // namespace