diff options
author | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-19 04:04:16 +0000 |
---|---|---|
committer | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-19 04:04:16 +0000 |
commit | 9dd1d5809c8420f1e636154424826bf575804cdc (patch) | |
tree | 2a9709d108d300c8ee303332674e3468befcaac2 /chrome/browser/sessions | |
parent | a26e6666e814600a133dae854ab6fa0762b0b51f (diff) | |
download | chromium_src-9dd1d5809c8420f1e636154424826bf575804cdc.zip chromium_src-9dd1d5809c8420f1e636154424826bf575804cdc.tar.gz chromium_src-9dd1d5809c8420f1e636154424826bf575804cdc.tar.bz2 |
Move all TabNavigation logic to session_types.{h,cc}
In particular, move the conversion to/from NavigationEntry,
to/from sync_pb::TabNavigation, and pickling/unpickling logic
to member functions of TabNavigation.
Merge TabNavigation and SyncedTabNavigation (i.e., add unique_id and timestamp to TabNavigation).
Mark most TabNavigation accessors ForTest().
Make CreateUpdateTabNavigationCommand() and UpdateTabNavigation() take a TabNavigation instead of an index + NavigationEntry.
Make TabNavigation use default copy constructor and assignment operator. Also do some other misc. cleanups.
Also remove unused field 'unique_id' from sync_pb::TabNavigation.
Use correct indices in session model associator.
Add some unit tests for TabNavigation.
BUG=128449
Review URL: https://chromiumcodereview.appspot.com/10917231
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@157491 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/sessions')
17 files changed, 1036 insertions, 455 deletions
diff --git a/chrome/browser/sessions/DEPS b/chrome/browser/sessions/DEPS index 5a55055..41ea134 100644 --- a/chrome/browser/sessions/DEPS +++ b/chrome/browser/sessions/DEPS @@ -1,4 +1,5 @@ include_rules = [ + "+sync/util/time.h", # For compressing data stored in SessionStorage. "+third_party/bzip2", ] diff --git a/chrome/browser/sessions/base_session_service.cc b/chrome/browser/sessions/base_session_service.cc index fe88ae0..b89c6a3 100644 --- a/chrome/browser/sessions/base_session_service.cc +++ b/chrome/browser/sessions/base_session_service.cc @@ -20,7 +20,6 @@ #include "content/public/common/referrer.h" #include "webkit/glue/webkit_glue.h" -using WebKit::WebReferrerPolicy; using content::BrowserThread; using content::NavigationEntry; @@ -150,52 +149,11 @@ void BaseSessionService::Save() { SessionCommand* BaseSessionService::CreateUpdateTabNavigationCommand( SessionID::id_type command_id, SessionID::id_type tab_id, - int index, - const NavigationEntry& entry) { + const TabNavigation& navigation) { // Use pickle to handle marshalling. Pickle pickle; pickle.WriteInt(tab_id); - pickle.WriteInt(index); - - // We only allow navigations up to 63k (which should be completely - // reasonable). On the off chance we get one that is too big, try to - // keep the url. - - // Bound the string data (which is variable length) to - // |max_state_size bytes| bytes. - static const SessionCommand::size_type max_state_size = - std::numeric_limits<SessionCommand::size_type>::max() - 1024; - - int bytes_written = 0; - - WriteStringToPickle(pickle, &bytes_written, max_state_size, - entry.GetVirtualURL().spec()); - - WriteString16ToPickle(pickle, &bytes_written, max_state_size, - entry.GetTitle()); - - std::string content_state = entry.GetContentState(); - if (entry.GetHasPostData()) { - content_state = - webkit_glue::RemovePasswordDataFromHistoryState(content_state); - } - WriteStringToPickle(pickle, &bytes_written, max_state_size, content_state); - - pickle.WriteInt(entry.GetTransitionType()); - int type_mask = entry.GetHasPostData() ? TabNavigation::HAS_POST_DATA : 0; - pickle.WriteInt(type_mask); - - WriteStringToPickle(pickle, &bytes_written, max_state_size, - entry.GetReferrer().url.is_valid() ? - entry.GetReferrer().url.spec() : std::string()); - pickle.WriteInt(entry.GetReferrer().policy); - - // Save info required to override the user agent. - WriteStringToPickle(pickle, &bytes_written, max_state_size, - entry.GetOriginalRequestURL().is_valid() ? - entry.GetOriginalRequestURL().spec() : std::string()); - pickle.WriteBool(entry.GetIsOverridingUserAgent()); - + navigation.WriteToPickle(&pickle); return new SessionCommand(command_id, pickle); } @@ -266,51 +224,9 @@ bool BaseSessionService::RestoreUpdateTabNavigationCommand( if (!pickle.get()) return false; PickleIterator iterator(*pickle); - std::string url_spec; - if (!pickle->ReadInt(&iterator, tab_id) || - !pickle->ReadInt(&iterator, &(navigation->index_)) || - !pickle->ReadString(&iterator, &url_spec) || - !pickle->ReadString16(&iterator, &(navigation->title_)) || - !pickle->ReadString(&iterator, &(navigation->state_)) || - !pickle->ReadInt(&iterator, - reinterpret_cast<int*>(&(navigation->transition_)))) - return false; - // type_mask did not always exist in the written stream. As such, we - // don't fail if it can't be read. - bool has_type_mask = pickle->ReadInt(&iterator, &(navigation->type_mask_)); - - if (has_type_mask) { - // the "referrer" property was added after type_mask to the written - // stream. As such, we don't fail if it can't be read. - std::string referrer_spec; - pickle->ReadString(&iterator, &referrer_spec); - // The "referrer policy" property was added even later, so we fall back to - // the default policy if the property is not present. - int policy_int; - WebReferrerPolicy policy; - if (pickle->ReadInt(&iterator, &policy_int)) - policy = static_cast<WebReferrerPolicy>(policy_int); - else - policy = WebKit::WebReferrerPolicyDefault; - navigation->referrer_ = content::Referrer( - referrer_spec.empty() ? GURL() : GURL(referrer_spec), - policy); - - // If the original URL can't be found, leave it empty. - std::string url_spec; - if (!pickle->ReadString(&iterator, &url_spec)) - url_spec = std::string(); - navigation->set_original_request_url(GURL(url_spec)); - - // Default to not overriding the user agent if we don't have info. - bool override_user_agent; - if (!pickle->ReadBool(&iterator, &override_user_agent)) - override_user_agent = false; - navigation->set_is_overriding_user_agent(override_user_agent); - } - - navigation->virtual_url_ = GURL(url_spec); - return true; + return + pickle->ReadInt(&iterator, tab_id) && + navigation->ReadFromPickle(&iterator); } bool BaseSessionService::RestoreSetTabExtensionAppIDCommand( diff --git a/chrome/browser/sessions/base_session_service.h b/chrome/browser/sessions/base_session_service.h index 2fd043a..ce0253d 100644 --- a/chrome/browser/sessions/base_session_service.h +++ b/chrome/browser/sessions/base_session_service.h @@ -22,10 +22,6 @@ class SessionBackend; class SessionCommand; class TabNavigation; -namespace content { -class NavigationEntry; -} - // BaseSessionService is the super class of both tab restore service and // session service. It contains commonality needed by both, in particular // it manages a set of SessionCommands that are periodically sent to a @@ -113,8 +109,7 @@ class BaseSessionService : public CancelableRequestProvider, SessionCommand* CreateUpdateTabNavigationCommand( SessionID::id_type command_id, SessionID::id_type tab_id, - int index, - const content::NavigationEntry& entry); + const TabNavigation& navigation); // Creates a SessionCommand that represents marking a tab as an application. SessionCommand* CreateSetTabExtensionAppIDCommand( diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc index adab427..c9145ba 100644 --- a/chrome/browser/sessions/session_restore.cc +++ b/chrome/browser/sessions/session_restore.cc @@ -947,7 +947,7 @@ class SessionRestoreImpl : public content::NotificationObserver { base::PLATFORM_FILE_EXCLUSIVE_READ | base::PLATFORM_FILE_ASYNC; const std::string& state = - tab.navigations.at(selected_index).state(); + tab.navigations.at(selected_index).content_state(); const std::vector<FilePath>& file_paths = webkit_glue::FilePathsFromHistoryState(state); for (std::vector<FilePath>::const_iterator file = file_paths.begin(); diff --git a/chrome/browser/sessions/session_restore_android.cc b/chrome/browser/sessions/session_restore_android.cc index 41b3c06..836ff0c 100644 --- a/chrome/browser/sessions/session_restore_android.cc +++ b/chrome/browser/sessions/session_restore_android.cc @@ -26,9 +26,9 @@ void SessionRestore::RestoreForeignSessionTab( Profile* profile = Profile::FromBrowserContext(context); TabModel* tab_model = TabModelList::GetTabModelWithProfile(profile); DCHECK(tab_model); - std::vector<content::NavigationEntry*> entries; - TabNavigation::CreateNavigationEntriesFromTabNavigations( - profile, session_tab.navigations, &entries); + std::vector<content::NavigationEntry*> entries = + TabNavigation::CreateNavigationEntriesFromTabNavigations( + session_tab.navigations, profile); content::WebContents* new_web_contents = content::WebContents::Create( context, NULL, MSG_ROUTING_NONE, NULL); int selected_index = session_tab.normalized_navigation_index(); diff --git a/chrome/browser/sessions/session_restore_browsertest.cc b/chrome/browser/sessions/session_restore_browsertest.cc index 76620e2..7c75e1d 100644 --- a/chrome/browser/sessions/session_restore_browsertest.cc +++ b/chrome/browser/sessions/session_restore_browsertest.cc @@ -14,6 +14,8 @@ #include "chrome/browser/sessions/session_service.h" #include "chrome/browser/sessions/session_service_factory.h" #include "chrome/browser/sessions/session_service_test_helper.h" +#include "chrome/browser/sessions/session_types.h" +#include "chrome/browser/sessions/session_types_test_helper.h" #include "chrome/browser/sessions/tab_restore_service.h" #include "chrome/browser/sessions/tab_restore_service_factory.h" #include "chrome/browser/ui/browser.h" @@ -387,10 +389,11 @@ IN_PROC_BROWSER_TEST_F(SessionRestoreTest, IncognitotoNonIncognito) { IN_PROC_BROWSER_TEST_F(SessionRestoreTest, RestoreForeignTab) { GURL url1("http://google.com"); GURL url2("http://google2.com"); - TabNavigation nav1(0, url1, content::Referrer(), ASCIIToUTF16("one"), - std::string(), content::PAGE_TRANSITION_TYPED); - TabNavigation nav2(0, url2, content::Referrer(), ASCIIToUTF16("two"), - std::string(), content::PAGE_TRANSITION_TYPED); + TabNavigation nav1 = + SessionTypesTestHelper::CreateNavigation(url1.spec(), "one"); + TabNavigation nav2 = + SessionTypesTestHelper::CreateNavigation(url2.spec(), "two"); + SessionTypesTestHelper::SetIsOverridingUserAgent(&nav2, true); // Set up the restore data. SessionTab tab; @@ -450,12 +453,10 @@ IN_PROC_BROWSER_TEST_F(SessionRestoreTest, RestoreForeignSession) { GURL url1("http://google.com"); GURL url2("http://google2.com"); - TabNavigation nav1(0, url1, content::Referrer(), ASCIIToUTF16("one"), - std::string(), content::PAGE_TRANSITION_TYPED); - TabNavigation nav2(0, url2, content::Referrer(), ASCIIToUTF16("two"), - std::string(), content::PAGE_TRANSITION_TYPED); - nav1.set_is_overriding_user_agent(false); - nav2.set_is_overriding_user_agent(true); + TabNavigation nav1 = + SessionTypesTestHelper::CreateNavigation(url1.spec(), "one"); + TabNavigation nav2 = + SessionTypesTestHelper::CreateNavigation(url2.spec(), "two"); // Set up the restore data -- one window with two tabs. std::vector<const SessionWindow*> session; @@ -499,11 +500,13 @@ IN_PROC_BROWSER_TEST_F(SessionRestoreTest, RestoreForeignSession) { content::NavigationEntry* entry = web_contents_1->GetController().GetActiveEntry(); ASSERT_TRUE(entry); - ASSERT_EQ(nav1.is_overriding_user_agent(), entry->GetIsOverridingUserAgent()); + ASSERT_EQ(SessionTypesTestHelper::GetIsOverridingUserAgent(nav1), + entry->GetIsOverridingUserAgent()); entry = web_contents_2->GetController().GetActiveEntry(); ASSERT_TRUE(entry); - ASSERT_EQ(nav2.is_overriding_user_agent(), entry->GetIsOverridingUserAgent()); + ASSERT_EQ(SessionTypesTestHelper::GetIsOverridingUserAgent(nav2), + entry->GetIsOverridingUserAgent()); // The SessionWindow destructor deletes the tabs, so we have to clear them // here to avoid a crash. diff --git a/chrome/browser/sessions/session_service.cc b/chrome/browser/sessions/session_service.cc index 3e4961d..eb406fc 100644 --- a/chrome/browser/sessions/session_service.cc +++ b/chrome/browser/sessions/session_service.cc @@ -430,9 +430,8 @@ void SessionService::TabNavigationPathPrunedFromFront( void SessionService::UpdateTabNavigation( const SessionID& window_id, const SessionID& tab_id, - int index, - const NavigationEntry& entry) { - if (!ShouldTrackEntry(entry.GetVirtualURL()) || + const TabNavigation& navigation) { + if (!ShouldTrackEntry(navigation.virtual_url()) || !ShouldTrackChangesToWindow(window_id)) { return; } @@ -440,11 +439,11 @@ void SessionService::UpdateTabNavigation( if (tab_to_available_range_.find(tab_id.id()) != tab_to_available_range_.end()) { std::pair<int, int>& range = tab_to_available_range_[tab_id.id()]; - range.first = std::min(index, range.first); - range.second = std::max(index, range.second); + range.first = std::min(navigation.index(), range.first); + range.second = std::max(navigation.index(), range.second); } ScheduleCommand(CreateUpdateTabNavigationCommand(kCommandUpdateTabNavigation, - tab_id.id(), index, entry)); + tab_id.id(), navigation)); } void SessionService::TabRestored(TabContents* tab, bool pinned) { @@ -689,9 +688,13 @@ void SessionService::Observe(int type, if (!session_tab_helper || web_contents->GetBrowserContext() != profile()) return; content::Details<content::EntryChangedDetails> changed(details); + const TabNavigation navigation = + TabNavigation::FromNavigationEntry( + changed->index, *changed->changed_entry, + base::Time::Now()); UpdateTabNavigation(session_tab_helper->window_id(), session_tab_helper->session_id(), - changed->index, *changed->changed_entry); + navigation); break; } @@ -709,11 +712,16 @@ void SessionService::Observe(int type, session_tab_helper->window_id(), session_tab_helper->session_id(), current_entry_index); + const TabNavigation navigation = + TabNavigation::FromNavigationEntry( + current_entry_index, + *web_contents->GetController().GetEntryAtIndex( + current_entry_index), + base::Time::Now()); UpdateTabNavigation( session_tab_helper->window_id(), session_tab_helper->session_id(), - current_entry_index, - *web_contents->GetController().GetEntryAtIndex(current_entry_index)); + navigation); content::Details<content::LoadCommittedDetails> changed(details); if (changed->type == content::NAVIGATION_TYPE_NEW_PAGE || changed->type == content::NAVIGATION_TYPE_EXISTING_PAGE) { @@ -1352,9 +1360,11 @@ void SessionService::BuildCommandsForTab( tab->web_contents()->GetController().GetEntryAtIndex(i); DCHECK(entry); if (ShouldTrackEntry(entry->GetVirtualURL())) { + const TabNavigation navigation = + TabNavigation::FromNavigationEntry(i, *entry, base::Time::Now()); commands->push_back( CreateUpdateTabNavigationCommand( - kCommandUpdateTabNavigation, session_id.id(), i, *entry)); + kCommandUpdateTabNavigation, session_id.id(), navigation)); } } commands->push_back( diff --git a/chrome/browser/sessions/session_service.h b/chrome/browser/sessions/session_service.h index 74512c4..b106640 100644 --- a/chrome/browser/sessions/session_service.h +++ b/chrome/browser/sessions/session_service.h @@ -149,8 +149,7 @@ class SessionService : public BaseSessionService, // Updates the navigation entry for the specified tab. void UpdateTabNavigation(const SessionID& window_id, const SessionID& tab_id, - int index, - const content::NavigationEntry& entry); + const TabNavigation& navigation); // Notification that a tab has restored its entries or a closed tab is being // reused. diff --git a/chrome/browser/sessions/session_service_test_helper.cc b/chrome/browser/sessions/session_service_test_helper.cc index 3f02a4c..62aac7c 100644 --- a/chrome/browser/sessions/session_service_test_helper.cc +++ b/chrome/browser/sessions/session_service_test_helper.cc @@ -9,6 +9,7 @@ #include "chrome/browser/sessions/session_id.h" #include "chrome/browser/sessions/session_service.h" #include "chrome/browser/sessions/session_types.h" +#include "chrome/browser/sessions/session_types_test_helper.h" #include "testing/gtest/include/gtest/gtest.h" using base::Time; @@ -89,16 +90,7 @@ void SessionServiceTestHelper::AssertTabEquals( void SessionServiceTestHelper::AssertNavigationEquals( const TabNavigation& expected, const TabNavigation& actual) { - EXPECT_TRUE(expected.virtual_url() == actual.virtual_url()); - EXPECT_EQ(expected.referrer().url, actual.referrer().url); - EXPECT_EQ(expected.referrer().policy, actual.referrer().policy); - EXPECT_EQ(expected.title(), actual.title()); - EXPECT_EQ(expected.state(), actual.state()); - EXPECT_EQ(expected.transition(), actual.transition()); - EXPECT_EQ(expected.type_mask(), actual.type_mask()); - EXPECT_TRUE(expected.original_request_url() == actual.original_request_url()); - EXPECT_EQ(expected.is_overriding_user_agent(), - actual.is_overriding_user_agent()); + SessionTypesTestHelper::ExpectNavigationEquals(expected, actual); } void SessionServiceTestHelper::AssertSingleWindowWithSingleTab( diff --git a/chrome/browser/sessions/session_service_unittest.cc b/chrome/browser/sessions/session_service_unittest.cc index 748ee7a..3152b3b 100644 --- a/chrome/browser/sessions/session_service_unittest.cc +++ b/chrome/browser/sessions/session_service_unittest.cc @@ -18,6 +18,7 @@ #include "chrome/browser/sessions/session_service.h" #include "chrome/browser/sessions/session_service_test_helper.h" #include "chrome/browser/sessions/session_types.h" +#include "chrome/browser/sessions/session_types_test_helper.h" #include "chrome/common/chrome_notification_types.h" #include "chrome/common/chrome_paths.h" #include "chrome/test/base/browser_with_test_window_test.h" @@ -75,21 +76,12 @@ class SessionServiceTest : public BrowserWithTestWindowTest, void UpdateNavigation(const SessionID& window_id, const SessionID& tab_id, const TabNavigation& navigation, - int index, bool select) { - scoped_ptr<NavigationEntry> entry(NavigationEntry::Create()); - entry->SetURL(navigation.virtual_url()); - entry->SetReferrer(navigation.referrer()); - entry->SetTitle(navigation.title()); - entry->SetContentState(navigation.state()); - entry->SetTransitionType(navigation.transition()); - entry->SetHasPostData( - navigation.type_mask() & TabNavigation::HAS_POST_DATA); - entry->SetOriginalRequestURL(navigation.original_request_url()); - entry->SetIsOverridingUserAgent(navigation.is_overriding_user_agent()); - service()->UpdateTabNavigation(window_id, tab_id, index, *entry.get()); - if (select) - service()->SetSelectedNavigationIndex(window_id, tab_id, index); + service()->UpdateTabNavigation(window_id, tab_id, navigation); + if (select) { + service()->SetSelectedNavigationIndex( + window_id, tab_id, navigation.index()); + } } void ReadWindows(std::vector<SessionWindow*>* windows) { @@ -107,14 +99,11 @@ class SessionServiceTest : public BrowserWithTestWindowTest, // and the pinned state of the read back tab is returned. bool CreateAndWriteSessionWithOneTab(bool pinned_state, bool write_always) { SessionID tab_id; - TabNavigation nav1(0, GURL("http://google.com"), - content::Referrer(GURL("http://www.referrer.com"), - WebKit::WebReferrerPolicyDefault), - ASCIIToUTF16("abc"), "def", - content::PAGE_TRANSITION_QUALIFIER_MASK); + TabNavigation nav1 = + SessionTypesTestHelper::CreateNavigation("http://google.com", "abc"); helper_.PrepareTabInWindow(window_id, tab_id, 0, true); - UpdateNavigation(window_id, tab_id, nav1, 0, true); + UpdateNavigation(window_id, tab_id, nav1, true); if (pinned_state || write_always) helper_.service()->SetPinnedState(window_id, tab_id, pinned_state); @@ -156,15 +145,13 @@ TEST_F(SessionServiceTest, Basic) { SessionID tab_id; ASSERT_NE(window_id.id(), tab_id.id()); - TabNavigation nav1(0, GURL("http://google.com"), - content::Referrer(GURL("http://www.referrer.com"), - WebKit::WebReferrerPolicyDefault), - ASCIIToUTF16("abc"), "def", - content::PAGE_TRANSITION_QUALIFIER_MASK); - nav1.set_original_request_url(GURL("http://original.request.com")); + TabNavigation nav1 = + SessionTypesTestHelper::CreateNavigation("http://google.com", "abc"); + SessionTypesTestHelper::SetOriginalRequestURL( + &nav1, GURL("http://original.request.com")); helper_.PrepareTabInWindow(window_id, tab_id, 0, true); - UpdateNavigation(window_id, tab_id, nav1, 0, true); + UpdateNavigation(window_id, tab_id, nav1, true); ScopedVector<SessionWindow> windows; ReadWindows(&(windows.get())); @@ -187,13 +174,12 @@ TEST_F(SessionServiceTest, PersistPostData) { SessionID tab_id; ASSERT_NE(window_id.id(), tab_id.id()); - TabNavigation nav1(0, GURL("http://google.com"), content::Referrer(), - ASCIIToUTF16("abc"), std::string(), - content::PAGE_TRANSITION_QUALIFIER_MASK); - nav1.set_type_mask(TabNavigation::HAS_POST_DATA); + TabNavigation nav1 = + SessionTypesTestHelper::CreateNavigation("http://google.com", "abc"); + SessionTypesTestHelper::SetHasPostData(&nav1, true); helper_.PrepareTabInWindow(window_id, tab_id, 0, true); - UpdateNavigation(window_id, tab_id, nav1, 0, true); + UpdateNavigation(window_id, tab_id, nav1, true); ScopedVector<SessionWindow> windows; ReadWindows(&(windows.get())); @@ -206,18 +192,16 @@ TEST_F(SessionServiceTest, ClosingTabStaysClosed) { SessionID tab2_id; ASSERT_NE(tab_id.id(), tab2_id.id()); - TabNavigation nav1(0, GURL("http://google.com"), content::Referrer(), - ASCIIToUTF16("abc"), "def", - content::PAGE_TRANSITION_QUALIFIER_MASK); - TabNavigation nav2(0, GURL("http://google2.com"), content::Referrer(), - ASCIIToUTF16("abcd"), "defg", - content::PAGE_TRANSITION_AUTO_BOOKMARK); + TabNavigation nav1 = + SessionTypesTestHelper::CreateNavigation("http://google.com", "abc"); + TabNavigation nav2 = + SessionTypesTestHelper::CreateNavigation("http://google2.com", "abcd"); helper_.PrepareTabInWindow(window_id, tab_id, 0, true); - UpdateNavigation(window_id, tab_id, nav1, 0, true); + UpdateNavigation(window_id, tab_id, nav1, true); helper_.PrepareTabInWindow(window_id, tab2_id, 1, false); - UpdateNavigation(window_id, tab2_id, nav2, 0, true); + UpdateNavigation(window_id, tab2_id, nav2, true); service()->TabClosed(window_id, tab2_id, false); ScopedVector<SessionWindow> windows; @@ -237,17 +221,16 @@ TEST_F(SessionServiceTest, ClosingTabStaysClosed) { TEST_F(SessionServiceTest, Pruning) { SessionID tab_id; - TabNavigation nav1(0, GURL("http://google.com"), content::Referrer(), - ASCIIToUTF16("abc"), "def", - content::PAGE_TRANSITION_QUALIFIER_MASK); - TabNavigation nav2(0, GURL("http://google2.com"), content::Referrer(), - ASCIIToUTF16("abcd"), "defg", - content::PAGE_TRANSITION_AUTO_BOOKMARK); + TabNavigation nav1 = + SessionTypesTestHelper::CreateNavigation("http://google.com", "abc"); + TabNavigation nav2 = + SessionTypesTestHelper::CreateNavigation("http://google2.com", "abcd"); helper_.PrepareTabInWindow(window_id, tab_id, 0, true); for (int i = 0; i < 6; ++i) { - TabNavigation& nav = (i % 2) == 0 ? nav1 : nav2; - UpdateNavigation(window_id, tab_id, nav, i, true); + TabNavigation* nav = (i % 2) == 0 ? &nav1 : &nav2; + nav->set_index(i); + UpdateNavigation(window_id, tab_id, *nav, true); } service()->TabNavigationPathPrunedFromBack(window_id, tab_id, 3); @@ -263,6 +246,7 @@ TEST_F(SessionServiceTest, Pruning) { // index should get reset to last valid navigation, which is 2. helper_.AssertTabEquals(window_id, tab_id, 0, 2, 3, *tab); + ASSERT_EQ(3u, tab->navigations.size()); helper_.AssertNavigationEquals(nav1, tab->navigations[0]); helper_.AssertNavigationEquals(nav2, tab->navigations[1]); helper_.AssertNavigationEquals(nav1, tab->navigations[2]); @@ -273,15 +257,13 @@ TEST_F(SessionServiceTest, TwoWindows) { SessionID tab1_id; SessionID tab2_id; - TabNavigation nav1(0, GURL("http://google.com"), content::Referrer(), - ASCIIToUTF16("abc"), "def", - content::PAGE_TRANSITION_QUALIFIER_MASK); - TabNavigation nav2(0, GURL("http://google2.com"), content::Referrer(), - ASCIIToUTF16("abcd"), "defg", - content::PAGE_TRANSITION_AUTO_BOOKMARK); + TabNavigation nav1 = + SessionTypesTestHelper::CreateNavigation("http://google.com", "abc"); + TabNavigation nav2 = + SessionTypesTestHelper::CreateNavigation("http://google2.com", "abcd"); helper_.PrepareTabInWindow(window_id, tab1_id, 0, true); - UpdateNavigation(window_id, tab1_id, nav1, 0, true); + UpdateNavigation(window_id, tab1_id, nav1, true); const gfx::Rect window2_bounds(3, 4, 5, 6); service()->SetWindowType( @@ -290,7 +272,7 @@ TEST_F(SessionServiceTest, TwoWindows) { window2_bounds, ui::SHOW_STATE_MAXIMIZED); helper_.PrepareTabInWindow(window2_id, tab2_id, 0, true); - UpdateNavigation(window2_id, tab2_id, nav2, 0, true); + UpdateNavigation(window2_id, tab2_id, nav2, true); ScopedVector<SessionWindow> windows; ReadWindows(&(windows.get())); @@ -331,12 +313,11 @@ TEST_F(SessionServiceTest, WindowWithNoTabsGetsPruned) { SessionID tab1_id; SessionID tab2_id; - TabNavigation nav1(0, GURL("http://google.com"), content::Referrer(), - ASCIIToUTF16("abc"), "def", - content::PAGE_TRANSITION_QUALIFIER_MASK); + TabNavigation nav1 = + SessionTypesTestHelper::CreateNavigation("http://google.com", "abc"); helper_.PrepareTabInWindow(window_id, tab1_id, 0, true); - UpdateNavigation(window_id, tab1_id, nav1, 0, true); + UpdateNavigation(window_id, tab1_id, nav1, true); const gfx::Rect window2_bounds(3, 4, 5, 6); service()->SetWindowType( @@ -364,18 +345,16 @@ TEST_F(SessionServiceTest, ClosingWindowDoesntCloseTabs) { SessionID tab2_id; ASSERT_NE(tab_id.id(), tab2_id.id()); - TabNavigation nav1(0, GURL("http://google.com"), content::Referrer(), - ASCIIToUTF16("abc"), "def", - content::PAGE_TRANSITION_QUALIFIER_MASK); - TabNavigation nav2(0, GURL("http://google2.com"), content::Referrer(), - ASCIIToUTF16("abcd"), "defg", - content::PAGE_TRANSITION_AUTO_BOOKMARK); + TabNavigation nav1 = + SessionTypesTestHelper::CreateNavigation("http://google.com", "abc"); + TabNavigation nav2 = + SessionTypesTestHelper::CreateNavigation("http://google2.com", "abcd"); helper_.PrepareTabInWindow(window_id, tab_id, 0, true); - UpdateNavigation(window_id, tab_id, nav1, 0, true); + UpdateNavigation(window_id, tab_id, nav1, true); helper_.PrepareTabInWindow(window_id, tab2_id, 1, false); - UpdateNavigation(window_id, tab2_id, nav2, 0, true); + UpdateNavigation(window_id, tab2_id, nav2, true); service()->WindowClosing(window_id); @@ -408,18 +387,16 @@ TEST_F(SessionServiceTest, WindowCloseCommittedAfterNavigate) { window_bounds, ui::SHOW_STATE_NORMAL); - TabNavigation nav1(0, GURL("http://google.com"), content::Referrer(), - ASCIIToUTF16("abc"), "def", - content::PAGE_TRANSITION_QUALIFIER_MASK); - TabNavigation nav2(0, GURL("http://google2.com"), content::Referrer(), - ASCIIToUTF16("abcd"), "defg", - content::PAGE_TRANSITION_AUTO_BOOKMARK); + TabNavigation nav1 = + SessionTypesTestHelper::CreateNavigation("http://google.com", "abc"); + TabNavigation nav2 = + SessionTypesTestHelper::CreateNavigation("http://google2.com", "abcd"); helper_.PrepareTabInWindow(window_id, tab_id, 0, true); - UpdateNavigation(window_id, tab_id, nav1, 0, true); + UpdateNavigation(window_id, tab_id, nav1, true); helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false); - UpdateNavigation(window2_id, tab2_id, nav2, 0, true); + UpdateNavigation(window2_id, tab2_id, nav2, true); service()->WindowClosing(window2_id); service()->TabClosed(window2_id, tab2_id, false); @@ -454,18 +431,16 @@ TEST_F(SessionServiceTest, IgnorePopups) { window_bounds, ui::SHOW_STATE_NORMAL); - TabNavigation nav1(0, GURL("http://google.com"), content::Referrer(), - ASCIIToUTF16("abc"), "def", - content::PAGE_TRANSITION_QUALIFIER_MASK); - TabNavigation nav2(0, GURL("http://google2.com"), content::Referrer(), - ASCIIToUTF16("abcd"), "defg", - content::PAGE_TRANSITION_AUTO_BOOKMARK); + TabNavigation nav1 = + SessionTypesTestHelper::CreateNavigation("http://google.com", "abc"); + TabNavigation nav2 = + SessionTypesTestHelper::CreateNavigation("http://google2.com", "abcd"); helper_.PrepareTabInWindow(window_id, tab_id, 0, true); - UpdateNavigation(window_id, tab_id, nav1, 0, true); + UpdateNavigation(window_id, tab_id, nav1, true); helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false); - UpdateNavigation(window2_id, tab2_id, nav2, 0, true); + UpdateNavigation(window2_id, tab2_id, nav2, true); ScopedVector<SessionWindow> windows; ReadWindows(&(windows.get())); @@ -496,18 +471,16 @@ TEST_F(SessionServiceTest, RestorePopup) { window_bounds, ui::SHOW_STATE_NORMAL); - TabNavigation nav1(0, GURL("http://google.com"), content::Referrer(), - ASCIIToUTF16("abc"), "def", - content::PAGE_TRANSITION_QUALIFIER_MASK); - TabNavigation nav2(0, GURL("http://google2.com"), content::Referrer(), - ASCIIToUTF16("abcd"), "defg", - content::PAGE_TRANSITION_AUTO_BOOKMARK); + TabNavigation nav1 = + SessionTypesTestHelper::CreateNavigation("http://google.com", "abc"); + TabNavigation nav2 = + SessionTypesTestHelper::CreateNavigation("http://google2.com", "abcd"); helper_.PrepareTabInWindow(window_id, tab_id, 0, true); - UpdateNavigation(window_id, tab_id, nav1, 0, true); + UpdateNavigation(window_id, tab_id, nav1, true); helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false); - UpdateNavigation(window2_id, tab2_id, nav2, 0, true); + UpdateNavigation(window2_id, tab2_id, nav2, true); ScopedVector<SessionWindow> windows; ReadWindows(&(windows.get())); @@ -548,18 +521,16 @@ TEST_F(SessionServiceTest, RestoreApp) { ui::SHOW_STATE_NORMAL); service()->SetWindowAppName(window2_id, "TestApp"); - TabNavigation nav1(0, GURL("http://google.com"), content::Referrer(), - ASCIIToUTF16("abc"), "def", - content::PAGE_TRANSITION_QUALIFIER_MASK); - TabNavigation nav2(0, GURL("http://google2.com"), content::Referrer(), - ASCIIToUTF16("abcd"), "defg", - content::PAGE_TRANSITION_AUTO_BOOKMARK); + TabNavigation nav1 = + SessionTypesTestHelper::CreateNavigation("http://google.com", "abc"); + TabNavigation nav2 = + SessionTypesTestHelper::CreateNavigation("http://google2.com", "abcd"); helper_.PrepareTabInWindow(window_id, tab_id, 0, true); - UpdateNavigation(window_id, tab_id, nav1, 0, true); + UpdateNavigation(window_id, tab_id, nav1, true); helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false); - UpdateNavigation(window2_id, tab2_id, nav2, 0, true); + UpdateNavigation(window2_id, tab2_id, nav2, true); ScopedVector<SessionWindow> windows; ReadWindows(&(windows.get())); @@ -597,11 +568,11 @@ TEST_F(SessionServiceTest, PruneFromFront) { // Add 5 navigations, with the 4th selected. for (int i = 0; i < 5; ++i) { - TabNavigation nav(0, GURL(base_url + base::IntToString(i)), - content::Referrer(), - ASCIIToUTF16("a"), "b", - content::PAGE_TRANSITION_QUALIFIER_MASK); - UpdateNavigation(window_id, tab_id, nav, i, (i == 3)); + TabNavigation nav = + SessionTypesTestHelper::CreateNavigation( + base_url + base::IntToString(i), "a"); + nav.set_index(i); + UpdateNavigation(window_id, tab_id, nav, (i == 3)); } // Prune the first two navigations from the front. @@ -640,11 +611,11 @@ TEST_F(SessionServiceTest, PruneToEmpty) { // Add 5 navigations, with the 4th selected. for (int i = 0; i < 5; ++i) { - TabNavigation nav(0, GURL(base_url + base::IntToString(i)), - content::Referrer(), - ASCIIToUTF16("a"), "b", - content::PAGE_TRANSITION_QUALIFIER_MASK); - UpdateNavigation(window_id, tab_id, nav, i, (i == 3)); + TabNavigation nav = + SessionTypesTestHelper::CreateNavigation( + base_url + base::IntToString(i), "a"); + nav.set_index(i); + UpdateNavigation(window_id, tab_id, nav, (i == 3)); } // Prune the first two navigations from the front. @@ -678,12 +649,11 @@ TEST_F(SessionServiceTest, PersistApplicationExtensionID) { ASSERT_NE(window_id.id(), tab_id.id()); std::string app_id("foo"); - TabNavigation nav1(0, GURL("http://google.com"), content::Referrer(), - ASCIIToUTF16("abc"), std::string(), - content::PAGE_TRANSITION_QUALIFIER_MASK); + TabNavigation nav1 = + SessionTypesTestHelper::CreateNavigation("http://google.com", "abc"); helper_.PrepareTabInWindow(window_id, tab_id, 0, true); - UpdateNavigation(window_id, tab_id, nav1, 0, true); + UpdateNavigation(window_id, tab_id, nav1, true); helper_.SetTabExtensionAppID(window_id, tab_id, app_id); ScopedVector<SessionWindow> windows; @@ -701,13 +671,12 @@ TEST_F(SessionServiceTest, PersistUserAgentOverrides) { "AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.45 " "Safari/535.19"; - TabNavigation nav1(0, GURL("http://google.com"), content::Referrer(), - ASCIIToUTF16("abc"), std::string(), - content::PAGE_TRANSITION_QUALIFIER_MASK); - nav1.set_is_overriding_user_agent(true); + TabNavigation nav1 = + SessionTypesTestHelper::CreateNavigation("http://google.com", "abc"); + SessionTypesTestHelper::SetIsOverridingUserAgent(&nav1, true); helper_.PrepareTabInWindow(window_id, tab_id, 0, true); - UpdateNavigation(window_id, tab_id, nav1, 0, true); + UpdateNavigation(window_id, tab_id, nav1, true); helper_.SetTabUserAgentOverride(window_id, tab_id, user_agent_override); ScopedVector<SessionWindow> windows; @@ -734,14 +703,11 @@ TEST_F(SessionServiceTest, CloseTabUserGesture) { SessionID tab_id; ASSERT_NE(window_id.id(), tab_id.id()); - TabNavigation nav1(0, GURL("http://google.com"), - content::Referrer(GURL("http://www.referrer.com"), - WebKit::WebReferrerPolicyDefault), - ASCIIToUTF16("abc"), "def", - content::PAGE_TRANSITION_QUALIFIER_MASK); + TabNavigation nav1 = + SessionTypesTestHelper::CreateNavigation("http://google.com", "abc"); helper_.PrepareTabInWindow(window_id, tab_id, 0, true); - UpdateNavigation(window_id, tab_id, nav1, 0, true); + UpdateNavigation(window_id, tab_id, nav1, true); service()->TabClosed(window_id, tab_id, true); ScopedVector<SessionWindow> windows; @@ -754,13 +720,10 @@ TEST_F(SessionServiceTest, CloseTabUserGesture) { TEST_F(SessionServiceTest, DontPersistDefault) { SessionID tab_id; ASSERT_NE(window_id.id(), tab_id.id()); - TabNavigation nav1(0, GURL("http://google.com"), - content::Referrer(GURL("http://www.referrer.com"), - WebKit::WebReferrerPolicyDefault), - ASCIIToUTF16("abc"), "def", - content::PAGE_TRANSITION_QUALIFIER_MASK); + TabNavigation nav1 = + SessionTypesTestHelper::CreateNavigation("http://google.com", "abc"); helper_.PrepareTabInWindow(window_id, tab_id, 0, true); - UpdateNavigation(window_id, tab_id, nav1, 0, true); + UpdateNavigation(window_id, tab_id, nav1, true); service()->SetWindowBounds(window_id, window_bounds, ui::SHOW_STATE_DEFAULT); @@ -787,20 +750,22 @@ TEST_F(SessionServiceTest, KeepPostDataWithoutPasswords) { // Create a TabNavigation containing content_state and representing a POST // request. - TabNavigation nav1(0, GURL("http://google.com"), content::Referrer(), - ASCIIToUTF16("title"), content_state, - content::PAGE_TRANSITION_QUALIFIER_MASK); - nav1.set_type_mask(TabNavigation::HAS_POST_DATA); + TabNavigation nav1 = + SessionTypesTestHelper::CreateNavigation("http://google.com", "title"); + SessionTypesTestHelper::SetContentState(&nav1, content_state); + SessionTypesTestHelper::SetHasPostData(&nav1, true); // Create a TabNavigation containing content_state and representing a normal // request. - TabNavigation nav2(0, GURL("http://google.com/nopost"), content::Referrer(), - ASCIIToUTF16("title"), content_state, - content::PAGE_TRANSITION_QUALIFIER_MASK); + TabNavigation nav2 = + SessionTypesTestHelper::CreateNavigation( + "http://google.com/nopost", "title"); + SessionTypesTestHelper::SetContentState(&nav2, content_state); + nav2.set_index(1); helper_.PrepareTabInWindow(window_id, tab_id, 0, true); - UpdateNavigation(window_id, tab_id, nav1, 0, true); - UpdateNavigation(window_id, tab_id, nav2, 1, true); + UpdateNavigation(window_id, tab_id, nav1, true); + UpdateNavigation(window_id, tab_id, nav2, true); ScopedVector<SessionWindow> windows; ReadWindows(&(windows.get())); @@ -808,6 +773,7 @@ TEST_F(SessionServiceTest, KeepPostDataWithoutPasswords) { helper_.AssertSingleWindowWithSingleTab(windows.get(), 2); // Expected: the content state of both navigations was saved and restored. + ASSERT_EQ(2u, windows[0]->tabs[0]->navigations.size()); helper_.AssertNavigationEquals(nav1, windows[0]->tabs[0]->navigations[0]); helper_.AssertNavigationEquals(nav2, windows[0]->tabs[0]->navigations[1]); } @@ -829,12 +795,12 @@ TEST_F(SessionServiceTest, RemovePostDataWithPasswords) { // Create a TabNavigation containing content_state and representing a POST // request with passwords. - TabNavigation nav1(0, GURL("http://google.com"), content::Referrer(), - ASCIIToUTF16("title"), content_state, - content::PAGE_TRANSITION_QUALIFIER_MASK); - nav1.set_type_mask(TabNavigation::HAS_POST_DATA); + TabNavigation nav1 = + SessionTypesTestHelper::CreateNavigation("http://google.com", "title"); + SessionTypesTestHelper::SetContentState(&nav1, content_state); + SessionTypesTestHelper::SetHasPostData(&nav1, true); helper_.PrepareTabInWindow(window_id, tab_id, 0, true); - UpdateNavigation(window_id, tab_id, nav1, 0, true); + UpdateNavigation(window_id, tab_id, nav1, true); ScopedVector<SessionWindow> windows; ReadWindows(&(windows.get())); @@ -843,7 +809,7 @@ TEST_F(SessionServiceTest, RemovePostDataWithPasswords) { // Expected: the HTTP body was removed from the content state of the POST // navigation with passwords. - EXPECT_NE(content_state, windows[0]->tabs[0]->navigations[0].state()); + EXPECT_NE(content_state, windows[0]->tabs[0]->navigations[0].content_state()); } // This test is only applicable to chromeos. diff --git a/chrome/browser/sessions/session_types.cc b/chrome/browser/sessions/session_types.cc index 5691f8d..c31ddf5 100644 --- a/chrome/browser/sessions/session_types.cc +++ b/chrome/browser/sessions/session_types.cc @@ -4,118 +4,420 @@ #include "chrome/browser/sessions/session_types.h" +#include "base/basictypes.h" +#include "base/pickle.h" +#include "base/stl_util.h" #include "base/string_util.h" -#include "chrome/browser/profiles/profile.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/sessions/session_command.h" #include "chrome/browser/ui/browser.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_entry.h" +#include "sync/util/time.h" +#include "third_party/WebKit/Source/Platform/chromium/public/WebReferrerPolicy.h" +#include "webkit/glue/webkit_glue.h" using content::NavigationEntry; // TabNavigation -------------------------------------------------------------- TabNavigation::TabNavigation() - : transition_(content::PAGE_TRANSITION_TYPED), - type_mask_(0), + : index_(-1), + unique_id_(0), + transition_type_(content::PAGE_TRANSITION_TYPED), + has_post_data_(false), post_id_(-1), - index_(-1), - is_overriding_user_agent_(false) { + is_overriding_user_agent_(false) {} + +TabNavigation::~TabNavigation() {} + +// static +TabNavigation TabNavigation::FromNavigationEntry( + int index, + const NavigationEntry& entry, + base::Time timestamp) { + TabNavigation navigation; + navigation.index_ = index; + navigation.unique_id_ = entry.GetUniqueID(); + navigation.referrer_ = entry.GetReferrer(); + navigation.virtual_url_ = entry.GetVirtualURL(); + navigation.title_ = entry.GetTitle(); + navigation.content_state_ = entry.GetContentState(); + navigation.transition_type_ = entry.GetTransitionType(); + navigation.has_post_data_ = entry.GetHasPostData(); + navigation.post_id_ = entry.GetPostID(); + navigation.original_request_url_ = entry.GetOriginalRequestURL(); + navigation.is_overriding_user_agent_ = entry.GetIsOverridingUserAgent(); + navigation.timestamp_ = timestamp; + return navigation; } -TabNavigation::TabNavigation(int index, - const GURL& virtual_url, - const content::Referrer& referrer, - const string16& title, - const std::string& state, - content::PageTransition transition) - : virtual_url_(virtual_url), - referrer_(referrer), - title_(title), - state_(state), - transition_(transition), - type_mask_(0), - post_id_(-1), - index_(index), - is_overriding_user_agent_(false) { +TabNavigation TabNavigation::FromSyncData( + int index, + const sync_pb::TabNavigation& specifics) { + TabNavigation navigation; + navigation.index_ = index; + if (specifics.has_unique_id()) { + navigation.unique_id_ = specifics.unique_id(); + } + if (specifics.has_referrer()) { + navigation.referrer_ = + content::Referrer(GURL(specifics.referrer()), + WebKit::WebReferrerPolicyDefault); + } + if (specifics.has_virtual_url()) + navigation.virtual_url_ = GURL(specifics.virtual_url()); + if (specifics.has_title()) + navigation.title_ = UTF8ToUTF16(specifics.title()); + if (specifics.has_state()) + navigation.content_state_ = specifics.state(); + navigation.transition_type_ = content::PAGE_TRANSITION_LINK; + if (specifics.has_page_transition() || + specifics.has_navigation_qualifier()) { + switch (specifics.page_transition()) { + case sync_pb::SyncEnums_PageTransition_LINK: + navigation.transition_type_ = content::PAGE_TRANSITION_LINK; + break; + case sync_pb::SyncEnums_PageTransition_TYPED: + navigation.transition_type_ = content::PAGE_TRANSITION_TYPED; + break; + case sync_pb::SyncEnums_PageTransition_AUTO_BOOKMARK: + navigation.transition_type_ = content::PAGE_TRANSITION_AUTO_BOOKMARK; + break; + case sync_pb::SyncEnums_PageTransition_AUTO_SUBFRAME: + navigation.transition_type_ = content::PAGE_TRANSITION_AUTO_SUBFRAME; + break; + case sync_pb::SyncEnums_PageTransition_MANUAL_SUBFRAME: + navigation.transition_type_ = content::PAGE_TRANSITION_MANUAL_SUBFRAME; + break; + case sync_pb::SyncEnums_PageTransition_GENERATED: + navigation.transition_type_ = content::PAGE_TRANSITION_GENERATED; + break; + case sync_pb::SyncEnums_PageTransition_AUTO_TOPLEVEL: + navigation.transition_type_ = content::PAGE_TRANSITION_AUTO_TOPLEVEL; + break; + case sync_pb::SyncEnums_PageTransition_FORM_SUBMIT: + navigation.transition_type_ = content::PAGE_TRANSITION_FORM_SUBMIT; + break; + case sync_pb::SyncEnums_PageTransition_RELOAD: + navigation.transition_type_ = content::PAGE_TRANSITION_RELOAD; + break; + case sync_pb::SyncEnums_PageTransition_KEYWORD: + navigation.transition_type_ = content::PAGE_TRANSITION_KEYWORD; + break; + case sync_pb::SyncEnums_PageTransition_KEYWORD_GENERATED: + navigation.transition_type_ = + content::PAGE_TRANSITION_KEYWORD_GENERATED; + break; + case sync_pb::SyncEnums_PageTransition_CHAIN_START: + navigation.transition_type_ = content::PAGE_TRANSITION_CHAIN_START; + break; + case sync_pb::SyncEnums_PageTransition_CHAIN_END: + navigation.transition_type_ = content::PAGE_TRANSITION_CHAIN_END; + break; + default: + switch (specifics.navigation_qualifier()) { + case sync_pb::SyncEnums_PageTransitionQualifier_CLIENT_REDIRECT: + navigation.transition_type_ = + content::PAGE_TRANSITION_CLIENT_REDIRECT; + break; + case sync_pb::SyncEnums_PageTransitionQualifier_SERVER_REDIRECT: + navigation.transition_type_ = + content::PAGE_TRANSITION_SERVER_REDIRECT; + break; + default: + navigation.transition_type_ = content::PAGE_TRANSITION_TYPED; + } + } + } + if (specifics.has_timestamp()) { + navigation.timestamp_ = syncer::ProtoTimeToTime(specifics.timestamp()); + } + return navigation; } -TabNavigation::TabNavigation(const TabNavigation& tab) - : virtual_url_(tab.virtual_url_), - referrer_(tab.referrer_), - title_(tab.title_), - state_(tab.state_), - transition_(tab.transition_), - type_mask_(tab.type_mask_), - post_id_(-1), - index_(tab.index_), - original_request_url_(tab.original_request_url_), - is_overriding_user_agent_(tab.is_overriding_user_agent_) { +namespace { + +// Helper used by TabNavigation::WriteToPickle(). It writes |str| to +// |pickle|, if and only if |str| fits within (|max_bytes| - +// |*bytes_written|). |bytes_written| is incremented to reflect the +// data written. +// +// TODO(akalin): Unify this with the same function in +// base_session_service.cc. +void WriteStringToPickle(Pickle* pickle, + int* bytes_written, + int max_bytes, + const std::string& str) { + int num_bytes = str.size() * sizeof(char); + if (*bytes_written + num_bytes < max_bytes) { + *bytes_written += num_bytes; + pickle->WriteString(str); + } else { + pickle->WriteString(std::string()); + } } -TabNavigation::~TabNavigation() { +// string16 version of WriteStringToPickle. +// +// TODO(akalin): Unify this, too. +void WriteString16ToPickle(Pickle* pickle, + int* bytes_written, + int max_bytes, + const string16& str) { + int num_bytes = str.size() * sizeof(char16); + if (*bytes_written + num_bytes < max_bytes) { + *bytes_written += num_bytes; + pickle->WriteString16(str); + } else { + pickle->WriteString16(string16()); + } +} + +// A mask used for arbitrary boolean values needed to represent a +// NavigationEntry. Currently only contains HAS_POST_DATA. +// +// NOTE(akalin): We may want to just serialize |has_post_data_| +// directly. Other bools (|is_overriding_user_agent_|) haven't been +// added to this mask. +enum TypeMask { + HAS_POST_DATA = 1 +}; + +} // namespace + +// Pickle order: +// +// index_ +// virtual_url_ +// title_ +// content_state_ +// transition_type_ +// +// Added on later: +// +// type_mask (has_post_data_) +// referrer_ +// original_request_url_ +// is_overriding_user_agent_ + +void TabNavigation::WriteToPickle(Pickle* pickle) const { + pickle->WriteInt(index_); + + // We only allow navigations up to 63k (which should be completely + // reasonable). On the off chance we get one that is too big, try to + // keep the url. + + // Bound the string data (which is variable length) to + // |max_state_size bytes| bytes. + static const size_t max_state_size = + std::numeric_limits<SessionCommand::size_type>::max() - 1024; + int bytes_written = 0; + + WriteStringToPickle(pickle, &bytes_written, max_state_size, + virtual_url_.spec()); + + WriteString16ToPickle(pickle, &bytes_written, max_state_size, title_); + + std::string content_state = content_state_; + if (has_post_data_) { + content_state = + webkit_glue::RemovePasswordDataFromHistoryState(content_state); + } + WriteStringToPickle(pickle, &bytes_written, max_state_size, content_state); + + pickle->WriteInt(transition_type_); + + const int type_mask = has_post_data_ ? HAS_POST_DATA : 0; + pickle->WriteInt(type_mask); + + WriteStringToPickle( + pickle, &bytes_written, max_state_size, + referrer_.url.is_valid() ? referrer_.url.spec() : std::string()); + + pickle->WriteInt(referrer_.policy); + + // Save info required to override the user agent. + WriteStringToPickle( + pickle, &bytes_written, max_state_size, + original_request_url_.is_valid() ? + original_request_url_.spec() : std::string()); + pickle->WriteBool(is_overriding_user_agent_); + + // TODO(akalin): Persist timestamp. } -TabNavigation& TabNavigation::operator=(const TabNavigation& tab) { - virtual_url_ = tab.virtual_url_; - referrer_ = tab.referrer_; - title_ = tab.title_; - state_ = tab.state_; - transition_ = tab.transition_; - type_mask_ = tab.type_mask_; - post_id_ = tab.post_id_; - index_ = tab.index_; - original_request_url_ = tab.original_request_url_; - is_overriding_user_agent_ = tab.is_overriding_user_agent_; - return *this; +bool TabNavigation::ReadFromPickle(PickleIterator* iterator) { + *this = TabNavigation(); + std::string virtual_url_spec; + int transition_type_int = 0; + if (!iterator->ReadInt(&index_) || + !iterator->ReadString(&virtual_url_spec) || + !iterator->ReadString16(&title_) || + !iterator->ReadString(&content_state_) || + !iterator->ReadInt(&transition_type_int)) + return false; + virtual_url_ = GURL(virtual_url_spec); + transition_type_ = static_cast<content::PageTransition>(transition_type_int); + + // type_mask did not always exist in the written stream. As such, we + // don't fail if it can't be read. + int type_mask = 0; + bool has_type_mask = iterator->ReadInt(&type_mask); + + if (has_type_mask) { + has_post_data_ = type_mask & HAS_POST_DATA; + // the "referrer" property was added after type_mask to the written + // stream. As such, we don't fail if it can't be read. + std::string referrer_spec; + if (!iterator->ReadString(&referrer_spec)) + referrer_spec = std::string(); + // The "referrer policy" property was added even later, so we fall back to + // the default policy if the property is not present. + int policy_int; + WebKit::WebReferrerPolicy policy; + if (iterator->ReadInt(&policy_int)) + policy = static_cast<WebKit::WebReferrerPolicy>(policy_int); + else + policy = WebKit::WebReferrerPolicyDefault; + referrer_ = content::Referrer(GURL(referrer_spec), policy); + + // If the original URL can't be found, leave it empty. + std::string original_request_url_spec; + if (!iterator->ReadString(&original_request_url_spec)) + original_request_url_spec = std::string(); + original_request_url_ = GURL(original_request_url_spec); + + // Default to not overriding the user agent if we don't have info. + if (!iterator->ReadBool(&is_overriding_user_agent_)) + is_overriding_user_agent_ = false; + } + + // TODO(akalin): Restore timestamp when it is persisted. + return true; } -// static -NavigationEntry* TabNavigation::ToNavigationEntry( - int page_id, Profile *profile) const { - NavigationEntry* entry = content::NavigationController::CreateNavigationEntry( - virtual_url_, - referrer_, - // Use a transition type of reload so that we don't incorrectly - // increase the typed count. - content::PAGE_TRANSITION_RELOAD, - false, - // The extra headers are not sync'ed across sessions. - std::string(), - profile); +scoped_ptr<NavigationEntry> TabNavigation::ToNavigationEntry( + int page_id, + content::BrowserContext* browser_context) const { + scoped_ptr<NavigationEntry> entry( + content::NavigationController::CreateNavigationEntry( + virtual_url_, + referrer_, + // Use a transition type of reload so that we don't incorrectly + // increase the typed count. + content::PAGE_TRANSITION_RELOAD, + false, + // The extra headers are not sync'ed across sessions. + std::string(), + browser_context)); - entry->SetPageID(page_id); entry->SetTitle(title_); - entry->SetContentState(state_); - entry->SetHasPostData(type_mask_ & TabNavigation::HAS_POST_DATA); + entry->SetContentState(content_state_); + entry->SetPageID(page_id); + entry->SetHasPostData(has_post_data_); entry->SetPostID(post_id_); entry->SetOriginalRequestURL(original_request_url_); entry->SetIsOverridingUserAgent(is_overriding_user_agent_); - return entry; + // TODO(akalin): Set |entry|'s timestamp once NavigationEntry has a + // field for it. + + return entry.Pass(); } -void TabNavigation::SetFromNavigationEntry(const NavigationEntry& entry) { - virtual_url_ = entry.GetVirtualURL(); - referrer_ = entry.GetReferrer(); - title_ = entry.GetTitle(); - state_ = entry.GetContentState(); - transition_ = entry.GetTransitionType(); - type_mask_ = entry.GetHasPostData() ? TabNavigation::HAS_POST_DATA : 0; - post_id_ = entry.GetPostID(); - original_request_url_ = entry.GetOriginalRequestURL(); - is_overriding_user_agent_ = entry.GetIsOverridingUserAgent(); +// TODO(zea): perhaps sync state (scroll position, form entries, etc.) as well? +// See http://crbug.com/67068. +sync_pb::TabNavigation TabNavigation::ToSyncData() const { + sync_pb::TabNavigation sync_data; + sync_data.set_virtual_url(virtual_url_.spec()); + // FIXME(zea): Support referrer policy? + sync_data.set_referrer(referrer_.url.spec()); + sync_data.set_title(UTF16ToUTF8(title_)); + switch (transition_type_) { + case content::PAGE_TRANSITION_LINK: + sync_data.set_page_transition( + sync_pb::SyncEnums_PageTransition_LINK); + break; + case content::PAGE_TRANSITION_TYPED: + sync_data.set_page_transition( + sync_pb::SyncEnums_PageTransition_TYPED); + break; + case content::PAGE_TRANSITION_AUTO_BOOKMARK: + sync_data.set_page_transition( + sync_pb::SyncEnums_PageTransition_AUTO_BOOKMARK); + break; + case content::PAGE_TRANSITION_AUTO_SUBFRAME: + sync_data.set_page_transition( + sync_pb::SyncEnums_PageTransition_AUTO_SUBFRAME); + break; + case content::PAGE_TRANSITION_MANUAL_SUBFRAME: + sync_data.set_page_transition( + sync_pb::SyncEnums_PageTransition_MANUAL_SUBFRAME); + break; + case content::PAGE_TRANSITION_GENERATED: + sync_data.set_page_transition( + sync_pb::SyncEnums_PageTransition_GENERATED); + break; + case content::PAGE_TRANSITION_AUTO_TOPLEVEL: + sync_data.set_page_transition( + sync_pb::SyncEnums_PageTransition_AUTO_TOPLEVEL); + break; + case content::PAGE_TRANSITION_FORM_SUBMIT: + sync_data.set_page_transition( + sync_pb::SyncEnums_PageTransition_FORM_SUBMIT); + break; + case content::PAGE_TRANSITION_RELOAD: + sync_data.set_page_transition( + sync_pb::SyncEnums_PageTransition_RELOAD); + break; + case content::PAGE_TRANSITION_KEYWORD: + sync_data.set_page_transition( + sync_pb::SyncEnums_PageTransition_KEYWORD); + break; + case content::PAGE_TRANSITION_KEYWORD_GENERATED: + sync_data.set_page_transition( + sync_pb::SyncEnums_PageTransition_KEYWORD_GENERATED); + break; + case content::PAGE_TRANSITION_CHAIN_START: + sync_data.set_page_transition( + sync_pb::SyncEnums_PageTransition_CHAIN_START); + break; + case content::PAGE_TRANSITION_CHAIN_END: + sync_data.set_page_transition( + sync_pb::SyncEnums_PageTransition_CHAIN_END); + break; + case content::PAGE_TRANSITION_CLIENT_REDIRECT: + sync_data.set_navigation_qualifier( + sync_pb::SyncEnums_PageTransitionQualifier_CLIENT_REDIRECT); + break; + case content::PAGE_TRANSITION_SERVER_REDIRECT: + sync_data.set_navigation_qualifier( + sync_pb::SyncEnums_PageTransitionQualifier_SERVER_REDIRECT); + break; + default: + sync_data.set_page_transition( + sync_pb::SyncEnums_PageTransition_TYPED); + } + sync_data.set_unique_id(unique_id_); + sync_data.set_timestamp(syncer::TimeToProtoTime(timestamp_)); + return sync_data; } // static -void TabNavigation::CreateNavigationEntriesFromTabNavigations( - Profile* profile, +std::vector<NavigationEntry*> +TabNavigation::CreateNavigationEntriesFromTabNavigations( const std::vector<TabNavigation>& navigations, - std::vector<NavigationEntry*>* entries) { + content::BrowserContext* browser_context) { int page_id = 0; - for (std::vector<TabNavigation>::const_iterator i = - navigations.begin(); i != navigations.end(); ++i, ++page_id) { - entries->push_back(i->ToNavigationEntry(page_id, profile)); + std::vector<NavigationEntry*> entries; + for (std::vector<TabNavigation>::const_iterator it = navigations.begin(); + it != navigations.end(); ++it) { + entries.push_back( + it->ToNavigationEntry(page_id, browser_context).release()); + ++page_id; } + return entries; } // SessionTab ----------------------------------------------------------------- diff --git a/chrome/browser/sessions/session_types.h b/chrome/browser/sessions/session_types.h index 0c3335b..dc9c7ba 100644 --- a/chrome/browser/sessions/session_types.h +++ b/chrome/browser/sessions/session_types.h @@ -8,119 +8,121 @@ #include <string> #include <vector> -#include "base/stl_util.h" +#include "base/memory/scoped_ptr.h" #include "base/string16.h" #include "base/time.h" #include "chrome/browser/sessions/session_id.h" #include "content/public/common/page_transition_types.h" #include "content/public/common/referrer.h" #include "googleurl/src/gurl.h" +#include "sync/protocol/session_specifics.pb.h" #include "ui/base/ui_base_types.h" #include "ui/gfx/rect.h" -class Profile; +class Pickle; +class PickleIterator; namespace content { +class BrowserContext; class NavigationEntry; } // TabNavigation ------------------------------------------------------------- -// TabNavigation corresponds to the parts of NavigationEntry needed to restore -// the NavigationEntry during session restore and tab restore. +// TabNavigation is a "freeze-dried" version of NavigationEntry. It +// contains the data needed to restore a NavigationEntry during +// session restore and tab restore, and it can also be pickled and +// unpickled. It is also convertible to a sync protocol buffer for +// session syncing. // -// TabNavigation is cheap and supports copy semantics. +// Default copy constructor and assignment operator welcome. class TabNavigation { public: - enum TypeMask { - HAS_POST_DATA = 1 - }; - + // Creates an invalid (index < 0) TabNavigation. TabNavigation(); - TabNavigation(int index, - const GURL& virtual_url, - const content::Referrer& referrer, - const string16& title, - const std::string& state, - content::PageTransition transition); - TabNavigation(const TabNavigation& tab); - virtual ~TabNavigation(); - TabNavigation& operator=(const TabNavigation& tab); - - // Converts this TabNavigation into a NavigationEntry with a page id of - // |page_id|. The caller owns the returned NavigationEntry. - content::NavigationEntry* ToNavigationEntry(int page_id, - Profile* profile) const; - - // Resets this TabNavigation from |entry|. - void SetFromNavigationEntry(const content::NavigationEntry& entry); - - // Virtual URL of the page. See NavigationEntry::GetVirtualURL() for details. - void set_virtual_url(const GURL& url) { virtual_url_ = url; } - const GURL& virtual_url() const { return virtual_url_; } - - // The referrer. - const content::Referrer& referrer() const { return referrer_; } - - // The title of the page. - void set_title(const string16& title) { title_ = title; } - const string16& title() const { return title_; } - - // State bits. - const std::string& state() const { return state_; } + ~TabNavigation(); - // Transition type. - void set_transition(content::PageTransition transition) { - transition_ = transition; - } - content::PageTransition transition() const { return transition_; } - - // A mask used for arbitrary boolean values needed to represent a - // NavigationEntry. Currently only contains HAS_POST_DATA or 0. - void set_type_mask(int type_mask) { type_mask_ = type_mask; } - int type_mask() const { return type_mask_; } - - // The index in the NavigationController. If this is -1, it means this - // TabNavigation is bogus. + // Construct a TabNavigation for a particular index from a + // NavigationEntry with the given timestamp. // - // This is used when determining the selected TabNavigation and only useful - // by BaseSessionService and SessionService. - void set_index(int index) { index_ = index; } + // TODO(akalin): Add a timestamp field to + // navigation::NavigationEntry and use that instead of passing a + // separate timestamp. + static TabNavigation FromNavigationEntry( + int index, + const content::NavigationEntry& entry, + base::Time timestamp); + + // Construct a TabNavigation for a particular index from a sync + // protocol buffer. Note that the sync protocol buffer doesn't + // contain all TabNavigation fields. + static TabNavigation FromSyncData( + int index, + const sync_pb::TabNavigation& specifics); + + // Note that not all TabNavigation fields are preserved. + void WriteToPickle(Pickle* pickle) const; + bool ReadFromPickle(PickleIterator* iterator); + + // Convert this TabNavigation into a NavigationEntry with the given + // page ID and context. The NavigationEntry will have a transition + // type of PAGE_TRANSITION_RELOAD and a new unique ID. + scoped_ptr<content::NavigationEntry> ToNavigationEntry( + int page_id, + content::BrowserContext* browser_context) const; + + // Convert this navigation into its sync protocol buffer equivalent. + // Note that the protocol buffer doesn't contain all TabNavigation + // fields. + sync_pb::TabNavigation ToSyncData() const; + + // The index in the NavigationController. This TabNavigation is + // valid only when the index is non-negative. + // + // This is used when determining the selected TabNavigation and only + // used by SessionService. int index() const { return index_; } + void set_index(int index) { index_ = index; } - // The URL that initially spawned the NavigationEntry. - const GURL& original_request_url() const { return original_request_url_; } - void set_original_request_url(const GURL& url) { - original_request_url_ = url; - } + // Accessors for some fields taken from NavigationEntry. + int unique_id() const { return unique_id_; } + const GURL& virtual_url() const { return virtual_url_; } + const string16& title() const { return title_; } + const std::string& content_state() const { return content_state_; } - // Whether or not we're overriding the standard user agent. - bool is_overriding_user_agent() const { return is_overriding_user_agent_; } - void set_is_overriding_user_agent(bool state) { - is_overriding_user_agent_ = state; - } + // Timestamp this navigation occurred. + base::Time timestamp() const { return timestamp_; } - // Converts a set of TabNavigations into a set of NavigationEntrys. The - // caller owns the NavigationEntrys. - static void CreateNavigationEntriesFromTabNavigations( - Profile* profile, + // Converts a set of TabNavigations into a list of NavigationEntrys + // with sequential page IDs and the given context. The caller owns + // the returned NavigationEntrys. + static std::vector<content::NavigationEntry*> + CreateNavigationEntriesFromTabNavigations( const std::vector<TabNavigation>& navigations, - std::vector<content::NavigationEntry*>* entries); + content::BrowserContext* browser_context); private: - friend class BaseSessionService; + friend struct SessionTypesTestHelper; - GURL virtual_url_; + // Index in the NavigationController. + int index_; + + // Member variables corresponding to NavigationEntry fields. + int unique_id_; content::Referrer referrer_; + GURL virtual_url_; string16 title_; - std::string state_; - content::PageTransition transition_; - int type_mask_; + std::string content_state_; + content::PageTransition transition_type_; + bool has_post_data_; int64 post_id_; - - int index_; GURL original_request_url_; bool is_overriding_user_agent_; + + // Timestamp when the navigation occurred. + // + // TODO(akalin): Add a timestamp field to NavigationEntry. + base::Time timestamp_; }; // SessionTab ---------------------------------------------------------------- diff --git a/chrome/browser/sessions/session_types_test_helper.cc b/chrome/browser/sessions/session_types_test_helper.cc new file mode 100644 index 0000000..f2201e4 --- /dev/null +++ b/chrome/browser/sessions/session_types_test_helper.cc @@ -0,0 +1,92 @@ +// Copyright (c) 2012 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/session_types_test_helper.h" + +#include "base/basictypes.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/sessions/session_types.h" +#include "googleurl/src/gurl.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/Source/Platform/chromium/public/WebReferrerPolicy.h" + +void SessionTypesTestHelper::ExpectNavigationEquals( + const TabNavigation& expected, + const TabNavigation& actual) { + EXPECT_EQ(expected.referrer_.url, actual.referrer_.url); + EXPECT_EQ(expected.referrer_.policy, actual.referrer_.policy); + EXPECT_EQ(expected.virtual_url_, actual.virtual_url_); + EXPECT_EQ(expected.title_, actual.title_); + EXPECT_EQ(expected.content_state_, actual.content_state_); + EXPECT_EQ(expected.transition_type_, actual.transition_type_); + EXPECT_EQ(expected.has_post_data_, actual.has_post_data_); + EXPECT_EQ(expected.original_request_url_, actual.original_request_url_); + EXPECT_EQ(expected.is_overriding_user_agent_, + actual.is_overriding_user_agent_); +} + +TabNavigation SessionTypesTestHelper::CreateNavigation( + const std::string& virtual_url, + const std::string& title) { + TabNavigation navigation; + navigation.index_ = 0; + navigation.referrer_ = + content::Referrer(GURL("http://www.referrer.com"), + WebKit::WebReferrerPolicyDefault); + navigation.virtual_url_ = GURL(virtual_url); + navigation.title_ = UTF8ToUTF16(title); + navigation.content_state_ = "fake_state"; + navigation.timestamp_ = base::Time::Now(); + return navigation; +} + +const content::Referrer& SessionTypesTestHelper::GetReferrer( + const TabNavigation& navigation) { + return navigation.referrer_; +} + +content::PageTransition SessionTypesTestHelper::GetTransitionType( + const TabNavigation& navigation) { + return navigation.transition_type_; +} + +bool SessionTypesTestHelper::GetHasPostData(const TabNavigation& navigation) { + return navigation.has_post_data_; +} + +int64 SessionTypesTestHelper::GetPostID(const TabNavigation& navigation) { + return navigation.post_id_; +} + +const GURL& SessionTypesTestHelper::GetOriginalRequestURL( + const TabNavigation& navigation) { + return navigation.original_request_url_; +} + +bool SessionTypesTestHelper::GetIsOverridingUserAgent( + const TabNavigation& navigation) { + return navigation.is_overriding_user_agent_; +} + +void SessionTypesTestHelper::SetContentState( + TabNavigation* navigation, + const std::string& content_state) { + navigation->content_state_ = content_state; +} + +void SessionTypesTestHelper::SetHasPostData(TabNavigation* navigation, + bool has_post_data) { + navigation->has_post_data_ = has_post_data; +} + +void SessionTypesTestHelper::SetOriginalRequestURL( + TabNavigation* navigation, + const GURL& original_request_url) { + navigation->original_request_url_ = original_request_url; +} + +void SessionTypesTestHelper::SetIsOverridingUserAgent( + TabNavigation* navigation, + bool is_overriding_user_agent) { + navigation->is_overriding_user_agent_ = is_overriding_user_agent; +} diff --git a/chrome/browser/sessions/session_types_test_helper.h b/chrome/browser/sessions/session_types_test_helper.h new file mode 100644 index 0000000..50eb2e3 --- /dev/null +++ b/chrome/browser/sessions/session_types_test_helper.h @@ -0,0 +1,60 @@ +// Copyright (c) 2012 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. + +#ifndef CHROME_BROWSER_SESSIONS_SESSION_TYPES_TEST_HELPER_H_ +#define CHROME_BROWSER_SESSIONS_SESSION_TYPES_TEST_HELPER_H_ + +#include <string> + +#include "content/public/common/page_transition_types.h" + +class GURL; +class TabNavigation; + +namespace content { +struct Referrer; +} + +struct SessionTypesTestHelper { + // Compares everything except index, unique ID, post ID, and + // timestamp. + static void ExpectNavigationEquals(const TabNavigation& expected, + const TabNavigation& actual); + + // Create a TabNavigation with the given URL and title and some + // common values for the other fields. + static TabNavigation CreateNavigation(const std::string& virtual_url, + const std::string& title); + + // Getters. + + static const content::Referrer& GetReferrer(const TabNavigation& navigation); + + static content::PageTransition GetTransitionType( + const TabNavigation& navigation); + + static bool GetHasPostData(const TabNavigation& navigation); + + static int64 GetPostID(const TabNavigation& navigation); + + static const GURL& GetOriginalRequestURL(const TabNavigation& navigation); + + static bool GetIsOverridingUserAgent(const TabNavigation& navigation); + + // Setters. + + static void SetContentState(TabNavigation* navigation, + const std::string& content_state); + + static void SetHasPostData(TabNavigation* navigation, + bool has_post_data); + + static void SetOriginalRequestURL(TabNavigation* navigation, + const GURL& original_request_url); + + static void SetIsOverridingUserAgent(TabNavigation* navigation, + bool is_overriding_user_agent); +}; + +#endif // CHROME_BROWSER_SESSIONS_SESSION_TYPES_TEST_HELPER_H_ diff --git a/chrome/browser/sessions/session_types_unittest.cc b/chrome/browser/sessions/session_types_unittest.cc new file mode 100644 index 0000000..0e8030b --- /dev/null +++ b/chrome/browser/sessions/session_types_unittest.cc @@ -0,0 +1,246 @@ +// Copyright (c) 2012 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 <cstddef> +#include <string> + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "base/pickle.h" +#include "base/string16.h" +#include "base/time.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/sessions/session_types.h" +#include "chrome/browser/sessions/session_types_test_helper.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/common/page_transition_types.h" +#include "content/public/common/referrer.h" +#include "googleurl/src/gurl.h" +#include "sync/protocol/session_specifics.pb.h" +#include "sync/util/time.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/Source/Platform/chromium/public/WebReferrerPolicy.h" + +namespace { + +const int kIndex = 3; +const int kUniqueID = 50; +const content::Referrer kReferrer = + content::Referrer(GURL("http://www.referrer.com"), + WebKit::WebReferrerPolicyAlways); +const GURL kVirtualURL("http://www.virtual-url.com"); +const string16 kTitle = ASCIIToUTF16("title"); +const std::string kContentState = "content state"; +const content::PageTransition kTransitionType = + content::PAGE_TRANSITION_AUTO_SUBFRAME; +const bool kHasPostData = true; +const int64 kPostID = 100; +const GURL kOriginalRequestURL("http://www.original-request.com"); +const bool kIsOverridingUserAgent = true; +const base::Time kTimestamp = syncer::ProtoTimeToTime(100); + +const int kPageID = 10; + +// Create a NavigationEntry from the constants above. +scoped_ptr<content::NavigationEntry> MakeNavigationEntryForTest() { + scoped_ptr<content::NavigationEntry> navigation_entry( + content::NavigationEntry::Create()); + navigation_entry->SetReferrer(kReferrer); + navigation_entry->SetVirtualURL(kVirtualURL); + navigation_entry->SetTitle(kTitle); + navigation_entry->SetContentState(kContentState); + navigation_entry->SetTransitionType(kTransitionType); + navigation_entry->SetHasPostData(kHasPostData); + navigation_entry->SetPostID(kPostID); + navigation_entry->SetOriginalRequestURL(kOriginalRequestURL); + navigation_entry->SetIsOverridingUserAgent(kIsOverridingUserAgent); + return navigation_entry.Pass(); +} + +// Create a sync_pb::TabNavigation from the constants above. +sync_pb::TabNavigation MakeSyncDataForTest() { + sync_pb::TabNavigation sync_data; + sync_data.set_virtual_url(kVirtualURL.spec()); + sync_data.set_referrer(kReferrer.url.spec()); + sync_data.set_title(UTF16ToUTF8(kTitle)); + sync_data.set_state(kContentState); + sync_data.set_page_transition( + sync_pb::SyncEnums_PageTransition_AUTO_SUBFRAME); + sync_data.set_unique_id(kUniqueID); + sync_data.set_timestamp(syncer::TimeToProtoTime(kTimestamp)); + return sync_data; +} + +// Create a default TabNavigation. All its fields should be +// initialized to their respective default values. +TEST(TabNavigationTest, DefaultInitializer) { + const TabNavigation navigation; + EXPECT_EQ(-1, navigation.index()); + EXPECT_EQ(0, navigation.unique_id()); + EXPECT_EQ(GURL(), SessionTypesTestHelper::GetReferrer(navigation).url); + EXPECT_EQ(WebKit::WebReferrerPolicyDefault, + SessionTypesTestHelper::GetReferrer(navigation).policy); + EXPECT_EQ(GURL(), navigation.virtual_url()); + EXPECT_TRUE(navigation.title().empty()); + EXPECT_TRUE(navigation.content_state().empty()); + EXPECT_EQ(content::PAGE_TRANSITION_TYPED, + SessionTypesTestHelper::GetTransitionType(navigation)); + EXPECT_FALSE(SessionTypesTestHelper::GetHasPostData(navigation)); + EXPECT_EQ(-1, SessionTypesTestHelper::GetPostID(navigation)); + EXPECT_EQ(GURL(), SessionTypesTestHelper::GetOriginalRequestURL(navigation)); + EXPECT_FALSE(SessionTypesTestHelper::GetIsOverridingUserAgent(navigation)); + EXPECT_EQ(base::Time(), navigation.timestamp()); +} + +// Create a TabNavigation from a NavigationEntry. All its fields +// should match the NavigationEntry's. +TEST(TabNavigationTest, FromNavigationEntry) { + const scoped_ptr<content::NavigationEntry> navigation_entry( + MakeNavigationEntryForTest()); + + const TabNavigation& navigation = + TabNavigation::FromNavigationEntry( + kIndex, *navigation_entry, kTimestamp); + + EXPECT_EQ(kIndex, navigation.index()); + + EXPECT_EQ(navigation_entry->GetUniqueID(), navigation.unique_id()); + EXPECT_EQ(kReferrer.url, + SessionTypesTestHelper::GetReferrer(navigation).url); + EXPECT_EQ(kReferrer.policy, + SessionTypesTestHelper::GetReferrer(navigation).policy); + EXPECT_EQ(kVirtualURL, navigation.virtual_url()); + EXPECT_EQ(kTitle, navigation.title()); + EXPECT_EQ(kContentState, navigation.content_state()); + EXPECT_EQ(kTransitionType, + SessionTypesTestHelper::GetTransitionType(navigation)); + EXPECT_EQ(kHasPostData, SessionTypesTestHelper::GetHasPostData(navigation)); + EXPECT_EQ(kPostID, SessionTypesTestHelper::GetPostID(navigation)); + EXPECT_EQ(kOriginalRequestURL, + SessionTypesTestHelper::GetOriginalRequestURL(navigation)); + EXPECT_EQ(kIsOverridingUserAgent, + SessionTypesTestHelper::GetIsOverridingUserAgent(navigation)); + EXPECT_EQ(kTimestamp, navigation.timestamp()); +} + +// Create a TabNavigation from a sync_pb::TabNavigation. All its +// fields should match the protocol buffer's if it exists there, and +// sbould be set to the default value otherwise. +TEST(TabNavigationTest, FromSyncData) { + const sync_pb::TabNavigation sync_data = MakeSyncDataForTest(); + + const TabNavigation& navigation = + TabNavigation::FromSyncData(kIndex, sync_data); + + EXPECT_EQ(kIndex, navigation.index()); + EXPECT_EQ(kUniqueID, navigation.unique_id()); + EXPECT_EQ(kReferrer.url, + SessionTypesTestHelper::GetReferrer(navigation).url); + EXPECT_EQ(WebKit::WebReferrerPolicyDefault, + SessionTypesTestHelper::GetReferrer(navigation).policy); + EXPECT_EQ(kVirtualURL, navigation.virtual_url()); + EXPECT_EQ(kTitle, navigation.title()); + EXPECT_EQ(kContentState, navigation.content_state()); + EXPECT_EQ(kTransitionType, + SessionTypesTestHelper::GetTransitionType(navigation)); + EXPECT_FALSE(SessionTypesTestHelper::GetHasPostData(navigation)); + EXPECT_EQ(-1, SessionTypesTestHelper::GetPostID(navigation)); + EXPECT_EQ(GURL(), SessionTypesTestHelper::GetOriginalRequestURL(navigation)); + EXPECT_FALSE(SessionTypesTestHelper::GetIsOverridingUserAgent(navigation)); + EXPECT_EQ(kTimestamp, navigation.timestamp()); +} + +// Create a TabNavigation, pickle it, then create another one by +// unpickling. The new one should match the old one except for fields +// that aren't pickled, which should be set to default values. +TEST(TabNavigationTest, Pickle) { + const TabNavigation& old_navigation = + TabNavigation::FromNavigationEntry( + kIndex, *MakeNavigationEntryForTest(), kTimestamp); + + Pickle pickle; + old_navigation.WriteToPickle(&pickle); + + TabNavigation new_navigation; + PickleIterator pickle_iterator(pickle); + EXPECT_TRUE(new_navigation.ReadFromPickle(&pickle_iterator)); + + EXPECT_EQ(kIndex, new_navigation.index()); + + EXPECT_EQ(0, new_navigation.unique_id()); + EXPECT_EQ(kReferrer.url, + SessionTypesTestHelper::GetReferrer(new_navigation).url); + EXPECT_EQ(kReferrer.policy, + SessionTypesTestHelper::GetReferrer(new_navigation).policy); + EXPECT_EQ(kVirtualURL, new_navigation.virtual_url()); + EXPECT_EQ(kTitle, new_navigation.title()); + EXPECT_TRUE(new_navigation.content_state().empty()); + EXPECT_EQ(kTransitionType, + SessionTypesTestHelper::GetTransitionType(new_navigation)); + EXPECT_EQ(kHasPostData, + SessionTypesTestHelper::GetHasPostData(new_navigation)); + EXPECT_EQ(-1, SessionTypesTestHelper::GetPostID(new_navigation)); + EXPECT_EQ(kOriginalRequestURL, + SessionTypesTestHelper::GetOriginalRequestURL(new_navigation)); + EXPECT_EQ(kIsOverridingUserAgent, + SessionTypesTestHelper::GetIsOverridingUserAgent(new_navigation)); + EXPECT_EQ(base::Time(), new_navigation.timestamp()); +} + +// Create a NavigationEntry, then create another one by converting to +// a TabNavigation and back. The new one should match the old one +// except for fields that aren't preserved, which should be set to +// expected values. +TEST(TabNavigationTest, ToNavigationEntry) { + const scoped_ptr<content::NavigationEntry> old_navigation_entry( + MakeNavigationEntryForTest()); + + const TabNavigation& navigation = + TabNavigation::FromNavigationEntry( + kIndex, *old_navigation_entry, kTimestamp); + + const scoped_ptr<content::NavigationEntry> new_navigation_entry( + navigation.ToNavigationEntry(kPageID, NULL)); + + EXPECT_EQ(kReferrer.url, new_navigation_entry->GetReferrer().url); + EXPECT_EQ(kReferrer.policy, new_navigation_entry->GetReferrer().policy); + EXPECT_EQ(kVirtualURL, new_navigation_entry->GetVirtualURL()); + EXPECT_EQ(kTitle, new_navigation_entry->GetTitle()); + EXPECT_EQ(kContentState, new_navigation_entry->GetContentState()); + EXPECT_EQ(kPageID, new_navigation_entry->GetPageID()); + EXPECT_EQ(content::PAGE_TRANSITION_RELOAD, + new_navigation_entry->GetTransitionType()); + EXPECT_EQ(kHasPostData, new_navigation_entry->GetHasPostData()); + EXPECT_EQ(kPostID, new_navigation_entry->GetPostID()); + EXPECT_EQ(kOriginalRequestURL, + new_navigation_entry->GetOriginalRequestURL()); + EXPECT_EQ(kIsOverridingUserAgent, + new_navigation_entry->GetIsOverridingUserAgent()); +} + +// Create a NavigationEntry, convert it to a TabNavigation, then +// create a sync protocol buffer from it. The protocol buffer should +// have matching fields to the NavigationEntry (when applicable). +TEST(TabNavigationTest, ToSyncData) { + const scoped_ptr<content::NavigationEntry> navigation_entry( + MakeNavigationEntryForTest()); + + const TabNavigation& navigation = + TabNavigation::FromNavigationEntry( + kIndex, *navigation_entry, kTimestamp); + + const sync_pb::TabNavigation sync_data = navigation.ToSyncData(); + + EXPECT_EQ(kVirtualURL.spec(), sync_data.virtual_url()); + EXPECT_EQ(kReferrer.url.spec(), sync_data.referrer()); + EXPECT_EQ(kTitle, ASCIIToUTF16(sync_data.title())); + EXPECT_TRUE(sync_data.state().empty()); + EXPECT_EQ(sync_pb::SyncEnums_PageTransition_AUTO_SUBFRAME, + sync_data.page_transition()); + EXPECT_FALSE(sync_data.has_navigation_qualifier()); + EXPECT_EQ(navigation_entry->GetUniqueID(), sync_data.unique_id()); + EXPECT_EQ(syncer::TimeToProtoTime(kTimestamp), sync_data.timestamp()); +} + +} // namespace diff --git a/chrome/browser/sessions/tab_restore_service.cc b/chrome/browser/sessions/tab_restore_service.cc index 19f5ada..cb7b68f 100644 --- a/chrome/browser/sessions/tab_restore_service.cc +++ b/chrome/browser/sessions/tab_restore_service.cc @@ -17,9 +17,9 @@ #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/tab_helper.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/sessions/session_command.h" #include "chrome/browser/sessions/session_service.h" #include "chrome/browser/sessions/session_service_factory.h" -#include "chrome/browser/sessions/session_command.h" #include "chrome/browser/sessions/session_types.h" #include "chrome/browser/sessions/tab_restore_service_delegate.h" #include "chrome/browser/sessions/tab_restore_service_observer.h" @@ -529,7 +529,8 @@ void TabRestoreService::PopulateTab(Tab* tab, for (int i = 0; i < entry_count; ++i) { NavigationEntry* entry = (i == pending_index) ? controller->GetPendingEntry() : controller->GetEntryAtIndex(i); - tab->navigations[i].SetFromNavigationEntry(*entry); + tab->navigations[i] = + TabNavigation::FromNavigationEntry(i, *entry, base::Time::Now()); } tab->timestamp = TimeNow(); tab->current_navigation_index = controller->GetCurrentEntryIndex(); @@ -708,14 +709,9 @@ void TabRestoreService::ScheduleCommandsForTab(const Tab& tab, for (int i = first_index_to_persist, wrote_count = 0; i < max_index && wrote_count < 2 * max_persist_navigation_count; ++i) { if (ShouldTrackEntry(navigations[i].virtual_url())) { - // Creating a NavigationEntry isn't the most efficient way to go about - // this, but it simplifies the code and makes it less error prone as we - // add new data to NavigationEntry. - scoped_ptr<NavigationEntry> entry( - navigations[i].ToNavigationEntry(wrote_count, profile())); ScheduleCommand( CreateUpdateTabNavigationCommand(kCommandUpdateTabNavigation, tab.id, - wrote_count++, *entry)); + navigations[i])); } } } diff --git a/chrome/browser/sessions/tab_restore_service_browsertest.cc b/chrome/browser/sessions/tab_restore_service_browsertest.cc index cd1d4ba..17ee22e 100644 --- a/chrome/browser/sessions/tab_restore_service_browsertest.cc +++ b/chrome/browser/sessions/tab_restore_service_browsertest.cc @@ -4,9 +4,10 @@ #include "base/stringprintf.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/sessions/session_service_factory.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/session_types_test_helper.h" #include "chrome/browser/sessions/tab_restore_service.h" #include "chrome/browser/sessions/tab_restore_service_factory.h" #include "chrome/browser/ui/browser_window.h" @@ -119,9 +120,9 @@ class TabRestoreServiceTest : public ChromeRenderViewHostTestHarness { session_service->SetSelectedTabInWindow(window_id, 0); if (pinned) session_service->SetPinnedState(window_id, tab_id, true); - scoped_ptr<NavigationEntry> entry(NavigationEntry::Create()); - entry->SetURL(url1_); - session_service->UpdateTabNavigation(window_id, tab_id, 0, *entry.get()); + session_service->UpdateTabNavigation( + window_id, tab_id, + SessionTypesTestHelper::CreateNavigation(url1_.spec(), "title")); } // Creates a SessionService and assigns it to the Profile. The SessionService @@ -557,10 +558,10 @@ TEST_F(TabRestoreServiceTest, PruneEntries) { const size_t max_entries = TabRestoreService::kMaxEntries; for (size_t i = 0; i < max_entries + 5; i++) { - TabNavigation navigation; - navigation.set_virtual_url(GURL(StringPrintf("http://%d", - static_cast<int>(i)))); - navigation.set_title(ASCIIToUTF16(StringPrintf("%d", static_cast<int>(i)))); + TabNavigation navigation = + SessionTypesTestHelper::CreateNavigation( + StringPrintf("http://%d", static_cast<int>(i)), + StringPrintf("%d", static_cast<int>(i))); Tab* tab = new Tab(); tab->navigations.push_back(navigation); @@ -578,10 +579,9 @@ TEST_F(TabRestoreServiceTest, PruneEntries) { EXPECT_EQ(max_entries, service_->entries_.size()); // Prune older first. - TabNavigation navigation; const char kRecentUrl[] = "http://recent"; - navigation.set_virtual_url(GURL(kRecentUrl)); - navigation.set_title(ASCIIToUTF16("Most recent")); + TabNavigation navigation = + SessionTypesTestHelper::CreateNavigation(kRecentUrl, "Most recent"); Tab* tab = new Tab(); tab->navigations.push_back(navigation); tab->current_navigation_index = 0; @@ -594,8 +594,9 @@ TEST_F(TabRestoreServiceTest, PruneEntries) { navigations[0].virtual_url()); // Ignore NTPs. - navigation.set_virtual_url(GURL(chrome::kChromeUINewTabURL)); - navigation.set_title(ASCIIToUTF16("New tab")); + navigation = + SessionTypesTestHelper::CreateNavigation( + chrome::kChromeUINewTabURL, "New tab"); tab = new Tab(); tab->navigations.push_back(navigation); |