зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1533385 - Make GeckoView read configuration options from filesystem. r=droeh
The configuration file format is YAML and looks like: ``` prefs: foo.bar.boolean: true foo.bar.string: "string" foo.bar.int: 500 env: MOZ_LOG: nsHttp:5 args: [--marionette] ``` By default, if the consuming App is debuggable, GeckoView will read configuration from `/data/local/tmp/$PACKAGE-geckoview-config.yaml` at startup. For consumers (including browsers) that want to allow the underlying GeckoView to be remote controlled in some way, the `GeckoRuntimeSettings.Builder.configFilePath()` method allows to avoid the default behaviour depending on the `android:debuggable` flag. For example, release versions of Firefox for Android will want to allow this configuration when appropriate App-level settings are toggled. The additional configuration is appended after any existing configuration methods, e.g., after anything specified using Intent argument extras or existing `GeckoRuntimeSettings.Builder` methods. Differential Revision: https://phabricator.services.mozilla.com/D25885 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
817c9ec8c9
Коммит
b03aa4ed38
|
@ -170,6 +170,9 @@
|
|||
-dontwarn java.lang.management.**
|
||||
-dontwarn javax.management.**
|
||||
|
||||
# Don't warn when classes referenced by, but not used at runtime by, SnakeYAML are missing.
|
||||
-dontwarn java.beans.**
|
||||
|
||||
-include "adjust-keeps.cfg"
|
||||
|
||||
-include "leakcanary-keeps.cfg"
|
||||
|
|
|
@ -211,6 +211,7 @@ package org.mozilla.geckoview {
|
|||
method @android.support.annotation.NonNull public java.lang.String[] getArguments();
|
||||
method public boolean getAutomaticFontSizeAdjustment();
|
||||
method public int getAutoplayDefault();
|
||||
method @android.support.annotation.Nullable public java.lang.String getConfigFilePath();
|
||||
method public boolean getConsoleOutputEnabled();
|
||||
method @android.support.annotation.NonNull public org.mozilla.geckoview.ContentBlocking.Settings getContentBlocking();
|
||||
method @android.support.annotation.Nullable public java.lang.Class<?> getCrashHandler();
|
||||
|
@ -252,6 +253,7 @@ package org.mozilla.geckoview {
|
|||
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 automaticFontSizeAdjustment(boolean);
|
||||
method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder autoplayDefault(int);
|
||||
method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder configFilePath(@android.support.annotation.Nullable java.lang.String);
|
||||
method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder consoleOutput(boolean);
|
||||
method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder contentBlocking(@android.support.annotation.NonNull org.mozilla.geckoview.ContentBlocking.Settings);
|
||||
method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder crashHandler(java.lang.Class<?>);
|
||||
|
|
|
@ -216,6 +216,7 @@ tasks.withType(Javadoc) {
|
|||
dependencies {
|
||||
implementation "com.android.support:support-v4:$support_library_version"
|
||||
implementation "com.android.support:palette-v7:$support_library_version"
|
||||
implementation "org.yaml:snakeyaml:1.24"
|
||||
|
||||
testImplementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
testImplementation 'junit:junit:4.12'
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* 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.gecko.util;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
|
||||
import org.mozilla.gecko.GeckoThread;
|
||||
import org.yaml.snakeyaml.TypeDescription;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
import org.yaml.snakeyaml.constructor.Constructor;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class DebugConfig {
|
||||
private static final String LOGTAG = "GeckoDebugConfig";
|
||||
|
||||
protected Map<String, Object> prefs;
|
||||
protected Map<String, String> env;
|
||||
protected List<String> args;
|
||||
|
||||
public static @NonNull DebugConfig fromFile(final @NonNull File configFile) throws FileNotFoundException {
|
||||
final Constructor constructor = new Constructor(DebugConfig.class);
|
||||
final TypeDescription description = new TypeDescription(DebugConfig.class);
|
||||
description.putMapPropertyType("prefs", String.class, Object.class);
|
||||
description.putMapPropertyType("env", String.class, String.class);
|
||||
description.putListPropertyType("args", String.class);
|
||||
|
||||
final Yaml yaml = new Yaml(constructor);
|
||||
yaml.addTypeDescription(description);
|
||||
|
||||
final FileInputStream fileInputStream = new FileInputStream(configFile);
|
||||
try {
|
||||
return yaml.load(fileInputStream);
|
||||
} finally {
|
||||
IOUtils.safeStreamClose(fileInputStream);
|
||||
}
|
||||
}
|
||||
|
||||
public void mergeIntoInitInfo(final @NonNull GeckoThread.InitInfo info) {
|
||||
if (env != null) {
|
||||
Log.d(LOGTAG, "Adding environment variables from debug config: " + env);
|
||||
|
||||
if (info.extras == null) {
|
||||
info.extras = new Bundle();
|
||||
}
|
||||
|
||||
int c = 0;
|
||||
while (info.extras.getString("env" + c) != null) {
|
||||
c += 1;
|
||||
}
|
||||
|
||||
for (final Map.Entry<String, String> entry : env.entrySet()) {
|
||||
info.extras.putString("env" + c, entry.getKey() + "=" + entry.getValue());
|
||||
c += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (args != null) {
|
||||
Log.d(LOGTAG, "Adding arguments from debug config: " + args);
|
||||
|
||||
final ArrayList<String> combinedArgs = new ArrayList<>();
|
||||
combinedArgs.addAll(Arrays.asList(info.args));
|
||||
combinedArgs.addAll(args);
|
||||
|
||||
info.args = combinedArgs.toArray(new String[combinedArgs.size()]);
|
||||
}
|
||||
|
||||
if (prefs != null) {
|
||||
Log.d(LOGTAG, "Adding prefs from debug config: " + prefs);
|
||||
|
||||
final Map<String, Object> combinedPrefs = new HashMap<>();
|
||||
combinedPrefs.putAll(info.prefs);
|
||||
combinedPrefs.putAll(prefs);
|
||||
info.prefs = Collections.unmodifiableMap(prefs);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,14 +8,15 @@ package org.mozilla.geckoview;
|
|||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Build;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.content.Context;
|
||||
import android.os.Process;
|
||||
import android.support.annotation.AnyThread;
|
||||
import android.support.annotation.NonNull;
|
||||
|
@ -25,21 +26,26 @@ import android.util.Log;
|
|||
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoSystemStateListener;
|
||||
import org.mozilla.gecko.GeckoScreenOrientation;
|
||||
import org.mozilla.gecko.GeckoSystemStateListener;
|
||||
import org.mozilla.gecko.GeckoThread;
|
||||
import org.mozilla.gecko.PrefsHelper;
|
||||
import org.mozilla.gecko.util.BundleEventListener;
|
||||
import org.mozilla.gecko.util.DebugConfig;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.yaml.snakeyaml.error.YAMLException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
public final class GeckoRuntime implements Parcelable {
|
||||
private static final String LOGTAG = "GeckoRuntime";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final String CONFIG_FILE_PATH_TEMPLATE = "/data/local/tmp/%s-geckoview-config.yaml";
|
||||
|
||||
/**
|
||||
* Intent action sent to the crash handler when a crash is encountered.
|
||||
* @see GeckoRuntimeSettings.Builder#crashHandler(Class)
|
||||
|
@ -215,6 +221,28 @@ public final class GeckoRuntime implements Parcelable {
|
|||
info.flags = flags;
|
||||
info.prefs = settings.getPrefsMap();
|
||||
|
||||
String configFilePath = settings.getConfigFilePath();
|
||||
if (configFilePath == null) {
|
||||
// Default to /data/local/tmp/$PACKAGE-geckoview-config.yaml if android:debuggable="true"
|
||||
// and to not read configuration from a file if android:debuggable="false".
|
||||
final ApplicationInfo applicationInfo = context.getApplicationInfo();
|
||||
final boolean isPackageDebuggable = (applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
|
||||
if (isPackageDebuggable) {
|
||||
configFilePath = String.format(CONFIG_FILE_PATH_TEMPLATE, applicationInfo.packageName);
|
||||
}
|
||||
}
|
||||
|
||||
if (configFilePath != null && !configFilePath.isEmpty()) {
|
||||
try {
|
||||
final DebugConfig debugConfig = DebugConfig.fromFile(new File(configFilePath));
|
||||
Log.i(LOGTAG, "Adding debug configuration from: " + configFilePath);
|
||||
debugConfig.mergeIntoInitInfo(info);
|
||||
} catch (YAMLException e) {
|
||||
Log.w(LOGTAG, "Failed to add debug configuration from: " + configFilePath, e);
|
||||
} catch (FileNotFoundException e) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!GeckoThread.init(info)) {
|
||||
Log.w(LOGTAG, "init failed (could not initiate GeckoThread)");
|
||||
return false;
|
||||
|
|
|
@ -77,6 +77,19 @@ public final class GeckoRuntimeSettings extends RuntimeSettings {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Path to configuration file from which GeckoView will read configuration options such as
|
||||
* Gecko process arguments, environment variables, and preferences.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
|
@ -330,6 +343,7 @@ public final class GeckoRuntimeSettings extends RuntimeSettings {
|
|||
/* package */ boolean mUseContentProcess;
|
||||
/* package */ String[] mArgs;
|
||||
/* package */ Bundle mExtras;
|
||||
/* package */ String mConfigFilePath;
|
||||
|
||||
/* package */ ContentBlocking.Settings mContentBlocking;
|
||||
|
||||
|
@ -412,6 +426,7 @@ public final class GeckoRuntimeSettings extends RuntimeSettings {
|
|||
mScreenHeightOverride = settings.mScreenHeightOverride;
|
||||
mCrashHandler = settings.mCrashHandler;
|
||||
mRequestedLocales = settings.mRequestedLocales;
|
||||
mConfigFilePath = settings.mConfigFilePath;
|
||||
}
|
||||
|
||||
/* package */ void commit() {
|
||||
|
@ -446,6 +461,18 @@ public final class GeckoRuntimeSettings extends RuntimeSettings {
|
|||
return mExtras;
|
||||
}
|
||||
|
||||
/**
|
||||
* Path to configuration file from which GeckoView will read configuration options such as
|
||||
* Gecko process arguments, environment variables, and preferences.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
|
@ -822,6 +849,7 @@ public final class GeckoRuntimeSettings extends RuntimeSettings {
|
|||
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.
|
||||
|
@ -851,6 +879,7 @@ public final class GeckoRuntimeSettings extends RuntimeSettings {
|
|||
}
|
||||
|
||||
mRequestedLocales = source.createStringArray();
|
||||
mConfigFilePath = source.readString();
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<GeckoRuntimeSettings> CREATOR
|
||||
|
|
|
@ -42,6 +42,13 @@ exclude: true
|
|||
|
||||
[68.9]: ../GeckoRuntimeSettings.html#setPreferredColorScheme-int-
|
||||
|
||||
- Added [`GeckoRuntimeSettings.Builder#configFilePath`][68.10] to set
|
||||
a path to a configuration file from which GeckoView will read
|
||||
configuration options such as Gecko process arguments, environment
|
||||
variables, and preferences.
|
||||
|
||||
[68.10]: ../GeckoRuntimeSettings.Builder.html#configFilePath-java.lang.String-
|
||||
|
||||
## v67
|
||||
- Added [`setAutomaticFontSizeAdjustment`][67.2] to
|
||||
[`GeckoRuntimeSettings`][67.3] for automatically adjusting font size settings
|
||||
|
@ -248,4 +255,4 @@ exclude: true
|
|||
[65.24]: ../CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String-
|
||||
[65.25]: ../GeckoResult.html
|
||||
|
||||
[api-version]: 053d9b4164690ff13996be9e7288dd183e2a1db4
|
||||
[api-version]: affe9cc5dc22f0700867a1ac7f9b55a033a4b88c
|
||||
|
|
Загрузка…
Ссылка в новой задаче