summaryrefslogtreecommitdiffstats
path: root/chrome/browser/navigation_controller_unittest.cc
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
commit09911bf300f1a419907a9412154760efd0b7abc3 (patch)
treef131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/browser/navigation_controller_unittest.cc
parent586acc5fe142f498261f52c66862fa417c3d52d2 (diff)
downloadchromium_src-09911bf300f1a419907a9412154760efd0b7abc3.zip
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.gz
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.bz2
Add chrome to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/navigation_controller_unittest.cc')
-rw-r--r--chrome/browser/navigation_controller_unittest.cc818
1 files changed, 818 insertions, 0 deletions
diff --git a/chrome/browser/navigation_controller_unittest.cc b/chrome/browser/navigation_controller_unittest.cc
new file mode 100644
index 0000000..6b8de0d
--- /dev/null
+++ b/chrome/browser/navigation_controller_unittest.cc
@@ -0,0 +1,818 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/string_util.h"
+#include "chrome/browser/browser_type.h"
+#include "chrome/browser/navigation_controller.h"
+#include "chrome/browser/navigation_entry.h"
+#include "chrome/browser/profile_manager.h"
+#include "chrome/browser/history/history.h"
+#include "chrome/browser/session_service_test_helper.h"
+#include "chrome/browser/tab_contents.h"
+#include "chrome/browser/tab_contents_delegate.h"
+#include "chrome/browser/tab_contents_factory.h"
+#include "chrome/common/stl_util-inl.h"
+#include "chrome/test/testing_profile.h"
+#include "net/base/net_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+// TODO(darin): come up with a better way to define these integers
+// TODO(acw): we should have a real dynamic factory for content types.
+// That way we could have several implementation of
+// TabContents::CreateWithType(). Once this is done we'll be able to
+// have a unit test for NavigationController::Clone()
+const TabContentsType kTestContentsType1 =
+ static_cast<TabContentsType>(TAB_CONTENTS_NUM_TYPES + 1);
+const TabContentsType kTestContentsType2 =
+ static_cast<TabContentsType>(TAB_CONTENTS_NUM_TYPES + 2);
+
+class TestContents : public TabContents {
+ public:
+ BEGIN_MSG_MAP(TestContents)
+ END_MSG_MAP()
+
+ TestContents(TabContentsType type) : TabContents(type) {
+ }
+
+ // Just record the navigation so it can be checked by the test case
+ bool Navigate(const NavigationEntry& entry, bool reload) {
+ pending_entry_.reset(new NavigationEntry(entry));
+ return true;
+ }
+
+ void CompleteNavigation(int page_id) {
+ DCHECK(pending_entry_.get());
+ pending_entry_->SetPageID(page_id);
+ DidNavigateToEntry(pending_entry_.get());
+ controller()->SyncSessionWithEntryByPageID(type(), NULL, page_id);
+ pending_entry_.release();
+ }
+
+ NavigationEntry* pending_entry() const { return pending_entry_.get(); }
+ void set_pending_entry(NavigationEntry* e) { pending_entry_.reset(e); }
+
+ private:
+ scoped_ptr<NavigationEntry> pending_entry_;
+};
+
+class TestContentsFactory : public TabContentsFactory {
+ public:
+ TestContentsFactory(TabContentsType type, const char* scheme)
+ : type_(type),
+ scheme_(scheme) {
+ }
+
+ virtual TabContents* CreateInstance() {
+ return new TestContents(type_);
+ }
+
+ virtual bool CanHandleURL(const GURL& url) {
+ return url.SchemeIs(scheme_);
+ }
+
+ private:
+ TabContentsType type_;
+ const char* scheme_;
+};
+
+TestContentsFactory factory1(kTestContentsType1, "test1");
+TestContentsFactory factory2(kTestContentsType2, "test2");
+
+class NavigationControllerTest : public testing::Test,
+ public TabContentsDelegate {
+ public:
+ NavigationControllerTest() : contents(NULL), profile(NULL) {
+ }
+
+ ~NavigationControllerTest() {
+ delete profile;
+ }
+
+ // testing::Test methods:
+
+ virtual void SetUp() {
+ TabContents::RegisterFactory(kTestContentsType1, &factory1);
+ TabContents::RegisterFactory(kTestContentsType2, &factory2);
+
+ if (!profile)
+ profile = new TestingProfile();
+
+ contents = new TestContents(kTestContentsType1);
+ contents->set_delegate(this);
+ contents->CreateView(::GetDesktopWindow(), gfx::Rect());
+ contents->SetupController(profile);
+ }
+
+ virtual void TearDown() {
+ // Make sure contents is valid. NavigationControllerHistoryTest ends up
+ // resetting this before TearDown is invoked.
+ if (contents)
+ ClearContents();
+ }
+
+
+ void ClearContents() {
+ contents->set_delegate(NULL);
+ contents->CloseContents();
+ contents = NULL;
+
+ TabContents::RegisterFactory(kTestContentsType1, NULL);
+ TabContents::RegisterFactory(kTestContentsType2, NULL);
+ }
+
+ // TabContentsDelegate methods (only care about ReplaceContents):
+ virtual void OpenURLFromTab(TabContents*,
+ const GURL&,
+ WindowOpenDisposition,
+ PageTransition::Type) {}
+ virtual void NavigationStateChanged(const TabContents*,
+ unsigned flags) {}
+ virtual void ReplaceContents(TabContents* source,
+ TabContents* new_contents) {
+ contents->set_delegate(NULL);
+ contents = static_cast<TestContents*>(new_contents);
+ contents->set_delegate(this);
+ }
+ virtual void AddNewContents(TabContents*,
+ TabContents*,
+ WindowOpenDisposition,
+ const gfx::Rect&,
+ bool user_gesture) {}
+ virtual void ActivateContents(TabContents*) {}
+ virtual void LoadingStateChanged(TabContents*) {}
+ virtual void NavigateToPage(TabContents*, const GURL&,
+ PageTransition::Type) {}
+ virtual void CloseContents(TabContents*) {}
+ virtual void MoveContents(TabContents*, const gfx::Rect&) {}
+ virtual bool IsPopup(TabContents*) { return false; }
+ virtual void ToolbarSizeChanged(TabContents* source, bool is_animating) {}
+ virtual void URLStarredChanged(TabContents* source, bool starred) {}
+ virtual void UpdateTargetURL(TabContents* source, const GURL& url) {};
+
+ TestContents* contents;
+
+ Profile* profile;
+};
+
+class NavigationControllerHistoryTest : public NavigationControllerTest {
+ public:
+ NavigationControllerHistoryTest()
+ : profile_manager_(NULL),
+ url0("test1:foo1"),
+ url1("test1:foo1"),
+ url2("test1:foo1") {
+ }
+
+ virtual ~NavigationControllerHistoryTest() {
+ // Prevent our base class from deleting the profile since profile's
+ // lifetime is managed by profile_manager_.
+ profile = NULL;
+ STLDeleteElements(&windows_);
+ }
+
+ virtual void SetUp() {
+ // Calculate the path for a scratch profile, and make sure it's empty.
+ ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &test_dir_));
+ file_util::AppendToPath(&test_dir_, L"NavigationControllerTest");
+ profile_path_ = test_dir_;
+ file_util::AppendToPath(&profile_path_, L"New Profile");
+ file_util::Delete(test_dir_, true);
+ CreateDirectory(test_dir_.c_str(), NULL);
+
+ // Create a profile.
+ profile_manager_ = new ProfileManager();
+ profile = ProfileManager::CreateProfile(profile_path_,
+ L"New Profile", L"new-profile", L"");
+ ASSERT_TRUE(profile);
+ profile_manager_->AddProfile(profile);
+
+ // Do the super thing. Notice that the above code sets profile, profile is
+ // used in NavigationControllerTest::SetUp(), hence it now.
+ NavigationControllerTest::SetUp();
+
+ // Force the session service to be created.
+ SessionService* service = profile->GetSessionService();
+ service->SetWindowType(window_id, BrowserType::TABBED_BROWSER);
+ service->SetWindowBounds(window_id, gfx::Rect(0, 1, 2, 3), false);
+ service->SetTabIndexInWindow(window_id,
+ contents->controller()->session_id(), 0);
+ contents->controller()->SetWindowID(window_id);
+ }
+
+ virtual void TearDown() {
+ NavigationControllerTest::TearDown();
+
+ helper_.set_service(NULL);
+
+ // Make sure we wait for history to shut down before continuing. The task
+ // we add will cause our message loop to quit once it is destroyed.
+ HistoryService* history =
+ profile->GetHistoryService(Profile::IMPLICIT_ACCESS);
+ history->SetOnBackendDestroyTask(new MessageLoop::QuitTask);
+ delete profile_manager_;
+ MessageLoop::current()->Run();
+
+ ASSERT_TRUE(file_util::Delete(test_dir_, true));
+ ASSERT_FALSE(file_util::PathExists(test_dir_));
+ }
+
+ // Deletes the current profile manager and creates a new one. Indirectly this
+ // shuts down the history database and reopens it.
+ void ReopenDatabase() {
+ ClearContents();
+ helper_.set_service(NULL);
+ delete profile_manager_;
+ profile_manager_ = new ProfileManager();
+ profile_manager_->AddProfileByPath(profile_path_);
+ profile = profile_manager_->GetProfileByPath(profile_path_);
+ helper_.set_service(profile->GetSessionService());
+ }
+
+ void GetLastSession() {
+ Profile* profile = contents->profile();
+ profile->GetSessionService()->TabClosed(
+ contents->controller()->window_id(),
+ contents->controller()->session_id());
+
+ ReopenDatabase();
+ Time close_time;
+
+ helper_.ReadWindows(&windows_);
+ }
+
+ CancelableRequestConsumer consumer;
+
+ // URLs for testing.
+ const GURL url0;
+ const GURL url1;
+ const GURL url2;
+
+ std::vector<SessionWindow*> windows_;
+
+ SessionID window_id;
+
+ SessionServiceTestHelper helper_;
+
+ private:
+ ProfileManager* profile_manager_;
+ std::wstring test_dir_;
+ std::wstring profile_path_;
+};
+
+} // namespace
+
+TEST_F(NavigationControllerTest, Defaults) {
+ EXPECT_TRUE(contents->is_active());
+ EXPECT_TRUE(contents->controller());
+ EXPECT_FALSE(contents->controller()->GetPendingEntry());
+ EXPECT_FALSE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), -1);
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 0);
+ EXPECT_FALSE(contents->controller()->CanGoBack());
+ EXPECT_FALSE(contents->controller()->CanGoForward());
+ EXPECT_FALSE(contents->controller()->CanStop());
+}
+
+TEST_F(NavigationControllerTest, LoadURL) {
+ const GURL url1("test1:foo1");
+ const GURL url2("test1:foo2");
+
+ contents->controller()->LoadURL(url1, PageTransition::TYPED);
+
+ // the load should now be pending
+ EXPECT_TRUE(contents->pending_entry());
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 0);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), -1);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1);
+ EXPECT_FALSE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_TRUE(contents->controller()->GetPendingEntry());
+ EXPECT_FALSE(contents->controller()->CanGoBack());
+ EXPECT_FALSE(contents->controller()->CanGoForward());
+ EXPECT_EQ(contents->GetMaxPageID(), -1);
+
+ contents->CompleteNavigation(0);
+
+ // the load should now be committed
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 1);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1);
+ EXPECT_TRUE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_FALSE(contents->controller()->GetPendingEntry());
+ EXPECT_FALSE(contents->controller()->CanGoBack());
+ EXPECT_FALSE(contents->controller()->CanGoForward());
+ EXPECT_EQ(contents->GetMaxPageID(), 0);
+
+ // load another...
+ contents->controller()->LoadURL(url2, PageTransition::TYPED);
+
+ // the load should now be pending
+ EXPECT_TRUE(contents->pending_entry());
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 1);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1);
+ EXPECT_TRUE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_TRUE(contents->controller()->GetPendingEntry());
+ // TODO(darin): maybe this should really be true?
+ EXPECT_FALSE(contents->controller()->CanGoBack());
+ EXPECT_FALSE(contents->controller()->CanGoForward());
+ EXPECT_EQ(contents->GetMaxPageID(), 0);
+
+ contents->CompleteNavigation(1);
+
+ // the load should now be committed
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 2);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 1);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1);
+ EXPECT_TRUE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_FALSE(contents->controller()->GetPendingEntry());
+ EXPECT_TRUE(contents->controller()->CanGoBack());
+ EXPECT_FALSE(contents->controller()->CanGoForward());
+ EXPECT_EQ(contents->GetMaxPageID(), 1);
+}
+
+// Tests what happens when the same page is loaded again. Should not create a
+// new session history entry.
+TEST_F(NavigationControllerTest, LoadURL_SamePage) {
+ const GURL url1("test1:foo1");
+
+ contents->controller()->LoadURL(url1, PageTransition::TYPED);
+ contents->CompleteNavigation(0);
+
+ contents->controller()->LoadURL(url1, PageTransition::TYPED);
+ contents->CompleteNavigation(0);
+
+ // should not have produced a new session history entry
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 1);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1);
+ EXPECT_TRUE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_FALSE(contents->controller()->GetPendingEntry());
+ EXPECT_FALSE(contents->controller()->CanGoBack());
+ EXPECT_FALSE(contents->controller()->CanGoForward());
+}
+
+TEST_F(NavigationControllerTest, LoadURL_Discarded) {
+ const GURL url1("test1:foo1");
+ const GURL url2("test1:foo2");
+
+ contents->controller()->LoadURL(url1, PageTransition::TYPED);
+ contents->CompleteNavigation(0);
+
+ contents->controller()->LoadURL(url2, PageTransition::TYPED);
+ contents->controller()->DiscardPendingEntry();
+
+ // should not have produced a new session history entry
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 1);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1);
+ EXPECT_TRUE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_FALSE(contents->controller()->GetPendingEntry());
+ EXPECT_FALSE(contents->controller()->CanGoBack());
+ EXPECT_FALSE(contents->controller()->CanGoForward());
+}
+
+TEST_F(NavigationControllerTest, Reload) {
+ const GURL url1("test1:foo1");
+
+ contents->controller()->LoadURL(url1, PageTransition::TYPED);
+ contents->CompleteNavigation(0);
+
+ contents->controller()->Reload();
+
+ // the reload is pending...
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 1);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), 0);
+ EXPECT_TRUE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_TRUE(contents->controller()->GetPendingEntry());
+ EXPECT_FALSE(contents->controller()->CanGoBack());
+ EXPECT_FALSE(contents->controller()->CanGoForward());
+
+ contents->CompleteNavigation(0);
+
+ // now the reload is committed...
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 1);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1);
+ EXPECT_TRUE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_FALSE(contents->controller()->GetPendingEntry());
+ EXPECT_FALSE(contents->controller()->CanGoBack());
+ EXPECT_FALSE(contents->controller()->CanGoForward());
+}
+
+// Tests what happens when a reload navigation produces a new page.
+TEST_F(NavigationControllerTest, Reload_GeneratesNewPage) {
+ const GURL url1("test1:foo1");
+ const GURL url2("test1:foo2");
+
+ contents->controller()->LoadURL(url1, PageTransition::TYPED);
+ contents->CompleteNavigation(0);
+
+ contents->controller()->Reload();
+
+ contents->pending_entry()->SetURL(url2);
+ contents->pending_entry()->SetTransitionType(PageTransition::LINK);
+ contents->CompleteNavigation(1);
+
+ // now the reload is committed...
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 2);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 1);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1);
+ EXPECT_TRUE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_FALSE(contents->controller()->GetPendingEntry());
+ EXPECT_TRUE(contents->controller()->CanGoBack());
+ EXPECT_FALSE(contents->controller()->CanGoForward());
+}
+
+// Tests what happens when we navigate back successfully
+TEST_F(NavigationControllerTest, Back) {
+ const GURL url1("test1:foo1");
+ const GURL url2("test1:foo2");
+
+ contents->controller()->LoadURL(url1, PageTransition::TYPED);
+ contents->CompleteNavigation(0);
+
+ contents->controller()->LoadURL(url2, PageTransition::TYPED);
+ contents->CompleteNavigation(1);
+
+ contents->controller()->GoBack();
+
+ // should now have a pending navigation to go back...
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 2);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 1);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), 0);
+ EXPECT_TRUE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_TRUE(contents->controller()->GetPendingEntry());
+ EXPECT_FALSE(contents->controller()->CanGoBack());
+ EXPECT_TRUE(contents->controller()->CanGoForward());
+
+ contents->CompleteNavigation(0);
+
+ // the back navigation completed successfully
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 2);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1);
+ EXPECT_TRUE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_FALSE(contents->controller()->GetPendingEntry());
+ EXPECT_FALSE(contents->controller()->CanGoBack());
+ EXPECT_TRUE(contents->controller()->CanGoForward());
+}
+
+// Tests what happens when a back navigation produces a new page.
+TEST_F(NavigationControllerTest, Back_GeneratesNewPage) {
+ const GURL url1("test1:foo1");
+ const GURL url2("test1:foo2");
+ const GURL url3("test1:foo3");
+
+ contents->controller()->LoadURL(url1, PageTransition::TYPED);
+ contents->CompleteNavigation(0);
+
+ contents->controller()->LoadURL(url2, PageTransition::TYPED);
+ contents->CompleteNavigation(1);
+
+ contents->controller()->GoBack();
+
+ // should now have a pending navigation to go back...
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 2);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 1);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), 0);
+ EXPECT_TRUE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_TRUE(contents->controller()->GetPendingEntry());
+ EXPECT_FALSE(contents->controller()->CanGoBack());
+ EXPECT_TRUE(contents->controller()->CanGoForward());
+
+ contents->pending_entry()->SetURL(url3);
+ contents->pending_entry()->SetTransitionType(PageTransition::LINK);
+ contents->CompleteNavigation(2);
+
+ // the back navigation resulted in a completely new navigation.
+ // TODO(darin): perhaps this behavior will be confusing to users?
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 3);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 2);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1);
+ EXPECT_TRUE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_FALSE(contents->controller()->GetPendingEntry());
+ EXPECT_TRUE(contents->controller()->CanGoBack());
+ EXPECT_FALSE(contents->controller()->CanGoForward());
+}
+
+// Tests what happens when we navigate forward successfully
+TEST_F(NavigationControllerTest, Forward) {
+ const GURL url1("test1:foo1");
+ const GURL url2("test1:foo2");
+
+ contents->controller()->LoadURL(url1, PageTransition::TYPED);
+ contents->CompleteNavigation(0);
+
+ contents->controller()->LoadURL(url2, PageTransition::TYPED);
+ contents->CompleteNavigation(1);
+
+ contents->controller()->GoBack();
+ contents->CompleteNavigation(0);
+
+ contents->controller()->GoForward();
+
+ // should now have a pending navigation to go forward...
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 2);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), 1);
+ EXPECT_TRUE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_TRUE(contents->controller()->GetPendingEntry());
+ EXPECT_TRUE(contents->controller()->CanGoBack());
+ EXPECT_FALSE(contents->controller()->CanGoForward());
+
+ contents->CompleteNavigation(1);
+
+ // the forward navigation completed successfully
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 2);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 1);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1);
+ EXPECT_TRUE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_FALSE(contents->controller()->GetPendingEntry());
+ EXPECT_TRUE(contents->controller()->CanGoBack());
+ EXPECT_FALSE(contents->controller()->CanGoForward());
+}
+
+// Tests what happens when a forward navigation produces a new page.
+TEST_F(NavigationControllerTest, Forward_GeneratesNewPage) {
+ const GURL url1("test1:foo1");
+ const GURL url2("test1:foo2");
+ const GURL url3("test1:foo3");
+
+ contents->controller()->LoadURL(url1, PageTransition::TYPED);
+ contents->CompleteNavigation(0);
+
+ contents->controller()->LoadURL(url2, PageTransition::TYPED);
+ contents->CompleteNavigation(1);
+
+ contents->controller()->GoBack();
+ contents->CompleteNavigation(0);
+
+ contents->controller()->GoForward();
+
+ // should now have a pending navigation to go forward...
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 2);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), 1);
+ EXPECT_TRUE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_TRUE(contents->controller()->GetPendingEntry());
+ EXPECT_TRUE(contents->controller()->CanGoBack());
+ EXPECT_FALSE(contents->controller()->CanGoForward());
+
+ contents->pending_entry()->SetURL(url3);
+ contents->pending_entry()->SetTransitionType(PageTransition::LINK);
+ contents->CompleteNavigation(2);
+
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 2);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 1);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1);
+ EXPECT_TRUE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_FALSE(contents->controller()->GetPendingEntry());
+ EXPECT_TRUE(contents->controller()->CanGoBack());
+ EXPECT_FALSE(contents->controller()->CanGoForward());
+}
+
+TEST_F(NavigationControllerTest, LinkClick) {
+ const GURL url1("test1:foo1");
+ const GURL url2("test1:foo2");
+
+ contents->controller()->LoadURL(url1, PageTransition::TYPED);
+ contents->CompleteNavigation(0);
+
+ contents->set_pending_entry(new NavigationEntry(kTestContentsType1, NULL, 0,
+ url2,
+ std::wstring(),
+ PageTransition::LINK));
+ contents->CompleteNavigation(1);
+
+ // should not have produced a new session history entry
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 2);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 1);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1);
+ EXPECT_TRUE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_FALSE(contents->controller()->GetPendingEntry());
+ EXPECT_TRUE(contents->controller()->CanGoBack());
+ EXPECT_FALSE(contents->controller()->CanGoForward());
+}
+
+TEST_F(NavigationControllerTest, DISABLED_SwitchTypes) {
+ const GURL url1("test1:foo");
+ const GURL url2("test2:foo");
+
+ contents->controller()->LoadURL(url1, PageTransition::TYPED);
+ contents->CompleteNavigation(0);
+
+ TestContents* initial_contents = contents;
+
+ contents->controller()->LoadURL(url2, PageTransition::TYPED);
+
+ // The tab contents should have been replaced
+ ASSERT_TRUE(initial_contents != contents);
+
+ contents->CompleteNavigation(0);
+
+ // A second navigation entry should have been committed even though the
+ // PageIDs are the same. PageIDs are scoped to the tab contents type.
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 2);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 1);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1);
+ EXPECT_TRUE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_FALSE(contents->controller()->GetPendingEntry());
+ EXPECT_TRUE(contents->controller()->CanGoBack());
+ EXPECT_FALSE(contents->controller()->CanGoForward());
+
+ // Navigate back...
+ contents->controller()->GoBack();
+ ASSERT_TRUE(initial_contents == contents); // switched again!
+ contents->CompleteNavigation(0);
+
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 2);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1);
+ EXPECT_TRUE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_FALSE(contents->controller()->GetPendingEntry());
+ EXPECT_FALSE(contents->controller()->CanGoBack());
+ EXPECT_TRUE(contents->controller()->CanGoForward());
+}
+
+// Tests what happens when we begin to navigate to a new contents type, but
+// then that navigation gets discarded instead.
+TEST_F(NavigationControllerTest, DISABLED_SwitchTypes_Discard) {
+ const GURL url1("test1:foo");
+ const GURL url2("test2:foo");
+
+ contents->controller()->LoadURL(url1, PageTransition::TYPED);
+ contents->CompleteNavigation(0);
+
+ TestContents* initial_contents = contents;
+
+ contents->controller()->LoadURL(url2, PageTransition::TYPED);
+
+ // The tab contents should have been replaced
+ ASSERT_TRUE(initial_contents != contents);
+
+ contents->controller()->DiscardPendingEntry();
+
+ // The tab contents should have been replaced back
+ ASSERT_TRUE(initial_contents == contents);
+
+ EXPECT_EQ(contents->controller()->GetEntryCount(), 1);
+ EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0);
+ EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1);
+ EXPECT_TRUE(contents->controller()->GetLastCommittedEntry());
+ EXPECT_FALSE(contents->controller()->GetPendingEntry());
+ EXPECT_FALSE(contents->controller()->CanGoBack());
+ EXPECT_FALSE(contents->controller()->CanGoForward());
+}
+
+// Tests that we limit the number of navigation entries created correctly.
+TEST_F(NavigationControllerTest, EnforceMaxNavigationCount) {
+ const size_t kMaxEntryCount = 5;
+
+ contents->controller()->max_entry_count_ = kMaxEntryCount;
+
+ int url_index;
+ char buffer[128];
+ // Load up to the max count, all entries should be there.
+ for (url_index = 0; url_index < kMaxEntryCount; url_index++) {
+ SNPrintF(buffer, 128, "test1://www.a.com/%d", url_index);
+ contents->controller()->LoadURL(GURL(buffer), PageTransition::TYPED);
+ contents->CompleteNavigation(url_index);
+ }
+
+ EXPECT_EQ(contents->controller()->GetEntryCount(), kMaxEntryCount);
+
+ // Navigate some more.
+ SNPrintF(buffer, 128, "test1://www.a.com/%d", url_index);
+ contents->controller()->LoadURL(GURL(buffer), PageTransition::TYPED);
+ contents->CompleteNavigation(url_index);
+ url_index++;
+
+ // We expect http://www.a.com/0 to be gone.
+ EXPECT_EQ(contents->controller()->GetEntryCount(), kMaxEntryCount);
+ EXPECT_EQ(contents->controller()->GetEntryAtIndex(0)->GetURL(),
+ GURL("test1://www.a.com/1"));
+
+ // More navigations.
+ for (int i = 0; i < 3; i++) {
+ SNPrintF(buffer, 128, "test1://www.a.com/%d", url_index);
+ contents->controller()->LoadURL(GURL(buffer), PageTransition::TYPED);
+ contents->CompleteNavigation(url_index);
+ url_index++;
+ }
+ EXPECT_EQ(contents->controller()->GetEntryCount(), kMaxEntryCount);
+ EXPECT_EQ(contents->controller()->GetEntryAtIndex(0)->GetURL(),
+ GURL("test1://www.a.com/4"));
+}
+
+// A basic test case. Navigates to a single url, and make sure the history
+// db matches.
+TEST_F(NavigationControllerHistoryTest, Basic) {
+ contents->controller()->LoadURL(url0, PageTransition::TYPED);
+ contents->CompleteNavigation(0);
+
+ GetLastSession();
+
+ helper_.AssertSingleWindowWithSingleTab(windows_, 1);
+ helper_.AssertTabEquals(0, 0, 1, *(windows_[0]->tabs[0]));
+ TabNavigation nav1(0, url0, std::wstring(), std::string(),
+ PageTransition::TYPED);
+ helper_.AssertNavigationEquals(nav1, windows_[0]->tabs[0]->navigations[0]);
+}
+
+// Navigates to three urls, then goes back and make sure the history database
+// is in sync.
+TEST_F(NavigationControllerHistoryTest, NavigationThenBack) {
+ contents->controller()->LoadURL(url0, PageTransition::TYPED);
+ contents->CompleteNavigation(0);
+
+ contents->controller()->LoadURL(url1, PageTransition::TYPED);
+ contents->CompleteNavigation(1);
+
+ contents->controller()->LoadURL(url2, PageTransition::TYPED);
+ contents->CompleteNavigation(2);
+
+ contents->controller()->GoBack();
+ contents->CompleteNavigation(1);
+
+ GetLastSession();
+
+ helper_.AssertSingleWindowWithSingleTab(windows_, 3);
+ helper_.AssertTabEquals(0, 1, 3, *(windows_[0]->tabs[0]));
+
+ TabNavigation nav(0, url0, std::wstring(), std::string(),
+ PageTransition::TYPED);
+ helper_.AssertNavigationEquals(nav, windows_[0]->tabs[0]->navigations[0]);
+ nav.index = 1;
+ nav.url = url1;
+ helper_.AssertNavigationEquals(nav, windows_[0]->tabs[0]->navigations[1]);
+ nav.index = 2;
+ nav.url = url2;
+ helper_.AssertNavigationEquals(nav, windows_[0]->tabs[0]->navigations[2]);
+}
+
+// Navigates to three urls, then goes back twice, then loads a new url.
+TEST_F(NavigationControllerHistoryTest, NavigationPruning) {
+ contents->controller()->LoadURL(url0, PageTransition::TYPED);
+ contents->CompleteNavigation(0);
+
+ contents->controller()->LoadURL(url1, PageTransition::TYPED);
+ contents->CompleteNavigation(1);
+
+ contents->controller()->LoadURL(url2, PageTransition::TYPED);
+ contents->CompleteNavigation(2);
+
+ contents->controller()->GoBack();
+ contents->CompleteNavigation(1);
+
+ contents->controller()->GoBack();
+ contents->CompleteNavigation(0);
+
+ contents->controller()->LoadURL(url2, PageTransition::TYPED);
+ contents->CompleteNavigation(3);
+
+ // Now have url0, and url2.
+
+ GetLastSession();
+
+ helper_.AssertSingleWindowWithSingleTab(windows_, 2);
+ helper_.AssertTabEquals(0, 1, 2, *(windows_[0]->tabs[0]));
+
+ TabNavigation nav(0, url0, std::wstring(), std::string(),
+ PageTransition::TYPED);
+ helper_.AssertNavigationEquals(nav, windows_[0]->tabs[0]->navigations[0]);
+ nav.index = 1;
+ nav.url = url2;
+ helper_.AssertNavigationEquals(nav, windows_[0]->tabs[0]->navigations[1]);
+}