| // 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 |