Bug 1500155 - Add methods for each setting in `GeckoSessionSettings`. r=snorp
authorEmily Toop <etoop@mozilla.com>
Tue, 08 Jan 2019 18:06:07 +0000
changeset 512932 18cb79bb1c78109448ad0817f8b6e435044000ab
parent 512919 e08a0bb35c033607bdd78aa32d00e5debb218c41
child 512933 f4bd2ef9b7295fbc04264e7c930d391b6595726c
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs1500155
milestone66.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 1500155 - Add methods for each setting in `GeckoSessionSettings`. r=snorp Part 1 - Add methods for each setting in `GeckoSessionSettings`. Migrate existing code to use these new methods instead of the exisiting get/set<DataType>(Key, Value) methods. Part 2 - Make old methods and fields for get/set<DataType> in `GeckoSessionSettings` private. Part 3 - Migrate existing code to use these new methods instead of the exisiting get/set<DataType>(Key, Value) methods. Part 4 - Add Builder to `GeckoSessionSettings` to handle setting of init only fields. * Make setters for init only fields protected. * Remove tests that ensure that init only fields throw an error when set on the fly as this is no longer possible. * Update tests to use builder when init-ing settings. * Update API doc to reflect new public API. Part 5 - Update `CHANGELOG.md`. Part 6 - Update `geckoview_example` to use new methods. Part 7 - Fetch `CHROME_URI` key when calling `getChromeUri` rather than incorrect `USER_AGENT_OVERRIDE` Differential Revision: https://phabricator.services.mozilla.com/D15651
mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
mobile/android/base/java/org/mozilla/gecko/VirtualPresentation.java
mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
mobile/android/base/java/org/mozilla/gecko/webapps/WebAppActivity.java
mobile/android/geckoview/api.txt
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/NavigationDelegateTest.kt
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/SessionLifecycleTest.kt
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/crash/RemoteGeckoService.kt
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.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
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
@@ -1102,19 +1102,20 @@ public abstract class GeckoApp extends G
         setContentView(getLayout());
 
         // Set up Gecko layout.
         mRootLayout = (RelativeLayout) findViewById(R.id.root_layout);
         mGeckoLayout = (RelativeLayout) findViewById(R.id.gecko_layout);
         mMainLayout = (RelativeLayout) findViewById(R.id.main_layout);
         mLayerView = (GeckoView) findViewById(R.id.layer_view);
 
-        final GeckoSession session = new GeckoSession();
-        session.getSettings().setString(GeckoSessionSettings.CHROME_URI,
-                                        "chrome://browser/content/browser.xul");
+        final GeckoSession session = new GeckoSession(
+                new GeckoSessionSettings.Builder()
+                        .chromeUri("chrome://browser/content/browser.xul")
+                        .build());
         session.setContentDelegate(this);
 
         // If the view already has a session, we need to ensure it is closed.
         if (mLayerView.getSession() != null) {
             mLayerView.getSession().close();
         }
         mLayerView.setSession(session, GeckoApplication.getRuntime());
         mLayerView.setOverScrollMode(View.OVER_SCROLL_NEVER);
--- a/mobile/android/base/java/org/mozilla/gecko/VirtualPresentation.java
+++ b/mobile/android/base/java/org/mozilla/gecko/VirtualPresentation.java
@@ -40,20 +40,20 @@ class VirtualPresentation extends CastPr
         super.onCreate(savedInstanceState);
 
         /*
          * NOTICE: The context get from getContext() is different to the context
          * of the application. Presentaion has its own context to get correct
          * resources.
          */
 
-        final GeckoSession session = new GeckoSession();
-        session.getSettings().setString(GeckoSessionSettings.CHROME_URI,
-                PRESENTATION_VIEW_URI + "#" + deviceId);
-        session.getSettings().setInt(GeckoSessionSettings.SCREEN_ID, screenId);
+        final GeckoSession session = new GeckoSession(new GeckoSessionSettings.Builder()
+                .chromeUri(PRESENTATION_VIEW_URI + "#" + deviceId)
+                .screenId(screenId)
+                .build());
 
         // Create new GeckoView
         view = new GeckoView(getContext());
         view.setSession(session, GeckoApplication.ensureRuntime(getContext()));
         view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
                 LayoutParams.MATCH_PARENT));
 
         // Create new layout to put the GeckoView
--- a/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
+++ b/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
@@ -118,18 +118,19 @@ public class CustomTabsActivity extends 
 
         actionBarPresenter = new ActionBarPresenter(actionBar, getActionBarTextColor());
         actionBarPresenter.displayUrlOnly(intent.getDataString());
         actionBarPresenter.setBackgroundColor(IntentUtil.getToolbarColor(intent), getWindow());
         actionBarPresenter.setTextLongClickListener(new UrlCopyListener());
 
         mGeckoView = (GeckoView) findViewById(R.id.gecko_view);
 
-        final GeckoSessionSettings settings = new GeckoSessionSettings();
-        settings.setBoolean(GeckoSessionSettings.USE_MULTIPROCESS, false);
+        final GeckoSessionSettings settings = new GeckoSessionSettings.Builder()
+                .useMultiprocess(false)
+                .build();
         mGeckoSession = new GeckoSession(settings);
         mGeckoSession.setNavigationDelegate(this);
         mGeckoSession.setProgressDelegate(this);
         mGeckoSession.setContentDelegate(this);
 
         mGeckoView.setSession(mGeckoSession, GeckoApplication.ensureRuntime(this));
 
         mPromptService = new PromptService(this, mGeckoView.getEventDispatcher());
--- a/mobile/android/base/java/org/mozilla/gecko/webapps/WebAppActivity.java
+++ b/mobile/android/base/java/org/mozilla/gecko/webapps/WebAppActivity.java
@@ -93,18 +93,19 @@ public class WebAppActivity extends AppC
         } else {
             Telemetry.sendUIEvent(TelemetryContract.Event.PWA, TelemetryContract.Method.HOMESCREEN);
         }
 
         super.onCreate(savedInstanceState);
         setContentView(R.layout.webapp_activity);
         mGeckoView = (GeckoView) findViewById(R.id.pwa_gecko_view);
 
-        final GeckoSessionSettings settings = new GeckoSessionSettings();
-        settings.setBoolean(GeckoSessionSettings.USE_MULTIPROCESS, false);
+        final GeckoSessionSettings settings = new GeckoSessionSettings.Builder()
+                .useMultiprocess(false)
+                .build();
         mGeckoSession = new GeckoSession(settings);
         mGeckoView.setSession(mGeckoSession, GeckoApplication.ensureRuntime(this));
 
         mGeckoSession.setNavigationDelegate(this);
         mGeckoSession.setContentDelegate(this);
         mGeckoSession.setProgressDelegate(new GeckoSession.ProgressDelegate() {
             @Override
             public void onPageStart(GeckoSession session, String url) {
@@ -314,17 +315,17 @@ public class WebAppActivity extends AppC
                 mode = GeckoSessionSettings.DISPLAY_MODE_MINIMAL_UI;
                 break;
             case "browser":
             default:
                 mode = GeckoSessionSettings.DISPLAY_MODE_BROWSER;
                 break;
         }
 
-        mGeckoSession.getSettings().setInt(GeckoSessionSettings.DISPLAY_MODE, mode);
+        mGeckoSession.getSettings().setDisplayMode(mode);
     }
 
     @Override // GeckoSession.NavigationDelegate
     public void onLocationChange(GeckoSession session, String url) {
     }
 
     @Override // GeckoSession.NavigationDelegate
     public void onCanGoBack(GeckoSession session, boolean canGoBack) {
--- a/mobile/android/geckoview/api.txt
+++ b/mobile/android/geckoview/api.txt
@@ -639,47 +639,67 @@ package org.mozilla.geckoview {
     field @android.support.annotation.Nullable public final java.lang.String contentType;
     field @android.support.annotation.Nullable public final java.lang.String filename;
     field @android.support.annotation.NonNull public final java.lang.String uri;
   }
 
   @android.support.annotation.AnyThread public final class GeckoSessionSettings implements android.os.Parcelable {
     ctor public GeckoSessionSettings();
     ctor public GeckoSessionSettings(@android.support.annotation.NonNull org.mozilla.geckoview.GeckoSessionSettings);
-    method public boolean getBoolean(@android.support.annotation.NonNull org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.Boolean>);
-    method public int getInt(@android.support.annotation.NonNull org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.Integer>);
-    method public java.lang.String getString(@android.support.annotation.NonNull org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.String>);
+    method public boolean getAllowJavascript();
+    method @android.support.annotation.Nullable public java.lang.String getChromeUri();
+    method public int getDisplayMode();
+    method public boolean getFullAccessibilityTree();
+    method public int getScreenId();
+    method public boolean getSuspendMediaWhenInactive();
+    method public boolean getUseMultiprocess();
+    method public boolean getUsePrivateMode();
+    method public boolean getUseTrackingProtection();
+    method public int getUserAgentMode();
+    method @android.support.annotation.Nullable public java.lang.String getUserAgentOverride();
+    method public int getViewportMode();
     method public void readFromParcel(@android.support.annotation.NonNull android.os.Parcel);
-    method public void setBoolean(@android.support.annotation.NonNull org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.Boolean>, boolean);
-    method public void setInt(@android.support.annotation.NonNull org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.Integer>, int);
-    method public void setString(@android.support.annotation.NonNull org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.String>, @android.support.annotation.Nullable java.lang.String);
-    field public static final org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.Boolean> ALLOW_JAVASCRIPT;
-    field public static final org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.String> CHROME_URI;
+    method public void setAllowJavascript(boolean);
+    method public void setDisplayMode(int);
+    method public void setFullAccessibilityTree(boolean);
+    method public void setSuspendMediaWhenInactive(boolean);
+    method public void setUseTrackingProtection(boolean);
+    method public void setUserAgentMode(int);
+    method public void setUserAgentOverride(@android.support.annotation.Nullable java.lang.String);
+    method public void setViewportMode(int);
     field public static final android.os.Parcelable.Creator<org.mozilla.geckoview.GeckoSessionSettings> CREATOR;
-    field public static final org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.Integer> DISPLAY_MODE;
     field public static final int DISPLAY_MODE_BROWSER = 0;
     field public static final int DISPLAY_MODE_FULLSCREEN = 3;
     field public static final int DISPLAY_MODE_MINIMAL_UI = 1;
     field public static final int DISPLAY_MODE_STANDALONE = 2;
-    field public static final org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.Boolean> FULL_ACCESSIBILITY_TREE;
-    field public static final org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.Integer> SCREEN_ID;
-    field public static final org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.Boolean> SUSPEND_MEDIA_WHEN_INACTIVE;
-    field public static final org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.Integer> USER_AGENT_MODE;
     field public static final int USER_AGENT_MODE_DESKTOP = 1;
     field public static final int USER_AGENT_MODE_MOBILE = 0;
     field public static final int USER_AGENT_MODE_VR = 2;
-    field public static final org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.String> USER_AGENT_OVERRIDE;
-    field public static final org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.Boolean> USE_MULTIPROCESS;
-    field public static final org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.Boolean> USE_PRIVATE_MODE;
-    field public static final org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.Boolean> USE_TRACKING_PROTECTION;
-    field public static final org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.Integer> VIEWPORT_MODE;
     field public static final int VIEWPORT_MODE_DESKTOP = 1;
     field public static final int VIEWPORT_MODE_MOBILE = 0;
   }
 
+  @android.support.annotation.AnyThread public static final class GeckoSessionSettings.Builder {
+    ctor public Builder();
+    ctor public Builder(org.mozilla.geckoview.GeckoSessionSettings);
+    method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoSessionSettings.Builder allowJavascript(boolean);
+    method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoSessionSettings build();
+    method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoSessionSettings.Builder chromeUri(java.lang.String);
+    method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoSessionSettings.Builder displayMode(int);
+    method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoSessionSettings.Builder fullAccessibilityTree(boolean);
+    method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoSessionSettings.Builder screenId(int);
+    method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoSessionSettings.Builder suspendMediaWhenInactive(boolean);
+    method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoSessionSettings.Builder useMultiprocess(boolean);
+    method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoSessionSettings.Builder usePrivateMode(boolean);
+    method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoSessionSettings.Builder useTrackingProtection(boolean);
+    method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoSessionSettings.Builder userAgentMode(int);
+    method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoSessionSettings.Builder userAgentOverride(@android.support.annotation.NonNull java.lang.String);
+    method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoSessionSettings.Builder viewportMode(int);
+  }
+
   public static class GeckoSessionSettings.Key<T> {
   }
 
   @android.support.annotation.UiThread public class GeckoView extends android.widget.FrameLayout {
     ctor public GeckoView(android.content.Context);
     ctor public GeckoView(android.content.Context, android.util.AttributeSet);
     method public void coverUntilFirstPaint(int);
     method @android.support.annotation.NonNull public org.mozilla.geckoview.DynamicToolbarAnimator getDynamicToolbarAnimator();
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt
@@ -3,17 +3,16 @@
  * 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/. */
 
 package org.mozilla.geckoview.test
 
 import android.os.Parcel
 import android.support.test.InstrumentationRegistry
 import org.mozilla.geckoview.GeckoSession
-import org.mozilla.geckoview.GeckoSessionSettings
 import org.mozilla.geckoview.test.rule.GeckoSessionTestRule
 
 import org.hamcrest.Matcher
 import org.hamcrest.Matchers
 import org.junit.Assume.assumeThat
 import org.junit.Rule
 import org.junit.rules.ErrorCollector
 
@@ -70,17 +69,17 @@ open class BaseSessionTest(noErrorCollec
 
     fun <T> forEachCall(vararg values: T): T = sessionRule.forEachCall(*values)
 
     fun getTestBytes(path: String) =
             InstrumentationRegistry.getTargetContext().resources.assets
                     .open(path.removePrefix("/assets/")).readBytes()
 
     val GeckoSession.isRemote
-        get() = this.settings.getBoolean(GeckoSessionSettings.USE_MULTIPROCESS)
+        get() = this.settings.getUseMultiprocess()
 
     fun createTestUrl(path: String) =
             GeckoSessionTestRule.APK_URI_PREFIX + path.removePrefix("/")
 
     fun GeckoSession.loadTestPath(path: String) =
             this.loadUri(createTestUrl(path))
 
     inline fun GeckoSession.toParcel(lambda: (Parcel) -> Unit) {
--- 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
@@ -43,29 +43,26 @@ class GeckoSessionTestRuleTest : BaseSes
     }
 
     @Setting.List(Setting(key = Setting.Key.USE_PRIVATE_MODE, value = "true"),
                   Setting(key = Setting.Key.DISPLAY_MODE, value = "DISPLAY_MODE_MINIMAL_UI"),
                   Setting(key = Setting.Key.ALLOW_JAVASCRIPT, value = "false"))
     @Setting(key = Setting.Key.USE_TRACKING_PROTECTION, value = "true")
     @Test fun settingsApplied() {
         assertThat("USE_PRIVATE_MODE should be set",
-                   sessionRule.session.settings.getBoolean(
-                           GeckoSessionSettings.USE_PRIVATE_MODE),
+                   sessionRule.session.settings.usePrivateMode,
                    equalTo(true))
         assertThat("DISPLAY_MODE should be set",
-                   sessionRule.session.settings.getInt(GeckoSessionSettings.DISPLAY_MODE),
+                   sessionRule.session.settings.displayMode,
                    equalTo(GeckoSessionSettings.DISPLAY_MODE_MINIMAL_UI))
         assertThat("USE_TRACKING_PROTECTION should be set",
-                   sessionRule.session.settings.getBoolean(
-                           GeckoSessionSettings.USE_TRACKING_PROTECTION),
+                   sessionRule.session.settings.useTrackingProtection,
                    equalTo(true))
         assertThat("ALLOW_JAVASCRIPT should be set",
-                sessionRule.session.settings.getBoolean(
-                        GeckoSessionSettings.ALLOW_JAVASCRIPT),
+                sessionRule.session.settings.allowJavascript,
                 equalTo(false))
     }
 
     @Test(expected = UiThreadUtils.TimeoutException::class)
     @TimeoutMillis(1000)
     fun noPendingCallbacks() {
         // Make sure we don't have unexpected pending callbacks at the start of a test.
         sessionRule.waitUntilCalled(object : Callbacks.All {})
@@ -891,18 +888,19 @@ class GeckoSessionTestRuleTest : BaseSes
         val newSession = sessionRule.createOpenSession()
         assertThat("Can create session", newSession, notNullValue())
         assertThat("New session is open", newSession.isOpen, equalTo(true))
         assertThat("New session has same settings",
                    newSession.settings, equalTo(sessionRule.session.settings))
     }
 
     @Test fun createOpenSession_withSettings() {
-        val settings = GeckoSessionSettings(sessionRule.session.settings)
-        settings.setBoolean(GeckoSessionSettings.USE_PRIVATE_MODE, true)
+        val settings = GeckoSessionSettings.Builder(sessionRule.session.settings)
+                .usePrivateMode(true)
+                .build()
 
         val newSession = sessionRule.createOpenSession(settings)
         assertThat("New session has same settings", newSession.settings, equalTo(settings))
     }
 
     @Test fun createOpenSession_canInterleaveOtherCalls() {
         sessionRule.session.loadTestPath(HELLO_HTML_PATH)
 
@@ -927,18 +925,17 @@ class GeckoSessionTestRuleTest : BaseSes
         val newSession = sessionRule.createClosedSession()
         assertThat("Can create session", newSession, notNullValue())
         assertThat("New session is open", newSession.isOpen, equalTo(false))
         assertThat("New session has same settings",
                    newSession.settings, equalTo(sessionRule.session.settings))
     }
 
     @Test fun createClosedSession_withSettings() {
-        val settings = GeckoSessionSettings(sessionRule.session.settings)
-        settings.setBoolean(GeckoSessionSettings.USE_PRIVATE_MODE, true)
+        val settings = GeckoSessionSettings.Builder(sessionRule.session.settings).usePrivateMode(true).build()
 
         val newSession = sessionRule.createClosedSession(settings)
         assertThat("New session has same settings", newSession.settings, equalTo(settings))
     }
 
     @Test(expected = UiThreadUtils.TimeoutException::class)
     @TimeoutMillis(1000)
     @ClosedSessionAtStart
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/NavigationDelegateTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/NavigationDelegateTest.kt
@@ -2,33 +2,32 @@
  * Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 package org.mozilla.geckoview.test
 
 import org.mozilla.geckoview.AllowOrDeny
 import org.mozilla.geckoview.GeckoResult
 import org.mozilla.geckoview.GeckoSession
-import org.mozilla.geckoview.GeckoSession.NavigationDelegate.LoadRequest;
-import org.mozilla.geckoview.GeckoSession.TrackingProtectionDelegate;
+import org.mozilla.geckoview.GeckoSession.NavigationDelegate.LoadRequest
+import org.mozilla.geckoview.GeckoSession.TrackingProtectionDelegate
 import org.mozilla.geckoview.GeckoSessionSettings
 import org.mozilla.geckoview.WebRequestError
 
 import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled
 import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.NullDelegate
 import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.ReuseSession
 import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.Setting
 import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDevToolsAPI
 import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDisplay
 import org.mozilla.geckoview.test.util.Callbacks
 
 import android.support.test.filters.MediumTest
 import android.support.test.runner.AndroidJUnit4
 import org.hamcrest.Matchers.*
-import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
 
 @RunWith(AndroidJUnit4::class)
 @MediumTest
 @ReuseSession(false)
 class NavigationDelegateTest : BaseSessionTest() {
 
@@ -61,17 +60,17 @@ class NavigationDelegateTest : BaseSessi
                     }
 
                     @AssertCalled(count = 1, order = [4])
                     override fun onPageStop(session: GeckoSession, success: Boolean) {
                         assertThat("Load should fail", success, equalTo(false))
                     }
                 })
 
-        sessionRule.session.loadUri(testUri);
+        sessionRule.session.loadUri(testUri)
         sessionRule.waitForPageStop()
 
         if (errorPageUrl != null) {
             sessionRule.waitUntilCalled(object : Callbacks.ContentDelegate, Callbacks.NavigationDelegate {
                 @AssertCalled(count = 1, order = [1])
                 override fun onLocationChange(session: GeckoSession, url: String?) {
                     assertThat("URL should match", url, equalTo(testUri))
                 }
@@ -120,17 +119,17 @@ class NavigationDelegateTest : BaseSessi
 
         sessionRule.session.loadUri(testUri)
         sessionRule.waitUntilCalled(Callbacks.NavigationDelegate::class, "onLoadError")
 
         if (errorPageUrl != null) {
             sessionRule.waitUntilCalled(object: Callbacks.ContentDelegate {
                 @AssertCalled(count = 1)
                 override fun onTitleChange(session: GeckoSession, title: String?) {
-                    assertThat("Title should not be empty", title, not(isEmptyOrNullString()));
+                    assertThat("Title should not be empty", title, not(isEmptyOrNullString()))
                 }
             })
         }
     }
 
     fun testLoadEarlyError(testUri: String, expectedCategory: Int,
                            expectedError: Int) {
         testLoadEarlyErrorWithErrorPage(testUri, expectedCategory, expectedError, createTestUrl(HELLO_HTML_PATH))
@@ -164,40 +163,39 @@ class NavigationDelegateTest : BaseSessi
     @Test fun loadUntrusted() {
         val uri = if (sessionRule.env.isAutomation) {
             "https://expired.example.com/"
         } else {
             "https://expired.badssl.com/"
         }
         testLoadExpectError(uri,
                 WebRequestError.ERROR_CATEGORY_SECURITY,
-                WebRequestError.ERROR_SECURITY_BAD_CERT);
+                WebRequestError.ERROR_SECURITY_BAD_CERT)
     }
 
     @Setting(key = Setting.Key.USE_TRACKING_PROTECTION, value = "true")
     @Test fun trackingProtection() {
-        val category = TrackingProtectionDelegate.CATEGORY_TEST;
+        val category = TrackingProtectionDelegate.CATEGORY_TEST
         sessionRule.runtime.settings.trackingProtectionCategories = category
         sessionRule.session.loadTestPath(TRACKERS_PATH)
 
         sessionRule.waitUntilCalled(
                 object : Callbacks.TrackingProtectionDelegate {
             @AssertCalled(count = 3)
             override fun onTrackerBlocked(session: GeckoSession, uri: String?,
                                           categories: Int) {
                 assertThat("Category should be set",
                            categories,
                            equalTo(category))
                 assertThat("URI should not be null", uri, notNullValue())
                 assertThat("URI should match", uri, endsWith("tracker.js"))
             }
         })
 
-        sessionRule.session.settings.setBoolean(
-            GeckoSessionSettings.USE_TRACKING_PROTECTION, false)
+        sessionRule.session.settings.useTrackingProtection = false
 
         sessionRule.session.reload()
         sessionRule.session.waitForPageStop()
 
         sessionRule.forCallbacksDuringWait(
                 object : Callbacks.TrackingProtectionDelegate {
             @AssertCalled(false)
             override fun onTrackerBlocked(session: GeckoSession, uri: String?,
@@ -366,60 +364,57 @@ class NavigationDelegateTest : BaseSessi
         val userAgentJs = "window.navigator.userAgent"
         val mobileSubStr = "Mobile"
         val desktopSubStr = "X11"
 
         assertThat("User agent should be set to mobile",
                    sessionRule.session.evaluateJS(userAgentJs) as String,
                    containsString(mobileSubStr))
 
-        var userAgent = sessionRule.waitForResult(sessionRule.session.getUserAgent());
+        var userAgent = sessionRule.waitForResult(sessionRule.session.userAgent)
         assertThat("User agent should be reported as mobile",
-                    userAgent, containsString(mobileSubStr));
+                    userAgent, containsString(mobileSubStr))
 
-        sessionRule.session.settings.setInt(
-            GeckoSessionSettings.USER_AGENT_MODE, GeckoSessionSettings.USER_AGENT_MODE_DESKTOP)
+        sessionRule.session.settings.userAgentMode = GeckoSessionSettings.USER_AGENT_MODE_DESKTOP
 
         sessionRule.session.reload()
         sessionRule.session.waitForPageStop()
 
         assertThat("User agent should be set to desktop",
                    sessionRule.session.evaluateJS(userAgentJs) as String,
                    containsString(desktopSubStr))
 
-        userAgent = sessionRule.waitForResult(sessionRule.session.getUserAgent());
+        userAgent = sessionRule.waitForResult(sessionRule.session.userAgent)
         assertThat("User agent should be reported as desktop",
-                    userAgent, containsString(desktopSubStr));
+                    userAgent, containsString(desktopSubStr))
 
-        sessionRule.session.settings.setInt(
-            GeckoSessionSettings.USER_AGENT_MODE, GeckoSessionSettings.USER_AGENT_MODE_MOBILE)
+        sessionRule.session.settings.userAgentMode = GeckoSessionSettings.USER_AGENT_MODE_MOBILE
 
         sessionRule.session.reload()
         sessionRule.session.waitForPageStop()
 
         assertThat("User agent should be set to mobile",
                    sessionRule.session.evaluateJS(userAgentJs) as String,
                    containsString(mobileSubStr))
 
-        userAgent = sessionRule.waitForResult(sessionRule.session.getUserAgent());
+        userAgent = sessionRule.waitForResult(sessionRule.session.userAgent)
         assertThat("User agent should be reported as mobile",
-                    userAgent, containsString(mobileSubStr));
+                    userAgent, containsString(mobileSubStr))
 
         val vrSubStr = "Mobile VR"
-        sessionRule.session.settings.setInt(
-                GeckoSessionSettings.USER_AGENT_MODE, GeckoSessionSettings.USER_AGENT_MODE_VR)
+        sessionRule.session.settings.userAgentMode = GeckoSessionSettings.USER_AGENT_MODE_VR
 
         sessionRule.session.reload()
         sessionRule.session.waitForPageStop()
 
         assertThat("User agent should be set to VR",
                 sessionRule.session.evaluateJS(userAgentJs) as String,
                 containsString(vrSubStr))
 
-        userAgent = sessionRule.waitForResult(sessionRule.session.getUserAgent())
+        userAgent = sessionRule.waitForResult(sessionRule.session.userAgent)
         assertThat("User agent should be reported as VR",
                 userAgent, containsString(vrSubStr))
 
     }
 
     @WithDevToolsAPI
     @Test fun uaOverride() {
         sessionRule.session.loadUri("https://example.com")
@@ -429,62 +424,61 @@ class NavigationDelegateTest : BaseSessi
         val mobileSubStr = "Mobile"
         val vrSubStr = "Mobile VR"
         val overrideUserAgent = "This is the override user agent"
 
         var userAgent = sessionRule.session.evaluateJS(userAgentJs) as String
         assertThat("User agent should be reported as mobile",
                 userAgent, containsString(mobileSubStr))
 
-        sessionRule.session.settings.setString(GeckoSessionSettings.USER_AGENT_OVERRIDE, overrideUserAgent)
+        sessionRule.session.settings.userAgentOverride = overrideUserAgent
 
         sessionRule.session.reload()
         sessionRule.session.waitForPageStop()
 
         userAgent = sessionRule.session.evaluateJS(userAgentJs) as String
 
         assertThat("User agent should be reported as override",
                 userAgent, equalTo(overrideUserAgent))
 
-        sessionRule.session.settings.setInt(
-                GeckoSessionSettings.USER_AGENT_MODE, GeckoSessionSettings.USER_AGENT_MODE_VR)
+        sessionRule.session.settings.userAgentMode = GeckoSessionSettings.USER_AGENT_MODE_VR
 
         sessionRule.session.reload()
         sessionRule.session.waitForPageStop()
 
         assertThat("User agent should still be reported as override even when USER_AGENT_MODE is set",
                 userAgent, equalTo(overrideUserAgent))
 
-        sessionRule.session.settings.setString(GeckoSessionSettings.USER_AGENT_OVERRIDE, null)
+        sessionRule.session.settings.userAgentOverride = null
 
         sessionRule.session.reload()
         sessionRule.session.waitForPageStop()
 
         userAgent = sessionRule.session.evaluateJS(userAgentJs) as String
         assertThat("User agent should now be reported as VR",
                 userAgent, containsString(vrSubStr))
 
         sessionRule.delegateDuringNextWait(object : Callbacks.NavigationDelegate {
             override fun onLoadRequest(session: GeckoSession, request: LoadRequest): GeckoResult<AllowOrDeny>? {
-                sessionRule.session.settings.setString(GeckoSessionSettings.USER_AGENT_OVERRIDE, overrideUserAgent)
+                sessionRule.session.settings.userAgentOverride = overrideUserAgent
                 return null
             }
         })
 
         sessionRule.session.reload()
         sessionRule.session.waitForPageStop()
 
         userAgent = sessionRule.session.evaluateJS(userAgentJs) as String
 
         assertThat("User agent should be reported as override after being set in onLoadRequest",
                 userAgent, equalTo(overrideUserAgent))
 
         sessionRule.delegateDuringNextWait(object : Callbacks.NavigationDelegate {
             override fun onLoadRequest(session: GeckoSession, request: LoadRequest): GeckoResult<AllowOrDeny>? {
-                sessionRule.session.settings.setString(GeckoSessionSettings.USER_AGENT_OVERRIDE, null)
+                sessionRule.session.settings.userAgentOverride = null
                 return null
             }
         })
 
         sessionRule.session.reload()
         sessionRule.session.waitForPageStop()
 
         userAgent = sessionRule.session.evaluateJS(userAgentJs) as String
@@ -503,28 +497,26 @@ class NavigationDelegateTest : BaseSessi
         val pixelRatio = sessionRule.session.evaluateJS("window.devicePixelRatio") as Double
         val mobileInnerWidth = physicalWidth / pixelRatio
         val innerWidthJs = "window.innerWidth"
 
         var innerWidth = sessionRule.session.evaluateJS(innerWidthJs) as Double
         assertThat("innerWidth should be equal to $mobileInnerWidth",
                 innerWidth, closeTo(mobileInnerWidth, 0.1))
 
-        sessionRule.session.settings.setInt(
-                GeckoSessionSettings.VIEWPORT_MODE, GeckoSessionSettings.VIEWPORT_MODE_DESKTOP)
+        sessionRule.session.settings.viewportMode = GeckoSessionSettings.VIEWPORT_MODE_DESKTOP
 
         sessionRule.session.reload()
         sessionRule.session.waitForPageStop()
 
         innerWidth = sessionRule.session.evaluateJS(innerWidthJs) as Double
         assertThat("innerWidth should be equal to $desktopInnerWidth", innerWidth,
                 closeTo(desktopInnerWidth, 0.1))
 
-        sessionRule.session.settings.setInt(
-                GeckoSessionSettings.VIEWPORT_MODE, GeckoSessionSettings.VIEWPORT_MODE_MOBILE)
+        sessionRule.session.settings.viewportMode = GeckoSessionSettings.VIEWPORT_MODE_MOBILE
 
         sessionRule.session.reload()
         sessionRule.session.waitForPageStop()
 
         innerWidth = sessionRule.session.evaluateJS(innerWidthJs) as Double
         assertThat("innerWidth should be equal to $mobileInnerWidth again",
                 innerWidth, closeTo(mobileInnerWidth, 0.1))
     }
@@ -589,18 +581,18 @@ class NavigationDelegateTest : BaseSessi
             override fun onNewSession(session: GeckoSession, uri: String): GeckoResult<GeckoSession>? {
                 return null
             }
         })
     }
 
     @Test fun load_dataUri() {
         val dataUrl = "data:,Hello%2C%20World!"
-        sessionRule.session.loadUri(dataUrl);
-        sessionRule.waitForPageStop();
+        sessionRule.session.loadUri(dataUrl)
+        sessionRule.waitForPageStop()
 
         sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate, Callbacks.ProgressDelegate {
             @AssertCalled(count = 1)
             override fun onLocationChange(session: GeckoSession, url: String?) {
                 assertThat("URL should match the provided data URL", url, equalTo(dataUrl))
             }
 
             @AssertCalled(count = 1)
@@ -642,22 +634,22 @@ class NavigationDelegateTest : BaseSessi
         assertThat("Should not get callback for second load",
                    onLocationCount, equalTo(1))
     }
 
     @Test fun loadString() {
         val dataString = "<html><head><title>TheTitle</title></head><body>TheBody</body></html>"
         val mimeType = "text/html"
         sessionRule.session.loadString(dataString, mimeType)
-        sessionRule.waitForPageStop();
+        sessionRule.waitForPageStop()
 
         sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate, Callbacks.ProgressDelegate, Callbacks.ContentDelegate {
             @AssertCalled
             override fun onTitleChange(session: GeckoSession, title: String?) {
-                assertThat("Title should match", title, equalTo("TheTitle"));
+                assertThat("Title should match", title, equalTo("TheTitle"))
             }
 
             @AssertCalled(count = 1)
             override fun onLocationChange(session: GeckoSession, url: String?) {
                 assertThat("URL should be a data URL", url,
                            equalTo(GeckoSession.createDataUri(dataString, mimeType)))
             }
 
@@ -665,17 +657,17 @@ class NavigationDelegateTest : BaseSessi
             override fun onPageStop(session: GeckoSession, success: Boolean) {
                 assertThat("Page should load successfully", success, equalTo(true))
             }
         })
     }
 
     @Test fun loadString_noMimeType() {
         sessionRule.session.loadString("Hello, World!", null)
-        sessionRule.waitForPageStop();
+        sessionRule.waitForPageStop()
 
         sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate, Callbacks.ProgressDelegate {
             @AssertCalled(count = 1)
             override fun onLocationChange(session: GeckoSession, url: String?) {
                 assertThat("URL should be a data URL", url, startsWith("data:"))
             }
 
             @AssertCalled(count = 1)
@@ -684,18 +676,18 @@ class NavigationDelegateTest : BaseSessi
             }
         })
     }
 
     @Test fun loadData_html() {
         val bytes = getTestBytes(HELLO_HTML_PATH)
         assertThat("test html should have data", bytes.size, greaterThan(0))
 
-        sessionRule.session.loadData(bytes, "text/html");
-        sessionRule.waitForPageStop();
+        sessionRule.session.loadData(bytes, "text/html")
+        sessionRule.waitForPageStop()
 
         sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate, Callbacks.ProgressDelegate, Callbacks.ContentDelegate {
             @AssertCalled(count = 1)
             override fun onTitleChange(session: GeckoSession, title: String?) {
                 assertThat("Title should match", title, equalTo("Hello, world!"))
             }
 
             @AssertCalled(count = 1)
@@ -709,18 +701,18 @@ class NavigationDelegateTest : BaseSessi
             }
         })
     }
 
     fun loadDataHelper(assetPath: String, mimeType: String? = null) {
         val bytes = getTestBytes(assetPath)
         assertThat("test data should have bytes", bytes.size, greaterThan(0))
 
-        sessionRule.session.loadData(bytes, mimeType);
-        sessionRule.waitForPageStop();
+        sessionRule.session.loadData(bytes, mimeType)
+        sessionRule.waitForPageStop()
 
         sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate, Callbacks.ProgressDelegate {
             @AssertCalled(count = 1)
             override fun onLocationChange(session: GeckoSession, url: String?) {
                 assertThat("URL should match", url, equalTo(GeckoSession.createDataUri(bytes, mimeType)))
             }
 
             @AssertCalled(count = 1)
@@ -1025,23 +1017,23 @@ class NavigationDelegateTest : BaseSessi
     @Setting(key = Setting.Key.USE_MULTIPROCESS, value = "false")
     @WithDevToolsAPI
     @Test fun onNewSession_openRemoteFromNonRemote() {
         // Disable popup blocker.
         sessionRule.setPrefsUntilTestEnd(mapOf("dom.disable_open_during_load" to false))
 
         // Ensure a non-remote page can open a remote page, as needed by some tests.
         assertThat("Opening session should be non-remote",
-                   mainSession.settings.getBoolean(GeckoSessionSettings.USE_MULTIPROCESS),
+                   mainSession.settings.useMultiprocess,
                    equalTo(false))
 
         val newSession = delegateNewSession(
-                GeckoSessionSettings(mainSession.settings).apply {
-                    setBoolean(GeckoSessionSettings.USE_MULTIPROCESS, true)
-                })
+                GeckoSessionSettings.Builder(mainSession.settings)
+                .useMultiprocess(true)
+                .build())
         mainSession.evaluateJS("window.open('http://example.com')")
         newSession.waitForPageStop()
 
         assertThat("window.opener should be set",
                    newSession.evaluateJS("window.opener"), notNullValue())
     }
 
     @WithDevToolsAPI
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/SessionLifecycleTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/SessionLifecycleTest.kt
@@ -72,38 +72,16 @@ class SessionLifecycleTest : BaseSession
     }
 
     @Test(expected = IllegalStateException::class)
     fun open_throwOnAlreadyOpen() {
         // Throw exception if retrying to open again; otherwise we would leak the old open window.
         sessionRule.session.open()
     }
 
-    @Test(expected = IllegalStateException::class)
-    fun setChromeURI_throwOnOpenSession() {
-        sessionRule.session.settings.setString(GeckoSessionSettings.CHROME_URI, "chrome://invalid/path/to.xul")
-    }
-
-    @Test(expected = IllegalStateException::class)
-    fun setScreenID_throwOnOpenSession() {
-        sessionRule.session.settings.setInt(GeckoSessionSettings.SCREEN_ID, 42)
-    }
-
-    @Test(expected = IllegalStateException::class)
-    fun setUsePrivateMode_throwOnOpenSession() {
-        sessionRule.session.settings.setBoolean(GeckoSessionSettings.USE_PRIVATE_MODE, true)
-    }
-
-    @Test(expected = IllegalStateException::class)
-    fun setUseMultiprocess_throwOnOpenSession() {
-        sessionRule.session.settings.setBoolean(
-                GeckoSessionSettings.USE_MULTIPROCESS,
-                !sessionRule.session.settings.getBoolean(GeckoSessionSettings.USE_MULTIPROCESS))
-    }
-
     @Test fun readFromParcel() {
         val session = sessionRule.createOpenSession()
 
         session.toParcel { parcel ->
             val newSession = sessionRule.createClosedSession()
             newSession.readFromParcel(parcel)
 
             assertThat("New session has same settings",
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/crash/RemoteGeckoService.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/crash/RemoteGeckoService.kt
@@ -26,18 +26,19 @@ class RemoteGeckoService : Service() {
             when (msg.what) {
                 CMD_CRASH_PARENT_NATIVE -> {
                     val settings = GeckoSessionSettings()
                     val session = GeckoSession(settings)
                     session.open(runtime!!)
                     session.loadUri("about:crashparent")
                 }
                 CMD_CRASH_CONTENT_NATIVE -> {
-                    val settings = GeckoSessionSettings()
-                    settings.setBoolean(GeckoSessionSettings.USE_MULTIPROCESS, true)
+                    val settings = GeckoSessionSettings.Builder()
+                            .useMultiprocess(true)
+                            .build()
                     val session = GeckoSession(settings)
                     session.open(runtime!!)
                     session.loadUri("about:crashcontent")
                 }
                 else -> {
                     throw RuntimeException("Unhandled command")
                 }
             }
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java
@@ -195,46 +195,68 @@ public class GeckoSessionTestRule implem
             FULL_ACCESSIBILITY_TREE;
 
             private final GeckoSessionSettings.Key<?> mKey;
             private final Class<?> mType;
 
             Key() {
                 final Field field;
                 try {
-                    field = GeckoSessionSettings.class.getField(name());
+                    field = GeckoSessionSettings.class.getDeclaredField(name());
+                    field.setAccessible(true);
                     mKey = (GeckoSessionSettings.Key<?>) field.get(null);
                 } catch (final NoSuchFieldException | IllegalAccessException e) {
                     throw new RuntimeException(e);
                 }
 
                 final ParameterizedType genericType = (ParameterizedType) field.getGenericType();
                 mType = (Class<?>) genericType.getActualTypeArguments()[0];
             }
 
             @SuppressWarnings("unchecked")
             public void set(final GeckoSessionSettings settings, final String value) {
-                if (boolean.class.equals(mType) || Boolean.class.equals(mType)) {
-                    settings.setBoolean((GeckoSessionSettings.Key<Boolean>) mKey,
-                            Boolean.valueOf(value));
-                } else if (int.class.equals(mType) || Integer.class.equals(mType)) {
-                    try {
-                        settings.setInt((GeckoSessionSettings.Key<Integer>) mKey,
-                                (Integer) GeckoSessionSettings.class.getField(value)
-                                        .get(null));
-                    } catch (final NoSuchFieldException | IllegalAccessException |
-                            ClassCastException e) {
-                        settings.setInt((GeckoSessionSettings.Key<Integer>) mKey,
-                                        Integer.valueOf(value));
+                try {
+                    if (boolean.class.equals(mType) || Boolean.class.equals(mType)) {
+                        Method method = GeckoSessionSettings.class
+                                .getDeclaredMethod("setBoolean",
+                                        GeckoSessionSettings.Key.class,
+                                        boolean.class);
+                        method.setAccessible(true);
+                        method.invoke(settings, mKey, Boolean.valueOf(value));
+                    } else if (int.class.equals(mType) || Integer.class.equals(mType)) {
+                        Method method = GeckoSessionSettings.class
+                                .getDeclaredMethod("setInt",
+                                        GeckoSessionSettings.Key.class,
+                                        int.class);
+                        method.setAccessible(true);
+                        try {
+                            method.invoke(settings, mKey,
+                                    (Integer)GeckoSessionSettings.class.getField(value)
+                                            .get(null));
+                        }
+                        catch (final NoSuchFieldException | IllegalAccessException |
+                                ClassCastException e) {
+                            method.invoke(settings, mKey,
+                                    Integer.valueOf(value));
+                        }
+                    } else if (String.class.equals(mType)) {
+                        Method method = GeckoSessionSettings.class
+                                .getDeclaredMethod("setString",
+                                        GeckoSessionSettings.Key.class,
+                                        String.class);
+                        method.setAccessible(true);
+                        method.invoke(settings, mKey, value);
+                    } else {
+                        throw new IllegalArgumentException("Unsupported type: " +
+                                mType.getSimpleName());
                     }
-                } else if (String.class.equals(mType)) {
-                    settings.setString((GeckoSessionSettings.Key<String>) mKey, value);
-                } else {
-                    throw new IllegalArgumentException("Unsupported type: " +
-                            mType.getSimpleName());
+                } catch (NoSuchMethodException
+                        | IllegalAccessException
+                        | InvocationTargetException e) {
+                    throw new RuntimeException(e);
                 }
             }
         }
 
         @Target({ElementType.METHOD, ElementType.TYPE})
         @Retention(RetentionPolicy.RUNTIME)
         @interface List {
             Setting[] value();
@@ -832,18 +854,19 @@ public class GeckoSessionTestRule implem
     protected boolean mClosedSession;
     protected boolean mWithDevTools;
     protected Map<GeckoSession, Tab> mRDPTabs;
     protected Tab mRDPChromeProcess;
     protected boolean mReuseSession;
     protected boolean mIgnoreCrash;
 
     public GeckoSessionTestRule() {
-        mDefaultSettings = new GeckoSessionSettings();
-        mDefaultSettings.setBoolean(GeckoSessionSettings.USE_MULTIPROCESS, env.isMultiprocess());
+        mDefaultSettings = new GeckoSessionSettings.Builder()
+                .useMultiprocess(env.isMultiprocess())
+                .build();
     }
 
     /**
      * Set an ErrorCollector for assertion errors, or null to not use one.
      *
      * @param ec ErrorCollector or null.
      */
     public void setErrorCollector(final @Nullable ErrorCollector ec) {
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
@@ -7,23 +7,21 @@
 package org.mozilla.geckoview;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
 import java.net.URLConnection;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.List;
 import java.util.UUID;
 
 import org.mozilla.gecko.annotation.WrapForJNI;
 import org.mozilla.gecko.EventDispatcher;
 import org.mozilla.gecko.GeckoAppShell;
-import org.mozilla.gecko.GeckoEditableChild;
 import org.mozilla.gecko.GeckoThread;
 import org.mozilla.gecko.IGeckoEditableParent;
 import org.mozilla.gecko.mozglue.JNIObject;
 import org.mozilla.gecko.NativeQueue;
 import org.mozilla.gecko.util.BundleEventListener;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.GeckoBundle;
 import org.mozilla.gecko.util.IntentUtils;
@@ -1254,19 +1252,19 @@ public class GeckoSession implements Par
     public void open(final @NonNull GeckoRuntime runtime) {
         ThreadUtils.assertOnUiThread();
 
         if (isOpen()) {
             // We will leak the existing Window if we open another one.
             throw new IllegalStateException("Session is open");
         }
 
-        final String chromeUri = mSettings.getString(GeckoSessionSettings.CHROME_URI);
-        final int screenId = mSettings.getInt(GeckoSessionSettings.SCREEN_ID);
-        final boolean isPrivate = mSettings.getBoolean(GeckoSessionSettings.USE_PRIVATE_MODE);
+        final String chromeUri = mSettings.getChromeUri();
+        final int screenId = mSettings.getScreenId();
+        final boolean isPrivate = mSettings.getUsePrivateMode();
 
         mWindow = new Window(runtime, this, mNativeQueue);
 
         onWindowChanged(WINDOW_OPEN, /* inProgress */ true);
 
         if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
             Window.open(mWindow, mNativeQueue, mCompositor, mEventDispatcher,
                         mAccessibility != null ? mAccessibility.nativeProvider : null,
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java
@@ -3,28 +3,206 @@
  * 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/. */
 
 package org.mozilla.geckoview;
 
 import org.mozilla.gecko.util.GeckoBundle;
 
+import android.app.Service;
+import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.support.annotation.AnyThread;
+import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.util.Log;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
 import java.util.Collection;
 
 @AnyThread
 public final class GeckoSessionSettings implements Parcelable {
+
+    /**
+     * Settings builder used to construct the settings object.
+     */
+    @AnyThread
+    public static final class Builder {
+        private final GeckoSessionSettings mSettings;
+
+        public Builder() {
+            mSettings = new GeckoSessionSettings();
+        }
+
+        public Builder(final GeckoSessionSettings settings) {
+            mSettings = new GeckoSessionSettings(settings);
+        }
+
+        /**
+         * Finalize and return the settings.
+         *
+         * @return The constructed settings.
+         */
+        public @NonNull GeckoSessionSettings build() {
+            return new GeckoSessionSettings(mSettings);
+        }
+
+        /**
+         * Set the chrome URI.
+         *
+         * @param uri The URI to set the Chrome URI to.
+         * @return This Builder instance.
+
+         */
+        public @NonNull  Builder chromeUri(final String uri) {
+            mSettings.setChromeUri(uri);
+            return this;
+        }
+
+        /**
+         * Set the screen id.
+         *
+         * @param id The screen id.
+         * @return This Builder instance.
+         */
+        public @NonNull Builder screenId(final int id) {
+            mSettings.setScreenId(id);
+            return this;
+        }
+
+        /**
+         * Set the privacy mode for this instance.
+         *
+         * @param flag A flag determining whether Private Mode should be enabled.
+         *             Default is false.
+         * @return This Builder instance.
+         */
+        public @NonNull Builder usePrivateMode(final boolean flag) {
+            mSettings.setUsePrivateMode(flag);
+            return this;
+        }
+
+        /**
+         * Set whether multi-process support should be enabled.
+         *
+         * @param flag A flag determining whether multi-process should be enabled.
+         *             Default is false.
+         * @return This Builder instance.
+         */
+        public @NonNull Builder useMultiprocess(final boolean flag) {
+            mSettings.setUseMultiprocess(flag);
+            return this;
+        }
+
+        /**
+         * Set whether tracking protection should be enabled.
+         *
+         * @param flag A flag determining whether tracking protection should be enabled.
+         *             Default is false.
+         * @return This Builder instance.
+         */
+        public @NonNull Builder useTrackingProtection(final boolean flag) {
+            mSettings.setUseTrackingProtection(flag);
+            return this;
+        }
+
+        /**
+         * Set the user agent mode.
+         *
+         * @param mode The mode to set the user agent to.
+         *             Use one or more of the
+         *             {@link GeckoSessionSettings#USER_AGENT_MODE_MOBILE GeckoSessionSettings.USER_AGENT_MODE_*} flags.
+         * @return This Builder instance.
+         */
+        public @NonNull Builder userAgentMode(final int mode) {
+            mSettings.setUserAgentMode(mode);
+            return this;
+        }
+
+        /**
+         * Override the user agent.
+         *
+         * @param agent The user agent to use.
+         * @return This Builder instance.
+
+         */
+        public @NonNull Builder userAgentOverride(final @NonNull String agent) {
+            mSettings.setUserAgentOverride(agent);
+            return this;
+        }
+
+        /**
+         * Specify which display-mode to use.
+         *
+         * @param mode The mode to set the display to.
+         *             Use one or more of the
+         *             {@link GeckoSessionSettings#DISPLAY_MODE_BROWSER GeckoSessionSettings.DISPLAY_MODE_*} flags.
+         * @return This Builder instance.
+         */
+        public @NonNull Builder displayMode(final int mode) {
+            mSettings.setDisplayMode(mode);
+            return this;
+        }
+
+        /**
+         * Set whether to suspend the playing of media when the session is inactive.
+         *
+         * @param flag A flag determining whether media should be suspended.
+         *             Default is false.
+         * @return This Builder instance.
+         */
+        public @NonNull Builder suspendMediaWhenInactive(final boolean flag) {
+            mSettings.setSuspendMediaWhenInactive(flag);
+            return this;
+        }
+
+        /**
+         * Set whether JavaScript support should be enabled.
+         *
+         * @param flag A flag determining whether JavaScript should be enabled.
+         *             Default is true.
+         * @return This Builder instance.
+         */
+        public @NonNull Builder allowJavascript(final boolean flag) {
+            mSettings.setAllowJavascript(flag);
+            return this;
+        }
+
+        /**
+         * Set whether the entire accessible tree should be exposed with no caching.
+         *
+         * @param flag A flag determining if the entire accessible tree should be exposed.
+         *             Default is false.
+         * @return This Builder instance.
+         */
+        public @NonNull Builder fullAccessibilityTree(final boolean flag) {
+            mSettings.setFullAccessibilityTree(flag);
+            return this;
+        }
+
+
+        /**
+         * Specify which viewport mode to use.
+         *
+         * @param mode The mode to set the viewport to.
+         *             Use one or more of the
+         *             {@link GeckoSessionSettings#VIEWPORT_MODE_MOBILE GeckoSessionSettings.VIEWPORT_MODE_*} flags.
+         * @return This Builder instance.
+         */
+        public @NonNull Builder viewportMode(final int mode) {
+            mSettings.setViewportMode(mode);
+            return this;
+        }
+    }
+
     private static final String LOGTAG = "GeckoSessionSettings";
     private static final boolean DEBUG = false;
 
     // This needs to match nsIDocShell.idl
     public static final int DISPLAY_MODE_BROWSER = 0;
     public static final int DISPLAY_MODE_MINIMAL_UI = 1;
     public static final int DISPLAY_MODE_STANDALONE = 2;
     public static final int DISPLAY_MODE_FULLSCREEN = 3;
@@ -54,88 +232,88 @@ public final class GeckoSessionSettings 
             this.values = values;
         }
     }
 
     /**
      * Key to set the chrome window URI, or null to use default URI.
      * Read-only once session is open.
      */
-    public static final Key<String> CHROME_URI =
+    private static final Key<String> CHROME_URI =
         new Key<String>("chromeUri", /* initOnly */ true, /* values */ null);
     /**
      * Key to set the window screen ID, or 0 to use default ID.
      * Read-only once session is open.
      */
-    public static final Key<Integer> SCREEN_ID =
+    private static final Key<Integer> SCREEN_ID =
         new Key<Integer>("screenId", /* initOnly */ true, /* values */ null);
 
     /**
      * Key to enable and disable tracking protection.
      */
-    public static final Key<Boolean> USE_TRACKING_PROTECTION =
+    private static final Key<Boolean> USE_TRACKING_PROTECTION =
         new Key<Boolean>("useTrackingProtection");
     /**
      * Key to enable and disable private mode browsing.
      * Read-only once session is open.
      */
-    public static final Key<Boolean> USE_PRIVATE_MODE =
+    private static final Key<Boolean> USE_PRIVATE_MODE =
         new Key<Boolean>("usePrivateMode", /* initOnly */ true, /* values */ null);
 
     /**
      * Key to enable and disable multiprocess browsing (e10s).
      * Read-only once session is open.
      */
-    public static final Key<Boolean> USE_MULTIPROCESS =
+    private static final Key<Boolean> USE_MULTIPROCESS =
         new Key<Boolean>("useMultiprocess", /* initOnly */ true, /* values */ null);
 
     /**
      * Key to specify which user agent mode we should use.
      */
-    public static final Key<Integer> USER_AGENT_MODE =
+    private static final Key<Integer> USER_AGENT_MODE =
         new Key<Integer>("userAgentMode", /* initOnly */ false,
                          Arrays.asList(USER_AGENT_MODE_MOBILE, USER_AGENT_MODE_DESKTOP, USER_AGENT_MODE_VR));
 
     /**
      * Key to specify the user agent override string.
      * Set value to null to use the user agent specified by USER_AGENT_MODE.
      */
-    public static final Key<String> USER_AGENT_OVERRIDE =
+    private static final Key<String> USER_AGENT_OVERRIDE =
         new Key<String>("userAgentOverride", /* initOnly */ false, /* values */ null);
 
     /**
      * Key to specify which viewport mode we should use.
      */
-    public static final Key<Integer> VIEWPORT_MODE =
+    private static final Key<Integer> VIEWPORT_MODE =
         new Key<Integer>("viewportMode", /* initOnly */ false,
                          Arrays.asList(VIEWPORT_MODE_MOBILE, VIEWPORT_MODE_DESKTOP));
 
     /**
      * Key to specify which display-mode we should use.
      */
-    public static final Key<Integer> DISPLAY_MODE =
+    private static final Key<Integer> DISPLAY_MODE =
         new Key<Integer>("displayMode", /* initOnly */ false,
                          Arrays.asList(DISPLAY_MODE_BROWSER, DISPLAY_MODE_MINIMAL_UI,
                                        DISPLAY_MODE_STANDALONE, DISPLAY_MODE_FULLSCREEN));
 
     /**
      * Key to specify if media should be suspended when the session is inactive.
      */
-    public static final Key<Boolean> SUSPEND_MEDIA_WHEN_INACTIVE =
+    private static final Key<Boolean> SUSPEND_MEDIA_WHEN_INACTIVE =
         new Key<Boolean>("suspendMediaWhenInactive", /* initOnly */ false, /* values */ null);
 
     /**
      * Key to specify if JavaScript should be allowed on this session.
      */
-    public static final Key<Boolean> ALLOW_JAVASCRIPT =
+    private static final Key<Boolean> ALLOW_JAVASCRIPT =
             new Key<Boolean>("allowJavascript", /* initOnly */ false, /* values */ null);
     /**
      * Key to specify if entire accessible tree should be exposed with no caching.
      */
-    public static final Key<Boolean> FULL_ACCESSIBILITY_TREE =
+    private static final Key<Boolean> FULL_ACCESSIBILITY_TREE =
             new Key<Boolean>("fullAccessibilityTree", /* initOnly */ false, /* values */ null);
 
     private final GeckoSession mSession;
     private final GeckoBundle mBundle;
 
     public GeckoSessionSettings() {
         this(null, null);
     }
@@ -163,62 +341,300 @@ public final class GeckoSessionSettings 
         mBundle.putBoolean(ALLOW_JAVASCRIPT.name, true);
         mBundle.putBoolean(FULL_ACCESSIBILITY_TREE.name, false);
         mBundle.putInt(USER_AGENT_MODE.name, USER_AGENT_MODE_MOBILE);
         mBundle.putString(USER_AGENT_OVERRIDE.name, null);
         mBundle.putInt(VIEWPORT_MODE.name, VIEWPORT_MODE_MOBILE);
         mBundle.putInt(DISPLAY_MODE.name, DISPLAY_MODE_BROWSER);
     }
 
-    public void setBoolean(final @NonNull Key<Boolean> key, final boolean value) {
+    /**
+     * Set whether tracking protection should be enabled.
+     *
+     * @param value A flag determining whether tracking protection should be enabled.
+     *             Default is false.
+     */
+    public void setUseTrackingProtection(final boolean value) {
+        setBoolean(USE_TRACKING_PROTECTION, value);
+    }
+
+    /**
+     * Set the privacy mode for this instance.
+     *
+     * @param value A flag determining whether Private Mode should be enabled.
+     *             Default is false.
+     */
+    private void setUsePrivateMode(final boolean value) {
+        setBoolean(USE_PRIVATE_MODE, value);
+    }
+
+
+    /**
+     * Set whether multi-process support should be enabled.
+     *
+     * @param value A flag determining whether multi-process should be enabled.
+     *             Default is false.
+     */
+    private void setUseMultiprocess(final boolean value) {
+        setBoolean(USE_MULTIPROCESS, value);
+    }
+
+    /**
+     * Set whether to suspend the playing of media when the session is inactive.
+     *
+     * @param value A flag determining whether media should be suspended.
+     *             Default is false.
+     */
+    public void setSuspendMediaWhenInactive(final boolean value) {
+        setBoolean(SUSPEND_MEDIA_WHEN_INACTIVE, value);
+    }
+
+
+    /**
+     * Set whether JavaScript support should be enabled.
+     *
+     * @param value A flag determining whether JavaScript should be enabled.
+     *             Default is true.
+     */
+    public void setAllowJavascript(final boolean value) {
+        setBoolean(ALLOW_JAVASCRIPT, value);
+    }
+
+
+    /**
+     * Set whether the entire accessible tree should be exposed with no caching.
+     *
+     * @param value A flag determining full accessibility tree should be exposed.
+     *             Default is false.
+     */
+    public void setFullAccessibilityTree(final boolean value) {
+        setBoolean(FULL_ACCESSIBILITY_TREE, value);
+    }
+
+    private void setBoolean(final Key<Boolean> key, final boolean value) {
         synchronized (mBundle) {
             if (valueChangedLocked(key, value)) {
                 mBundle.putBoolean(key.name, value);
                 dispatchUpdate();
             }
         }
     }
 
-    public boolean getBoolean(final @NonNull Key<Boolean> key) {
+    /**
+     * Whether tracking protection is enabled.
+     *
+     * @return true if tracking protection is enabled, false if not.
+     */
+    public boolean getUseTrackingProtection() {
+        return getBoolean(USE_TRACKING_PROTECTION);
+    }
+
+    /**
+     * Whether private mode is enabled.
+     *
+     * @return true if private mode is enabled, false if not.
+     */
+    public boolean getUsePrivateMode() {
+        return getBoolean(USE_PRIVATE_MODE);
+    }
+
+    /**
+     * Whether multiprocess is enabled.
+     *
+     * @return true if multiprocess is enabled, false if not.
+     */
+    public boolean getUseMultiprocess() {
+        return getBoolean(USE_MULTIPROCESS);
+    }
+
+    /**
+     * Whether media will be suspended when the session is inactice.
+     *
+     * @return true if media will be suspended, false if not.
+     */
+    public boolean getSuspendMediaWhenInactive() {
+        return getBoolean(SUSPEND_MEDIA_WHEN_INACTIVE);
+    }
+
+    /**
+     * Whether javascript execution is allowed.
+     *
+     * @return true if javascript execution is allowed, false if not.
+     */
+    public boolean getAllowJavascript() {
+        return getBoolean(ALLOW_JAVASCRIPT);
+    }
+
+    /**
+     * Whether entire accessible tree is exposed with no caching.
+     *
+     * @return true if accessibility tree is exposed, false if not.
+     */
+    public boolean getFullAccessibilityTree() {
+        return getBoolean(FULL_ACCESSIBILITY_TREE);
+    }
+
+    private boolean getBoolean(final Key<Boolean> key) {
         synchronized (mBundle) {
             return mBundle.getBoolean(key.name);
         }
     }
 
-    public void setInt(final @NonNull Key<Integer> key, final int value) {
+    /**
+     * Set the screen id.
+     *
+     * @param value The screen id.
+     */
+    private void setScreenId(final int value) {
+        setInt(SCREEN_ID, value);
+    }
+
+
+    /**
+     * Specify which user agent mode we should use
+     *
+     * @param value One or more of the
+     *             {@link GeckoSessionSettings#USER_AGENT_MODE_MOBILE GeckoSessionSettings.USER_AGENT_MODE_*} flags.
+     */
+    public void setUserAgentMode(final int value) {
+        setInt(USER_AGENT_MODE, value);
+    }
+
+
+    /**
+     * Set the display mode.
+     *
+     * @param value The mode to set the display to.
+     *             Use one or more of the
+     *             {@link GeckoSessionSettings#DISPLAY_MODE_BROWSER GeckoSessionSettings.DISPLAY_MODE_*} flags.
+     */
+    public void setDisplayMode(final int value) {
+        setInt(DISPLAY_MODE, value);
+    }
+
+
+    /**
+     * Specify which viewport mode we should use
+     *
+     * @param value One or more of the
+     *             {@link GeckoSessionSettings#VIEWPORT_MODE_MOBILE GeckoSessionSettings.VIEWPORT_MODE_*} flags.
+     */
+    public void setViewportMode(final int value) {
+        setInt(VIEWPORT_MODE, value);
+    }
+
+    private void setInt(final Key<Integer> key, final int value) {
         synchronized (mBundle) {
             if (valueChangedLocked(key, value)) {
                 mBundle.putInt(key.name, value);
                 dispatchUpdate();
             }
         }
     }
 
-    public int getInt(final @NonNull Key<Integer> key) {
+    /**
+     * Set the window screen ID.
+     * Read-only once session is open.
+     * Use the {@link Builder} to set on session open.
+     *
+     * @return Key to set the window screen ID. 0 is the default ID.
+     */
+    public int getScreenId() {
+        return getInt(SCREEN_ID);
+    }
+
+    /**
+     * The current user agent Mode
+     * @return One or more of the
+     *      {@link GeckoSessionSettings#USER_AGENT_MODE_MOBILE GeckoSessionSettings.USER_AGENT_MODE_*} flags.
+     */
+    public int getUserAgentMode() {
+        return getInt(USER_AGENT_MODE);
+    }
+
+    /**
+     * The current display mode.
+     * @return )One or more of the
+     *      {@link GeckoSessionSettings#DISPLAY_MODE_BROWSER GeckoSessionSettings.DISPLAY_MODE_*} flags.
+     */
+    public int getDisplayMode() {
+        return getInt(DISPLAY_MODE);
+    }
+
+    /**
+     * The current viewport Mode
+     * @return One or more of the
+     *      {@link GeckoSessionSettings#VIEWPORT_MODE GeckoSessionSettings.VIEWPORT_MODE_*} flags.
+     */
+    public int getViewportMode() {
+        return getInt(VIEWPORT_MODE);
+    }
+
+    private int getInt(final Key<Integer> key) {
         synchronized (mBundle) {
             return mBundle.getInt(key.name);
         }
     }
 
-    public void setString(final @NonNull Key<String> key, final @Nullable String value) {
+    /**
+     * Set the chrome URI.
+     *
+     * @param value The URI to set the Chrome URI to.
+
+     */
+    private void setChromeUri(final @NonNull String value) {
+        setString(CHROME_URI, value);
+    }
+
+
+    /**
+     * Specify the user agent override string.
+     * Set value to null to use the user agent specified by USER_AGENT_MODE.
+     * @param value
+     */
+    public void setUserAgentOverride(final @Nullable String value) {
+        setString(USER_AGENT_OVERRIDE, value);
+    }
+
+    private void setString(final Key<String> key, final String value) {
         synchronized (mBundle) {
             if (valueChangedLocked(key, value)) {
                 mBundle.putString(key.name, value);
                 dispatchUpdate();
             }
         }
     }
 
-    public String getString(final @NonNull Key<String> key) {
+    /**
+     * Set the chrome window URI.
+     * Read-only once session is open.
+     * Use the {@link Builder} to set on session open.
+     *
+     * @return Key to set the chrome window URI, or null to use default URI.
+     */
+    public @Nullable String getChromeUri() {
+        return getString(CHROME_URI);
+    }
+
+    /**
+     * The user agent override string.
+     * @return The current user agent string or null if the agent is specified by
+     *          {@link GeckoSessionSettings#USER_AGENT_MODE}
+     */
+    public @Nullable String getUserAgentOverride() {
+        return getString(USER_AGENT_OVERRIDE);
+    }
+
+    private String getString(final Key<String> key) {
         synchronized (mBundle) {
             return mBundle.getString(key.name);
         }
     }
 
-    /* package */ GeckoBundle toBundle() {
+    /* package */ @NonNull GeckoBundle toBundle() {
         return new GeckoBundle(mBundle);
     }
 
     @Override
     public String toString() {
         return mBundle.toString();
     }
 
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.java
@@ -111,17 +111,17 @@ public class SessionAccessibility {
         return "android.view.View"; // Fallback class is View
     }
 
     /* package */ final class NodeProvider extends AccessibilityNodeProvider {
         @Override
         public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualDescendantId) {
             AccessibilityNodeInfo node = null;
             if (mAttached) {
-                node = mSession.getSettings().getBoolean(GeckoSessionSettings.FULL_ACCESSIBILITY_TREE) ?
+                node = mSession.getSettings().getFullAccessibilityTree() ?
                         getNodeFromGecko(virtualDescendantId) : getNodeFromCache(virtualDescendantId);
                 if (node != null) {
                     node.setAccessibilityFocused(mAccessibilityFocusedNode == virtualDescendantId);
                     node.setFocused(mFocusedNode == virtualDescendantId);
                 }
             }
 
             if (node == null) {
@@ -656,17 +656,17 @@ public class SessionAccessibility {
         if (!Settings.isPlatformEnabled() && (Build.VERSION.SDK_INT < 17 || mView.getDisplay() != null)) {
             // Accessibility could be activated in Gecko via xpcom, for example when using a11y
             // devtools. Here we assure that either Android a11y is *really* enabled, or no
             // display is attached and we must be in a junit test.
             return;
         }
 
         GeckoBundle cachedBundle = null;
-        if (!mSession.getSettings().getBoolean(GeckoSessionSettings.FULL_ACCESSIBILITY_TREE)) {
+        if (!mSession.getSettings().getFullAccessibilityTree()) {
             cachedBundle = getMostRecentBundle(sourceId);
             // Suppress events from non cached nodes if cache is enabled.
             if (cachedBundle == null && sourceId != View.NO_ID) {
                 return;
             }
         }
 
         final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
--- 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
@@ -5,16 +5,20 @@ layout: geckoview
 <h1> GeckoView API Changelog. </h1>
 
 ## v66
 - Added [`@NonNull`][66.1] or [`@Nullable`][66.2] to all APIs.
 
 [66.1]: https://developer.android.com/reference/android/support/annotation/NonNull
 [66.2]: https://developer.android.com/reference/android/support/annotation/Nullable
 
+- Added methods for each setting in [`GeckoSessionSettings`][66.3]
+
+[66.3]: ../GeckoSessionSettings.html
+
 - Added GeckoRuntimeSetting for enabling desktop viewport. Desktop viewport is
   no longer set by `USER_AGENT_MODE_DESKTOP` and must be set separately.
 
 ## v65
 - Moved [`CompositorController`][65.1], [`DynamicToolbarAnimator`][65.2],
   [`OverscrollEdgeEffect`][65.3], [`PanZoomController`][65.4] from
   `org.mozilla.gecko.gfx` to [`org.mozilla.geckoview`][65.5]
 
@@ -96,9 +100,9 @@ layout: geckoview
 [65.23]: ../GeckoSession.FinderResult.html
 
 - Update [`CrashReporter#sendCrashReport`][65.24] to return the crash ID as a
   [`GeckoResult<String>`][65.25].
 
 [65.24]: ../CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String-
 [65.25]: ../GeckoResult.html
 
-[api-version]: a0f14e2c654491c9f12b3e1ce46e5e59705ef917
+[api-version]: 5957a5943b39ae0e56b7e892bd824a16bb71e811
--- 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
@@ -140,39 +140,38 @@ public class GeckoViewActivity extends A
             mGeckoSession = (GeckoSession)getIntent().getParcelableExtra("session");
             if (mGeckoSession != null) {
                 connectSession(mGeckoSession);
 
                 if (!mGeckoSession.isOpen()) {
                     mGeckoSession.open(sGeckoRuntime);
                 }
 
-                mUseMultiprocess = mGeckoSession.getSettings().getBoolean(GeckoSessionSettings.USE_MULTIPROCESS);
-                mFullAccessibilityTree = mGeckoSession.getSettings().getBoolean(GeckoSessionSettings.FULL_ACCESSIBILITY_TREE);
+                mUseMultiprocess = mGeckoSession.getSettings().getUseMultiprocess();
+                mFullAccessibilityTree = mGeckoSession.getSettings().getFullAccessibilityTree();
 
                 mGeckoView.setSession(mGeckoSession);
             } else {
                 mGeckoSession = createSession();
                 mGeckoView.setSession(mGeckoSession, sGeckoRuntime);
 
                 loadFromIntent(getIntent());
             }
         }
 
         mLocationView.setCommitListener(mCommitListener);
     }
 
     private GeckoSession createSession() {
-        GeckoSession session = new GeckoSession();
-        session.getSettings().setBoolean(GeckoSessionSettings.USE_MULTIPROCESS, mUseMultiprocess);
-        session.getSettings().setBoolean(GeckoSessionSettings.USE_PRIVATE_MODE, mUsePrivateBrowsing);
-        session.getSettings().setBoolean(
-            GeckoSessionSettings.USE_TRACKING_PROTECTION, mUseTrackingProtection);
-        session.getSettings().setBoolean(
-                GeckoSessionSettings.FULL_ACCESSIBILITY_TREE, mFullAccessibilityTree);
+        GeckoSession session = new GeckoSession(new GeckoSessionSettings.Builder()
+                .useMultiprocess(mUseMultiprocess)
+                .usePrivateMode(mUsePrivateBrowsing)
+                .useTrackingProtection(mUseTrackingProtection)
+                .fullAccessibilityTree(mFullAccessibilityTree)
+                .build());
 
         connectSession(session);
 
         return session;
     }
 
     private void connectSession(GeckoSession session) {
         session.setContentDelegate(new ExampleContentDelegate());
@@ -212,18 +211,17 @@ public class GeckoViewActivity extends A
         if(savedInstanceState != null) {
             mGeckoSession = mGeckoView.getSession();
         } else {
             recreateSession();
         }
     }
 
     private void updateTrackingProtection(GeckoSession session) {
-        session.getSettings().setBoolean(
-            GeckoSessionSettings.USE_TRACKING_PROTECTION, mUseTrackingProtection);
+        session.getSettings().setUseTrackingProtection(mUseTrackingProtection);
     }
 
     @Override
     public void onBackPressed() {
         if (mFullScreen) {
             mGeckoSession.exitFullScreen();
             return;
         }