Bug 1515728 - [1.5] Add support for nested runtime settings. r=snorp,geckoview-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D15130

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Eugen Sawin 2019-01-29 15:07:12 +00:00
Родитель 46a7de5091
Коммит 540d235551
5 изменённых файлов: 369 добавлений и 184 удалений

Просмотреть файл

@ -154,7 +154,7 @@ package org.mozilla.geckoview {
method @android.support.annotation.UiThread public void onShutdown();
}
@android.support.annotation.AnyThread public final class GeckoRuntimeSettings implements android.os.Parcelable {
@android.support.annotation.AnyThread public final class GeckoRuntimeSettings extends org.mozilla.geckoview.RuntimeSettings {
method @android.support.annotation.NonNull public java.lang.String[] getArguments();
method public boolean getBlockMalware();
method public boolean getBlockPhishing();
@ -169,12 +169,12 @@ package org.mozilla.geckoview {
method @android.support.annotation.Nullable public java.lang.String[] getLocales();
method public boolean getPauseForDebuggerEnabled();
method public boolean getRemoteDebuggingEnabled();
method @android.support.annotation.Nullable public org.mozilla.geckoview.GeckoRuntime getRuntime();
method @android.support.annotation.Nullable public android.graphics.Rect getScreenSizeOverride();
method public int getTrackingProtectionCategories();
method public boolean getUseContentProcessHint();
method public boolean getUseMaxScreenDepth();
method public boolean getWebFontsEnabled();
method public void readFromParcel(@android.support.annotation.NonNull android.os.Parcel);
method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings setBlockMalware(boolean);
method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings setBlockPhishing(boolean);
method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings setConsoleOutputEnabled(boolean);
@ -196,13 +196,11 @@ package org.mozilla.geckoview {
field public static final android.os.Parcelable.Creator<org.mozilla.geckoview.GeckoRuntimeSettings> CREATOR;
}
@android.support.annotation.AnyThread public static final class GeckoRuntimeSettings.Builder {
@android.support.annotation.AnyThread public static final class GeckoRuntimeSettings.Builder extends org.mozilla.geckoview.RuntimeSettings.Builder<Settings extends org.mozilla.geckoview.RuntimeSettings> {
ctor public Builder();
ctor public Builder(org.mozilla.geckoview.GeckoRuntimeSettings);
method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder arguments(@android.support.annotation.NonNull java.lang.String[]);
method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder blockMalware(boolean);
method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder blockPhishing(boolean);
method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings build();
method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder consoleOutput(boolean);
method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder cookieBehavior(int);
method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder cookieLifetime(int);
@ -219,6 +217,7 @@ package org.mozilla.geckoview {
method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder useContentProcessHint(boolean);
method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder useMaxScreenDepth(boolean);
method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder webFontsEnabled(boolean);
method @android.support.annotation.NonNull protected org.mozilla.geckoview.GeckoRuntimeSettings newSettings(org.mozilla.geckoview.GeckoRuntimeSettings);
}
public class GeckoSession implements android.os.Parcelable {
@ -818,6 +817,20 @@ package org.mozilla.geckoview {
method public void setScrollFactor(float);
}
public abstract class RuntimeSettings implements android.os.Parcelable {
ctor protected RuntimeSettings();
ctor protected RuntimeSettings(@android.support.annotation.Nullable org.mozilla.geckoview.RuntimeSettings);
method @android.support.annotation.AnyThread public void readFromParcel(@android.support.annotation.NonNull android.os.Parcel);
method @android.support.annotation.AnyThread protected void updatePrefs(@android.support.annotation.NonNull org.mozilla.geckoview.RuntimeSettings);
}
public abstract static class RuntimeSettings.Builder<Settings extends org.mozilla.geckoview.RuntimeSettings> {
ctor public Builder();
method @android.support.annotation.AnyThread @android.support.annotation.NonNull public Settings build();
method @android.support.annotation.AnyThread @android.support.annotation.NonNull protected Settings getSettings();
method @android.support.annotation.AnyThread @android.support.annotation.NonNull protected abstract Settings newSettings(@android.support.annotation.Nullable Settings);
}
public final class RuntimeTelemetry {
method @android.support.annotation.AnyThread @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoResult<org.mozilla.gecko.util.GeckoBundle> getSnapshots(boolean);
}

Просмотреть файл

@ -230,8 +230,8 @@ public final class GeckoRuntime implements Parcelable {
// Bug 1453062 -- the EventDispatcher should really live here (or in GeckoThread)
EventDispatcher.getInstance().registerUiThreadListener(mEventListener, "Gecko:Exited");
mSettings.runtime = this;
mSettings.flush();
// Attach and commit settings.
mSettings.attachTo(this);
// Initialize the system ClipboardManager by accessing it on the main thread.
GeckoAppShell.getApplicationContext().getSystemService(Context.CLIPBOARD_SERVICE);

Просмотреть файл

@ -8,8 +8,6 @@ package org.mozilla.geckoview;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
import java.util.Map;
import android.app.Service;
import android.graphics.Rect;
@ -20,37 +18,23 @@ import android.support.annotation.AnyThread;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.util.ArrayMap;
import org.mozilla.gecko.EventDispatcher;
import org.mozilla.gecko.util.GeckoBundle;
import org.mozilla.geckoview.GeckoSession.TrackingProtectionDelegate;
@AnyThread
public final class GeckoRuntimeSettings implements Parcelable {
public final class GeckoRuntimeSettings extends RuntimeSettings {
/**
* Settings builder used to construct the settings object.
*/
@AnyThread
public static final class Builder {
private final GeckoRuntimeSettings mSettings;
public Builder() {
mSettings = new GeckoRuntimeSettings();
}
public Builder(final GeckoRuntimeSettings settings) {
mSettings = new GeckoRuntimeSettings(settings);
}
/**
* Finalize and return the settings.
*
* @return The constructed settings.
*/
public @NonNull GeckoRuntimeSettings build() {
return new GeckoRuntimeSettings(mSettings);
public static final class Builder
extends RuntimeSettings.Builder<GeckoRuntimeSettings> {
@Override
protected @NonNull GeckoRuntimeSettings newSettings(
final GeckoRuntimeSettings settings) {
return new GeckoRuntimeSettings(settings);
}
/**
@ -62,7 +46,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
*/
public @NonNull Builder useContentProcessHint(final boolean use) {
mSettings.mUseContentProcess = use;
getSettings().mUseContentProcess = use;
return this;
}
@ -76,7 +60,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
if (args == null) {
throw new IllegalArgumentException("Arguments must not be null");
}
mSettings.mArgs = args;
getSettings().mArgs = args;
return this;
}
@ -90,7 +74,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
if (extras == null) {
throw new IllegalArgumentException("Extras must not be null");
}
mSettings.mExtras = extras;
getSettings().mExtras = extras;
return this;
}
@ -102,7 +86,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
* @return This Builder instance.
*/
public @NonNull Builder javaScriptEnabled(final boolean flag) {
mSettings.mJavaScript.set(flag);
getSettings().mJavaScript.set(flag);
return this;
}
@ -113,7 +97,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
* @return This Builder instance.
*/
public @NonNull Builder remoteDebuggingEnabled(final boolean enabled) {
mSettings.mRemoteDebugging.set(enabled);
getSettings().mRemoteDebugging.set(enabled);
return this;
}
@ -125,7 +109,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
* @return This Builder instance.
*/
public @NonNull Builder webFontsEnabled(final boolean flag) {
mSettings.mWebFonts.set(flag ? 1 : 0);
getSettings().mWebFonts.set(flag ? 1 : 0);
return this;
}
@ -138,7 +122,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
* @return This Builder.
*/
public @NonNull Builder pauseForDebugger(boolean enabled) {
mSettings.mDebugPause = enabled;
getSettings().mDebugPause = enabled;
return this;
}
/**
@ -152,7 +136,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
* @return This Builder.
*/
public @NonNull Builder useMaxScreenDepth(boolean enable) {
mSettings.mUseMaxScreenDepth = enable;
getSettings().mUseMaxScreenDepth = enable;
return this;
}
@ -164,7 +148,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
* @return The Builder instance.
*/
public @NonNull Builder cookieBehavior(@CookieBehavior int behavior) {
mSettings.mCookieBehavior.set(behavior);
getSettings().mCookieBehavior.set(behavior);
return this;
}
@ -176,7 +160,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
* @return The Builder instance.
*/
public @NonNull Builder cookieLifetime(@CookieLifetime int lifetime) {
mSettings.mCookieLifetime.set(lifetime);
getSettings().mCookieLifetime.set(lifetime);
return this;
}
@ -190,7 +174,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
**/
public @NonNull Builder trackingProtectionCategories(
@TrackingProtectionDelegate.Category int categories) {
mSettings.mTrackingProtection
getSettings().mTrackingProtection
.set(TrackingProtection.buildPrefValue(categories));
return this;
}
@ -206,7 +190,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
* @return The builder instance.
*/
public @NonNull Builder consoleOutput(boolean enabled) {
mSettings.mConsoleOutput.set(enabled);
getSettings().mConsoleOutput.set(enabled);
return this;
}
@ -217,7 +201,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
* @return The builder instance.
*/
public @NonNull Builder displayDensityOverride(float density) {
mSettings.mDisplayDensityOverride = density;
getSettings().mDisplayDensityOverride = density;
return this;
}
@ -232,7 +216,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
* @return The builder instance.
*/
public @NonNull Builder blockMalware(boolean enabled) {
mSettings.mSafebrowsingMalware.set(enabled);
getSettings().mSafebrowsingMalware.set(enabled);
return this;
}
@ -248,7 +232,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
* @return The builder instance.
*/
public @NonNull Builder blockPhishing(boolean enabled) {
mSettings.mSafebrowsingPhishing.set(enabled);
getSettings().mSafebrowsingPhishing.set(enabled);
return this;
}
@ -259,7 +243,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
* @return The builder instance.
*/
public @NonNull Builder displayDpiOverride(int dpi) {
mSettings.mDisplayDpiOverride = dpi;
getSettings().mDisplayDpiOverride = dpi;
return this;
}
@ -271,8 +255,8 @@ public final class GeckoRuntimeSettings implements Parcelable {
* @return The builder instance.
*/
public @NonNull Builder screenSizeOverride(int width, int height) {
mSettings.mScreenWidthOverride = width;
mSettings.mScreenHeightOverride = height;
getSettings().mScreenWidthOverride = width;
getSettings().mScreenHeightOverride = height;
return this;
}
@ -310,7 +294,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
* @see GeckoRuntime#ACTION_CRASHED
*/
public @NonNull Builder crashHandler(final Class<? extends Service> handler) {
mSettings.mCrashHandler = handler;
getSettings().mCrashHandler = handler;
return this;
}
@ -321,88 +305,38 @@ public final class GeckoRuntimeSettings implements Parcelable {
* @return The builder instance.
*/
public @NonNull Builder locales(String[] requestedLocales) {
mSettings.mRequestedLocales = requestedLocales;
getSettings().mRequestedLocales = requestedLocales;
return this;
}
}
/* package */ GeckoRuntime runtime;
private GeckoRuntime mRuntime;
/* package */ boolean mUseContentProcess;
/* package */ String[] mArgs;
/* package */ Bundle mExtras;
/* package */ int prefCount;
private class Pref<T> {
public final String name;
public final T defaultValue;
private T mValue;
private boolean mIsSet;
public Pref(final String name, final T defaultValue) {
GeckoRuntimeSettings.this.prefCount++;
this.name = name;
this.defaultValue = defaultValue;
mValue = defaultValue;
}
public void set(T newValue) {
mValue = newValue;
mIsSet = true;
// There is a flush() in GeckoRuntimeSettings, so be explicit.
this.flush();
}
public T get() {
return mValue;
}
private void flush() {
final GeckoRuntime runtime = GeckoRuntimeSettings.this.runtime;
if (runtime != null) {
final GeckoBundle prefs = new GeckoBundle(1);
intoBundle(prefs);
runtime.setDefaultPrefs(prefs);
}
}
public void intoBundle(final GeckoBundle bundle) {
final T value = mIsSet ? mValue : defaultValue;
if (value instanceof String) {
bundle.putString(name, (String)value);
} else if (value instanceof Integer) {
bundle.putInt(name, (Integer)value);
} else if (value instanceof Boolean) {
bundle.putBoolean(name, (Boolean)value);
} else {
throw new UnsupportedOperationException("Unhandled pref type for " + name);
}
}
}
/* package */ Pref<Boolean> mJavaScript = new Pref<Boolean>(
/* package */ final Pref<Boolean> mJavaScript = new Pref<Boolean>(
"javascript.enabled", true);
/* package */ Pref<Boolean> mRemoteDebugging = new Pref<Boolean>(
/* package */ final Pref<Boolean> mRemoteDebugging = new Pref<Boolean>(
"devtools.debugger.remote-enabled", false);
/* package */ Pref<Integer> mWebFonts = new Pref<Integer>(
/* package */ final Pref<Integer> mWebFonts = new Pref<Integer>(
"browser.display.use_document_fonts", 1);
/* package */ Pref<Integer> mCookieBehavior = new Pref<Integer>(
/* package */ final Pref<Integer> mCookieBehavior = new Pref<Integer>(
"network.cookie.cookieBehavior", COOKIE_ACCEPT_ALL);
/* package */ Pref<Integer> mCookieLifetime = new Pref<Integer>(
/* package */ final Pref<Integer> mCookieLifetime = new Pref<Integer>(
"network.cookie.lifetimePolicy", COOKIE_LIFETIME_NORMAL);
/* package */ Pref<String> mTrackingProtection = new Pref<String>(
/* package */ final Pref<String> mTrackingProtection = new Pref<String>(
"urlclassifier.trackingTable",
TrackingProtection.buildPrefValue(
TrackingProtectionDelegate.CATEGORY_TEST |
TrackingProtectionDelegate.CATEGORY_ANALYTIC |
TrackingProtectionDelegate.CATEGORY_SOCIAL |
TrackingProtectionDelegate.CATEGORY_AD));
/* package */ Pref<Boolean> mConsoleOutput = new Pref<Boolean>(
/* package */ final Pref<Boolean> mConsoleOutput = new Pref<Boolean>(
"geckoview.console.enabled", false);
/* package */ Pref<Boolean> mSafebrowsingMalware = new Pref<Boolean>(
/* package */ final Pref<Boolean> mSafebrowsingMalware = new Pref<Boolean>(
"browser.safebrowsing.malware.enabled", true);
/* package */ Pref<Boolean> mSafebrowsingPhishing = new Pref<Boolean>(
/* package */ final Pref<Boolean> mSafebrowsingPhishing = new Pref<Boolean>(
"browser.safebrowsing.phishing.enabled", true);
/* package */ boolean mDebugPause;
@ -414,20 +348,26 @@ public final class GeckoRuntimeSettings implements Parcelable {
/* package */ Class<? extends Service> mCrashHandler;
/* package */ String[] mRequestedLocales;
private final Pref<?>[] mPrefs = new Pref<?>[] {
mCookieBehavior, mCookieLifetime, mConsoleOutput,
mJavaScript, mRemoteDebugging, mSafebrowsingMalware,
mSafebrowsingPhishing, mTrackingProtection, mWebFonts,
};
/**
* 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();
}
@Override // RuntimeSettings
public @Nullable GeckoRuntime getRuntime() {
return mRuntime;
}
/* package */ GeckoRuntimeSettings() {
this(null);
}
/* package */ GeckoRuntimeSettings(final @Nullable GeckoRuntimeSettings settings) {
if (BuildConfig.DEBUG && prefCount != mPrefs.length) {
throw new AssertionError("Add new pref to prefs list");
}
super(/* parent */ null);
if (settings == null) {
mArgs = new String[0];
@ -435,20 +375,16 @@ public final class GeckoRuntimeSettings implements Parcelable {
return;
}
updateSettings(settings);
}
private void updateSettings(final @NonNull GeckoRuntimeSettings settings) {
updatePrefs(settings);
mUseContentProcess = settings.getUseContentProcessHint();
mArgs = settings.getArguments().clone();
mExtras = new Bundle(settings.getExtras());
for (int i = 0; i < mPrefs.length; i++) {
if (!settings.mPrefs[i].mIsSet) {
continue;
}
// We know this is safe.
@SuppressWarnings("unchecked")
final Pref<Object> uncheckedPref = (Pref<Object>) mPrefs[i];
uncheckedPref.set(settings.mPrefs[i].get());
}
mDebugPause = settings.mDebugPause;
mUseMaxScreenDepth = settings.mUseMaxScreenDepth;
mDisplayDensityOverride = settings.mDisplayDensityOverride;
@ -459,32 +395,9 @@ public final class GeckoRuntimeSettings implements Parcelable {
mRequestedLocales = settings.mRequestedLocales;
}
/* package */ Map<String, Object> getPrefsMap() {
final ArrayMap<String, Object> prefs = new ArrayMap<>(mPrefs.length);
for (final Pref<?> pref : mPrefs) {
prefs.put(pref.name, pref.get());
}
return Collections.unmodifiableMap(prefs);
}
/* package */ void flush() {
flushLocales();
// Prefs are flushed individually when they are set, and
// initial values are handled by GeckoRuntime itself.
// We may have user prefs due to previous versions of
// this class operating differently, though, so we'll
// send a message to clear any user prefs that may have
// been set on the prefs we manage.
final String[] names = new String[mPrefs.length];
for (int i = 0; i < mPrefs.length; i++) {
names[i] = mPrefs[i].name;
}
final GeckoBundle data = new GeckoBundle(1);
data.putStringArray("names", names);
EventDispatcher.getInstance().dispatch("GeckoView:ResetUserPrefs", data);
/* package */ void commit() {
commitLocales();
commitResetPrefs();
}
/**
@ -530,7 +443,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
* @return This GeckoRuntimeSettings instance.
*/
public @NonNull GeckoRuntimeSettings setJavaScriptEnabled(final boolean flag) {
mJavaScript.set(flag);
mJavaScript.commit(flag);
return this;
}
@ -550,7 +463,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
* @return This GeckoRuntimeSettings instance.
*/
public @NonNull GeckoRuntimeSettings setRemoteDebuggingEnabled(final boolean enabled) {
mRemoteDebugging.set(enabled);
mRemoteDebugging.commit(enabled);
return this;
}
@ -570,7 +483,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
* @return This GeckoRuntimeSettings instance.
*/
public @NonNull GeckoRuntimeSettings setWebFontsEnabled(final boolean flag) {
mWebFonts.set(flag ? 1 : 0);
mWebFonts.commit(flag ? 1 : 0);
return this;
}
@ -645,10 +558,10 @@ public final class GeckoRuntimeSettings implements Parcelable {
*/
public void setLocales(@Nullable String[] requestedLocales) {
mRequestedLocales = requestedLocales;
flushLocales();
commitLocales();
}
private void flushLocales() {
private void commitLocales() {
if (mRequestedLocales == null) {
return;
}
@ -707,7 +620,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
*/
public @NonNull GeckoRuntimeSettings setCookieBehavior(
@CookieBehavior int behavior) {
mCookieBehavior.set(behavior);
mCookieBehavior.commit(behavior);
return this;
}
@ -749,7 +662,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
*/
public @NonNull GeckoRuntimeSettings setCookieLifetime(
@CookieLifetime int lifetime) {
mCookieLifetime.set(lifetime);
mCookieLifetime.commit(lifetime);
return this;
}
@ -774,7 +687,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
**/
public @NonNull GeckoRuntimeSettings setTrackingProtectionCategories(
@TrackingProtectionDelegate.Category int categories) {
mTrackingProtection.set(TrackingProtection.buildPrefValue(categories));
mTrackingProtection.commit(TrackingProtection.buildPrefValue(categories));
return this;
}
@ -790,7 +703,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
*/
public @NonNull GeckoRuntimeSettings setConsoleOutputEnabled(boolean enabled) {
mConsoleOutput.set(enabled);
mConsoleOutput.commit(enabled);
return this;
}
@ -814,7 +727,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
* @return The GeckoRuntimeSettings instance.
*/
public @NonNull GeckoRuntimeSettings setBlockMalware(boolean enabled) {
mSafebrowsingMalware.set(enabled);
mSafebrowsingMalware.commit(enabled);
return this;
}
@ -838,7 +751,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
* @return The GeckoRuntimeSettings instance.
*/
public @NonNull GeckoRuntimeSettings setBlockPhishing(boolean enabled) {
mSafebrowsingPhishing.set(enabled);
mSafebrowsingPhishing.commit(enabled);
return this;
}
@ -851,21 +764,13 @@ public final class GeckoRuntimeSettings implements Parcelable {
return mSafebrowsingPhishing.get();
}
@Override // Parcelable
public int describeContents() {
return 0;
}
@Override // Parcelable
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
ParcelableUtils.writeBoolean(out, mUseContentProcess);
out.writeStringArray(mArgs);
mExtras.writeToParcel(out, flags);
for (final Pref<?> pref : mPrefs) {
out.writeValue(pref.get());
}
ParcelableUtils.writeBoolean(out, mDebugPause);
ParcelableUtils.writeBoolean(out, mUseMaxScreenDepth);
out.writeFloat(mDisplayDensityOverride);
@ -878,17 +783,11 @@ public final class GeckoRuntimeSettings implements Parcelable {
// AIDL code may call readFromParcel even though it's not part of Parcelable.
public void readFromParcel(final @NonNull Parcel source) {
super.readFromParcel(source);
mUseContentProcess = ParcelableUtils.readBoolean(source);
mArgs = source.createStringArray();
mExtras.readFromParcel(source);
for (final Pref<?> pref : mPrefs) {
// We know this is safe.
@SuppressWarnings("unchecked")
final Pref<Object> uncheckedPref = (Pref<Object>) pref;
uncheckedPref.set(source.readValue(getClass().getClassLoader()));
}
mDebugPause = ParcelableUtils.readBoolean(source);
mUseMaxScreenDepth = ParcelableUtils.readBoolean(source);
mDisplayDensityOverride = source.readFloat();

Просмотреть файл

@ -0,0 +1,271 @@
/* -*- 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 java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.util.ArrayMap;
import android.support.annotation.AnyThread;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.mozilla.gecko.EventDispatcher;
import org.mozilla.gecko.util.GeckoBundle;
/**
* Base class for (nested) runtime settings.
*
* Handles pref-based settings.
* Please extend this class when adding nested settings for
* GeckoRuntimeSettings.
*/
public abstract class RuntimeSettings implements Parcelable {
private static final String LOGTAG = "RuntimeSettings";
/**
* Base class for (nested) runtime settings builders.
*
* Please extend this class when adding nested settings builders for
* GeckoRuntimeSettings.
*/
public abstract static class Builder<Settings extends RuntimeSettings> {
private final Settings mSettings;
public Builder() {
mSettings = newSettings(null);
}
/**
* Finalize and return the settings.
*
* @return The constructed settings.
*/
@AnyThread
public @NonNull Settings build() {
return newSettings(mSettings);
}
@AnyThread
protected @NonNull Settings getSettings() {
return mSettings;
}
/**
* Create a default or copy settings object.
*
* @param settings Settings object to copy, null for default settings.
* @return The constructed settings object.
*/
@AnyThread
protected abstract @NonNull Settings newSettings(
final @Nullable Settings settings);
}
/**
* Used to handle pref-based settings.
*/
/* package */ class Pref<T> {
public final String name;
public final T defaultValue;
private T mValue;
private boolean mIsSet;
public Pref(@NonNull final String name, final T defaultValue) {
this.name = name;
this.defaultValue = defaultValue;
mValue = defaultValue;
RuntimeSettings.this.addPref(this);
}
public void set(T newValue) {
mValue = newValue;
mIsSet = true;
}
public void commit(final T newValue) {
set(newValue);
commit();
}
public void commit() {
final GeckoRuntime runtime = RuntimeSettings.this.getRuntime();
if (runtime == null) {
return;
}
final GeckoBundle prefs = new GeckoBundle(1);
addToBundle(prefs);
runtime.setDefaultPrefs(prefs);
}
public T get() {
return mValue;
}
public boolean isSet() {
return mIsSet;
}
public void reset() {
mValue = defaultValue;
mIsSet = false;
}
private void addToBundle(final GeckoBundle bundle) {
final T value = mIsSet ? mValue : defaultValue;
if (value instanceof String) {
bundle.putString(name, (String)value);
} else if (value instanceof Integer) {
bundle.putInt(name, (Integer)value);
} else if (value instanceof Boolean) {
bundle.putBoolean(name, (Boolean)value);
} else {
throw new UnsupportedOperationException("Unhandled pref type for " + name);
}
}
}
private RuntimeSettings mParent;
private final ArrayList<RuntimeSettings> mChildren;
private final ArrayList<Pref<?>> mPrefs;
protected RuntimeSettings() {
this(null /* parent */);
}
/**
* Create settings object.
*
* @param parent The parent settings, specify in case of nested settings.
*/
protected RuntimeSettings(final @Nullable RuntimeSettings parent) {
mPrefs = new ArrayList<Pref<?>>();
mChildren = new ArrayList<RuntimeSettings>();
setParent(parent);
}
/**
* Update the prefs based on the provided settings.
*
* @param settings Copy from this settings.
*/
@AnyThread
protected void updatePrefs(final @NonNull RuntimeSettings settings) {
if (mPrefs.size() != settings.mPrefs.size()) {
throw new IllegalArgumentException("Settings must be compatible");
}
for (int i = 0; i < mPrefs.size(); ++i) {
if (!mPrefs.get(i).name.equals(settings.mPrefs.get(i).name)) {
throw new IllegalArgumentException("Settings must be compatible");
}
if (!settings.mPrefs.get(i).isSet()) {
continue;
}
// We know it is safe.
@SuppressWarnings("unchecked")
final Pref<Object> uncheckedPref = (Pref<Object>) mPrefs.get(i);
uncheckedPref.commit(settings.mPrefs.get(i).get());
}
}
/* package */ @Nullable GeckoRuntime getRuntime() {
if (mParent != null) {
return mParent.getRuntime();
}
return null;
}
private void setParent(final @Nullable RuntimeSettings parent) {
mParent = parent;
if (mParent != null) {
mParent.addChild(this);
}
}
private void addChild(final @NonNull RuntimeSettings child) {
mChildren.add(child);
}
/* pacakge */ void addPref(final Pref<?> pref) {
mPrefs.add(pref);
}
/**
* Return a mapping of the prefs managed in this settings, including child
* settings.
*
* @return A key-value mapping of the prefs.
*/
/* package */ @NonNull Map<String, Object> getPrefsMap() {
final ArrayMap<String, Object> prefs = new ArrayMap<>();
for (final Pref<?> pref : mPrefs) {
prefs.put(pref.name, pref.get());
}
for (final RuntimeSettings child : mChildren) {
prefs.putAll(child.getPrefsMap());
}
return Collections.unmodifiableMap(prefs);
}
/**
* Reset the prefs managed by this settings and its children.
*
* The actual prefs values are set via {@link getPrefsMap} during
* initialization and via {@link Pref.commit} during runtime for individual
* prefs.
*/
/* package */ void commitResetPrefs() {
final ArrayList<String> names = new ArrayList<String>();
for (final Pref<?> pref : mPrefs) {
names.add(pref.name);
}
for (final RuntimeSettings child : mChildren) {
for (final Pref<?> pref : child.mPrefs) {
names.add(pref.name);
}
}
final GeckoBundle data = new GeckoBundle(1);
data.putStringArray("names", names);
EventDispatcher.getInstance().dispatch("GeckoView:ResetUserPrefs", data);
}
@Override // Parcelable
@AnyThread
public int describeContents() {
return 0;
}
@Override // Parcelable
@AnyThread
public void writeToParcel(Parcel out, int flags) {
for (final Pref<?> pref : mPrefs) {
out.writeValue(pref.get());
}
}
@AnyThread
// AIDL code may call readFromParcel even though it's not part of Parcelable.
public void readFromParcel(final @NonNull Parcel source) {
for (final Pref<?> pref : mPrefs) {
// We know this is safe.
@SuppressWarnings("unchecked")
final Pref<Object> uncheckedPref = (Pref<Object>) pref;
uncheckedPref.commit(source.readValue(getClass().getClassLoader()));
}
}
}

Просмотреть файл

@ -7,6 +7,8 @@ description: GeckoView API Changelog.
<h1> GeckoView API Changelog. </h1>
## v66
- Added `RuntimeSettings` base class to support nested settings.
- Added `baseUri` to [`ContentDelegate.ContextElement`][65.21] and changed
`linkUri` to absolute form.
@ -118,4 +120,4 @@ description: GeckoView API Changelog.
[65.24]: ../CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String-
[65.25]: ../GeckoResult.html
[api-version]: 8b68d674a0ddb2498df59e0cf8b2edad6f0b3a8e
[api-version]: 53ffb6141c90d561251dd831e9af1bd7197c3c75