blob: 4bd035d661215a644c1e4951fc87f74bb4445ec8 [file] [log] [blame]
// 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 "base/logging.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/replaced_navigation_entry_data.h"
#include "content/public/common/page_state.h"
#include "content/public/common/referrer.h"
namespace sessions {
namespace {
base::Optional<SerializedNavigationEntry::ReplacedNavigationEntryData>
ConvertReplacedEntryData(
const base::Optional<content::ReplacedNavigationEntryData>& input_data) {
if (!input_data.has_value())
return base::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();
navigation.children_task_ids_ = NavigationTaskId::Get(entry)->children_ids();
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) {
// TODO(lukasza): https://crbug.com/976055: |initiator_origin| should be
// persisted across session restore.
base::Optional<url::Origin> initiator_origin = base::nullopt;
network::mojom::ReferrerPolicy policy =
static_cast<network::mojom::ReferrerPolicy>(navigation->referrer_policy_);
std::unique_ptr<content::NavigationEntry> entry(
content::NavigationController::CreateNavigationEntry(
navigation->virtual_url_,
content::Referrer::SanitizeForRequest(
navigation->virtual_url_,
content::Referrer(navigation->referrer_url_, policy)),
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 */));
entry->SetTitle(navigation->title_);
entry->SetPageState(content::PageState::CreateFromEncodedData(
navigation->encoded_page_state_));
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_);
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());
}
// These fields should have default values.
DCHECK_EQ(SerializedNavigationEntry::STATE_INVALID,
navigation->blocked_state_);
DCHECK_EQ(0u, navigation->content_pack_categories_.size());
return entry;
}
// static
std::vector<std::unique_ptr<content::NavigationEntry>>
ContentSerializedNavigationBuilder::ToNavigationEntries(
const std::vector<SerializedNavigationEntry>& navigations,
content::BrowserContext* browser_context) {
std::vector<std::unique_ptr<content::NavigationEntry>> entries;
entries.reserve(navigations.size());
for (const auto& navigation : navigations)
entries.push_back(ToNavigationEntry(&navigation, browser_context));
return entries;
}
} // namespace sessions