Commit 0740e232 authored by Paul Miller's avatar Paul Miller Committed by Commit Bot

WebView: Log field trials when a dummy app is present

Create an empty "WebView Log Verbosifier" app. When installed, WebView
will log all registered field trials and their assigned groups, for QA
purposes. Check for the dummy app asynchronously, because PackageManager
is slow.

Skipping presubmit for LOG(INFO).

BUG=892870
NOPRESUBMIT=true

Change-Id: Ia4fee870aec84a60e9e70642405c5ff8b07da7cf
Reviewed-on: https://chromium-review.googlesource.com/c/1266611
Commit-Queue: Paul Miller <paulmiller@chromium.org>
Reviewed-by: default avatarAlexei Svitkine <asvitkine@chromium.org>
Reviewed-by: default avatarRichard Coles <torne@chromium.org>
Reviewed-by: default avataragrieve <agrieve@chromium.org>
Cr-Commit-Position: refs/heads/master@{#603996}
parent 6f13e530
...@@ -341,6 +341,7 @@ group("gn_all") { ...@@ -341,6 +341,7 @@ group("gn_all") {
"//android_webview/test", "//android_webview/test",
"//android_webview/tools/automated_ui_tests:webview_ui_test_app", "//android_webview/tools/automated_ui_tests:webview_ui_test_app",
"//android_webview/tools/system_webview_shell", "//android_webview/tools/system_webview_shell",
"//android_webview/tools/webview_log_verbosifier:webview_log_verbosifier_apk",
"//chrome/android:chrome_junit_tests", "//chrome/android:chrome_junit_tests",
"//chrome/android:chrome_public_apk", "//chrome/android:chrome_public_apk",
"//chrome/android:chrome_public_test_apk", "//chrome/android:chrome_public_test_apk",
......
...@@ -38,6 +38,7 @@ import org.chromium.android_webview.WebViewChromiumRunQueue; ...@@ -38,6 +38,7 @@ import org.chromium.android_webview.WebViewChromiumRunQueue;
import org.chromium.android_webview.command_line.CommandLineUtil; import org.chromium.android_webview.command_line.CommandLineUtil;
import org.chromium.base.BuildConfig; import org.chromium.base.BuildConfig;
import org.chromium.base.ContextUtils; import org.chromium.base.ContextUtils;
import org.chromium.base.FieldTrialList;
import org.chromium.base.PathService; import org.chromium.base.PathService;
import org.chromium.base.ThreadUtils; import org.chromium.base.ThreadUtils;
import org.chromium.base.TraceEvent; import org.chromium.base.TraceEvent;
...@@ -47,6 +48,7 @@ import org.chromium.base.library_loader.LibraryProcessType; ...@@ -47,6 +48,7 @@ import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.base.library_loader.ProcessInitException; import org.chromium.base.library_loader.ProcessInitException;
import org.chromium.base.metrics.CachedMetrics; import org.chromium.base.metrics.CachedMetrics;
import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.task.AsyncTask;
import org.chromium.net.NetworkChangeNotifier; import org.chromium.net.NetworkChangeNotifier;
/** /**
...@@ -199,6 +201,8 @@ public class WebViewChromiumAwInit { ...@@ -199,6 +201,8 @@ public class WebViewChromiumAwInit {
} }
mFactory.getRunQueue().drainQueue(); mFactory.getRunQueue().drainQueue();
maybeLogActiveTrials(context);
} }
} }
...@@ -452,6 +456,23 @@ public class WebViewChromiumAwInit { ...@@ -452,6 +456,23 @@ public class WebViewChromiumAwInit {
} }
} }
// If a certain app is installed, log field trials as they become active, for debugging
// purposes. Check for the app asyncronously because PackageManager is slow.
private static void maybeLogActiveTrials(final Context ctx) {
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
try {
// This must match the package name in:
// android_webview/tools/webview_log_verbosifier/AndroidManifest.xml
ctx.getPackageManager().getPackageInfo(
"org.chromium.webview_log_verbosifier", /*flags=*/0);
} catch (PackageManager.NameNotFoundException e) {
return;
}
ThreadUtils.postOnUiThread(() -> FieldTrialList.logActiveTrials());
});
}
public WebViewChromiumRunQueue getRunQueue() { public WebViewChromiumRunQueue getRunQueue() {
return mFactory.getRunQueue(); return mFactory.getRunQueue();
} }
......
<!-- Copyright 2018 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<!-- This package name must match the one in WebViewChromiumAwInit.maybeLogActiveTrials() -->
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="org.chromium.webview_log_verbosifier"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
<application android:label="WebView Log Verbosifier" />
</manifest>
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/android/rules.gni")
android_apk("webview_log_verbosifier_apk") {
apk_name = "WebViewLogVerbosifier"
android_manifest = "AndroidManifest.xml"
}
WebView Log Verbosifier is an empty dummy app. If this app is installed, WebView
will log the active field trials, for debugging/QA purposes. A dummy app is used
because it can be installed on any device, unlike command-line flags.
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include <string> #include <string>
#include "base/android/jni_string.h" #include "base/android/jni_string.h"
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/metrics/field_trial.h" #include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h" #include "base/metrics/field_trial_params.h"
#include "jni/FieldTrialList_jni.h" #include "jni/FieldTrialList_jni.h"
...@@ -17,6 +19,36 @@ using base::android::ConvertUTF8ToJavaString; ...@@ -17,6 +19,36 @@ using base::android::ConvertUTF8ToJavaString;
using base::android::JavaParamRef; using base::android::JavaParamRef;
using base::android::ScopedJavaLocalRef; using base::android::ScopedJavaLocalRef;
namespace {
// Log trials and their groups on activation, for debugging purposes.
class TrialLogger : public base::FieldTrialList::Observer {
public:
TrialLogger() {}
void OnFieldTrialGroupFinalized(const std::string& trial_name,
const std::string& group_name) override {
Log(trial_name, group_name);
}
static void Log(const std::string& trial_name,
const std::string& group_name) {
LOG(INFO) << "Active field trial \"" << trial_name
<< "\" in group \"" << group_name<< '"';
}
protected:
~TrialLogger() override {}
private:
DISALLOW_COPY_AND_ASSIGN(TrialLogger);
};
base::LazyInstance<TrialLogger>::Leaky g_trial_logger =
LAZY_INSTANCE_INITIALIZER;
} // namespace
static ScopedJavaLocalRef<jstring> JNI_FieldTrialList_FindFullName( static ScopedJavaLocalRef<jstring> JNI_FieldTrialList_FindFullName(
JNIEnv* env, JNIEnv* env,
const JavaParamRef<jclass>& clazz, const JavaParamRef<jclass>& clazz,
...@@ -45,3 +77,19 @@ static ScopedJavaLocalRef<jstring> JNI_FieldTrialList_GetVariationParameter( ...@@ -45,3 +77,19 @@ static ScopedJavaLocalRef<jstring> JNI_FieldTrialList_GetVariationParameter(
return ConvertUTF8ToJavaString( return ConvertUTF8ToJavaString(
env, parameters[ConvertJavaStringToUTF8(env, jparameter_key)]); env, parameters[ConvertJavaStringToUTF8(env, jparameter_key)]);
} }
static void JNI_FieldTrialList_LogActiveTrials(
JNIEnv* env,
const base::android::JavaParamRef<jclass>& clazz) {
DCHECK(!g_trial_logger.IsCreated()); // This need only be called once.
LOG(INFO) << "Logging active field trials...";
base::FieldTrialList::AddObserver(&g_trial_logger.Get());
// Log any trials that were already active before adding the observer.
std::vector<base::FieldTrial::ActiveGroup> active_groups;
base::FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
for (const base::FieldTrial::ActiveGroup& group : active_groups) {
TrialLogger::Log(group.trial_name, group.group_name);
}
}
...@@ -40,7 +40,16 @@ public class FieldTrialList { ...@@ -40,7 +40,16 @@ public class FieldTrialList {
return nativeGetVariationParameter(trialName, parameterKey); return nativeGetVariationParameter(trialName, parameterKey);
} }
/**
* Print active trials and their group assignments to logcat, for debugging purposes. Continue
* prtinting new trials as they become active. This should be called at most once.
*/
public static void logActiveTrials() {
nativeLogActiveTrials();
}
private static native String nativeFindFullName(String trialName); private static native String nativeFindFullName(String trialName);
private static native boolean nativeTrialExists(String trialName); private static native boolean nativeTrialExists(String trialName);
private static native String nativeGetVariationParameter(String trialName, String parameterKey); private static native String nativeGetVariationParameter(String trialName, String parameterKey);
private static native void nativeLogActiveTrials();
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment