summaryrefslogtreecommitdiffstats
path: root/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java')
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java1314
1 files changed, 1314 insertions, 0 deletions
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
new file mode 100644
index 0000000000..b74d7476e1
--- /dev/null
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
@@ -0,0 +1,1314 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * vim: ts=4 sw=4 expandtab:
+ * 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 static android.os.Build.VERSION;
+
+import android.app.Service;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.LocaleList;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.Log;
+import androidx.annotation.AnyThread;
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.LinkedHashMap;
+import java.util.Locale;
+import org.mozilla.gecko.EventDispatcher;
+import org.mozilla.gecko.GeckoSystemStateListener;
+import org.mozilla.gecko.util.GeckoBundle;
+
+@AnyThread
+public final class GeckoRuntimeSettings extends RuntimeSettings {
+ private static final String LOGTAG = "GeckoRuntimeSettings";
+
+ /** Settings builder used to construct the settings object. */
+ @AnyThread
+ public static final class Builder extends RuntimeSettings.Builder<GeckoRuntimeSettings> {
+ @Override
+ protected @NonNull GeckoRuntimeSettings newSettings(
+ final @Nullable GeckoRuntimeSettings settings) {
+ return new GeckoRuntimeSettings(settings);
+ }
+
+ /**
+ * 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");
+ }
+ getSettings().mArgs = args;
+ return this;
+ }
+
+ /**
+ * Set the custom Gecko intent extras.
+ *
+ * @param extras The Gecko intent extras.
+ * @return This Builder instance.
+ */
+ public @NonNull Builder extras(final @NonNull Bundle extras) {
+ if (extras == null) {
+ throw new IllegalArgumentException("Extras must not be null");
+ }
+ getSettings().mExtras = extras;
+ return this;
+ }
+
+ /**
+ * Path to configuration file from which GeckoView will read configuration options such as Gecko
+ * process arguments, environment variables, and preferences.
+ *
+ * <p>Note: this feature is only available for <code>{@link VERSION#SDK_INT} &gt; 21</code>, on
+ * older devices this will be silently ignored.
+ *
+ * @param configFilePath Configuration file path to read from, or <code>null</code> to use
+ * default location <code>/data/local/tmp/$PACKAGE-geckoview-config.yaml</code>.
+ * @return This Builder instance.
+ */
+ public @NonNull Builder configFilePath(final @Nullable String configFilePath) {
+ getSettings().mConfigFilePath = configFilePath;
+ 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 javaScriptEnabled(final boolean flag) {
+ getSettings().mJavaScript.set(flag);
+ return this;
+ }
+
+ /**
+ * Set whether remote debugging support should be enabled.
+ *
+ * @param enabled True if remote debugging should be enabled.
+ * @return This Builder instance.
+ */
+ public @NonNull Builder remoteDebuggingEnabled(final boolean enabled) {
+ getSettings().mRemoteDebugging.set(enabled);
+ return this;
+ }
+
+ /**
+ * Set whether support for web fonts should be enabled.
+ *
+ * @param flag A flag determining whether web fonts should be enabled. Default is true.
+ * @return This Builder instance.
+ */
+ public @NonNull Builder webFontsEnabled(final boolean flag) {
+ getSettings().mWebFonts.set(flag ? 1 : 0);
+ return this;
+ }
+
+ /**
+ * Set whether there should be a pause during startup. This is useful if you need to wait for a
+ * debugger to attach.
+ *
+ * @param enabled A flag determining whether there will be a pause early in startup. Defaults to
+ * false.
+ * @return This Builder.
+ */
+ public @NonNull Builder pauseForDebugger(final boolean enabled) {
+ getSettings().mDebugPause = enabled;
+ return this;
+ }
+
+ /**
+ * Set whether the to report the full bit depth of the device.
+ *
+ * <p>By default, 24 bits are reported for high memory devices and 16 bits for low memory
+ * devices. If set to true, the device's maximum bit depth is reported. On most modern devices
+ * this will be 32 bit screen depth.
+ *
+ * @param enable A flag determining whether maximum screen depth should be used.
+ * @return This Builder.
+ */
+ public @NonNull Builder useMaxScreenDepth(final boolean enable) {
+ getSettings().mUseMaxScreenDepth = enable;
+ return this;
+ }
+
+ /**
+ * Set whether web manifest support is enabled.
+ *
+ * <p>This controls if Gecko actually downloads, or "obtains", web manifests and processes them.
+ * Without setting this pref, trying to obtain a manifest throws.
+ *
+ * @param enabled A flag determining whether Web Manifest processing support is enabled.
+ * @return The builder instance.
+ */
+ public @NonNull Builder webManifest(final boolean enabled) {
+ getSettings().mWebManifest.set(enabled);
+ return this;
+ }
+
+ /**
+ * Set whether or not web console messages should go to logcat.
+ *
+ * <p>Note: If enabled, Gecko performance may be negatively impacted if content makes heavy use
+ * of the console API.
+ *
+ * @param enabled A flag determining whether or not web console messages should be printed to
+ * logcat.
+ * @return The builder instance.
+ */
+ public @NonNull Builder consoleOutput(final boolean enabled) {
+ getSettings().mConsoleOutput.set(enabled);
+ return this;
+ }
+
+ /**
+ * Set whether or not font sizes in web content should be automatically scaled according to the
+ * device's current system font scale setting.
+ *
+ * @param enabled A flag determining whether or not font sizes should be scaled automatically to
+ * match the device's system font scale.
+ * @return The builder instance.
+ */
+ public @NonNull Builder automaticFontSizeAdjustment(final boolean enabled) {
+ getSettings().setAutomaticFontSizeAdjustment(enabled);
+ return this;
+ }
+
+ /**
+ * Set a font size factor that will operate as a global text zoom. All font sizes will be
+ * multiplied by this factor.
+ *
+ * <p>The default factor is 1.0.
+ *
+ * <p>This setting cannot be modified if {@link Builder#automaticFontSizeAdjustment automatic
+ * font size adjustment} has already been enabled.
+ *
+ * @param fontSizeFactor The factor to be used for scaling all text. Setting a value of 0
+ * disables both this feature and {@link Builder#fontInflation font inflation}.
+ * @return The builder instance.
+ */
+ public @NonNull Builder fontSizeFactor(final float fontSizeFactor) {
+ getSettings().setFontSizeFactor(fontSizeFactor);
+ return this;
+ }
+
+ /**
+ * Enable the Enterprise Roots feature.
+ *
+ * <p>When Enabled, GeckoView will fetch the third-party root certificates added to the Android
+ * OS CA store and will use them internally.
+ *
+ * @param enabled whether to enable this feature or not
+ * @return The builder instance
+ */
+ public @NonNull Builder enterpriseRootsEnabled(final boolean enabled) {
+ getSettings().setEnterpriseRootsEnabled(enabled);
+ return this;
+ }
+
+ /**
+ * Set whether or not font inflation for non mobile-friendly pages should be enabled. The
+ * default value of this setting is <code>false</code>.
+ *
+ * <p>When enabled, font sizes will be increased on all pages that are lacking a &lt;meta&gt;
+ * viewport tag and have been loaded in a session using {@link
+ * GeckoSessionSettings#VIEWPORT_MODE_MOBILE}. To improve readability, the font inflation logic
+ * will attempt to increase font sizes for the main text content of the page only.
+ *
+ * <p>The magnitude of font inflation applied depends on the {@link Builder#fontSizeFactor font
+ * size factor} currently in use.
+ *
+ * <p>This setting cannot be modified if {@link Builder#automaticFontSizeAdjustment automatic
+ * font size adjustment} has already been enabled.
+ *
+ * @param enabled A flag determining whether or not font inflation should be enabled.
+ * @return The builder instance.
+ */
+ public @NonNull Builder fontInflation(final boolean enabled) {
+ getSettings().setFontInflationEnabled(enabled);
+ return this;
+ }
+
+ /**
+ * Set the display density override.
+ *
+ * @param density The display density value to use for overriding the system default.
+ * @return The builder instance.
+ */
+ public @NonNull Builder displayDensityOverride(final float density) {
+ getSettings().mDisplayDensityOverride = density;
+ return this;
+ }
+
+ /**
+ * Set the display DPI override.
+ *
+ * @param dpi The display DPI value to use for overriding the system default.
+ * @return The builder instance.
+ */
+ public @NonNull Builder displayDpiOverride(final int dpi) {
+ getSettings().mDisplayDpiOverride = dpi;
+ return this;
+ }
+
+ /**
+ * Set the screen size override.
+ *
+ * @param width The screen width value to use for overriding the system default.
+ * @param height The screen height value to use for overriding the system default.
+ * @return The builder instance.
+ */
+ public @NonNull Builder screenSizeOverride(final int width, final int height) {
+ getSettings().mScreenWidthOverride = width;
+ getSettings().mScreenHeightOverride = height;
+ return this;
+ }
+
+ /**
+ * Set whether login forms should be filled automatically if only one viable candidate is
+ * provided via {@link Autocomplete.StorageDelegate#onLoginFetch onLoginFetch}.
+ *
+ * @param enabled A flag determining whether login autofill should be enabled.
+ * @return The builder instance.
+ */
+ public @NonNull Builder loginAutofillEnabled(final boolean enabled) {
+ getSettings().setLoginAutofillEnabled(enabled);
+ return this;
+ }
+
+ /**
+ * When set, the specified {@link android.app.Service} will be started by an {@link
+ * android.content.Intent} with action {@link GeckoRuntime#ACTION_CRASHED} when a crash is
+ * encountered. Crash details can be found in the Intent extras, such as {@link
+ * GeckoRuntime#EXTRA_MINIDUMP_PATH}. <br>
+ * <br>
+ * The crash handler Service must be declared to run in a different process from the {@link
+ * GeckoRuntime}. Additionally, the handler will be run as a foreground service, so the normal
+ * rules about activating a foreground service apply. <br>
+ * <br>
+ * In practice, you have one of three options once the crash handler is started:
+ *
+ * <ul>
+ * <li>Call {@link android.app.Service#startForeground(int, android.app.Notification)}. You
+ * can then take as much time as necessary to report the crash.
+ * <li>Start an activity. Unless you also call {@link android.app.Service#startForeground(int,
+ * android.app.Notification)} this should be in a different process from the crash
+ * handler, since Android will kill the crash handler process as part of the background
+ * execution limitations.
+ * <li>Schedule work via {@link android.app.job.JobScheduler}. This will allow you to do
+ * substantial work in the background without execution limits.
+ * </ul>
+ *
+ * <br>
+ * You can use {@link CrashReporter} to send the report to Mozilla, which provides Mozilla with
+ * data needed to fix the crash. Be aware that the minidump may contain personally identifiable
+ * information (PII). Consult Mozilla's <a href="https://www.mozilla.org/en-US/privacy/">privacy
+ * policy</a> for information on how this data will be handled.
+ *
+ * @param handler The class for the crash handler Service.
+ * @return This builder instance.
+ * @see <a href="https://developer.android.com/about/versions/oreo/background">Android
+ * Background Execution Limits</a>
+ * @see GeckoRuntime#ACTION_CRASHED
+ */
+ public @NonNull Builder crashHandler(final @Nullable Class<? extends Service> handler) {
+ getSettings().mCrashHandler = handler;
+ return this;
+ }
+
+ /**
+ * Set the locale.
+ *
+ * @param requestedLocales List of locale codes in Gecko format ("en" or "en-US").
+ * @return The builder instance.
+ */
+ public @NonNull Builder locales(final @Nullable String[] requestedLocales) {
+ getSettings().mRequestedLocales = requestedLocales;
+ return this;
+ }
+
+ @SuppressWarnings("checkstyle:javadocmethod")
+ public @NonNull Builder contentBlocking(final @NonNull ContentBlocking.Settings cb) {
+ getSettings().mContentBlocking = cb;
+ return this;
+ }
+
+ /**
+ * Sets the preferred color scheme override for web content.
+ *
+ * @param scheme The preferred color scheme. Must be one of the {@link
+ * GeckoRuntimeSettings#COLOR_SCHEME_LIGHT COLOR_SCHEME_*} constants.
+ * @return This Builder instance.
+ */
+ public @NonNull Builder preferredColorScheme(final @ColorScheme int scheme) {
+ getSettings().setPreferredColorScheme(scheme);
+ return this;
+ }
+
+ /**
+ * Set whether auto-zoom to editable fields should be enabled.
+ *
+ * @param flag True if auto-zoom should be enabled, false otherwise.
+ * @return This Builder instance.
+ */
+ public @NonNull Builder inputAutoZoomEnabled(final boolean flag) {
+ getSettings().mInputAutoZoom.set(flag);
+ return this;
+ }
+
+ /**
+ * Set whether double tap zooming should be enabled.
+ *
+ * @param flag True if double tap zooming should be enabled, false otherwise.
+ * @return This Builder instance.
+ */
+ public @NonNull Builder doubleTapZoomingEnabled(final boolean flag) {
+ getSettings().mDoubleTapZooming.set(flag);
+ return this;
+ }
+
+ /**
+ * Sets the WebGL MSAA level.
+ *
+ * @param level number of MSAA samples, 0 if MSAA should be disabled.
+ * @return This Builder instance.
+ */
+ public @NonNull Builder glMsaaLevel(final int level) {
+ getSettings().mGlMsaaLevel.set(level);
+ return this;
+ }
+
+ /**
+ * Add a {@link RuntimeTelemetry.Delegate} instance to this GeckoRuntime. This delegate can be
+ * used by the app to receive streaming telemetry data from GeckoView.
+ *
+ * @param delegate the delegate that will handle telemetry
+ * @return The builder instance.
+ */
+ public @NonNull Builder telemetryDelegate(final @NonNull RuntimeTelemetry.Delegate delegate) {
+ getSettings().mTelemetryProxy = new RuntimeTelemetry.Proxy(delegate);
+ getSettings().mTelemetryEnabled.set(true);
+ return this;
+ }
+
+ /**
+ * Enables GeckoView and Gecko Logging. Logging is on by default. Does not control all logging
+ * in Gecko. Logging done in Java code must be stripped out at build time.
+ *
+ * @param enable True if logging is enabled.
+ * @return This Builder instance.
+ */
+ public @NonNull Builder debugLogging(final boolean enable) {
+ getSettings().mDevToolsConsoleToLogcat.set(enable);
+ getSettings().mConsoleServiceToLogcat.set(enable);
+ getSettings().mGeckoViewLogLevel.set(enable ? "Debug" : "Fatal");
+ return this;
+ }
+
+ /**
+ * Sets whether or not about:config should be enabled. This is a page that allows users to
+ * directly modify Gecko preferences. Modification of some preferences may cause the app to
+ * break in unpredictable ways -- crashes, performance issues, security vulnerabilities, etc.
+ *
+ * @param flag True if about:config should be enabled, false otherwise.
+ * @return This Builder instance.
+ */
+ public @NonNull Builder aboutConfigEnabled(final boolean flag) {
+ getSettings().mAboutConfig.set(flag);
+ return this;
+ }
+
+ /**
+ * Sets whether or not pinch-zooming should be enabled when <code>user-scalable=no</code> is set
+ * on the viewport.
+ *
+ * @param flag True if force user scalable zooming should be enabled, false otherwise.
+ * @return This Builder instance.
+ */
+ public @NonNull Builder forceUserScalableEnabled(final boolean flag) {
+ getSettings().mForceUserScalable.set(flag);
+ return this;
+ }
+
+ /**
+ * Sets whether and where insecure (non-HTTPS) connections are allowed.
+ *
+ * @param level One of the {@link GeckoRuntimeSettings#ALLOW_ALL HttpsOnlyMode} constants.
+ * @return This Builder instance.
+ */
+ public @NonNull Builder allowInsecureConnections(final @HttpsOnlyMode int level) {
+ getSettings().setAllowInsecureConnections(level);
+ return this;
+ }
+ }
+
+ private GeckoRuntime mRuntime;
+ /* package */ String[] mArgs;
+ /* package */ Bundle mExtras;
+ /* package */ String mConfigFilePath;
+
+ /* package */ ContentBlocking.Settings mContentBlocking;
+
+ @SuppressWarnings("checkstyle:javadocmethod")
+ public @NonNull ContentBlocking.Settings getContentBlocking() {
+ return mContentBlocking;
+ }
+
+ /* package */ final Pref<Boolean> mWebManifest = new Pref<Boolean>("dom.manifest.enabled", true);
+ /* package */ final Pref<Boolean> mJavaScript = new Pref<Boolean>("javascript.enabled", true);
+ /* package */ final Pref<Boolean> mRemoteDebugging =
+ new Pref<Boolean>("devtools.debugger.remote-enabled", false);
+ /* package */ final Pref<Integer> mWebFonts =
+ new Pref<Integer>("browser.display.use_document_fonts", 1);
+ /* package */ final Pref<Boolean> mConsoleOutput =
+ new Pref<Boolean>("geckoview.console.enabled", false);
+ /* package */ float mFontSizeFactor = 1f;
+ /* package */ final Pref<Boolean> mEnterpriseRootsEnabled =
+ new Pref<>("security.enterprise_roots.enabled", false);
+ /* package */ final Pref<Integer> mFontInflationMinTwips =
+ new Pref<>("font.size.inflation.minTwips", 0);
+ /* package */ final Pref<Boolean> mInputAutoZoom = new Pref<>("formhelper.autozoom", true);
+ /* package */ final Pref<Boolean> mDoubleTapZooming =
+ new Pref<>("apz.allow_double_tap_zooming", true);
+ /* package */ final Pref<Integer> mGlMsaaLevel = new Pref<>("webgl.msaa-samples", 4);
+ /* package */ final Pref<Boolean> mTelemetryEnabled =
+ new Pref<>("toolkit.telemetry.geckoview.streaming", false);
+ /* package */ final Pref<String> mGeckoViewLogLevel = new Pref<>("geckoview.logging", "Debug");
+ /* 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> mAutofillLogins =
+ new Pref<Boolean>("signon.autofillForms", true);
+ /* package */ final Pref<Boolean> mHttpsOnly =
+ new Pref<Boolean>("dom.security.https_only_mode", false);
+ /* package */ final Pref<Boolean> mHttpsOnlyPrivateMode =
+ new Pref<Boolean>("dom.security.https_only_mode_pbm", false);
+ /* package */ final Pref<Integer> mProcessCount = new Pref<>("dom.ipc.processCount", 2);
+
+ /* package */ int mPreferredColorScheme = COLOR_SCHEME_SYSTEM;
+
+ /* package */ boolean mForceEnableAccessibility;
+ /* package */ boolean mDebugPause;
+ /* package */ boolean mUseMaxScreenDepth;
+ /* package */ float mDisplayDensityOverride = -1.0f;
+ /* package */ int mDisplayDpiOverride;
+ /* package */ int mScreenWidthOverride;
+ /* package */ int mScreenHeightOverride;
+ /* package */ Class<? extends Service> mCrashHandler;
+ /* package */ String[] mRequestedLocales;
+ /* package */ RuntimeTelemetry.Proxy mTelemetryProxy;
+
+ /**
+ * Attach and commit the settings to the given runtime.
+ *
+ * @param runtime The runtime to attach to.
+ */
+ /* package */ void attachTo(final @NonNull GeckoRuntime runtime) {
+ mRuntime = runtime;
+ commit();
+
+ if (mTelemetryProxy != null) {
+ mTelemetryProxy.attach();
+ }
+ }
+
+ @Override // RuntimeSettings
+ public @Nullable GeckoRuntime getRuntime() {
+ return mRuntime;
+ }
+
+ /* package */ GeckoRuntimeSettings() {
+ this(null);
+ }
+
+ /* package */ GeckoRuntimeSettings(final @Nullable GeckoRuntimeSettings settings) {
+ super(/* parent */ null);
+
+ if (settings == null) {
+ mArgs = new String[0];
+ mExtras = new Bundle();
+ mContentBlocking = new ContentBlocking.Settings(this /* parent */, null /* settings */);
+ return;
+ }
+
+ updateSettings(settings);
+ }
+
+ private void updateSettings(final @NonNull GeckoRuntimeSettings settings) {
+ updatePrefs(settings);
+
+ mArgs = settings.getArguments().clone();
+ mExtras = new Bundle(settings.getExtras());
+ mContentBlocking = new ContentBlocking.Settings(this /* parent */, settings.mContentBlocking);
+
+ mForceEnableAccessibility = settings.mForceEnableAccessibility;
+ mDebugPause = settings.mDebugPause;
+ mUseMaxScreenDepth = settings.mUseMaxScreenDepth;
+ mDisplayDensityOverride = settings.mDisplayDensityOverride;
+ mDisplayDpiOverride = settings.mDisplayDpiOverride;
+ mScreenWidthOverride = settings.mScreenWidthOverride;
+ mScreenHeightOverride = settings.mScreenHeightOverride;
+ mCrashHandler = settings.mCrashHandler;
+ mRequestedLocales = settings.mRequestedLocales;
+ mConfigFilePath = settings.mConfigFilePath;
+ mTelemetryProxy = settings.mTelemetryProxy;
+ }
+
+ /* package */ void commit() {
+ commitLocales();
+ commitResetPrefs();
+ }
+
+ /**
+ * Get the custom Gecko process arguments.
+ *
+ * @return The Gecko process arguments.
+ */
+ public @NonNull String[] getArguments() {
+ return mArgs;
+ }
+
+ /**
+ * Get the custom Gecko intent extras.
+ *
+ * @return The Gecko intent extras.
+ */
+ public @NonNull Bundle getExtras() {
+ return mExtras;
+ }
+
+ /**
+ * Path to configuration file from which GeckoView will read configuration options such as Gecko
+ * process arguments, environment variables, and preferences.
+ *
+ * <p>Note: this feature is only available for <code>{@link VERSION#SDK_INT} &gt; 21</code>.
+ *
+ * @return Path to configuration file from which GeckoView will read configuration options, or
+ * <code>null</code> for default location <code>/data/local/tmp/$PACKAGE-geckoview-config.yaml
+ * </code>.
+ */
+ public @Nullable String getConfigFilePath() {
+ return mConfigFilePath;
+ }
+
+ /**
+ * Get whether JavaScript support is enabled.
+ *
+ * @return Whether JavaScript support is enabled.
+ */
+ public boolean getJavaScriptEnabled() {
+ return mJavaScript.get();
+ }
+
+ /**
+ * Set whether JavaScript support should be enabled.
+ *
+ * @param flag A flag determining whether JavaScript should be enabled.
+ * @return This GeckoRuntimeSettings instance.
+ */
+ public @NonNull GeckoRuntimeSettings setJavaScriptEnabled(final boolean flag) {
+ mJavaScript.commit(flag);
+ return this;
+ }
+
+ /**
+ * Get whether remote debugging support is enabled.
+ *
+ * @return True if remote debugging support is enabled.
+ */
+ public boolean getRemoteDebuggingEnabled() {
+ return mRemoteDebugging.get();
+ }
+
+ /**
+ * Set whether remote debugging support should be enabled.
+ *
+ * @param enabled True if remote debugging should be enabled.
+ * @return This GeckoRuntimeSettings instance.
+ */
+ public @NonNull GeckoRuntimeSettings setRemoteDebuggingEnabled(final boolean enabled) {
+ mRemoteDebugging.commit(enabled);
+ return this;
+ }
+
+ /**
+ * Get whether web fonts support is enabled.
+ *
+ * @return Whether web fonts support is enabled.
+ */
+ public boolean getWebFontsEnabled() {
+ return mWebFonts.get() != 0 ? true : false;
+ }
+
+ /**
+ * Set whether support for web fonts should be enabled.
+ *
+ * @param flag A flag determining whether web fonts should be enabled.
+ * @return This GeckoRuntimeSettings instance.
+ */
+ public @NonNull GeckoRuntimeSettings setWebFontsEnabled(final boolean flag) {
+ mWebFonts.commit(flag ? 1 : 0);
+ return this;
+ }
+
+ /**
+ * Gets whether the pause-for-debugger is enabled or not.
+ *
+ * @return True if the pause is enabled.
+ */
+ public boolean getPauseForDebuggerEnabled() {
+ return mDebugPause;
+ }
+
+ /**
+ * Gets whether accessibility is force enabled or not.
+ *
+ * @return true if accessibility is force enabled.
+ */
+ public boolean getForceEnableAccessibility() {
+ return mForceEnableAccessibility;
+ }
+
+ /**
+ * Sets whether accessibility is force enabled or not.
+ *
+ * <p>Useful when testing accessibility.
+ *
+ * @param value whether accessibility is force enabled or not
+ * @return this GeckoRuntimeSettings instance.
+ */
+ public @NonNull GeckoRuntimeSettings setForceEnableAccessibility(final boolean value) {
+ mForceEnableAccessibility = value;
+ SessionAccessibility.setForceEnabled(value);
+ return this;
+ }
+
+ /**
+ * Gets whether the compositor should use the maximum screen depth when rendering.
+ *
+ * @return True if the maximum screen depth should be used.
+ */
+ public boolean getUseMaxScreenDepth() {
+ return mUseMaxScreenDepth;
+ }
+
+ /**
+ * Gets the display density override value.
+ *
+ * @return Returns a positive number. Will return null if not set.
+ */
+ public @Nullable Float getDisplayDensityOverride() {
+ if (mDisplayDensityOverride > 0.0f) {
+ return mDisplayDensityOverride;
+ }
+ return null;
+ }
+
+ /**
+ * Gets the display DPI override value.
+ *
+ * @return Returns a positive number. Will return null if not set.
+ */
+ public @Nullable Integer getDisplayDpiOverride() {
+ if (mDisplayDpiOverride > 0) {
+ return mDisplayDpiOverride;
+ }
+ return null;
+ }
+
+ @SuppressWarnings("checkstyle:javadocmethod")
+ public @Nullable Class<? extends Service> getCrashHandler() {
+ return mCrashHandler;
+ }
+
+ /**
+ * Gets the screen size override value.
+ *
+ * @return Returns a Rect containing the dimensions to use for the window size. Will return null
+ * if not set.
+ */
+ public @Nullable Rect getScreenSizeOverride() {
+ if ((mScreenWidthOverride > 0) && (mScreenHeightOverride > 0)) {
+ return new Rect(0, 0, mScreenWidthOverride, mScreenHeightOverride);
+ }
+ return null;
+ }
+
+ /**
+ * Gets the list of requested locales.
+ *
+ * @return A list of locale codes in Gecko format ("en" or "en-US").
+ */
+ public @Nullable String[] getLocales() {
+ return mRequestedLocales;
+ }
+
+ /**
+ * Set the locale.
+ *
+ * @param requestedLocales An ordered list of locales in Gecko format ("en-US").
+ */
+ public void setLocales(final @Nullable String[] requestedLocales) {
+ mRequestedLocales = requestedLocales;
+ commitLocales();
+ }
+
+ private void commitLocales() {
+ final GeckoBundle data = new GeckoBundle(1);
+ data.putStringArray("requestedLocales", mRequestedLocales);
+ data.putString("acceptLanguages", computeAcceptLanguages());
+ EventDispatcher.getInstance().dispatch("GeckoView:SetLocale", data);
+ }
+
+ private String computeAcceptLanguages() {
+ final LinkedHashMap<String, String> locales = new LinkedHashMap<>();
+
+ // Explicitly-set app prefs come first:
+ if (mRequestedLocales != null) {
+ for (final String locale : mRequestedLocales) {
+ locales.put(locale.toLowerCase(Locale.ROOT), locale);
+ }
+ }
+ // OS prefs come second:
+ for (final String locale : getDefaultLocales()) {
+ final String localeLowerCase = locale.toLowerCase(Locale.ROOT);
+ if (!locales.containsKey(localeLowerCase)) {
+ locales.put(localeLowerCase, locale);
+ }
+ }
+
+ return TextUtils.join(",", locales.values());
+ }
+
+ private static String[] getDefaultLocales() {
+ if (VERSION.SDK_INT >= 24) {
+ final LocaleList localeList = LocaleList.getDefault();
+ final String[] locales = new String[localeList.size()];
+ for (int i = 0; i < localeList.size(); i++) {
+ locales[i] = localeList.get(i).toLanguageTag();
+ }
+ return locales;
+ }
+ final String[] locales = new String[1];
+ final Locale locale = Locale.getDefault();
+ if (VERSION.SDK_INT >= 21) {
+ locales[0] = locale.toLanguageTag();
+ return locales;
+ }
+
+ locales[0] = getLanguageTag(locale);
+ return locales;
+ }
+
+ private static String getLanguageTag(final Locale locale) {
+ final StringBuilder out = new StringBuilder(locale.getLanguage());
+ final String country = locale.getCountry();
+ final String variant = locale.getVariant();
+ if (!TextUtils.isEmpty(country)) {
+ out.append('-').append(country);
+ }
+ if (!TextUtils.isEmpty(variant)) {
+ out.append('-').append(variant);
+ }
+ // e.g. "en", "en-US", or "en-US-POSIX".
+ return out.toString();
+ }
+
+ /**
+ * Sets whether Web Manifest processing support is enabled.
+ *
+ * @param enabled A flag determining whether Web Manifest processing support is enabled.
+ * @return This GeckoRuntimeSettings instance.
+ */
+ public @NonNull GeckoRuntimeSettings setWebManifestEnabled(final boolean enabled) {
+ mWebManifest.commit(enabled);
+ return this;
+ }
+
+ /**
+ * Get whether or not Web Manifest processing support is enabled.
+ *
+ * @return True if web manifest processing support is enabled.
+ */
+ public boolean getWebManifestEnabled() {
+ return mWebManifest.get();
+ }
+
+ /**
+ * Set whether or not web console messages should go to logcat.
+ *
+ * <p>Note: If enabled, Gecko performance may be negatively impacted if content makes heavy use of
+ * the console API.
+ *
+ * @param enabled A flag determining whether or not web console messages should be printed to
+ * logcat.
+ * @return This GeckoRuntimeSettings instance.
+ */
+ public @NonNull GeckoRuntimeSettings setConsoleOutputEnabled(final boolean enabled) {
+ mConsoleOutput.commit(enabled);
+ return this;
+ }
+
+ /**
+ * Get whether or not web console messages are sent to logcat.
+ *
+ * @return True if console output is enabled.
+ */
+ public boolean getConsoleOutputEnabled() {
+ return mConsoleOutput.get();
+ }
+
+ /**
+ * Set whether or not font sizes in web content should be automatically scaled according to the
+ * device's current system font scale setting. Enabling this will prevent modification of the
+ * {@link GeckoRuntimeSettings#setFontSizeFactor font size factor}. Disabling this setting will
+ * restore the previously used value for the {@link GeckoRuntimeSettings#getFontSizeFactor font
+ * size factor}.
+ *
+ * @param enabled A flag determining whether or not font sizes should be scaled automatically to
+ * match the device's system font scale.
+ * @return This GeckoRuntimeSettings instance.
+ */
+ public @NonNull GeckoRuntimeSettings setAutomaticFontSizeAdjustment(final boolean enabled) {
+ GeckoFontScaleListener.getInstance().setEnabled(enabled);
+ return this;
+ }
+
+ /**
+ * Get whether or not the font sizes for web content are automatically adjusted to match the
+ * device's system font scale setting.
+ *
+ * @return True if font sizes are automatically adjusted.
+ */
+ public boolean getAutomaticFontSizeAdjustment() {
+ return GeckoFontScaleListener.getInstance().getEnabled();
+ }
+
+ private static final int FONT_INFLATION_BASE_VALUE = 120;
+
+ /**
+ * Set a font size factor that will operate as a global text zoom. All font sizes will be
+ * multiplied by this factor.
+ *
+ * <p>The default factor is 1.0.
+ *
+ * <p>Currently, any changes only take effect after a reload of the session.
+ *
+ * <p>This setting cannot be modified while {@link
+ * GeckoRuntimeSettings#setAutomaticFontSizeAdjustment automatic font size adjustment} is enabled.
+ *
+ * @param fontSizeFactor The factor to be used for scaling all text. Setting a value of 0 disables
+ * both this feature and {@link GeckoRuntimeSettings#setFontInflationEnabled font inflation}.
+ * @return This GeckoRuntimeSettings instance.
+ */
+ public @NonNull GeckoRuntimeSettings setFontSizeFactor(final float fontSizeFactor) {
+ if (getAutomaticFontSizeAdjustment()) {
+ throw new IllegalStateException("Not allowed when automatic font size adjustment is enabled");
+ }
+ return setFontSizeFactorInternal(fontSizeFactor);
+ }
+
+ /*
+ * Enable the Enteprise Roots feature.
+ *
+ * When Enabled, GeckoView will fetch the third-party root certificates added to the
+ * Android OS CA store and will use them internally.
+ *
+ * @param enabled whether to enable this feature or not
+ * @return This GeckoRuntimeSettings instance
+ */
+ public @NonNull GeckoRuntimeSettings setEnterpriseRootsEnabled(final boolean enabled) {
+ mEnterpriseRootsEnabled.commit(enabled);
+ return this;
+ }
+
+ /**
+ * Gets whether the Enteprise Roots feature is enabled or not.
+ *
+ * @return true if the feature is enabled, false otherwise.
+ */
+ public boolean getEnterpriseRootsEnabled() {
+ return mEnterpriseRootsEnabled.get();
+ }
+
+ private static final float DEFAULT_FONT_SIZE_FACTOR = 1f;
+
+ private float sanitizeFontSizeFactor(final float fontSizeFactor) {
+ if (fontSizeFactor < 0) {
+ if (BuildConfig.DEBUG_BUILD) {
+ throw new IllegalArgumentException("fontSizeFactor cannot be < 0");
+ } else {
+ Log.e(LOGTAG, "fontSizeFactor cannot be < 0");
+ return DEFAULT_FONT_SIZE_FACTOR;
+ }
+ }
+
+ return fontSizeFactor;
+ }
+
+ /* package */ @NonNull
+ GeckoRuntimeSettings setFontSizeFactorInternal(final float fontSizeFactor) {
+ final float newFactor = sanitizeFontSizeFactor(fontSizeFactor);
+ if (mFontSizeFactor == newFactor) {
+ return this;
+ }
+ mFontSizeFactor = newFactor;
+ if (getFontInflationEnabled()) {
+ final int scaledFontInflation = Math.round(FONT_INFLATION_BASE_VALUE * newFactor);
+ mFontInflationMinTwips.commit(scaledFontInflation);
+ }
+ GeckoSystemStateListener.onDeviceChanged();
+ return this;
+ }
+
+ /**
+ * Gets the currently applied font size factor.
+ *
+ * @return The currently applied font size factor.
+ */
+ public float getFontSizeFactor() {
+ return mFontSizeFactor;
+ }
+
+ /**
+ * Set whether or not font inflation for non mobile-friendly pages should be enabled. The default
+ * value of this setting is <code>false</code>.
+ *
+ * <p>When enabled, font sizes will be increased on all pages that are lacking a &lt;meta&gt;
+ * viewport tag and have been loaded in a session using {@link
+ * GeckoSessionSettings#VIEWPORT_MODE_MOBILE}. To improve readability, the font inflation logic
+ * will attempt to increase font sizes for the main text content of the page only.
+ *
+ * <p>The magnitude of font inflation applied depends on the {@link
+ * GeckoRuntimeSettings#setFontSizeFactor font size factor} currently in use.
+ *
+ * <p>Currently, any changes only take effect after a reload of the session.
+ *
+ * @param enabled A flag determining whether or not font inflation should be enabled.
+ * @return This GeckoRuntimeSettings instance.
+ */
+ public @NonNull GeckoRuntimeSettings setFontInflationEnabled(final boolean enabled) {
+ final int minTwips = enabled ? Math.round(FONT_INFLATION_BASE_VALUE * getFontSizeFactor()) : 0;
+ mFontInflationMinTwips.commit(minTwips);
+ return this;
+ }
+
+ /**
+ * Get whether or not font inflation for non mobile-friendly pages is currently enabled.
+ *
+ * @return True if font inflation is enabled.
+ */
+ public boolean getFontInflationEnabled() {
+ return mFontInflationMinTwips.get() > 0;
+ }
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({COLOR_SCHEME_LIGHT, COLOR_SCHEME_DARK, COLOR_SCHEME_SYSTEM})
+ public @interface ColorScheme {}
+
+ /** A light theme for web content is preferred. */
+ public static final int COLOR_SCHEME_LIGHT = 0;
+
+ /** A dark theme for web content is preferred. */
+ public static final int COLOR_SCHEME_DARK = 1;
+
+ /** The preferred color scheme will be based on system settings. */
+ public static final int COLOR_SCHEME_SYSTEM = -1;
+
+ /**
+ * Gets the preferred color scheme override for web content.
+ *
+ * @return One of the {@link GeckoRuntimeSettings#COLOR_SCHEME_LIGHT COLOR_SCHEME_*} constants.
+ */
+ public @ColorScheme int getPreferredColorScheme() {
+ return mPreferredColorScheme;
+ }
+
+ /**
+ * Sets the preferred color scheme override for web content.
+ *
+ * @param scheme The preferred color scheme. Must be one of the {@link
+ * GeckoRuntimeSettings#COLOR_SCHEME_LIGHT COLOR_SCHEME_*} constants.
+ * @return This GeckoRuntimeSettings instance.
+ */
+ public @NonNull GeckoRuntimeSettings setPreferredColorScheme(final @ColorScheme int scheme) {
+ if (mPreferredColorScheme != scheme) {
+ mPreferredColorScheme = scheme;
+ GeckoSystemStateListener.onDeviceChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Gets whether auto-zoom to editable fields is enabled.
+ *
+ * @return True if auto-zoom is enabled, false otherwise.
+ */
+ public boolean getInputAutoZoomEnabled() {
+ return mInputAutoZoom.get();
+ }
+
+ /**
+ * Set whether auto-zoom to editable fields should be enabled.
+ *
+ * @param flag True if auto-zoom should be enabled, false otherwise.
+ * @return This GeckoRuntimeSettings instance.
+ */
+ public @NonNull GeckoRuntimeSettings setInputAutoZoomEnabled(final boolean flag) {
+ mInputAutoZoom.commit(flag);
+ return this;
+ }
+
+ /**
+ * Gets whether double-tap zooming is enabled.
+ *
+ * @return True if double-tap zooming is enabled, false otherwise.
+ */
+ public boolean getDoubleTapZoomingEnabled() {
+ return mDoubleTapZooming.get();
+ }
+
+ /**
+ * Sets whether double tap zooming is enabled.
+ *
+ * @param flag true if double tap zooming should be enabled, false otherwise.
+ * @return This GeckoRuntimeSettings instance.
+ */
+ public @NonNull GeckoRuntimeSettings setDoubleTapZoomingEnabled(final boolean flag) {
+ mDoubleTapZooming.commit(flag);
+ return this;
+ }
+
+ /**
+ * Gets the current WebGL MSAA level.
+ *
+ * @return number of MSAA samples, 0 if MSAA is disabled.
+ */
+ public int getGlMsaaLevel() {
+ return mGlMsaaLevel.get();
+ }
+
+ /**
+ * Sets the WebGL MSAA level.
+ *
+ * @param level number of MSAA samples, 0 if MSAA should be disabled.
+ * @return This GeckoRuntimeSettings instance.
+ */
+ public @NonNull GeckoRuntimeSettings setGlMsaaLevel(final int level) {
+ mGlMsaaLevel.commit(level);
+ return this;
+ }
+
+ @SuppressWarnings("checkstyle:javadocmethod")
+ public @Nullable RuntimeTelemetry.Delegate getTelemetryDelegate() {
+ return mTelemetryProxy.getDelegate();
+ }
+
+ /**
+ * Gets whether about:config is enabled or not.
+ *
+ * @return True if about:config is enabled, false otherwise.
+ */
+ public boolean getAboutConfigEnabled() {
+ return mAboutConfig.get();
+ }
+
+ /**
+ * Sets whether or not about:config should be enabled. This is a page that allows users to
+ * directly modify Gecko preferences. Modification of some preferences may cause the app to break
+ * in unpredictable ways -- crashes, performance issues, security vulnerabilities, etc.
+ *
+ * @param flag True if about:config should be enabled, false otherwise.
+ * @return This GeckoRuntimeSettings instance.
+ */
+ public @NonNull GeckoRuntimeSettings setAboutConfigEnabled(final boolean flag) {
+ mAboutConfig.commit(flag);
+ return this;
+ }
+
+ /**
+ * Gets whether or not force user scalable zooming should be enabled or not.
+ *
+ * @return True if force user scalable zooming should be enabled, false otherwise.
+ */
+ public boolean getForceUserScalableEnabled() {
+ return mForceUserScalable.get();
+ }
+
+ /**
+ * Sets whether or not pinch-zooming should be enabled when <code>user-scalable=no</code> is set
+ * on the viewport.
+ *
+ * @param flag True if force user scalable zooming should be enabled, false otherwise.
+ * @return This GeckoRuntimeSettings instance.
+ */
+ public @NonNull GeckoRuntimeSettings setForceUserScalableEnabled(final boolean flag) {
+ mForceUserScalable.commit(flag);
+ return this;
+ }
+
+ /**
+ * Get whether login form autofill is enabled.
+ *
+ * @return True if login autofill is enabled.
+ */
+ public boolean getLoginAutofillEnabled() {
+ return mAutofillLogins.get();
+ }
+
+ /**
+ * Set whether login forms should be filled automatically if only one viable candidate is provided
+ * via {@link Autocomplete.StorageDelegate#onLoginFetch onLoginFetch}.
+ *
+ * @param enabled A flag determining whether login autofill should be enabled.
+ * @return The builder instance.
+ */
+ public @NonNull GeckoRuntimeSettings setLoginAutofillEnabled(final boolean enabled) {
+ mAutofillLogins.commit(enabled);
+ return this;
+ }
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({ALLOW_ALL, HTTPS_ONLY_PRIVATE, HTTPS_ONLY})
+ public @interface HttpsOnlyMode {}
+
+ /** Allow all insecure connections */
+ public static final int ALLOW_ALL = 0;
+
+ /** Allow insecure connections in normal browsing, but only HTTPS in private browsing. */
+ public static final int HTTPS_ONLY_PRIVATE = 1;
+
+ /** Only allow HTTPS connections. */
+ public static final int HTTPS_ONLY = 2;
+
+ /**
+ * Get whether and where insecure (non-HTTPS) connections are allowed.
+ *
+ * @return One of the {@link GeckoRuntimeSettings#ALLOW_ALL HttpsOnlyMode} constants.
+ */
+ public @HttpsOnlyMode int getAllowInsecureConnections() {
+ final boolean httpsOnly = mHttpsOnly.get();
+ final boolean httpsOnlyPrivate = mHttpsOnlyPrivateMode.get();
+ if (httpsOnly) {
+ return HTTPS_ONLY;
+ } else if (httpsOnlyPrivate) {
+ return HTTPS_ONLY_PRIVATE;
+ }
+ return ALLOW_ALL;
+ }
+
+ /**
+ * Set whether and where insecure (non-HTTPS) connections are allowed.
+ *
+ * @param level One of the {@link GeckoRuntimeSettings#ALLOW_ALL HttpsOnlyMode} constants.
+ * @return This GeckoRuntimeSettings instance.
+ */
+ public @NonNull GeckoRuntimeSettings setAllowInsecureConnections(final @HttpsOnlyMode int level) {
+ switch (level) {
+ case ALLOW_ALL:
+ mHttpsOnly.commit(false);
+ mHttpsOnlyPrivateMode.commit(false);
+ break;
+ case HTTPS_ONLY_PRIVATE:
+ mHttpsOnly.commit(false);
+ mHttpsOnlyPrivateMode.commit(true);
+ break;
+ case HTTPS_ONLY:
+ mHttpsOnly.commit(true);
+ mHttpsOnlyPrivateMode.commit(false);
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid setting for setAllowInsecureConnections");
+ }
+ return this;
+ }
+
+ // For internal use only
+ /* protected */ @NonNull
+ GeckoRuntimeSettings setProcessCount(final int processCount) {
+ mProcessCount.commit(processCount);
+ return this;
+ }
+
+ @Override // Parcelable
+ public void writeToParcel(final Parcel out, final int flags) {
+ super.writeToParcel(out, flags);
+
+ out.writeStringArray(mArgs);
+ mExtras.writeToParcel(out, flags);
+ ParcelableUtils.writeBoolean(out, mForceEnableAccessibility);
+ ParcelableUtils.writeBoolean(out, mDebugPause);
+ ParcelableUtils.writeBoolean(out, mUseMaxScreenDepth);
+ out.writeFloat(mDisplayDensityOverride);
+ out.writeInt(mDisplayDpiOverride);
+ out.writeInt(mScreenWidthOverride);
+ out.writeInt(mScreenHeightOverride);
+ out.writeString(mCrashHandler != null ? mCrashHandler.getName() : null);
+ out.writeStringArray(mRequestedLocales);
+ out.writeString(mConfigFilePath);
+ }
+
+ // AIDL code may call readFromParcel even though it's not part of Parcelable.
+ @SuppressWarnings("checkstyle:javadocmethod")
+ public void readFromParcel(final @NonNull Parcel source) {
+ super.readFromParcel(source);
+
+ mArgs = source.createStringArray();
+ mExtras.readFromParcel(source);
+ mForceEnableAccessibility = ParcelableUtils.readBoolean(source);
+ mDebugPause = ParcelableUtils.readBoolean(source);
+ mUseMaxScreenDepth = ParcelableUtils.readBoolean(source);
+ mDisplayDensityOverride = source.readFloat();
+ mDisplayDpiOverride = source.readInt();
+ mScreenWidthOverride = source.readInt();
+ mScreenHeightOverride = source.readInt();
+
+ final String crashHandlerName = source.readString();
+ if (crashHandlerName != null) {
+ try {
+ @SuppressWarnings("unchecked")
+ final Class<? extends Service> handler =
+ (Class<? extends Service>) Class.forName(crashHandlerName);
+
+ mCrashHandler = handler;
+ } catch (final ClassNotFoundException e) {
+ }
+ }
+
+ mRequestedLocales = source.createStringArray();
+ mConfigFilePath = source.readString();
+ }
+
+ public static final Parcelable.Creator<GeckoRuntimeSettings> CREATOR =
+ new Parcelable.Creator<GeckoRuntimeSettings>() {
+ @Override
+ public GeckoRuntimeSettings createFromParcel(final Parcel in) {
+ final GeckoRuntimeSettings settings = new GeckoRuntimeSettings();
+ settings.readFromParcel(in);
+ return settings;
+ }
+
+ @Override
+ public GeckoRuntimeSettings[] newArray(final int size) {
+ return new GeckoRuntimeSettings[size];
+ }
+ };
+}