blob: fde8edb5d10e9b6f8d68eee8045b8cf8219a3ff0 [file] [log] [blame]
// Copyright 2018 The Cobalt Authors. 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/browser/user_agent_string.h"
#include <vector>
#include "base/command_line.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "cobalt/browser/switches.h"
#if SB_IS(EVERGREEN)
#include "cobalt/extension/installation_manager.h"
#endif // SB_IS(EVERGREEN)
#include "starboard/common/log.h"
#include "starboard/common/string.h"
#include "starboard/system.h"
namespace cobalt {
namespace browser {
namespace {
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;
base::ReplaceChars(clean, replacement->replace_chars,
replacement->replace_with, &clean);
}
return clean;
}
} // namespace
UserAgentPlatformInfo GetUserAgentPlatformInfoFromSystem() {
UserAgentPlatformInfo platform_info;
return platform_info;
}
// This function is expected to be deterministic and non-dependent on global
// variables and state. If global state should be referenced, it should be done
// so during the creation of |platform_info| instead.
std::string CreateUserAgentString(const UserAgentPlatformInfo& platform_info) {
// Cobalt's user agent contains the following sections:
// Mozilla/5.0 (ChromiumStylePlatform)
// Cobalt/Version.BuildNumber-BuildConfiguration (unlike Gecko)
// JavaScript Engine Name/Version
// Starboard/APIVersion,
// Device/FirmwareVersion (Brand, Model, ConnectionType)
std::string os_name_and_version = platform_info.os_name_and_version();
#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
// Because we add Cobalt's user agent string to Crashpad before we actually
// start Cobalt, the command line won't be initialized when we first try to
// get the user agent string.
if (base::CommandLine::InitializedForCurrentProcess()) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kUserAgentOsNameVersion)) {
os_name_and_version =
command_line->GetSwitchValueASCII(switches::kUserAgentOsNameVersion);
}
}
#endif // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
// Mozilla/5.0 (ChromiumStylePlatform)
std::string user_agent =
base::StringPrintf("Mozilla/5.0 (%s)", os_name_and_version.c_str());
// Cobalt/Version.BuildNumber-BuildConfiguration (unlike Gecko)
base::StringAppendF(&user_agent, " Cobalt/%s.%s-%s (unlike Gecko)",
platform_info.cobalt_version().c_str(),
platform_info.cobalt_build_version_number().c_str(),
platform_info.build_configuration().c_str());
// JavaScript Engine Name/Version
if (!platform_info.javascript_engine_version().empty()) {
base::StringAppendF(&user_agent, " %s",
platform_info.javascript_engine_version().c_str());
}
// Rasterizer Type
if (!platform_info.rasterizer_type().empty()) {
base::StringAppendF(&user_agent, " %s",
platform_info.rasterizer_type().c_str());
}
// Evergreen version
if (!platform_info.evergreen_version().empty()) {
base::StringAppendF(&user_agent, " Evergreen/%s",
platform_info.evergreen_version().c_str());
#if SB_IS(EVERGREEN)
if (!SbSystemGetExtension(kCobaltExtensionInstallationManagerName)) {
// If the installation manager is not initialized, the "evergreen_lite"
// command line parameter is specified and the system image is loaded.
base::StringAppendF(&user_agent, " Evergreen-Lite");
} else {
base::StringAppendF(&user_agent, " Evergreen-Full");
}
#endif // SB_IS(EVERGREEN)
}
// Starboard/APIVersion,
if (!platform_info.starboard_version().empty()) {
base::StringAppendF(&user_agent, " %s",
platform_info.starboard_version().c_str());
}
// Device/FirmwareVersion (Brand, Model, ConnectionType)
base::StringAppendF(
&user_agent, ", %s_%s_%s_%s/%s (%s, %s, %s)",
Sanitize(platform_info.original_design_manufacturer().value_or(""))
.c_str(),
platform_info.device_type_string().c_str(),
Sanitize(platform_info.chipset_model_number().value_or("")).c_str(),
Sanitize(platform_info.model_year().value_or("")).c_str(),
Sanitize(platform_info.firmware_version().value_or("")).c_str(),
Sanitize(platform_info.brand().value_or("")).c_str(),
Sanitize(platform_info.model().value_or("")).c_str(),
platform_info.connection_type_string().c_str());
if (!platform_info.aux_field().empty()) {
user_agent.append(" ");
user_agent.append(platform_info.aux_field());
}
return user_agent;
}
} // namespace browser
} // namespace cobalt