blob: 8bd7815eec5e04882d331943d830180e08a8e3ed [file] [log] [blame]
// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/network/user_agent_string_factory.h"
#include <vector>
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "cobalt/version.h"
#include "cobalt_build_id.h" // NOLINT(build/include)
namespace cobalt {
namespace network {
namespace {
#if defined(COBALT_BUILD_TYPE_DEBUG)
const char kBuildConfiguration[] = "debug";
#elif defined(COBALT_BUILD_TYPE_DEVEL)
const char kBuildConfiguration[] = "devel";
#elif defined(COBALT_BUILD_TYPE_QA)
const char kBuildConfiguration[] = "qa";
#elif defined(COBALT_BUILD_TYPE_GOLD)
const char kBuildConfiguration[] = "gold";
#else
#error Unknown build configuration.
#endif
struct SanitizeReplacements {
const char* replace_chars;
const char* replace_with;
} kSanitizeReplacements[] = {
{ ",", u8"\uFF0C" }, // fullwidth comma
{ "_", u8"\u2E0F" }, // paragraphos
{ "/", u8"\u2215" }, // division slash
{ "(", u8"\uFF08" }, // fullwidth left paren
{ ")", u8"\uFF09" }, // fullwidth right paren
};
// Replace reserved characters with Unicode homoglyphs
std::string Sanitize(const std::string& str) {
std::string clean(str);
for (size_t i=0; i < arraysize(kSanitizeReplacements); i++) {
const SanitizeReplacements* replacement = kSanitizeReplacements + i;
ReplaceChars(
clean, replacement->replace_chars, replacement->replace_with, &clean);
}
return clean;
}
} // namespace
std::string UserAgentStringFactory::CreateUserAgentString() {
// Cobalt's user agent contains the following sections:
// Mozilla/5.0 (ChromiumStylePlatform)
// Cobalt/Version.BuildNumber-BuildConfiguration (unlike Gecko)
// Starboard/APIVersion,
// Device/FirmwareVersion (Brand, Model, ConnectionType)
// Mozilla/5.0 (ChromiumStylePlatform)
std::string user_agent =
base::StringPrintf("Mozilla/5.0 (%s)", CreatePlatformString().c_str());
// Cobalt/Version.BuildNumber-BuildConfiguration (unlike Gecko)
base::StringAppendF(&user_agent, " Cobalt/%s.%s-%s (unlike Gecko)",
COBALT_VERSION, COBALT_BUILD_VERSION_NUMBER,
kBuildConfiguration);
// Starboard/APIVersion,
if (!starboard_version_.empty()) {
base::StringAppendF(&user_agent, " %s", starboard_version_.c_str());
}
// Device/FirmwareVersion (Brand, Model, ConnectionType)
if (youtube_tv_info_) {
base::StringAppendF(
&user_agent, ", %s_%s_%s/%s (%s, %s, %s)",
Sanitize(youtube_tv_info_->network_operator.value_or("")).c_str(),
CreateDeviceTypeString().c_str(),
Sanitize(youtube_tv_info_->chipset_model_number.value_or("")).c_str(),
Sanitize(youtube_tv_info_->firmware_version.value_or("")).c_str(),
Sanitize(youtube_tv_info_->brand).c_str(),
Sanitize(youtube_tv_info_->model).c_str(),
CreateConnectionTypeString().c_str());
}
if (!aux_field_.empty()) {
user_agent.append(" ");
user_agent.append(aux_field_);
}
return user_agent;
}
// Inserts semicolons between non-empty components of the platform.
std::string UserAgentStringFactory::CreatePlatformString() {
std::string platform;
if (!historic_platform_name_.empty()) {
platform += historic_platform_name_;
platform += "; ";
}
DCHECK(!os_name_and_version_.empty());
platform += os_name_and_version_;
if (!architecture_tokens_.empty()) {
platform += "; ";
platform += architecture_tokens_;
}
return platform;
}
std::string UserAgentStringFactory::CreateDeviceTypeString() {
switch (youtube_tv_info_->device_type) {
case YouTubeTVInfo::kBlueRayDiskPlayer:
return "BDP";
case YouTubeTVInfo::kGameConsole:
return "GAME";
case YouTubeTVInfo::kOverTheTopBox:
return "OTT";
case YouTubeTVInfo::kSetTopBox:
return "STB";
case YouTubeTVInfo::kTV:
return "TV";
case YouTubeTVInfo::kAndroidTV:
return "ATV";
case YouTubeTVInfo::kInvalidDeviceType:
default:
NOTREACHED();
return "";
}
}
std::string UserAgentStringFactory::CreateConnectionTypeString() {
if (youtube_tv_info_->connection_type) {
switch (*youtube_tv_info_->connection_type) {
case YouTubeTVInfo::kWiredConnection:
return "Wired";
case YouTubeTVInfo::kWirelessConnection:
return "Wireless";
default:
NOTREACHED();
}
}
return "";
}
} // namespace network
} // namespace cobalt