diff options
author | Zeno Albisser <zeno.albisser@digia.com> | 2013-08-15 21:46:11 +0200 |
---|---|---|
committer | Zeno Albisser <zeno.albisser@digia.com> | 2013-08-15 21:46:11 +0200 |
commit | 679147eead574d186ebf3069647b4c23e8ccace6 (patch) | |
tree | fc247a0ac8ff119f7c8550879ebb6d3dd8d1ff69 /chromium/components/sessions | |
download | qtwebengine-chromium-679147eead574d186ebf3069647b4c23e8ccace6.tar.gz |
Initial import.
Diffstat (limited to 'chromium/components/sessions')
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(×tamp_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_ |