Bug 1602819 - Expose desktop environment (e.g. GNOME, KDE) on Linux. r=jrmuizel draft
authorAndrew Osmond <aosmond@mozilla.com>
Tue, 10 Dec 2019 18:21:22 +0000
changeset 2527029 5389dc78f6bcb060c78da61da458dd14421f8563
parent 2526795 f5d38101ac7c0bb452a09a08226f65d9e5d29f8c
child 2527030 a97d5270c80dad7a04a380a19230e79ca8cd2241
push id463244
push userreviewbot
push dateTue, 10 Dec 2019 18:21:42 +0000
treeherdertry@a97d5270c80d [default view] [failures only]
reviewersjrmuizel
bugs1602819
milestone73.0a1
Bug 1602819 - Expose desktop environment (e.g. GNOME, KDE) on Linux. r=jrmuizel Differential Revision: https://phabricator.services.mozilla.com/D56563 Differential Diff: PHID-DIFF-xj4gqm6fmv32bume2xzx
toolkit/content/aboutSupport.js
toolkit/crashreporter/CrashAnnotations.yaml
toolkit/locales/en-US/toolkit/about/aboutSupport.ftl
toolkit/modules/Troubleshoot.jsm
toolkit/modules/tests/browser/browser_Troubleshoot.js
widget/GfxInfoX11.cpp
widget/GfxInfoX11.h
widget/android/GfxInfo.cpp
widget/android/GfxInfo.h
widget/cocoa/GfxInfo.h
widget/cocoa/GfxInfo.mm
widget/nsIGfxInfo.idl
widget/windows/GfxInfo.cpp
widget/windows/GfxInfo.h
--- a/toolkit/content/aboutSupport.js
+++ b/toolkit/content/aboutSupport.js
@@ -586,16 +586,17 @@ var snapshotFormatters = {
       "webgl2WSIInfo",
       "webgl2Renderer",
       "webgl2Version",
       "webgl2DriverExtensions",
       "webgl2Extensions",
       ["supportsHardwareH264", "hardware-h264"],
       ["direct2DEnabled", "#Direct2D"],
       ["windowProtocol", "graphics-window-protocol"],
+      ["desktopEnvironment", "graphics-desktop-environment"],
       "usesTiling",
       "contentUsesTiling",
       "offMainThreadPaintEnabled",
       "offMainThreadPaintWorkerCount",
       "targetFrameRate",
     ];
     for (let feature of featureKeys) {
       if (Array.isArray(feature)) {
--- a/toolkit/crashreporter/CrashAnnotations.yaml
+++ b/toolkit/crashreporter/CrashAnnotations.yaml
@@ -260,16 +260,21 @@ CreateStreamOnHGlobalFailure:
     IPC proxy stream.
   type: string
 
 CycleCollector:
   description: >
     Reason why the cycle collector crashed.
   type: string
 
+DesktopEnvironment:
+  description: >
+    Desktop environment used on Linux, e.g. GNOME, KDE, XFCE, etc.
+  type: string
+
 DeviceResetReason:
   description: >
     Reason why a DirectX device has been reset, Windows only.
   type: string
 
 DOMFissionEnabled:
   description: >
     Set to 1 when DOM fission is enabled, and subframes are potentially loaded
--- a/toolkit/locales/en-US/toolkit/about/aboutSupport.ftl
+++ b/toolkit/locales/en-US/toolkit/about/aboutSupport.ftl
@@ -88,16 +88,18 @@ graphics-diagnostics-title = Diagnostics
 graphics-failure-log-title = Failure Log
 graphics-gpu1-title = GPU #1
 graphics-gpu2-title = GPU #2
 graphics-decision-log-title = Decision Log
 graphics-crash-guards-title = Crash Guard Disabled Features
 graphics-workarounds-title = Workarounds
 # Windowing system in use on Linux (e.g. X11, Wayland).
 graphics-window-protocol = Window Protocol
+# Desktop environment in use on Linux (e.g. GNOME, KDE, XFCE, etc).
+graphics-desktop-environment = Desktop Environment
 place-database-title = Places Database
 place-database-integrity = Integrity
 place-database-verify-integrity = Verify Integrity
 js-title = JavaScript
 js-incremental-gc = Incremental GC
 a11y-title = Accessibility
 a11y-activated = Activated
 a11y-force-disabled = Prevent Accessibility
--- a/toolkit/modules/Troubleshoot.jsm
+++ b/toolkit/modules/Troubleshoot.jsm
@@ -531,16 +531,17 @@ var dataProviders = {
       DWriteVersion: "directWriteVersion",
       cleartypeParameters: "clearTypeParameters",
       UsesTiling: "usesTiling",
       ContentUsesTiling: "contentUsesTiling",
       OffMainThreadPaintEnabled: "offMainThreadPaintEnabled",
       OffMainThreadPaintWorkerCount: "offMainThreadPaintWorkerCount",
       TargetFrameRate: "targetFrameRate",
       windowProtocol: null,
+      desktopEnvironment: null,
     };
 
     for (let prop in gfxInfoProps) {
       try {
         data[gfxInfoProps[prop] || prop] = gfxInfo[prop];
       } catch (e) {}
     }
 
--- a/toolkit/modules/tests/browser/browser_Troubleshoot.js
+++ b/toolkit/modules/tests/browser/browser_Troubleshoot.js
@@ -479,16 +479,19 @@ const SNAPSHOT_SCHEMA = {
           },
         },
         targetFrameRate: {
           type: "number",
         },
         windowProtocol: {
           type: "string",
         },
+        desktopEnvironment: {
+          type: "string",
+        },
       },
     },
     media: {
       required: true,
       type: "object",
       properties: {
         currentAudioBackend: {
           required: true,
--- a/widget/GfxInfoX11.cpp
+++ b/widget/GfxInfoX11.cpp
@@ -57,16 +57,18 @@ void GfxInfo::AddCrashReportAnnotations(
   CrashReporter::AnnotateCrashReport(
       CrashReporter::Annotation::AdapterDriverVendor, mDriverVendor);
   CrashReporter::AnnotateCrashReport(
       CrashReporter::Annotation::AdapterDriverVersion, mDriverVersion);
   CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::IsWayland,
                                      mIsWayland);
   CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::IsWaylandDRM,
                                      mIsWaylandDRM);
+  CrashReporter::AnnotateCrashReport(
+      CrashReporter::Annotation::DesktopEnvironment, mDesktopEnvironment);
 }
 
 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;
@@ -326,16 +328,69 @@ void GfxInfo::GetData() {
 
   mAdapterDescription.Assign(glRenderer);
 #ifdef MOZ_WAYLAND
   mIsWayland = !GDK_IS_X11_DISPLAY(gdk_display_get_default());
   if (mIsWayland) {
     mIsWaylandDRM = nsWaylandDisplay::IsDMABufEnabled();
   }
 #endif
+
+  const char* desktopEnv = getenv("XDG_CURRENT_DESKTOP");
+  if (!desktopEnv) {
+    desktopEnv = getenv("DESKTOP_SESSION");
+  }
+
+  if (desktopEnv) {
+    nsDependentCString currentDesktop(desktopEnv);
+    if (currentDesktop.EqualsIgnoreCase("gnome", sizeof("gnome") - 1)) {
+      mDesktopEnvironment.AssignLiteral("gnome");
+    } else if (currentDesktop.LowerCaseEqualsLiteral("kde")) {
+      mDesktopEnvironment.AssignLiteral("kde");
+    } else if (currentDesktop.LowerCaseEqualsLiteral("xfce")) {
+      mDesktopEnvironment.AssignLiteral("xfce");
+    } else if (currentDesktop.LowerCaseEqualsLiteral("x-cinnamon") ||
+               currentDesktop.LowerCaseEqualsLiteral("cinnamon")) {
+      mDesktopEnvironment.AssignLiteral("cinnamon");
+    } else if (currentDesktop.LowerCaseEqualsLiteral("enlightenment")) {
+      mDesktopEnvironment.AssignLiteral("enlightenment");
+    } else if (currentDesktop.LowerCaseEqualsLiteral("lxde") ||
+               currentDesktop.LowerCaseEqualsLiteral("lubuntu")) {
+      mDesktopEnvironment.AssignLiteral("lxde");
+    } else if (currentDesktop.LowerCaseEqualsLiteral("openbox")) {
+      mDesktopEnvironment.AssignLiteral("openbox");
+    } else if (currentDesktop.LowerCaseEqualsLiteral("i3")) {
+      mDesktopEnvironment.AssignLiteral("i3");
+    } else if (currentDesktop.LowerCaseEqualsLiteral("mate")) {
+      mDesktopEnvironment.AssignLiteral("mate");
+    } else if (currentDesktop.LowerCaseEqualsLiteral("unity")) {
+      mDesktopEnvironment.AssignLiteral("unity");
+    } else if (currentDesktop.LowerCaseEqualsLiteral("pantheon")) {
+      mDesktopEnvironment.AssignLiteral("pantheon");
+    } else if (currentDesktop.LowerCaseEqualsLiteral("lxqt")) {
+      mDesktopEnvironment.AssignLiteral("lxqt");
+    } else if (currentDesktop.LowerCaseEqualsLiteral("deepin")) {
+      mDesktopEnvironment.AssignLiteral("deepin");
+    }
+  }
+
+  if (mDesktopEnvironment.IsEmpty()) {
+    if (getenv("GNOME_DESKTOP_SESSION_ID")) {
+      mDesktopEnvironment.AssignLiteral("gnome");
+    } else if (getenv("KDE_FULL_SESSION")) {
+      mDesktopEnvironment.AssignLiteral("kde");
+    } else if (getenv("MATE_DESKTOP_SESSION_ID")) {
+      mDesktopEnvironment.AssignLiteral("mate");
+    } else if (getenv("LXQT_SESSION_CONFIG")) {
+      mDesktopEnvironment.AssignLiteral("lxqt");
+    } else {
+      mDesktopEnvironment.AssignLiteral("unknown");
+    }
+  }
+
   AddCrashReportAnnotations();
 }
 
 const nsTArray<GfxDriverInfo>& GfxInfo::GetGfxDriverInfo() {
   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(
@@ -504,16 +559,23 @@ GfxInfo::GetWindowProtocol(nsAString& aW
     return NS_OK;
   }
 
   aWindowProtocol.AssignLiteral("x11");
   return NS_OK;
 }
 
 NS_IMETHODIMP
+GfxInfo::GetDesktopEnvironment(nsAString& aDesktopEnvironment) {
+  GetData();
+  AppendASCIItoUTF16(mDesktopEnvironment, aDesktopEnvironment);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 GfxInfo::GetAdapterDescription(nsAString& aAdapterDescription) {
   GetData();
   AppendASCIItoUTF16(mAdapterDescription, aAdapterDescription);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 GfxInfo::GetAdapterDescription2(nsAString& aAdapterDescription) {
--- a/widget/GfxInfoX11.h
+++ b/widget/GfxInfoX11.h
@@ -18,16 +18,17 @@ class GfxInfo final : public GfxInfoBase
  public:
   // We only declare the subset of nsIGfxInfo that we actually implement. The
   // rest is brought forward from GfxInfoBase.
   NS_IMETHOD GetD2DEnabled(bool* aD2DEnabled) override;
   NS_IMETHOD GetDWriteEnabled(bool* aDWriteEnabled) override;
   NS_IMETHOD GetDWriteVersion(nsAString& aDwriteVersion) override;
   NS_IMETHOD GetCleartypeParameters(nsAString& aCleartypeParams) override;
   NS_IMETHOD GetWindowProtocol(nsAString& aWindowProtocol) override;
+  NS_IMETHOD GetDesktopEnvironment(nsAString& aDesktopEnvironment) override;
   NS_IMETHOD GetAdapterDescription(nsAString& aAdapterDescription) override;
   NS_IMETHOD GetAdapterDriver(nsAString& aAdapterDriver) override;
   NS_IMETHOD GetAdapterVendorID(nsAString& aAdapterVendorID) override;
   NS_IMETHOD GetAdapterDeviceID(nsAString& aAdapterDeviceID) override;
   NS_IMETHOD GetAdapterSubsysID(nsAString& aAdapterSubsysID) override;
   NS_IMETHOD GetAdapterRAM(uint32_t* aAdapterRAM) override;
   NS_IMETHOD GetAdapterDriverVendor(nsAString& aAdapterDriverVendor) override;
   NS_IMETHOD GetAdapterDriverVersion(nsAString& aAdapterDriverVersion) override;
@@ -74,16 +75,17 @@ class GfxInfo final : public GfxInfoBase
   nsCString mVendorId;
   nsCString mDeviceId;
   nsCString mDriverVendor;
   nsCString mDriverVersion;
   nsCString mAdapterDescription;
   uint32_t mAdapterRAM;
   nsCString mOS;
   nsCString mOSRelease;
+  nsAutoCStringN<16> mDesktopEnvironment;
 
   struct ScreenInfo {
     uint32_t mWidth;
     uint32_t mHeight;
     bool mIsDefault;
   };
 
   nsTArray<ScreenInfo> mScreenInfo;
--- a/widget/android/GfxInfo.cpp
+++ b/widget/android/GfxInfo.cpp
@@ -137,16 +137,21 @@ GfxInfo::GetCleartypeParameters(nsAStrin
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 GfxInfo::GetWindowProtocol(nsAString& aWindowProtocol) {
   return NS_ERROR_FAILURE;
 }
 
+NS_IMETHODIMP
+GfxInfo::GetDesktopEnvironment(nsAString& aDesktopEnvironment) {
+  return NS_ERROR_FAILURE;
+}
+
 void GfxInfo::EnsureInitialized() {
   if (mInitialized) return;
 
   if (!mozilla::AndroidBridge::Bridge()) {
     gfxWarning() << "AndroidBridge missing during initialization";
     return;
   }
 
--- a/widget/android/GfxInfo.h
+++ b/widget/android/GfxInfo.h
@@ -27,16 +27,17 @@ class GfxInfo : public GfxInfoBase {
 
   // We only declare the subset of nsIGfxInfo that we actually implement. The
   // rest is brought forward from GfxInfoBase.
   NS_IMETHOD GetD2DEnabled(bool* aD2DEnabled) override;
   NS_IMETHOD GetDWriteEnabled(bool* aDWriteEnabled) override;
   NS_IMETHOD GetDWriteVersion(nsAString& aDwriteVersion) override;
   NS_IMETHOD GetCleartypeParameters(nsAString& aCleartypeParams) override;
   NS_IMETHOD GetWindowProtocol(nsAString& aWindowProtocol) override;
+  NS_IMETHOD GetDesktopEnvironment(nsAString& aDesktopEnvironment) override;
   NS_IMETHOD GetAdapterDescription(nsAString& aAdapterDescription) override;
   NS_IMETHOD GetAdapterDriver(nsAString& aAdapterDriver) override;
   NS_IMETHOD GetAdapterVendorID(nsAString& aAdapterVendorID) override;
   NS_IMETHOD GetAdapterDeviceID(nsAString& aAdapterDeviceID) override;
   NS_IMETHOD GetAdapterSubsysID(nsAString& aAdapterSubsysID) override;
   NS_IMETHOD GetAdapterRAM(uint32_t* aAdapterRAM) override;
   NS_IMETHOD GetAdapterDriverVendor(nsAString& aAdapterDriverVendor) override;
   NS_IMETHOD GetAdapterDriverVersion(nsAString& aAdapterDriverVersion) override;
--- a/widget/cocoa/GfxInfo.h
+++ b/widget/cocoa/GfxInfo.h
@@ -19,16 +19,17 @@ class GfxInfo : public GfxInfoBase {
  public:
   GfxInfo();
   // We only declare the subset of nsIGfxInfo that we actually implement. The
   // rest is brought forward from GfxInfoBase.
   NS_IMETHOD GetD2DEnabled(bool* aD2DEnabled) override;
   NS_IMETHOD GetDWriteEnabled(bool* aDWriteEnabled) override;
   NS_IMETHOD GetDWriteVersion(nsAString& aDwriteVersion) override;
   NS_IMETHOD GetWindowProtocol(nsAString& aWindowProtocol) override;
+  NS_IMETHOD GetDesktopEnvironment(nsAString& aDesktopEnvironment) override;
   NS_IMETHOD GetCleartypeParameters(nsAString& aCleartypeParams) override;
   NS_IMETHOD GetAdapterDescription(nsAString& aAdapterDescription) override;
   NS_IMETHOD GetAdapterDriver(nsAString& aAdapterDriver) override;
   NS_IMETHOD GetAdapterVendorID(nsAString& aAdapterVendorID) override;
   NS_IMETHOD GetAdapterDeviceID(nsAString& aAdapterDeviceID) override;
   NS_IMETHOD GetAdapterSubsysID(nsAString& aAdapterSubsysID) override;
   NS_IMETHOD GetAdapterRAM(uint32_t* aAdapterRAM) override;
   NS_IMETHOD GetAdapterDriverVendor(nsAString& aAdapterDriverVendor) override;
--- a/widget/cocoa/GfxInfo.mm
+++ b/widget/cocoa/GfxInfo.mm
@@ -120,16 +120,20 @@ GfxInfo::GetDWriteVersion(nsAString& aDw
 /* readonly attribute DOMString cleartypeParameters; */
 NS_IMETHODIMP
 GfxInfo::GetCleartypeParameters(nsAString& aCleartypeParams) { return NS_ERROR_FAILURE; }
 
 /* readonly attribute DOMString windowProtocol; */
 NS_IMETHODIMP
 GfxInfo::GetWindowProtocol(nsAString& aWindowProtocol) { return NS_ERROR_FAILURE; }
 
+/* readonly attribute DOMString desktopEnvironment; */
+NS_IMETHODIMP
+GfxInfo::GetDesktopEnvironment(nsAString& aDesktopEnvironment) { return NS_ERROR_FAILURE; }
+
 /* readonly attribute DOMString adapterDescription; */
 NS_IMETHODIMP
 GfxInfo::GetAdapterDescription(nsAString& aAdapterDescription) {
   aAdapterDescription.AssignLiteral("");
   return NS_OK;
 }
 
 /* readonly attribute DOMString adapterDescription2; */
--- a/widget/nsIGfxInfo.idl
+++ b/widget/nsIGfxInfo.idl
@@ -18,16 +18,17 @@ interface nsIGfxInfo : nsISupports
   readonly attribute boolean usingGPUProcess;
   readonly attribute AString DWriteVersion;
   readonly attribute AString cleartypeParameters;
 
   /*
    * These are non-Android linux-specific
    */
   readonly attribute AString windowProtocol;
+  readonly attribute AString desktopEnvironment;
 
   /*
    * These are valid across all platforms.
    */
   readonly attribute AString ContentBackend;
   readonly attribute boolean WebRenderEnabled;
   readonly attribute boolean isHeadless;
   readonly attribute boolean UsesTiling;
--- a/widget/windows/GfxInfo.cpp
+++ b/widget/windows/GfxInfo.cpp
@@ -125,16 +125,21 @@ GfxInfo::GetCleartypeParameters(nsAStrin
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 GfxInfo::GetWindowProtocol(nsAString& aWindowProtocol) {
   return NS_ERROR_FAILURE;
 }
 
+NS_IMETHODIMP
+GfxInfo::GetDesktopEnvironment(nsAString& aDesktopEnvironment) {
+  return NS_ERROR_FAILURE;
+}
+
 static nsresult GetKeyValue(const WCHAR* keyLocation, const WCHAR* keyName,
                             uint32_t& destValue, int type) {
   MOZ_ASSERT(type == REG_DWORD || type == REG_QWORD);
   HKEY key;
   DWORD dwcbData;
   DWORD dValue;
   DWORD resultType;
   LONG result;
--- a/widget/windows/GfxInfo.h
+++ b/widget/windows/GfxInfo.h
@@ -21,16 +21,17 @@ class GfxInfo : public GfxInfoBase {
 
   // We only declare the subset of nsIGfxInfo that we actually implement. The
   // rest is brought forward from GfxInfoBase.
   NS_IMETHOD GetD2DEnabled(bool* aD2DEnabled) override;
   NS_IMETHOD GetDWriteEnabled(bool* aDWriteEnabled) override;
   NS_IMETHOD GetDWriteVersion(nsAString& aDwriteVersion) override;
   NS_IMETHOD GetCleartypeParameters(nsAString& aCleartypeParams) override;
   NS_IMETHOD GetWindowProtocol(nsAString& aWindowProtocol) override;
+  NS_IMETHOD GetDesktopEnvironment(nsAString& aDesktopEnvironment) override;
   NS_IMETHOD GetAdapterDescription(nsAString& aAdapterDescription) override;
   NS_IMETHOD GetAdapterDriver(nsAString& aAdapterDriver) override;
   NS_IMETHOD GetAdapterVendorID(nsAString& aAdapterVendorID) override;
   NS_IMETHOD GetAdapterDeviceID(nsAString& aAdapterDeviceID) override;
   NS_IMETHOD GetAdapterSubsysID(nsAString& aAdapterSubsysID) override;
   NS_IMETHOD GetAdapterRAM(uint32_t* aAdapterRAM) override;
   NS_IMETHOD GetAdapterDriverVendor(nsAString& aAdapterDriverVendor) override;
   NS_IMETHOD GetAdapterDriverVersion(nsAString& aAdapterDriverVersion) override;