| Index: chrome/browser/sessions/session_types.cc
|
| diff --git a/chrome/browser/sessions/session_types.cc b/chrome/browser/sessions/session_types.cc
|
| index 5691f8d635ce2e50f17356e1ec7168dc5124c04a..c31ddf5b4d449ae70799f8233d37a6eddec9758e 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 -----------------------------------------------------------------
|
|
|