blob: 3b99c66c43d13eb86e95c2d2d50e9b9c4f2bce31 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
#include "base/pickle.h"
#include "net/http/structured_headers.h"
#include "third_party/blink/public/common/features.h"
namespace blink {
namespace {
constexpr uint32_t kVersion = 2u;
} // namespace
UserAgentBrandVersion::UserAgentBrandVersion(const std::string& ua_brand,
const std::string& ua_version) {
brand = ua_brand;
version = ua_version;
}
const std::string UserAgentMetadata::SerializeBrandVersionList(
const blink::UserAgentBrandList& ua_brand_version_list) {
net::structured_headers::List brand_version_header =
net::structured_headers::List();
for (const UserAgentBrandVersion& brand_version : ua_brand_version_list) {
if (brand_version.version.empty()) {
brand_version_header.push_back(
net::structured_headers::ParameterizedMember(
net::structured_headers::Item(brand_version.brand), {}));
} else {
brand_version_header.push_back(
net::structured_headers::ParameterizedMember(
net::structured_headers::Item(brand_version.brand),
{std::make_pair(
"v", net::structured_headers::Item(brand_version.version))}));
}
}
return net::structured_headers::SerializeList(brand_version_header)
.value_or("");
}
const std::string UserAgentMetadata::SerializeBrandFullVersionList() {
return SerializeBrandVersionList(brand_full_version_list);
}
const std::string UserAgentMetadata::SerializeBrandMajorVersionList() {
return SerializeBrandVersionList(brand_version_list);
}
// static
absl::optional<std::string> UserAgentMetadata::Marshal(
const absl::optional<UserAgentMetadata>& in) {
if (!in)
return absl::nullopt;
base::Pickle out;
out.WriteUInt32(kVersion);
out.WriteUInt32(in->brand_version_list.size());
for (const auto& brand_version : in->brand_version_list) {
out.WriteString(brand_version.brand);
out.WriteString(brand_version.version);
}
out.WriteUInt32(in->brand_full_version_list.size());
for (const auto& brand_version : in->brand_full_version_list) {
out.WriteString(brand_version.brand);
out.WriteString(brand_version.version);
}
out.WriteString(in->full_version);
out.WriteString(in->platform);
out.WriteString(in->platform_version);
out.WriteString(in->architecture);
out.WriteString(in->model);
out.WriteBool(in->mobile);
out.WriteString(in->bitness);
out.WriteBool(in->wow64);
return std::string(reinterpret_cast<const char*>(out.data()), out.size());
}
// static
absl::optional<UserAgentMetadata> UserAgentMetadata::Demarshal(
const absl::optional<std::string>& encoded) {
if (!encoded)
return absl::nullopt;
base::Pickle pickle(encoded->data(), encoded->size());
base::PickleIterator in(pickle);
uint32_t version;
UserAgentMetadata out;
if (!in.ReadUInt32(&version) || version != kVersion)
return absl::nullopt;
uint32_t brand_version_size;
if (!in.ReadUInt32(&brand_version_size))
return absl::nullopt;
for (uint32_t i = 0; i < brand_version_size; i++) {
UserAgentBrandVersion brand_version;
if (!in.ReadString(&brand_version.brand))
return absl::nullopt;
if (!in.ReadString(&brand_version.version))
return absl::nullopt;
out.brand_version_list.push_back(std::move(brand_version));
}
uint32_t brand_full_version_size;
if (!in.ReadUInt32(&brand_full_version_size))
return absl::nullopt;
for (uint32_t i = 0; i < brand_full_version_size; i++) {
UserAgentBrandVersion brand_version;
if (!in.ReadString(&brand_version.brand))
return absl::nullopt;
if (!in.ReadString(&brand_version.version))
return absl::nullopt;
out.brand_full_version_list.push_back(std::move(brand_version));
}
if (!in.ReadString(&out.full_version))
return absl::nullopt;
if (!in.ReadString(&out.platform))
return absl::nullopt;
if (!in.ReadString(&out.platform_version))
return absl::nullopt;
if (!in.ReadString(&out.architecture))
return absl::nullopt;
if (!in.ReadString(&out.model))
return absl::nullopt;
if (!in.ReadBool(&out.mobile))
return absl::nullopt;
if (!in.ReadString(&out.bitness))
return absl::nullopt;
if (!in.ReadBool(&out.wow64))
return absl::nullopt;
return absl::make_optional(std::move(out));
}
bool UserAgentBrandVersion::operator==(const UserAgentBrandVersion& a) const {
return a.brand == brand && a.version == version;
}
bool operator==(const UserAgentMetadata& a, const UserAgentMetadata& b) {
return a.brand_version_list == b.brand_version_list &&
a.brand_full_version_list == b.brand_full_version_list &&
a.full_version == b.full_version && a.platform == b.platform &&
a.platform_version == b.platform_version &&
a.architecture == b.architecture && a.model == b.model &&
a.mobile == b.mobile && a.bitness == b.bitness && a.wow64 == b.wow64;
}
// static
UserAgentOverride UserAgentOverride::UserAgentOnly(const std::string& ua) {
UserAgentOverride result;
result.ua_string_override = ua;
// If ua is not empty, it's assumed the system default should be used
if (!ua.empty() &&
base::FeatureList::IsEnabled(features::kUACHOverrideBlank)) {
result.ua_metadata_override = UserAgentMetadata();
}
return result;
}
bool operator==(const UserAgentOverride& a, const UserAgentOverride& b) {
return a.ua_string_override == b.ua_string_override &&
a.ua_metadata_override == b.ua_metadata_override;
}
} // namespace blink