Home | History | Annotate | Download | only in common
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/public/common/user_agent.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/strings/string_util.h"
      9 #include "base/strings/stringprintf.h"
     10 #include "base/sys_info.h"
     11 #include "build/build_config.h"
     12 
     13 #if defined(OS_POSIX) && !defined(OS_MACOSX)
     14 #include <sys/utsname.h>
     15 #endif
     16 
     17 #if defined(OS_WIN)
     18 #include "base/win/windows_version.h"
     19 #endif
     20 
     21 // Generated
     22 #include "webkit_version.h"  // NOLINT
     23 
     24 namespace content {
     25 
     26 namespace {
     27 
     28 #if defined(OS_ANDROID)
     29 std::string GetAndroidDeviceName() {
     30   return base::SysInfo::GetDeviceName();
     31 }
     32 #endif
     33 
     34 }  // namespace
     35 
     36 std::string GetWebKitVersion() {
     37   return base::StringPrintf("%d.%d (%s)",
     38                             WEBKIT_VERSION_MAJOR,
     39                             WEBKIT_VERSION_MINOR,
     40                             WEBKIT_SVN_REVISION);
     41 }
     42 
     43 int GetWebKitMajorVersion() {
     44   return WEBKIT_VERSION_MAJOR;
     45 }
     46 
     47 int GetWebKitMinorVersion() {
     48   return WEBKIT_VERSION_MINOR;
     49 }
     50 
     51 std::string GetWebKitRevision() {
     52   return WEBKIT_SVN_REVISION;
     53 }
     54 
     55 std::string BuildOSCpuInfo() {
     56   std::string os_cpu;
     57 
     58 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS) ||\
     59     defined(OS_ANDROID)
     60   int32 os_major_version = 0;
     61   int32 os_minor_version = 0;
     62   int32 os_bugfix_version = 0;
     63   base::SysInfo::OperatingSystemVersionNumbers(&os_major_version,
     64                                                &os_minor_version,
     65                                                &os_bugfix_version);
     66 #endif
     67 
     68 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
     69   // Should work on any Posix system.
     70   struct utsname unixinfo;
     71   uname(&unixinfo);
     72 
     73   std::string cputype;
     74   // special case for biarch systems
     75   if (strcmp(unixinfo.machine, "x86_64") == 0 &&
     76       sizeof(void*) == sizeof(int32)) {  // NOLINT
     77     cputype.assign("i686 (x86_64)");
     78   } else {
     79     cputype.assign(unixinfo.machine);
     80   }
     81 #endif
     82 
     83 #if defined(OS_WIN)
     84   std::string architecture_token;
     85   base::win::OSInfo* os_info = base::win::OSInfo::GetInstance();
     86   if (os_info->wow64_status() == base::win::OSInfo::WOW64_ENABLED) {
     87     architecture_token = "; WOW64";
     88   } else {
     89     base::win::OSInfo::WindowsArchitecture windows_architecture =
     90         os_info->architecture();
     91     if (windows_architecture == base::win::OSInfo::X64_ARCHITECTURE)
     92       architecture_token = "; Win64; x64";
     93     else if (windows_architecture == base::win::OSInfo::IA64_ARCHITECTURE)
     94       architecture_token = "; Win64; IA64";
     95   }
     96 #endif
     97 
     98 #if defined(OS_ANDROID)
     99   std::string android_version_str;
    100   base::StringAppendF(
    101       &android_version_str, "%d.%d", os_major_version, os_minor_version);
    102   if (os_bugfix_version != 0)
    103     base::StringAppendF(&android_version_str, ".%d", os_bugfix_version);
    104 
    105   std::string android_info_str;
    106 
    107   // Send information about the device.
    108   bool semicolon_inserted = false;
    109   std::string android_build_codename = base::SysInfo::GetAndroidBuildCodename();
    110   std::string android_device_name = GetAndroidDeviceName();
    111   if ("REL" == android_build_codename && android_device_name.size() > 0) {
    112     android_info_str += "; " + android_device_name;
    113     semicolon_inserted = true;
    114   }
    115 
    116   // Append the build ID.
    117   std::string android_build_id = base::SysInfo::GetAndroidBuildID();
    118   if (android_build_id.size() > 0) {
    119     if (!semicolon_inserted) {
    120       android_info_str += ";";
    121     }
    122     android_info_str += " Build/" + android_build_id;
    123   }
    124 #endif
    125 
    126   base::StringAppendF(
    127       &os_cpu,
    128 #if defined(OS_WIN)
    129       "Windows NT %d.%d%s",
    130       os_major_version,
    131       os_minor_version,
    132       architecture_token.c_str()
    133 #elif defined(OS_MACOSX)
    134       "Intel Mac OS X %d_%d_%d",
    135       os_major_version,
    136       os_minor_version,
    137       os_bugfix_version
    138 #elif defined(OS_CHROMEOS)
    139       "CrOS "
    140       "%s %d.%d.%d",
    141       cputype.c_str(),   // e.g. i686
    142       os_major_version,
    143       os_minor_version,
    144       os_bugfix_version
    145 #elif defined(OS_ANDROID)
    146       "Android %s%s",
    147       android_version_str.c_str(),
    148       android_info_str.c_str()
    149 #else
    150       "%s %s",
    151       unixinfo.sysname,  // e.g. Linux
    152       cputype.c_str()    // e.g. i686
    153 #endif
    154   );  // NOLINT
    155 
    156   return os_cpu;
    157 }
    158 
    159 std::string BuildUserAgentFromProduct(const std::string& product) {
    160   const char kUserAgentPlatform[] =
    161 #if defined(OS_WIN)
    162       "";
    163 #elif defined(OS_MACOSX)
    164       "Macintosh; ";
    165 #elif defined(USE_X11)
    166       "X11; ";           // strange, but that's what Firefox uses
    167 #elif defined(OS_ANDROID)
    168       "Linux; ";
    169 #else
    170       "Unknown; ";
    171 #endif
    172 
    173   std::string os_info;
    174   base::StringAppendF(
    175       &os_info, "%s%s", kUserAgentPlatform, BuildOSCpuInfo().c_str());
    176   return BuildUserAgentFromOSAndProduct(os_info, product);
    177 }
    178 
    179 std::string BuildUserAgentFromOSAndProduct(const std::string& os_info,
    180                                            const std::string& product) {
    181   // Derived from Safari's UA string.
    182   // This is done to expose our product name in a manner that is maximally
    183   // compatible with Safari, we hope!!
    184   std::string user_agent;
    185   base::StringAppendF(
    186       &user_agent,
    187       "Mozilla/5.0 (%s) AppleWebKit/%d.%d (KHTML, like Gecko) %s Safari/%d.%d",
    188       os_info.c_str(),
    189       WEBKIT_VERSION_MAJOR,
    190       WEBKIT_VERSION_MINOR,
    191       product.c_str(),
    192       WEBKIT_VERSION_MAJOR,
    193       WEBKIT_VERSION_MINOR);
    194   return user_agent;
    195 }
    196 
    197 }  // namespace content
    198