diff --git a/shell/browser/electron_browser_main_parts.cc b/shell/browser/electron_browser_main_parts.cc index d97f24fe631a..45937808d07a 100644 --- a/shell/browser/electron_browser_main_parts.cc +++ b/shell/browser/electron_browser_main_parts.cc @@ -155,6 +155,7 @@ std::u16string MediaStringProvider(media::MessageId id) { } #if defined(OS_LINUX) + void OverrideLinuxAppDataPath() { base::FilePath path; if (base::PathService::Get(DIR_APP_DATA, &path)) @@ -375,8 +376,24 @@ void ElectronBrowserMainParts::PostDestroyThreads() { fake_browser_process_->PostDestroyThreads(); } +#if defined(OS_LINUX) +// static +base::Optional& ElectronBrowserMainParts::GetGDKBackend() { + static base::Optional gdk_backend; + return gdk_backend; +} +#endif + void ElectronBrowserMainParts::ToolkitInitialized() { #if defined(OS_LINUX) + // This is set by Chromium here: + // https://chromium-review.googlesource.com/c/chromium/src/+/2586184 + // and can detrimentally affect external app behaviors, so we want to + // check if the user has set it so we can use it later. + std::string backend; + if (base::Environment::Create()->GetVar("GDK_BACKEND", &backend)) + GetGDKBackend().reset(backend); + auto linux_ui = BuildGtkUi(); linux_ui->Initialize(); diff --git a/shell/browser/electron_browser_main_parts.h b/shell/browser/electron_browser_main_parts.h index d385e5ef7e79..22c92e76a3fc 100644 --- a/shell/browser/electron_browser_main_parts.h +++ b/shell/browser/electron_browser_main_parts.h @@ -88,6 +88,11 @@ class ElectronBrowserMainParts : public content::BrowserMainParts { Browser* browser() { return browser_.get(); } BrowserProcessImpl* browser_process() { return fake_browser_process_.get(); } +#if defined(OS_LINUX) + // Used by platform_util to set GDK_BACKEND. + static base::Optional& GetGDKBackend(); +#endif + protected: // content::BrowserMainParts: int PreEarlyInitialization() override; diff --git a/shell/common/platform_util_linux.cc b/shell/common/platform_util_linux.cc index a54b0144aa4c..b9895e4ddc86 100644 --- a/shell/common/platform_util_linux.cc +++ b/shell/common/platform_util_linux.cc @@ -19,6 +19,7 @@ #include "dbus/bus.h" #include "dbus/message.h" #include "dbus/object_proxy.h" +#include "shell/browser/electron_browser_main_parts.h" #include "shell/common/platform_util_internal.h" #include "ui/gtk/gtk_util.h" #include "url/gurl.h" @@ -122,6 +123,18 @@ bool XDGUtil(const std::vector& argv, // bring up a new terminal if necessary. See "man mailcap". options.environment["MM_NOTTTY"] = "1"; + // If the user set a GDK_BACKEND value of their own, use that, + // otherwise unset it becuase Chromium is setting GDK_BACKEND + // during GTK initialization and we want to respect user preference. + // Setting values in EnvironmentMap to an empty-string + // will make sure that they get unset from the environment via + // AlterEnvironment(). + const base::Optional& gdk_backend = + electron::ElectronBrowserMainParts::GetGDKBackend(); + options.environment["GDK_BACKEND"] = gdk_backend.has_value() + ? gdk_backend.value().c_str() + : base::NativeEnvironmentString(); + base::Process process = base::LaunchProcess(argv, options); if (!process.IsValid()) return false; diff --git a/spec-main/chromium-spec.ts b/spec-main/chromium-spec.ts index c27f652c7603..512583f38266 100644 --- a/spec-main/chromium-spec.ts +++ b/spec-main/chromium-spec.ts @@ -367,6 +367,13 @@ describe('web security', () => { }); }); +ifdescribe(process.platform === 'linux')('subprocesses', () => { + it('does not propagate GDK_BACKEND', () => { + const backend = process.env.GDK_BACKEND; + expect(backend).to.eq(null); + }); +}); + describe('command line switches', () => { let appProcess: ChildProcess.ChildProcessWithoutNullStreams | undefined; afterEach(() => {