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.
4
5#include <vector>
6
7#include "base/command_line.h"
8#include "base/files/file_path.h"
9#include "base/process/launch.h"
10#include "base/strings/utf_string_conversions.h"
11#include "base/time/time.h"
12#include "chrome/browser/browser_process.h"
13#include "chrome/browser/chrome_notification_types.h"
14#include "chrome/browser/defaults.h"
15#include "chrome/browser/first_run/first_run.h"
16#include "chrome/browser/profiles/profile.h"
17#include "chrome/browser/profiles/profile_manager.h"
18#include "chrome/browser/sessions/session_restore.h"
19#include "chrome/browser/sessions/session_service.h"
20#include "chrome/browser/sessions/session_service_factory.h"
21#include "chrome/browser/sessions/session_service_test_helper.h"
22#include "chrome/browser/sessions/session_types.h"
23#include "chrome/browser/sessions/tab_restore_service.h"
24#include "chrome/browser/sessions/tab_restore_service_factory.h"
25#include "chrome/browser/ui/browser.h"
26#include "chrome/browser/ui/browser_commands.h"
27#include "chrome/browser/ui/browser_list.h"
28#include "chrome/browser/ui/browser_tabstrip.h"
29#include "chrome/browser/ui/browser_window.h"
30#include "chrome/browser/ui/host_desktop.h"
31#include "chrome/browser/ui/tabs/tab_strip_model.h"
32#include "chrome/common/chrome_switches.h"
33#include "chrome/common/url_constants.h"
34#include "chrome/test/base/in_process_browser_test.h"
35#include "chrome/test/base/test_switches.h"
36#include "chrome/test/base/ui_test_utils.h"
37#include "components/sessions/serialized_navigation_entry_test_helper.h"
38#include "content/public/browser/navigation_controller.h"
39#include "content/public/browser/navigation_entry.h"
40#include "content/public/browser/notification_service.h"
41#include "content/public/browser/notification_types.h"
42#include "content/public/browser/render_process_host.h"
43#include "content/public/browser/render_view_host.h"
44#include "content/public/browser/web_contents.h"
45#include "content/public/common/bindings_policy.h"
46#include "content/public/test/browser_test_utils.h"
47#include "content/public/test/test_navigation_observer.h"
48#include "sync/protocol/session_specifics.pb.h"
49#include "ui/base/page_transition_types.h"
50
51using sessions::SerializedNavigationEntry;
52using sessions::SerializedNavigationEntryTestHelper;
53
54#if defined(OS_MACOSX)
55#include "base/mac/scoped_nsautorelease_pool.h"
56#endif
57
58#if defined(USE_AURA)
59#include "ui/aura/window.h"
60#endif
61
62class SessionRestoreTest : public InProcessBrowserTest {
63 public:
64  SessionRestoreTest() : active_browser_list_(NULL) {}
65
66 protected:
67#if defined(OS_CHROMEOS)
68  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
69    // TODO(nkostylev): Investigate if we can remove this switch.
70    command_line->AppendSwitch(switches::kCreateBrowserOnStartupForTests);
71    InProcessBrowserTest::SetUpCommandLine(command_line);
72  }
73#endif
74
75  virtual void SetUpOnMainThread() OVERRIDE {
76    active_browser_list_ = BrowserList::GetInstance(chrome::GetActiveDesktop());
77
78    SessionStartupPref pref(SessionStartupPref::LAST);
79    SessionStartupPref::SetStartupPref(browser()->profile(), pref);
80#if defined(OS_CHROMEOS)
81    const testing::TestInfo* const test_info =
82        testing::UnitTest::GetInstance()->current_test_info();
83    if (strcmp(test_info->name(), "NoSessionRestoreNewWindowChromeOS") != 0) {
84      // Undo the effect of kBrowserAliveWithNoWindows in defaults.cc so that we
85      // can get these test to work without quitting.
86      SessionServiceTestHelper helper(
87          SessionServiceFactory::GetForProfile(browser()->profile()));
88      helper.SetForceBrowserNotAliveWithNoWindows(true);
89      helper.ReleaseService();
90    }
91#endif
92
93    InProcessBrowserTest::SetUpOnMainThread();
94  }
95
96  virtual bool SetUpUserDataDirectory() OVERRIDE {
97    url1_ = ui_test_utils::GetTestUrl(
98        base::FilePath().AppendASCII("session_history"),
99        base::FilePath().AppendASCII("bot1.html"));
100    url2_ = ui_test_utils::GetTestUrl(
101        base::FilePath().AppendASCII("session_history"),
102        base::FilePath().AppendASCII("bot2.html"));
103    url3_ = ui_test_utils::GetTestUrl(
104        base::FilePath().AppendASCII("session_history"),
105        base::FilePath().AppendASCII("bot3.html"));
106
107    return InProcessBrowserTest::SetUpUserDataDirectory();
108  }
109
110  void CloseBrowserSynchronously(Browser* browser) {
111    content::WindowedNotificationObserver observer(
112        chrome::NOTIFICATION_BROWSER_CLOSED,
113        content::NotificationService::AllSources());
114    browser->window()->Close();
115#if defined(OS_MACOSX)
116    // BrowserWindowController depends on the auto release pool being recycled
117    // in the message loop to delete itself, which frees the Browser object
118    // which fires this event.
119    AutoreleasePool()->Recycle();
120#endif
121    observer.Wait();
122  }
123
124  Browser* QuitBrowserAndRestore(Browser* browser, int expected_tab_count) {
125    return QuitBrowserAndRestoreWithURL(browser, expected_tab_count, GURL());
126  }
127
128  Browser* QuitBrowserAndRestoreWithURL(Browser* browser,
129                                        int expected_tab_count,
130                                        const GURL& url) {
131    Profile* profile = browser->profile();
132
133    // Close the browser.
134    g_browser_process->AddRefModule();
135    CloseBrowserSynchronously(browser);
136
137    // Create a new window, which should trigger session restore.
138    ui_test_utils::BrowserAddedObserver window_observer;
139    content::WindowedNotificationObserver restore_observer(
140        chrome::NOTIFICATION_SESSION_RESTORE_DONE,
141        content::NotificationService::AllSources());
142    if (url.is_empty()) {
143      chrome::NewEmptyWindow(profile, chrome::HOST_DESKTOP_TYPE_NATIVE);
144    } else {
145      chrome::NavigateParams params(profile,
146                                    url,
147                                    ui::PAGE_TRANSITION_LINK);
148      chrome::Navigate(&params);
149    }
150    Browser* new_browser = window_observer.WaitForSingleNewBrowser();
151    restore_observer.Wait();
152    g_browser_process->ReleaseModule();
153
154    return new_browser;
155  }
156
157  void GoBack(Browser* browser) {
158    content::TestNavigationObserver observer(
159        browser->tab_strip_model()->GetActiveWebContents());
160    chrome::GoBack(browser, CURRENT_TAB);
161    observer.Wait();
162  }
163
164  void GoForward(Browser* browser) {
165    content::TestNavigationObserver observer(
166        browser->tab_strip_model()->GetActiveWebContents());
167    chrome::GoForward(browser, CURRENT_TAB);
168    observer.Wait();
169  }
170
171  void AssertOneWindowWithOneTab(Browser* browser) {
172    ASSERT_EQ(1u, active_browser_list_->size());
173    ASSERT_EQ(1, browser->tab_strip_model()->count());
174  }
175
176  int RenderProcessHostCount() {
177    content::RenderProcessHost::iterator hosts =
178        content::RenderProcessHost::AllHostsIterator();
179    int count = 0;
180    while (!hosts.IsAtEnd()) {
181      if (hosts.GetCurrentValue()->HasConnection())
182        count++;
183      hosts.Advance();
184    }
185    return count;
186  }
187
188  GURL url1_;
189  GURL url2_;
190  GURL url3_;
191
192  const BrowserList* active_browser_list_;
193};
194
195#if defined(USE_AURA)
196// Verifies that restored tabs have a root window. This is important
197// otherwise the wrong information is communicated to the renderer.
198// (http://crbug.com/342672).
199IN_PROC_BROWSER_TEST_F(SessionRestoreTest, RestoredTabsShouldHaveRootWindow) {
200  // Create tabs.
201  ui_test_utils::NavigateToURLWithDisposition(
202      browser(),
203      GURL(url::kAboutBlankURL),
204      NEW_FOREGROUND_TAB,
205      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
206  ui_test_utils::NavigateToURLWithDisposition(
207      browser(),
208      GURL(url::kAboutBlankURL),
209      NEW_BACKGROUND_TAB,
210      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
211
212  // Restart and session restore the tabs.
213  Browser* restored = QuitBrowserAndRestore(browser(), 3);
214  TabStripModel* tab_strip_model = restored->tab_strip_model();
215  const int tabs = tab_strip_model->count();
216  ASSERT_EQ(3, tabs);
217
218  // Check the restored tabs have a root window.
219  for (int i = 0; i < tabs; ++i) {
220    content::WebContents* contents = tab_strip_model->GetWebContentsAt(i);
221    gfx::NativeView window = contents->GetNativeView();
222    bool tab_has_root_window = !!window->GetRootWindow();
223    EXPECT_TRUE(tab_has_root_window);
224  }
225}
226#endif  // USE_AURA
227
228// Verify that restored tabs have correct disposition. Only one tab should
229// have "visible" visibility state, the rest should not.
230// (http://crbug.com/155365 http://crbug.com/118269)
231IN_PROC_BROWSER_TEST_F(SessionRestoreTest,
232    RestoredTabsHaveCorrectVisibilityState) {
233  // Create tabs.
234  GURL test_page(ui_test_utils::GetTestUrl(base::FilePath(),
235      base::FilePath(FILE_PATH_LITERAL("tab-restore-visibilty.html"))));
236  ui_test_utils::NavigateToURLWithDisposition(
237      browser(), test_page, NEW_FOREGROUND_TAB,
238      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
239  ui_test_utils::NavigateToURLWithDisposition(
240      browser(), test_page, NEW_BACKGROUND_TAB,
241      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
242
243  // Restart and session restore the tabs.
244  content::DOMMessageQueue message_queue;
245  Browser* restored = QuitBrowserAndRestore(browser(), 3);
246  for (int i = 0; i < 2; ++i) {
247    std::string message;
248    EXPECT_TRUE(message_queue.WaitForMessage(&message));
249    EXPECT_EQ("\"READY\"", message);
250  }
251
252  // There should be 3 restored tabs in the new browser.
253  TabStripModel* tab_strip_model = restored->tab_strip_model();
254  const int tabs = tab_strip_model->count();
255  ASSERT_EQ(3, tabs);
256
257  // The middle tab only should have visible disposition.
258  for (int i = 0; i < tabs; ++i) {
259    content::WebContents* contents = tab_strip_model->GetWebContentsAt(i);
260    std::string document_visibility_state;
261    const char kGetStateJS[] = "window.domAutomationController.send("
262        "window.document.visibilityState);";
263    EXPECT_TRUE(content::ExecuteScriptAndExtractString(
264        contents, kGetStateJS, &document_visibility_state));
265    if (i == 1) {
266      EXPECT_EQ("visible", document_visibility_state);
267    } else {
268      EXPECT_EQ("hidden", document_visibility_state);
269    }
270  }
271}
272
273#if defined(OS_CHROMEOS)
274// Verify that session restore does not occur when a user opens a browser window
275// when no other browser windows are open on ChromeOS.
276// TODO(pkotwicz): Add test which doesn't open incognito browser once
277// disable-zero-browsers-open-for-tests is removed.
278// (http://crbug.com/119175)
279// TODO(pkotwicz): Mac should have the behavior outlined by this test. It should
280// not do session restore if an incognito window is already open.
281// (http://crbug.com/120927)
282IN_PROC_BROWSER_TEST_F(SessionRestoreTest, NoSessionRestoreNewWindowChromeOS) {
283  GURL url(ui_test_utils::GetTestUrl(
284      base::FilePath(base::FilePath::kCurrentDirectory),
285      base::FilePath(FILE_PATH_LITERAL("title1.html"))));
286
287  // Add a single tab.
288  ui_test_utils::NavigateToURL(browser(), url);
289
290  Browser* incognito_browser = CreateIncognitoBrowser();
291  chrome::AddTabAt(incognito_browser, GURL(), -1, true);
292  incognito_browser->window()->Show();
293
294  // Close the normal browser. After this we only have the incognito window
295  // open.
296  CloseBrowserSynchronously(browser());
297
298  // Create a new window, which should open NTP.
299  ui_test_utils::BrowserAddedObserver browser_added_observer;
300  chrome::NewWindow(incognito_browser);
301  Browser* new_browser = browser_added_observer.WaitForSingleNewBrowser();
302
303  ASSERT_TRUE(new_browser);
304  EXPECT_EQ(1, new_browser->tab_strip_model()->count());
305  EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
306            new_browser->tab_strip_model()->GetWebContentsAt(0)->GetURL());
307}
308
309// Test that maximized applications get restored maximized.
310IN_PROC_BROWSER_TEST_F(SessionRestoreTest, MaximizedApps) {
311  const char* app_name = "TestApp";
312  Browser* app_browser = CreateBrowserForApp(app_name, browser()->profile());
313  app_browser->window()->Maximize();
314  app_browser->window()->Show();
315  EXPECT_TRUE(app_browser->window()->IsMaximized());
316  EXPECT_TRUE(app_browser->is_app());
317  EXPECT_TRUE(app_browser->is_type_popup());
318
319  // Close the normal browser. After this we only have the app_browser window.
320  CloseBrowserSynchronously(browser());
321
322  // Create a new window, which should open NTP.
323  ui_test_utils::BrowserAddedObserver browser_added_observer;
324  chrome::NewWindow(app_browser);
325  Browser* new_browser = browser_added_observer.WaitForSingleNewBrowser();
326
327  ASSERT_TRUE(new_browser);
328  EXPECT_TRUE(app_browser->window()->IsMaximized());
329  EXPECT_TRUE(app_browser->is_app());
330  EXPECT_TRUE(app_browser->is_type_popup());
331}
332#endif  // OS_CHROMEOS
333
334#if !defined(OS_CHROMEOS)
335// This test does not apply to ChromeOS as it does not do session restore when
336// a new window is opened.
337
338#if defined(OS_LINUX) && defined(TOOLKIT_VIEWS)
339// Crashes on Linux Views: http://crbug.com/39476
340#define MAYBE_RestoreOnNewWindowWithNoTabbedBrowsers \
341        DISABLED_RestoreOnNewWindowWithNoTabbedBrowsers
342#else
343#define MAYBE_RestoreOnNewWindowWithNoTabbedBrowsers \
344        RestoreOnNewWindowWithNoTabbedBrowsers
345#endif
346
347// Makes sure when session restore is triggered in the same process we don't end
348// up with an extra tab.
349IN_PROC_BROWSER_TEST_F(SessionRestoreTest,
350                       MAYBE_RestoreOnNewWindowWithNoTabbedBrowsers) {
351  const base::FilePath::CharType* kTitle1File =
352      FILE_PATH_LITERAL("title1.html");
353  GURL url(ui_test_utils::GetTestUrl(base::FilePath(
354      base::FilePath::kCurrentDirectory), base::FilePath(kTitle1File)));
355  ui_test_utils::NavigateToURL(browser(), url);
356
357  // Turn on session restore.
358  SessionStartupPref::SetStartupPref(
359      browser()->profile(),
360      SessionStartupPref(SessionStartupPref::LAST));
361
362  // Create a new popup.
363  Profile* profile = browser()->profile();
364  Browser* popup =
365      new Browser(Browser::CreateParams(Browser::TYPE_POPUP, profile,
366                                        browser()->host_desktop_type()));
367  popup->window()->Show();
368
369  // Close the browser.
370  CloseBrowserSynchronously(browser());
371
372  // Create a new window, which should trigger session restore.
373  ui_test_utils::BrowserAddedObserver observer;
374  chrome::NewWindow(popup);
375  Browser* new_browser = observer.WaitForSingleNewBrowser();
376
377  ASSERT_TRUE(new_browser != NULL);
378
379  // The browser should only have one tab.
380  ASSERT_EQ(1, new_browser->tab_strip_model()->count());
381
382  // And the first url should be url.
383  EXPECT_EQ(url, new_browser->tab_strip_model()->GetWebContentsAt(0)->GetURL());
384}
385#endif  // !OS_CHROMEOS
386
387IN_PROC_BROWSER_TEST_F(SessionRestoreTest, RestoreIndividualTabFromWindow) {
388  GURL url1(ui_test_utils::GetTestUrl(
389      base::FilePath(base::FilePath::kCurrentDirectory),
390      base::FilePath(FILE_PATH_LITERAL("title1.html"))));
391  // Any page that will yield a 200 status code will work here.
392  GURL url2("about:version");
393  GURL url3(ui_test_utils::GetTestUrl(
394      base::FilePath(base::FilePath::kCurrentDirectory),
395      base::FilePath(FILE_PATH_LITERAL("title3.html"))));
396
397  // Add and navigate three tabs.
398  ui_test_utils::NavigateToURL(browser(), url1);
399  {
400    content::WindowedNotificationObserver observer(
401        content::NOTIFICATION_LOAD_STOP,
402        content::NotificationService::AllSources());
403    chrome::AddSelectedTabWithURL(browser(), url2,
404                                  ui::PAGE_TRANSITION_LINK);
405    observer.Wait();
406  }
407  {
408    content::WindowedNotificationObserver observer(
409        content::NOTIFICATION_LOAD_STOP,
410        content::NotificationService::AllSources());
411    chrome::AddSelectedTabWithURL(browser(), url3,
412                                  ui::PAGE_TRANSITION_LINK);
413    observer.Wait();
414  }
415
416  TabRestoreService* service =
417      TabRestoreServiceFactory::GetForProfile(browser()->profile());
418  service->ClearEntries();
419
420  chrome::HostDesktopType host_desktop_type = browser()->host_desktop_type();
421
422  browser()->window()->Close();
423
424  // Expect a window with three tabs.
425  ASSERT_EQ(1U, service->entries().size());
426  ASSERT_EQ(TabRestoreService::WINDOW, service->entries().front()->type);
427  const TabRestoreService::Window* window =
428      static_cast<TabRestoreService::Window*>(service->entries().front());
429  EXPECT_EQ(3U, window->tabs.size());
430
431  // Find the SessionID for entry2. Since the session service was destroyed,
432  // there is no guarantee that the SessionID for the tab has remained the same.
433  base::Time timestamp;
434  int http_status_code = 0;
435  for (std::vector<TabRestoreService::Tab>::const_iterator it =
436           window->tabs.begin(); it != window->tabs.end(); ++it) {
437    const TabRestoreService::Tab& tab = *it;
438    // If this tab held url2, then restore this single tab.
439    if (tab.navigations[0].virtual_url() == url2) {
440      timestamp = tab.navigations[0].timestamp();
441      http_status_code = tab.navigations[0].http_status_code();
442      std::vector<content::WebContents*> content =
443          service->RestoreEntryById(NULL, tab.id, host_desktop_type, UNKNOWN);
444      ASSERT_EQ(1U, content.size());
445      ASSERT_TRUE(content[0]);
446      EXPECT_EQ(url2, content[0]->GetURL());
447      break;
448    }
449  }
450  EXPECT_FALSE(timestamp.is_null());
451  EXPECT_EQ(200, http_status_code);
452
453  // Make sure that the restored tab is removed from the service.
454  ASSERT_EQ(1U, service->entries().size());
455  ASSERT_EQ(TabRestoreService::WINDOW, service->entries().front()->type);
456  window = static_cast<TabRestoreService::Window*>(service->entries().front());
457  EXPECT_EQ(2U, window->tabs.size());
458
459  // Make sure that the restored tab was restored with the correct
460  // timestamp and status code.
461  const content::WebContents* contents =
462      browser()->tab_strip_model()->GetActiveWebContents();
463  ASSERT_TRUE(contents);
464  const content::NavigationEntry* entry =
465      contents->GetController().GetActiveEntry();
466  ASSERT_TRUE(entry);
467  EXPECT_EQ(timestamp, entry->GetTimestamp());
468  EXPECT_EQ(http_status_code, entry->GetHttpStatusCode());
469}
470
471IN_PROC_BROWSER_TEST_F(SessionRestoreTest, WindowWithOneTab) {
472  GURL url(ui_test_utils::GetTestUrl(
473      base::FilePath(base::FilePath::kCurrentDirectory),
474      base::FilePath(FILE_PATH_LITERAL("title1.html"))));
475
476  // Add a single tab.
477  ui_test_utils::NavigateToURL(browser(), url);
478
479  TabRestoreService* service =
480      TabRestoreServiceFactory::GetForProfile(browser()->profile());
481  service->ClearEntries();
482  EXPECT_EQ(0U, service->entries().size());
483
484  chrome::HostDesktopType host_desktop_type = browser()->host_desktop_type();
485
486  // Close the window.
487  browser()->window()->Close();
488
489  // Expect the window to be converted to a tab by the TRS.
490  EXPECT_EQ(1U, service->entries().size());
491  ASSERT_EQ(TabRestoreService::TAB, service->entries().front()->type);
492  const TabRestoreService::Tab* tab =
493      static_cast<TabRestoreService::Tab*>(service->entries().front());
494
495  // Restore the tab.
496  std::vector<content::WebContents*> content =
497      service->RestoreEntryById(NULL, tab->id, host_desktop_type, UNKNOWN);
498  ASSERT_EQ(1U, content.size());
499  ASSERT_TRUE(content[0]);
500  EXPECT_EQ(url, content[0]->GetURL());
501
502  // Make sure the restore was successful.
503  EXPECT_EQ(0U, service->entries().size());
504}
505
506#if !defined(OS_CHROMEOS)
507// This test does not apply to ChromeOS as ChromeOS does not do session
508// restore when a new window is open.
509
510// Verifies we remember the last browser window when closing the last
511// non-incognito window while an incognito window is open.
512IN_PROC_BROWSER_TEST_F(SessionRestoreTest, IncognitotoNonIncognito) {
513  GURL url(ui_test_utils::GetTestUrl(
514      base::FilePath(base::FilePath::kCurrentDirectory),
515      base::FilePath(FILE_PATH_LITERAL("title1.html"))));
516
517  // Add a single tab.
518  ui_test_utils::NavigateToURL(browser(), url);
519
520  // Create a new incognito window.
521  Browser* incognito_browser = CreateIncognitoBrowser();
522  chrome::AddTabAt(incognito_browser, GURL(), -1, true);
523  incognito_browser->window()->Show();
524
525  // Close the normal browser. After this we only have the incognito window
526  // open.
527  CloseBrowserSynchronously(browser());
528
529  // Create a new window, which should trigger session restore.
530  ui_test_utils::BrowserAddedObserver browser_added_observer;
531  chrome::NewWindow(incognito_browser);
532  Browser* new_browser = browser_added_observer.WaitForSingleNewBrowser();
533
534  // The first tab should have 'url' as its url.
535  ASSERT_TRUE(new_browser);
536  EXPECT_EQ(url, new_browser->tab_strip_model()->GetWebContentsAt(0)->GetURL());
537}
538#endif  // !OS_CHROMEOS
539
540namespace {
541
542// Verifies that the given NavigationController has exactly two
543// entries that correspond to the given URLs and that all but the last
544// entry have null timestamps.
545void VerifyNavigationEntries(
546    const content::NavigationController& controller,
547    GURL url1, GURL url2) {
548  ASSERT_EQ(2, controller.GetEntryCount());
549  EXPECT_EQ(1, controller.GetCurrentEntryIndex());
550  EXPECT_EQ(url1, controller.GetEntryAtIndex(0)->GetURL());
551  EXPECT_EQ(url2, controller.GetEntryAtIndex(1)->GetURL());
552  EXPECT_TRUE(controller.GetEntryAtIndex(0)->GetTimestamp().is_null());
553  EXPECT_FALSE(controller.GetEntryAtIndex(1)->GetTimestamp().is_null());
554}
555
556}  // namespace
557
558IN_PROC_BROWSER_TEST_F(SessionRestoreTest, RestoreForeignTab) {
559  GURL url1("http://google.com");
560  GURL url2("http://google2.com");
561  SerializedNavigationEntry nav1 =
562      SerializedNavigationEntryTestHelper::CreateNavigation(url1.spec(), "one");
563  SerializedNavigationEntry nav2 =
564      SerializedNavigationEntryTestHelper::CreateNavigation(url2.spec(), "two");
565
566  // Set up the restore data.
567  sync_pb::SessionTab sync_data;
568  sync_data.set_tab_visual_index(0);
569  sync_data.set_current_navigation_index(1);
570  sync_data.set_pinned(false);
571  sync_data.add_navigation()->CopyFrom(nav1.ToSyncData());
572  sync_data.add_navigation()->CopyFrom(nav2.ToSyncData());
573
574  SessionTab tab;
575  tab.SetFromSyncData(sync_data, base::Time::Now());
576  EXPECT_EQ(2U, tab.navigations.size());
577  for (size_t i = 0; i < tab.navigations.size(); ++i)
578    EXPECT_TRUE(tab.navigations[i].timestamp().is_null());
579
580  ASSERT_EQ(1, browser()->tab_strip_model()->count());
581
582  // Restore in the current tab.
583  content::WebContents* tab_content = NULL;
584  {
585    content::WindowedNotificationObserver observer(
586        content::NOTIFICATION_LOAD_STOP,
587        content::NotificationService::AllSources());
588    tab_content = SessionRestore::RestoreForeignSessionTab(
589        browser()->tab_strip_model()->GetActiveWebContents(), tab, CURRENT_TAB);
590    observer.Wait();
591  }
592  ASSERT_EQ(1, browser()->tab_strip_model()->count());
593  content::WebContents* web_contents =
594      browser()->tab_strip_model()->GetWebContentsAt(0);
595  VerifyNavigationEntries(web_contents->GetController(), url1, url2);
596  ASSERT_TRUE(web_contents->GetUserAgentOverride().empty());
597  ASSERT_TRUE(tab_content);
598  ASSERT_EQ(url2, tab_content->GetURL());
599
600  // Restore in a new tab.
601  tab_content = NULL;
602  {
603    content::WindowedNotificationObserver observer(
604        content::NOTIFICATION_LOAD_STOP,
605        content::NotificationService::AllSources());
606    tab_content = SessionRestore::RestoreForeignSessionTab(
607        browser()->tab_strip_model()->GetActiveWebContents(),
608        tab, NEW_BACKGROUND_TAB);
609    observer.Wait();
610  }
611  ASSERT_EQ(2, browser()->tab_strip_model()->count());
612  ASSERT_EQ(0, browser()->tab_strip_model()->active_index());
613  web_contents = browser()->tab_strip_model()->GetWebContentsAt(1);
614  VerifyNavigationEntries(web_contents->GetController(), url1, url2);
615  ASSERT_TRUE(web_contents->GetUserAgentOverride().empty());
616  ASSERT_TRUE(tab_content);
617  ASSERT_EQ(url2, tab_content->GetURL());
618
619  // Restore in a new window.
620  Browser* new_browser = NULL;
621  tab_content = NULL;
622  {
623    ui_test_utils::BrowserAddedObserver browser_observer;
624    content::WindowedNotificationObserver observer(
625        content::NOTIFICATION_LOAD_STOP,
626        content::NotificationService::AllSources());
627    tab_content = SessionRestore::RestoreForeignSessionTab(
628        browser()->tab_strip_model()->GetActiveWebContents(), tab, NEW_WINDOW);
629    new_browser = browser_observer.WaitForSingleNewBrowser();
630    observer.Wait();
631  }
632
633  ASSERT_EQ(1, new_browser->tab_strip_model()->count());
634  web_contents = new_browser->tab_strip_model()->GetWebContentsAt(0);
635  VerifyNavigationEntries(web_contents->GetController(), url1, url2);
636  ASSERT_TRUE(web_contents->GetUserAgentOverride().empty());
637  ASSERT_TRUE(tab_content);
638  ASSERT_EQ(url2, tab_content->GetURL());
639}
640
641IN_PROC_BROWSER_TEST_F(SessionRestoreTest, RestoreForeignSession) {
642  Profile* profile = browser()->profile();
643
644  GURL url1("http://google.com");
645  GURL url2("http://google2.com");
646  SerializedNavigationEntry nav1 =
647      SerializedNavigationEntryTestHelper::CreateNavigation(url1.spec(), "one");
648  SerializedNavigationEntry nav2 =
649      SerializedNavigationEntryTestHelper::CreateNavigation(url2.spec(), "two");
650  SerializedNavigationEntryTestHelper::SetIsOverridingUserAgent(true, &nav2);
651
652  // Set up the restore data -- one window with two tabs.
653  std::vector<const SessionWindow*> session;
654  SessionWindow window;
655  SessionTab tab1;
656  {
657    sync_pb::SessionTab sync_data;
658    sync_data.set_tab_visual_index(0);
659    sync_data.set_current_navigation_index(0);
660    sync_data.set_pinned(true);
661    sync_data.add_navigation()->CopyFrom(nav1.ToSyncData());
662    tab1.SetFromSyncData(sync_data, base::Time::Now());
663  }
664  window.tabs.push_back(&tab1);
665
666  SessionTab tab2;
667  {
668    sync_pb::SessionTab sync_data;
669    sync_data.set_tab_visual_index(1);
670    sync_data.set_current_navigation_index(0);
671    sync_data.set_pinned(false);
672    sync_data.add_navigation()->CopyFrom(nav2.ToSyncData());
673    tab2.SetFromSyncData(sync_data, base::Time::Now());
674  }
675  window.tabs.push_back(&tab2);
676
677  // Leave tab3 empty. Should have no effect on restored session, but simulates
678  // partially complete foreign session data.
679  SessionTab tab3;
680  window.tabs.push_back(&tab3);
681
682  session.push_back(static_cast<const SessionWindow*>(&window));
683  ui_test_utils::BrowserAddedObserver window_observer;
684  std::vector<Browser*> browsers =
685      SessionRestore::RestoreForeignSessionWindows(
686          profile, browser()->host_desktop_type(), session.begin(),
687          session.end());
688  Browser* new_browser = window_observer.WaitForSingleNewBrowser();
689  ASSERT_TRUE(new_browser);
690  ASSERT_EQ(2u, active_browser_list_->size());
691  ASSERT_EQ(2, new_browser->tab_strip_model()->count());
692
693  ASSERT_EQ(1u, browsers.size());
694  ASSERT_TRUE(browsers[0]);
695  ASSERT_EQ(2, browsers[0]->tab_strip_model()->count());
696
697  content::WebContents* web_contents_1 =
698      new_browser->tab_strip_model()->GetWebContentsAt(0);
699  content::WebContents* web_contents_2 =
700      new_browser->tab_strip_model()->GetWebContentsAt(1);
701  ASSERT_EQ(url1, web_contents_1->GetURL());
702  ASSERT_EQ(url2, web_contents_2->GetURL());
703
704  // Check user agent override state.
705  ASSERT_TRUE(web_contents_1->GetUserAgentOverride().empty());
706  ASSERT_TRUE(web_contents_2->GetUserAgentOverride().empty());
707
708  content::NavigationEntry* entry =
709      web_contents_1->GetController().GetActiveEntry();
710  ASSERT_TRUE(entry);
711  ASSERT_FALSE(entry->GetIsOverridingUserAgent());
712
713  entry = web_contents_2->GetController().GetActiveEntry();
714  ASSERT_TRUE(entry);
715  ASSERT_FALSE(entry->GetIsOverridingUserAgent());
716
717  // The SessionWindow destructor deletes the tabs, so we have to clear them
718  // here to avoid a crash.
719  window.tabs.clear();
720}
721
722IN_PROC_BROWSER_TEST_F(SessionRestoreTest, Basic) {
723  ui_test_utils::NavigateToURL(browser(), url1_);
724  ui_test_utils::NavigateToURL(browser(), url2_);
725
726  Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
727  ASSERT_EQ(1u, active_browser_list_->size());
728  ASSERT_EQ(url2_,
729            new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
730  GoBack(new_browser);
731  ASSERT_EQ(url1_,
732            new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
733}
734
735IN_PROC_BROWSER_TEST_F(SessionRestoreTest, RestoreWebUI) {
736  const GURL webui_url("chrome://omnibox");
737  ui_test_utils::NavigateToURL(browser(), webui_url);
738  const content::WebContents* old_tab =
739      browser()->tab_strip_model()->GetActiveWebContents();
740  EXPECT_EQ(content::BINDINGS_POLICY_WEB_UI,
741            old_tab->GetRenderViewHost()->GetEnabledBindings());
742
743  Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
744  ASSERT_EQ(1u, active_browser_list_->size());
745  const content::WebContents* new_tab =
746      new_browser->tab_strip_model()->GetActiveWebContents();
747  EXPECT_EQ(webui_url, new_tab->GetURL());
748  EXPECT_EQ(content::BINDINGS_POLICY_WEB_UI,
749            new_tab->GetRenderViewHost()->GetEnabledBindings());
750}
751
752IN_PROC_BROWSER_TEST_F(SessionRestoreTest, RestoreWebUISettings) {
753  const GURL webui_url("chrome://settings");
754  ui_test_utils::NavigateToURL(browser(), webui_url);
755  const content::WebContents* old_tab =
756      browser()->tab_strip_model()->GetActiveWebContents();
757  EXPECT_EQ(content::BINDINGS_POLICY_WEB_UI,
758            old_tab->GetRenderViewHost()->GetEnabledBindings());
759
760  Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
761  ASSERT_EQ(1u, active_browser_list_->size());
762  const content::WebContents* new_tab =
763      new_browser->tab_strip_model()->GetActiveWebContents();
764  EXPECT_EQ(webui_url, new_tab->GetURL());
765  EXPECT_EQ(content::BINDINGS_POLICY_WEB_UI,
766            new_tab->GetRenderViewHost()->GetEnabledBindings());
767}
768
769IN_PROC_BROWSER_TEST_F(SessionRestoreTest, RestoresForwardAndBackwardNavs) {
770  ui_test_utils::NavigateToURL(browser(), url1_);
771  ui_test_utils::NavigateToURL(browser(), url2_);
772  ui_test_utils::NavigateToURL(browser(), url3_);
773
774  GoBack(browser());
775  Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
776  ASSERT_EQ(1u, active_browser_list_->size());
777  ASSERT_EQ(url2_,
778            new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
779  GoForward(new_browser);
780  ASSERT_EQ(url3_,
781            new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
782  GoBack(new_browser);
783  ASSERT_EQ(url2_,
784            new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
785
786  // Test renderer-initiated back/forward as well.
787  GURL go_back_url("javascript:history.back();");
788  ui_test_utils::NavigateToURL(new_browser, go_back_url);
789  ASSERT_EQ(url1_,
790            new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
791}
792
793// Tests that the SiteInstances used for entries in a restored tab's history
794// are given appropriate max page IDs, so that going back to a restored
795// cross-site page and then forward again works.  (Bug 1204135)
796// This test fails. See http://crbug.com/237497.
797IN_PROC_BROWSER_TEST_F(SessionRestoreTest,
798                       DISABLED_RestoresCrossSiteForwardAndBackwardNavs) {
799  ASSERT_TRUE(test_server()->Start());
800
801  GURL cross_site_url(test_server()->GetURL("files/title2.html"));
802
803  // Visit URLs on different sites.
804  ui_test_utils::NavigateToURL(browser(), url1_);
805  ui_test_utils::NavigateToURL(browser(), cross_site_url);
806  ui_test_utils::NavigateToURL(browser(), url2_);
807
808  GoBack(browser());
809  Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
810  ASSERT_EQ(1u, active_browser_list_->size());
811  ASSERT_EQ(1, new_browser->tab_strip_model()->count());
812
813  // Check that back and forward work as expected.
814  ASSERT_EQ(cross_site_url,
815            new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
816
817  GoBack(new_browser);
818  ASSERT_EQ(url1_,
819            new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
820
821  GoForward(new_browser);
822  ASSERT_EQ(cross_site_url,
823            new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
824
825  // Test renderer-initiated back/forward as well.
826  GURL go_forward_url("javascript:history.forward();");
827  ui_test_utils::NavigateToURL(new_browser, go_forward_url);
828  ASSERT_EQ(url2_,
829            new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
830}
831
832IN_PROC_BROWSER_TEST_F(SessionRestoreTest, TwoTabsSecondSelected) {
833  ui_test_utils::NavigateToURL(browser(), url1_);
834
835  ui_test_utils::NavigateToURLWithDisposition(
836      browser(), url2_, NEW_FOREGROUND_TAB,
837      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
838
839  Browser* new_browser = QuitBrowserAndRestore(browser(), 2);
840
841  ASSERT_EQ(1u, active_browser_list_->size());
842  ASSERT_EQ(2, new_browser->tab_strip_model()->count());
843  ASSERT_EQ(1, new_browser->tab_strip_model()->active_index());
844  ASSERT_EQ(url2_,
845            new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
846
847  ASSERT_EQ(url1_,
848            new_browser->tab_strip_model()->GetWebContentsAt(0)->GetURL());
849}
850
851// Creates two tabs, closes one, quits and makes sure only one tab is restored.
852IN_PROC_BROWSER_TEST_F(SessionRestoreTest, ClosedTabStaysClosed) {
853  ui_test_utils::NavigateToURL(browser(), url1_);
854
855  ui_test_utils::NavigateToURLWithDisposition(
856      browser(), url2_, NEW_FOREGROUND_TAB,
857      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
858  chrome::CloseTab(browser());
859
860  Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
861
862  AssertOneWindowWithOneTab(new_browser);
863  ASSERT_EQ(url1_,
864            new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
865}
866
867// Ensures active tab properly restored when tabs before it closed.
868IN_PROC_BROWSER_TEST_F(SessionRestoreTest, ActiveIndexUpdatedAtClose) {
869  ui_test_utils::NavigateToURL(browser(), url1_);
870  ui_test_utils::NavigateToURLWithDisposition(
871      browser(), url2_, NEW_FOREGROUND_TAB,
872      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
873  ui_test_utils::NavigateToURLWithDisposition(
874      browser(), url3_, NEW_BACKGROUND_TAB,
875      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
876
877  browser()->tab_strip_model()->CloseWebContentsAt(
878      0,
879      TabStripModel::CLOSE_CREATE_HISTORICAL_TAB);
880
881  Browser* new_browser = QuitBrowserAndRestore(browser(), 2);
882
883  ASSERT_EQ(url2_,
884            new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
885  ASSERT_EQ(new_browser->tab_strip_model()->active_index(), 0);
886}
887
888// Ensures active tab properly restored when tabs are inserted before it .
889IN_PROC_BROWSER_TEST_F(SessionRestoreTest, ActiveIndexUpdatedAtInsert) {
890  ui_test_utils::NavigateToURL(browser(), url1_);
891  ui_test_utils::NavigateToURLWithDisposition(
892      browser(), url2_, NEW_BACKGROUND_TAB,
893      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
894
895  chrome::NavigateParams navigate_params(browser(), url3_,
896                                         ui::PAGE_TRANSITION_TYPED);
897  navigate_params.tabstrip_index = 0;
898  navigate_params.disposition = NEW_BACKGROUND_TAB;
899  ui_test_utils::NavigateToURL(&navigate_params);
900
901  Browser* new_browser = QuitBrowserAndRestore(browser(), 3);
902
903  ASSERT_EQ(url1_,
904            new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
905  ASSERT_EQ(new_browser->tab_strip_model()->active_index(), 1);
906}
907
908#if !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
909// This test doesn't apply to the Mac version; see GetCommandLineForRelaunch
910// for details. It was disabled for a long time so might never have worked on
911// ChromeOS.
912
913// Launches an app window, closes tabbed browser, launches and makes sure
914// we restore the tabbed browser url.
915// If this test flakes, use http://crbug.com/29110
916IN_PROC_BROWSER_TEST_F(SessionRestoreTest,
917                       RestoreAfterClosingTabbedBrowserWithAppAndLaunching) {
918#if defined(OS_WIN) && defined(USE_ASH)
919  // Disable this test in Metro+Ash for now (http://crbug.com/262796).
920  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
921    return;
922#endif
923
924  ui_test_utils::NavigateToURL(browser(), url1_);
925
926  // Launch an app.
927  CommandLine app_launch_arguments = GetCommandLineForRelaunch();
928  app_launch_arguments.AppendSwitchASCII(switches::kApp, url2_.spec());
929
930  ui_test_utils::BrowserAddedObserver window_observer;
931
932  base::LaunchProcess(app_launch_arguments, base::LaunchOptionsForTest(), NULL);
933
934  Browser* app_window = window_observer.WaitForSingleNewBrowser();
935  ASSERT_EQ(2u, active_browser_list_->size());
936
937  // Close the first window. The only window left is the App window.
938  CloseBrowserSynchronously(browser());
939
940  // Restore the session, which should bring back the first window with url1_.
941  Browser* new_browser = QuitBrowserAndRestore(app_window, 1);
942
943  AssertOneWindowWithOneTab(new_browser);
944
945  ASSERT_EQ(url1_,
946            new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
947}
948
949#endif  // !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
950
951// Creates two windows, closes one, restores, make sure only one window open.
952IN_PROC_BROWSER_TEST_F(SessionRestoreTest, TwoWindowsCloseOneRestoreOnlyOne) {
953  ui_test_utils::NavigateToURL(browser(), url1_);
954
955  // Open a second window.
956  ui_test_utils::NavigateToURLWithDisposition(
957      browser(),
958      GURL(url::kAboutBlankURL),
959      NEW_WINDOW,
960      ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER);
961
962  ASSERT_EQ(2u, active_browser_list_->size());
963
964  // Close it.
965  Browser* new_window = active_browser_list_->get(1);
966  CloseBrowserSynchronously(new_window);
967
968  // Restart and make sure we have only one window with one tab and the url
969  // is url1_.
970  Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
971
972  AssertOneWindowWithOneTab(new_browser);
973
974  ASSERT_EQ(url1_,
975            new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
976}
977
978// Make sure after a restore the number of processes matches that of the number
979// of processes running before the restore. This creates a new tab so that
980// we should have two new tabs running.  (This test will pass in both
981// process-per-site and process-per-site-instance, because we treat the new tab
982// as a special case in process-per-site-instance so that it only ever uses one
983// process.)
984//
985// Flaky: http://code.google.com/p/chromium/issues/detail?id=52022
986// Unfortunately, the fix at http://codereview.chromium.org/6546078
987// breaks NTP background image refreshing, so ThemeSource had to revert to
988// replacing the existing data source.
989IN_PROC_BROWSER_TEST_F(SessionRestoreTest, ShareProcessesOnRestore) {
990  // Create two new tabs.
991  ui_test_utils::NavigateToURLWithDisposition(
992      browser(),
993      GURL(url::kAboutBlankURL),
994      NEW_FOREGROUND_TAB,
995      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
996  ui_test_utils::NavigateToURLWithDisposition(
997      browser(),
998      GURL(url::kAboutBlankURL),
999      NEW_FOREGROUND_TAB,
1000      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
1001
1002  int expected_process_count = RenderProcessHostCount();
1003
1004  // Restart.
1005  Browser* new_browser = QuitBrowserAndRestore(browser(), 3);
1006
1007  ASSERT_EQ(3, new_browser->tab_strip_model()->count());
1008
1009  ASSERT_EQ(expected_process_count, RenderProcessHostCount());
1010}
1011
1012// Test that changing the user agent override will persist it to disk.
1013IN_PROC_BROWSER_TEST_F(SessionRestoreTest, PersistAndRestoreUserAgentOverride) {
1014  // Create a tab with an overridden user agent.
1015  ui_test_utils::NavigateToURL(browser(), url1_);
1016  ASSERT_EQ(0, browser()->tab_strip_model()->active_index());
1017  browser()->tab_strip_model()->GetWebContentsAt(0)->
1018      SetUserAgentOverride("override");
1019
1020  // Create a tab without an overridden user agent.
1021  ui_test_utils::NavigateToURLWithDisposition(
1022      browser(), url2_, NEW_FOREGROUND_TAB,
1023      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
1024  ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
1025
1026  // Kill the original browser then open a new one to trigger a restore.
1027  Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
1028  ASSERT_EQ(1u, active_browser_list_->size());
1029  ASSERT_EQ(2, new_browser->tab_strip_model()->count());
1030  ASSERT_EQ(1, new_browser->tab_strip_model()->active_index());
1031
1032  // Confirm that the user agent overrides are properly set.
1033  EXPECT_EQ("override",
1034            new_browser->tab_strip_model()->GetWebContentsAt(0)->
1035                GetUserAgentOverride());
1036  EXPECT_EQ("",
1037            new_browser->tab_strip_model()->GetWebContentsAt(1)->
1038                GetUserAgentOverride());
1039}
1040
1041// Regression test for crbug.com/125958. When restoring a pinned selected tab in
1042// a setting where there are existing tabs, the selected index computation was
1043// wrong, leading to the wrong tab getting selected, DCHECKs firing, and the
1044// pinned tab not getting loaded.
1045IN_PROC_BROWSER_TEST_F(SessionRestoreTest, RestorePinnedSelectedTab) {
1046  // Create a pinned tab.
1047  ui_test_utils::NavigateToURL(browser(), url1_);
1048  browser()->tab_strip_model()->SetTabPinned(0, true);
1049  ASSERT_EQ(0, browser()->tab_strip_model()->active_index());
1050  // Create a nonpinned tab.
1051  ui_test_utils::NavigateToURLWithDisposition(
1052      browser(), url2_, NEW_FOREGROUND_TAB,
1053      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
1054  ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
1055  // Select the pinned tab.
1056  browser()->tab_strip_model()->ActivateTabAt(0, true);
1057  ASSERT_EQ(0, browser()->tab_strip_model()->active_index());
1058  Profile* profile = browser()->profile();
1059
1060  // This will also initiate a session restore, but we're not interested in it.
1061  Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
1062  ASSERT_EQ(1u, active_browser_list_->size());
1063  ASSERT_EQ(2, new_browser->tab_strip_model()->count());
1064  ASSERT_EQ(0, new_browser->tab_strip_model()->active_index());
1065  // Close the pinned tab.
1066  chrome::CloseTab(new_browser);
1067  ASSERT_EQ(1, new_browser->tab_strip_model()->count());
1068  ASSERT_EQ(0, new_browser->tab_strip_model()->active_index());
1069  // Use the existing tab to navigate away, so that we can verify it was really
1070  // clobbered.
1071  ui_test_utils::NavigateToURL(new_browser, url3_);
1072
1073  // Restore the session again, clobbering the existing tab.
1074  SessionRestore::RestoreSession(
1075      profile, new_browser,
1076      new_browser->host_desktop_type(),
1077      SessionRestore::CLOBBER_CURRENT_TAB | SessionRestore::SYNCHRONOUS,
1078      std::vector<GURL>());
1079
1080  // The pinned tab is the selected tab.
1081  ASSERT_EQ(2, new_browser->tab_strip_model()->count());
1082  EXPECT_EQ(0, new_browser->tab_strip_model()->active_index());
1083  EXPECT_EQ(url1_,
1084            new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
1085  EXPECT_EQ(url2_,
1086            new_browser->tab_strip_model()->GetWebContentsAt(1)->GetURL());
1087}
1088
1089// Regression test for crbug.com/240156. When restoring tabs with a navigation,
1090// the navigation should take active tab focus.
1091IN_PROC_BROWSER_TEST_F(SessionRestoreTest, RestoreWithNavigateSelectedTab) {
1092  // Create 2 tabs.
1093  ui_test_utils::NavigateToURL(browser(), url1_);
1094  ui_test_utils::NavigateToURLWithDisposition(
1095      browser(), url2_, NEW_FOREGROUND_TAB,
1096      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
1097
1098  // Restore the session by calling chrome::Navigate().
1099  Browser* new_browser = QuitBrowserAndRestoreWithURL(browser(), 3, url3_);
1100  ASSERT_EQ(1u, active_browser_list_->size());
1101  ASSERT_EQ(3, new_browser->tab_strip_model()->count());
1102  // Navigated url should be the active tab.
1103  ASSERT_EQ(url3_,
1104            new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
1105}
1106
1107// Do a clobber restore from the new tab page. This test follows the code path
1108// of a crash followed by the user clicking restore from the new tab page.
1109IN_PROC_BROWSER_TEST_F(SessionRestoreTest, ClobberRestoreTest) {
1110  // Create 2 tabs.
1111  ui_test_utils::NavigateToURL(browser(), url1_);
1112  ASSERT_EQ(0, browser()->tab_strip_model()->active_index());
1113  ui_test_utils::NavigateToURLWithDisposition(
1114      browser(), url2_, NEW_FOREGROUND_TAB,
1115      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
1116  ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
1117  Profile* profile = browser()->profile();
1118
1119  // This will also initiate a session restore, but we're not interested in it.
1120  Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
1121  ASSERT_EQ(1u, active_browser_list_->size());
1122  ASSERT_EQ(2, new_browser->tab_strip_model()->count());
1123  ASSERT_EQ(1, new_browser->tab_strip_model()->active_index());
1124  // Close the first tab.
1125  chrome::CloseTab(new_browser);
1126  ASSERT_EQ(1, new_browser->tab_strip_model()->count());
1127  ASSERT_EQ(0, new_browser->tab_strip_model()->active_index());
1128  // Use the existing tab to navigate to the NTP.
1129  ui_test_utils::NavigateToURL(new_browser, GURL(chrome::kChromeUINewTabURL));
1130
1131  // Restore the session again, clobbering the existing tab.
1132  SessionRestore::RestoreSession(
1133      profile, new_browser,
1134      new_browser->host_desktop_type(),
1135      SessionRestore::CLOBBER_CURRENT_TAB | SessionRestore::SYNCHRONOUS,
1136      std::vector<GURL>());
1137
1138  // 2 tabs should have been restored, with the existing tab clobbered, giving
1139  // us a total of 2 tabs.
1140  ASSERT_EQ(2, new_browser->tab_strip_model()->count());
1141  EXPECT_EQ(1, new_browser->tab_strip_model()->active_index());
1142  EXPECT_EQ(url1_,
1143            new_browser->tab_strip_model()->GetWebContentsAt(0)->GetURL());
1144  EXPECT_EQ(url2_,
1145            new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
1146}
1147
1148IN_PROC_BROWSER_TEST_F(SessionRestoreTest, SessionStorage) {
1149  ui_test_utils::NavigateToURL(browser(), url1_);
1150  content::NavigationController* controller =
1151      &browser()->tab_strip_model()->GetActiveWebContents()->GetController();
1152  ASSERT_TRUE(controller->GetDefaultSessionStorageNamespace());
1153  std::string session_storage_persistent_id =
1154      controller->GetDefaultSessionStorageNamespace()->persistent_id();
1155  Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
1156  ASSERT_EQ(1u, active_browser_list_->size());
1157  ASSERT_EQ(url1_,
1158            new_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
1159  content::NavigationController* new_controller =
1160      &new_browser->tab_strip_model()->GetActiveWebContents()->GetController();
1161  ASSERT_TRUE(new_controller->GetDefaultSessionStorageNamespace());
1162  std::string restored_session_storage_persistent_id =
1163      new_controller->GetDefaultSessionStorageNamespace()->persistent_id();
1164  EXPECT_EQ(session_storage_persistent_id,
1165            restored_session_storage_persistent_id);
1166}
1167
1168IN_PROC_BROWSER_TEST_F(SessionRestoreTest, SessionStorageAfterTabReplace) {
1169  // Simulate what prerendering does: create a new WebContents with the same
1170  // SessionStorageNamespace as an existing tab, then replace the tab with it.
1171  {
1172    content::NavigationController* controller =
1173        &browser()->tab_strip_model()->GetActiveWebContents()->GetController();
1174    ASSERT_TRUE(controller->GetDefaultSessionStorageNamespace());
1175
1176    content::SessionStorageNamespaceMap session_storage_namespace_map;
1177    session_storage_namespace_map[std::string()] =
1178        controller->GetDefaultSessionStorageNamespace();
1179    scoped_ptr<content::WebContents> web_contents(
1180        content::WebContents::CreateWithSessionStorage(
1181            content::WebContents::CreateParams(browser()->profile()),
1182            session_storage_namespace_map));
1183
1184    TabStripModel* tab_strip_model = browser()->tab_strip_model();
1185    scoped_ptr<content::WebContents> old_web_contents(
1186        tab_strip_model->ReplaceWebContentsAt(
1187            tab_strip_model->active_index(), web_contents.release()));
1188    // Navigate with the new tab.
1189    ui_test_utils::NavigateToURL(browser(), url2_);
1190    // old_web_contents goes out of scope.
1191  }
1192
1193  // Check that the sessionStorage data is going to be persisted.
1194  content::NavigationController* controller =
1195      &browser()->tab_strip_model()->GetActiveWebContents()->GetController();
1196  EXPECT_TRUE(
1197      controller->GetDefaultSessionStorageNamespace()->should_persist());
1198
1199  // Quit and restore. Check that no extra tabs were created.
1200  Browser* new_browser = QuitBrowserAndRestore(browser(), 1);
1201  ASSERT_EQ(1u, active_browser_list_->size());
1202  EXPECT_EQ(1, new_browser->tab_strip_model()->count());
1203}
1204