widget/windows/GfxInfo.cpp

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     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 <windows.h>
     9 #include <setupapi.h>
    10 #include "gfxWindowsPlatform.h"
    11 #include "GfxInfo.h"
    12 #include "GfxInfoWebGL.h"
    13 #include "nsUnicharUtils.h"
    14 #include "prenv.h"
    15 #include "prprf.h"
    16 #include "GfxDriverInfo.h"
    17 #include "mozilla/Preferences.h"
    18 #include "nsPrintfCString.h"
    20 #if defined(MOZ_CRASHREPORTER)
    21 #include "nsExceptionHandler.h"
    22 #include "nsICrashReporter.h"
    23 #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
    24 #endif
    26 using namespace mozilla;
    27 using namespace mozilla::widget;
    29 #ifdef DEBUG
    30 NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug)
    31 #endif
    33 static const uint32_t allWindowsVersions = 0xffffffff;
    35 GfxInfo::GfxInfo()
    36  :  mWindowsVersion(0),
    37     mHasDualGPU(false),
    38     mIsGPU2Active(false)
    39 {
    40 }
    42 /* GetD2DEnabled and GetDwriteEnabled shouldn't be called until after gfxPlatform initialization
    43  * has occurred because they depend on it for information. (See bug 591561) */
    44 nsresult
    45 GfxInfo::GetD2DEnabled(bool *aEnabled)
    46 {
    47   *aEnabled = gfxWindowsPlatform::GetPlatform()->GetRenderMode() == gfxWindowsPlatform::RENDER_DIRECT2D;
    48   return NS_OK;
    49 }
    51 nsresult
    52 GfxInfo::GetDWriteEnabled(bool *aEnabled)
    53 {
    54   *aEnabled = gfxWindowsPlatform::GetPlatform()->DWriteEnabled();
    55   return NS_OK;
    56 }
    58 /* readonly attribute DOMString DWriteVersion; */
    59 NS_IMETHODIMP
    60 GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
    61 {
    62   gfxWindowsPlatform::GetDLLVersion(L"dwrite.dll", aDwriteVersion);
    63   return NS_OK;
    64 }
    66 #define PIXEL_STRUCT_RGB  1
    67 #define PIXEL_STRUCT_BGR  2
    69 /* readonly attribute DOMString cleartypeParameters; */
    70 NS_IMETHODIMP
    71 GfxInfo::GetCleartypeParameters(nsAString & aCleartypeParams)
    72 {
    73   nsTArray<ClearTypeParameterInfo> clearTypeParams;
    75   gfxWindowsPlatform::GetPlatform()->GetCleartypeParams(clearTypeParams);
    76   uint32_t d, numDisplays = clearTypeParams.Length();
    77   bool displayNames = (numDisplays > 1);
    78   bool foundData = false;
    79   nsString outStr;
    81   for (d = 0; d < numDisplays; d++) {
    82     ClearTypeParameterInfo& params = clearTypeParams[d];
    84     if (displayNames) {
    85       outStr.AppendPrintf("%s [ ", params.displayName.get());
    86     }
    88     if (params.gamma >= 0) {
    89       foundData = true;
    90       outStr.AppendPrintf("Gamma: %d ", params.gamma);
    91     }
    93     if (params.pixelStructure >= 0) {
    94       foundData = true;
    95       if (params.pixelStructure == PIXEL_STRUCT_RGB ||
    96           params.pixelStructure == PIXEL_STRUCT_BGR)
    97       {
    98         outStr.AppendPrintf("Pixel Structure: %s ",
    99                    (params.pixelStructure == PIXEL_STRUCT_RGB ?
   100                       L"RGB" : L"BGR"));
   101       } else {
   102         outStr.AppendPrintf("Pixel Structure: %d ", params.pixelStructure);
   103       }
   104     }
   106     if (params.clearTypeLevel >= 0) {
   107       foundData = true;
   108       outStr.AppendPrintf("ClearType Level: %d ", params.clearTypeLevel);
   109     }
   111     if (params.enhancedContrast >= 0) {
   112       foundData = true;
   113       outStr.AppendPrintf("Enhanced Contrast: %d ", params.enhancedContrast);
   114     }
   116     if (displayNames) {
   117       outStr.Append(MOZ_UTF16("] "));
   118     }
   119   }
   121   if (foundData) {
   122     aCleartypeParams.Assign(outStr);
   123     return NS_OK;
   124   }
   125   return NS_ERROR_FAILURE;
   126 }
   128 static nsresult GetKeyValue(const WCHAR* keyLocation, const WCHAR* keyName, nsAString& destString, int type)
   129 {
   130   HKEY key;
   131   DWORD dwcbData;
   132   DWORD dValue;
   133   DWORD resultType;
   134   LONG result;
   135   nsresult retval = NS_OK;
   137   result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyLocation, 0, KEY_QUERY_VALUE, &key);
   138   if (result != ERROR_SUCCESS) {
   139     return NS_ERROR_FAILURE;
   140   }
   142   switch (type) {
   143     case REG_DWORD: {
   144       // We only use this for vram size
   145       dwcbData = sizeof(dValue);
   146       result = RegQueryValueExW(key, keyName, nullptr, &resultType,
   147                                 (LPBYTE)&dValue, &dwcbData);
   148       if (result == ERROR_SUCCESS && resultType == REG_DWORD) {
   149         dValue = dValue / 1024 / 1024;
   150         destString.AppendInt(int32_t(dValue));
   151       } else {
   152         retval = NS_ERROR_FAILURE;
   153       }
   154       break;
   155     }
   156     case REG_MULTI_SZ: {
   157       // A chain of null-separated strings; we convert the nulls to spaces
   158       WCHAR wCharValue[1024];
   159       dwcbData = sizeof(wCharValue);
   161       result = RegQueryValueExW(key, keyName, nullptr, &resultType,
   162                                 (LPBYTE)wCharValue, &dwcbData);
   163       if (result == ERROR_SUCCESS && resultType == REG_MULTI_SZ) {
   164         // This bit here could probably be cleaner.
   165         bool isValid = false;
   167         DWORD strLen = dwcbData/sizeof(wCharValue[0]);
   168         for (DWORD i = 0; i < strLen; i++) {
   169           if (wCharValue[i] == '\0') {
   170             if (i < strLen - 1 && wCharValue[i + 1] == '\0') {
   171               isValid = true;
   172               break;
   173             } else {
   174               wCharValue[i] = ' ';
   175             }
   176           }
   177         }
   179         // ensure wCharValue is null terminated
   180         wCharValue[strLen-1] = '\0';
   182         if (isValid)
   183           destString = wCharValue;
   185       } else {
   186         retval = NS_ERROR_FAILURE;
   187       }
   189       break;
   190     }
   191   }
   192   RegCloseKey(key);
   194   return retval;
   195 }
   197 // The driver ID is a string like PCI\VEN_15AD&DEV_0405&SUBSYS_040515AD, possibly
   198 // followed by &REV_XXXX.  We uppercase the string, and strip the &REV_ part
   199 // from it, if found.
   200 static void normalizeDriverId(nsString& driverid) {
   201   ToUpperCase(driverid);
   202   int32_t rev = driverid.Find(NS_LITERAL_CSTRING("&REV_"));
   203   if (rev != -1) {
   204     driverid.Cut(rev, driverid.Length());
   205   }
   206 }
   208 // The device ID is a string like PCI\VEN_15AD&DEV_0405&SUBSYS_040515AD
   209 // this function is used to extract the id's out of it
   210 uint32_t
   211 ParseIDFromDeviceID(const nsAString &key, const char *prefix, int length)
   212 {
   213   nsAutoString id(key);
   214   ToUpperCase(id);
   215   int32_t start = id.Find(prefix);
   216   if (start != -1) {
   217     id.Cut(0, start + strlen(prefix));
   218     id.Truncate(length);
   219   }
   220   nsresult err;
   221   return id.ToInteger(&err, 16);
   222 }
   224 // OS version in 16.16 major/minor form
   225 // based on http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx
   226 enum {
   227   kWindowsUnknown = 0,
   228   kWindowsXP = 0x50001,
   229   kWindowsServer2003 = 0x50002,
   230   kWindowsVista = 0x60000,
   231   kWindows7 = 0x60001,
   232   kWindows8 = 0x60002,
   233   kWindows8_1 = 0x60003
   234 };
   236 static int32_t
   237 WindowsOSVersion()
   238 {
   239   static int32_t winVersion = UNINITIALIZED_VALUE;
   241   OSVERSIONINFO vinfo;
   243   if (winVersion == UNINITIALIZED_VALUE) {
   244     vinfo.dwOSVersionInfoSize = sizeof (vinfo);
   245 #pragma warning(push)
   246 #pragma warning(disable:4996)
   247     if (!GetVersionEx(&vinfo)) {
   248 #pragma warning(pop)
   249       winVersion = kWindowsUnknown;
   250     } else {
   251       winVersion = int32_t(vinfo.dwMajorVersion << 16) + vinfo.dwMinorVersion;
   252     }
   253   }
   255   return winVersion;
   256 }
   258 /* Other interesting places for info:
   259  *   IDXGIAdapter::GetDesc()
   260  *   IDirectDraw7::GetAvailableVidMem()
   261  *   e->GetAvailableTextureMem()
   262  * */
   264 #define DEVICE_KEY_PREFIX L"\\Registry\\Machine\\"
   265 nsresult
   266 GfxInfo::Init()
   267 {
   268   nsresult rv = GfxInfoBase::Init();
   270   DISPLAY_DEVICEW displayDevice;
   271   displayDevice.cb = sizeof(displayDevice);
   272   int deviceIndex = 0;
   274   const char *spoofedWindowsVersion = PR_GetEnv("MOZ_GFX_SPOOF_WINDOWS_VERSION");
   275   if (spoofedWindowsVersion) {
   276     PR_sscanf(spoofedWindowsVersion, "%x", &mWindowsVersion);
   277   } else {
   278     mWindowsVersion = WindowsOSVersion();
   279   }
   281   mDeviceKeyDebug = NS_LITERAL_STRING("PrimarySearch");
   283   while (EnumDisplayDevicesW(nullptr, deviceIndex, &displayDevice, 0)) {
   284     if (displayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
   285       mDeviceKeyDebug = NS_LITERAL_STRING("NullSearch");
   286       break;
   287     }
   288     deviceIndex++;
   289   }
   291   // make sure the string is nullptr terminated
   292   if (wcsnlen(displayDevice.DeviceKey, ArrayLength(displayDevice.DeviceKey))
   293       == ArrayLength(displayDevice.DeviceKey)) {
   294     // we did not find a nullptr
   295     return rv;
   296   }
   298   mDeviceKeyDebug = displayDevice.DeviceKey;
   300   /* DeviceKey is "reserved" according to MSDN so we'll be careful with it */
   301   /* check that DeviceKey begins with DEVICE_KEY_PREFIX */
   302   /* some systems have a DeviceKey starting with \REGISTRY\Machine\ so we need to compare case insenstively */
   303   if (_wcsnicmp(displayDevice.DeviceKey, DEVICE_KEY_PREFIX, ArrayLength(DEVICE_KEY_PREFIX)-1) != 0)
   304     return rv;
   306   // chop off DEVICE_KEY_PREFIX
   307   mDeviceKey = displayDevice.DeviceKey + ArrayLength(DEVICE_KEY_PREFIX)-1;
   309   mDeviceID = displayDevice.DeviceID;
   310   mDeviceString = displayDevice.DeviceString;
   312   // On Windows 8 and Server 2012 hosts, we want to not block RDP
   313   // sessions from attempting hardware acceleration.  RemoteFX
   314   // provides features and functionaltiy that can give a good D3D10 +
   315   // D2D + DirectWrite experience emulated via a software GPU.
   316   //
   317   // Unfortunately, the Device ID is nullptr, and we can't enumerate
   318   // it using the setup infrastructure (SetupDiGetClassDevsW below
   319   // will return INVALID_HANDLE_VALUE).
   320   if (mWindowsVersion == kWindows8 &&
   321       mDeviceID.Length() == 0 &&
   322       mDeviceString.EqualsLiteral("RDPUDD Chained DD"))
   323   {
   324     WCHAR sysdir[255];
   325     UINT len = GetSystemDirectory(sysdir, sizeof(sysdir));
   326     if (len < sizeof(sysdir)) {
   327       nsString rdpudd(sysdir);
   328       rdpudd.AppendLiteral("\\rdpudd.dll");
   329       gfxWindowsPlatform::GetDLLVersion(rdpudd.BeginReading(), mDriverVersion);
   330       mDriverDate.AssignLiteral("01-01-1970");
   332       // 0x1414 is Microsoft; 0xfefe is an invented (and unused) code
   333       mDeviceID.AssignLiteral("PCI\\VEN_1414&DEV_FEFE&SUBSYS_00000000");
   334     }
   335   }
   337   /* create a device information set composed of the current display device */
   338   HDEVINFO devinfo = SetupDiGetClassDevsW(nullptr, mDeviceID.get(), nullptr,
   339                                           DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES);
   341   if (devinfo != INVALID_HANDLE_VALUE) {
   342     HKEY key;
   343     LONG result;
   344     WCHAR value[255];
   345     DWORD dwcbData;
   346     SP_DEVINFO_DATA devinfoData;
   347     DWORD memberIndex = 0;
   349     devinfoData.cbSize = sizeof(devinfoData);
   350     NS_NAMED_LITERAL_STRING(driverKeyPre, "System\\CurrentControlSet\\Control\\Class\\");
   351     /* enumerate device information elements in the device information set */
   352     while (SetupDiEnumDeviceInfo(devinfo, memberIndex++, &devinfoData)) {
   353       /* get a string that identifies the device's driver key */
   354       if (SetupDiGetDeviceRegistryPropertyW(devinfo,
   355                                             &devinfoData,
   356                                             SPDRP_DRIVER,
   357                                             nullptr,
   358                                             (PBYTE)value,
   359                                             sizeof(value),
   360                                             nullptr)) {
   361         nsAutoString driverKey(driverKeyPre);
   362         driverKey += value;
   363         result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey.get(), 0, KEY_QUERY_VALUE, &key);
   364         if (result == ERROR_SUCCESS) {
   365           /* we've found the driver we're looking for */
   366           dwcbData = sizeof(value);
   367           result = RegQueryValueExW(key, L"DriverVersion", nullptr, nullptr,
   368                                     (LPBYTE)value, &dwcbData);
   369           if (result == ERROR_SUCCESS) {
   370             mDriverVersion = value;
   371           } else {
   372             // If the entry wasn't found, assume the worst (0.0.0.0).
   373             mDriverVersion.AssignLiteral("0.0.0.0");
   374           }
   375           dwcbData = sizeof(value);
   376           result = RegQueryValueExW(key, L"DriverDate", nullptr, nullptr,
   377                                     (LPBYTE)value, &dwcbData);
   378           if (result == ERROR_SUCCESS) {
   379             mDriverDate = value;
   380           } else {
   381             // Again, assume the worst
   382             mDriverDate.AssignLiteral("01-01-1970");
   383           }
   384           RegCloseKey(key); 
   385           break;
   386         }
   387       }
   388     }
   390     SetupDiDestroyDeviceInfoList(devinfo);
   391   }
   393   mAdapterVendorID.AppendPrintf("0x%04x", ParseIDFromDeviceID(mDeviceID, "VEN_", 4));
   394   mAdapterDeviceID.AppendPrintf("0x%04x", ParseIDFromDeviceID(mDeviceID, "&DEV_", 4));
   395   mAdapterSubsysID  = ParseIDFromDeviceID(mDeviceID,  "&SUBSYS_", 8);
   397   // We now check for second display adapter.
   399   // Device interface class for display adapters.
   400   CLSID GUID_DISPLAY_DEVICE_ARRIVAL;
   401   HRESULT hresult = CLSIDFromString(L"{1CA05180-A699-450A-9A0C-DE4FBE3DDD89}",
   402                                &GUID_DISPLAY_DEVICE_ARRIVAL);
   403   if (hresult == NOERROR) {
   404     devinfo = SetupDiGetClassDevsW(&GUID_DISPLAY_DEVICE_ARRIVAL,
   405                                    nullptr, nullptr,
   406                                    DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
   408     if (devinfo != INVALID_HANDLE_VALUE) {
   409       HKEY key;
   410       LONG result;
   411       WCHAR value[255];
   412       DWORD dwcbData;
   413       SP_DEVINFO_DATA devinfoData;
   414       DWORD memberIndex = 0;
   415       devinfoData.cbSize = sizeof(devinfoData);
   417       nsAutoString adapterDriver2;
   418       nsAutoString deviceID2;
   419       nsAutoString driverVersion2;
   420       nsAutoString driverDate2;
   421       uint32_t adapterVendorID2;
   422       uint32_t adapterDeviceID2;
   424       NS_NAMED_LITERAL_STRING(driverKeyPre, "System\\CurrentControlSet\\Control\\Class\\");
   425       /* enumerate device information elements in the device information set */
   426       while (SetupDiEnumDeviceInfo(devinfo, memberIndex++, &devinfoData)) {
   427         /* get a string that identifies the device's driver key */
   428         if (SetupDiGetDeviceRegistryPropertyW(devinfo,
   429                                               &devinfoData,
   430                                               SPDRP_DRIVER,
   431                                               nullptr,
   432                                               (PBYTE)value,
   433                                               sizeof(value),
   434                                               nullptr)) {
   435           nsAutoString driverKey2(driverKeyPre);
   436           driverKey2 += value;
   437           result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey2.get(), 0, KEY_QUERY_VALUE, &key);
   438           if (result == ERROR_SUCCESS) {
   439             dwcbData = sizeof(value);
   440             result = RegQueryValueExW(key, L"MatchingDeviceId", nullptr,
   441                                       nullptr, (LPBYTE)value, &dwcbData);
   442             if (result != ERROR_SUCCESS) {
   443               continue;
   444             }
   445             deviceID2 = value;
   446             nsAutoString adapterVendorID2String;
   447             nsAutoString adapterDeviceID2String;
   448             adapterVendorID2 = ParseIDFromDeviceID(deviceID2, "VEN_", 4);
   449             adapterVendorID2String.AppendPrintf("0x%04x", adapterVendorID2);
   450             adapterDeviceID2 = ParseIDFromDeviceID(deviceID2, "&DEV_", 4);
   451             adapterDeviceID2String.AppendPrintf("0x%04x", adapterDeviceID2);
   452             if (mAdapterVendorID == adapterVendorID2String &&
   453                 mAdapterDeviceID == adapterDeviceID2String) {
   454               RegCloseKey(key);
   455               continue;
   456             }
   458             // If this device is missing driver information, it is unlikely to
   459             // be a real display adapter.
   460             if (NS_FAILED(GetKeyValue(driverKey2.get(), L"InstalledDisplayDrivers",
   461                            adapterDriver2, REG_MULTI_SZ))) {
   462               RegCloseKey(key);
   463               continue;
   464             }
   465             dwcbData = sizeof(value);
   466             result = RegQueryValueExW(key, L"DriverVersion", nullptr, nullptr,
   467                                       (LPBYTE)value, &dwcbData);
   468             if (result != ERROR_SUCCESS) {
   469               RegCloseKey(key);
   470               continue;
   471             }
   472             driverVersion2 = value;
   473             dwcbData = sizeof(value);
   474             result = RegQueryValueExW(key, L"DriverDate", nullptr, nullptr,
   475                                       (LPBYTE)value, &dwcbData);
   476             if (result != ERROR_SUCCESS) {
   477               RegCloseKey(key);
   478               continue;
   479             }
   480             driverDate2 = value;
   481             dwcbData = sizeof(value);
   482             result = RegQueryValueExW(key, L"Device Description", nullptr,
   483                                       nullptr, (LPBYTE)value, &dwcbData);
   484             if (result != ERROR_SUCCESS) {
   485               dwcbData = sizeof(value);
   486               result = RegQueryValueExW(key, L"DriverDesc", nullptr, nullptr,
   487                                         (LPBYTE)value, &dwcbData);
   488             }
   489             RegCloseKey(key);
   490             if (result == ERROR_SUCCESS) {
   491               mHasDualGPU = true;
   492               mDeviceString2 = value;
   493               mDeviceID2 = deviceID2;
   494               mDeviceKey2 = driverKey2;
   495               mDriverVersion2 = driverVersion2;
   496               mDriverDate2 = driverDate2;
   497               mAdapterVendorID2.AppendPrintf("0x%04x", adapterVendorID2);
   498               mAdapterDeviceID2.AppendPrintf("0x%04x", adapterDeviceID2);
   499               mAdapterSubsysID2 = ParseIDFromDeviceID(mDeviceID2, "&SUBSYS_", 8);
   500               break;
   501             }
   502           }
   503         }
   504       }
   506       SetupDiDestroyDeviceInfoList(devinfo);
   507     }
   508   }
   510   mHasDriverVersionMismatch = false;
   511   if (mAdapterVendorID == GfxDriverInfo::GetDeviceVendor(VendorIntel)) {
   512     // we've had big crashers (bugs 590373 and 595364) apparently correlated
   513     // with bad Intel driver installations where the DriverVersion reported
   514     // by the registry was not the version of the DLL.
   515     bool is64bitApp = sizeof(void*) == 8;
   516     const char16_t *dllFileName = is64bitApp
   517                                  ? MOZ_UTF16("igd10umd64.dll")
   518                                  : MOZ_UTF16("igd10umd32.dll"),
   519                     *dllFileName2 = is64bitApp
   520                                  ? MOZ_UTF16("igd10iumd64.dll")
   521                                  : MOZ_UTF16("igd10iumd32.dll");
   522     nsString dllVersion, dllVersion2;
   523     gfxWindowsPlatform::GetDLLVersion((char16_t*)dllFileName, dllVersion);
   524     gfxWindowsPlatform::GetDLLVersion((char16_t*)dllFileName2, dllVersion2);
   526     uint64_t dllNumericVersion = 0, dllNumericVersion2 = 0,
   527              driverNumericVersion = 0, knownSafeMismatchVersion = 0;
   528     ParseDriverVersion(dllVersion, &dllNumericVersion);
   529     ParseDriverVersion(dllVersion2, &dllNumericVersion2);
   530     ParseDriverVersion(mDriverVersion, &driverNumericVersion);
   531     ParseDriverVersion(NS_LITERAL_STRING("9.17.10.0"), &knownSafeMismatchVersion);
   533     // If there's a driver version mismatch, consider this harmful only when
   534     // the driver version is less than knownSafeMismatchVersion.  See the
   535     // above comment about crashes with old mismatches. If the GetDllVersion
   536     // call fails, then they return 0, so that will be considered a mismatch.
   537     if (dllNumericVersion != driverNumericVersion &&
   538         dllNumericVersion2 != driverNumericVersion &&
   539         (driverNumericVersion < knownSafeMismatchVersion ||
   540          std::max(dllNumericVersion, dllNumericVersion2) < knownSafeMismatchVersion)) {
   541       mHasDriverVersionMismatch = true;
   542     }
   543   }
   545   const char *spoofedDriverVersionString = PR_GetEnv("MOZ_GFX_SPOOF_DRIVER_VERSION");
   546   if (spoofedDriverVersionString) {
   547     mDriverVersion.AssignASCII(spoofedDriverVersionString);
   548   }
   550   const char *spoofedVendor = PR_GetEnv("MOZ_GFX_SPOOF_VENDOR_ID");
   551   if (spoofedVendor) {
   552     mAdapterVendorID.AssignASCII(spoofedVendor);
   553   }
   555   const char *spoofedDevice = PR_GetEnv("MOZ_GFX_SPOOF_DEVICE_ID");
   556   if (spoofedDevice) {
   557     mAdapterDeviceID.AssignASCII(spoofedDevice);
   558   }
   560   AddCrashReportAnnotations();
   562   return rv;
   563 }
   565 /* readonly attribute DOMString adapterDescription; */
   566 NS_IMETHODIMP
   567 GfxInfo::GetAdapterDescription(nsAString & aAdapterDescription)
   568 {
   569   aAdapterDescription = mDeviceString;
   570   return NS_OK;
   571 }
   573 /* readonly attribute DOMString adapterDescription2; */
   574 NS_IMETHODIMP
   575 GfxInfo::GetAdapterDescription2(nsAString & aAdapterDescription)
   576 {
   577   aAdapterDescription = mDeviceString2;
   578   return NS_OK;
   579 }
   581 /* readonly attribute DOMString adapterRAM; */
   582 NS_IMETHODIMP
   583 GfxInfo::GetAdapterRAM(nsAString & aAdapterRAM)
   584 {
   585   if (NS_FAILED(GetKeyValue(mDeviceKey.get(), L"HardwareInformation.MemorySize", aAdapterRAM, REG_DWORD)))
   586     aAdapterRAM = L"Unknown";
   587   return NS_OK;
   588 }
   590 /* readonly attribute DOMString adapterRAM2; */
   591 NS_IMETHODIMP
   592 GfxInfo::GetAdapterRAM2(nsAString & aAdapterRAM)
   593 {
   594   if (!mHasDualGPU) {
   595     aAdapterRAM.AssignLiteral("");
   596   } else if (NS_FAILED(GetKeyValue(mDeviceKey2.get(), L"HardwareInformation.MemorySize", aAdapterRAM, REG_DWORD))) {
   597     aAdapterRAM = L"Unknown";
   598   }
   599   return NS_OK;
   600 }
   602 /* readonly attribute DOMString adapterDriver; */
   603 NS_IMETHODIMP
   604 GfxInfo::GetAdapterDriver(nsAString & aAdapterDriver)
   605 {
   606   if (NS_FAILED(GetKeyValue(mDeviceKey.get(), L"InstalledDisplayDrivers", aAdapterDriver, REG_MULTI_SZ)))
   607     aAdapterDriver = L"Unknown";
   608   return NS_OK;
   609 }
   611 /* readonly attribute DOMString adapterDriver2; */
   612 NS_IMETHODIMP
   613 GfxInfo::GetAdapterDriver2(nsAString & aAdapterDriver)
   614 {
   615   if (!mHasDualGPU) {
   616     aAdapterDriver.AssignLiteral("");
   617   } else if (NS_FAILED(GetKeyValue(mDeviceKey2.get(), L"InstalledDisplayDrivers", aAdapterDriver, REG_MULTI_SZ))) {
   618     aAdapterDriver = L"Unknown";
   619   }
   620   return NS_OK;
   621 }
   623 /* readonly attribute DOMString adapterDriverVersion; */
   624 NS_IMETHODIMP
   625 GfxInfo::GetAdapterDriverVersion(nsAString & aAdapterDriverVersion)
   626 {
   627   aAdapterDriverVersion = mDriverVersion;
   628   return NS_OK;
   629 }
   631 /* readonly attribute DOMString adapterDriverDate; */
   632 NS_IMETHODIMP
   633 GfxInfo::GetAdapterDriverDate(nsAString & aAdapterDriverDate)
   634 {
   635   aAdapterDriverDate = mDriverDate;
   636   return NS_OK;
   637 }
   639 /* readonly attribute DOMString adapterDriverVersion2; */
   640 NS_IMETHODIMP
   641 GfxInfo::GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion)
   642 {
   643   aAdapterDriverVersion = mDriverVersion2;
   644   return NS_OK;
   645 }
   647 /* readonly attribute DOMString adapterDriverDate2; */
   648 NS_IMETHODIMP
   649 GfxInfo::GetAdapterDriverDate2(nsAString & aAdapterDriverDate)
   650 {
   651   aAdapterDriverDate = mDriverDate2;
   652   return NS_OK;
   653 }
   655 /* readonly attribute DOMString adapterVendorID; */
   656 NS_IMETHODIMP
   657 GfxInfo::GetAdapterVendorID(nsAString & aAdapterVendorID)
   658 {
   659   aAdapterVendorID = mAdapterVendorID;
   660   return NS_OK;
   661 }
   663 /* readonly attribute DOMString adapterVendorID2; */
   664 NS_IMETHODIMP
   665 GfxInfo::GetAdapterVendorID2(nsAString & aAdapterVendorID)
   666 {
   667   aAdapterVendorID = mAdapterVendorID2;
   668   return NS_OK;
   669 }
   671 /* readonly attribute DOMString adapterDeviceID; */
   672 NS_IMETHODIMP
   673 GfxInfo::GetAdapterDeviceID(nsAString & aAdapterDeviceID)
   674 {
   675   aAdapterDeviceID = mAdapterDeviceID;
   676   return NS_OK;
   677 }
   679 /* readonly attribute DOMString adapterDeviceID2; */
   680 NS_IMETHODIMP
   681 GfxInfo::GetAdapterDeviceID2(nsAString & aAdapterDeviceID)
   682 {
   683   aAdapterDeviceID = mAdapterDeviceID2;
   684   return NS_OK;
   685 }
   687 /* readonly attribute boolean isGPU2Active; */
   688 NS_IMETHODIMP
   689 GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active)
   690 {
   691   *aIsGPU2Active = mIsGPU2Active;
   692   return NS_OK;
   693 }
   695 #if defined(MOZ_CRASHREPORTER)
   696 /* Cisco's VPN software can cause corruption of the floating point state.
   697  * Make a note of this in our crash reports so that some weird crashes
   698  * make more sense */
   699 static void
   700 CheckForCiscoVPN() {
   701   LONG result;
   702   HKEY key;
   703   /* This will give false positives, but hopefully no false negatives */
   704   result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Cisco Systems\\VPN Client", 0, KEY_QUERY_VALUE, &key);
   705   if (result == ERROR_SUCCESS) {
   706     RegCloseKey(key);
   707     CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("Cisco VPN\n"));
   708   }
   709 }
   710 #endif
   712 void
   713 GfxInfo::AddCrashReportAnnotations()
   714 {
   715 #if defined(MOZ_CRASHREPORTER)
   716   CheckForCiscoVPN();
   718   nsString deviceID, vendorID;
   719   nsCString narrowDeviceID, narrowVendorID;
   720   nsAutoString adapterDriverVersionString;
   722   GetAdapterDeviceID(deviceID);
   723   CopyUTF16toUTF8(deviceID, narrowDeviceID);
   724   GetAdapterVendorID(vendorID);
   725   CopyUTF16toUTF8(vendorID, narrowVendorID);
   726   GetAdapterDriverVersion(adapterDriverVersionString);
   728   CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterVendorID"),
   729                                      narrowVendorID);
   730   CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterDeviceID"),
   731                                      narrowDeviceID);
   733   /* Add an App Note for now so that we get the data immediately. These
   734    * can go away after we store the above in the socorro db */
   735   nsAutoCString note;
   736   /* AppendPrintf only supports 32 character strings, mrghh. */
   737   note.Append("AdapterVendorID: ");
   738   note.Append(narrowVendorID);
   739   note.Append(", AdapterDeviceID: ");
   740   note.Append(narrowDeviceID);
   741   note.AppendPrintf(", AdapterSubsysID: %08x, ", mAdapterSubsysID);
   742   note.Append("AdapterDriverVersion: ");
   743   note.Append(NS_LossyConvertUTF16toASCII(adapterDriverVersionString));
   745   if (vendorID == GfxDriverInfo::GetDeviceVendor(VendorAll)) {
   746     /* if we didn't find a valid vendorID lets append the mDeviceID string to try to find out why */
   747     note.Append(", ");
   748     LossyAppendUTF16toASCII(mDeviceID, note);
   749     note.Append(", ");
   750     LossyAppendUTF16toASCII(mDeviceKeyDebug, note);
   751     LossyAppendUTF16toASCII(mDeviceKeyDebug, note);
   752   }
   753   note.Append("\n");
   755   if (mHasDualGPU) {
   756     nsString deviceID2, vendorID2;
   757     nsAutoString adapterDriverVersionString2;
   758     nsCString narrowDeviceID2, narrowVendorID2;
   760     note.AppendLiteral("Has dual GPUs. GPU #2: ");
   761     GetAdapterDeviceID2(deviceID2);
   762     CopyUTF16toUTF8(deviceID2, narrowDeviceID2);
   763     GetAdapterVendorID2(vendorID2);
   764     CopyUTF16toUTF8(vendorID2, narrowVendorID2);
   765     GetAdapterDriverVersion2(adapterDriverVersionString2);
   766     note.Append("AdapterVendorID2: ");
   767     note.Append(narrowVendorID2);
   768     note.Append(", AdapterDeviceID2: ");
   769     note.Append(narrowDeviceID2);
   770     note.AppendPrintf(", AdapterSubsysID2: %08x, ", mAdapterSubsysID2);
   771     note.AppendPrintf("AdapterDriverVersion2: ");
   772     note.Append(NS_LossyConvertUTF16toASCII(adapterDriverVersionString2));
   773   }
   774   CrashReporter::AppendAppNotesToCrashReport(note);
   776 #endif
   777 }
   779 static OperatingSystem
   780 WindowsVersionToOperatingSystem(int32_t aWindowsVersion)
   781 {
   782   switch(aWindowsVersion) {
   783     case kWindowsXP:
   784       return DRIVER_OS_WINDOWS_XP;
   785     case kWindowsServer2003:
   786       return DRIVER_OS_WINDOWS_SERVER_2003;
   787     case kWindowsVista:
   788       return DRIVER_OS_WINDOWS_VISTA;
   789     case kWindows7:
   790       return DRIVER_OS_WINDOWS_7;
   791     case kWindows8:
   792       return DRIVER_OS_WINDOWS_8;
   793     case kWindows8_1:
   794       return DRIVER_OS_WINDOWS_8_1;
   795     case kWindowsUnknown:
   796     default:
   797       return DRIVER_OS_UNKNOWN;
   798     };
   799 }
   801 const nsTArray<GfxDriverInfo>&
   802 GfxInfo::GetGfxDriverInfo()
   803 {
   804   if (!mDriverInfo->Length()) {
   805     /*
   806      * It should be noted here that more specialized rules on certain features
   807      * should be inserted -before- more generalized restriction. As the first
   808      * match for feature/OS/device found in the list will be used for the final
   809      * blacklisting call.
   810      */
   812     /*
   813      * NVIDIA entries
   814      */
   815     APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_VISTA,
   816       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
   817       nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
   818       DRIVER_LESS_THAN, V(8,17,12,5721), "257.21" );
   819     APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_7,
   820       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
   821       nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
   822       DRIVER_LESS_THAN, V(8,17,12,5721), "257.21" );
   823     APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_XP,
   824       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
   825       GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
   826       DRIVER_LESS_THAN, V(6,14,11,8265), "182.65" );
   827     APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_VISTA,
   828       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
   829       GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
   830       DRIVER_LESS_THAN, V(8,17,11,8265), "182.65" );
   831     APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_7,
   832       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
   833       GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
   834       DRIVER_LESS_THAN, V(8,17,11,8265), "182.65" );
   836     /*
   837      * AMD/ATI entries
   838      */
   839     APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL,
   840       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
   841       nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
   842        DRIVER_LESS_THAN, V(8,741,0,0), "10.6" );
   843     APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL,
   844       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices,
   845       nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
   846       DRIVER_LESS_THAN, V(8,741,0,0), "10.6" );
   847     APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL,
   848       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
   849       GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
   850       DRIVER_LESS_THAN, V(8,62,0,0), "9.6" );
   851     APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL,
   852       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices,
   853       GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
   854       DRIVER_LESS_THAN, V(8,62,0,0), "9.6" );
   856     /*
   857      * Bug 783517 - crashes in AMD driver on Windows 8
   858      */
   859     APPEND_TO_DRIVER_BLOCKLIST_RANGE( DRIVER_OS_WINDOWS_8,
   860       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
   861       GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
   862       DRIVER_BETWEEN_INCLUSIVE_START, V(8,982,0,0), V(8,983,0,0), "!= 8.982.*.*" );
   863     APPEND_TO_DRIVER_BLOCKLIST_RANGE( DRIVER_OS_WINDOWS_8,
   864       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices,
   865       GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
   866       DRIVER_BETWEEN_INCLUSIVE_START, V(8,982,0,0), V(8,983,0,0), "!= 8.982.*.*" );
   868     /* OpenGL on any ATI/AMD hardware is discouraged
   869      * See:
   870      *  bug 619773 - WebGL: Crash with blue screen : "NMI: Parity Check / Memory Parity Error"
   871      *  bugs 584403, 584404, 620924 - crashes in atioglxx
   872      *  + many complaints about incorrect rendering
   873      */
   874     APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
   875       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
   876       nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
   877       DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
   878     APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
   879       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
   880       nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
   881       DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
   882     APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
   883       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices,
   884       nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
   885       DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
   886     APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
   887       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices,
   888       nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
   889       DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
   891     /*
   892      * Intel entries
   893      */
   895     /* implement the blocklist from bug 594877
   896      * Block all features on any drivers before this, as there's a crash when a MS Hotfix is installed.
   897      * The crash itself is Direct2D-related, but for safety we block all features.
   898      */
   899     #define IMPLEMENT_INTEL_DRIVER_BLOCKLIST(winVer, devFamily, driverVer)                                                      \
   900       APPEND_TO_DRIVER_BLOCKLIST2( winVer,                                                                                      \
   901         (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(devFamily), \
   902         GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,                                                 \
   903         DRIVER_LESS_THAN, driverVer )
   904     #define IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(winVer, devFamily, driverVer)                                                      \
   905       APPEND_TO_DRIVER_BLOCKLIST2( winVer,                                                                                      \
   906         (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(devFamily), \
   907         nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,                                                 \
   908         DRIVER_LESS_THAN, driverVer )
   910     IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMA500,   V(7,14,10,1006));
   911     IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMA900,   GfxDriverInfo::allDriverVersions);
   912     IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMA950,   V(7,14,10,1504));
   913     IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMA3150,  V(7,14,10,2124));
   914     IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMAX3000, V(7,15,10,1666));
   915     IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMAX4500HD, V(8,15,10,2202));
   917     IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMA500,   V(5,0,0,2026));
   918     IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMA900,   GfxDriverInfo::allDriverVersions);
   919     IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMA950,   V(8,15,10,1930));
   920     IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMA3150,  V(8,14,10,2117));
   921     IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMAX3000, V(8,15,10,1930));
   922     IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMAX4500HD, V(8,15,10,2202));
   924     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMA500,   V(3,0,20,3200));
   925     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMA900,   V(6,14,10,4764));
   926     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMA950,   V(6,14,10,4926));
   927     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMA3150,  V(6,14,10,5134));
   928     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMAX3000, V(6,14,10,5218));
   929     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMAX4500HD, V(6,14,10,4969));
   931     // StrechRect seems to suffer from precision issues which leads to artifacting
   932     // during content drawing starting with at least version 6.14.10.5082
   933     // and going until 6.14.10.5218. See bug 919454 and bug 949275 for more info.
   934     APPEND_TO_DRIVER_BLOCKLIST_RANGE(DRIVER_OS_WINDOWS_XP,
   935       const_cast<nsAString&>(GfxDriverInfo::GetDeviceVendor(VendorIntel)),
   936       const_cast<GfxDeviceFamily*>(GfxDriverInfo::GetDeviceFamily(IntelGMAX4500HD)),
   937       GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
   938       DRIVER_BETWEEN_EXCLUSIVE, V(6,14,10,5076), V(6,14,10,5218), "6.14.10.5218");
   940     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMA500,   V(3,0,20,3200));
   941     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMA900,   GfxDriverInfo::allDriverVersions);
   942     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMA950,   V(7,14,10,1504));
   943     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMA3150,  V(7,14,10,1910));
   944     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMAX3000, V(7,15,10,1666));
   945     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMAX4500HD, V(7,15,10,1666));
   947     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMA500,   V(5,0,0,2026));
   948     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMA900,   GfxDriverInfo::allDriverVersions);
   949     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMA950,   V(8,15,10,1930));
   950     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMA3150,  V(8,14,10,1972));
   951     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMAX3000, V(7,15,10,1666));
   952     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMAX4500HD, V(7,15,10,1666));
   954     /* OpenGL on any Intel hardware is discouraged */
   955     APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
   956       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), GfxDriverInfo::allDevices,
   957       nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
   958       DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
   959     APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
   960       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), GfxDriverInfo::allDevices,
   961       nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
   962       DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
   964     /* Disable D2D on Win7 on Intel HD Graphics on driver <= 8.15.10.2302
   965      * See bug 806786
   966      */
   967     APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_WINDOWS_7,
   968         (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(IntelMobileHDGraphics),
   969       nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
   970       DRIVER_LESS_THAN_OR_EQUAL, V(8,15,10,2302) );
   972     /* Disable D2D on Win8 on Intel HD Graphics on driver <= 8.15.10.2302
   973      * See bug 804144 and 863683
   974      */
   975     APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_WINDOWS_8,
   976         (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(IntelMobileHDGraphics),
   977       nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
   978       DRIVER_LESS_THAN_OR_EQUAL, V(8,15,10,2302) );
   980     /* Disable D3D9 layers on NVIDIA 6100/6150/6200 series due to glitches
   981      * whilst scrolling. See bugs: 612007, 644787 & 645872.
   982      */
   983     APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
   984       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(NvidiaBlockD3D9Layers),
   985       nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
   986       DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
   988     /* Microsoft RemoteFX; blocked less than 6.2.0.0 */
   989     APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL,
   990       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorMicrosoft), GfxDriverInfo::allDevices,
   991       GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
   992       DRIVER_LESS_THAN, V(6,2,0,0), "< 6.2.0.0" );
   993   }
   994   return *mDriverInfo;
   995 }
   997 nsresult
   998 GfxInfo::GetFeatureStatusImpl(int32_t aFeature,
   999                               int32_t *aStatus, 
  1000                               nsAString & aSuggestedDriverVersion, 
  1001                               const nsTArray<GfxDriverInfo>& aDriverInfo,
  1002                               OperatingSystem* aOS /* = nullptr */)
  1004   NS_ENSURE_ARG_POINTER(aStatus);
  1005   aSuggestedDriverVersion.SetIsVoid(true);
  1006   OperatingSystem os = WindowsVersionToOperatingSystem(mWindowsVersion);
  1007   *aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
  1008   if (aOS)
  1009     *aOS = os;
  1011   // Don't evaluate special cases if we're checking the downloaded blocklist.
  1012   if (!aDriverInfo.Length()) {
  1013     nsAutoString adapterVendorID;
  1014     nsAutoString adapterDeviceID;
  1015     nsAutoString adapterDriverVersionString;
  1016     if (NS_FAILED(GetAdapterVendorID(adapterVendorID)) ||
  1017         NS_FAILED(GetAdapterDeviceID(adapterDeviceID)) ||
  1018         NS_FAILED(GetAdapterDriverVersion(adapterDriverVersionString)))
  1020       return NS_ERROR_FAILURE;
  1023     if (!adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorIntel), nsCaseInsensitiveStringComparator()) &&
  1024         !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), nsCaseInsensitiveStringComparator()) &&
  1025         !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorAMD), nsCaseInsensitiveStringComparator()) &&
  1026         !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorATI), nsCaseInsensitiveStringComparator()) &&
  1027         !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorMicrosoft), nsCaseInsensitiveStringComparator()) &&
  1028         // FIXME - these special hex values are currently used in xpcshell tests introduced by
  1029         // bug 625160 patch 8/8. Maybe these tests need to be adjusted now that we're only whitelisting
  1030         // intel/ati/nvidia.
  1031         !adapterVendorID.LowerCaseEqualsLiteral("0xabcd") &&
  1032         !adapterVendorID.LowerCaseEqualsLiteral("0xdcba") &&
  1033         !adapterVendorID.LowerCaseEqualsLiteral("0xabab") &&
  1034         !adapterVendorID.LowerCaseEqualsLiteral("0xdcdc"))
  1036       *aStatus = FEATURE_BLOCKED_DEVICE;
  1037       return NS_OK;
  1040     uint64_t driverVersion;
  1041     if (!ParseDriverVersion(adapterDriverVersionString, &driverVersion)) {
  1042       return NS_ERROR_FAILURE;
  1045     // special-case the WinXP test slaves: they have out-of-date drivers, but we still want to
  1046     // whitelist them, actually we do know that this combination of device and driver version
  1047     // works well.
  1048     if (mWindowsVersion == kWindowsXP &&
  1049         adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), nsCaseInsensitiveStringComparator()) &&
  1050         adapterDeviceID.LowerCaseEqualsLiteral("0x0861") && // GeForce 9400
  1051         driverVersion == V(6,14,11,7756))
  1053       *aStatus = FEATURE_NO_INFO;
  1054       return NS_OK;
  1057     // Windows Server 2003 should be just like Windows XP for present purpose, but still has a different version number.
  1058     // OTOH Windows Server 2008 R1 and R2 already have the same version numbers as Vista and Seven respectively
  1059     if (os == DRIVER_OS_WINDOWS_SERVER_2003)
  1060       os = DRIVER_OS_WINDOWS_XP;
  1062     if (mHasDriverVersionMismatch) {
  1063       if (aFeature == nsIGfxInfo::FEATURE_DIRECT3D_10_LAYERS ||
  1064           aFeature == nsIGfxInfo::FEATURE_DIRECT3D_10_1_LAYERS ||
  1065           aFeature == nsIGfxInfo::FEATURE_DIRECT2D)
  1067         *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
  1068         return NS_OK;
  1073   return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, &os);
  1076 #ifdef DEBUG
  1078 // Implement nsIGfxInfoDebug
  1080 /* void spoofVendorID (in DOMString aVendorID); */
  1081 NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString & aVendorID)
  1083   mAdapterVendorID = aVendorID;
  1084   return NS_OK;
  1087 /* void spoofDeviceID (in unsigned long aDeviceID); */
  1088 NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString & aDeviceID)
  1090   mAdapterDeviceID = aDeviceID;
  1091   return NS_OK;
  1094 /* void spoofDriverVersion (in DOMString aDriverVersion); */
  1095 NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString & aDriverVersion)
  1097   mDriverVersion = aDriverVersion;
  1098   return NS_OK;
  1101 /* void spoofOSVersion (in unsigned long aVersion); */
  1102 NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion)
  1104   mWindowsVersion = aVersion;
  1105   return NS_OK;
  1108 #endif

mercurial