1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/ui/browser_navigator_browsertest.h"
6
7#include "base/command_line.h"
8#include "chrome/browser/profiles/profile.h"
9#include "chrome/browser/tabs/tab_strip_model.h"
10#include "chrome/browser/ui/browser_list.h"
11#include "chrome/browser/ui/browser_navigator.h"
12#include "chrome/browser/ui/browser_window.h"
13#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
14#include "chrome/common/chrome_switches.h"
15#include "chrome/test/ui_test_utils.h"
16#include "content/browser/tab_contents/tab_contents.h"
17#include "content/browser/tab_contents/tab_contents_view.h"\
18
19GURL BrowserNavigatorTest::GetGoogleURL() const {
20  return GURL("http://www.google.com/");
21}
22
23browser::NavigateParams BrowserNavigatorTest::MakeNavigateParams() const {
24  return MakeNavigateParams(browser());
25}
26
27browser::NavigateParams BrowserNavigatorTest::MakeNavigateParams(
28    Browser* browser) const {
29  browser::NavigateParams params(browser, GetGoogleURL(),
30                                 PageTransition::LINK);
31  params.window_action = browser::NavigateParams::SHOW_WINDOW;
32  return params;
33}
34
35Browser* BrowserNavigatorTest::CreateEmptyBrowserForType(Browser::Type type,
36                                                         Profile* profile) {
37  Browser* browser = Browser::CreateForType(type, profile);
38  browser->AddBlankTab(true);
39  return browser;
40}
41
42TabContentsWrapper* BrowserNavigatorTest::CreateTabContents() {
43  return Browser::TabContentsFactory(
44      browser()->profile(),
45      NULL,
46      MSG_ROUTING_NONE,
47      browser()->GetSelectedTabContents(),
48      NULL);
49}
50
51void BrowserNavigatorTest::RunSuppressTest(WindowOpenDisposition disposition) {
52  GURL old_url = browser()->GetSelectedTabContents()->GetURL();
53  browser::NavigateParams p(MakeNavigateParams());
54  p.disposition = disposition;
55  browser::Navigate(&p);
56
57  // Nothing should have happened as a result of Navigate();
58  EXPECT_EQ(1, browser()->tab_count());
59  EXPECT_EQ(1u, BrowserList::size());
60  EXPECT_EQ(old_url, browser()->GetSelectedTabContents()->GetURL());
61}
62
63void BrowserNavigatorTest::Observe(NotificationType type,
64                                   const NotificationSource& source,
65                                   const NotificationDetails& details) {
66  switch (type.value) {
67    case NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB: {
68      ++this->created_tab_contents_count_;
69      break;
70    }
71    default:
72      break;
73  }
74}
75
76namespace {
77
78// This test verifies that when a navigation occurs within a tab, the tab count
79// of the Browser remains the same and the current tab bears the loaded URL.
80IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, Disposition_CurrentTab) {
81  browser::NavigateParams p(MakeNavigateParams());
82  browser::Navigate(&p);
83  ui_test_utils::WaitForNavigationInCurrentTab(browser());
84  EXPECT_EQ(GetGoogleURL(), browser()->GetSelectedTabContents()->GetURL());
85  // We should have one window with one tab.
86  EXPECT_EQ(1u, BrowserList::size());
87  EXPECT_EQ(1, browser()->tab_count());
88}
89
90// This test verifies that a singleton tab is refocused if one is already opened
91// in another or an existing window, or added if it is not.
92IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, Disposition_SingletonTabExisting) {
93  GURL url("http://www.google.com/");
94  GURL singleton_url1("http://maps.google.com/");
95
96  // Register for a notification if an additional tab_contents was instantiated.
97  // Opening a Singleton tab that is already opened should not be opening a new
98  // tab nor be creating a new TabContents object
99  NotificationRegistrar registrar;
100
101  // As the registrar object goes out of scope, this will get unregistered
102  registrar.Add(this, NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB,
103                NotificationService::AllSources());
104
105  browser()->AddSelectedTabWithURL(singleton_url1, PageTransition::LINK);
106  browser()->AddSelectedTabWithURL(url, PageTransition::LINK);
107
108  // We should have one browser with 3 tabs, the 3rd selected.
109  EXPECT_EQ(1u, BrowserList::size());
110  EXPECT_EQ(2, browser()->active_index());
111
112  unsigned int previous_tab_contents_count =
113      created_tab_contents_count_ = 0;
114
115  // Navigate to singleton_url1.
116  browser::NavigateParams p(MakeNavigateParams());
117  p.disposition = SINGLETON_TAB;
118  p.url = singleton_url1;
119  browser::Navigate(&p);
120
121  // The middle tab should now be selected.
122  EXPECT_EQ(browser(), p.browser);
123  EXPECT_EQ(1, browser()->active_index());
124
125  // No tab contents should have been created
126  EXPECT_EQ(previous_tab_contents_count,
127            created_tab_contents_count_);
128}
129
130IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest,
131                       Disposition_SingletonTabNoneExisting) {
132  GURL url("http://www.google.com/");
133  GURL singleton_url1("http://maps.google.com/");
134
135  // We should have one browser with 1 tab.
136  EXPECT_EQ(1u, BrowserList::size());
137  EXPECT_EQ(0, browser()->active_index());
138
139  // Navigate to singleton_url1.
140  browser::NavigateParams p(MakeNavigateParams());
141  p.disposition = SINGLETON_TAB;
142  p.url = singleton_url1;
143  browser::Navigate(&p);
144
145  // We should now have 2 tabs, the 2nd one selected.
146  EXPECT_EQ(browser(), p.browser);
147  EXPECT_EQ(2, browser()->tab_count());
148  EXPECT_EQ(1, browser()->active_index());
149}
150
151// This test verifies that when a navigation results in a foreground tab, the
152// tab count of the Browser increases and the selected tab shifts to the new
153// foreground tab.
154IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, Disposition_NewForegroundTab) {
155  TabContents* old_contents = browser()->GetSelectedTabContents();
156  browser::NavigateParams p(MakeNavigateParams());
157  p.disposition = NEW_FOREGROUND_TAB;
158  browser::Navigate(&p);
159  EXPECT_NE(old_contents, browser()->GetSelectedTabContents());
160  EXPECT_EQ(browser()->GetSelectedTabContentsWrapper(), p.target_contents);
161  EXPECT_EQ(2, browser()->tab_count());
162}
163
164// This test verifies that when a navigation results in a background tab, the
165// tab count of the Browser increases but the selected tab remains the same.
166IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, Disposition_NewBackgroundTab) {
167  TabContents* old_contents = browser()->GetSelectedTabContents();
168  browser::NavigateParams p(MakeNavigateParams());
169  p.disposition = NEW_BACKGROUND_TAB;
170  browser::Navigate(&p);
171  TabContents* new_contents = browser()->GetSelectedTabContents();
172  // The selected tab should have remained unchanged, since the new tab was
173  // opened in the background.
174  EXPECT_EQ(old_contents, new_contents);
175  EXPECT_EQ(2, browser()->tab_count());
176}
177
178// This test verifies that when a navigation requiring a new foreground tab
179// occurs in a Browser that cannot host multiple tabs, the new foreground tab
180// is created in an existing compatible Browser.
181IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest,
182                       Disposition_IncompatibleWindow_Existing) {
183  // Open a foreground tab in a window that cannot open popups when there is an
184  // existing compatible window somewhere else that they can be opened within.
185  Browser* popup = CreateEmptyBrowserForType(Browser::TYPE_POPUP,
186                                             browser()->profile());
187  browser::NavigateParams p(MakeNavigateParams(popup));
188  p.disposition = NEW_FOREGROUND_TAB;
189  browser::Navigate(&p);
190
191  // Navigate() should have opened the tab in a different browser since the
192  // one we supplied didn't support additional tabs.
193  EXPECT_NE(popup, p.browser);
194
195  // Since browser() is an existing compatible tabbed browser, it should have
196  // opened the tab there.
197  EXPECT_EQ(browser(), p.browser);
198
199  // We should be left with 2 windows, the popup with one tab and the browser()
200  // provided by the framework with two.
201  EXPECT_EQ(2u, BrowserList::size());
202  EXPECT_EQ(1, popup->tab_count());
203  EXPECT_EQ(2, browser()->tab_count());
204}
205
206// This test verifies that when a navigation requiring a new foreground tab
207// occurs in a Browser that cannot host multiple tabs and no compatible Browser
208// that can is open, a compatible Browser is created.
209IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest,
210                       Disposition_IncompatibleWindow_NoExisting) {
211  // We want to simulate not being able to find an existing window compatible
212  // with our non-tabbed browser window so Navigate() is forced to create a
213  // new compatible window. Because browser() supplied by the in-process
214  // browser testing framework is compatible with browser()->profile(), we
215  // need a different profile, and creating a popup window with an incognito
216  // profile is a quick and dirty way of achieving this.
217  Browser* popup = CreateEmptyBrowserForType(
218      Browser::TYPE_POPUP, browser()->profile()->GetOffTheRecordProfile());
219  browser::NavigateParams p(MakeNavigateParams(popup));
220  p.disposition = NEW_FOREGROUND_TAB;
221  browser::Navigate(&p);
222
223  // Navigate() should have opened the tab in a different browser since the
224  // one we supplied didn't support additional tabs.
225  EXPECT_NE(popup, p.browser);
226
227  // This time, browser() is _not_ compatible with popup since it is not an
228  // incognito window.
229  EXPECT_NE(browser(), p.browser);
230
231  // We should have three windows, each with one tab:
232  // 1. the browser() provided by the framework (unchanged in this test)
233  // 2. the incognito popup we created originally
234  // 3. the new incognito tabbed browser that was created by Navigate().
235  EXPECT_EQ(3u, BrowserList::size());
236  EXPECT_EQ(1, browser()->tab_count());
237  EXPECT_EQ(1, popup->tab_count());
238  EXPECT_EQ(1, p.browser->tab_count());
239  EXPECT_EQ(Browser::TYPE_NORMAL, p.browser->type());
240}
241
242// This test verifies that navigating with WindowOpenDisposition = NEW_POPUP
243// from a normal Browser results in a new Browser with TYPE_POPUP.
244IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, Disposition_NewPopup) {
245  browser::NavigateParams p(MakeNavigateParams());
246  p.disposition = NEW_POPUP;
247  browser::Navigate(&p);
248  // Wait for new popup to to load and gain focus.
249  ui_test_utils::WaitForNavigationInCurrentTab(p.browser);
250
251  // Navigate() should have opened a new, focused popup window.
252  EXPECT_NE(browser(), p.browser);
253#if 0
254  // TODO(stevenjb): Enable this test. See: crbug.com/79493
255  EXPECT_TRUE(p.browser->window()->IsActive());
256#endif
257  EXPECT_EQ(Browser::TYPE_POPUP, p.browser->type());
258
259  // We should have two windows, the browser() provided by the framework and the
260  // new popup window.
261  EXPECT_EQ(2u, BrowserList::size());
262  EXPECT_EQ(1, browser()->tab_count());
263  EXPECT_EQ(1, p.browser->tab_count());
264}
265
266// This test verifies that navigating with WindowOpenDisposition = NEW_POPUP
267// from a normal popup results in a new Browser with TYPE_POPUP.
268IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, Disposition_NewPopupFromPopup) {
269  // Open a popup.
270  browser::NavigateParams p1(MakeNavigateParams());
271  p1.disposition = NEW_POPUP;
272  browser::Navigate(&p1);
273  // Open another popup.
274  browser::NavigateParams p2(MakeNavigateParams(p1.browser));
275  p2.disposition = NEW_POPUP;
276  browser::Navigate(&p2);
277
278  // Navigate() should have opened a new normal popup window.
279  EXPECT_NE(p1.browser, p2.browser);
280  EXPECT_EQ(Browser::TYPE_POPUP, p2.browser->type());
281
282  // We should have three windows, the browser() provided by the framework,
283  // the first popup window, and the second popup window.
284  EXPECT_EQ(3u, BrowserList::size());
285  EXPECT_EQ(1, browser()->tab_count());
286  EXPECT_EQ(1, p1.browser->tab_count());
287  EXPECT_EQ(1, p2.browser->tab_count());
288}
289
290// This test verifies that navigating with WindowOpenDisposition = NEW_POPUP
291// from an app frame results in a new Browser with TYPE_APP_POPUP.
292IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest,
293                       Disposition_NewPopupFromAppWindow) {
294  Browser* app_browser = CreateEmptyBrowserForType(Browser::TYPE_APP,
295                                                   browser()->profile());
296  browser::NavigateParams p(MakeNavigateParams(app_browser));
297  p.disposition = NEW_POPUP;
298  browser::Navigate(&p);
299
300  // Navigate() should have opened a new popup app window.
301  EXPECT_NE(app_browser, p.browser);
302  EXPECT_NE(browser(), p.browser);
303  EXPECT_EQ(Browser::TYPE_APP_POPUP, p.browser->type());
304
305  // We should now have three windows, the app window, the app popup it created,
306  // and the original browser() provided by the framework.
307  EXPECT_EQ(3u, BrowserList::size());
308  EXPECT_EQ(1, browser()->tab_count());
309  EXPECT_EQ(1, app_browser->tab_count());
310  EXPECT_EQ(1, p.browser->tab_count());
311}
312
313// This test verifies that navigating with WindowOpenDisposition = NEW_POPUP
314// from an app popup results in a new Browser also of TYPE_APP_POPUP.
315IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest,
316                       Disposition_NewPopupFromAppPopup) {
317  Browser* app_browser = CreateEmptyBrowserForType(Browser::TYPE_APP,
318                                                   browser()->profile());
319  // Open an app popup.
320  browser::NavigateParams p1(MakeNavigateParams(app_browser));
321  p1.disposition = NEW_POPUP;
322  browser::Navigate(&p1);
323  // Now open another app popup.
324  browser::NavigateParams p2(MakeNavigateParams(p1.browser));
325  p2.disposition = NEW_POPUP;
326  browser::Navigate(&p2);
327
328  // Navigate() should have opened a new popup app window.
329  EXPECT_NE(browser(), p1.browser);
330  EXPECT_NE(p1.browser, p2.browser);
331  EXPECT_EQ(Browser::TYPE_APP_POPUP, p2.browser->type());
332
333  // We should now have four windows, the app window, the first app popup,
334  // the second app popup, and the original browser() provided by the framework.
335  EXPECT_EQ(4u, BrowserList::size());
336  EXPECT_EQ(1, browser()->tab_count());
337  EXPECT_EQ(1, app_browser->tab_count());
338  EXPECT_EQ(1, p1.browser->tab_count());
339  EXPECT_EQ(1, p2.browser->tab_count());
340}
341
342// This test verifies that navigating with WindowOpenDisposition = NEW_POPUP
343// from an extension app tab results in a new Browser with TYPE_APP_POPUP.
344IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest,
345                       Disposition_NewPopupFromExtensionApp) {
346  // TODO(beng): TBD.
347}
348
349// This test verifies that navigating with window_action = SHOW_WINDOW_INACTIVE
350// does not focus a new new popup window.
351IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, Disposition_NewPopupUnfocused) {
352  browser::NavigateParams p(MakeNavigateParams());
353  p.disposition = NEW_POPUP;
354  p.window_action = browser::NavigateParams::SHOW_WINDOW_INACTIVE;
355  browser::Navigate(&p);
356  // Wait for new popup to load (and gain focus if the test fails).
357  ui_test_utils::WaitForNavigationInCurrentTab(p.browser);
358
359  // Navigate() should have opened a new, unfocused, popup window.
360  EXPECT_NE(browser(), p.browser);
361  EXPECT_EQ(Browser::TYPE_POPUP, p.browser->type());
362#if 0
363// TODO(stevenjb): Enable this test. See: crbug.com/79493
364  EXPECT_FALSE(p.browser->window()->IsActive());
365#endif
366}
367
368// This test verifies that navigating with WindowOpenDisposition = NEW_WINDOW
369// always opens a new window.
370IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, Disposition_NewWindow) {
371  browser::NavigateParams p(MakeNavigateParams());
372  p.disposition = NEW_WINDOW;
373  browser::Navigate(&p);
374
375  // Navigate() should have opened a new toplevel window.
376  EXPECT_NE(browser(), p.browser);
377  EXPECT_EQ(Browser::TYPE_NORMAL, p.browser->type());
378
379  // We should now have two windows, the browser() provided by the framework and
380  // the new normal window.
381  EXPECT_EQ(2u, BrowserList::size());
382  EXPECT_EQ(1, browser()->tab_count());
383  EXPECT_EQ(1, p.browser->tab_count());
384}
385
386// This test verifies that navigating with WindowOpenDisposition = INCOGNITO
387// opens a new incognito window if no existing incognito window is present.
388IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, Disposition_Incognito) {
389  browser::NavigateParams p(MakeNavigateParams());
390  p.disposition = OFF_THE_RECORD;
391  browser::Navigate(&p);
392
393  // Navigate() should have opened a new toplevel incognito window.
394  EXPECT_NE(browser(), p.browser);
395  EXPECT_EQ(browser()->profile()->GetOffTheRecordProfile(),
396            p.browser->profile());
397
398  // |source_contents| should be set to NULL because the profile for the new
399  // page is different from the originating page.
400  EXPECT_EQ(NULL, p.source_contents);
401
402  // We should now have two windows, the browser() provided by the framework and
403  // the new incognito window.
404  EXPECT_EQ(2u, BrowserList::size());
405  EXPECT_EQ(1, browser()->tab_count());
406  EXPECT_EQ(1, p.browser->tab_count());
407}
408
409// This test verifies that navigating with WindowOpenDisposition = INCOGNITO
410// reuses an existing incognito window when possible.
411IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, Disposition_IncognitoRefocus) {
412  Browser* incognito_browser =
413      CreateEmptyBrowserForType(Browser::TYPE_NORMAL,
414                                browser()->profile()->GetOffTheRecordProfile());
415  browser::NavigateParams p(MakeNavigateParams());
416  p.disposition = OFF_THE_RECORD;
417  browser::Navigate(&p);
418
419  // Navigate() should have opened a new tab in the existing incognito window.
420  EXPECT_NE(browser(), p.browser);
421  EXPECT_EQ(p.browser, incognito_browser);
422
423  // We should now have two windows, the browser() provided by the framework and
424  // the incognito window we opened earlier.
425  EXPECT_EQ(2u, BrowserList::size());
426  EXPECT_EQ(1, browser()->tab_count());
427  EXPECT_EQ(2, incognito_browser->tab_count());
428}
429
430// This test verifies that no navigation action occurs when
431// WindowOpenDisposition = SUPPRESS_OPEN.
432IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, Disposition_SuppressOpen) {
433  RunSuppressTest(SUPPRESS_OPEN);
434}
435
436// This test verifies that no navigation action occurs when
437// WindowOpenDisposition = SAVE_TO_DISK.
438IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, Disposition_SaveToDisk) {
439  RunSuppressTest(SAVE_TO_DISK);
440}
441
442// This test verifies that no navigation action occurs when
443// WindowOpenDisposition = IGNORE_ACTION.
444IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, Disposition_IgnoreAction) {
445  RunSuppressTest(IGNORE_ACTION);
446}
447
448// This tests adding a foreground tab with a predefined TabContents.
449IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, TargetContents_ForegroundTab) {
450  browser::NavigateParams p(MakeNavigateParams());
451  p.disposition = NEW_FOREGROUND_TAB;
452  p.target_contents = CreateTabContents();
453  browser::Navigate(&p);
454
455  // Navigate() should have opened the contents in a new foreground in the
456  // current Browser.
457  EXPECT_EQ(browser(), p.browser);
458  EXPECT_EQ(browser()->GetSelectedTabContentsWrapper(), p.target_contents);
459
460  // We should have one window, with two tabs.
461  EXPECT_EQ(1u, BrowserList::size());
462  EXPECT_EQ(2, browser()->tab_count());
463}
464
465#if defined(OS_WIN)
466// This tests adding a popup with a predefined TabContents.
467IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, DISABLED_TargetContents_Popup) {
468  browser::NavigateParams p(MakeNavigateParams());
469  p.disposition = NEW_POPUP;
470  p.target_contents = CreateTabContents();
471  p.window_bounds = gfx::Rect(10, 10, 500, 500);
472  browser::Navigate(&p);
473
474  // Navigate() should have opened a new popup window.
475  EXPECT_NE(browser(), p.browser);
476  EXPECT_EQ(Browser::TYPE_POPUP, p.browser->type());
477
478  // The web platform is weird. The window bounds specified in
479  // |p.window_bounds| are used as follows:
480  // - the origin is used to position the window
481  // - the size is used to size the TabContents of the window.
482  // As such the position of the resulting window will always match
483  // p.window_bounds.origin(), but its size will not. We need to match
484  // the size against the selected tab's view's container size.
485  // Only Windows positions the window according to |p.window_bounds.origin()| -
486  // on Mac the window is offset from the opener and on Linux it always opens
487  // at 0,0.
488  EXPECT_EQ(p.window_bounds.origin(),
489            p.browser->window()->GetRestoredBounds().origin());
490  // All platforms should respect size however provided width > 400 (Mac has a
491  // minimum window width of 400).
492  EXPECT_EQ(p.window_bounds.size(),
493            p.target_contents->tab_contents()->view()->GetContainerSize());
494
495  // We should have two windows, the new popup and the browser() provided by the
496  // framework.
497  EXPECT_EQ(2u, BrowserList::size());
498  EXPECT_EQ(1, browser()->tab_count());
499  EXPECT_EQ(1, p.browser->tab_count());
500}
501#endif
502
503// This tests adding a tab at a specific index.
504IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, Tabstrip_InsertAtIndex) {
505  // This is not meant to be a comprehensive test of whether or not the tab
506  // implementation of the browser observes the insertion index. That is
507  // covered by the unit tests for TabStripModel. This merely verifies that
508  // insertion index preference is reflected in common cases.
509  browser::NavigateParams p(MakeNavigateParams());
510  p.disposition = NEW_FOREGROUND_TAB;
511  p.tabstrip_index = 0;
512  p.tabstrip_add_types = TabStripModel::ADD_FORCE_INDEX;
513  browser::Navigate(&p);
514
515  // Navigate() should have inserted a new tab at slot 0 in the tabstrip.
516  EXPECT_EQ(browser(), p.browser);
517  EXPECT_EQ(0, browser()->tabstrip_model()->GetIndexOfTabContents(
518      static_cast<const TabContentsWrapper*>(p.target_contents)));
519
520  // We should have one window - the browser() provided by the framework.
521  EXPECT_EQ(1u, BrowserList::size());
522  EXPECT_EQ(2, browser()->tab_count());
523}
524
525// This test verifies that constructing params with a NULL browser has
526// the same result as navigating to a new foreground tab in the (only)
527// active browser. Tests are the same as for Disposition_NewForegroundTab.
528IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, NullBrowser_NewForegroundTab) {
529  TabContents* old_contents = browser()->GetSelectedTabContents();
530  // Navigate with a NULL browser.
531  browser::NavigateParams p(MakeNavigateParams(NULL));
532  p.disposition = NEW_FOREGROUND_TAB;
533  p.profile = browser()->profile();
534  browser::Navigate(&p);
535
536  // Navigate() should have found browser() and create a new tab.
537  EXPECT_EQ(browser(), p.browser);
538  EXPECT_NE(old_contents, browser()->GetSelectedTabContents());
539  EXPECT_EQ(browser()->GetSelectedTabContentsWrapper(), p.target_contents);
540  EXPECT_EQ(2, browser()->tab_count());
541}
542
543// This test verifies that constructing params with a NULL browser and
544// a specific profile matches the specified profile.
545IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, NullBrowser_MatchProfile) {
546  // Create a new browser with using the incognito profile.
547  Browser* incognito =
548      Browser::Create(browser()->profile()->GetOffTheRecordProfile());
549
550  // Navigate with a NULL browser and the incognito profile.
551  browser::NavigateParams p(MakeNavigateParams(NULL));
552  p.disposition = NEW_FOREGROUND_TAB;
553  p.profile = incognito->profile();
554  browser::Navigate(&p);
555
556  // Navigate() should have found incognito, not browser().
557  EXPECT_EQ(incognito, p.browser);
558  EXPECT_EQ(incognito->GetSelectedTabContentsWrapper(), p.target_contents);
559  EXPECT_EQ(1, incognito->tab_count());
560}
561
562// This test verifies that constructing params with a NULL browser and
563// disposition = NEW_WINDOW always opens exactly one new window.
564IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, NullBrowser_NewWindow) {
565  browser::NavigateParams p(MakeNavigateParams(NULL));
566  p.disposition = NEW_WINDOW;
567  p.profile = browser()->profile();
568  browser::Navigate(&p);
569
570  // Navigate() should have created a new browser.
571  EXPECT_NE(browser(), p.browser);
572  EXPECT_EQ(Browser::TYPE_NORMAL, p.browser->type());
573
574  // We should now have two windows, the browser() provided by the framework and
575  // the new normal window.
576  EXPECT_EQ(2u, BrowserList::size());
577  EXPECT_EQ(1, browser()->tab_count());
578  EXPECT_EQ(1, p.browser->tab_count());
579}
580
581// This test verifies that constructing params with disposition = SINGLETON_TAB
582// and IGNORE_AND_NAVIGATE opens a new tab navigated to the specified URL if
583// no previous tab with that URL (minus the path) exists.
584IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest,
585                       Disposition_SingletonTabNew_IgnorePath) {
586  GURL url("http://www.google.com/");
587  browser()->AddSelectedTabWithURL(url, PageTransition::LINK);
588
589  // We should have one browser with 2 tabs, the 2nd selected.
590  EXPECT_EQ(1u, BrowserList::size());
591  EXPECT_EQ(2, browser()->tab_count());
592  EXPECT_EQ(1, browser()->active_index());
593
594  // Navigate to a new singleton tab with a sub-page.
595  browser::NavigateParams p(MakeNavigateParams());
596  p.disposition = SINGLETON_TAB;
597  p.url = GURL("chrome://settings/advanced");
598  p.window_action = browser::NavigateParams::SHOW_WINDOW;
599  p.path_behavior = browser::NavigateParams::IGNORE_AND_NAVIGATE;
600  browser::Navigate(&p);
601
602  // The last tab should now be selected and navigated to the sub-page of the
603  // URL.
604  EXPECT_EQ(browser(), p.browser);
605  EXPECT_EQ(3, browser()->tab_count());
606  EXPECT_EQ(2, browser()->active_index());
607  EXPECT_EQ(GURL("chrome://settings/advanced"),
608            browser()->GetSelectedTabContents()->GetURL());
609}
610
611// This test verifies that constructing params with disposition = SINGLETON_TAB
612// and IGNORE_AND_NAVIGATE opens an existing tab with the matching URL (minus
613// the path) which is navigated to the specified URL.
614IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest,
615                       Disposition_SingletonTabExisting_IgnorePath) {
616  GURL singleton_url1("chrome://settings");
617  GURL url("http://www.google.com/");
618  browser()->AddSelectedTabWithURL(singleton_url1, PageTransition::LINK);
619  browser()->AddSelectedTabWithURL(url, PageTransition::LINK);
620
621  // We should have one browser with 3 tabs, the 3rd selected.
622  EXPECT_EQ(1u, BrowserList::size());
623  EXPECT_EQ(3, browser()->tab_count());
624  EXPECT_EQ(2, browser()->active_index());
625
626  // Navigate to singleton_url1.
627  browser::NavigateParams p(MakeNavigateParams());
628  p.disposition = SINGLETON_TAB;
629  p.url = GURL("chrome://settings/advanced");
630  p.window_action = browser::NavigateParams::SHOW_WINDOW;
631  p.path_behavior = browser::NavigateParams::IGNORE_AND_NAVIGATE;
632  browser::Navigate(&p);
633
634  // The middle tab should now be selected and navigated to the sub-page of the
635  // URL.
636  EXPECT_EQ(browser(), p.browser);
637  EXPECT_EQ(3, browser()->tab_count());
638  EXPECT_EQ(1, browser()->active_index());
639  EXPECT_EQ(GURL("chrome://settings/advanced"),
640            browser()->GetSelectedTabContents()->GetURL());
641}
642
643// This test verifies that constructing params with disposition = SINGLETON_TAB
644// and IGNORE_AND_NAVIGATE opens an existing tab with the matching URL (minus
645// the path) which is navigated to the specified URL.
646IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest,
647                       Disposition_SingletonTabExistingSubPath_IgnorePath) {
648  GURL singleton_url1("chrome://settings/advanced");
649  GURL url("http://www.google.com/");
650  browser()->AddSelectedTabWithURL(singleton_url1, PageTransition::LINK);
651  browser()->AddSelectedTabWithURL(url, PageTransition::LINK);
652
653  // We should have one browser with 3 tabs, the 3rd selected.
654  EXPECT_EQ(1u, BrowserList::size());
655  EXPECT_EQ(3, browser()->tab_count());
656  EXPECT_EQ(2, browser()->active_index());
657
658  // Navigate to singleton_url1.
659  browser::NavigateParams p(MakeNavigateParams());
660  p.disposition = SINGLETON_TAB;
661  p.url = GURL("chrome://settings/personal");
662  p.window_action = browser::NavigateParams::SHOW_WINDOW;
663  p.path_behavior = browser::NavigateParams::IGNORE_AND_NAVIGATE;
664  browser::Navigate(&p);
665
666  // The middle tab should now be selected and navigated to the sub-page of the
667  // URL.
668  EXPECT_EQ(browser(), p.browser);
669  EXPECT_EQ(3, browser()->tab_count());
670  EXPECT_EQ(1, browser()->active_index());
671  EXPECT_EQ(GURL("chrome://settings/personal"),
672            browser()->GetSelectedTabContents()->GetURL());
673}
674
675// This test verifies that constructing params with disposition = SINGLETON_TAB
676// and IGNORE_AND_STAY_PUT opens an existing tab with the matching URL (minus
677// the path).
678IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest,
679                       Disposition_SingletonTabExistingSubPath_IgnorePath2) {
680  GURL singleton_url1("chrome://settings/advanced");
681  GURL url("http://www.google.com/");
682  browser()->AddSelectedTabWithURL(singleton_url1, PageTransition::LINK);
683  browser()->AddSelectedTabWithURL(url, PageTransition::LINK);
684
685  // We should have one browser with 3 tabs, the 3rd selected.
686  EXPECT_EQ(1u, BrowserList::size());
687  EXPECT_EQ(3, browser()->tab_count());
688  EXPECT_EQ(2, browser()->active_index());
689
690  // Navigate to singleton_url1.
691  browser::NavigateParams p(MakeNavigateParams());
692  p.disposition = SINGLETON_TAB;
693  p.url = GURL("chrome://settings/personal");
694  p.window_action = browser::NavigateParams::SHOW_WINDOW;
695  p.path_behavior = browser::NavigateParams::IGNORE_AND_STAY_PUT;
696  browser::Navigate(&p);
697
698  // The middle tab should now be selected.
699  EXPECT_EQ(browser(), p.browser);
700  EXPECT_EQ(3, browser()->tab_count());
701  EXPECT_EQ(1, browser()->active_index());
702  EXPECT_EQ(singleton_url1,
703            browser()->GetSelectedTabContents()->GetURL());
704}
705
706// This test verifies that constructing params with disposition = SINGLETON_TAB
707// and IGNORE_AND_NAVIGATE will update the current tab's URL if the currently
708// selected tab is a match but has a different path.
709IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest,
710                       Disposition_SingletonTabFocused_IgnorePath) {
711  GURL singleton_url_current("chrome://settings/advanced");
712  GURL url("http://www.google.com/");
713  browser()->AddSelectedTabWithURL(singleton_url_current, PageTransition::LINK);
714
715  // We should have one browser with 2 tabs, the 2nd selected.
716  EXPECT_EQ(1u, BrowserList::size());
717  EXPECT_EQ(2, browser()->tab_count());
718  EXPECT_EQ(1, browser()->active_index());
719
720  // Navigate to a different settings path.
721  GURL singleton_url_target("chrome://settings/personal");
722  browser::NavigateParams p(MakeNavigateParams());
723  p.disposition = SINGLETON_TAB;
724  p.url = singleton_url_target;
725  p.window_action = browser::NavigateParams::SHOW_WINDOW;
726  p.path_behavior = browser::NavigateParams::IGNORE_AND_NAVIGATE;
727  browser::Navigate(&p);
728
729  // The second tab should still be selected, but navigated to the new path.
730  EXPECT_EQ(browser(), p.browser);
731  EXPECT_EQ(2, browser()->tab_count());
732  EXPECT_EQ(1, browser()->active_index());
733  EXPECT_EQ(singleton_url_target,
734            browser()->GetSelectedTabContents()->GetURL());
735}
736
737// This test verifies that constructing params with disposition = SINGLETON_TAB
738// and IGNORE_AND_NAVIGATE will open an existing matching tab with a different
739// query.
740IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest,
741                       Disposition_SingletonTabExisting_IgnoreQuery) {
742  int initial_tab_count = browser()->tab_count();
743  GURL singleton_url_current("chrome://settings/internet");
744  browser()->AddSelectedTabWithURL(singleton_url_current, PageTransition::LINK);
745
746  EXPECT_EQ(initial_tab_count + 1, browser()->tab_count());
747  EXPECT_EQ(initial_tab_count, browser()->active_index());
748
749  // Navigate to a different settings path.
750  GURL singleton_url_target(
751      "chrome://settings/internet?"
752      "servicePath=/profile/ethernet_00aa00aa00aa&networkType=1");
753  browser::NavigateParams p(MakeNavigateParams());
754  p.disposition = SINGLETON_TAB;
755  p.url = singleton_url_target;
756  p.window_action = browser::NavigateParams::SHOW_WINDOW;
757  p.path_behavior = browser::NavigateParams::IGNORE_AND_NAVIGATE;
758  browser::Navigate(&p);
759
760  // Last tab should still be selected.
761  EXPECT_EQ(browser(), p.browser);
762  EXPECT_EQ(initial_tab_count + 1, browser()->tab_count());
763  EXPECT_EQ(initial_tab_count, browser()->active_index());
764}
765
766// This test verifies that the settings page isn't opened in the incognito
767// window.
768IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest,
769                       Disposition_Settings_UseNonIncognitoWindow) {
770  Browser* incognito_browser = CreateIncognitoBrowser();
771
772  EXPECT_EQ(2u, BrowserList::size());
773  EXPECT_EQ(1, browser()->tab_count());
774  EXPECT_EQ(1, incognito_browser->tab_count());
775
776  // Navigate to the settings page.
777  browser::NavigateParams p(MakeNavigateParams(incognito_browser));
778  p.disposition = SINGLETON_TAB;
779  p.url = GURL("chrome://settings");
780  p.window_action = browser::NavigateParams::SHOW_WINDOW;
781  browser::Navigate(&p);
782
783  // The settings page should be opened in browser() window.
784  EXPECT_NE(incognito_browser, p.browser);
785  EXPECT_EQ(browser(), p.browser);
786  EXPECT_EQ(2, browser()->tab_count());
787  EXPECT_EQ(GURL("chrome://settings"),
788            browser()->GetSelectedTabContents()->GetURL());
789}
790
791// This test verifies that the bookmarks page isn't opened in the incognito
792// window.
793IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest,
794                       Disposition_Bookmarks_UseNonIncognitoWindow) {
795  Browser* incognito_browser = CreateIncognitoBrowser();
796
797  EXPECT_EQ(2u, BrowserList::size());
798  EXPECT_EQ(1, browser()->tab_count());
799  EXPECT_EQ(1, incognito_browser->tab_count());
800
801  // Navigate to the settings page.
802  browser::NavigateParams p(MakeNavigateParams(incognito_browser));
803  p.disposition = SINGLETON_TAB;
804  p.url = GURL("chrome://bookmarks");
805  p.window_action = browser::NavigateParams::SHOW_WINDOW;
806  browser::Navigate(&p);
807
808  // The bookmarks page should be opened in browser() window.
809  EXPECT_NE(incognito_browser, p.browser);
810  EXPECT_EQ(browser(), p.browser);
811  EXPECT_EQ(2, browser()->tab_count());
812  EXPECT_EQ(GURL("chrome://bookmarks"),
813            browser()->GetSelectedTabContents()->GetURL());
814}
815
816}  // namespace
817