Thu, 15 Jan 2015 15:59:08 +0100
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 */)
1003 {
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)))
1019 {
1020 return NS_ERROR_FAILURE;
1021 }
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"))
1035 {
1036 *aStatus = FEATURE_BLOCKED_DEVICE;
1037 return NS_OK;
1038 }
1040 uint64_t driverVersion;
1041 if (!ParseDriverVersion(adapterDriverVersionString, &driverVersion)) {
1042 return NS_ERROR_FAILURE;
1043 }
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))
1052 {
1053 *aStatus = FEATURE_NO_INFO;
1054 return NS_OK;
1055 }
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)
1066 {
1067 *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
1068 return NS_OK;
1069 }
1070 }
1071 }
1073 return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, &os);
1074 }
1076 #ifdef DEBUG
1078 // Implement nsIGfxInfoDebug
1080 /* void spoofVendorID (in DOMString aVendorID); */
1081 NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString & aVendorID)
1082 {
1083 mAdapterVendorID = aVendorID;
1084 return NS_OK;
1085 }
1087 /* void spoofDeviceID (in unsigned long aDeviceID); */
1088 NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString & aDeviceID)
1089 {
1090 mAdapterDeviceID = aDeviceID;
1091 return NS_OK;
1092 }
1094 /* void spoofDriverVersion (in DOMString aDriverVersion); */
1095 NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString & aDriverVersion)
1096 {
1097 mDriverVersion = aDriverVersion;
1098 return NS_OK;
1099 }
1101 /* void spoofOSVersion (in unsigned long aVersion); */
1102 NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion)
1103 {
1104 mWindowsVersion = aVersion;
1105 return NS_OK;
1106 }
1108 #endif