#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "third_party/blink/public/common/page_state/page_state_serialization.h"
#include <algorithm>
#include <limits>
#include <utility>
#include "base/containers/span.h"
#include "base/pickle.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "mojo/public/cpp/base/string16_mojom_traits.h"
#include "mojo/public/cpp/base/time_mojom_traits.h"
#include "mojo/public/cpp/bindings/enum_utils.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "third_party/blink/public/common/loader/http_body_element_type.h"
#include "third_party/blink/public/common/unique_name/unique_name_helper.h"
#include "third_party/blink/public/mojom/page_state/page_state.mojom.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/mojom/geometry_mojom_traits.h"
#include "url/mojom/url_gurl_mojom_traits.h"
namespace blink {
namespace {
#if BUILDFLAG(IS_ANDROID)
float g_device_scale_factor_for_testing = 0.0;
#endif
void AppendDataToRequestBody(
const scoped_refptr<network::ResourceRequestBody>& request_body,
const char* data,
size_t data_length) { … }
void AppendFileRangeToRequestBody(
const scoped_refptr<network::ResourceRequestBody>& request_body,
const std::optional<std::u16string>& file_path,
int file_start,
int file_length,
base::Time file_modification_time) { … }
void AppendReferencedFilesFromHttpBody(
const std::vector<network::DataElement>& elements,
std::vector<std::optional<std::u16string>>* referenced_files) { … }
bool AppendReferencedFilesFromDocumentState(
const std::vector<std::optional<std::u16string>>& document_state,
std::vector<std::optional<std::u16string>>* referenced_files) { … }
bool RecursivelyAppendReferencedFiles(
const ExplodedFrameState& frame_state,
std::vector<std::optional<std::u16string>>* referenced_files) { … }
struct SerializeObject { … };
const int kMinVersion = …;
const int kCurrentVersion = …;
void WriteData(base::span<const uint8_t> data, SerializeObject* obj) { … }
std::optional<base::span<const uint8_t>> ReadData(SerializeObject* obj) { … }
void WriteInteger(int data, SerializeObject* obj) { … }
int ReadInteger(SerializeObject* obj) { … }
void WriteInteger64(int64_t data, SerializeObject* obj) { … }
int64_t ReadInteger64(SerializeObject* obj) { … }
void WriteReal(double data, SerializeObject* obj) { … }
double ReadReal(SerializeObject* obj) { … }
void WriteBoolean(bool data, SerializeObject* obj) { … }
bool ReadBoolean(SerializeObject* obj) { … }
GURL ReadGURL(SerializeObject* obj) { … }
std::string ReadStdString(SerializeObject* obj) { … }
void WriteString(const std::u16string& str, SerializeObject* obj) { … }
void WriteString(const std::optional<std::u16string>& str,
SerializeObject* obj) { … }
const char16_t* ReadStringNoCopy(SerializeObject* obj, int* num_chars) { … }
std::optional<std::u16string> ReadString(SerializeObject* obj) { … }
template <typename T>
void WriteAndValidateVectorSize(const std::vector<T>& v, SerializeObject* obj) { … }
size_t ReadAndValidateVectorSize(SerializeObject* obj, size_t element_size) { … }
void WriteStringVector(const std::vector<std::optional<std::u16string>>& data,
SerializeObject* obj) { … }
void ReadStringVector(SerializeObject* obj,
std::vector<std::optional<std::u16string>>* result) { … }
void WriteResourceRequestBody(const network::ResourceRequestBody& request_body,
SerializeObject* obj) { … }
void ReadResourceRequestBody(
SerializeObject* obj,
const scoped_refptr<network::ResourceRequestBody>& request_body) { … }
void ReadHttpBody(SerializeObject* obj, ExplodedHttpBody* http_body) { … }
void WriteHttpBody(const ExplodedHttpBody& http_body, SerializeObject* obj) { … }
void ReadLegacyFrameState(
SerializeObject* obj,
bool is_top,
std::vector<UniqueNameHelper::Replacement>* unique_name_replacements,
ExplodedFrameState* state) { … }
void WriteLegacyFrameState(const ExplodedFrameState& state,
SerializeObject* obj,
bool is_top) { … }
void WriteLegacyPageState(const ExplodedPageState& state,
SerializeObject* obj) { … }
void WriteResourceRequestBody(const network::ResourceRequestBody& request_body,
mojom::RequestBody* mojo_body) { … }
void ReadResourceRequestBody(
mojom::RequestBody* mojo_body,
const scoped_refptr<network::ResourceRequestBody>& request_body) { … }
void WriteHttpBody(const ExplodedHttpBody& http_body,
mojom::HttpBody* mojo_body) { … }
void ReadHttpBody(mojom::HttpBody* mojo_body, ExplodedHttpBody* http_body) { … }
void WriteMojoFrameState(const ExplodedFrameState& state,
mojom::FrameState* frame) { … }
void ReadMojoFrameState(mojom::FrameState* frame, ExplodedFrameState* state) { … }
void ReadMojoPageState(SerializeObject* obj, ExplodedPageState* state) { … }
void WriteMojoPageState(const ExplodedPageState& state, SerializeObject* obj) { … }
void ReadPageState(SerializeObject* obj, ExplodedPageState* state) { … }
}
ExplodedHttpBody::ExplodedHttpBody() : … { … }
ExplodedHttpBody::~ExplodedHttpBody() { … }
ExplodedFrameState::ExplodedFrameState() = default;
ExplodedFrameState::ExplodedFrameState(const ExplodedFrameState& other) { … }
ExplodedFrameState::~ExplodedFrameState() { … }
void ExplodedFrameState::operator=(const ExplodedFrameState& other) { … }
void ExplodedFrameState::assign(const ExplodedFrameState& other) { … }
ExplodedPageState::ExplodedPageState() { … }
ExplodedPageState::~ExplodedPageState() { … }
int DecodePageStateInternal(const std::string& encoded,
ExplodedPageState* exploded) { … }
bool DecodePageState(const std::string& encoded, ExplodedPageState* exploded) { … }
int DecodePageStateForTesting(const std::string& encoded,
ExplodedPageState* exploded) { … }
void EncodePageState(const ExplodedPageState& exploded, std::string* encoded) { … }
void LegacyEncodePageStateForTesting(const ExplodedPageState& exploded,
int version,
std::string* encoded) { … }
#if BUILDFLAG(IS_ANDROID)
bool DecodePageStateWithDeviceScaleFactorForTesting(
const std::string& encoded,
float device_scale_factor,
ExplodedPageState* exploded) {
g_device_scale_factor_for_testing = device_scale_factor;
bool rv = DecodePageState(encoded, exploded);
g_device_scale_factor_for_testing = 0.0;
return rv;
}
scoped_refptr<network::ResourceRequestBody> DecodeResourceRequestBody(
const char* data,
size_t size) {
scoped_refptr<network::ResourceRequestBody> result =
new network::ResourceRequestBody();
SerializeObject obj(base::as_bytes(base::span(data, size)));
ReadResourceRequestBody(&obj, result);
result->set_contains_sensitive_info(ReadBoolean(&obj));
return obj.parse_error ? nullptr : result;
}
std::string EncodeResourceRequestBody(
const network::ResourceRequestBody& resource_request_body) {
SerializeObject obj;
obj.version = 25;
WriteResourceRequestBody(resource_request_body, &obj);
WriteBoolean(resource_request_body.contains_sensitive_info(), &obj);
return obj.GetAsString();
}
#endif
}