xpcom/base/nsSystemInfo.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 50; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "mozilla/ArrayUtils.h"
     8 #include "nsSystemInfo.h"
     9 #include "prsystem.h"
    10 #include "prio.h"
    11 #include "prprf.h"
    12 #include "mozilla/SSE.h"
    13 #include "mozilla/arm.h"
    15 #ifdef XP_WIN
    16 #include <windows.h>
    17 #include <winioctl.h>
    18 #include "base/scoped_handle_win.h"
    19 #include "nsAppDirectoryServiceDefs.h"
    20 #include "nsDirectoryServiceDefs.h"
    21 #include "nsDirectoryServiceUtils.h"
    22 #endif
    24 #ifdef MOZ_WIDGET_GTK
    25 #include <gtk/gtk.h>
    26 #endif
    28 #ifdef MOZ_WIDGET_ANDROID
    29 #include "AndroidBridge.h"
    30 using namespace mozilla::widget::android;
    31 #endif
    33 #ifdef MOZ_WIDGET_GONK
    34 #include <sys/system_properties.h>
    35 #endif
    37 #ifdef ANDROID
    38 extern "C" {
    39 NS_EXPORT int android_sdk_version;
    40 }
    41 #endif
    43 // Slot for NS_InitXPCOM2 to pass information to nsSystemInfo::Init.
    44 // Only set to nonzero (potentially) if XP_UNIX.  On such systems, the
    45 // system call to discover the appropriate value is not thread-safe,
    46 // so we must call it before going multithreaded, but nsSystemInfo::Init
    47 // only happens well after that point.
    48 uint32_t nsSystemInfo::gUserUmask = 0;
    50 #if defined(XP_WIN)
    51 namespace {
    52 nsresult GetHDDInfo(const char* aSpecialDirName, nsAutoCString& aModel,
    53                     nsAutoCString& aRevision)
    54 {
    55     aModel.Truncate();
    56     aRevision.Truncate();
    58     nsCOMPtr<nsIFile> profDir;
    59     nsresult rv = NS_GetSpecialDirectory(aSpecialDirName,
    60                                          getter_AddRefs(profDir));
    61     NS_ENSURE_SUCCESS(rv, rv);
    62     nsAutoString profDirPath;
    63     rv = profDir->GetPath(profDirPath);
    64     NS_ENSURE_SUCCESS(rv, rv);
    65     wchar_t volumeMountPoint[MAX_PATH] = {L'\\', L'\\', L'.', L'\\'};
    66     const size_t PREFIX_LEN = 4;
    67     if (!::GetVolumePathNameW(profDirPath.get(), volumeMountPoint + PREFIX_LEN,
    68                               mozilla::ArrayLength(volumeMountPoint) -
    69                               PREFIX_LEN)) {
    70         return NS_ERROR_UNEXPECTED;
    71     }
    72     size_t volumeMountPointLen = wcslen(volumeMountPoint);
    73     // Since we would like to open a drive and not a directory, we need to
    74     // remove any trailing backslash. A drive handle is valid for
    75     // DeviceIoControl calls, a directory handle is not.
    76     if (volumeMountPoint[volumeMountPointLen - 1] == L'\\') {
    77       volumeMountPoint[volumeMountPointLen - 1] = L'\0';
    78     }
    79     ScopedHandle handle(::CreateFileW(volumeMountPoint, 0,
    80                                       FILE_SHARE_READ | FILE_SHARE_WRITE,
    81                                       nullptr, OPEN_EXISTING, 0, nullptr));
    82     if (!handle.IsValid()) {
    83         return NS_ERROR_UNEXPECTED;
    84     }
    85     STORAGE_PROPERTY_QUERY queryParameters = {StorageDeviceProperty,
    86                                               PropertyStandardQuery};
    87     STORAGE_DEVICE_DESCRIPTOR outputHeader = {sizeof(STORAGE_DEVICE_DESCRIPTOR)};
    88     DWORD bytesRead = 0;
    89     if (!::DeviceIoControl(handle, IOCTL_STORAGE_QUERY_PROPERTY,
    90                            &queryParameters, sizeof(queryParameters),
    91                            &outputHeader, sizeof(outputHeader), &bytesRead,
    92                            nullptr)) {
    93         return NS_ERROR_FAILURE;
    94     }
    95     PSTORAGE_DEVICE_DESCRIPTOR deviceOutput =
    96                           (PSTORAGE_DEVICE_DESCRIPTOR)malloc(outputHeader.Size);
    97     if (!::DeviceIoControl(handle, IOCTL_STORAGE_QUERY_PROPERTY,
    98                            &queryParameters, sizeof(queryParameters),
    99                            deviceOutput, outputHeader.Size, &bytesRead,
   100                            nullptr)) {
   101         free(deviceOutput);
   102         return NS_ERROR_FAILURE;
   103     }
   104     // Some HDDs are including product ID info in the vendor field. Since PNP
   105     // IDs include vendor info and product ID concatenated together, we'll do
   106     // that here and interpret the result as a unique ID for the HDD model.
   107     if (deviceOutput->VendorIdOffset) {
   108         aModel = reinterpret_cast<char*>(deviceOutput) +
   109                      deviceOutput->VendorIdOffset;
   110     }
   111     if (deviceOutput->ProductIdOffset) {
   112         aModel += reinterpret_cast<char*>(deviceOutput) +
   113                       deviceOutput->ProductIdOffset;
   114     }
   115     aModel.CompressWhitespace();
   116     if (deviceOutput->ProductRevisionOffset) {
   117         aRevision = reinterpret_cast<char*>(deviceOutput) +
   118                         deviceOutput->ProductRevisionOffset;
   119         aRevision.CompressWhitespace();
   120     }
   121     free(deviceOutput);
   122     return NS_OK;
   123 }
   124 } // anonymous namespace
   125 #endif // defined(XP_WIN)
   127 using namespace mozilla;
   129 nsSystemInfo::nsSystemInfo()
   130 {
   131 }
   133 nsSystemInfo::~nsSystemInfo()
   134 {
   135 }
   137 // CPU-specific information.
   138 static const struct PropItems {
   139     const char *name;
   140     bool (*propfun)(void);
   141 } cpuPropItems[] = {
   142     // x86-specific bits.
   143     { "hasMMX", mozilla::supports_mmx },
   144     { "hasSSE", mozilla::supports_sse },
   145     { "hasSSE2", mozilla::supports_sse2 },
   146     { "hasSSE3", mozilla::supports_sse3 },
   147     { "hasSSSE3", mozilla::supports_ssse3 },
   148     { "hasSSE4A", mozilla::supports_sse4a },
   149     { "hasSSE4_1", mozilla::supports_sse4_1 },
   150     { "hasSSE4_2", mozilla::supports_sse4_2 },
   151     // ARM-specific bits.
   152     { "hasEDSP", mozilla::supports_edsp },
   153     { "hasARMv6", mozilla::supports_armv6 },
   154     { "hasARMv7", mozilla::supports_armv7 },
   155     { "hasNEON", mozilla::supports_neon }
   156 };
   158 nsresult
   159 nsSystemInfo::Init()
   160 {
   161     nsresult rv;
   163     static const struct {
   164       PRSysInfo cmd;
   165       const char *name;
   166     } items[] = {
   167       { PR_SI_SYSNAME, "name" },
   168       { PR_SI_HOSTNAME, "host" },
   169       { PR_SI_ARCHITECTURE, "arch" },
   170       { PR_SI_RELEASE, "version" }
   171     };
   173     for (uint32_t i = 0; i < (sizeof(items) / sizeof(items[0])); i++) {
   174       char buf[SYS_INFO_BUFFER_LENGTH];
   175       if (PR_GetSystemInfo(items[i].cmd, buf, sizeof(buf)) == PR_SUCCESS) {
   176         rv = SetPropertyAsACString(NS_ConvertASCIItoUTF16(items[i].name),
   177                                    nsDependentCString(buf));
   178         if (NS_WARN_IF(NS_FAILED(rv)))
   179           return rv;
   180       }
   181       else {
   182         NS_WARNING("PR_GetSystemInfo failed");
   183       }
   184     }
   186 #if defined(XP_WIN) && defined(MOZ_METRO)
   187     // Create "hasWindowsTouchInterface" property.
   188     nsAutoString version;
   189     rv = GetPropertyAsAString(NS_LITERAL_STRING("version"), version);
   190     NS_ENSURE_SUCCESS(rv, rv);
   191     double versionDouble = version.ToDouble(&rv);
   192     NS_ENSURE_SUCCESS(rv, rv);
   194     rv = SetPropertyAsBool(NS_ConvertASCIItoUTF16("hasWindowsTouchInterface"),
   195       versionDouble >= 6.2);
   196     NS_ENSURE_SUCCESS(rv, rv);
   197 #else
   198     rv = SetPropertyAsBool(NS_ConvertASCIItoUTF16("hasWindowsTouchInterface"), false);
   199     NS_ENSURE_SUCCESS(rv, rv);
   200 #endif
   202     // Additional informations not available through PR_GetSystemInfo.
   203     SetInt32Property(NS_LITERAL_STRING("pagesize"), PR_GetPageSize());
   204     SetInt32Property(NS_LITERAL_STRING("pageshift"), PR_GetPageShift());
   205     SetInt32Property(NS_LITERAL_STRING("memmapalign"), PR_GetMemMapAlignment());
   206     SetInt32Property(NS_LITERAL_STRING("cpucount"), PR_GetNumberOfProcessors());
   207     SetUint64Property(NS_LITERAL_STRING("memsize"), PR_GetPhysicalMemorySize());
   208     SetUint32Property(NS_LITERAL_STRING("umask"), nsSystemInfo::gUserUmask);
   210     for (uint32_t i = 0; i < ArrayLength(cpuPropItems); i++) {
   211         rv = SetPropertyAsBool(NS_ConvertASCIItoUTF16(cpuPropItems[i].name),
   212                                cpuPropItems[i].propfun());
   213         if (NS_WARN_IF(NS_FAILED(rv)))
   214           return rv;
   215     }
   217 #ifdef XP_WIN
   218     BOOL isWow64;
   219     BOOL gotWow64Value = IsWow64Process(GetCurrentProcess(), &isWow64);
   220     NS_WARN_IF_FALSE(gotWow64Value, "IsWow64Process failed");
   221     if (gotWow64Value) {
   222       rv = SetPropertyAsBool(NS_LITERAL_STRING("isWow64"), !!isWow64);
   223       if (NS_WARN_IF(NS_FAILED(rv)))
   224         return rv;
   225     }
   226     nsAutoCString hddModel, hddRevision;
   227     if (NS_SUCCEEDED(GetHDDInfo(NS_APP_USER_PROFILE_50_DIR, hddModel,
   228                                 hddRevision))) {
   229       rv = SetPropertyAsACString(NS_LITERAL_STRING("profileHDDModel"), hddModel);
   230       NS_ENSURE_SUCCESS(rv, rv);
   231       rv = SetPropertyAsACString(NS_LITERAL_STRING("profileHDDRevision"),
   232                                  hddRevision);
   233       NS_ENSURE_SUCCESS(rv, rv);
   234     }
   235     if (NS_SUCCEEDED(GetHDDInfo(NS_GRE_DIR, hddModel, hddRevision))) {
   236       rv = SetPropertyAsACString(NS_LITERAL_STRING("binHDDModel"), hddModel);
   237       NS_ENSURE_SUCCESS(rv, rv);
   238       rv = SetPropertyAsACString(NS_LITERAL_STRING("binHDDRevision"),
   239                                  hddRevision);
   240       NS_ENSURE_SUCCESS(rv, rv);
   241     }
   242     if (NS_SUCCEEDED(GetHDDInfo(NS_WIN_WINDOWS_DIR, hddModel, hddRevision))) {
   243       rv = SetPropertyAsACString(NS_LITERAL_STRING("winHDDModel"), hddModel);
   244       NS_ENSURE_SUCCESS(rv, rv);
   245       rv = SetPropertyAsACString(NS_LITERAL_STRING("winHDDRevision"),
   246                                  hddRevision);
   247       NS_ENSURE_SUCCESS(rv, rv);
   248     }
   249 #endif
   251 #if defined(MOZ_WIDGET_GTK)
   252     // This must be done here because NSPR can only separate OS's when compiled, not libraries.
   253     char* gtkver = PR_smprintf("GTK %u.%u.%u", gtk_major_version, gtk_minor_version, gtk_micro_version);
   254     if (gtkver) {
   255       rv = SetPropertyAsACString(NS_LITERAL_STRING("secondaryLibrary"),
   256                                  nsDependentCString(gtkver));
   257       PR_smprintf_free(gtkver);
   258       if (NS_WARN_IF(NS_FAILED(rv)))
   259         return rv;
   260     }
   261 #endif
   263 #ifdef MOZ_WIDGET_ANDROID
   264     if (mozilla::AndroidBridge::Bridge()) {
   265         nsAutoString str;
   266         if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "MODEL", str))
   267             SetPropertyAsAString(NS_LITERAL_STRING("device"), str);
   268         if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "MANUFACTURER", str))
   269             SetPropertyAsAString(NS_LITERAL_STRING("manufacturer"), str);
   270         if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build$VERSION", "RELEASE", str))
   271             SetPropertyAsAString(NS_LITERAL_STRING("release_version"), str);
   272         int32_t version;
   273         if (!mozilla::AndroidBridge::Bridge()->GetStaticIntField("android/os/Build$VERSION", "SDK_INT", &version))
   274             version = 0;
   275         android_sdk_version = version;
   276         if (version >= 8 && mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "HARDWARE", str))
   277             SetPropertyAsAString(NS_LITERAL_STRING("hardware"), str);
   278         bool isTablet = mozilla::widget::android::GeckoAppShell::IsTablet();
   279         SetPropertyAsBool(NS_LITERAL_STRING("tablet"), isTablet);
   280         // NSPR "version" is the kernel version. For Android we want the Android version.
   281         // Rename SDK version to version and put the kernel version into kernel_version.
   282         rv = GetPropertyAsAString(NS_LITERAL_STRING("version"), str);
   283         if (NS_SUCCEEDED(rv)) {
   284             SetPropertyAsAString(NS_LITERAL_STRING("kernel_version"), str);
   285         }
   286         SetPropertyAsInt32(NS_LITERAL_STRING("version"), android_sdk_version);
   287     }
   288 #endif
   290 #ifdef MOZ_WIDGET_GONK
   291     char sdk[PROP_VALUE_MAX], characteristics[PROP_VALUE_MAX];
   292     if (__system_property_get("ro.build.version.sdk", sdk))
   293       android_sdk_version = atoi(sdk);
   294     if (__system_property_get("ro.build.characteristics", characteristics)) {
   295       if (!strcmp(characteristics, "tablet"))
   296         SetPropertyAsBool(NS_LITERAL_STRING("tablet"), true);
   297     }
   298 #endif
   300     return NS_OK;
   301 }
   303 void
   304 nsSystemInfo::SetInt32Property(const nsAString &aPropertyName,
   305                                const int32_t aValue)
   306 {
   307   NS_WARN_IF_FALSE(aValue > 0, "Unable to read system value");
   308   if (aValue > 0) {
   309 #ifdef DEBUG
   310     nsresult rv =
   311 #endif
   312       SetPropertyAsInt32(aPropertyName, aValue);
   313     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Unable to set property");
   314   }
   315 }
   317 void
   318 nsSystemInfo::SetUint32Property(const nsAString &aPropertyName,
   319                                 const uint32_t aValue)
   320 {
   321   // Only one property is currently set via this function.
   322   // It may legitimately be zero.
   323 #ifdef DEBUG
   324   nsresult rv =
   325 #endif
   326     SetPropertyAsUint32(aPropertyName, aValue);
   327   NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Unable to set property");
   328 }
   330 void
   331 nsSystemInfo::SetUint64Property(const nsAString &aPropertyName,
   332                                 const uint64_t aValue)
   333 {
   334   NS_WARN_IF_FALSE(aValue > 0, "Unable to read system value");
   335   if (aValue > 0) {
   336 #ifdef DEBUG
   337     nsresult rv =
   338 #endif
   339       SetPropertyAsUint64(aPropertyName, aValue);
   340     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Unable to set property");
   341   }
   342 }

mercurial