blob: 66cc78cf51df8d9a520c1ca732319988974f2419 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ios/web/common/user_agent.h"
#import <UIKit/UIKit.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/sysctl.h>
#include <string>
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
#include "base/system/sys_info.h"
#include "ios/web/common/features.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
namespace {
const char kDesktopUserAgentProductPlaceholder[] =
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) "
"AppleWebKit/605.1.15 (KHTML, like Gecko) %s"
"Version/11.1.1 "
// UserAgentType description strings.
const char kUserAgentTypeAutomaticDescription[] = "AUTOMATIC";
const char kUserAgentTypeNoneDescription[] = "NONE";
const char kUserAgentTypeMobileDescription[] = "MOBILE";
const char kUserAgentTypeDesktopDescription[] = "DESKTOP";
std::string OSVersion() {
int32_t os_major_version = 0;
int32_t os_minor_version = 0;
int32_t os_bugfix_version = 0;
&os_major_version, &os_minor_version, &os_bugfix_version);
std::string os_version;
base::StringAppendF(&os_version, "%d_%d", os_major_version, os_minor_version);
return os_version;
} // namespace
namespace web {
std::string GetUserAgentTypeDescription(UserAgentType type) {
switch (type) {
case UserAgentType::AUTOMATIC:
return std::string(kUserAgentTypeAutomaticDescription);
case UserAgentType::NONE:
return std::string(kUserAgentTypeNoneDescription);
case UserAgentType::MOBILE:
return std::string(kUserAgentTypeMobileDescription);
case UserAgentType::DESKTOP:
return std::string(kUserAgentTypeDesktopDescription);
UserAgentType GetUserAgentTypeWithDescription(const std::string& description) {
if (description == std::string(kUserAgentTypeMobileDescription))
return UserAgentType::MOBILE;
if (description == std::string(kUserAgentTypeDesktopDescription))
return UserAgentType::DESKTOP;
if (description == std::string(kUserAgentTypeAutomaticDescription))
return UserAgentType::AUTOMATIC;
return UserAgentType::NONE;
std::string BuildOSCpuInfo() {
std::string os_cpu;
// Remove the end of the platform name. For example "iPod touch" becomes
// "iPod".
std::string platform =
base::SysNSStringToUTF8([[UIDevice currentDevice] model]);
size_t position = platform.find_first_of(" ");
if (position != std::string::npos)
platform = platform.substr(0, position);
base::StringAppendF(&os_cpu, "%s; CPU %s %s like Mac OS X", platform.c_str(),
(platform == "iPad") ? "OS" : "iPhone OS",
return os_cpu;
std::string BuildDesktopUserAgent(const std::string& desktop_product) {
std::string product = desktop_product;
if (!desktop_product.empty()) {
// In case the product isn't empty, add a space after it.
product = product + " ";
std::string user_agent;
base::StringAppendF(&user_agent, kDesktopUserAgentProductPlaceholder,
return user_agent;
std::string BuildMobileUserAgent(const std::string& mobile_product) {
std::string user_agent;
"Mozilla/5.0 (%s) AppleWebKit/605.1.15"
" (KHTML, like Gecko) %s Mobile/15E148 Safari/604.1",
BuildOSCpuInfo().c_str(), mobile_product.c_str());
return user_agent;
} // namespace web