// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/sessions/persistent_tab_restore_service.h"

#include "base/compiler_specific.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/sequenced_worker_pool.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/sessions/session_service.h"
#include "chrome/browser/sessions/session_service_factory.h"
#include "chrome/browser/sessions/session_types.h"
#include "chrome/browser/sessions/tab_restore_service_factory.h"
#include "chrome/browser/sessions/tab_restore_service_observer.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/chrome_render_view_test.h"
#include "chrome/test/base/testing_profile.h"
#include "components/sessions/serialized_navigation_entry_test_helper.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/render_view_test.h"
#include "content/public/test/web_contents_tester.h"
#include "testing/gtest/include/gtest/gtest.h"

typedef TabRestoreService::Tab Tab;
typedef TabRestoreService::Window Window;

using content::NavigationEntry;
using content::WebContentsTester;
using sessions::SerializedNavigationEntry;
using sessions::SerializedNavigationEntryTestHelper;

// Create subclass that overrides TimeNow so that we can control the time used
// for closed tabs and windows.
class PersistentTabRestoreTimeFactory : public TabRestoreService::TimeFactory {
 public:
  PersistentTabRestoreTimeFactory() : time_(base::Time::Now()) {}

  virtual ~PersistentTabRestoreTimeFactory() {}

  virtual base::Time TimeNow() OVERRIDE {
    return time_;
  }

 private:
  base::Time time_;
};

class PersistentTabRestoreServiceTest : public ChromeRenderViewHostTestHarness {
 public:
  PersistentTabRestoreServiceTest()
    : url1_("http://1"),
      url2_("http://2"),
      url3_("http://3"),
      user_agent_override_(
          "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.19"
          " (KHTML, like Gecko) Chrome/18.0.1025.45 Safari/535.19"),
      time_factory_(NULL) {
  }

  virtual ~PersistentTabRestoreServiceTest() {
  }

 protected:
  enum {
    kMaxEntries = TabRestoreServiceHelper::kMaxEntries,
  };

  // testing::Test:
  virtual void SetUp() OVERRIDE {
    ChromeRenderViewHostTestHarness::SetUp();
    time_factory_ = new PersistentTabRestoreTimeFactory();
    service_.reset(new PersistentTabRestoreService(profile(), time_factory_));
  }

  virtual void TearDown() OVERRIDE {
    service_->Shutdown();
    service_.reset();
    delete time_factory_;
    ChromeRenderViewHostTestHarness::TearDown();
  }

  TabRestoreService::Entries* mutable_entries() {
    return service_->mutable_entries();
  }

  void PruneEntries() {
    service_->PruneEntries();
  }

  void AddThreeNavigations() {
    // Navigate to three URLs.
    NavigateAndCommit(url1_);
    NavigateAndCommit(url2_);
    NavigateAndCommit(url3_);
  }

  void NavigateToIndex(int index) {
    // Navigate back. We have to do this song and dance as NavigationController
    // isn't happy if you navigate immediately while going back.
    controller().GoToIndex(index);
    WebContentsTester::For(web_contents())->CommitPendingNavigation();
  }

  void RecreateService() {
    // Must set service to null first so that it is destroyed before the new
    // one is created.
    service_->Shutdown();
    content::BrowserThread::GetBlockingPool()->FlushForTesting();
    service_.reset();
    service_.reset(new PersistentTabRestoreService(profile(), time_factory_));
    SynchronousLoadTabsFromLastSession();
  }

  // Adds a window with one tab and url to the profile's session service.
  // If |pinned| is true, the tab is marked as pinned in the session service.
  void AddWindowWithOneTabToSessionService(bool pinned) {
    SessionService* session_service =
        SessionServiceFactory::GetForProfile(profile());
    SessionID tab_id;
    SessionID window_id;
    session_service->SetWindowType(
        window_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL);
    session_service->SetTabWindow(window_id, tab_id);
    session_service->SetTabIndexInWindow(window_id, tab_id, 0);
    session_service->SetSelectedTabInWindow(window_id, 0);
    if (pinned)
      session_service->SetPinnedState(window_id, tab_id, true);
    session_service->UpdateTabNavigation(
        window_id, tab_id,
        SerializedNavigationEntryTestHelper::CreateNavigation(
            url1_.spec(), "title"));
  }

  // Creates a SessionService and assigns it to the Profile. The SessionService
  // is configured with a single window with a single tab pointing at url1_ by
  // way of AddWindowWithOneTabToSessionService. If |pinned| is true, the
  // tab is marked as pinned in the session service.
  void CreateSessionServiceWithOneWindow(bool pinned) {
    // The profile takes ownership of this.
    SessionService* session_service = new SessionService(profile());
    SessionServiceFactory::SetForTestProfile(profile(), session_service);

    AddWindowWithOneTabToSessionService(pinned);

    // Set this, otherwise previous session won't be loaded.
    profile()->set_last_session_exited_cleanly(false);
  }

  void SynchronousLoadTabsFromLastSession() {
    // Ensures that the load is complete before continuing.
    service_->LoadTabsFromLastSession();
    content::BrowserThread::GetBlockingPool()->FlushForTesting();
    base::RunLoop().RunUntilIdle();
    content::BrowserThread::GetBlockingPool()->FlushForTesting();
  }

  GURL url1_;
  GURL url2_;
  GURL url3_;
  std::string user_agent_override_;
  scoped_ptr<PersistentTabRestoreService> service_;
  PersistentTabRestoreTimeFactory* time_factory_;
};

namespace {

class TestTabRestoreServiceObserver : public TabRestoreServiceObserver {
 public:
  TestTabRestoreServiceObserver() : got_loaded_(false) {}

  void clear_got_loaded() { got_loaded_ = false; }
  bool got_loaded() const { return got_loaded_; }

  // TabRestoreServiceObserver:
  virtual void TabRestoreServiceChanged(TabRestoreService* service) OVERRIDE {
  }
  virtual void TabRestoreServiceDestroyed(TabRestoreService* service) OVERRIDE {
  }
  virtual void TabRestoreServiceLoaded(TabRestoreService* service) OVERRIDE {
    got_loaded_ = true;
  }

 private:
  // Was TabRestoreServiceLoaded() invoked?
  bool got_loaded_;

  DISALLOW_COPY_AND_ASSIGN(TestTabRestoreServiceObserver);
};

}  // namespace

TEST_F(PersistentTabRestoreServiceTest, Basic) {
  AddThreeNavigations();

  // Have the service record the tab.
  service_->CreateHistoricalTab(web_contents(), -1);

  // Make sure an entry was created.
  ASSERT_EQ(1U, service_->entries().size());

  // Make sure the entry matches.
  TabRestoreService::Entry* entry = service_->entries().front();
  ASSERT_EQ(TabRestoreService::TAB, entry->type);
  Tab* tab = static_cast<Tab*>(entry);
  EXPECT_FALSE(tab->pinned);
  EXPECT_TRUE(tab->extension_app_id.empty());
  ASSERT_EQ(3U, tab->navigations.size());
  EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url());
  EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url());
  EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url());
  EXPECT_EQ("", tab->user_agent_override);
  EXPECT_EQ(2, tab->current_navigation_index);
  EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(),
            tab->timestamp.ToInternalValue());

  NavigateToIndex(1);

  // And check again, but set the user agent override this time.
  web_contents()->SetUserAgentOverride(user_agent_override_);
  service_->CreateHistoricalTab(web_contents(), -1);

  // There should be two entries now.
  ASSERT_EQ(2U, service_->entries().size());

  // Make sure the entry matches.
  entry = service_->entries().front();
  ASSERT_EQ(TabRestoreService::TAB, entry->type);
  tab = static_cast<Tab*>(entry);
  EXPECT_FALSE(tab->pinned);
  ASSERT_EQ(3U, tab->navigations.size());
  EXPECT_EQ(url1_, tab->navigations[0].virtual_url());
  EXPECT_EQ(url2_, tab->navigations[1].virtual_url());
  EXPECT_EQ(url3_, tab->navigations[2].virtual_url());
  EXPECT_EQ(user_agent_override_, tab->user_agent_override);
  EXPECT_EQ(1, tab->current_navigation_index);
  EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(),
            tab->timestamp.ToInternalValue());
}

// Make sure TabRestoreService doesn't create an entry for a tab with no
// navigations.
TEST_F(PersistentTabRestoreServiceTest, DontCreateEmptyTab) {
  service_->CreateHistoricalTab(web_contents(), -1);
  EXPECT_TRUE(service_->entries().empty());
}

// Tests restoring a single tab.
TEST_F(PersistentTabRestoreServiceTest, Restore) {
  AddThreeNavigations();

  // Have the service record the tab.
  service_->CreateHistoricalTab(web_contents(), -1);

  // Recreate the service and have it load the tabs.
  RecreateService();

  // One entry should be created.
  ASSERT_EQ(1U, service_->entries().size());

  // And verify the entry.
  PersistentTabRestoreService::Entry* entry = service_->entries().front();
  ASSERT_EQ(TabRestoreService::TAB, entry->type);
  Tab* tab = static_cast<Tab*>(entry);
  EXPECT_FALSE(tab->pinned);
  ASSERT_EQ(3U, tab->navigations.size());
  EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url());
  EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url());
  EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url());
  EXPECT_EQ(2, tab->current_navigation_index);
  EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(),
            tab->timestamp.ToInternalValue());
}

// Tests restoring a single pinned tab.
TEST_F(PersistentTabRestoreServiceTest, RestorePinnedAndApp) {
  AddThreeNavigations();

  // Have the service record the tab.
  service_->CreateHistoricalTab(web_contents(), -1);

  // One entry should be created.
  ASSERT_EQ(1U, service_->entries().size());

  // We have to explicitly mark the tab as pinned as there is no browser for
  // these tests.
  TabRestoreService::Entry* entry = service_->entries().front();
  ASSERT_EQ(TabRestoreService::TAB, entry->type);
  Tab* tab = static_cast<Tab*>(entry);
  tab->pinned = true;
  const std::string extension_app_id("test");
  tab->extension_app_id = extension_app_id;

  // Recreate the service and have it load the tabs.
  RecreateService();

  // One entry should be created.
  ASSERT_EQ(1U, service_->entries().size());

  // And verify the entry.
  entry = service_->entries().front();
  ASSERT_EQ(TabRestoreService::TAB, entry->type);
  tab = static_cast<Tab*>(entry);
  EXPECT_TRUE(tab->pinned);
  ASSERT_EQ(3U, tab->navigations.size());
  EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url());
  EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url());
  EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url());
  EXPECT_EQ(2, tab->current_navigation_index);
  EXPECT_TRUE(extension_app_id == tab->extension_app_id);
}

// Make sure we persist entries to disk that have post data.
TEST_F(PersistentTabRestoreServiceTest, DontPersistPostData) {
  AddThreeNavigations();
  controller().GetEntryAtIndex(0)->SetHasPostData(true);
  controller().GetEntryAtIndex(1)->SetHasPostData(true);
  controller().GetEntryAtIndex(2)->SetHasPostData(true);

  // Have the service record the tab.
  service_->CreateHistoricalTab(web_contents(), -1);
  ASSERT_EQ(1U, service_->entries().size());

  // Recreate the service and have it load the tabs.
  RecreateService();

  // One entry should be created.
  ASSERT_EQ(1U, service_->entries().size());

  const TabRestoreService::Entry* restored_entry = service_->entries().front();
  ASSERT_EQ(TabRestoreService::TAB, restored_entry->type);

  const Tab* restored_tab =
      static_cast<const Tab*>(restored_entry);
  // There should be 3 navs.
  ASSERT_EQ(3U, restored_tab->navigations.size());
  EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(),
            restored_tab->timestamp.ToInternalValue());
}

// Make sure we don't persist entries to disk that have post data. This
// differs from DontPersistPostData1 in that all the navigations have post
// data, so that nothing should be persisted.
TEST_F(PersistentTabRestoreServiceTest, DontLoadTwice) {
  AddThreeNavigations();

  // Have the service record the tab.
  service_->CreateHistoricalTab(web_contents(), -1);
  ASSERT_EQ(1U, service_->entries().size());

  // Recreate the service and have it load the tabs.
  RecreateService();

  SynchronousLoadTabsFromLastSession();

  // There should only be one entry.
  ASSERT_EQ(1U, service_->entries().size());
}

// Makes sure we load the previous session as necessary.
TEST_F(PersistentTabRestoreServiceTest, LoadPreviousSession) {
  CreateSessionServiceWithOneWindow(false);

  SessionServiceFactory::GetForProfile(profile())->
      MoveCurrentSessionToLastSession();

  EXPECT_FALSE(service_->IsLoaded());

  TestTabRestoreServiceObserver observer;
  service_->AddObserver(&observer);
  SynchronousLoadTabsFromLastSession();
  EXPECT_TRUE(observer.got_loaded());
  service_->RemoveObserver(&observer);

  // Make sure we get back one entry with one tab whose url is url1.
  ASSERT_EQ(1U, service_->entries().size());
  TabRestoreService::Entry* entry2 = service_->entries().front();
  ASSERT_EQ(TabRestoreService::WINDOW, entry2->type);
  TabRestoreService::Window* window =
      static_cast<TabRestoreService::Window*>(entry2);
  ASSERT_EQ(1U, window->tabs.size());
  EXPECT_EQ(0, window->timestamp.ToInternalValue());
  EXPECT_EQ(0, window->selected_tab_index);
  ASSERT_EQ(1U, window->tabs[0].navigations.size());
  EXPECT_EQ(0, window->tabs[0].current_navigation_index);
  EXPECT_EQ(0, window->tabs[0].timestamp.ToInternalValue());
  EXPECT_TRUE(url1_ == window->tabs[0].navigations[0].virtual_url());
}

// Makes sure we don't attempt to load previous sessions after a restore.
TEST_F(PersistentTabRestoreServiceTest, DontLoadAfterRestore) {
  CreateSessionServiceWithOneWindow(false);

  SessionServiceFactory::GetForProfile(profile())->
      MoveCurrentSessionToLastSession();

  profile()->set_restored_last_session(true);

  SynchronousLoadTabsFromLastSession();

  // Because we restored a session PersistentTabRestoreService shouldn't load
  // the tabs.
  ASSERT_EQ(0U, service_->entries().size());
}

// Makes sure we don't attempt to load previous sessions after a clean exit.
TEST_F(PersistentTabRestoreServiceTest, DontLoadAfterCleanExit) {
  CreateSessionServiceWithOneWindow(false);

  SessionServiceFactory::GetForProfile(profile())->
      MoveCurrentSessionToLastSession();

  profile()->set_last_session_exited_cleanly(true);

  SynchronousLoadTabsFromLastSession();

  ASSERT_EQ(0U, service_->entries().size());
}

TEST_F(PersistentTabRestoreServiceTest, LoadPreviousSessionAndTabs) {
  CreateSessionServiceWithOneWindow(false);

  SessionServiceFactory::GetForProfile(profile())->
      MoveCurrentSessionToLastSession();

  AddThreeNavigations();

  service_->CreateHistoricalTab(web_contents(), -1);

  RecreateService();

  // We should get back two entries, one from the previous session and one from
  // the tab restore service. The previous session entry should be first.
  ASSERT_EQ(2U, service_->entries().size());
  // The first entry should come from the session service.
  TabRestoreService::Entry* entry = service_->entries().front();
  ASSERT_EQ(TabRestoreService::WINDOW, entry->type);
  TabRestoreService::Window* window =
      static_cast<TabRestoreService::Window*>(entry);
  ASSERT_EQ(1U, window->tabs.size());
  EXPECT_EQ(0, window->selected_tab_index);
  EXPECT_EQ(0, window->timestamp.ToInternalValue());
  ASSERT_EQ(1U, window->tabs[0].navigations.size());
  EXPECT_EQ(0, window->tabs[0].current_navigation_index);
  EXPECT_EQ(0, window->tabs[0].timestamp.ToInternalValue());
  EXPECT_TRUE(url1_ == window->tabs[0].navigations[0].virtual_url());

  // Then the closed tab.
  entry = *(++service_->entries().begin());
  ASSERT_EQ(TabRestoreService::TAB, entry->type);
  Tab* tab = static_cast<Tab*>(entry);
  ASSERT_FALSE(tab->pinned);
  ASSERT_EQ(3U, tab->navigations.size());
  EXPECT_EQ(2, tab->current_navigation_index);
  EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(),
            tab->timestamp.ToInternalValue());
  EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url());
  EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url());
  EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url());
}

// Make sure pinned state is correctly loaded from session service.
TEST_F(PersistentTabRestoreServiceTest, LoadPreviousSessionAndTabsPinned) {
  CreateSessionServiceWithOneWindow(true);

  SessionServiceFactory::GetForProfile(profile())->
      MoveCurrentSessionToLastSession();

  AddThreeNavigations();

  service_->CreateHistoricalTab(web_contents(), -1);

  RecreateService();

  // We should get back two entries, one from the previous session and one from
  // the tab restore service. The previous session entry should be first.
  ASSERT_EQ(2U, service_->entries().size());
  // The first entry should come from the session service.
  TabRestoreService::Entry* entry = service_->entries().front();
  ASSERT_EQ(TabRestoreService::WINDOW, entry->type);
  TabRestoreService::Window* window =
      static_cast<TabRestoreService::Window*>(entry);
  ASSERT_EQ(1U, window->tabs.size());
  EXPECT_EQ(0, window->selected_tab_index);
  EXPECT_TRUE(window->tabs[0].pinned);
  ASSERT_EQ(1U, window->tabs[0].navigations.size());
  EXPECT_EQ(0, window->tabs[0].current_navigation_index);
  EXPECT_TRUE(url1_ == window->tabs[0].navigations[0].virtual_url());

  // Then the closed tab.
  entry = *(++service_->entries().begin());
  ASSERT_EQ(TabRestoreService::TAB, entry->type);
  Tab* tab = static_cast<Tab*>(entry);
  ASSERT_FALSE(tab->pinned);
  ASSERT_EQ(3U, tab->navigations.size());
  EXPECT_EQ(2, tab->current_navigation_index);
  EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url());
  EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url());
  EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url());
}

// Creates kMaxEntries + 1 windows in the session service and makes sure we only
// get back kMaxEntries on restore.
TEST_F(PersistentTabRestoreServiceTest, ManyWindowsInSessionService) {
  CreateSessionServiceWithOneWindow(false);

  for (size_t i = 0; i < kMaxEntries; ++i)
    AddWindowWithOneTabToSessionService(false);

  SessionServiceFactory::GetForProfile(profile())->
      MoveCurrentSessionToLastSession();

  AddThreeNavigations();

  service_->CreateHistoricalTab(web_contents(), -1);

  RecreateService();

  // We should get back kMaxEntries entries. We added more, but
  // TabRestoreService only allows up to kMaxEntries.
  ASSERT_EQ(kMaxEntries, service_->entries().size());

  // The first entry should come from the session service.
  TabRestoreService::Entry* entry = service_->entries().front();
  ASSERT_EQ(TabRestoreService::WINDOW, entry->type);
  TabRestoreService::Window* window =
      static_cast<TabRestoreService::Window*>(entry);
  ASSERT_EQ(1U, window->tabs.size());
  EXPECT_EQ(0, window->selected_tab_index);
  EXPECT_EQ(0, window->timestamp.ToInternalValue());
  ASSERT_EQ(1U, window->tabs[0].navigations.size());
  EXPECT_EQ(0, window->tabs[0].current_navigation_index);
  EXPECT_EQ(0, window->tabs[0].timestamp.ToInternalValue());
  EXPECT_TRUE(url1_ == window->tabs[0].navigations[0].virtual_url());
}

// Makes sure we restore timestamps correctly.
TEST_F(PersistentTabRestoreServiceTest, TimestampSurvivesRestore) {
  base::Time tab_timestamp(base::Time::FromInternalValue(123456789));

  AddThreeNavigations();

  // Have the service record the tab.
  service_->CreateHistoricalTab(web_contents(), -1);

  // Make sure an entry was created.
  ASSERT_EQ(1U, service_->entries().size());

  // Make sure the entry matches.
  std::vector<SerializedNavigationEntry> old_navigations;
  {
    // |entry|/|tab| doesn't survive after RecreateService().
    TabRestoreService::Entry* entry = service_->entries().front();
    ASSERT_EQ(TabRestoreService::TAB, entry->type);
    Tab* tab = static_cast<Tab*>(entry);
    tab->timestamp = tab_timestamp;
    old_navigations = tab->navigations;
  }

  EXPECT_EQ(3U, old_navigations.size());
  for (size_t i = 0; i < old_navigations.size(); ++i) {
    EXPECT_FALSE(old_navigations[i].timestamp().is_null());
  }

  // Set this, otherwise previous session won't be loaded.
  profile()->set_last_session_exited_cleanly(false);

  RecreateService();

  // One entry should be created.
  ASSERT_EQ(1U, service_->entries().size());

  // And verify the entry.
  TabRestoreService::Entry* restored_entry = service_->entries().front();
  ASSERT_EQ(TabRestoreService::TAB, restored_entry->type);
  Tab* restored_tab =
      static_cast<Tab*>(restored_entry);
  EXPECT_EQ(tab_timestamp.ToInternalValue(),
            restored_tab->timestamp.ToInternalValue());
  ASSERT_EQ(old_navigations.size(), restored_tab->navigations.size());
  for (size_t i = 0; i < restored_tab->navigations.size(); ++i) {
    EXPECT_EQ(old_navigations[i].timestamp(),
              restored_tab->navigations[i].timestamp());
  }
}

// Makes sure we restore status codes correctly.
TEST_F(PersistentTabRestoreServiceTest, StatusCodesSurviveRestore) {
  AddThreeNavigations();

  // Have the service record the tab.
  service_->CreateHistoricalTab(web_contents(), -1);

  // Make sure an entry was created.
  ASSERT_EQ(1U, service_->entries().size());

  // Make sure the entry matches.
  std::vector<sessions::SerializedNavigationEntry> old_navigations;
  {
    // |entry|/|tab| doesn't survive after RecreateService().
    TabRestoreService::Entry* entry = service_->entries().front();
    ASSERT_EQ(TabRestoreService::TAB, entry->type);
    Tab* tab = static_cast<Tab*>(entry);
    old_navigations = tab->navigations;
  }

  EXPECT_EQ(3U, old_navigations.size());
  for (size_t i = 0; i < old_navigations.size(); ++i) {
    EXPECT_EQ(200, old_navigations[i].http_status_code());
  }

  // Set this, otherwise previous session won't be loaded.
  profile()->set_last_session_exited_cleanly(false);

  RecreateService();

  // One entry should be created.
  ASSERT_EQ(1U, service_->entries().size());

  // And verify the entry.
  TabRestoreService::Entry* restored_entry = service_->entries().front();
  ASSERT_EQ(TabRestoreService::TAB, restored_entry->type);
  Tab* restored_tab =
      static_cast<Tab*>(restored_entry);
  ASSERT_EQ(old_navigations.size(), restored_tab->navigations.size());
  for (size_t i = 0; i < restored_tab->navigations.size(); ++i) {
    EXPECT_EQ(200, restored_tab->navigations[i].http_status_code());
  }
}

TEST_F(PersistentTabRestoreServiceTest, PruneEntries) {
  service_->ClearEntries();
  ASSERT_TRUE(service_->entries().empty());

  const size_t max_entries = kMaxEntries;
  for (size_t i = 0; i < max_entries + 5; i++) {
    SerializedNavigationEntry navigation =
        SerializedNavigationEntryTestHelper::CreateNavigation(
            base::StringPrintf("http://%d", static_cast<int>(i)),
            base::StringPrintf("%d", static_cast<int>(i)));

    Tab* tab = new Tab();
    tab->navigations.push_back(navigation);
    tab->current_navigation_index = 0;

    mutable_entries()->push_back(tab);
  }

  // Only keep kMaxEntries around.
  EXPECT_EQ(max_entries + 5, service_->entries().size());
  PruneEntries();
  EXPECT_EQ(max_entries, service_->entries().size());
  // Pruning again does nothing.
  PruneEntries();
  EXPECT_EQ(max_entries, service_->entries().size());

  // Prune older first.
  const char kRecentUrl[] = "http://recent";
  SerializedNavigationEntry navigation =
      SerializedNavigationEntryTestHelper::CreateNavigation(kRecentUrl,
                                                            "Most recent");
  Tab* tab = new Tab();
  tab->navigations.push_back(navigation);
  tab->current_navigation_index = 0;
  mutable_entries()->push_front(tab);
  EXPECT_EQ(max_entries + 1, service_->entries().size());
  PruneEntries();
  EXPECT_EQ(max_entries, service_->entries().size());
  EXPECT_EQ(GURL(kRecentUrl),
      static_cast<Tab*>(service_->entries().front())->
          navigations[0].virtual_url());

  // Ignore NTPs.
  navigation = SerializedNavigationEntryTestHelper::CreateNavigation(
      chrome::kChromeUINewTabURL, "New tab");

  tab = new Tab();
  tab->navigations.push_back(navigation);
  tab->current_navigation_index = 0;
  mutable_entries()->push_front(tab);

  EXPECT_EQ(max_entries + 1, service_->entries().size());
  PruneEntries();
  EXPECT_EQ(max_entries, service_->entries().size());
  EXPECT_EQ(GURL(kRecentUrl),
      static_cast<Tab*>(service_->entries().front())->
          navigations[0].virtual_url());

  // Don't prune pinned NTPs.
  tab = new Tab();
  tab->pinned = true;
  tab->current_navigation_index = 0;
  tab->navigations.push_back(navigation);
  mutable_entries()->push_front(tab);
  EXPECT_EQ(max_entries + 1, service_->entries().size());
  PruneEntries();
  EXPECT_EQ(max_entries, service_->entries().size());
  EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
            static_cast<Tab*>(service_->entries().front())->
            navigations[0].virtual_url());

  // Don't prune NTPs that have multiple navigations.
  // (Erase the last NTP first.)
  delete service_->entries().front();
  mutable_entries()->erase(mutable_entries()->begin());
  tab = new Tab();
  tab->current_navigation_index = 1;
  tab->navigations.push_back(navigation);
  tab->navigations.push_back(navigation);
  mutable_entries()->push_front(tab);
  EXPECT_EQ(max_entries, service_->entries().size());
  PruneEntries();
  EXPECT_EQ(max_entries, service_->entries().size());
  EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
            static_cast<Tab*>(service_->entries().front())->
            navigations[1].virtual_url());
}

// Regression test for crbug.com/106082
TEST_F(PersistentTabRestoreServiceTest, PruneIsCalled) {
  CreateSessionServiceWithOneWindow(false);

  SessionServiceFactory::GetForProfile(profile())->
      MoveCurrentSessionToLastSession();

  profile()->set_restored_last_session(true);

  const size_t max_entries = kMaxEntries;
  for (size_t i = 0; i < max_entries + 5; i++) {
    NavigateAndCommit(
        GURL(base::StringPrintf("http://%d", static_cast<int>(i))));
    service_->CreateHistoricalTab(web_contents(), -1);
  }

  EXPECT_EQ(max_entries, service_->entries().size());
  // This should not crash.
  SynchronousLoadTabsFromLastSession();
  EXPECT_EQ(max_entries, service_->entries().size());
}

// Makes sure invoking LoadTabsFromLastSession() when the max number of entries
// have been added results in IsLoaded() returning true and notifies observers.
TEST_F(PersistentTabRestoreServiceTest, GoToLoadedWhenHaveMaxEntries) {
  const size_t max_entries = kMaxEntries;
  for (size_t i = 0; i < max_entries + 5; i++) {
    NavigateAndCommit(
        GURL(base::StringPrintf("http://%d", static_cast<int>(i))));
    service_->CreateHistoricalTab(web_contents(), -1);
  }

  EXPECT_FALSE(service_->IsLoaded());
  TestTabRestoreServiceObserver observer;
  service_->AddObserver(&observer);
  EXPECT_EQ(max_entries, service_->entries().size());
  SynchronousLoadTabsFromLastSession();
  EXPECT_TRUE(observer.got_loaded());
  EXPECT_TRUE(service_->IsLoaded());
  service_->RemoveObserver(&observer);
}
