diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 5930e879c0d2..58d94a672637 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -279,6 +279,7 @@ #ifdef MOZ_WIDGET_GTK # include +# include "mozilla/WidgetUtilsGtk.h" #endif #include "mozilla/RemoteSpellCheckEngineParent.h" @@ -2545,6 +2546,15 @@ bool ContentParent::BeginSubprocessLaunch(ProcessPriority aPriority) { extraArgs.push_back("-parentBuildID"); extraArgs.push_back(parentBuildID.get()); +#ifdef MOZ_WIDGET_GTK + // This is X11-only pending a solution for WebGL in Wayland mode. + if (StaticPrefs::dom_ipc_avoid_gtk() && + StaticPrefs::widget_non_native_theme_enabled() && + widget::GdkIsX11Display()) { + mSubprocess->SetEnv("MOZ_HEADLESS", "1"); + } +#endif + // See also ActorDealloc. mSelfRef = this; mLaunchYieldTS = TimeStamp::Now(); diff --git a/dom/ipc/tests/browser.ini b/dom/ipc/tests/browser.ini index de0c376c358a..708a6133a9fd 100644 --- a/dom/ipc/tests/browser.ini +++ b/dom/ipc/tests/browser.ini @@ -37,3 +37,6 @@ support-files = file_dummy.html skip-if = verify fission && os == "linux" && asan # Bug 1713905 - new Fission platform triage +[browser_very_fission.js] +support-files = file_dummy.html +run-if = widget == "gtk" diff --git a/dom/ipc/tests/browser_very_fission.js b/dom/ipc/tests/browser_very_fission.js new file mode 100644 index 000000000000..582fe0013368 --- /dev/null +++ b/dom/ipc/tests/browser_very_fission.js @@ -0,0 +1,38 @@ +/* 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/. */ + +"use strict"; + +// This test creates a large number of content processes as a +// regression test for bug 1635451. + +const TEST_PAGE = + "http://mochi.test:8888/browser/dom/ipc/tests/file_dummy.html"; + +const NUM_TABS = 256; + +add_task(async () => { + let promises = []; + for (let i = 0; i < NUM_TABS; ++i) { + promises.push( + BrowserTestUtils.openNewForegroundTab({ + gBrowser, + opening: TEST_PAGE, + waitForLoad: true, + forceNewProcess: true, + }) + ); + } + + let tabs = []; + for (const p of promises) { + tabs.push(await p); + } + + ok(true, "All of the tabs loaded"); + + for (const t of tabs) { + BrowserTestUtils.removeTab(t); + } +}); diff --git a/gfx/gl/GLContextProviderWayland.cpp b/gfx/gl/GLContextProviderWayland.cpp index 36ecf5032a88..3f1f926cd931 100644 --- a/gfx/gl/GLContextProviderWayland.cpp +++ b/gfx/gl/GLContextProviderWayland.cpp @@ -17,14 +17,24 @@ using namespace mozilla::widget; static class GLContextProviderX11 sGLContextProviderX11; static class GLContextProviderEGL sGLContextProviderEGL; +// Note that if there is no GTK display, `GdkIsX11Display` and +// `GdkIsWaylandDisplay` will both return false. That case can +// currently happen only in X11 mode if the pref `dom.ipc.avoid-gtk` +// is set (and applicable to this process). Thus, these conditionals +// check for the presence of Wayland rather than the absence of X11. +// +// In the future we'll want `dom.ipc.avoid-gtk` to also apply to +// Wayland; at that time we'll need another way to communicate the +// choice of window system. + already_AddRefed GLContextProviderWayland::CreateForCompositorWidget( CompositorWidget* aCompositorWidget, bool aHardwareWebRender, bool aForceAccelerated) { - if (GdkIsX11Display()) { - return sGLContextProviderX11.CreateForCompositorWidget( + if (GdkIsWaylandDisplay()) { + return sGLContextProviderEGL.CreateForCompositorWidget( aCompositorWidget, aHardwareWebRender, aForceAccelerated); } else { - return sGLContextProviderEGL.CreateForCompositorWidget( + return sGLContextProviderX11.CreateForCompositorWidget( aCompositorWidget, aHardwareWebRender, aForceAccelerated); } } @@ -32,28 +42,28 @@ already_AddRefed GLContextProviderWayland::CreateForCompositorWidget( /*static*/ already_AddRefed GLContextProviderWayland::CreateHeadless( const GLContextCreateDesc& desc, nsACString* const out_failureId) { - if (GdkIsX11Display()) { - return sGLContextProviderX11.CreateHeadless(desc, out_failureId); - } else { + if (GdkIsWaylandDisplay()) { return sGLContextProviderEGL.CreateHeadless(desc, out_failureId); + } else { + return sGLContextProviderX11.CreateHeadless(desc, out_failureId); } } /*static*/ GLContext* GLContextProviderWayland::GetGlobalContext() { - if (GdkIsX11Display()) { - return sGLContextProviderX11.GetGlobalContext(); - } else { + if (GdkIsWaylandDisplay()) { return sGLContextProviderEGL.GetGlobalContext(); + } else { + return sGLContextProviderX11.GetGlobalContext(); } } /*static*/ void GLContextProviderWayland::Shutdown() { - if (GdkIsX11Display()) { - sGLContextProviderX11.Shutdown(); - } else { + if (GdkIsWaylandDisplay()) { sGLContextProviderEGL.Shutdown(); + } else { + sGLContextProviderX11.Shutdown(); } } diff --git a/image/decoders/icon/gtk/nsIconChannel.cpp b/image/decoders/icon/gtk/nsIconChannel.cpp index 2aa78f4b1c42..ccfe789cf526 100644 --- a/image/decoders/icon/gtk/nsIconChannel.cpp +++ b/image/decoders/icon/gtk/nsIconChannel.cpp @@ -15,8 +15,6 @@ #include "mozilla/dom/ContentChild.h" #include "mozilla/gfx/Swizzle.h" #include "mozilla/ipc/ByteBuf.h" -#include "mozilla/Preferences.h" -#include "mozilla/StaticPrefs_dom.h" #include #include @@ -407,8 +405,7 @@ nsresult nsIconChannel::Init(nsIURI* aURI) { nsCOMPtr stream; using ContentChild = mozilla::dom::ContentChild; - auto* contentChild = ContentChild::GetSingleton(); - if (contentChild && mozilla::StaticPrefs::dom_ipc_remote_mozIcon()) { + if (auto* contentChild = ContentChild::GetSingleton()) { // Get the icon via IPC and translate the promise of a ByteBuf // into an actually-existing channel. RefPtr icon = diff --git a/image/test/browser/browser_mozicon_file.js b/image/test/browser/browser_mozicon_file.js index e041876716d0..8e01e0484d11 100644 --- a/image/test/browser/browser_mozicon_file.js +++ b/image/test/browser/browser_mozicon_file.js @@ -6,18 +6,6 @@ add_task(async function test_mozicon_file_no_sandbox() { assertFileProcess(); - assertMozIconIsRemote(); - await createMozIconInFile("txt"); - await createMozIconInFile("exe"); - await createMozIconInFile("non-existent-bidule"); -}); - -add_task(async function test_mozicon_file_no_sandbox_no_remote() { - await SpecialPowers.pushPrefEnv({ - set: [["dom.ipc.remote-mozIcon", false]], - }); - assertFileProcess(); - assertMozIconIsNotRemote(); await createMozIconInFile("txt"); await createMozIconInFile("exe"); await createMozIconInFile("non-existent-bidule"); diff --git a/image/test/browser/browser_mozicon_file_sandbox_headless.js b/image/test/browser/browser_mozicon_file_sandbox_headless.js index 3302bccf159c..08e86899040b 100644 --- a/image/test/browser/browser_mozicon_file_sandbox_headless.js +++ b/image/test/browser/browser_mozicon_file_sandbox_headless.js @@ -11,17 +11,3 @@ add_task(async function test_mozicon_file_with_sandbox() { await createMozIconInFile("exe"); await createMozIconInFile("non-existent-bidule"); }); - -// https://bugzilla.mozilla.org/show_bug.cgi?id=1695381#c0 -// with sandbox and no remote enabled, this is expected to fail -add_task(async function test_mozicon_file_with_sandbox_no_remote() { - await SpecialPowers.pushPrefEnv({ - set: [["dom.ipc.remote-mozIcon", false]], - }); - assertFileProcess(); - assertSandboxHeadless(); - assertMozIconIsNotRemote(); - await createMozIconInFile("txt", false); - await createMozIconInFile("exe", false); - await createMozIconInFile("non-existent-bidule", false); -}); diff --git a/image/test/browser/browser_sandbox_headless.ini b/image/test/browser/browser_sandbox_headless.ini index 3f712c141848..70cd0147ca65 100644 --- a/image/test/browser/browser_sandbox_headless.ini +++ b/image/test/browser/browser_sandbox_headless.ini @@ -3,10 +3,6 @@ support-files = head.js prefs = security.sandbox.content.headless=true -skip-if = - (os != 'linux') # the pref is only used on linux - tsan # timeout on test_mozicon_file_with_sandbox_no_remote - asan # timeout on test_mozicon_file_with_sandbox_no_remote - ccov # timeout on test_mozicon_file_with_sandbox_no_remote +skip-if = (os != 'linux') # the pref is only used on linux [browser_mozicon_file_sandbox_headless.js] diff --git a/image/test/browser/head.js b/image/test/browser/head.js index 6765f6227d3a..01db2ee45912 100644 --- a/image/test/browser/head.js +++ b/image/test/browser/head.js @@ -42,14 +42,6 @@ function assertSandboxHeadless() { assertPrefVal("security.sandbox.content.headless", true); } -function assertMozIconIsRemote() { - assertPrefVal("dom.ipc.remote-mozIcon", true); -} - -function assertMozIconIsNotRemote() { - assertPrefVal("dom.ipc.remote-mozIcon", false); -} - function getPage() { let filePage = undefined; const { Services } = ChromeUtils.import( diff --git a/ipc/glue/GeckoChildProcessHost.cpp b/ipc/glue/GeckoChildProcessHost.cpp index fa13b493030b..be44ea319ca5 100644 --- a/ipc/glue/GeckoChildProcessHost.cpp +++ b/ipc/glue/GeckoChildProcessHost.cpp @@ -603,6 +603,13 @@ uint32_t GeckoChildProcessHost::sNextUniqueID = 1; /* static */ uint32_t GeckoChildProcessHost::GetUniqueID() { return sNextUniqueID++; } +/* static */ +void GeckoChildProcessHost::SetEnv(const char* aKey, const char* aValue) { + MOZ_ASSERT(mLaunchOptions); + mLaunchOptions->env_map[ENVIRONMENT_STRING(aKey)] = + ENVIRONMENT_STRING(aValue); +} + void GeckoChildProcessHost::PrepareLaunch() { if (CrashReporter::GetEnabled()) { CrashReporter::OOPInit(); diff --git a/ipc/glue/GeckoChildProcessHost.h b/ipc/glue/GeckoChildProcessHost.h index 617c222051f6..3f7e71649fd8 100644 --- a/ipc/glue/GeckoChildProcessHost.h +++ b/ipc/glue/GeckoChildProcessHost.h @@ -84,6 +84,10 @@ class GeckoChildProcessHost : public ChildProcessHost, static uint32_t GetUniqueID(); + // Call this before launching to set an environment variable for the + // child process. The arguments must be UTF-8. + void SetEnv(const char* aKey, const char* aValue); + // Does not block. The IPC channel may not be initialized yet, and // the child process may or may not have been created when this // method returns. diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml index 37c1ad58047c..cb3ccc14e8d6 100644 --- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -2261,12 +2261,6 @@ value: 500 mirror: always -# Temporary pref to allow disabling remoting of MozIcon -- name: dom.ipc.remote-mozIcon - type: bool - value: true - mirror: always - #ifdef MOZ_ENABLE_FORKSERVER - name: dom.ipc.forkserver.enable type: bool @@ -2274,6 +2268,21 @@ mirror: once #endif +#ifdef MOZ_WIDGET_GTK +# +# Avoid the use of GTK in content processes if possible, by running +# them in headless mode, to conserve resources (e.g., connections to +# the X server). See the usage in `ContentParent.cpp` for the full +# definition of "if possible". +# +# This does not affect sandbox policies; content processes may still +# dynamically connect to the display server for, e.g., WebGL. +- name: dom.ipc.avoid-gtk + type: bool + value: true + mirror: always +#endif + # Whether or not to collect a paired minidump when force-killing a # content process. - name: dom.ipc.tabs.createKillHardCrashReports diff --git a/testing/mochitest/tests/Harness_sanity/test_sanityEventUtils.html b/testing/mochitest/tests/Harness_sanity/test_sanityEventUtils.html index 2de0b4f3dba1..b72d474f0e2d 100644 --- a/testing/mochitest/tests/Harness_sanity/test_sanityEventUtils.html +++ b/testing/mochitest/tests/Harness_sanity/test_sanityEventUtils.html @@ -34,8 +34,6 @@ const kStrictKeyPressEvents = SpecialPowers.getBoolPref("dom.keyboardevent.keypress.dispatch_non_printable_keys_only_system_group_in_content"); const kStrictKeyDownKeyUpEvents = SpecialPowers.getBoolPref("dom.keyboardevent.dispatch_during_composition"); -const kIsHeadless = - SpecialPowers.Cc["@mozilla.org/gfx/info;1"].getService(SpecialPowers.Ci.nsIGfxInfo).isHeadless; info("\nProfile::EventUtilsLoadTime: " + (loadTime - start) + "\n"); function starttest() { @@ -48,6 +46,10 @@ function starttest() { check = true; } + const kIsHeadless = await SpecialPowers.spawnChrome([], () => { + return Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo).isHeadless; + }); + if (navigator.appVersion.includes("Android")) { // This is the workaround for test failure on debug build. await SpecialPowers.pushPrefEnv({set: [["apz.zoom-to-focused-input.enabled", false]]});