summaryrefslogtreecommitdiffstats
path: root/chrome/browser/sessions
diff options
context:
space:
mode:
authorakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-19 04:04:16 +0000
committerakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-19 04:04:16 +0000
commit9dd1d5809c8420f1e636154424826bf575804cdc (patch)
tree2a9709d108d300c8ee303332674e3468befcaac2 /chrome/browser/sessions
parenta26e6666e814600a133dae854ab6fa0762b0b51f (diff)
downloadchromium_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')
-rw-r--r--chrome/browser/sessions/DEPS1
-rw-r--r--chrome/browser/sessions/base_session_service.cc94
-rw-r--r--chrome/browser/sessions/base_session_service.h7
-rw-r--r--chrome/browser/sessions/session_restore.cc2
-rw-r--r--chrome/browser/sessions/session_restore_android.cc6
-rw-r--r--chrome/browser/sessions/session_restore_browsertest.cc27
-rw-r--r--chrome/browser/sessions/session_service.cc30
-rw-r--r--chrome/browser/sessions/session_service.h3
-rw-r--r--chrome/browser/sessions/session_service_test_helper.cc12
-rw-r--r--chrome/browser/sessions/session_service_unittest.cc258
-rw-r--r--chrome/browser/sessions/session_types.cc456
-rw-r--r--chrome/browser/sessions/session_types.h158
-rw-r--r--chrome/browser/sessions/session_types_test_helper.cc92
-rw-r--r--chrome/browser/sessions/session_types_test_helper.h60
-rw-r--r--chrome/browser/sessions/session_types_unittest.cc246
-rw-r--r--chrome/browser/sessions/tab_restore_service.cc12
-rw-r--r--chrome/browser/sessions/tab_restore_service_browsertest.cc27
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);