Bug 1294232 - Refactor blocklisting on Linux to support the downloadable blocklist. r=jrmuizel
authorAndrew Comminos <andrew@comminos.com>
Fri, 08 Feb 2019 14:36:08 -0500
changeset 464774 8962b8d9b7a673288218ed9087102032d7cf015b
parent 464773 52390d9090fbd8d46b00ea29034e7039511ff8a4
child 464775 fa767271520314149dfa231a5f3e265a533c91db
push id35725
push userrgurzau@mozilla.com
push dateMon, 18 Mar 2019 21:38:44 +0000
treeherdermozilla-central@fe798624cda0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1294232
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1294232 - Refactor blocklisting on Linux to support the downloadable blocklist. r=jrmuizel MozReview-Commit-ID: ESJY9kkqXR8 Differential Revision: https://phabricator.services.mozilla.com/D19190
toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js
toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Device.js
toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_DriverNew.js
toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverNew.js
toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverOld.js
toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_OK.js
toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_DriverOld.js
toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_OK.js
toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_No_Comparison.js
toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OK.js
toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_match.js
toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_mismatch_DriverVersion.js
toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_mismatch_OSVersion.js
toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Vendor.js
toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Version.js
toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_prefs.js
toolkit/xre/glxtest.cpp
widget/GfxDriverInfo.cpp
widget/GfxDriverInfo.h
widget/GfxInfoBase.cpp
widget/GfxInfoBase.h
widget/GfxInfoX11.cpp
widget/GfxInfoX11.h
widget/android/GfxInfo.cpp
widget/cocoa/GfxInfo.mm
widget/nsIGfxInfoDebug.idl
widget/windows/GfxInfo.cpp
--- a/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js
+++ b/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js
@@ -286,16 +286,17 @@ function spoofTheme(aId, aName, aDesc) {
     textcolor: Math.random().toString(),
     accentcolor: Math.random().toString(),
   };
 }
 
 function spoofGfxAdapter() {
   try {
     let gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfoDebug);
+    gfxInfo.fireTestProcess();
     gfxInfo.spoofVendorID(GFX_VENDOR_ID);
     gfxInfo.spoofDeviceID(GFX_DEVICE_ID);
   } catch (x) {
     // If we can't test gfxInfo, that's fine, we'll note it later.
   }
 }
 
 function spoofProfileReset() {
--- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Device.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Device.js
@@ -25,16 +25,17 @@ async function run_test() {
 
   // We can't do anything if we can't spoof the stuff we need.
   if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) {
     do_test_finished();
     return;
   }
 
   gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug);
+  gfxInfo.fireTestProcess();
 
   // Set the vendor/device ID, etc, to match the test file.
   switch (Services.appinfo.OS) {
     case "WINNT":
       gfxInfo.spoofVendorID("0xabcd");
       gfxInfo.spoofDeviceID("0x9876");
       gfxInfo.spoofDriverVersion("8.52.322.2201");
       // Windows 7
--- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_DriverNew.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_DriverNew.js
@@ -25,16 +25,17 @@ async function run_test() {
 
   // We can't do anything if we can't spoof the stuff we need.
   if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) {
     do_test_finished();
     return;
   }
 
   gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug);
+  gfxInfo.fireTestProcess();
 
   // Set the vendor/device ID, etc, to match the test file.
   switch (Services.appinfo.OS) {
     case "WINNT":
       gfxInfo.spoofVendorID("0xabcd");
       gfxInfo.spoofDeviceID("0x1234");
       gfxInfo.spoofDriverVersion("8.52.322.2202");
       // Windows 7
--- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverNew.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverNew.js
@@ -25,16 +25,17 @@ async function run_test() {
 
   // We can't do anything if we can't spoof the stuff we need.
   if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) {
     do_test_finished();
     return;
   }
 
   gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug);
+  gfxInfo.fireTestProcess();
 
   // Set the vendor/device ID, etc, to match the test file.
   switch (Services.appinfo.OS) {
     case "WINNT":
       gfxInfo.spoofVendorID("0xdcdc");
       gfxInfo.spoofDeviceID("0x1234");
       gfxInfo.spoofDriverVersion("8.52.322.1112");
       // Windows 7
--- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverOld.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverOld.js
@@ -26,16 +26,17 @@ async function run_test() {
 
   // We can't do anything if we can't spoof the stuff we need.
   if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) {
     do_test_finished();
     return;
   }
 
   gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug);
+  gfxInfo.fireTestProcess();
 
   // Set the vendor/device ID, etc, to match the test file.
   switch (Services.appinfo.OS) {
     case "WINNT":
       gfxInfo.spoofVendorID("0xdcdc");
       gfxInfo.spoofDeviceID("0x1234");
       gfxInfo.spoofDriverVersion("8.52.322.1110");
       // Windows 7
--- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_OK.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_OK.js
@@ -25,16 +25,17 @@ async function run_test() {
 
   // We can't do anything if we can't spoof the stuff we need.
   if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) {
     do_test_finished();
     return;
   }
 
   gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug);
+  gfxInfo.fireTestProcess();
 
   // Set the vendor/device ID, etc, to match the test file.
   switch (Services.appinfo.OS) {
     case "WINNT":
       gfxInfo.spoofVendorID("0xdcdc");
       gfxInfo.spoofDeviceID("0x1234");
       gfxInfo.spoofDriverVersion("8.52.322.1111");
       // Windows 7
--- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_DriverOld.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_DriverOld.js
@@ -25,16 +25,17 @@ async function run_test() {
 
   // We can't do anything if we can't spoof the stuff we need.
   if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) {
     do_test_finished();
     return;
   }
 
   gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug);
+  gfxInfo.fireTestProcess();
 
   // Set the vendor/device ID, etc, to match the test file.
   switch (Services.appinfo.OS) {
     case "WINNT":
       gfxInfo.spoofVendorID("0xabab");
       gfxInfo.spoofDeviceID("0x1234");
       gfxInfo.spoofDriverVersion("8.52.322.2201");
       // Windows 7
--- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_OK.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_OK.js
@@ -25,16 +25,17 @@ async function run_test() {
 
   // We can't do anything if we can't spoof the stuff we need.
   if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) {
     do_test_finished();
     return;
   }
 
   gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug);
+  gfxInfo.fireTestProcess();
 
   // Set the vendor/device ID, etc, to match the test file.
   switch (Services.appinfo.OS) {
     case "WINNT":
       gfxInfo.spoofVendorID("0xabab");
       gfxInfo.spoofDeviceID("0x1234");
       gfxInfo.spoofDriverVersion("8.52.322.2202");
       // Windows 7
--- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_No_Comparison.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_No_Comparison.js
@@ -25,16 +25,17 @@ async function run_test() {
 
   // We can't do anything if we can't spoof the stuff we need.
   if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) {
     do_test_finished();
     return;
   }
 
   gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug);
+  gfxInfo.fireTestProcess();
 
   gfxInfo.spoofVendorID("0xabcd");
   gfxInfo.spoofDeviceID("0x6666");
 
   // Spoof the OS version so it matches the test file.
   switch (Services.appinfo.OS) {
     case "WINNT":
       // Windows 7
--- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OK.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OK.js
@@ -25,16 +25,17 @@ async function run_test() {
 
   // We can't do anything if we can't spoof the stuff we need.
   if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) {
     do_test_finished();
     return;
   }
 
   gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug);
+  gfxInfo.fireTestProcess();
 
   // Set the vendor/device ID, etc, to match the test file.
   switch (Services.appinfo.OS) {
     case "WINNT":
       gfxInfo.spoofVendorID("0xabcd");
       gfxInfo.spoofDeviceID("0x1234");
       gfxInfo.spoofDriverVersion("8.52.322.2201");
       // Windows 7
--- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_match.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_match.js
@@ -24,16 +24,17 @@ async function run_test() {
 
   // We can't do anything if we can't spoof the stuff we need.
   if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) {
     do_test_finished();
     return;
   }
 
   gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug);
+  gfxInfo.fireTestProcess();
 
   // Set the vendor/device ID, etc, to match the test file.
   gfxInfo.spoofDriverVersion("8.52.322.2201");
   gfxInfo.spoofVendorID("0xabcd");
   gfxInfo.spoofDeviceID("0x1234");
 
   // Spoof the version of the OS appropriately to test the test file.
   switch (Services.appinfo.OS) {
--- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_mismatch_DriverVersion.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_mismatch_DriverVersion.js
@@ -25,16 +25,17 @@ async function run_test() {
 
   // We can't do anything if we can't spoof the stuff we need.
   if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) {
     do_test_finished();
     return;
   }
 
   gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug);
+  gfxInfo.fireTestProcess();
 
   // Set the vendor/device ID, etc, to match the test file.
   gfxInfo.spoofDriverVersion("8.52.322.2202");
   gfxInfo.spoofVendorID("0xabcd");
   gfxInfo.spoofDeviceID("0x1234");
 
   // Spoof the version of the OS appropriately to test the test file.
   switch (Services.appinfo.OS) {
--- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_mismatch_OSVersion.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_mismatch_OSVersion.js
@@ -25,16 +25,17 @@ async function run_test() {
 
   // We can't do anything if we can't spoof the stuff we need.
   if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) {
     do_test_finished();
     return;
   }
 
   gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug);
+  gfxInfo.fireTestProcess();
 
   // Set the vendor/device ID, etc, to match the test file.
   gfxInfo.spoofDriverVersion("8.52.322.2201");
   gfxInfo.spoofVendorID("0xabcd");
   gfxInfo.spoofDeviceID("0x1234");
 
   // Spoof the version of the OS appropriately to test the test file.
   switch (Services.appinfo.OS) {
--- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Vendor.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Vendor.js
@@ -25,16 +25,17 @@ async function run_test() {
 
   // We can't do anything if we can't spoof the stuff we need.
   if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) {
     do_test_finished();
     return;
   }
 
   gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug);
+  gfxInfo.fireTestProcess();
 
   // Set the vendor/device ID, etc, to match the test file.
   switch (Services.appinfo.OS) {
     case "WINNT":
       gfxInfo.spoofVendorID("0xdcba");
       gfxInfo.spoofDeviceID("0x1234");
       gfxInfo.spoofDriverVersion("8.52.322.2201");
       // Windows 7
--- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Version.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Version.js
@@ -24,16 +24,17 @@ async function run_test() {
 
   // We can't do anything if we can't spoof the stuff we need.
   if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) {
     do_test_finished();
     return;
   }
 
   gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug);
+  gfxInfo.fireTestProcess();
 
   // Set the vendor/device ID, etc, to match the test file.
   switch (Services.appinfo.OS) {
     case "WINNT":
       gfxInfo.spoofVendorID("0xabcd");
       gfxInfo.spoofDeviceID("0x1234");
       gfxInfo.spoofDriverVersion("8.52.322.2201");
       // Windows 7
--- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_prefs.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_prefs.js
@@ -29,16 +29,17 @@ async function run_test() {
 
   // We can't do anything if we can't spoof the stuff we need.
   if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) {
     do_test_finished();
     return;
   }
 
   gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug);
+  gfxInfo.fireTestProcess();
 
   // Set the vendor/device ID, etc, to match the test file.
   switch (Services.appinfo.OS) {
     case "WINNT":
       gfxInfo.spoofVendorID("0xabcd");
       gfxInfo.spoofDeviceID("0x1234");
       gfxInfo.spoofDriverVersion("8.52.322.2201");
       // Windows 7
--- a/toolkit/xre/glxtest.cpp
+++ b/toolkit/xre/glxtest.cpp
@@ -53,16 +53,30 @@ typedef XID GLXPbuffer;
 
 // stuff from gl.h
 typedef uint8_t GLubyte;
 typedef uint32_t GLenum;
 #define GL_VENDOR 0x1F00
 #define GL_RENDERER 0x1F01
 #define GL_VERSION 0x1F02
 
+// GLX_MESA_query_renderer
+#define GLX_RENDERER_VENDOR_ID_MESA                            0x8183
+#define GLX_RENDERER_DEVICE_ID_MESA                            0x8184
+#define GLX_RENDERER_VERSION_MESA                              0x8185
+#define GLX_RENDERER_ACCELERATED_MESA                          0x8186
+#define GLX_RENDERER_VIDEO_MEMORY_MESA                         0x8187
+#define GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA          0x8188
+#define GLX_RENDERER_PREFERRED_PROFILE_MESA                    0x8189
+#define GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA          0x818A
+#define GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA 0x818B
+#define GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA            0x818C
+#define GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA           0x818D
+#define GLX_RENDERER_ID_MESA                                   0x818E
+
 namespace mozilla {
 namespace widget {
 // the read end of the pipe, which will be used by GfxInfo
 extern int glxtest_pipe;
 // the PID of the glxtest process, to pass to waitpid()
 extern pid_t glxtest_pid;
 }  // namespace widget
 }  // namespace mozilla
@@ -196,32 +210,72 @@ void glxtest() {
   ///// Get a GL context and make it current //////
   GLXContext context = glXCreateContext(dpy, vInfo, nullptr, True);
   glXMakeCurrent(dpy, window, context);
 
   ///// Look for this symbol to determine texture_from_pixmap support /////
   void *glXBindTexImageEXT = glXGetProcAddress("glXBindTexImageEXT");
 
   ///// Get GL vendor/renderer/versions strings /////
-  enum { bufsize = 1024 };
+  enum { bufsize = 2048 };
   char buf[bufsize];
-  const GLubyte *vendorString = glGetString(GL_VENDOR);
-  const GLubyte *rendererString = glGetString(GL_RENDERER);
-  const GLubyte *versionString = glGetString(GL_VERSION);
+  const GLubyte* versionString = glGetString(GL_VERSION);
+  const GLubyte* vendorString = glGetString(GL_VENDOR);
+  const GLubyte* rendererString = glGetString(GL_RENDERER);
 
-  if (!vendorString || !rendererString || !versionString)
+  if (!versionString || !vendorString || !rendererString)
     fatal_error("glGetString returned null");
 
   int length =
       snprintf(buf, bufsize, "VENDOR\n%s\nRENDERER\n%s\nVERSION\n%s\nTFP\n%s\n",
                vendorString, rendererString, versionString,
                glXBindTexImageEXT ? "TRUE" : "FALSE");
   if (length >= bufsize)
     fatal_error("GL strings length too large for buffer size");
 
+  // If GLX_MESA_query_renderer is available, populate additional data.
+  typedef Bool (*PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC) (int attribute, unsigned int* value);
+  PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC glXQueryCurrentRendererIntegerMESAProc =
+    cast<PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC>(glXGetProcAddress("glXQueryCurrentRendererIntegerMESA"));
+  if (glXQueryCurrentRendererIntegerMESAProc) {
+    unsigned int vendorId, deviceId, accelerated, videoMemoryMB;
+    glXQueryCurrentRendererIntegerMESAProc(GLX_RENDERER_VENDOR_ID_MESA, &vendorId);
+    glXQueryCurrentRendererIntegerMESAProc(GLX_RENDERER_DEVICE_ID_MESA, &deviceId);
+    glXQueryCurrentRendererIntegerMESAProc(GLX_RENDERER_ACCELERATED_MESA, &accelerated);
+    glXQueryCurrentRendererIntegerMESAProc(GLX_RENDERER_VIDEO_MEMORY_MESA, &videoMemoryMB);
+
+    // Truncate IDs to 4 digits- that's all PCI IDs are.
+    vendorId &= 0xFFFF;
+    deviceId &= 0xFFFF;
+
+    length += snprintf(buf + length, bufsize,
+                       "MESA_VENDOR_ID\n0x%04x\n"
+                       "MESA_DEVICE_ID\n0x%04x\n"
+                       "MESA_ACCELERATED\n%s\n"
+                       "MESA_VRAM\n%dMB\n",
+                       vendorId, deviceId, accelerated ? "TRUE" : "FALSE",
+                       videoMemoryMB);
+
+    if (length >= bufsize)
+      fatal_error("GL strings length too large for buffer size");
+  }
+
+  // From Mesa's GL/internal/dri_interface.h, to be used by DRI clients.
+  typedef const char * (* PFNGLXGETSCREENDRIVERPROC) (Display *dpy, int scrNum);
+  PFNGLXGETSCREENDRIVERPROC glXGetScreenDriverProc =
+    cast<PFNGLXGETSCREENDRIVERPROC>(glXGetProcAddress("glXGetScreenDriver"));
+  if (glXGetScreenDriverProc) {
+    const char* driDriver = glXGetScreenDriverProc(dpy, DefaultScreen(dpy));
+    if (driDriver) {
+      length += snprintf(buf + length, bufsize, "DRI_DRIVER\n%s\n", driDriver);
+      if (length >= bufsize)
+        fatal_error("GL strings length too large for buffer size");
+    }
+  }
+
   ///// Clean up. Indeed, the parent process might fail to kill us (e.g. if it
   ///// doesn't need to check GL info) so we might be staying alive for longer
   ///// than expected, so it's important to consume as little memory as
   ///// possible. Also we want to check that we're able to do that too without
   ///// generating X errors.
   glXMakeCurrent(dpy, None,
                  nullptr);  // must release the GL context before destroying it
   glXDestroyContext(dpy, context);
--- a/widget/GfxDriverInfo.cpp
+++ b/widget/GfxDriverInfo.cpp
@@ -376,14 +376,19 @@ const nsAString& GfxDriverInfo::GetDevic
     DECLARE_VENDOR_ID(VendorNVIDIA, "0x10de");
     DECLARE_VENDOR_ID(VendorAMD, "0x1022");
     DECLARE_VENDOR_ID(VendorATI, "0x1002");
     DECLARE_VENDOR_ID(VendorMicrosoft, "0x1414");
     DECLARE_VENDOR_ID(VendorParallels, "0x1ab8");
     // Choose an arbitrary Qualcomm PCI VENdor ID for now.
     // TODO: This should be "QCOM" when Windows device ID parsing is reworked.
     DECLARE_VENDOR_ID(VendorQualcomm, "0x5143");
+    DECLARE_VENDOR_ID(VendorMesaAll, "mesa/all");
+    DECLARE_VENDOR_ID(VendorMesaLLVMPipe, "mesa/llvmpipe");
+    DECLARE_VENDOR_ID(VendorMesaSoftPipe, "mesa/softpipe");
+    DECLARE_VENDOR_ID(VendorMesaSWRast, "mesa/swrast");
+    DECLARE_VENDOR_ID(VendorMesaUnknown, "mesa/unknown");
     // Suppress a warning.
     DECLARE_VENDOR_ID(DeviceVendorMax, "");
   }
 
   return *sDeviceVendors[id];
 }
--- a/widget/GfxDriverInfo.h
+++ b/widget/GfxDriverInfo.h
@@ -122,16 +122,28 @@ enum DeviceVendor {
   VendorAll,  // There is an assumption that this is the first enum
   VendorIntel,
   VendorNVIDIA,
   VendorAMD,
   VendorATI,
   VendorMicrosoft,
   VendorParallels,
   VendorQualcomm,
+
+  // Wildcard for all Mesa drivers.
+  VendorMesaAll,
+  // Note that the following list of Mesa drivers is not comprehensive; we pull
+  // the DRI driver at runtime. These drivers are provided for convenience when
+  // populating the local blocklist.
+  VendorMesaLLVMPipe,
+  VendorMesaSoftPipe,
+  VendorMesaSWRast,
+  // A generic ID to be provided when we can't determine the DRI driver on Mesa.
+  VendorMesaUnknown,
+
   DeviceVendorMax
 };
 
 /* Array of devices to match, or an empty array for all devices */
 typedef nsTArray<nsString> GfxDeviceFamily;
 
 struct GfxDriverInfo {
   // If |ownDevices| is true, you are transferring ownership of the devices
@@ -271,17 +283,17 @@ inline void PadDriverDecimal(char *aStri
   }
   aString[4] = 0;
 }
 
 inline bool ParseDriverVersion(const nsAString &aVersion,
                                uint64_t *aNumericVersion) {
   *aNumericVersion = 0;
 
-#if defined(XP_WIN)
+#if defined(XP_WIN) || defined(MOZ_X11)
   int a, b, c, d;
   char aStr[8], bStr[8], cStr[8], dStr[8];
   /* honestly, why do I even bother */
   if (!SplitDriverVersion(NS_LossyConvertUTF16toASCII(aVersion).get(), aStr,
                           bStr, cStr, dStr))
     return false;
 
   PadDriverDecimal(bStr);
--- a/widget/GfxInfoBase.cpp
+++ b/widget/GfxInfoBase.cpp
@@ -690,17 +690,17 @@ int32_t GfxInfoBase::FindBlocklistedDevi
       (NS_FAILED(GetAdapterVendorID2(adapterVendorID[1])) ||
        NS_FAILED(GetAdapterDeviceID2(adapterDeviceID[1])) ||
        NS_FAILED(GetAdapterDriverVersion2(adapterDriverVersionString[1])));
   // No point in going on if we don't have adapter info
   if (adapterInfoFailed[0] && adapterInfoFailed[1]) {
     return 0;
   }
 
-#if defined(XP_WIN) || defined(ANDROID)
+#if defined(XP_WIN) || defined(ANDROID) || defined(MOZ_X11)
   uint64_t driverVersion[2] = {0, 0};
   if (!adapterInfoFailed[0]) {
     ParseDriverVersion(adapterDriverVersionString[0], &driverVersion[0]);
   }
   if (!adapterInfoFailed[1]) {
     ParseDriverVersion(adapterDriverVersionString[1], &driverVersion[1]);
   }
 #endif
@@ -723,21 +723,17 @@ int32_t GfxInfoBase::FindBlocklistedDevi
       continue;
     }
 
     if (info[i].mOperatingSystemVersion &&
         info[i].mOperatingSystemVersion != OperatingSystemVersion()) {
       continue;
     }
 
-    if (!info[i].mAdapterVendor.Equals(
-            GfxDriverInfo::GetDeviceVendor(VendorAll),
-            nsCaseInsensitiveStringComparator()) &&
-        !info[i].mAdapterVendor.Equals(adapterVendorID[infoIndex],
-                                       nsCaseInsensitiveStringComparator())) {
+    if (!DoesVendorMatch(info[i].mAdapterVendor, adapterVendorID[infoIndex])) {
       continue;
     }
 
     if (info[i].mDevices != GfxDriverInfo::allDevices &&
         info[i].mDevices->Length()) {
       bool deviceMatches = false;
       for (uint32_t j = 0; j < info[i].mDevices->Length(); j++) {
         if ((*info[i].mDevices)[j].Equals(
@@ -764,17 +760,17 @@ int32_t GfxInfoBase::FindBlocklistedDevi
     if (!info[i].mProduct.IsEmpty() && !info[i].mProduct.Equals(Product())) {
       continue;
     }
     if (!info[i].mManufacturer.IsEmpty() &&
         !info[i].mManufacturer.Equals(Manufacturer())) {
       continue;
     }
 
-#if defined(XP_WIN) || defined(ANDROID)
+#if defined(XP_WIN) || defined(ANDROID) || defined(MOZ_X11)
     switch (info[i].mComparisonOp) {
       case DRIVER_LESS_THAN:
         match = driverVersion[infoIndex] < info[i].mDriverVersion;
         break;
       case DRIVER_BUILD_ID_LESS_THAN:
         match = (driverVersion[infoIndex] & 0xFFFF) < info[i].mDriverVersion;
         break;
       case DRIVER_LESS_THAN_OR_EQUAL:
@@ -878,16 +874,24 @@ int32_t GfxInfoBase::FindBlocklistedDevi
 }
 
 void GfxInfoBase::SetFeatureStatus(
     const nsTArray<dom::GfxInfoFeatureStatus>& aFS) {
   MOZ_ASSERT(!sFeatureStatus);
   sFeatureStatus = new nsTArray<dom::GfxInfoFeatureStatus>(aFS);
 }
 
+bool GfxInfoBase::DoesVendorMatch(const nsAString& aBlocklistVendor,
+                                  const nsAString& aAdapterVendor) {
+  return aBlocklistVendor.Equals(aAdapterVendor,
+                                 nsCaseInsensitiveStringComparator()) ||
+         aBlocklistVendor.Equals(GfxDriverInfo::GetDeviceVendor(VendorAll),
+                                 nsCaseInsensitiveStringComparator());
+}
+
 nsresult GfxInfoBase::GetFeatureStatusImpl(
     int32_t aFeature, int32_t* aStatus, nsAString& aSuggestedVersion,
     const nsTArray<GfxDriverInfo>& aDriverInfo, nsACString& aFailureId,
     OperatingSystem* aOS /* = nullptr */) {
   if (aFeature <= 0) {
     gfxWarning() << "Invalid feature <= 0";
     return NS_OK;
   }
--- a/widget/GfxInfoBase.h
+++ b/widget/GfxInfoBase.h
@@ -120,16 +120,20 @@ class GfxInfoBase : public nsIGfxInfo,
       const nsTArray<GfxDriverInfo>& aDriverInfo, nsACString& aFailureId,
       OperatingSystem* aOS = nullptr);
 
   // Gets the driver info table. Used by GfxInfoBase to check for general cases
   // (while subclasses check for more specific ones).
   virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo() = 0;
 
   virtual void DescribeFeatures(JSContext* aCx, JS::Handle<JSObject*> obj);
+
+  virtual bool DoesVendorMatch(const nsAString& aBlocklistVendor,
+                               const nsAString& aAdapterVendor);
+
   bool InitFeatureObject(JSContext* aCx, JS::Handle<JSObject*> aContainer,
                          const char* aName,
                          mozilla::gfx::FeatureStatus& aKnownStatus,
                          JS::MutableHandle<JSObject*> aOutObj);
 
   NS_IMETHOD ControlGPUProcessForXPCShell(bool aEnable, bool* _retval) override;
 
  private:
--- a/widget/GfxInfoX11.cpp
+++ b/widget/GfxInfoX11.cpp
@@ -9,53 +9,52 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <errno.h>
 #include <sys/utsname.h>
 #include "nsCRTGlue.h"
 #include "nsExceptionHandler.h"
 #include "nsICrashReporter.h"
 #include "prenv.h"
+#include "nsPrintfCString.h"
+#include "nsWhitespaceTokenizer.h"
 
 #include "GfxInfoX11.h"
 
+#ifdef DEBUG
+bool fire_glxtest_process();
+#endif
+
 namespace mozilla {
 namespace widget {
 
 #ifdef DEBUG
 NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug)
 #endif
 
 // these global variables will be set when firing the glxtest process
 int glxtest_pipe = -1;
 pid_t glxtest_pid = 0;
 
 nsresult GfxInfo::Init() {
   mGLMajorVersion = 0;
-  mMajorVersion = 0;
-  mMinorVersion = 0;
-  mRevisionVersion = 0;
+  mGLMinorVersion = 0;
+  mHasTextureFromPixmap = false;
   mIsMesa = false;
-  mIsNVIDIA = false;
-  mIsFGLRX = false;
-  mIsNouveau = false;
-  mIsIntel = false;
-  mIsOldSwrast = false;
-  mIsLlvmpipe = false;
-  mHasTextureFromPixmap = false;
+  mIsAccelerated = true;
   return GfxInfoBase::Init();
 }
 
 void GfxInfo::AddCrashReportAnnotations() {
   CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::AdapterVendorID,
-                                     mVendor);
+                                     mVendorId);
   CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::AdapterDeviceID,
-                                     mRenderer);
+                                     mDeviceId);
   CrashReporter::AnnotateCrashReport(
-      CrashReporter::Annotation::AdapterDriverVersion, mVersion);
+      CrashReporter::Annotation::AdapterDriverVersion, mDriverVersion);
 }
 
 void GfxInfo::GetData() {
   // to understand this function, see bug 639842. We retrieve the OpenGL driver
   // information in a separate process to protect against bad drivers.
 
   // if glxtest_pipe == -1, that means that we already read the information
   if (glxtest_pipe == -1) return;
@@ -103,60 +102,81 @@ void GfxInfo::GetData() {
                                 WIFEXITED(glxtest_status) &&
                                 WEXITSTATUS(glxtest_status) != EXIT_SUCCESS;
   bool received_signal =
       !waiting_for_glxtest_process_failed && WIFSIGNALED(glxtest_status);
 
   bool error = waiting_for_glxtest_process_failed || exited_with_error_code ||
                received_signal;
 
+  nsCString glVendor;
+  nsCString glRenderer;
+  nsCString glVersion;
   nsCString textureFromPixmap;
+
+  // Available if GLX_MESA_query_renderer is supported.
+  nsCString mesaVendor;
+  nsCString mesaDevice;
+  nsCString mesaAccelerated;
+  // Available if using a DRI-based libGL stack.
+  nsCString driDriver;
+
   nsCString *stringToFill = nullptr;
   char *bufptr = buf;
   if (!error) {
     while (true) {
       char *line = NS_strtok("\n", &bufptr);
       if (!line) break;
       if (stringToFill) {
         stringToFill->Assign(line);
         stringToFill = nullptr;
       } else if (!strcmp(line, "VENDOR"))
-        stringToFill = &mVendor;
+        stringToFill = &glVendor;
       else if (!strcmp(line, "RENDERER"))
-        stringToFill = &mRenderer;
+        stringToFill = &glRenderer;
       else if (!strcmp(line, "VERSION"))
-        stringToFill = &mVersion;
+        stringToFill = &glVersion;
       else if (!strcmp(line, "TFP"))
         stringToFill = &textureFromPixmap;
+      else if (!strcmp(line, "MESA_VENDOR_ID"))
+        stringToFill = &mesaVendor;
+      else if (!strcmp(line, "MESA_DEVICE_ID"))
+        stringToFill = &mesaDevice;
+      else if (!strcmp(line, "MESA_ACCELERATED"))
+        stringToFill = &mesaAccelerated;
+      else if (!strcmp(line, "MESA_VRAM"))
+        stringToFill = &mAdapterRAM;
+      else if (!strcmp(line, "DRI_DRIVER"))
+        stringToFill = &driDriver;
     }
   }
 
   if (!strcmp(textureFromPixmap.get(), "TRUE")) mHasTextureFromPixmap = true;
 
   // only useful for Linux kernel version check for FGLRX driver.
   // assumes X client == X server, which is sad.
   struct utsname unameobj;
   if (uname(&unameobj) >= 0) {
     mOS.Assign(unameobj.sysname);
     mOSRelease.Assign(unameobj.release);
   }
 
   const char *spoofedVendor = PR_GetEnv("MOZ_GFX_SPOOF_GL_VENDOR");
-  if (spoofedVendor) mVendor.Assign(spoofedVendor);
+  if (spoofedVendor) glVendor.Assign(spoofedVendor);
   const char *spoofedRenderer = PR_GetEnv("MOZ_GFX_SPOOF_GL_RENDERER");
-  if (spoofedRenderer) mRenderer.Assign(spoofedRenderer);
+  if (spoofedRenderer) glRenderer.Assign(spoofedRenderer);
   const char *spoofedVersion = PR_GetEnv("MOZ_GFX_SPOOF_GL_VERSION");
-  if (spoofedVersion) mVersion.Assign(spoofedVersion);
+  if (spoofedVersion) glVersion.Assign(spoofedVersion);
   const char *spoofedOS = PR_GetEnv("MOZ_GFX_SPOOF_OS");
   if (spoofedOS) mOS.Assign(spoofedOS);
   const char *spoofedOSRelease = PR_GetEnv("MOZ_GFX_SPOOF_OS_RELEASE");
   if (spoofedOSRelease) mOSRelease.Assign(spoofedOSRelease);
 
-  if (error || mVendor.IsEmpty() || mRenderer.IsEmpty() || mVersion.IsEmpty() ||
-      mOS.IsEmpty() || mOSRelease.IsEmpty()) {
+  if (error || glVendor.IsEmpty() || glRenderer.IsEmpty() ||
+      glVersion.IsEmpty() || mOS.IsEmpty() || mOSRelease.IsEmpty()) {
     mAdapterDescription.AppendLiteral("GLXtest process failed");
     if (waiting_for_glxtest_process_failed)
       mAdapterDescription.AppendPrintf(
           " (waitpid failed with errno=%d for pid %d)", waitpid_errno,
           glxtest_pid);
     if (exited_with_error_code)
       mAdapterDescription.AppendPrintf(" (exited with status %d)",
                                        WEXITSTATUS(glxtest_status));
@@ -168,93 +188,144 @@ void GfxInfo::GetData() {
       mAdapterDescription.Append(nsDependentCString(buf));
       mAdapterDescription.Append('\n');
     }
 
     CrashReporter::AppendAppNotesToCrashReport(mAdapterDescription);
     return;
   }
 
-  mAdapterDescription.Append(mVendor);
-  mAdapterDescription.AppendLiteral(" -- ");
-  mAdapterDescription.Append(mRenderer);
-
-  AddCrashReportAnnotations();
-
-  // determine the major OpenGL version. That's the first integer in the version
-  // string.
-  mGLMajorVersion = strtol(mVersion.get(), 0, 10);
-
-  // determine driver type (vendor) and where in the version string
-  // the actual driver version numbers should be expected to be found
-  // (whereToReadVersionNumbers)
-  const char *whereToReadVersionNumbers = nullptr;
-  const char *Mesa_in_version_string = strstr(mVersion.get(), "Mesa");
-  if (Mesa_in_version_string) {
-    mIsMesa = true;
-    // with Mesa, the version string contains "Mesa major.minor" and that's all
-    // the version information we get: there is no actual driver version info.
-    whereToReadVersionNumbers = Mesa_in_version_string + strlen("Mesa");
-    if (strcasestr(mVendor.get(), "nouveau")) mIsNouveau = true;
-    if (strcasestr(mRenderer.get(),
-                   "intel"))  // yes, intel is in the renderer string
-      mIsIntel = true;
-    if (strcasestr(mRenderer.get(), "llvmpipe")) mIsLlvmpipe = true;
-    if (strcasestr(mRenderer.get(), "software rasterizer")) mIsOldSwrast = true;
-  } else if (strstr(mVendor.get(), "NVIDIA Corporation")) {
-    mIsNVIDIA = true;
-    // with the NVIDIA driver, the version string contains "NVIDIA major.minor"
-    // note that here the vendor and version strings behave differently, that's
-    // why we don't put this above alongside Mesa_in_version_string.
-    const char *NVIDIA_in_version_string = strstr(mVersion.get(), "NVIDIA");
-    if (NVIDIA_in_version_string)
-      whereToReadVersionNumbers = NVIDIA_in_version_string + strlen("NVIDIA");
-  } else if (strstr(mVendor.get(), "ATI Technologies Inc")) {
-    mIsFGLRX = true;
-    // with the FGLRX driver, the version string only gives a OpenGL version :/
-    // so let's return that. that can at least give a rough idea of how old the
-    // driver is.
-    whereToReadVersionNumbers = mVersion.get();
-  }
-
-  // read major.minor version numbers of the driver (not to be confused with the
-  // OpenGL version)
-  if (whereToReadVersionNumbers) {
-    // copy into writable buffer, for tokenization
-    strncpy(buf, whereToReadVersionNumbers, buf_size);
-    bufptr = buf;
-
-    // now try to read major.minor version numbers. In case of failure,
-    // gracefully exit: these numbers have been initialized as 0 anyways
-    char *token = NS_strtok(".", &bufptr);
-    if (token) {
-      mMajorVersion = strtol(token, 0, 10);
-      token = NS_strtok(".", &bufptr);
-      if (token) {
-        mMinorVersion = strtol(token, 0, 10);
-        token = NS_strtok(".", &bufptr);
-        if (token) mRevisionVersion = strtol(token, 0, 10);
+  // Scan the GL_VERSION string for the GL and driver versions.
+  nsCWhitespaceTokenizer tokenizer(glVersion);
+  while (tokenizer.hasMoreTokens()) {
+    nsCString token(tokenizer.nextToken());
+    unsigned int major = 0, minor = 0, revision = 0, patch = 0;
+    if (sscanf(token.get(), "%u.%u.%u.%u", &major, &minor, &revision, &patch) >=
+        2) {
+      // A survey of GL_VENDOR strings indicates that the first version is
+      // always the GL version, the second is usually the driver version.
+      if (mGLMajorVersion == 0) {
+        mGLMajorVersion = major;
+        mGLMinorVersion = minor;
+      } else if (mDriverVersion.IsEmpty()) {  // Not already spoofed.
+        mDriverVersion =
+            nsPrintfCString("%u.%u.%u.%u", major, minor, revision, patch);
       }
     }
   }
-}
+
+  if (mGLMajorVersion == 0) {
+    NS_WARNING("Failed to parse GL version!");
+    return;
+  }
+
+  // Mesa always exposes itself in the GL_VERSION string, but not always the
+  // GL_VENDOR string.
+  mIsMesa = glVersion.Find("Mesa") != -1;
 
-static inline uint64_t version(uint32_t major, uint32_t minor,
-                               uint32_t revision = 0) {
-  return (uint64_t(major) << 32) + (uint64_t(minor) << 16) + uint64_t(revision);
+  // We need to use custom vendor IDs for mesa so we can treat them
+  // differently than the proprietary drivers.
+  if (mIsMesa) {
+    mIsAccelerated = !mesaAccelerated.Equals("FALSE");
+    // Process software rasterizers before the DRI driver string; we may be
+    // forcing software rasterization on a DRI-accelerated X server by using
+    // LIBGL_ALWAYS_SOFTWARE or a similar restriction.
+    if (strcasestr(glRenderer.get(), "llvmpipe")) {
+      CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(VendorMesaLLVMPipe),
+                      mVendorId);
+      mIsAccelerated = false;
+    } else if (strcasestr(glRenderer.get(), "softpipe")) {
+      CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(VendorMesaSoftPipe),
+                      mVendorId);
+      mIsAccelerated = false;
+    } else if (strcasestr(glRenderer.get(), "software rasterizer") ||
+               !mIsAccelerated) {
+      // Fallback to reporting swrast if GLX_MESA_query_renderer tells us
+      // we're using an unaccelerated context.
+      CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(VendorMesaSWRast),
+                      mVendorId);
+      mIsAccelerated = false;
+    } else if (!driDriver.IsEmpty()) {
+      mVendorId = nsPrintfCString("mesa/%s", driDriver.get());
+    } else {
+      // Some other mesa configuration where we couldn't get enough info.
+      NS_WARNING("Failed to detect Mesa driver being used!");
+      CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(VendorMesaUnknown),
+                      mVendorId);
+    }
+
+    if (!mesaDevice.IsEmpty()) {
+      mDeviceId = mesaDevice;
+    } else {
+      NS_WARNING(
+          "Failed to get Mesa device ID! GLX_MESA_query_renderer unsupported?");
+    }
+  } else if (glVendor.EqualsLiteral("NVIDIA Corporation")) {
+    CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), mVendorId);
+    // TODO: Use NV-CONTROL X11 extension to query Device ID and VRAM.
+  } else if (glVendor.EqualsLiteral("ATI Technologies Inc.")) {
+    CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(VendorATI), mVendorId);
+    // TODO: Look into ways to find the device ID on FGLRX.
+  } else {
+    NS_WARNING("Failed to detect GL vendor!");
+  }
+
+  // Fallback to GL_VENDOR and GL_RENDERER.
+  if (mVendorId.IsEmpty()) {
+    mVendorId.Assign(glVendor.get());
+  }
+  if (mDeviceId.IsEmpty()) {
+    mDeviceId.Assign(glRenderer.get());
+  }
+
+  mAdapterDescription.Assign(glRenderer);
+
+  AddCrashReportAnnotations();
 }
 
 const nsTArray<GfxDriverInfo> &GfxInfo::GetGfxDriverInfo() {
-  // Nothing here yet.
-  // if (!sDriverInfo->Length()) {
-  //
-  //}
+  if (!sDriverInfo->Length()) {
+    // Mesa 10.0 provides the GLX_MESA_query_renderer extension, which allows us
+    // to query device IDs backing a GL context for blacklisting.
+    APPEND_TO_DRIVER_BLOCKLIST(
+        OperatingSystem::Linux,
+        (nsAString &)GfxDriverInfo::GetDeviceVendor(VendorMesaAll),
+        GfxDriverInfo::allDevices, GfxDriverInfo::allFeatures,
+        nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
+        V(10, 0, 0, 0), "FEATURE_FAILURE_OLD_MESA", "Mesa 10.0");
+
+    // NVIDIA baseline (ported from old blocklist)
+    APPEND_TO_DRIVER_BLOCKLIST(
+        OperatingSystem::Linux,
+        (nsAString &)GfxDriverInfo::GetDeviceVendor(VendorNVIDIA),
+        GfxDriverInfo::allDevices, GfxDriverInfo::allFeatures,
+        nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
+        V(257, 21, 0, 0), "FEATURE_FAILURE_OLD_NVIDIA", "NVIDIA 257.21");
+
+    // fglrx baseline (chosen arbitrarily as 2013-07-22 release).
+    APPEND_TO_DRIVER_BLOCKLIST(
+        OperatingSystem::Linux,
+        (nsAString &)GfxDriverInfo::GetDeviceVendor(VendorATI),
+        GfxDriverInfo::allDevices, GfxDriverInfo::allFeatures,
+        nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
+        V(13, 15, 100, 1), "FEATURE_FAILURE_OLD_FGLRX", "fglrx 13.15.100.1");
+  }
   return *sDriverInfo;
 }
 
+bool GfxInfo::DoesVendorMatch(const nsAString &aBlocklistVendor,
+                              const nsAString &aAdapterVendor) {
+  if (mIsMesa &&
+      aBlocklistVendor.Equals(GfxDriverInfo::GetDeviceVendor(VendorMesaAll),
+                              nsCaseInsensitiveStringComparator())) {
+    return true;
+  }
+  return GfxInfoBase::DoesVendorMatch(aBlocklistVendor, aAdapterVendor);
+}
+
 nsresult GfxInfo::GetFeatureStatusImpl(
     int32_t aFeature, int32_t *aStatus, nsAString &aSuggestedDriverVersion,
     const nsTArray<GfxDriverInfo> &aDriverInfo, nsACString &aFailureId,
     OperatingSystem *aOS /* = nullptr */)
 
 {
   NS_ENSURE_ARG_POINTER(aStatus);
   *aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
@@ -263,122 +334,39 @@ nsresult GfxInfo::GetFeatureStatusImpl(
   if (aOS) *aOS = os;
 
   if (sShutdownOccurred) {
     return NS_OK;
   }
 
   GetData();
 
+  if (mGLMajorVersion == 0) {
+    // If we failed to get a GL version, glxtest failed.
+    *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
+    aFailureId = "FEATURE_FAILURE_GLXTEST_FAILED";
+    return NS_OK;
+  }
+
   if (mGLMajorVersion == 1) {
     // We're on OpenGL 1. In most cases that indicates really old hardware.
     // We better block them, rather than rely on them to fail gracefully,
     // because they don't! see bug 696636
     *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
     aFailureId = "FEATURE_FAILURE_OPENGL_1";
     return NS_OK;
   }
 
-  // Don't evaluate any special cases if we're checking the downloaded
-  // blocklist.
-  if (!aDriverInfo.Length()) {
-    // Blacklist software GL implementations from using layers acceleration.
-    // On the test infrastructure, we'll force-enable layers acceleration.
-    if (aFeature == nsIGfxInfo::FEATURE_OPENGL_LAYERS &&
-        (mIsLlvmpipe || mIsOldSwrast) &&
-        !PR_GetEnv("MOZ_LAYERS_ALLOW_SOFTWARE_GL")) {
-      *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
-      aFailureId = "FEATURE_FAILURE_SOFTWARE_GL";
-      return NS_OK;
-    }
-
-    if (aFeature == nsIGfxInfo::FEATURE_WEBRENDER) {
-      *aStatus = nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION;
-      aFailureId = "FEATURE_UNQUALIFIED_WEBRENDER_LINUX";
-      return NS_OK;
-    }
-
-    // Only check features relevant to Linux.
-    if (aFeature == nsIGfxInfo::FEATURE_OPENGL_LAYERS ||
-        aFeature == nsIGfxInfo::FEATURE_WEBGL_OPENGL ||
-        aFeature == nsIGfxInfo::FEATURE_WEBGL2 ||
-        aFeature == nsIGfxInfo::FEATURE_WEBGL_MSAA) {
-      // whitelist the linux test slaves' current configuration.
-      // this is necessary as they're still using the slightly outdated 190.42
-      // driver. this isn't a huge risk, as at least this is the exact setting
-      // in which we do continuous testing, and this only affects GeForce 9400
-      // cards on linux on this precise driver version, which is very few users.
-      // We do the same thing on Windows XP, see in widget/windows/GfxInfo.cpp
-      if (mIsNVIDIA && !strcmp(mRenderer.get(), "GeForce 9400/PCI/SSE2") &&
-          !strcmp(mVersion.get(), "3.2.0 NVIDIA 190.42")) {
-        *aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
-        return NS_OK;
-      }
-
-      if (mIsMesa) {
-        if (mIsNouveau &&
-            version(mMajorVersion, mMinorVersion) < version(8, 0)) {
-          *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
-          aFailureId = "FEATURE_FAILURE_MESA_1";
-          aSuggestedDriverVersion.AssignLiteral("Mesa 8.0");
-        } else if (version(mMajorVersion, mMinorVersion, mRevisionVersion) <
-                   version(7, 10, 3)) {
-          *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
-          aFailureId = "FEATURE_FAILURE_MESA_2";
-          aSuggestedDriverVersion.AssignLiteral("Mesa 7.10.3");
-        } else if (mIsOldSwrast) {
-          *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
-          aFailureId = "FEATURE_FAILURE_SW_RAST";
-        } else if (mIsLlvmpipe &&
-                   version(mMajorVersion, mMinorVersion) < version(9, 1)) {
-          // bug 791905, Mesa bug 57733, fixed in Mesa 9.1 according to
-          // https://bugs.freedesktop.org/show_bug.cgi?id=57733#c3
-          *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
-          aFailureId = "FEATURE_FAILURE_MESA_3";
-        } else if (aFeature == nsIGfxInfo::FEATURE_WEBGL_MSAA) {
-          if (mIsIntel &&
-              version(mMajorVersion, mMinorVersion) < version(8, 1)) {
-            *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
-            aFailureId = "FEATURE_FAILURE_MESA_4";
-            aSuggestedDriverVersion.AssignLiteral("Mesa 8.1");
-          }
-        }
-
-      } else if (mIsNVIDIA) {
-        if (version(mMajorVersion, mMinorVersion, mRevisionVersion) <
-            version(257, 21)) {
-          *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
-          aFailureId = "FEATURE_FAILURE_OLD_NV";
-          aSuggestedDriverVersion.AssignLiteral("NVIDIA 257.21");
-        }
-      } else if (mIsFGLRX) {
-        // FGLRX does not report a driver version number, so we have the OpenGL
-        // version instead. by requiring OpenGL 3, we effectively require recent
-        // drivers.
-        if (version(mMajorVersion, mMinorVersion, mRevisionVersion) <
-            version(3, 0)) {
-          *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
-          aFailureId = "FEATURE_FAILURE_OLD_FGLRX";
-          aSuggestedDriverVersion.AssignLiteral("<Something recent>");
-        }
-        // Bug 724640: FGLRX + Linux 2.6.32 is a crashy combo
-        bool unknownOS = mOS.IsEmpty() || mOSRelease.IsEmpty();
-        bool badOS =
-            mOS.Find("Linux", true) != -1 && mOSRelease.Find("2.6.32") != -1;
-        if (unknownOS || badOS) {
-          *aStatus = nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION;
-          aFailureId = "FEATURE_FAILURE_OLD_OS";
-        }
-      } else {
-        // like on windows, let's block unknown vendors. Think of virtual
-        // machines. Also, this case is hit whenever the GLXtest probe failed to
-        // get driver info or crashed.
-        *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
-      }
-    }
+  // Blacklist software GL implementations from using layers acceleration.
+  // On the test infrastructure, we'll force-enable layers acceleration.
+  if (aFeature == nsIGfxInfo::FEATURE_OPENGL_LAYERS && !mIsAccelerated &&
+      !PR_GetEnv("MOZ_LAYERS_ALLOW_SOFTWARE_GL")) {
+    *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
+    aFailureId = "FEATURE_FAILURE_SOFTWARE_GL";
+    return NS_OK;
   }
 
   return GfxInfoBase::GetFeatureStatusImpl(
       aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, aFailureId, &os);
 }
 
 NS_IMETHODIMP
 GfxInfo::GetD2DEnabled(bool *aEnabled) { return NS_ERROR_FAILURE; }
@@ -405,17 +393,18 @@ GfxInfo::GetAdapterDescription(nsAString
 
 NS_IMETHODIMP
 GfxInfo::GetAdapterDescription2(nsAString &aAdapterDescription) {
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 GfxInfo::GetAdapterRAM(nsAString &aAdapterRAM) {
-  aAdapterRAM.Truncate();
+  GetData();
+  CopyUTF8toUTF16(mAdapterRAM, aAdapterRAM);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 GfxInfo::GetAdapterRAM2(nsAString &aAdapterRAM) { return NS_ERROR_FAILURE; }
 
 NS_IMETHODIMP
 GfxInfo::GetAdapterDriver(nsAString &aAdapterDriver) {
@@ -426,17 +415,17 @@ GfxInfo::GetAdapterDriver(nsAString &aAd
 NS_IMETHODIMP
 GfxInfo::GetAdapterDriver2(nsAString &aAdapterDriver) {
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 GfxInfo::GetAdapterDriverVersion(nsAString &aAdapterDriverVersion) {
   GetData();
-  CopyASCIItoUTF16(mVersion, aAdapterDriverVersion);
+  CopyASCIItoUTF16(mDriverVersion, aAdapterDriverVersion);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 GfxInfo::GetAdapterDriverVersion2(nsAString &aAdapterDriverVersion) {
   return NS_ERROR_FAILURE;
 }
 
@@ -449,29 +438,29 @@ GfxInfo::GetAdapterDriverDate(nsAString 
 NS_IMETHODIMP
 GfxInfo::GetAdapterDriverDate2(nsAString &aAdapterDriverDate) {
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 GfxInfo::GetAdapterVendorID(nsAString &aAdapterVendorID) {
   GetData();
-  CopyUTF8toUTF16(mVendor, aAdapterVendorID);
+  CopyUTF8toUTF16(mVendorId, aAdapterVendorID);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 GfxInfo::GetAdapterVendorID2(nsAString &aAdapterVendorID) {
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 GfxInfo::GetAdapterDeviceID(nsAString &aAdapterDeviceID) {
   GetData();
-  CopyUTF8toUTF16(mRenderer, aAdapterDeviceID);
+  CopyUTF8toUTF16(mDeviceId, aAdapterDeviceID);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 GfxInfo::GetAdapterDeviceID2(nsAString &aAdapterDeviceID) {
   return NS_ERROR_FAILURE;
 }
 
@@ -489,31 +478,47 @@ NS_IMETHODIMP
 GfxInfo::GetIsGPU2Active(bool *aIsGPU2Active) { return NS_ERROR_FAILURE; }
 
 #ifdef DEBUG
 
 // Implement nsIGfxInfoDebug
 // We don't support spoofing anything on Linux
 
 NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString &aVendorID) {
-  CopyUTF16toUTF8(aVendorID, mVendor);
+  GetData();
+  CopyUTF16toUTF8(aVendorID, mVendorId);
+  mIsAccelerated = !(mVendorId.EqualsLiteral("mesa/llvmpipe") ||
+                     mVendorId.EqualsLiteral("mesa/softpipe") ||
+                     mVendorId.EqualsLiteral("mesa/swrast"));
   return NS_OK;
 }
 
 NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString &aDeviceID) {
-  CopyUTF16toUTF8(aDeviceID, mRenderer);
+  GetData();
+  CopyUTF16toUTF8(aDeviceID, mDeviceId);
   return NS_OK;
 }
 
 NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString &aDriverVersion) {
-  CopyUTF16toUTF8(aDriverVersion, mVersion);
+  GetData();
+  CopyUTF16toUTF8(aDriverVersion, mDriverVersion);
   return NS_OK;
 }
 
 NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion) {
   // We don't support OS versioning on Linux. There's just "Linux".
   return NS_OK;
 }
 
+NS_IMETHODIMP GfxInfo::FireTestProcess() {
+  // If the pid is zero, then we have never run the test process to query for
+  // driver information. This would normally be run on startup, but we need to
+  // manually invoke it for XPC shell tests.
+  if (glxtest_pid == 0) {
+    fire_glxtest_process();
+  }
+  return NS_OK;
+}
+
 #endif
 
 }  // end namespace widget
 }  // end namespace mozilla
--- a/widget/GfxInfoX11.h
+++ b/widget/GfxInfoX11.h
@@ -4,16 +4,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef __GfxInfoX11_h__
 #define __GfxInfoX11_h__
 
 #include "GfxInfoBase.h"
+#include "nsString.h"
 
 namespace mozilla {
 namespace widget {
 
 class GfxInfo final : public GfxInfoBase {
  public:
   // We only declare the subset of nsIGfxInfo that we actually implement. The
   // rest is brought forward from GfxInfoBase.
@@ -55,27 +56,31 @@ class GfxInfo final : public GfxInfoBase
   ~GfxInfo() {}
 
   virtual nsresult GetFeatureStatusImpl(
       int32_t aFeature, int32_t* aStatus, nsAString& aSuggestedDriverVersion,
       const nsTArray<GfxDriverInfo>& aDriverInfo, nsACString& aFailureId,
       OperatingSystem* aOS = nullptr) override;
   virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo() override;
 
+  virtual bool DoesVendorMatch(const nsAString& aBlocklistVendor,
+                               const nsAString& aAdapterVendor) override;
+
  private:
-  nsCString mVendor;
-  nsCString mRenderer;
-  nsCString mVersion;
+  nsCString mVendorId;
+  nsCString mDeviceId;
+  nsCString mDriverVersion;
   nsCString mAdapterDescription;
+  nsCString mAdapterRAM;
   nsCString mOS;
   nsCString mOSRelease;
-  bool mIsMesa, mIsNVIDIA, mIsFGLRX, mIsNouveau, mIsIntel, mIsOldSwrast,
-      mIsLlvmpipe;
   bool mHasTextureFromPixmap;
-  int mGLMajorVersion, mMajorVersion, mMinorVersion, mRevisionVersion;
+  unsigned int mGLMajorVersion, mGLMinorVersion;
+  bool mIsMesa;
+  bool mIsAccelerated;
 
   void AddCrashReportAnnotations();
 };
 
 }  // namespace widget
 }  // namespace mozilla
 
 #endif /* __GfxInfoX11_h__ */
--- a/widget/android/GfxInfo.cpp
+++ b/widget/android/GfxInfo.cpp
@@ -528,16 +528,20 @@ NS_IMETHODIMP GfxInfo::SpoofDriverVersio
 }
 
 NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion) {
   EnsureInitialized();
   mOSVersion = aVersion;
   return NS_OK;
 }
 
+NS_IMETHODIMP GfxInfo::FireTestProcess() {
+  return NS_OK;
+}
+
 #endif
 
 nsString GfxInfo::Model() {
   EnsureInitialized();
   return mModel;
 }
 
 nsString GfxInfo::Hardware() {
--- a/widget/cocoa/GfxInfo.mm
+++ b/widget/cocoa/GfxInfo.mm
@@ -349,9 +349,14 @@ NS_IMETHODIMP GfxInfo::SpoofDriverVersio
 }
 
 /* void spoofOSVersion (in unsigned long aVersion); */
 NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion) {
   mOSXVersion = aVersion;
   return NS_OK;
 }
 
+/* void fireTestProcess (); */
+NS_IMETHODIMP GfxInfo::FireTestProcess() {
+  return NS_OK;
+}
+
 #endif
--- a/widget/nsIGfxInfoDebug.idl
+++ b/widget/nsIGfxInfoDebug.idl
@@ -11,9 +11,14 @@
 interface nsIGfxInfoDebug : nsISupports
 {
   void spoofVendorID(in AString aVendorID);
   void spoofDeviceID(in AString aDeviceID);
   
   void spoofDriverVersion(in AString aDriverVersion);
 
   void spoofOSVersion(in unsigned long aVersion);
+
+  /* Manually invoke any test processes required to query for driver
+     information. This is used by XPC shell tests which do not run these queries
+     by default. */
+  void fireTestProcess();
 };
--- a/widget/windows/GfxInfo.cpp
+++ b/widget/windows/GfxInfo.cpp
@@ -1822,9 +1822,13 @@ NS_IMETHODIMP GfxInfo::SpoofDriverVersio
   return NS_OK;
 }
 
 NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion) {
   mWindowsVersion = aVersion;
   return NS_OK;
 }
 
+NS_IMETHODIMP GfxInfo::FireTestProcess() {
+  return NS_OK;
+}
+
 #endif