diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
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.java | 1314 |
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} > 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 <meta> + * 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} > 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 <meta> + * 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]; + } + }; +} |