Chromium Code Reviews| 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..35ee139bff726e16b2d29e5cdcf374110662c4f8 100644 |
| --- a/chrome/browser/sessions/session_types.cc |
| +++ b/chrome/browser/sessions/session_types.cc |
| @@ -4,118 +4,480 @@ |
| #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 "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) { |
| -} |
| - |
| -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) { |
| + 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(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_) { |
| +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() { |
| +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, |
|
sky
2012/09/17 14:03:36
Each param on its own line. Any how about a templa
akalin
2012/09/17 23:24:32
Put them on their own lines. Can't template, sinc
|
| + 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::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; |
| +// 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()); |
| + } |
| } |
| -// 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); |
| +// 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_); |
| + |
| + int type_mask = 0; |
|
sky
2012/09/17 14:03:36
nit: type_mask = has_post_data ? HAS_POST_DATA : 0
akalin
2012/09/17 23:24:32
Done.
|
| + if (has_post_data_) { |
|
sky
2012/09/17 14:03:36
no {}
akalin
2012/09/17 23:24:32
moot
|
| + type_mask |= HAS_POST_DATA; |
| + } |
| + 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. |
| +} |
| + |
| +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_)) { |
|
sky
2012/09/17 14:03:36
no {}
akalin
2012/09/17 23:24:32
Done.
|
| + is_overriding_user_agent_ = false; |
| + } |
| + } |
| + |
| + // TODO(akalin): Restore timestamp when it is persisted. |
| + return true; |
| +} |
| + |
| +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; |
| +} |
| + |
| +TabNavigation TabNavigation::CreateForTest(const std::string& virtual_url, |
| + const std::string& title) { |
| + TabNavigation navigation; |
| + navigation.index_ = 0; |
| + navigation.referrer_ = |
| + content::Referrer(GURL("http://www.referrer.com"), |
| + WebKit::WebReferrerPolicyDefault); |
| + navigation.virtual_url_ = GURL(virtual_url); |
| + navigation.title_ = UTF8ToUTF16(title); |
| + navigation.content_state_ = "fake_state"; |
| + navigation.timestamp_ = base::Time::Now(); |
| + return navigation; |
| +} |
| + |
| +const content::Referrer& TabNavigation::GetReferrerForTest() const { |
| + return referrer_; |
| +} |
| + |
| +content::PageTransition TabNavigation::GetTransitionTypeForTest() const { |
| + return transition_type_; |
| +} |
| + |
| +bool TabNavigation::GetHasPostDataForTest() const { |
| + return has_post_data_; |
| +} |
| + |
| +int64 TabNavigation::GetPostIdForTest() const { |
| + return post_id_; |
| +} |
| + |
| +const GURL& TabNavigation::GetOriginalRequestURLForTest() const { |
| + return original_request_url_; |
| +} |
| + |
| +bool TabNavigation::GetIsOverridingUserAgentForTest() const { |
| + return is_overriding_user_agent_; |
| +} |
| + |
| +void TabNavigation::SetContentStateForTest(const std::string& content_state) { |
| + content_state_ = content_state; |
| +} |
| + |
| +void TabNavigation::SetTransitionTypeForTest( |
| + content::PageTransition transition_type) { |
| + transition_type_ = transition_type; |
| +} |
| + |
| +void TabNavigation::SetOriginalRequestURLForTest( |
| + const GURL& original_request_url) { |
| + original_request_url_ = original_request_url; |
| +} |
| + |
| +void TabNavigation::SetHasPostDataForTest(bool has_post_data) { |
| + has_post_data_ = has_post_data; |
| +} |
| + |
| +void TabNavigation::SetIsOverridingUserAgentForTest( |
| + bool is_overriding_user_agent) { |
| + is_overriding_user_agent_ = is_overriding_user_agent; |
| } |
| // SessionTab ----------------------------------------------------------------- |