blob: 0b5b901b5b82717f0fdb376f6e48ba74f970b124 [file] [log] [blame]
// 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 "content/public/common/page_state.h"
#include <stddef.h>
#include "base/files/file_path.h"
#include "base/optional.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "content/common/page_state_serialization.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "services/network/public/mojom/referrer_policy.mojom.h"
namespace content {
namespace {
base::FilePath ToFilePath(const base::Optional<base::string16>& s) {
return s ? base::FilePath::FromUTF16Unsafe(*s) : base::FilePath();
}
void ToFilePathVector(const std::vector<base::Optional<base::string16>>& input,
std::vector<base::FilePath>* output) {
output->clear();
output->reserve(input.size());
for (size_t i = 0; i < input.size(); ++i)
output->emplace_back(ToFilePath(input[i]));
}
PageState ToPageState(const ExplodedPageState& state) {
std::string encoded_data;
EncodePageState(state, &encoded_data);
return PageState::CreateFromEncodedData(encoded_data);
}
void RecursivelyRemovePasswordData(ExplodedFrameState* state) {
if (state->http_body.contains_passwords)
state->http_body = ExplodedHttpBody();
}
void RecursivelyRemoveScrollOffset(ExplodedFrameState* state) {
state->scroll_offset = gfx::Point();
state->visual_viewport_scroll_offset = gfx::PointF();
}
void RecursivelyRemoveReferrer(ExplodedFrameState* state) {
state->referrer.reset();
state->referrer_policy = network::mojom::ReferrerPolicy::kDefault;
for (std::vector<ExplodedFrameState>::iterator it = state->children.begin();
it != state->children.end();
++it) {
RecursivelyRemoveReferrer(&*it);
}
}
} // namespace
// static
PageState PageState::CreateFromEncodedData(const std::string& data) {
return PageState(data);
}
// static
PageState PageState::CreateFromURL(const GURL& url) {
ExplodedPageState state;
state.top.url_string = base::UTF8ToUTF16(url.possibly_invalid_spec());
return ToPageState(state);
}
// static
PageState PageState::CreateForTesting(
const GURL& url,
bool body_contains_password_data,
const char* optional_body_data,
const base::FilePath* optional_body_file_path) {
ExplodedPageState state;
state.top.url_string = base::UTF8ToUTF16(url.possibly_invalid_spec());
if (optional_body_data || optional_body_file_path) {
if (optional_body_data) {
std::string body_data(optional_body_data);
state.top.http_body.request_body = new network::ResourceRequestBody();
state.top.http_body.request_body->AppendBytes(body_data.data(),
body_data.size());
}
if (optional_body_file_path) {
state.top.http_body.request_body = new network::ResourceRequestBody();
state.top.http_body.request_body->AppendFileRange(
*optional_body_file_path,
0, std::numeric_limits<uint64_t>::max(),
base::Time());
state.referenced_files.emplace_back(
optional_body_file_path->AsUTF16Unsafe());
}
state.top.http_body.contains_passwords =
body_contains_password_data;
}
return ToPageState(state);
}
// static
PageState PageState::CreateForTestingWithSequenceNumbers(
const GURL& url,
int64_t item_sequence_number,
int64_t document_sequence_number) {
ExplodedPageState page_state;
page_state.top.url_string = base::UTF8ToUTF16(url.spec());
page_state.top.item_sequence_number = item_sequence_number;
page_state.top.document_sequence_number = document_sequence_number;
std::string encoded_page_state;
EncodePageState(page_state, &encoded_page_state);
return CreateFromEncodedData(encoded_page_state);
}
PageState::PageState() {
}
bool PageState::IsValid() const {
return !data_.empty();
}
bool PageState::Equals(const PageState& other) const {
return data_ == other.data_;
}
const std::string& PageState::ToEncodedData() const {
return data_;
}
std::vector<base::FilePath> PageState::GetReferencedFiles() const {
std::vector<base::FilePath> results;
ExplodedPageState state;
if (DecodePageState(data_, &state))
ToFilePathVector(state.referenced_files, &results);
return results;
}
PageState PageState::RemovePasswordData() const {
ExplodedPageState state;
if (!DecodePageState(data_, &state))
return PageState(); // Oops!
RecursivelyRemovePasswordData(&state.top);
return ToPageState(state);
}
PageState PageState::RemoveScrollOffset() const {
ExplodedPageState state;
if (!DecodePageState(data_, &state))
return PageState(); // Oops!
RecursivelyRemoveScrollOffset(&state.top);
return ToPageState(state);
}
PageState PageState::RemoveReferrer() const {
if (data_.empty())
return *this;
ExplodedPageState state;
if (!DecodePageState(data_, &state))
return PageState(); // Oops!
RecursivelyRemoveReferrer(&state.top);
return ToPageState(state);
}
PageState::PageState(const std::string& data)
: data_(data) {
// TODO(darin): Enable this DCHECK once tests have been fixed up to not pass
// bogus encoded data to CreateFromEncodedData.
//DCHECK(IsValid());
}
} // namespace content