summaryrefslogtreecommitdiff
path: root/chromium/components/sessions
diff options
context:
space:
mode:
authorZeno Albisser <zeno.albisser@digia.com>2013-08-15 21:46:11 +0200
committerZeno Albisser <zeno.albisser@digia.com>2013-08-15 21:46:11 +0200
commit679147eead574d186ebf3069647b4c23e8ccace6 (patch)
treefc247a0ac8ff119f7c8550879ebb6d3dd8d1ff69 /chromium/components/sessions
downloadqtwebengine-chromium-679147eead574d186ebf3069647b4c23e8ccace6.tar.gz
Initial import.
Diffstat (limited to 'chromium/components/sessions')
-rw-r--r--chromium/components/sessions/DEPS7
-rw-r--r--chromium/components/sessions/OWNERS2
-rw-r--r--chromium/components/sessions/serialized_navigation_entry.cc475
-rw-r--r--chromium/components/sessions/serialized_navigation_entry.h160
-rw-r--r--chromium/components/sessions/serialized_navigation_entry_test_helper.cc84
-rw-r--r--chromium/components/sessions/serialized_navigation_entry_test_helper.h63
-rw-r--r--chromium/components/sessions/serialized_navigation_entry_unittest.cc290
-rw-r--r--chromium/components/sessions/sessions_export.h29
8 files changed, 1110 insertions, 0 deletions
diff --git a/chromium/components/sessions/DEPS b/chromium/components/sessions/DEPS
new file mode 100644
index 00000000000..fd2f190d0a5
--- /dev/null
+++ b/chromium/components/sessions/DEPS
@@ -0,0 +1,7 @@
+include_rules = [
+ "+content/public/browser",
+ "+content/public/common",
+ "+sync",
+ "+third_party/WebKit/public/platform",
+ "+webkit",
+]
diff --git a/chromium/components/sessions/OWNERS b/chromium/components/sessions/OWNERS
new file mode 100644
index 00000000000..73674b786cb
--- /dev/null
+++ b/chromium/components/sessions/OWNERS
@@ -0,0 +1,2 @@
+marja@chromium.org
+sky@chromium.org
diff --git a/chromium/components/sessions/serialized_navigation_entry.cc b/chromium/components/sessions/serialized_navigation_entry.cc
new file mode 100644
index 00000000000..5e4183cf5d2
--- /dev/null
+++ b/chromium/components/sessions/serialized_navigation_entry.cc
@@ -0,0 +1,475 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/sessions/serialized_navigation_entry.h"
+
+#include "base/pickle.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/browser/favicon_status.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/navigation_entry.h"
+#include "sync/protocol/session_specifics.pb.h"
+#include "sync/util/time.h"
+#include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
+
+using content::NavigationEntry;
+
+namespace sessions {
+
+const char kSearchTermsKey[] = "search_terms";
+
+SerializedNavigationEntry::SerializedNavigationEntry()
+ : index_(-1),
+ unique_id_(0),
+ transition_type_(content::PAGE_TRANSITION_TYPED),
+ has_post_data_(false),
+ post_id_(-1),
+ is_overriding_user_agent_(false),
+ blocked_state_(STATE_INVALID) {}
+
+SerializedNavigationEntry::~SerializedNavigationEntry() {}
+
+// static
+SerializedNavigationEntry SerializedNavigationEntry::FromNavigationEntry(
+ int index,
+ const NavigationEntry& entry) {
+ SerializedNavigationEntry navigation;
+ navigation.index_ = index;
+ navigation.unique_id_ = entry.GetUniqueID();
+ navigation.referrer_ = entry.GetReferrer();
+ navigation.virtual_url_ = entry.GetVirtualURL();
+ navigation.title_ = entry.GetTitle();
+ navigation.page_state_ = entry.GetPageState();
+ 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_ = entry.GetTimestamp();
+ // If you want to navigate a named frame in Chrome, you will first need to
+ // add support for persisting it. It is currently only used for layout tests.
+ CHECK(entry.GetFrameToNavigate().empty());
+ entry.GetExtraData(kSearchTermsKey, &navigation.search_terms_);
+ if (entry.GetFavicon().valid)
+ navigation.favicon_url_ = entry.GetFavicon().url;
+
+ return navigation;
+}
+
+SerializedNavigationEntry SerializedNavigationEntry::FromSyncData(
+ int index,
+ const sync_pb::TabNavigation& sync_data) {
+ SerializedNavigationEntry navigation;
+ navigation.index_ = index;
+ navigation.unique_id_ = sync_data.unique_id();
+ navigation.referrer_ =
+ content::Referrer(GURL(sync_data.referrer()),
+ WebKit::WebReferrerPolicyDefault);
+ navigation.virtual_url_ = GURL(sync_data.virtual_url());
+ navigation.title_ = UTF8ToUTF16(sync_data.title());
+ navigation.page_state_ =
+ content::PageState::CreateFromEncodedData(sync_data.state());
+
+ uint32 transition = 0;
+ if (sync_data.has_page_transition()) {
+ switch (sync_data.page_transition()) {
+ case sync_pb::SyncEnums_PageTransition_LINK:
+ transition = content::PAGE_TRANSITION_LINK;
+ break;
+ case sync_pb::SyncEnums_PageTransition_TYPED:
+ transition = content::PAGE_TRANSITION_TYPED;
+ break;
+ case sync_pb::SyncEnums_PageTransition_AUTO_BOOKMARK:
+ transition = content::PAGE_TRANSITION_AUTO_BOOKMARK;
+ break;
+ case sync_pb::SyncEnums_PageTransition_AUTO_SUBFRAME:
+ transition = content::PAGE_TRANSITION_AUTO_SUBFRAME;
+ break;
+ case sync_pb::SyncEnums_PageTransition_MANUAL_SUBFRAME:
+ transition = content::PAGE_TRANSITION_MANUAL_SUBFRAME;
+ break;
+ case sync_pb::SyncEnums_PageTransition_GENERATED:
+ transition = content::PAGE_TRANSITION_GENERATED;
+ break;
+ case sync_pb::SyncEnums_PageTransition_AUTO_TOPLEVEL:
+ transition = content::PAGE_TRANSITION_AUTO_TOPLEVEL;
+ break;
+ case sync_pb::SyncEnums_PageTransition_FORM_SUBMIT:
+ transition = content::PAGE_TRANSITION_FORM_SUBMIT;
+ break;
+ case sync_pb::SyncEnums_PageTransition_RELOAD:
+ transition = content::PAGE_TRANSITION_RELOAD;
+ break;
+ case sync_pb::SyncEnums_PageTransition_KEYWORD:
+ transition = content::PAGE_TRANSITION_KEYWORD;
+ break;
+ case sync_pb::SyncEnums_PageTransition_KEYWORD_GENERATED:
+ transition =
+ content::PAGE_TRANSITION_KEYWORD_GENERATED;
+ break;
+ default:
+ transition = content::PAGE_TRANSITION_LINK;
+ break;
+ }
+ }
+
+ if (sync_data.has_redirect_type()) {
+ switch (sync_data.redirect_type()) {
+ case sync_pb::SyncEnums_PageTransitionRedirectType_CLIENT_REDIRECT:
+ transition |= content::PAGE_TRANSITION_CLIENT_REDIRECT;
+ break;
+ case sync_pb::SyncEnums_PageTransitionRedirectType_SERVER_REDIRECT:
+ transition |= content::PAGE_TRANSITION_SERVER_REDIRECT;
+ break;
+ }
+ }
+ if (sync_data.navigation_forward_back())
+ transition |= content::PAGE_TRANSITION_FORWARD_BACK;
+ if (sync_data.navigation_from_address_bar())
+ transition |= content::PAGE_TRANSITION_FROM_ADDRESS_BAR;
+ if (sync_data.navigation_home_page())
+ transition |= content::PAGE_TRANSITION_HOME_PAGE;
+ if (sync_data.navigation_chain_start())
+ transition |= content::PAGE_TRANSITION_CHAIN_START;
+ if (sync_data.navigation_chain_end())
+ transition |= content::PAGE_TRANSITION_CHAIN_END;
+
+ navigation.transition_type_ =
+ static_cast<content::PageTransition>(transition);
+
+ navigation.timestamp_ = base::Time();
+ navigation.search_terms_ = UTF8ToUTF16(sync_data.search_terms());
+ if (sync_data.has_favicon_url())
+ navigation.favicon_url_ = GURL(sync_data.favicon_url());
+
+ // We shouldn't sync session data for managed users down at the moment.
+ DCHECK(!sync_data.has_blocked_state());
+ DCHECK_EQ(0, sync_data.content_pack_categories_size());
+
+ return navigation;
+}
+
+namespace {
+
+// Helper used by SerializedNavigationEntry::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());
+ }
+}
+
+// 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_
+// page_state_
+// transition_type_
+//
+// Added on later:
+//
+// type_mask (has_post_data_)
+// referrer_
+// original_request_url_
+// is_overriding_user_agent_
+// timestamp_
+// search_terms_
+
+void SerializedNavigationEntry::WriteToPickle(int max_size,
+ Pickle* pickle) const {
+ pickle->WriteInt(index_);
+
+ int bytes_written = 0;
+
+ WriteStringToPickle(pickle, &bytes_written, max_size,
+ virtual_url_.spec());
+
+ WriteString16ToPickle(pickle, &bytes_written, max_size, title_);
+
+ content::PageState page_state = page_state_;
+ if (has_post_data_)
+ page_state = page_state.RemovePasswordData();
+
+ WriteStringToPickle(pickle, &bytes_written, max_size,
+ page_state.ToEncodedData());
+
+ pickle->WriteInt(transition_type_);
+
+ const int type_mask = has_post_data_ ? HAS_POST_DATA : 0;
+ pickle->WriteInt(type_mask);
+
+ WriteStringToPickle(
+ pickle, &bytes_written, max_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_size,
+ original_request_url_.is_valid() ?
+ original_request_url_.spec() : std::string());
+ pickle->WriteBool(is_overriding_user_agent_);
+ pickle->WriteInt64(timestamp_.ToInternalValue());
+
+ WriteString16ToPickle(pickle, &bytes_written, max_size, search_terms_);
+}
+
+bool SerializedNavigationEntry::ReadFromPickle(PickleIterator* iterator) {
+ *this = SerializedNavigationEntry();
+ std::string virtual_url_spec, page_state_data;
+ int transition_type_int = 0;
+ if (!iterator->ReadInt(&index_) ||
+ !iterator->ReadString(&virtual_url_spec) ||
+ !iterator->ReadString16(&title_) ||
+ !iterator->ReadString(&page_state_data) ||
+ !iterator->ReadInt(&transition_type_int))
+ return false;
+ virtual_url_ = GURL(virtual_url_spec);
+ page_state_ = content::PageState::CreateFromEncodedData(page_state_data);
+ 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;
+
+ int64 timestamp_internal_value = 0;
+ if (iterator->ReadInt64(&timestamp_internal_value)) {
+ timestamp_ = base::Time::FromInternalValue(timestamp_internal_value);
+ } else {
+ timestamp_ = base::Time();
+ }
+
+ // If the search terms field can't be found, leave it empty.
+ if (!iterator->ReadString16(&search_terms_))
+ search_terms_.clear();
+ }
+
+ return true;
+}
+
+scoped_ptr<NavigationEntry> SerializedNavigationEntry::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->SetTitle(title_);
+ entry->SetPageState(page_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_);
+ entry->SetTimestamp(timestamp_);
+ entry->SetExtraData(kSearchTermsKey, search_terms_);
+
+ // These fields should have default values.
+ DCHECK_EQ(STATE_INVALID, blocked_state_);
+ DCHECK_EQ(0u, content_pack_categories_.size());
+
+ return entry.Pass();
+}
+
+// TODO(zea): perhaps sync state (scroll position, form entries, etc.) as well?
+// See http://crbug.com/67068.
+sync_pb::TabNavigation SerializedNavigationEntry::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_));
+
+ // Page transition core.
+ COMPILE_ASSERT(content::PAGE_TRANSITION_LAST_CORE ==
+ content::PAGE_TRANSITION_KEYWORD_GENERATED,
+ PageTransitionCoreBounds);
+ switch (PageTransitionStripQualifier(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;
+ default:
+ NOTREACHED();
+ }
+
+ // Page transition qualifiers.
+ if (PageTransitionIsRedirect(transition_type_)) {
+ if (transition_type_ & content::PAGE_TRANSITION_CLIENT_REDIRECT) {
+ sync_data.set_redirect_type(
+ sync_pb::SyncEnums_PageTransitionRedirectType_CLIENT_REDIRECT);
+ } else if (transition_type_ & content::PAGE_TRANSITION_SERVER_REDIRECT) {
+ sync_data.set_redirect_type(
+ sync_pb::SyncEnums_PageTransitionRedirectType_SERVER_REDIRECT);
+ }
+ }
+ sync_data.set_navigation_forward_back(
+ (transition_type_ & content::PAGE_TRANSITION_FORWARD_BACK) != 0);
+ sync_data.set_navigation_from_address_bar(
+ (transition_type_ & content::PAGE_TRANSITION_FROM_ADDRESS_BAR) != 0);
+ sync_data.set_navigation_home_page(
+ (transition_type_ & content::PAGE_TRANSITION_HOME_PAGE) != 0);
+ sync_data.set_navigation_chain_start(
+ (transition_type_ & content::PAGE_TRANSITION_CHAIN_START) != 0);
+ sync_data.set_navigation_chain_end(
+ (transition_type_ & content::PAGE_TRANSITION_CHAIN_END) != 0);
+
+ sync_data.set_unique_id(unique_id_);
+ sync_data.set_timestamp_msec(syncer::TimeToProtoTime(timestamp_));
+ // The full-resolution timestamp works as a global ID.
+ sync_data.set_global_id(timestamp_.ToInternalValue());
+
+ sync_data.set_search_terms(UTF16ToUTF8(search_terms_));
+
+ if (favicon_url_.is_valid())
+ sync_data.set_favicon_url(favicon_url_.spec());
+
+ if (blocked_state_ != STATE_INVALID) {
+ sync_data.set_blocked_state(
+ static_cast<sync_pb::TabNavigation_BlockedState>(blocked_state_));
+ }
+
+ for (std::set<std::string>::const_iterator it =
+ content_pack_categories_.begin();
+ it != content_pack_categories_.end(); ++it) {
+ sync_data.add_content_pack_categories(*it);
+ }
+
+ return sync_data;
+}
+
+// static
+std::vector<NavigationEntry*> SerializedNavigationEntry::ToNavigationEntries(
+ const std::vector<SerializedNavigationEntry>& navigations,
+ content::BrowserContext* browser_context) {
+ int page_id = 0;
+ std::vector<NavigationEntry*> entries;
+ for (std::vector<SerializedNavigationEntry>::const_iterator
+ it = navigations.begin(); it != navigations.end(); ++it) {
+ entries.push_back(
+ it->ToNavigationEntry(page_id, browser_context).release());
+ ++page_id;
+ }
+ return entries;
+}
+
+} // namespace sessions
diff --git a/chromium/components/sessions/serialized_navigation_entry.h b/chromium/components/sessions/serialized_navigation_entry.h
new file mode 100644
index 00000000000..e5813dce0d8
--- /dev/null
+++ b/chromium/components/sessions/serialized_navigation_entry.h
@@ -0,0 +1,160 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SESSIONS_SERIALIZED_NAVIGATION_ENTRY_H_
+#define COMPONENTS_SESSIONS_SERIALIZED_NAVIGATION_ENTRY_H_
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string16.h"
+#include "base/time/time.h"
+#include "components/sessions/sessions_export.h"
+#include "content/public/common/page_state.h"
+#include "content/public/common/page_transition_types.h"
+#include "content/public/common/referrer.h"
+#include "url/gurl.h"
+
+class Pickle;
+class PickleIterator;
+
+namespace content {
+class BrowserContext;
+class NavigationEntry;
+}
+
+namespace sync_pb {
+class TabNavigation;
+}
+
+namespace sessions {
+
+class SerializedNavigationEntryTestHelper;
+
+// The key used to store search terms data in the NavigationEntry.
+SESSIONS_EXPORT extern const char kSearchTermsKey[];
+
+// SerializedNavigationEntry 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.
+//
+// Default copy constructor and assignment operator welcome.
+class SESSIONS_EXPORT SerializedNavigationEntry {
+ public:
+ enum BlockedState {
+ STATE_INVALID = 0,
+ STATE_ALLOWED = 1,
+ STATE_BLOCKED = 2,
+ };
+
+ // Creates an invalid (index < 0) SerializedNavigationEntry.
+ SerializedNavigationEntry();
+ ~SerializedNavigationEntry();
+
+ // Construct a SerializedNavigationEntry for a particular index from the given
+ // NavigationEntry.
+ static SerializedNavigationEntry FromNavigationEntry(
+ int index,
+ const content::NavigationEntry& entry);
+
+ // Construct a SerializedNavigationEntry for a particular index from a sync
+ // protocol buffer. Note that the sync protocol buffer doesn't contain all
+ // SerializedNavigationEntry fields. Also, the timestamp of the returned
+ // SerializedNavigationEntry is nulled out, as we assume that the protocol
+ // buffer is from a foreign session.
+ static SerializedNavigationEntry FromSyncData(
+ int index,
+ const sync_pb::TabNavigation& sync_data);
+
+ // Note that not all SerializedNavigationEntry fields are preserved.
+ // |max_size| is the max number of bytes to write.
+ void WriteToPickle(int max_size, Pickle* pickle) const;
+ bool ReadFromPickle(PickleIterator* iterator);
+
+ // Convert this SerializedNavigationEntry 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 SerializedNavigationEntry
+ // fields.
+ sync_pb::TabNavigation ToSyncData() const;
+
+ // The index in the NavigationController. This SerializedNavigationEntry is
+ // valid only when the index is non-negative.
+ int index() const { return index_; }
+ void set_index(int index) { index_ = index; }
+
+ // 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 content::PageState& page_state() const { return page_state_; }
+ const string16& search_terms() const { return search_terms_; }
+ const GURL& favicon_url() const { return favicon_url_; }
+ const content::Referrer& referrer() const { return referrer_; }
+ content::PageTransition transition_type() const {
+ return transition_type_;
+ }
+ bool has_post_data() const { return has_post_data_; }
+ int64 post_id() const { return post_id_; }
+ const GURL& original_request_url() const { return original_request_url_; }
+ bool is_overriding_user_agent() const { return is_overriding_user_agent_; }
+ base::Time timestamp() const { return timestamp_; }
+
+ BlockedState blocked_state() { return blocked_state_; }
+ void set_blocked_state(BlockedState blocked_state) {
+ blocked_state_ = blocked_state;
+ }
+ std::set<std::string> content_pack_categories() {
+ return content_pack_categories_;
+ }
+ void set_content_pack_categories(
+ const std::set<std::string>& content_pack_categories) {
+ content_pack_categories_ = content_pack_categories;
+ }
+
+ // Converts a set of SerializedNavigationEntrys into a list of
+ // NavigationEntrys with sequential page IDs and the given context. The caller
+ // owns the returned NavigationEntrys.
+ static std::vector<content::NavigationEntry*> ToNavigationEntries(
+ const std::vector<SerializedNavigationEntry>& navigations,
+ content::BrowserContext* browser_context);
+
+ private:
+ friend class SerializedNavigationEntryTestHelper;
+
+ // Index in the NavigationController.
+ int index_;
+
+ // Member variables corresponding to NavigationEntry fields.
+ int unique_id_;
+ content::Referrer referrer_;
+ GURL virtual_url_;
+ string16 title_;
+ content::PageState page_state_;
+ content::PageTransition transition_type_;
+ bool has_post_data_;
+ int64 post_id_;
+ GURL original_request_url_;
+ bool is_overriding_user_agent_;
+ base::Time timestamp_;
+ string16 search_terms_;
+ GURL favicon_url_;
+
+ // Additional information.
+ BlockedState blocked_state_;
+ std::set<std::string> content_pack_categories_;
+};
+
+} // namespace sessions
+
+#endif // COMPONENTS_SESSIONS_SERIALIZED_NAVIGATION_ENTRY_H_
diff --git a/chromium/components/sessions/serialized_navigation_entry_test_helper.cc b/chromium/components/sessions/serialized_navigation_entry_test_helper.cc
new file mode 100644
index 00000000000..f4a7e2eba6a
--- /dev/null
+++ b/chromium/components/sessions/serialized_navigation_entry_test_helper.cc
@@ -0,0 +1,84 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/sessions/serialized_navigation_entry_test_helper.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
+#include "components/sessions/serialized_navigation_entry.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
+#include "url/gurl.h"
+
+namespace sessions {
+
+// static
+void SerializedNavigationEntryTestHelper::ExpectNavigationEquals(
+ const SerializedNavigationEntry& expected,
+ const SerializedNavigationEntry& 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.page_state_, actual.page_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_);
+}
+
+// static
+SerializedNavigationEntry SerializedNavigationEntryTestHelper::CreateNavigation(
+ const std::string& virtual_url,
+ const std::string& title) {
+ SerializedNavigationEntry 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.page_state_ =
+ content::PageState::CreateFromEncodedData("fake_state");
+ navigation.timestamp_ = base::Time::Now();
+ return navigation;
+}
+
+// static
+void SerializedNavigationEntryTestHelper::SetPageState(
+ const content::PageState& page_state,
+ SerializedNavigationEntry* navigation) {
+ navigation->page_state_ = page_state;
+}
+
+// static
+void SerializedNavigationEntryTestHelper::SetHasPostData(
+ bool has_post_data,
+ SerializedNavigationEntry* navigation) {
+ navigation->has_post_data_ = has_post_data;
+}
+
+// static
+void SerializedNavigationEntryTestHelper::SetOriginalRequestURL(
+ const GURL& original_request_url,
+ SerializedNavigationEntry* navigation) {
+ navigation->original_request_url_ = original_request_url;
+}
+
+// static
+void SerializedNavigationEntryTestHelper::SetIsOverridingUserAgent(
+ bool is_overriding_user_agent,
+ SerializedNavigationEntry* navigation) {
+ navigation->is_overriding_user_agent_ = is_overriding_user_agent;
+}
+
+// static
+void SerializedNavigationEntryTestHelper::SetTimestamp(
+ base::Time timestamp,
+ SerializedNavigationEntry* navigation) {
+ navigation->timestamp_ = timestamp;
+}
+
+} // namespace sessions
diff --git a/chromium/components/sessions/serialized_navigation_entry_test_helper.h b/chromium/components/sessions/serialized_navigation_entry_test_helper.h
new file mode 100644
index 00000000000..a653f22d67e
--- /dev/null
+++ b/chromium/components/sessions/serialized_navigation_entry_test_helper.h
@@ -0,0 +1,63 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SESSIONS_SESSION_TYPES_TEST_HELPER_H_
+#define COMPONENTS_SESSIONS_SESSION_TYPES_TEST_HELPER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "content/public/common/page_transition_types.h"
+
+class GURL;
+
+namespace base {
+class Time;
+}
+
+namespace content {
+class PageState;
+struct Referrer;
+}
+
+namespace sessions {
+
+class SerializedNavigationEntry;
+
+// Set of test functions to manipulate a SerializedNavigationEntry.
+class SerializedNavigationEntryTestHelper {
+ public:
+ // Compares the two entries. This uses EXPECT_XXX on each member, if your test
+ // needs to stop after this wrap calls to this in EXPECT_NO_FATAL_FAILURE.
+ static void ExpectNavigationEquals(const SerializedNavigationEntry& expected,
+ const SerializedNavigationEntry& actual);
+
+ // Create a SerializedNavigationEntry with the given URL and title and some
+ // common values for the other fields.
+ static SerializedNavigationEntry CreateNavigation(
+ const std::string& virtual_url,
+ const std::string& title);
+
+ static void SetPageState(const content::PageState& page_state,
+ SerializedNavigationEntry* navigation);
+
+ static void SetHasPostData(bool has_post_data,
+ SerializedNavigationEntry* navigation);
+
+ static void SetOriginalRequestURL(const GURL& original_request_url,
+ SerializedNavigationEntry* navigation);
+
+ static void SetIsOverridingUserAgent(bool is_overriding_user_agent,
+ SerializedNavigationEntry* navigation);
+
+ static void SetTimestamp(base::Time timestamp,
+ SerializedNavigationEntry* navigation);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(SerializedNavigationEntryTestHelper);
+};
+
+} // sessions
+
+#endif // COMPONENTS_SESSIONS_SESSION_TYPES_TEST_HELPER_H_
diff --git a/chromium/components/sessions/serialized_navigation_entry_unittest.cc b/chromium/components/sessions/serialized_navigation_entry_unittest.cc
new file mode 100644
index 00000000000..5f052fe23e7
--- /dev/null
+++ b/chromium/components/sessions/serialized_navigation_entry_unittest.cc
@@ -0,0 +1,290 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/sessions/serialized_navigation_entry.h"
+
+#include <cstddef>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/pickle.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
+#include "content/public/browser/favicon_status.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/common/page_transition_types.h"
+#include "content/public/common/referrer.h"
+#include "sync/protocol/session_specifics.pb.h"
+#include "sync/util/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
+#include "url/gurl.h"
+
+namespace sessions {
+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 content::PageState kPageState =
+ content::PageState::CreateFromEncodedData("page state");
+const content::PageTransition kTransitionType =
+ static_cast<content::PageTransition>(
+ content::PAGE_TRANSITION_AUTO_SUBFRAME |
+ content::PAGE_TRANSITION_HOME_PAGE |
+ content::PAGE_TRANSITION_CLIENT_REDIRECT);
+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 string16 kSearchTerms = ASCIIToUTF16("my search terms");
+const GURL kFaviconURL("http://virtual-url.com/favicon.ico");
+
+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->SetPageState(kPageState);
+ navigation_entry->SetTransitionType(kTransitionType);
+ navigation_entry->SetHasPostData(kHasPostData);
+ navigation_entry->SetPostID(kPostID);
+ navigation_entry->SetOriginalRequestURL(kOriginalRequestURL);
+ navigation_entry->SetIsOverridingUserAgent(kIsOverridingUserAgent);
+ navigation_entry->SetTimestamp(kTimestamp);
+ navigation_entry->SetExtraData(kSearchTermsKey, kSearchTerms);
+ navigation_entry->GetFavicon().valid = true;
+ navigation_entry->GetFavicon().url = kFaviconURL;
+ 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(kPageState.ToEncodedData());
+ sync_data.set_page_transition(
+ sync_pb::SyncEnums_PageTransition_AUTO_SUBFRAME);
+ sync_data.set_unique_id(kUniqueID);
+ sync_data.set_timestamp_msec(syncer::TimeToProtoTime(kTimestamp));
+ sync_data.set_redirect_type(sync_pb::SyncEnums::CLIENT_REDIRECT);
+ sync_data.set_navigation_home_page(true);
+ sync_data.set_search_terms(UTF16ToUTF8(kSearchTerms));
+ sync_data.set_favicon_url(kFaviconURL.spec());
+ return sync_data;
+}
+
+// Create a default SerializedNavigationEntry. All its fields should be
+// initialized to their respective default values.
+TEST(SerializedNavigationEntryTest, DefaultInitializer) {
+ const SerializedNavigationEntry navigation;
+ EXPECT_EQ(-1, navigation.index());
+ EXPECT_EQ(0, navigation.unique_id());
+ EXPECT_EQ(GURL(), navigation.referrer().url);
+ EXPECT_EQ(WebKit::WebReferrerPolicyDefault, navigation.referrer().policy);
+ EXPECT_EQ(GURL(), navigation.virtual_url());
+ EXPECT_TRUE(navigation.title().empty());
+ EXPECT_FALSE(navigation.page_state().IsValid());
+ EXPECT_EQ(content::PAGE_TRANSITION_TYPED, navigation.transition_type());
+ EXPECT_FALSE(navigation.has_post_data());
+ EXPECT_EQ(-1, navigation.post_id());
+ EXPECT_EQ(GURL(), navigation.original_request_url());
+ EXPECT_FALSE(navigation.is_overriding_user_agent());
+ EXPECT_TRUE(navigation.timestamp().is_null());
+ EXPECT_TRUE(navigation.search_terms().empty());
+ EXPECT_FALSE(navigation.favicon_url().is_valid());
+}
+
+// Create a SerializedNavigationEntry from a NavigationEntry. All its fields
+// should match the NavigationEntry's.
+TEST(SerializedNavigationEntryTest, FromNavigationEntry) {
+ const scoped_ptr<content::NavigationEntry> navigation_entry(
+ MakeNavigationEntryForTest());
+
+ const SerializedNavigationEntry& navigation =
+ SerializedNavigationEntry::FromNavigationEntry(kIndex, *navigation_entry);
+
+ EXPECT_EQ(kIndex, navigation.index());
+
+ EXPECT_EQ(navigation_entry->GetUniqueID(), navigation.unique_id());
+ EXPECT_EQ(kReferrer.url, navigation.referrer().url);
+ EXPECT_EQ(kReferrer.policy, navigation.referrer().policy);
+ EXPECT_EQ(kVirtualURL, navigation.virtual_url());
+ EXPECT_EQ(kTitle, navigation.title());
+ EXPECT_EQ(kPageState, navigation.page_state());
+ EXPECT_EQ(kTransitionType, navigation.transition_type());
+ EXPECT_EQ(kHasPostData, navigation.has_post_data());
+ EXPECT_EQ(kPostID, navigation.post_id());
+ EXPECT_EQ(kOriginalRequestURL, navigation.original_request_url());
+ EXPECT_EQ(kIsOverridingUserAgent, navigation.is_overriding_user_agent());
+ EXPECT_EQ(kTimestamp, navigation.timestamp());
+ EXPECT_EQ(kFaviconURL, navigation.favicon_url());
+}
+
+// Create a SerializedNavigationEntry 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(SerializedNavigationEntryTest, FromSyncData) {
+ const sync_pb::TabNavigation sync_data = MakeSyncDataForTest();
+
+ const SerializedNavigationEntry& navigation =
+ SerializedNavigationEntry::FromSyncData(kIndex, sync_data);
+
+ EXPECT_EQ(kIndex, navigation.index());
+ EXPECT_EQ(kUniqueID, navigation.unique_id());
+ EXPECT_EQ(kReferrer.url, navigation.referrer().url);
+ EXPECT_EQ(WebKit::WebReferrerPolicyDefault, navigation.referrer().policy);
+ EXPECT_EQ(kVirtualURL, navigation.virtual_url());
+ EXPECT_EQ(kTitle, navigation.title());
+ EXPECT_EQ(kPageState, navigation.page_state());
+ EXPECT_EQ(kTransitionType, navigation.transition_type());
+ EXPECT_FALSE(navigation.has_post_data());
+ EXPECT_EQ(-1, navigation.post_id());
+ EXPECT_EQ(GURL(), navigation.original_request_url());
+ EXPECT_FALSE(navigation.is_overriding_user_agent());
+ EXPECT_TRUE(navigation.timestamp().is_null());
+ EXPECT_EQ(kSearchTerms, navigation.search_terms());
+ EXPECT_EQ(kFaviconURL, navigation.favicon_url());
+}
+
+// Create a SerializedNavigationEntry, 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(SerializedNavigationEntryTest, Pickle) {
+ const SerializedNavigationEntry& old_navigation =
+ SerializedNavigationEntry::FromNavigationEntry(
+ kIndex, *MakeNavigationEntryForTest());
+
+ Pickle pickle;
+ old_navigation.WriteToPickle(30000, &pickle);
+
+ SerializedNavigationEntry 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, new_navigation.referrer().url);
+ EXPECT_EQ(kReferrer.policy, new_navigation.referrer().policy);
+ EXPECT_EQ(kVirtualURL, new_navigation.virtual_url());
+ EXPECT_EQ(kTitle, new_navigation.title());
+ EXPECT_FALSE(new_navigation.page_state().IsValid());
+ EXPECT_EQ(kTransitionType, new_navigation.transition_type());
+ EXPECT_EQ(kHasPostData, new_navigation.has_post_data());
+ EXPECT_EQ(-1, new_navigation.post_id());
+ EXPECT_EQ(kOriginalRequestURL, new_navigation.original_request_url());
+ EXPECT_EQ(kIsOverridingUserAgent, new_navigation.is_overriding_user_agent());
+ EXPECT_EQ(kTimestamp, new_navigation.timestamp());
+ EXPECT_EQ(kSearchTerms, new_navigation.search_terms());
+}
+
+// Create a NavigationEntry, then create another one by converting to
+// a SerializedNavigationEntry 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(SerializedNavigationEntryTest, ToNavigationEntry) {
+ const scoped_ptr<content::NavigationEntry> old_navigation_entry(
+ MakeNavigationEntryForTest());
+
+ const SerializedNavigationEntry& navigation =
+ SerializedNavigationEntry::FromNavigationEntry(kIndex,
+ *old_navigation_entry);
+
+ 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(kPageState, new_navigation_entry->GetPageState());
+ 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());
+ string16 search_terms;
+ new_navigation_entry->GetExtraData(kSearchTermsKey, &search_terms);
+ EXPECT_EQ(kSearchTerms, search_terms);
+}
+
+// Create a NavigationEntry, convert it to a SerializedNavigationEntry, then
+// create a sync protocol buffer from it. The protocol buffer should
+// have matching fields to the NavigationEntry (when applicable).
+TEST(SerializedNavigationEntryTest, ToSyncData) {
+ const scoped_ptr<content::NavigationEntry> navigation_entry(
+ MakeNavigationEntryForTest());
+
+ const SerializedNavigationEntry& navigation =
+ SerializedNavigationEntry::FromNavigationEntry(kIndex, *navigation_entry);
+
+ 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_TRUE(sync_data.has_redirect_type());
+ EXPECT_EQ(navigation_entry->GetUniqueID(), sync_data.unique_id());
+ EXPECT_EQ(syncer::TimeToProtoTime(kTimestamp), sync_data.timestamp_msec());
+ EXPECT_EQ(kTimestamp.ToInternalValue(), sync_data.global_id());
+ EXPECT_EQ(kFaviconURL.spec(), sync_data.favicon_url());
+}
+
+// Ensure all transition types and qualifiers are converted to/from the sync
+// SerializedNavigationEntry representation properly.
+TEST(SerializedNavigationEntryTest, TransitionTypes) {
+ scoped_ptr<content::NavigationEntry> navigation_entry(
+ MakeNavigationEntryForTest());
+ for (uint32 core_type = content::PAGE_TRANSITION_LINK;
+ core_type != content::PAGE_TRANSITION_LAST_CORE; ++core_type) {
+ // Because qualifier is a uint32, left shifting will eventually overflow
+ // and hit zero again. SERVER_REDIRECT, as the last qualifier and also
+ // in place of the sign bit, is therefore the last transition before
+ // breaking.
+ for (uint32 qualifier = content::PAGE_TRANSITION_FORWARD_BACK;
+ qualifier != 0; qualifier <<= 1) {
+ if (qualifier == 0x08000000)
+ continue; // 0x08000000 is not a valid qualifier.
+ content::PageTransition transition =
+ static_cast<content::PageTransition>(core_type | qualifier);
+
+ navigation_entry->SetTransitionType(transition);
+ const SerializedNavigationEntry& navigation =
+ SerializedNavigationEntry::FromNavigationEntry(kIndex,
+ *navigation_entry);
+ const sync_pb::TabNavigation& sync_data = navigation.ToSyncData();
+ const SerializedNavigationEntry& constructed_nav =
+ SerializedNavigationEntry::FromSyncData(kIndex, sync_data);
+ const content::PageTransition constructed_transition =
+ constructed_nav.transition_type();
+
+ EXPECT_EQ(transition, constructed_transition);
+ }
+ }
+}
+
+} // namespace
+} // namespace sessions
diff --git a/chromium/components/sessions/sessions_export.h b/chromium/components/sessions/sessions_export.h
new file mode 100644
index 00000000000..66ac82270bc
--- /dev/null
+++ b/chromium/components/sessions/sessions_export.h
@@ -0,0 +1,29 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SESSIONS_SESSIONS_EXPORT_H_
+#define COMPONENTS_SESSIONS_SESSIONS_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(SESSIONS_IMPLEMENTATION)
+#define SESSIONS_EXPORT __declspec(dllexport)
+#else
+#define SESSIONS_EXPORT __declspec(dllimport)
+#endif // defined(BASE_PREFS_IMPLEMENTATION)
+
+#else // defined(WIN32)
+#if defined(SESSIONS_IMPLEMENTATION)
+#define SESSIONS_EXPORT __attribute__((visibility("default")))
+#else
+#define SESSIONS_EXPORT
+#endif
+#endif
+
+#else // defined(COMPONENT_BUILD)
+#define SESSIONS_EXPORT
+#endif
+
+#endif // COMPONENTS_SESSIONS_SESSIONS_EXPORT_H_