Backed out 8 changesets (bug 1650118) for wpt failures on inside-dedicated-worker.html. CLOSED TREE
authorRazvan Maries <rmaries@mozilla.com>
Tue, 27 Oct 2020 18:39:11 +0200
changeset 554723 a0879ea722295655a7111b727f164b8c15681436
parent 554722 c5d8b4f34c06152748c6ac1e38ab59325a6887db
child 554724 6e297cea9592ca843887c294fec3bed8327e8b87
push id37898
push userabutkovits@mozilla.com
push dateWed, 28 Oct 2020 09:24:21 +0000
treeherdermozilla-central@83bf4fd3b1fb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1650118
milestone84.0a1
backs outab6218dd84f501adbdd38817c71ee6ffee87ee63
a99d1aae6e2e43500bdafce0a80ee57405fc020c
ed357b8bb07e625461d192a20d9451582fd50ec3
cd5155e732d9ecd961e97a4ecbe7a9557aab392b
63cc752924f2be431f86e7de0fc4970ce310e96b
7f0a281a399e7b02760f8b1c55a10d110f3f45cf
0fd77fef3c952b0571637ca700affbca4d8f4b50
f397e86fd61eb36e607a120af6f69df36ec0ed93
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
Backed out 8 changesets (bug 1650118) for wpt failures on inside-dedicated-worker.html. CLOSED TREE Backed out changeset ab6218dd84f5 (bug 1650118) Backed out changeset a99d1aae6e2e (bug 1650118) Backed out changeset ed357b8bb07e (bug 1650118) Backed out changeset cd5155e732d9 (bug 1650118) Backed out changeset 63cc752924f2 (bug 1650118) Backed out changeset 7f0a281a399e (bug 1650118) Backed out changeset 0fd77fef3c95 (bug 1650118) Backed out changeset f397e86fd61e (bug 1650118)
mobile/android/actors/WebBrowserChromeChild.jsm
mobile/android/app/geckoview-prefs.js
mobile/android/chrome/geckoview/geckoview.js
mobile/android/geckoview/api.txt
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ContentCrashTest.kt
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ContentDelegateMultipleSessionsTest.kt
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ContentDelegateTest.kt
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/util/Environment.java
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/util/RuntimeCreator.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md
mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java
mobile/android/modules/geckoview/GeckoViewSettings.jsm
python/mozbuild/mozbuild/mach_commands.py
taskcluster/taskgraph/transforms/tests.py
testing/mochitest/runjunit.py
testing/mozharness/scripts/android_emulator_unittest.py
testing/mozharness/scripts/android_hardware_unittest.py
testing/raptor/raptor/webextension/android.py
testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox_android.py
testing/xpcshell/remotexpcshelltests.py
toolkit/xre/nsAppRunner.cpp
widget/android/GeckoViewSupport.h
widget/android/nsWindow.cpp
--- a/mobile/android/actors/WebBrowserChromeChild.jsm
+++ b/mobile/android/actors/WebBrowserChromeChild.jsm
@@ -37,16 +37,22 @@ class WebBrowserChromeChild extends Geck
     aURI,
     aReferrerInfo,
     aHasPostData,
     aTriggeringPrincipal,
     aCsp
   ) {
     debug`shouldLoadURI ${aURI.displaySpec}`;
 
+    if (!GeckoViewSettings.useMultiprocess) {
+      // If we're in non-e10s mode there's no other process we can load this
+      // page in.
+      return true;
+    }
+
     if (!E10SUtils.shouldLoadURI(aDocShell, aURI, aHasPostData)) {
       E10SUtils.redirectLoad(
         aDocShell,
         aURI,
         aReferrerInfo,
         aTriggeringPrincipal,
         null,
         aCsp
--- a/mobile/android/app/geckoview-prefs.js
+++ b/mobile/android/app/geckoview-prefs.js
@@ -12,17 +12,16 @@
 // Please indent all prefs defined within #ifdef/#ifndef conditions. This
 // improves readability, particular for conditional blocks that exceed a single
 // screen.
 
 #include mobile.js
 
 pref("privacy.trackingprotection.pbmode.enabled", false);
 
-pref("browser.tabs.remote.autostart", true);
 pref("dom.ipc.keepProcessesAlive.web", 1);
 pref("dom.ipc.processCount", 1);
 pref("dom.ipc.processPrelaunch.enabled", false);
 
 // Disable the Telemetry Event Ping
 pref("toolkit.telemetry.eventping.enabled", false);
 // Don't create the hidden window during startup.
 pref("toolkit.lazyHiddenWindow", true);
--- a/mobile/android/chrome/geckoview/geckoview.js
+++ b/mobile/android/chrome/geckoview/geckoview.js
@@ -146,17 +146,17 @@ var ModuleManager = {
     return this.browser.browsingContext.currentWindowGlobal?.getActor(
       aActorName
     );
   },
 
   remoteTypeFor(aURI, currentType) {
     return E10SUtils.getRemoteTypeForURI(
       aURI,
-      /* multiProcess */ true,
+      GeckoViewSettings.useMultiprocess,
       /* useRemoteSubframes */ false,
       currentType,
       this.browser.currentURI
     );
   },
 
   // Ensures that session history has been flushed before changing remoteness
   async prepareToChangeRemoteness() {
@@ -505,25 +505,27 @@ function createBrowser() {
   browser.permanentKey = {};
 
   browser.setAttribute("nodefaultsrc", "true");
   browser.setAttribute("type", "content");
   browser.setAttribute("primary", "true");
   browser.setAttribute("flex", "1");
   browser.setAttribute("maychangeremoteness", "true");
 
-  const pointerEventsEnabled = Services.prefs.getBoolPref(
-    "dom.w3c_pointer_events.multiprocess.android.enabled",
-    false
-  );
-  if (pointerEventsEnabled) {
-    Services.prefs.setBoolPref("dom.w3c_pointer_events.enabled", true);
+  if (GeckoViewSettings.useMultiprocess) {
+    const pointerEventsEnabled = Services.prefs.getBoolPref(
+      "dom.w3c_pointer_events.multiprocess.android.enabled",
+      false
+    );
+    if (pointerEventsEnabled) {
+      Services.prefs.setBoolPref("dom.w3c_pointer_events.enabled", true);
+    }
+    browser.setAttribute("remote", "true");
+    browser.setAttribute("remoteType", E10SUtils.DEFAULT_REMOTE_TYPE);
   }
-  browser.setAttribute("remote", "true");
-  browser.setAttribute("remoteType", E10SUtils.DEFAULT_REMOTE_TYPE);
 
   return browser;
 }
 
 function InitLater(fn, object, name) {
   return DelayedInit.schedule(fn, object, name, 15000 /* 15s max wait */);
 }
 
--- a/mobile/android/geckoview/api.txt
+++ b/mobile/android/geckoview/api.txt
@@ -627,16 +627,17 @@ package org.mozilla.geckoview {
     method public boolean getLoginAutofillEnabled();
     method public boolean getPauseForDebuggerEnabled();
     method public int getPreferredColorScheme();
     method public boolean getRemoteDebuggingEnabled();
     method @Nullable public GeckoRuntime getRuntime();
     method @Nullable public Rect getScreenSizeOverride();
     method @Nullable public RuntimeTelemetry.Delegate getTelemetryDelegate();
     method public boolean getUseMaxScreenDepth();
+    method @Deprecated public boolean getUseMultiprocess();
     method public boolean getWebFontsEnabled();
     method public boolean getWebManifestEnabled();
     method @NonNull public GeckoRuntimeSettings setAboutConfigEnabled(boolean);
     method @NonNull public GeckoRuntimeSettings setAutomaticFontSizeAdjustment(boolean);
     method @NonNull public GeckoRuntimeSettings setConsoleOutputEnabled(boolean);
     method @NonNull public GeckoRuntimeSettings setDoubleTapZoomingEnabled(boolean);
     method @NonNull public GeckoRuntimeSettings setFontInflationEnabled(boolean);
     method @NonNull public GeckoRuntimeSettings setFontSizeFactor(float);
@@ -679,16 +680,17 @@ package org.mozilla.geckoview {
     method @NonNull public GeckoRuntimeSettings.Builder locales(@Nullable String[]);
     method @NonNull public GeckoRuntimeSettings.Builder loginAutofillEnabled(boolean);
     method @NonNull public GeckoRuntimeSettings.Builder pauseForDebugger(boolean);
     method @NonNull public GeckoRuntimeSettings.Builder preferredColorScheme(int);
     method @NonNull public GeckoRuntimeSettings.Builder remoteDebuggingEnabled(boolean);
     method @NonNull public GeckoRuntimeSettings.Builder screenSizeOverride(int, int);
     method @NonNull public GeckoRuntimeSettings.Builder telemetryDelegate(@NonNull RuntimeTelemetry.Delegate);
     method @NonNull public GeckoRuntimeSettings.Builder useMaxScreenDepth(boolean);
+    method @Deprecated @NonNull public GeckoRuntimeSettings.Builder useMultiprocess(boolean);
     method @NonNull public GeckoRuntimeSettings.Builder webFontsEnabled(boolean);
     method @NonNull public GeckoRuntimeSettings.Builder webManifest(boolean);
     method @NonNull protected GeckoRuntimeSettings newSettings(@Nullable GeckoRuntimeSettings);
   }
 
   public class GeckoSession {
     ctor public GeckoSession();
     ctor public GeckoSession(@Nullable GeckoSessionSettings);
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ContentCrashTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ContentCrashTest.kt
@@ -26,16 +26,17 @@ class ContentCrashTest : BaseSessionTest
     fun setup() {
         assertTrue(client.connect(env.defaultTimeoutMillis))
         client.setEvalNextCrashDump(/* expectFatal */ false)
     }
 
     @IgnoreCrash
     @Test
     fun crashContent() {
+        assumeTrue(sessionRule.env.isMultiprocess)
         // We need the crash reporter for this test
         assumeTrue(BuildConfig.MOZ_CRASHREPORTER)
 
         mainSession.loadUri(CONTENT_CRASH_URL)
         mainSession.waitUntilCalled(Callbacks.ContentDelegate::class, "onCrash")
 
         // This test is really slow so we allow double the usual timeout
         var evalResult = client.getEvalResult(env.defaultTimeoutMillis * 2)
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ContentDelegateMultipleSessionsTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ContentDelegateMultipleSessionsTest.kt
@@ -114,16 +114,19 @@ class ContentDelegateMultipleSessionsTes
 
     @Before
     fun setup() {
         resetContentProcesses()
     }
 
     @IgnoreCrash
     @Test fun crashContentMultipleSessions() {
+        // This test doesn't make sense without multiprocess
+        assumeThat(sessionRule.env.isMultiprocess, equalTo(true))
+
         val newSession = getSecondGeckoSession()
 
         // We can inadvertently catch the `onCrash` call for the cached session if we don't specify
         // individual sessions here. Therefore, assert 'onCrash' is called for the two sessions
         // individually...
         val mainSessionCrash = GeckoResult<Void>()
         val newSessionCrash = GeckoResult<Void>()
 
@@ -153,16 +156,18 @@ class ContentDelegateMultipleSessionsTes
 
         mainSession.loadUri(CONTENT_CRASH_URL)
 
         sessionRule.waitForResult(allCrashesFound)
     }
 
     @IgnoreCrash
     @Test fun killContentMultipleSessions() {
+        assumeThat(sessionRule.env.isMultiprocess, equalTo(true))
+
         val newSession = getSecondGeckoSession()
 
         val mainSessionKilled = GeckoResult<Void>()
         val newSessionKilled = GeckoResult<Void>()
 
         val allKillEventsReceived = GeckoResult.allOf(mainSessionKilled, newSessionKilled)
 
         sessionRule.delegateUntilTestEnd(object : Callbacks.ContentDelegate {
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ContentDelegateTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ContentDelegateTest.kt
@@ -106,16 +106,19 @@ class ContentDelegateTest : BaseSessionT
                 assertThat("Content length should be non-zero", response.headers.get("Content-Length")!!.toLong(), greaterThan(0L))
                 assertThat("Filename should match", response.headers.get("cONTent-diSPOsiTion"), equalTo("attachment; filename=\"download.txt\""))
             }
         })
     }
 
     @IgnoreCrash
     @Test fun crashContent() {
+        // This test doesn't make sense without multiprocess
+        assumeThat(sessionRule.env.isMultiprocess, equalTo(true))
+
         mainSession.loadUri(CONTENT_CRASH_URL)
         mainSession.waitUntilCalled(object : Callbacks.ContentDelegate {
             @AssertCalled(count = 1)
             override fun onCrash(session: GeckoSession) {
                 assertThat("Session should be closed after a crash",
                            session.isOpen, equalTo(false))
             }
         })
@@ -129,16 +132,19 @@ class ContentDelegateTest : BaseSessionT
                 assertThat("Page should load successfully", success, equalTo(true))
             }
         })
     }
 
     @IgnoreCrash
     @WithDisplay(width = 10, height = 10)
     @Test fun crashContent_tapAfterCrash() {
+        // This test doesn't make sense without multiprocess
+        assumeThat(sessionRule.env.isMultiprocess, equalTo(true))
+
         mainSession.delegateUntilTestEnd(object : Callbacks.ContentDelegate {
             override fun onCrash(session: GeckoSession) {
                 mainSession.open()
                 mainSession.loadTestPath(HELLO_HTML_PATH)
             }
         })
 
         mainSession.synthesizeTap(5, 5)
@@ -159,16 +165,18 @@ class ContentDelegateTest : BaseSessionT
             if (info.processName.matches(expr)) {
                 Process.killProcess(info.pid)
             }
         }
     }
 
     @IgnoreCrash
     @Test fun killContent() {
+        assumeThat(sessionRule.env.isMultiprocess, equalTo(true))
+
         killAllContentProcesses()
         mainSession.waitUntilCalled(object : Callbacks.ContentDelegate {
             @AssertCalled(count = 1)
             override fun onKill(session: GeckoSession) {
                 assertThat("Session should be closed after being killed",
                         session.isOpen, equalTo(false))
             }
         })
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt
@@ -1632,25 +1632,28 @@ class GeckoSessionTestRuleTest : BaseSes
         assertThat("Test delegate should still be registered", delegate, notNullValue())
         assertThat("Test delegate return value should be correct",
                 delegate?.onDelegate("", ""), equalTo(42))
         sessionRule.performTestEndCheck()
     }
 
     @IgnoreCrash
     @Test fun contentCrashIgnored() {
+        assumeThat(sessionRule.env.isMultiprocess, equalTo(true))
+
         mainSession.loadUri(CONTENT_CRASH_URL)
         mainSession.waitUntilCalled(object : Callbacks.ContentDelegate {
             @AssertCalled(count = 1)
             override fun onCrash(session: GeckoSession) = Unit
         })
     }
 
     @Test(expected = ChildCrashedException::class)
     fun contentCrashFails() {
+        assumeThat(sessionRule.env.isMultiprocess, equalTo(true))
         assumeThat(sessionRule.env.shouldShutdownOnCrash(), equalTo(false))
 
         sessionRule.session.loadUri(CONTENT_CRASH_URL)
         sessionRule.waitForPageStop()
     }
 
     @Test fun waitForResult() {
         val handler = Handler(Looper.getMainLooper())
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/util/Environment.java
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/util/Environment.java
@@ -33,16 +33,22 @@ public class Environment {
     public boolean isAutomation() {
         return !getEnvVar("MOZ_IN_AUTOMATION").isEmpty();
     }
 
     public boolean shouldShutdownOnCrash() {
         return !getEnvVar("MOZ_CRASHREPORTER_SHUTDOWN").isEmpty();
     }
 
+    public boolean isMultiprocess() {
+        return Boolean.valueOf(InstrumentationRegistry.getArguments()
+                .getString("use_multiprocess",
+                        "true"));
+    }
+
     public boolean isDebugging() {
         return Debug.isDebuggerConnected();
     }
 
     public boolean isEmulator() {
         return "generic".equals(Build.DEVICE) || Build.DEVICE.startsWith("generic_");
     }
 
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/util/RuntimeCreator.java
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/util/RuntimeCreator.java
@@ -154,16 +154,17 @@ public class RuntimeCreator {
 
         final SafeBrowsingProvider google = SafeBrowsingProvider
                 .from(ContentBlocking.GOOGLE_SAFE_BROWSING_PROVIDER)
                 .getHashUrl("http://mochi.test:8888/safebrowsing4-dummy/gethash")
                 .updateUrl("http://mochi.test:8888/safebrowsing4-dummy/update")
                 .build();
 
         final GeckoRuntimeSettings runtimeSettings = new GeckoRuntimeSettings.Builder()
+                .useMultiprocess(env.isMultiprocess())
                 .contentBlocking(new ContentBlocking.Settings.Builder()
                         .safeBrowsingProviders(googleLegacy, google)
                         .build())
                 .arguments(new String[]{"-purgecaches"})
                 .extras(InstrumentationRegistry.getArguments())
                 .remoteDebuggingEnabled(true)
                 .consoleOutput(true)
                 .crashHandler(TestCrashHandler.class)
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java
@@ -289,17 +289,20 @@ public final class GeckoRuntime implemen
 
         return null;
     }
 
     /* package */ boolean init(final @NonNull Context context, final @NonNull GeckoRuntimeSettings settings) {
         if (DEBUG) {
             Log.d(LOGTAG, "init");
         }
-        int flags = GeckoThread.FLAG_PRELOAD_CHILD;
+        int flags = 0;
+        if (settings.getUseMultiprocess()) {
+            flags |= GeckoThread.FLAG_PRELOAD_CHILD;
+        }
 
         if (settings.getPauseForDebuggerEnabled()) {
             flags |= GeckoThread.FLAG_DEBUGGING;
         }
 
         final Class<?> crashHandler = settings.getCrashHandler();
         if (crashHandler != null) {
             try {
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
@@ -41,16 +41,32 @@ public final class GeckoRuntimeSettings 
             extends RuntimeSettings.Builder<GeckoRuntimeSettings> {
         @Override
         protected @NonNull GeckoRuntimeSettings newSettings(
                 final @Nullable GeckoRuntimeSettings settings) {
             return new GeckoRuntimeSettings(settings);
         }
 
         /**
+         * Set whether multiprocess support should be enabled.
+         *
+         * @param use A flag determining whether multiprocess should be enabled.
+         *            Default is true.
+         * @return This Builder instance.
+         *
+         * @deprecated This method will be removed in GeckoView 82, at which point GeckoView will
+         *             only operate in multiprocess mode.
+         */
+        @Deprecated // Bug 1650118
+        public @NonNull Builder useMultiprocess(final boolean use) {
+            getSettings().mUseMultiprocess.set(use);
+            return this;
+        }
+
+        /**
          * Set the custom Gecko process arguments.
          *
          * @param args The Gecko process arguments.
          * @return This Builder instance.
          */
         public @NonNull Builder arguments(final @NonNull String[] args) {
             if (args == null) {
                 throw new IllegalArgumentException("Arguments must not  be null");
@@ -482,16 +498,18 @@ public final class GeckoRuntimeSettings 
     /* package */ final Pref<Boolean> mConsoleServiceToLogcat = new Pref<>(
             "consoleservice.logcat", true);
     /* package */ final Pref<Boolean> mDevToolsConsoleToLogcat = new Pref<>(
             "devtools.console.stdout.chrome", true);
     /* package */ final Pref<Boolean> mAboutConfig = new Pref<>(
             "general.aboutConfig.enable", false);
     /* package */ final Pref<Boolean> mForceUserScalable = new Pref<>(
             "browser.ui.zoom.force-user-scalable", false);
+    /* package */ final Pref<Boolean> mUseMultiprocess = new Pref<>(
+            "browser.tabs.remote.autostart", true);
     /* package */ final Pref<Boolean> mAutofillLogins = new Pref<Boolean>(
         "signon.autofillForms", true);
 
     /* package */ int mPreferredColorScheme = COLOR_SCHEME_SYSTEM;
 
     /* package */ boolean mDebugPause;
     /* package */ boolean mUseMaxScreenDepth;
     /* package */ float mDisplayDensityOverride = -1.0f;
@@ -555,16 +573,30 @@ public final class GeckoRuntimeSettings 
     }
 
     /* package */ void commit() {
         commitLocales();
         commitResetPrefs();
     }
 
     /**
+     * Whether multiprocess is enabled.
+     *
+     * @return true if multiprocess is enabled, false otherwise.
+     *
+     * @deprecated This method will be removed in GeckoView 82, at which point GeckoView will only
+     *             operate in multiprocess mode.
+     */
+    @Deprecated // Bug 1650118
+    public boolean getUseMultiprocess() {
+        return mUseMultiprocess.get();
+    }
+
+
+    /**
      * Get the custom Gecko process arguments.
      *
      * @return The Gecko process arguments.
      */
     public @NonNull String[] getArguments() {
         return mArgs;
     }
 
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
@@ -1026,17 +1026,17 @@ public class GeckoSession {
         }
 
         // Create a new Gecko window and assign an initial set of Java session objects to it.
         @WrapForJNI(dispatchTo = "proxy")
         public static native void open(Window instance, NativeQueue queue,
                                        Compositor compositor, EventDispatcher dispatcher,
                                        SessionAccessibility.NativeProvider sessionAccessibility,
                                        GeckoBundle initData, String id, String chromeUri,
-                                       int screenId, boolean privateMode);
+                                       int screenId, boolean privateMode, boolean isRemote);
 
         @Override // JNIObject
         public void disposeNative() {
             if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
                 nativeDisposeNative();
             } else {
                 GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY,
                         this, "nativeDisposeNative");
@@ -1296,40 +1296,41 @@ public class GeckoSession {
         if (isOpen()) {
             // We will leak the existing Window if we open another one.
             throw new IllegalStateException("Session is open");
         }
 
         final String chromeUri = mSettings.getChromeUri();
         final int screenId = mSettings.getScreenId();
         final boolean isPrivate = mSettings.getUsePrivateMode();
+        final boolean isRemote = runtime.getSettings().getUseMultiprocess();
 
         mWindow = new Window(runtime, this, mNativeQueue);
         mWebExtensionController.setRuntime(runtime);
 
         onWindowChanged(WINDOW_OPEN, /* inProgress */ true);
 
         if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
             Window.open(mWindow, mNativeQueue, mCompositor, mEventDispatcher,
                         mAccessibility != null ? mAccessibility.nativeProvider : null,
-                        createInitData(), mId, chromeUri, screenId, isPrivate);
+                        createInitData(), mId, chromeUri, screenId, isPrivate, isRemote);
         } else {
             GeckoThread.queueNativeCallUntil(
                 GeckoThread.State.PROFILE_READY,
                 Window.class, "open",
                 Window.class, mWindow,
                 NativeQueue.class, mNativeQueue,
                 Compositor.class, mCompositor,
                 EventDispatcher.class, mEventDispatcher,
                 SessionAccessibility.NativeProvider.class,
                 mAccessibility != null ? mAccessibility.nativeProvider : null,
                 GeckoBundle.class, createInitData(),
                 String.class, mId,
                 String.class, chromeUri,
-                screenId, isPrivate);
+                screenId, isPrivate, isRemote);
         }
 
         onWindowChanged(WINDOW_OPEN, /* inProgress */ false);
     }
 
     /**
      * Closes the session.
      *
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md
@@ -8,21 +8,16 @@ exclude: true
 
 {% capture javadoc_uri %}{{ site.url }}{{ site.baseurl}}/javadoc/mozilla-central/org/mozilla/geckoview{% endcapture %}
 {% capture bugzilla %}https://bugzilla.mozilla.org/show_bug.cgi?id={% endcapture %}
 
 # GeckoView API Changelog.
 
 ⚠️  breaking change and deprecation notices
 
-## v84
-- ⚠️  Removed deprecated [`GeckoRuntimeSettings.Builder.useMultiprocess`] and
-  [`GeckoRuntimeSettings.getUseMultiprocess`]. Single-process GeckoView is no
-  longer supported. ([bug 1650118]({{bugzilla}}1650118))
-
 ## v83
 - Added [`WebExtension.MetaData.temporary`][83.1] which exposes whether an extension
   has been installed temporarily, e.g. when using web-ext.
   ([bug 1624410]({{bugzilla}}1624410))
 - ⚠️  Removing unsupported `MediaSession.Delegate.onPictureInPicture` for now.
   Also, [`MediaSession.Delegate.onMetadata`][83.2] is no longer dispatched for
   plain media elements.
   ([bug 1658937]({{bugzilla}}1658937))
@@ -71,17 +66,17 @@ exclude: true
   resending POST requests.
   ([bug 1659073]({{bugzilla}}1659073))
 - Removed `Parcelable` support in `GeckoSession`. Use [`ProgressDelegate#onSessionStateChange`][68.29] and [`ProgressDelegate#restoreState`][82.5] instead.
   ([bug 1650108]({{bugzilla}}1650108))
 - ⚠️ Use AndroidX instead of the Android support library. For the public API this only changes
   the thread and nullable annotation types.
 - Added [`REPLACED_TRACKING_CONTENT`][82.6] to content blocking API to indicate when unsafe content is shimmed.
   ([bug 1663756]({{bugzilla}}1663756))
-
+  
 [82.1]: {{javadoc_uri}}/GeckoSession.ContentDelegate.html#onExternalResponse-org.mozilla.geckoview.GeckoSession-org.mozilla.geckoview.GeckoSession.WebResponseInfo-
 [82.2]: {{javadoc_uri}}/GeckoSession.ContentDelegate.html#onExternalResponse-org.mozilla.geckoview.GeckoSession-org.mozilla.geckoview.GeckoResult-
 [82.3]: {{javadoc_uri}}/Image.html
 [82.4]: {{javadoc_uri}}/GeckoSession.PromptDelegate.RepostConfirmPrompt.html
 [82.5]: {{javadoc_uri}}/GeckoSession.html#restoreState-org.mozilla.geckoview.GeckoSession.SessionState-
 [82.6]: {{javadoc_uri}}/ContentBlockingController.Event.html#REPLACED_TRACKING_CONTENT
 
 ## v81
@@ -836,9 +831,9 @@ to allow adding gecko profiler markers.
 [65.19]: {{javadoc_uri}}/GeckoSession.NavigationDelegate.LoadRequest.html#isRedirect
 [65.20]: {{javadoc_uri}}/GeckoSession.html#LOAD_FLAGS_BYPASS_CLASSIFIER
 [65.21]: {{javadoc_uri}}/GeckoSession.ContentDelegate.ContextElement.html
 [65.22]: {{javadoc_uri}}/GeckoSession.ContentDelegate.html#onContextMenu-org.mozilla.geckoview.GeckoSession-int-int-org.mozilla.geckoview.GeckoSession.ContentDelegate.ContextElement-
 [65.23]: {{javadoc_uri}}/GeckoSession.FinderResult.html
 [65.24]: {{javadoc_uri}}/CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String-
 [65.25]: {{javadoc_uri}}/GeckoResult.html
 
-[api-version]: 8a6a2cd431b4185d3bc665c6ce13a84684dd7b9e
+[api-version]: cd2ba68c049db26ce20ba332ef2ba46cbde4910a
--- a/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java
+++ b/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java
@@ -368,16 +368,17 @@ class WebExtensionManager implements Web
 
 public class GeckoViewActivity
         extends AppCompatActivity
         implements
             ToolbarLayout.TabListener,
             WebExtensionDelegate,
             SharedPreferences.OnSharedPreferenceChangeListener {
     private static final String LOGTAG = "GeckoViewActivity";
+    private static final String USE_MULTIPROCESS_EXTRA = "use_multiprocess";
     private static final String FULL_ACCESSIBILITY_TREE_EXTRA = "full_accessibility_tree";
     private static final String SEARCH_URI_BASE = "https://www.google.com/search?q=";
     private static final String ACTION_SHUTDOWN = "org.mozilla.geckoview_example.SHUTDOWN";
     private static final String CHANNEL_ID = "GeckoViewExample";
     private static final int REQUEST_FILE_PICKER = 1;
     private static final int REQUEST_PERMISSIONS = 2;
     private static final int REQUEST_WRITE_EXTERNAL_STORAGE = 3;
 
@@ -700,16 +701,18 @@ public class GeckoViewActivity
         mToolbarView.setId(R.id.toolbar_layout);
         mToolbarView.setTabListener(this);
 
         getSupportActionBar().setCustomView(mToolbarView,
                 new ActionBar.LayoutParams(ActionBar.LayoutParams.MATCH_PARENT,
                         ActionBar.LayoutParams.WRAP_CONTENT));
         getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
 
+        final boolean useMultiprocess =
+                getIntent().getBooleanExtra(USE_MULTIPROCESS_EXTRA, true);
         mFullAccessibilityTree = getIntent().getBooleanExtra(FULL_ACCESSIBILITY_TREE_EXTRA, false);
         mProgressView = findViewById(R.id.page_progress);
 
         if (sGeckoRuntime == null) {
             final GeckoRuntimeSettings.Builder runtimeSettingsBuilder =
                 new GeckoRuntimeSettings.Builder();
 
             if (BuildConfig.DEBUG) {
@@ -718,16 +721,17 @@ public class GeckoViewActivity
                 runtimeSettingsBuilder.arguments(new String[] { "-purgecaches" });
             }
 
             final Bundle extras = getIntent().getExtras();
             if (extras != null) {
                 runtimeSettingsBuilder.extras(extras);
             }
             runtimeSettingsBuilder
+                    .useMultiprocess(useMultiprocess)
                     .remoteDebuggingEnabled(mRemoteDebugging.value())
                     .consoleOutput(true)
                     .contentBlocking(new ContentBlocking.Settings.Builder()
                         .antiTracking(ContentBlocking.AntiTracking.DEFAULT |
                                       ContentBlocking.AntiTracking.STP)
                         .safeBrowsing(ContentBlocking.SafeBrowsing.DEFAULT)
                         .cookieBehavior(ContentBlocking.CookieBehavior.ACCEPT_NON_TRACKERS)
                         .enhancedTrackingProtectionLevel(ContentBlocking.EtpLevel.DEFAULT)
--- a/mobile/android/modules/geckoview/GeckoViewSettings.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewSettings.jsm
@@ -43,16 +43,20 @@ const USER_AGENT_MODE_VR = 2;
 // This needs to match GeckoSessionSettings.java
 const DISPLAY_MODE_BROWSER = 0;
 const DISPLAY_MODE_MINIMAL_UI = 1;
 const DISPLAY_MODE_STANDALONE = 2;
 const DISPLAY_MODE_FULLSCREEN = 3;
 
 // Handles GeckoSession settings.
 class GeckoViewSettings extends GeckoViewModule {
+  static get useMultiprocess() {
+    return Services.prefs.getBoolPref("browser.tabs.remote.autostart", true);
+  }
+
   onInit() {
     debug`onInit`;
     this._userAgentMode = USER_AGENT_MODE_MOBILE;
     this._userAgentOverride = null;
     this._sessionContextId = null;
 
     this.registerListener(["GeckoView:GetUserAgent"]);
   }
--- a/python/mozbuild/mozbuild/mach_commands.py
+++ b/python/mozbuild/mozbuild/mach_commands.py
@@ -1316,16 +1316,17 @@ class RunProgram(MachCommandBase):
         if enable_fission:
             env.append("MOZ_FORCE_ENABLE_FISSION=1")
 
         extras = {}
         for i, e in enumerate(env):
             extras["env{}".format(i)] = e
         if args:
             extras["args"] = " ".join(args)
+        extras["use_multiprocess"] = True  # Only GVE and TRA process this extra.
 
         if env or args:
             restart = True
 
         if restart:
             fail_if_running = False
             self.log(
                 logging.INFO,
--- a/taskcluster/taskgraph/transforms/tests.py
+++ b/taskcluster/taskgraph/transforms/tests.py
@@ -1184,23 +1184,19 @@ def get_mobile_project(task):
         for name in mobile_projects:
             if name in target:
                 return name
 
     return "fennec"
 
 
 @transforms.add
-def adjust_mobile_e10s(config, tasks):
+def disable_fennec_e10s(config, tasks):
     for task in tasks:
-        project = get_mobile_project(task)
-        if project == "geckoview":
-            # Geckoview is always-e10s
-            task["e10s"] = True
-        elif project == "fennec":
+        if get_mobile_project(task) == "fennec":
             # Fennec is non-e10s
             task["e10s"] = False
         yield task
 
 
 @transforms.add
 def disable_wpt_timeouts_on_autoland(config, tasks):
     """do not run web-platform-tests that are expected TIMEOUT on autoland"""
--- a/testing/mochitest/runjunit.py
+++ b/testing/mochitest/runjunit.py
@@ -158,16 +158,19 @@ class JUnitTestRunner(MochitestDesktop):
 
     def build_command_line(self, test_filters_file, test_filters):
         """
         Construct and return the 'am instrument' command line.
         """
         cmd = "am instrument -w -r"
         # profile location
         cmd = cmd + " -e args '-profile %s'" % self.remote_profile
+        # multi-process
+        e10s = "true" if self.options.e10s else "false"
+        cmd = cmd + " -e use_multiprocess %s" % e10s
         # chunks (shards)
         shards = self.options.totalChunks
         shard = self.options.thisChunk
         if shards is not None and shard is not None:
             shard -= 1  # shard index is 0 based
             cmd = cmd + " -e numShards %d -e shardIndex %d" % (shards, shard)
 
         # test filters: limit run to specific test(s)
@@ -446,16 +449,23 @@ class JunitArgumentParser(argparse.Argum
             "--remoteTestRoot",
             action="store",
             type=str,
             dest="remoteTestRoot",
             help="Remote directory to use as test root "
             "(eg. /data/local/tmp/test_root).",
         )
         self.add_argument(
+            "--disable-e10s",
+            action="store_false",
+            dest="e10s",
+            default=True,
+            help="Disable multiprocess mode in test app.",
+        )
+        self.add_argument(
             "--max-time",
             action="store",
             type=int,
             dest="max_time",
             default="2400",
             help="Max time in seconds to wait for tests (default 2400s).",
         )
         self.add_argument(
--- a/testing/mozharness/scripts/android_emulator_unittest.py
+++ b/testing/mozharness/scripts/android_emulator_unittest.py
@@ -89,16 +89,27 @@ class AndroidEmulatorTest(
                 {
                     "action": "store",
                     "dest": "log_tbpl_level",
                     "default": "info",
                     "help": "Set log level (debug|info|warning|error|critical|fatal)",
                 },
             ],
             [
+                [
+                    "--disable-e10s",
+                ],
+                {
+                    "action": "store_false",
+                    "dest": "e10s",
+                    "default": True,
+                    "help": "Run tests without multiple processes (e10s).",
+                },
+            ],
+            [
                 ["--enable-webrender"],
                 {
                     "action": "store_true",
                     "dest": "enable_webrender",
                     "default": False,
                     "help": "Run with WebRender enabled.",
                 },
             ],
@@ -159,16 +170,17 @@ class AndroidEmulatorTest(
         suite = c.get("test_suite")
         self.test_suite = suite
         self.this_chunk = c.get("this_chunk")
         self.total_chunks = c.get("total_chunks")
         self.xre_path = None
         self.device_serial = "emulator-5554"
         self.log_raw_level = c.get("log_raw_level")
         self.log_tbpl_level = c.get("log_tbpl_level")
+        self.e10s = c.get("e10s")
         self.enable_webrender = c.get("enable_webrender")
         if self.enable_webrender:
             # AndroidMixin uses this when launching the emulator. We only want
             # GLES3 if we're running WebRender
             self.use_gles3 = True
         self.extra_prefs = c.get("extra_prefs")
 
     def query_abs_dirs(self):
@@ -285,16 +297,21 @@ class AndroidEmulatorTest(
                     cmd.extend([option])
 
         if "mochitest" in self.test_suite:
             category = "mochitest"
         elif "reftest" in self.test_suite or "crashtest" in self.test_suite:
             category = "reftest"
         else:
             category = self.test_suite
+        if category not in SUITE_NO_E10S:
+            if category in SUITE_DEFAULT_E10S and not self.e10s:
+                cmd.extend(["--disable-e10s"])
+            elif category not in SUITE_DEFAULT_E10S and self.e10s:
+                cmd.extend(["--e10s"])
         if c.get("repeat"):
             if category in SUITE_REPEATABLE:
                 cmd.extend(["--repeat=%s" % c.get("repeat")])
             else:
                 self.log("--repeat not supported in {}".format(category), level=WARNING)
 
         cmd.extend(["--setpref={}".format(p) for p in self.extra_prefs])
 
--- a/testing/mozharness/scripts/android_hardware_unittest.py
+++ b/testing/mozharness/scripts/android_hardware_unittest.py
@@ -74,16 +74,27 @@ class AndroidHardwareTest(
             {
                 "action": "store",
                 "dest": "log_tbpl_level",
                 "default": "info",
                 "help": "Set log level (debug|info|warning|error|critical|fatal)",
             },
         ],
         [
+            [
+                "--disable-e10s",
+            ],
+            {
+                "action": "store_false",
+                "dest": "e10s",
+                "default": True,
+                "help": "Run tests without multiple processes (e10s).",
+            },
+        ],
+        [
             ["--enable-webrender"],
             {
                 "action": "store_true",
                 "dest": "enable_webrender",
                 "default": False,
                 "help": "Run with WebRender enabled.",
             },
         ],
@@ -141,16 +152,17 @@ class AndroidHardwareTest(
         self.test_manifest = c.get("test_manifest")
         suite = c.get("test_suite")
         self.test_suite = suite
         self.this_chunk = c.get("this_chunk")
         self.total_chunks = c.get("total_chunks")
         self.xre_path = None
         self.log_raw_level = c.get("log_raw_level")
         self.log_tbpl_level = c.get("log_tbpl_level")
+        self.e10s = c.get("e10s")
         self.enable_webrender = c.get("enable_webrender")
         self.extra_prefs = c.get("extra_prefs")
 
     def query_abs_dirs(self):
         if self.abs_dirs:
             return self.abs_dirs
         abs_dirs = super(AndroidHardwareTest, self).query_abs_dirs()
         dirs = {}
@@ -255,16 +267,21 @@ class AndroidHardwareTest(
                 cmd.extend(["--total-chunks", self.total_chunks])
 
         if "mochitest" in self.test_suite:
             category = "mochitest"
         elif "reftest" in self.test_suite or "crashtest" in self.test_suite:
             category = "reftest"
         else:
             category = self.test_suite
+        if category not in SUITE_NO_E10S:
+            if category in SUITE_DEFAULT_E10S and not self.e10s:
+                cmd.extend(["--disable-e10s"])
+            elif category not in SUITE_DEFAULT_E10S and self.e10s:
+                cmd.extend(["--e10s"])
         if c.get("repeat"):
             if category in SUITE_REPEATABLE:
                 cmd.extend(["--repeat=%s" % c.get("repeat")])
             else:
                 self.log("--repeat not supported in {}".format(category), level=WARNING)
 
         # Only enable WebRender if the flag is enabled. All downstream harnesses
         # are expected to force-disable WebRender if not explicitly enabled,
--- a/testing/raptor/raptor/webextension/android.py
+++ b/testing/raptor/raptor/webextension/android.py
@@ -80,16 +80,18 @@ class WebExtensionAndroid(PerftestAndroi
             return
         LOG.info("creating android app config.yml")
 
         yml_config_data = dict(
             args=[
                 "--profile",
                 self.remote_profile,
                 "--allow-downgrade",
+                "use_multiprocess",
+                self.config["e10s"],
             ],
             env=dict(
                 LOG_VERBOSE=1,
                 R_LOG_LEVEL=6,
                 MOZ_WEBRENDER=int(self.config["enable_webrender"]),
             ),
         )
 
--- a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox_android.py
+++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox_android.py
@@ -82,31 +82,34 @@ def env_options():
     # The server host is set to public localhost IP so that resources can be accessed
     # from Android emulator
     return {"server_host": moznetwork.get_ip(),
             "bind_address": False,
             "supports_debugger": True}
 
 
 class ProfileCreator(FirefoxProfileCreator):
-    def __init__(self, logger, prefs_root, config, test_type, extra_prefs,
+    def __init__(self, logger, prefs_root, config, test_type, extra_prefs, e10s,
                  enable_fission, browser_channel, certutil_binary, ca_certificate_path):
         super(ProfileCreator, self).__init__(logger, prefs_root, config, test_type, extra_prefs,
-                                             True, enable_fission, browser_channel, None,
+                                             e10s, enable_fission, browser_channel, None,
                                              certutil_binary, ca_certificate_path)
 
     def _set_required_prefs(self, profile):
         profile.set_preferences({
             "network.dns.localDomains": ",".join(self.config.domains_set),
             "dom.disable_open_during_load": False,
             "places.history.enabled": False,
             "dom.send_after_paint_to_content": True,
             "network.preload": True,
         })
 
+        if self.e10s:
+            profile.set_preferences({"browser.tabs.remote.autostart": True})
+
         if self.test_type == "reftest":
             self.logger.info("Setting android reftest preferences")
             profile.set_preferences({
                 "browser.viewport.desktopWidth": 800,
                 # Disable high DPI
                 "layout.css.devPixelsPerPx": "1.0",
                 # Ensure that the full browser element
                 # appears in the screenshot
@@ -134,17 +137,17 @@ class FirefoxAndroidBrowser(Browser):
         self.test_type = test_type
         self.package_name = package_name
         self.device_serial = device_serial
         self.debug_info = debug_info
         self.symbols_path = symbols_path
         self.stackwalk_binary = stackwalk_binary
         self.certutil_binary = certutil_binary
         self.ca_certificate_path = ca_certificate_path
-        self.e10s = True
+        self.e10s = e10s
         self.enable_webrender = enable_webrender
         self.stackfix_dir = stackfix_dir
         self.binary_args = binary_args
         self.timeout_multiplier = timeout_multiplier
         self.leak_check = leak_check
         self.asan = asan
         self.stylo_threads = stylo_threads
         self.chaos_mode_flags = chaos_mode_flags
@@ -154,16 +157,17 @@ class FirefoxAndroidBrowser(Browser):
         self.tests_root = tests_root
         self.specialpowers_path = specialpowers_path
 
         self.profile_creator = ProfileCreator(logger,
                                               prefs_root,
                                               config,
                                               test_type,
                                               extra_prefs,
+                                              e10s,
                                               False,
                                               browser_channel,
                                               certutil_binary,
                                               ca_certificate_path)
 
         self.marionette_port = None
         self.profile = None
         self.runner = None
--- a/testing/xpcshell/remotexpcshelltests.py
+++ b/testing/xpcshell/remotexpcshelltests.py
@@ -366,17 +366,16 @@ class XPCShellRemote(xpcshell.XPCShellTe
         self.env["MOZ_LINKER_CACHE"] = self.remoteBinDir
         self.env["GRE_HOME"] = self.remoteBinDir
         self.env["XPCSHELL_TEST_PROFILE_DIR"] = self.profileDir
         self.env["TMPDIR"] = self.remoteTmpDir
         self.env["HOME"] = self.profileDir
         self.env["XPCSHELL_TEST_TEMP_DIR"] = self.remoteTmpDir
         self.env["XPCSHELL_MINIDUMP_DIR"] = self.remoteMinidumpDir
         self.env["MOZ_ANDROID_DATA_DIR"] = self.remoteBinDir
-        self.env["MOZ_FORCE_DISABLE_E10S"] = "1"
 
         # Guard against intermittent failures to retrieve abi property;
         # without an abi, xpcshell cannot find greprefs.js and crashes.
         abilistprop = None
         abi = None
         retries = 0
         while not abi and retries < 3:
             abi = self.device.get_prop("ro.product.cpu.abi")
@@ -409,17 +408,16 @@ class XPCShellRemote(xpcshell.XPCShellTe
                 self.log.info("failed to get matching abi from apk.")
                 if len(names) > 0:
                     self.log.info(
                         "device cpu abi not found in apk. Using abi from apk."
                     )
                     abi = names[0].split("/")[1]
         self.log.info("Using abi %s." % abi)
         self.env["MOZ_ANDROID_CPU_ABI"] = abi
-        self.log.info("Using env %r" % (self.env,))
 
     def setupUtilities(self):
         self.initDir(self.remoteTmpDir)
         self.initDir(self.remoteBinDir)
         remotePrefDir = posixpath.join(self.remoteBinDir, "defaults", "pref")
         self.initDir(posixpath.join(remotePrefDir, "extra"))
         self.initDir(self.remoteComponentsDir)
 
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -551,23 +551,18 @@ bool BrowserTabsRemoteAutostart() {
     }
   } else {
     gBrowserTabsRemoteAutostart = true;
   }
 
   // Uber override pref for emergency blocking
   if (gBrowserTabsRemoteAutostart) {
     const char* forceDisable = PR_GetEnv("MOZ_FORCE_DISABLE_E10S");
-#if defined(MOZ_WIDGET_ANDROID)
-    // We need this for xpcshell on Android
-    if (forceDisable && *forceDisable) {
-#else
     // The environment variable must match the application version to apply.
     if (forceDisable && gAppData && !strcmp(forceDisable, gAppData->version)) {
-#endif
       gBrowserTabsRemoteAutostart = false;
       status = kE10sForceDisabled;
     }
   }
 
   gBrowserTabsRemoteStatus = status;
 
   return gBrowserTabsRemoteAutostart;
--- a/widget/android/GeckoViewSupport.h
+++ b/widget/android/GeckoViewSupport.h
@@ -57,17 +57,17 @@ class GeckoViewSupport final
   // Create and attach a window.
   static void Open(const jni::Class::LocalRef& aCls,
                    java::GeckoSession::Window::Param aWindow,
                    jni::Object::Param aQueue, jni::Object::Param aCompositor,
                    jni::Object::Param aDispatcher,
                    jni::Object::Param aSessionAccessibility,
                    jni::Object::Param aInitData, jni::String::Param aId,
                    jni::String::Param aChromeURI, int32_t aScreenId,
-                   bool aPrivateMode);
+                   bool aPrivateMode, bool aRemote);
 
   // Close and destroy the nsWindow.
   void Close();
 
   // Transfer this nsWindow to new GeckoSession objects.
   void Transfer(const java::GeckoSession::Window::LocalRef& inst,
                 jni::Object::Param aQueue, jni::Object::Param aCompositor,
                 jni::Object::Param aDispatcher,
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -1222,17 +1222,18 @@ GeckoViewSupport::~GeckoViewSupport() {
 }
 
 /* static */
 void GeckoViewSupport::Open(
     const jni::Class::LocalRef& aCls, GeckoSession::Window::Param aWindow,
     jni::Object::Param aQueue, jni::Object::Param aCompositor,
     jni::Object::Param aDispatcher, jni::Object::Param aSessionAccessibility,
     jni::Object::Param aInitData, jni::String::Param aId,
-    jni::String::Param aChromeURI, int32_t aScreenId, bool aPrivateMode) {
+    jni::String::Param aChromeURI, int32_t aScreenId, bool aPrivateMode,
+    bool aRemote) {
   MOZ_ASSERT(NS_IsMainThread());
 
   AUTO_PROFILER_LABEL("mozilla::widget::GeckoViewSupport::Open", OTHER);
 
   nsCOMPtr<nsIWindowWatcher> ww = do_GetService(NS_WINDOWWATCHER_CONTRACTID);
   MOZ_RELEASE_ASSERT(ww);
 
   nsAutoCString url;
@@ -1246,20 +1247,23 @@ void GeckoViewSupport::Open(
   }
 
   // Prepare an nsIAndroidView to pass as argument to the window.
   RefPtr<AndroidView> androidView = new AndroidView();
   androidView->mEventDispatcher->Attach(
       java::EventDispatcher::Ref::From(aDispatcher), nullptr);
   androidView->mInitData = java::GeckoBundle::Ref::From(aInitData);
 
-  nsAutoCString chromeFlags("chrome,dialog=0,remote,resizable,scrollbars");
+  nsAutoCString chromeFlags("chrome,dialog=0,resizable,scrollbars");
   if (aPrivateMode) {
     chromeFlags += ",private";
   }
+  if (aRemote) {
+    chromeFlags += ",remote";
+  }
   nsCOMPtr<mozIDOMWindowProxy> domWindow;
   ww->OpenWindow(nullptr, url, nsDependentCString(aId->ToCString().get()),
                  chromeFlags, androidView, getter_AddRefs(domWindow));
   MOZ_RELEASE_ASSERT(domWindow);
 
   nsCOMPtr<nsPIDOMWindowOuter> pdomWindow = nsPIDOMWindowOuter::From(domWindow);
   const RefPtr<nsWindow> window = nsWindow::From(pdomWindow);
   MOZ_ASSERT(window);