123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- // Copyright 2014 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/content/content_serialized_navigation_builder.h"
- #include <string>
- #include "base/check_op.h"
- #include "components/sessions/content/content_record_password_state.h"
- #include "components/sessions/content/content_serialized_navigation_driver.h"
- #include "components/sessions/content/extended_info_handler.h"
- #include "components/sessions/content/navigation_task_id.h"
- #include "components/sessions/core/serialized_navigation_entry.h"
- #include "content/public/browser/browser_context.h"
- #include "content/public/browser/favicon_status.h"
- #include "content/public/browser/navigation_controller.h"
- #include "content/public/browser/navigation_entry.h"
- #include "content/public/browser/navigation_entry_restore_context.h"
- #include "content/public/browser/replaced_navigation_entry_data.h"
- #include "content/public/common/referrer.h"
- #include "services/network/public/cpp/shared_url_loader_factory.h"
- #include "third_party/blink/public/common/page_state/page_state.h"
- namespace sessions {
- namespace {
- absl::optional<SerializedNavigationEntry::ReplacedNavigationEntryData>
- ConvertReplacedEntryData(
- const absl::optional<content::ReplacedNavigationEntryData>& input_data) {
- if (!input_data.has_value())
- return absl::nullopt;
- SerializedNavigationEntry::ReplacedNavigationEntryData output_data;
- output_data.first_committed_url = input_data->first_committed_url;
- output_data.first_timestamp = input_data->first_timestamp;
- output_data.first_transition_type = input_data->first_transition_type;
- return output_data;
- }
- } // namespace
- // static
- SerializedNavigationEntry
- ContentSerializedNavigationBuilder::FromNavigationEntry(
- int index,
- content::NavigationEntry* entry,
- SerializationOptions serialization_options) {
- SerializedNavigationEntry navigation;
- navigation.index_ = index;
- navigation.unique_id_ = entry->GetUniqueID();
- navigation.referrer_url_ = entry->GetReferrer().url;
- navigation.referrer_policy_ = static_cast<int>(entry->GetReferrer().policy);
- navigation.virtual_url_ = entry->GetVirtualURL();
- navigation.title_ = entry->GetTitle();
- if (!(serialization_options & SerializationOptions::EXCLUDE_PAGE_STATE))
- navigation.encoded_page_state_ = entry->GetPageState().ToEncodedData();
- 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();
- navigation.is_restored_ = entry->IsRestored();
- if (entry->GetFavicon().valid)
- navigation.favicon_url_ = entry->GetFavicon().url;
- navigation.http_status_code_ = entry->GetHttpStatusCode();
- navigation.redirect_chain_ = entry->GetRedirectChain();
- navigation.replaced_entry_data_ =
- ConvertReplacedEntryData(entry->GetReplacedEntryData());
- navigation.password_state_ = GetPasswordStateFromNavigation(entry);
- navigation.task_id_ = NavigationTaskId::Get(entry)->id();
- navigation.parent_task_id_ = NavigationTaskId::Get(entry)->parent_id();
- navigation.root_task_id_ = NavigationTaskId::Get(entry)->root_id();
- for (const auto& handler_entry :
- ContentSerializedNavigationDriver::GetInstance()
- ->GetAllExtendedInfoHandlers()) {
- ExtendedInfoHandler* handler = handler_entry.second.get();
- DCHECK(handler);
- std::string value = handler->GetExtendedInfo(entry);
- if (!value.empty())
- navigation.extended_info_map_[handler_entry.first] = value;
- }
- return navigation;
- }
- // static
- std::unique_ptr<content::NavigationEntry>
- ContentSerializedNavigationBuilder::ToNavigationEntry(
- const SerializedNavigationEntry* navigation,
- content::BrowserContext* browser_context,
- content::NavigationEntryRestoreContext* restore_context) {
- DCHECK(navigation);
- DCHECK(browser_context);
- DCHECK(restore_context);
- // The initial values of the NavigationEntry are only temporary - they
- // will get cloberred by one of the SetPageState calls below.
- //
- // This means that things like |navigation->referrer_url| are ignored
- // in favor of using the data stored in |navigation->encoded_page_state|.
- GURL temporary_url;
- content::Referrer temporary_referrer;
- absl::optional<url::Origin> temporary_initiator_origin;
- std::unique_ptr<content::NavigationEntry> entry(
- content::NavigationController::CreateNavigationEntry(
- temporary_url, temporary_referrer, temporary_initiator_origin,
- // Use a transition type of reload so that we don't incorrectly
- // increase the typed count.
- ui::PAGE_TRANSITION_RELOAD, false,
- // The extra headers are not sync'ed across sessions.
- std::string(), browser_context,
- nullptr /* blob_url_loader_factory */));
- // In some cases the |encoded_page_state| might be empty - we
- // need to gracefully handle such data when it is deserialized.
- //
- // One case is tests for "foreign" session restore entries, such as
- // SessionRestoreTest.RestoreForeignTab. We hypothesise that old session
- // restore entries might also contain an empty |encoded_page_state|.
- if (navigation->encoded_page_state_.empty()) {
- // Ensure that the deserialized/restored content::NavigationEntry (and
- // the content::FrameNavigationEntry underneath) has a valid PageState.
- entry->SetPageState(
- blink::PageState::CreateFromURL(navigation->virtual_url_),
- restore_context);
- // The |navigation|-based referrer set below might be inconsistent with the
- // referrer embedded inside the PageState set above. Nevertheless, to
- // minimize changes to behavior of old session restore entries, we restore
- // the deserialized referrer here.
- //
- // TODO(lukasza): Consider including the |deserialized_referrer| in the
- // PageState set above + drop the SetReferrer call below. This will
- // slightly change the legacy behavior, but will make PageState and
- // Referrer consistent.
- content::Referrer referrer(
- navigation->referrer_url(),
- content::Referrer::ConvertToPolicy(navigation->referrer_policy()));
- entry->SetReferrer(referrer);
- } else {
- // Note that PageState covers some of the values inside |navigation| (e.g.
- // URL, Referrer). Calling SetPageState will clobber these values in
- // content::NavigationEntry (and FrameNavigationEntry(s) below).
- entry->SetPageState(blink::PageState::CreateFromEncodedData(
- navigation->encoded_page_state_),
- restore_context);
- // |navigation|-level referrer information is redundant wrt PageState, but
- // they should be consistent / in-sync.
- DCHECK_EQ(navigation->referrer_url(), entry->GetReferrer().url);
- DCHECK_EQ(navigation->referrer_policy(),
- static_cast<int>(entry->GetReferrer().policy));
- }
- entry->SetTitle(navigation->title_);
- entry->SetHasPostData(navigation->has_post_data_);
- entry->SetPostID(navigation->post_id_);
- entry->SetOriginalRequestURL(navigation->original_request_url_);
- entry->SetIsOverridingUserAgent(navigation->is_overriding_user_agent_);
- entry->SetTimestamp(navigation->timestamp_);
- entry->SetHttpStatusCode(navigation->http_status_code_);
- entry->SetRedirectChain(navigation->redirect_chain_);
- entry->SetVirtualURL(navigation->virtual_url_);
- sessions::NavigationTaskId* navigation_task_id =
- sessions::NavigationTaskId::Get(entry.get());
- navigation_task_id->set_id(navigation->task_id());
- navigation_task_id->set_parent_id(navigation->parent_task_id());
- navigation_task_id->set_root_id(navigation->root_task_id());
- const ContentSerializedNavigationDriver::ExtendedInfoHandlerMap&
- extended_info_handlers = ContentSerializedNavigationDriver::GetInstance()
- ->GetAllExtendedInfoHandlers();
- for (const auto& extended_info_entry : navigation->extended_info_map_) {
- const std::string& key = extended_info_entry.first;
- if (!extended_info_handlers.count(key))
- continue;
- ExtendedInfoHandler* extended_info_handler =
- extended_info_handlers.at(key).get();
- DCHECK(extended_info_handler);
- extended_info_handler->RestoreExtendedInfo(extended_info_entry.second,
- entry.get());
- }
- // This field should have the default value.
- DCHECK_EQ(SerializedNavigationEntry::STATE_INVALID,
- navigation->blocked_state_);
- return entry;
- }
- // static
- std::vector<std::unique_ptr<content::NavigationEntry>>
- ContentSerializedNavigationBuilder::ToNavigationEntries(
- const std::vector<SerializedNavigationEntry>& navigations,
- content::BrowserContext* browser_context) {
- std::unique_ptr<content::NavigationEntryRestoreContext> restore_context =
- content::NavigationEntryRestoreContext::Create();
- std::vector<std::unique_ptr<content::NavigationEntry>> entries;
- entries.reserve(navigations.size());
- for (const auto& navigation : navigations) {
- entries.push_back(
- ToNavigationEntry(&navigation, browser_context, restore_context.get()));
- }
- return entries;
- }
- } // namespace sessions
|