summaryrefslogtreecommitdiff
path: root/chromium/components/embedder_support
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/embedder_support')
-rw-r--r--chromium/components/embedder_support/BUILD.gn1
-rw-r--r--chromium/components/embedder_support/android/BUILD.gn4
-rw-r--r--chromium/components/embedder_support/android/browser_context/browser_context_handle.cc3
-rw-r--r--chromium/components/embedder_support/android/delegate/web_contents_delegate_android.cc3
-rw-r--r--chromium/components/embedder_support/android/delegate/web_contents_delegate_android.h3
-rw-r--r--chromium/components/embedder_support/android/java/src/org/chromium/components/embedder_support/delegate/ColorPickerDialogRenderTest.java3
-rw-r--r--chromium/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java154
-rw-r--r--chromium/components/embedder_support/android/junit/src/org/chromium/components/embedder_support/util/OriginTest.java3
-rw-r--r--chromium/components/embedder_support/android/metrics/BUILD.gn4
-rw-r--r--chromium/components/embedder_support/android/metrics/DEPS3
-rw-r--r--chromium/components/embedder_support/android/metrics/android_metrics_log_uploader.cc12
-rw-r--r--chromium/components/embedder_support/android/metrics/android_metrics_service_client.cc278
-rw-r--r--chromium/components/embedder_support/android/metrics/android_metrics_service_client.h46
-rw-r--r--chromium/components/embedder_support/android/metrics/android_metrics_service_client_unittest.cc2
-rw-r--r--chromium/components/embedder_support/android/view/content_view_render_view.h1
-rw-r--r--chromium/components/embedder_support/origin_trials/BUILD.gn2
-rw-r--r--chromium/components/embedder_support/origin_trials/features.cc20
-rw-r--r--chromium/components/embedder_support/origin_trials/features.h20
-rw-r--r--chromium/components/embedder_support/origin_trials/origin_trial_policy_impl.cc20
-rw-r--r--chromium/components/embedder_support/origin_trials/origin_trial_policy_impl.h1
-rw-r--r--chromium/components/embedder_support/origin_trials/origin_trial_policy_impl_unittest.cc13
21 files changed, 531 insertions, 65 deletions
diff --git a/chromium/components/embedder_support/BUILD.gn b/chromium/components/embedder_support/BUILD.gn
index 3a042f43d70..647bd364620 100644
--- a/chromium/components/embedder_support/BUILD.gn
+++ b/chromium/components/embedder_support/BUILD.gn
@@ -17,6 +17,7 @@ source_set("unit_tests") {
deps = [
"//base",
+ "//base/test:test_support",
"//components/embedder_support",
"//components/embedder_support/origin_trials",
"//testing/gtest",
diff --git a/chromium/components/embedder_support/android/BUILD.gn b/chromium/components/embedder_support/android/BUILD.gn
index 49f264a0791..182b461b42b 100644
--- a/chromium/components/embedder_support/android/BUILD.gn
+++ b/chromium/components/embedder_support/android/BUILD.gn
@@ -242,7 +242,7 @@ android_library("junit_test_support") {
sources = [ "junit/src/org/chromium/components/embedder_support/util/ShadowUrlUtilities.java" ]
deps = [
":util_java",
- "//third_party/robolectric:robolectric_all_java",
+ "//third_party/android_deps:robolectric_all_java",
]
}
@@ -256,6 +256,8 @@ java_library("components_embedder_support_junit_tests") {
deps = [
":util_java",
"//base:base_junit_test_support",
+ "//third_party/android_deps:robolectric_all_java",
+ "//third_party/junit",
]
}
diff --git a/chromium/components/embedder_support/android/browser_context/browser_context_handle.cc b/chromium/components/embedder_support/android/browser_context/browser_context_handle.cc
index af9a43dacd4..77ddc0cf804 100644
--- a/chromium/components/embedder_support/android/browser_context/browser_context_handle.cc
+++ b/chromium/components/embedder_support/android/browser_context/browser_context_handle.cc
@@ -15,6 +15,9 @@ namespace browser_context {
content::BrowserContext* BrowserContextFromJavaHandle(
const JavaRef<jobject>& jhandle) {
+ if (!jhandle)
+ return nullptr;
+
return reinterpret_cast<content::BrowserContext*>(
Java_BrowserContextHandle_getNativeBrowserContextPointer(
AttachCurrentThread(), jhandle));
diff --git a/chromium/components/embedder_support/android/delegate/web_contents_delegate_android.cc b/chromium/components/embedder_support/android/delegate/web_contents_delegate_android.cc
index c7adaddc988..ff394138e01 100644
--- a/chromium/components/embedder_support/android/delegate/web_contents_delegate_android.cc
+++ b/chromium/components/embedder_support/android/delegate/web_contents_delegate_android.cc
@@ -313,8 +313,7 @@ bool WebContentsDelegateAndroid::ShouldBlockMediaRequest(const GURL& url) {
}
void WebContentsDelegateAndroid::EnterFullscreenModeForTab(
- WebContents* web_contents,
- const GURL& origin,
+ content::RenderFrameHost* requesting_frame,
const blink::mojom::FullscreenOptions& options) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
diff --git a/chromium/components/embedder_support/android/delegate/web_contents_delegate_android.h b/chromium/components/embedder_support/android/delegate/web_contents_delegate_android.h
index c8d8af79a16..56706c7f610 100644
--- a/chromium/components/embedder_support/android/delegate/web_contents_delegate_android.h
+++ b/chromium/components/embedder_support/android/delegate/web_contents_delegate_android.h
@@ -96,8 +96,7 @@ class WebContentsDelegateAndroid : public content::WebContentsDelegate {
void ShowRepostFormWarningDialog(content::WebContents* source) override;
bool ShouldBlockMediaRequest(const GURL& url) override;
void EnterFullscreenModeForTab(
- content::WebContents* web_contents,
- const GURL& origin,
+ content::RenderFrameHost* requesting_frame,
const blink::mojom::FullscreenOptions& options) override;
void ExitFullscreenModeForTab(content::WebContents* web_contents) override;
bool IsFullscreenForTabOrPending(
diff --git a/chromium/components/embedder_support/android/java/src/org/chromium/components/embedder_support/delegate/ColorPickerDialogRenderTest.java b/chromium/components/embedder_support/android/java/src/org/chromium/components/embedder_support/delegate/ColorPickerDialogRenderTest.java
index 6a162f600dd..f5d2b05baa0 100644
--- a/chromium/components/embedder_support/android/java/src/org/chromium/components/embedder_support/delegate/ColorPickerDialogRenderTest.java
+++ b/chromium/components/embedder_support/android/java/src/org/chromium/components/embedder_support/delegate/ColorPickerDialogRenderTest.java
@@ -43,8 +43,7 @@ public class ColorPickerDialogRenderTest extends DummyUiActivityTestCase {
new NightModeTestUtils.NightModeParams().getParameters();
@Rule
- public RenderTestRule mRenderTestRule =
- new RenderTestRule("chrome/test/data/android/render_tests");
+ public RenderTestRule mRenderTestRule = new RenderTestRule();
private View mView;
diff --git a/chromium/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java b/chromium/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java
index 251ee9ea516..33465886b25 100644
--- a/chromium/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java
+++ b/chromium/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java
@@ -34,10 +34,16 @@ import org.chromium.content_public.browser.ViewEventSink;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.WebContentsAccessibility;
import org.chromium.ui.base.EventForwarder;
+import org.chromium.ui.base.EventOffsetHandler;
/**
* The containing view for {@link WebContents} that exists in the Android UI hierarchy and exposes
* the various {@link View} functionality to it.
+ *
+ * While ContentView is a ViewGroup, the only place that should add children is ViewAndroidDelegate,
+ * and only for cases that WebContentsAccessibility handles (such as anchoring popups). This is
+ * because the accessibility support provided by WebContentsAccessibility ignores all child views.
+ * In other words, any children added to this are *not* accessible.
*/
public class ContentView extends FrameLayout
implements ViewEventSink.InternalAccessDelegate, SmartClipProvider,
@@ -48,7 +54,9 @@ public class ContentView extends FrameLayout
public static final int DEFAULT_MEASURE_SPEC =
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- private final WebContents mWebContents;
+ @Nullable
+ private WebContents mWebContents;
+ private boolean mIsObscuredForAccessibility;
private final ObserverList<OnHierarchyChangeListener> mHierarchyChangeListeners =
new ObserverList<>();
private final ObserverList<OnSystemUiVisibilityChangeListener> mSystemUiChangeListeners =
@@ -62,6 +70,9 @@ public class ContentView extends FrameLayout
private int mDesiredWidthMeasureSpec = DEFAULT_MEASURE_SPEC;
private int mDesiredHeightMeasureSpec = DEFAULT_MEASURE_SPEC;
+ @Nullable
+ private final EventOffsetHandler mEventOffsetHandler;
+
/**
* Constructs a new ContentView for the appropriate Android version.
* @param context The Context the view is running in, through which it can
@@ -69,11 +80,12 @@ public class ContentView extends FrameLayout
* @param webContents The WebContents managing this content view.
* @return an instance of a ContentView.
*/
- public static ContentView createContentView(Context context, WebContents webContents) {
+ public static ContentView createContentView(Context context,
+ @Nullable EventOffsetHandler eventOffsetHandler, @Nullable WebContents webContents) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- return new ContentViewApi23(context, webContents);
+ return new ContentViewApi23(context, eventOffsetHandler, webContents);
}
- return new ContentView(context, webContents);
+ return new ContentView(context, eventOffsetHandler, webContents);
}
/**
@@ -82,7 +94,7 @@ public class ContentView extends FrameLayout
* access the current theme, resources, etc.
* @param webContents A pointer to the WebContents managing this content view.
*/
- ContentView(Context context, WebContents webContents) {
+ ContentView(Context context, EventOffsetHandler eventOffsetHandler, WebContents webContents) {
super(context, null, android.R.attr.webViewStyle);
if (getScrollBarStyle() == View.SCROLLBARS_INSIDE_OVERLAY) {
@@ -91,6 +103,7 @@ public class ContentView extends FrameLayout
}
mWebContents = webContents;
+ mEventOffsetHandler = eventOffsetHandler;
setFocusable(true);
setFocusableInTouchMode(true);
@@ -103,13 +116,41 @@ public class ContentView extends FrameLayout
setOnSystemUiVisibilityChangeListener(this);
}
+ protected WebContentsAccessibility getWebContentsAccessibility() {
+ return hasValidWebContents() ? WebContentsAccessibility.fromWebContents(mWebContents)
+ : null;
+ }
+
public WebContents getWebContents() {
return mWebContents;
}
- protected WebContentsAccessibility getWebContentsAccessibility() {
- return !mWebContents.isDestroyed() ? WebContentsAccessibility.fromWebContents(mWebContents)
- : null;
+ public void setWebContents(WebContents webContents) {
+ boolean wasFocused = isFocused();
+ boolean wasWindowFocused = hasWindowFocus();
+ boolean wasAttached = isAttachedToWindow();
+ boolean wasObscured = mIsObscuredForAccessibility;
+ if (wasFocused) onFocusChanged(false, View.FOCUS_FORWARD, null);
+ if (wasWindowFocused) onWindowFocusChanged(false);
+ if (wasAttached) onDetachedFromWindow();
+ if (wasObscured) setIsObscuredForAccessibility(false);
+ mWebContents = webContents;
+ mViewEventSink = null;
+ if (wasFocused) onFocusChanged(true, View.FOCUS_FORWARD, null);
+ if (wasWindowFocused) onWindowFocusChanged(true);
+ if (wasAttached) onAttachedToWindow();
+ if (wasObscured) setIsObscuredForAccessibility(true);
+ }
+
+ /**
+ * Control whether WebContentsAccessibility will respond to accessibility requests.
+ */
+ public void setIsObscuredForAccessibility(boolean isObscured) {
+ if (mIsObscuredForAccessibility == isObscured) return;
+ mIsObscuredForAccessibility = isObscured;
+ WebContentsAccessibility wcax = getWebContentsAccessibility();
+ if (wcax == null) return;
+ wcax.setObscuredByAnotherView(mIsObscuredForAccessibility);
}
@Override
@@ -228,13 +269,13 @@ public class ContentView extends FrameLayout
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
// Calls may come while/after WebContents is destroyed. See https://crbug.com/821750#c8.
- if (mWebContents.isDestroyed()) return null;
+ if (!hasValidWebContents()) return null;
return ImeAdapter.fromWebContents(mWebContents).onCreateInputConnection(outAttrs);
}
@Override
public boolean onCheckIsTextEditor() {
- if (mWebContents.isDestroyed()) return false;
+ if (!hasValidWebContents()) return false;
return ImeAdapter.fromWebContents(mWebContents).onCheckIsTextEditor();
}
@@ -243,8 +284,10 @@ public class ContentView extends FrameLayout
try {
TraceEvent.begin("ContentView.onFocusChanged");
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
- getViewEventSink().setHideKeyboardOnBlur(true);
- getViewEventSink().onViewFocusChanged(gainFocus);
+ if (hasValidWebContents()) {
+ getViewEventSink().setHideKeyboardOnBlur(true);
+ getViewEventSink().onViewFocusChanged(gainFocus);
+ }
} finally {
TraceEvent.end("ContentView.onFocusChanged");
}
@@ -253,7 +296,9 @@ public class ContentView extends FrameLayout
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
- getViewEventSink().onWindowFocusChanged(hasWindowFocus);
+ if (hasValidWebContents()) {
+ getViewEventSink().onWindowFocusChanged(hasWindowFocus);
+ }
}
@Override
@@ -276,9 +321,40 @@ public class ContentView extends FrameLayout
}
@Override
+ public boolean onInterceptTouchEvent(MotionEvent e) {
+ boolean ret = super.onInterceptTouchEvent(e);
+ if (mEventOffsetHandler != null) {
+ mEventOffsetHandler.onInterceptTouchEvent(e);
+ }
+ return ret;
+ }
+
+ @Override
public boolean onTouchEvent(MotionEvent event) {
EventForwarder forwarder = getEventForwarder();
- return forwarder != null ? forwarder.onTouchEvent(event) : false;
+ boolean ret = forwarder != null ? forwarder.onTouchEvent(event) : false;
+ if (mEventOffsetHandler != null) mEventOffsetHandler.onTouchEvent(event);
+ return ret;
+ }
+
+ @Override
+ public boolean onInterceptHoverEvent(MotionEvent e) {
+ if (mEventOffsetHandler != null) {
+ mEventOffsetHandler.onInterceptHoverEvent(e);
+ }
+ return super.onInterceptHoverEvent(e);
+ }
+
+ @Override
+ public boolean dispatchDragEvent(DragEvent e) {
+ if (mEventOffsetHandler != null) {
+ mEventOffsetHandler.onPreDispatchDragEvent(e.getAction());
+ }
+ boolean ret = super.dispatchDragEvent(e);
+ if (mEventOffsetHandler != null) {
+ mEventOffsetHandler.onPostDispatchDragEvent(e.getAction());
+ }
+ return ret;
}
/**
@@ -307,7 +383,9 @@ public class ContentView extends FrameLayout
}
private ViewEventSink getViewEventSink() {
- if (mViewEventSink == null) mViewEventSink = ViewEventSink.from(mWebContents);
+ if (mViewEventSink == null && hasValidWebContents()) {
+ mViewEventSink = ViewEventSink.from(mWebContents);
+ }
return mViewEventSink;
}
@@ -318,7 +396,9 @@ public class ContentView extends FrameLayout
@Override
protected void onConfigurationChanged(Configuration newConfig) {
- getViewEventSink().onConfigurationChanged(newConfig);
+ if (hasValidWebContents()) {
+ getViewEventSink().onConfigurationChanged(newConfig);
+ }
super.onConfigurationChanged(newConfig);
}
@@ -342,40 +422,44 @@ public class ContentView extends FrameLayout
@Override
protected int computeHorizontalScrollExtent() {
- RenderCoordinates rc = RenderCoordinates.fromWebContents(mWebContents);
+ RenderCoordinates rc = getRenderCoordinates();
return rc != null ? rc.getLastFrameViewportWidthPixInt() : 0;
}
@Override
protected int computeHorizontalScrollOffset() {
- RenderCoordinates rc = RenderCoordinates.fromWebContents(mWebContents);
+ RenderCoordinates rc = getRenderCoordinates();
return rc != null ? rc.getScrollXPixInt() : 0;
}
@Override
protected int computeHorizontalScrollRange() {
- RenderCoordinates rc = RenderCoordinates.fromWebContents(mWebContents);
+ RenderCoordinates rc = getRenderCoordinates();
return rc != null ? rc.getContentWidthPixInt() : 0;
}
@Override
protected int computeVerticalScrollExtent() {
- RenderCoordinates rc = RenderCoordinates.fromWebContents(mWebContents);
+ RenderCoordinates rc = getRenderCoordinates();
return rc != null ? rc.getLastFrameViewportHeightPixInt() : 0;
}
@Override
protected int computeVerticalScrollOffset() {
- RenderCoordinates rc = RenderCoordinates.fromWebContents(mWebContents);
+ RenderCoordinates rc = getRenderCoordinates();
return rc != null ? rc.getScrollYPixInt() : 0;
}
@Override
protected int computeVerticalScrollRange() {
- RenderCoordinates rc = RenderCoordinates.fromWebContents(mWebContents);
+ RenderCoordinates rc = getRenderCoordinates();
return rc != null ? rc.getContentHeightPixInt() : 0;
}
+ private RenderCoordinates getRenderCoordinates() {
+ return hasValidWebContents() ? RenderCoordinates.fromWebContents(mWebContents) : null;
+ }
+
// End FrameLayout overrides.
@Override
@@ -390,25 +474,33 @@ public class ContentView extends FrameLayout
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- getViewEventSink().onAttachedToWindow();
+ if (hasValidWebContents()) {
+ getViewEventSink().onAttachedToWindow();
+ }
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- getViewEventSink().onDetachedFromWindow();
+ if (hasValidWebContents()) {
+ getViewEventSink().onDetachedFromWindow();
+ }
}
// Implements SmartClipProvider
@Override
public void extractSmartClipData(int x, int y, int width, int height) {
- mWebContents.requestSmartClipExtract(x, y, width, height);
+ if (hasValidWebContents()) {
+ mWebContents.requestSmartClipExtract(x, y, width, height);
+ }
}
// Implements SmartClipProvider
@Override
public void setSmartClipResultHandler(final Handler resultHandler) {
- mWebContents.setSmartClipResultHandler(resultHandler);
+ if (hasValidWebContents()) {
+ mWebContents.setSmartClipResultHandler(resultHandler);
+ }
}
///////////////////////////////////////////////////////////////////////////////////////////////
@@ -442,9 +534,13 @@ public class ContentView extends FrameLayout
return hasValidWebContents() && mWebContents.getTopLevelNativeWindow() != null;
}
- private static class ContentViewApi23 extends ContentView {
- public ContentViewApi23(Context context, WebContents webContents) {
- super(context, webContents);
+ /**
+ * ContentView on Api23 to override onProvideVirtualStructure.
+ */
+ public static class ContentViewApi23 extends ContentView {
+ protected ContentViewApi23(
+ Context context, EventOffsetHandler eventOffsetHandler, WebContents webContents) {
+ super(context, eventOffsetHandler, webContents);
}
@Override
diff --git a/chromium/components/embedder_support/android/junit/src/org/chromium/components/embedder_support/util/OriginTest.java b/chromium/components/embedder_support/android/junit/src/org/chromium/components/embedder_support/util/OriginTest.java
index 8be1437fce3..fd8cf8c8841 100644
--- a/chromium/components/embedder_support/android/junit/src/org/chromium/components/embedder_support/util/OriginTest.java
+++ b/chromium/components/embedder_support/android/junit/src/org/chromium/components/embedder_support/util/OriginTest.java
@@ -5,7 +5,8 @@
package org.chromium.components.embedder_support.util;
import android.net.Uri;
-import android.support.test.filters.SmallTest;
+
+import androidx.test.filters.SmallTest;
import org.junit.Assert;
import org.junit.Test;
diff --git a/chromium/components/embedder_support/android/metrics/BUILD.gn b/chromium/components/embedder_support/android/metrics/BUILD.gn
index d9641ed058c..7a0e269c738 100644
--- a/chromium/components/embedder_support/android/metrics/BUILD.gn
+++ b/chromium/components/embedder_support/android/metrics/BUILD.gn
@@ -21,14 +21,16 @@ static_library("metrics") {
deps = [
":jni",
"//components/metrics",
- "//components/metrics:gpu",
+ "//components/metrics:content",
"//components/metrics:net",
"//components/metrics:ui",
"//components/prefs",
+ "//components/ukm",
"//components/version_info",
"//components/version_info/android:channel_getter",
"//content/public/browser",
"//services/resource_coordinator/public/cpp/memory_instrumentation:browser",
+ "//third_party/metrics_proto",
]
}
diff --git a/chromium/components/embedder_support/android/metrics/DEPS b/chromium/components/embedder_support/android/metrics/DEPS
index a7e7754f1e8..a2b32b905eb 100644
--- a/chromium/components/embedder_support/android/metrics/DEPS
+++ b/chromium/components/embedder_support/android/metrics/DEPS
@@ -1,8 +1,11 @@
include_rules = [
"+components/metrics",
"+components/prefs",
+ "+components/ukm",
"+components/version_info",
"+content/public/browser",
"+content/public/test",
+ "+services/network/public/cpp",
"+services/resource_coordinator/public/cpp/memory_instrumentation",
+ "+third_party/metrics_proto",
]
diff --git a/chromium/components/embedder_support/android/metrics/android_metrics_log_uploader.cc b/chromium/components/embedder_support/android/metrics/android_metrics_log_uploader.cc
index a737dc5bcc4..18dabdad7ae 100644
--- a/chromium/components/embedder_support/android/metrics/android_metrics_log_uploader.cc
+++ b/chromium/components/embedder_support/android/metrics/android_metrics_log_uploader.cc
@@ -5,8 +5,10 @@
#include "components/embedder_support/android/metrics/android_metrics_log_uploader.h"
#include "base/android/jni_array.h"
+#include "base/check.h"
#include "components/embedder_support/android/metrics/jni/AndroidMetricsLogUploader_jni.h"
#include "components/metrics/log_decoder.h"
+#include "third_party/metrics_proto/chrome_user_metrics_extension.pb.h"
using base::android::ScopedJavaLocalRef;
using base::android::ToJavaByteArray;
@@ -34,6 +36,16 @@ void AndroidMetricsLogUploader::UploadLog(
return;
}
+ // Speculative CHECKs to see why WebView UMA (and probably other embedders of
+ // this component) are missing system_profiles for a small fraction of
+ // records. TODO(https://crbug.com/1081925): downgrade these to DCHECKs or
+ // remove entirely when we figure out the issue.
+ CHECK(!log_data.empty());
+ metrics::ChromeUserMetricsExtension uma_log;
+ bool can_parse = uma_log.ParseFromString(log_data);
+ CHECK(can_parse);
+ CHECK(uma_log.has_system_profile());
+
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jbyteArray> java_data = ToJavaByteArray(
env, reinterpret_cast<const uint8_t*>(log_data.data()), log_data.size());
diff --git a/chromium/components/embedder_support/android/metrics/android_metrics_service_client.cc b/chromium/components/embedder_support/android/metrics/android_metrics_service_client.cc
index 32cd418ed13..a36c0a1dc54 100644
--- a/chromium/components/embedder_support/android/metrics/android_metrics_service_client.cc
+++ b/chromium/components/embedder_support/android/metrics/android_metrics_service_client.cc
@@ -10,32 +10,53 @@
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/base_paths_android.h"
+#include "base/files/file_util.h"
#include "base/i18n/rtl.h"
+#include "base/metrics/persistent_histogram_allocator.h"
+#include "base/metrics/statistics_recorder.h"
+#include "base/path_service.h"
+#include "base/process/process_handle.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
+#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "components/embedder_support/android/metrics/android_metrics_log_uploader.h"
#include "components/embedder_support/android/metrics/jni/AndroidMetricsServiceClient_jni.h"
#include "components/metrics/android_metrics_provider.h"
#include "components/metrics/call_stack_profile_metrics_provider.h"
+#include "components/metrics/content/gpu_metrics_provider.h"
+#include "components/metrics/content/subprocess_metrics_provider.h"
#include "components/metrics/cpu_metrics_provider.h"
#include "components/metrics/drive_metrics_provider.h"
-#include "components/metrics/gpu/gpu_metrics_provider.h"
+#include "components/metrics/file_metrics_provider.h"
#include "components/metrics/metrics_pref_names.h"
#include "components/metrics/metrics_service.h"
#include "components/metrics/metrics_state_manager.h"
#include "components/metrics/net/cellular_logic_helper.h"
+#include "components/metrics/net/net_metrics_log_uploader.h"
#include "components/metrics/net/network_metrics_provider.h"
+#include "components/metrics/persistent_histograms.h"
#include "components/metrics/stability_metrics_helper.h"
#include "components/metrics/ui/screen_info_metrics_provider.h"
#include "components/metrics/version_utils.h"
#include "components/prefs/pref_service.h"
+#include "components/ukm/field_trials_provider_helper.h"
+#include "components/ukm/ukm_service.h"
+#include "content/public/browser/histogram_fetcher.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
-
+#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace metrics {
namespace {
+// This specifies the amount of time to wait for all renderers to send their
+// data.
+const int kMaxHistogramGatheringWaitDuration = 60000; // 60 seconds.
+
+const int kMaxHistogramStorageKiB = 100 << 10; // 100 MiB
+
// Callbacks for MetricsStateManager::Create. Store/LoadClientInfo
// allow Windows Chrome to back up ClientInfo. They're no-ops for
// AndroidMetricsServiceClient.
@@ -61,15 +82,121 @@ int UintToPerMille(uint32_t value) {
return static_cast<int>(value_per_mille);
}
+bool IsProcessRunning(base::ProcessId pid) {
+ // Sending a signal value of 0 will cause error checking to be performed
+ // with no signal being sent.
+ return (kill(pid, 0) == 0 || errno != ESRCH);
+}
+
+metrics::FileMetricsProvider::FilterAction FilterBrowserMetricsFiles(
+ const base::FilePath& path) {
+ base::ProcessId pid;
+ if (!base::GlobalHistogramAllocator::ParseFilePath(path, nullptr, nullptr,
+ &pid)) {
+ return metrics::FileMetricsProvider::FILTER_PROCESS_FILE;
+ }
+
+ if (pid == base::GetCurrentProcId())
+ return metrics::FileMetricsProvider::FILTER_ACTIVE_THIS_PID;
+
+ if (IsProcessRunning(pid))
+ return metrics::FileMetricsProvider::FILTER_TRY_LATER;
+
+ return metrics::FileMetricsProvider::FILTER_PROCESS_FILE;
+}
+
+// Constructs the name of a persistent metrics file from a directory and metrics
+// name, and either registers that file as associated with a previous run if
+// metrics reporting is enabled, or deletes it if not.
+void RegisterOrRemovePreviousRunMetricsFile(
+ bool metrics_reporting_enabled,
+ const base::FilePath& dir,
+ base::StringPiece metrics_name,
+ metrics::FileMetricsProvider::SourceAssociation association,
+ metrics::FileMetricsProvider* file_metrics_provider) {
+ base::FilePath metrics_file;
+ base::GlobalHistogramAllocator::ConstructFilePaths(
+ dir, metrics_name, &metrics_file, nullptr, nullptr);
+
+ if (metrics_reporting_enabled) {
+ // Enable reading any existing saved metrics.
+ file_metrics_provider->RegisterSource(metrics::FileMetricsProvider::Params(
+ metrics_file,
+ metrics::FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
+ association, metrics_name));
+ } else {
+ // When metrics reporting is not enabled, any existing file should be
+ // deleted in order to preserve user privacy.
+ base::ThreadPool::PostTask(
+ FROM_HERE,
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+ base::BindOnce(base::GetDeleteFileCallback(), metrics_file));
+ }
+}
+
+std::unique_ptr<metrics::FileMetricsProvider> CreateFileMetricsProvider(
+ PrefService* pref_service,
+ bool metrics_reporting_enabled) {
+ // Create an object to monitor files of metrics and include them in reports.
+ std::unique_ptr<metrics::FileMetricsProvider> file_metrics_provider(
+ new metrics::FileMetricsProvider(pref_service));
+
+ base::FilePath user_data_dir;
+ base::PathService::Get(base::DIR_ANDROID_APP_DATA, &user_data_dir);
+ // Register the Crashpad metrics files.
+ // Register the data from the previous run if crashpad_handler didn't exit
+ // cleanly.
+ RegisterOrRemovePreviousRunMetricsFile(
+ metrics_reporting_enabled, user_data_dir, kCrashpadHistogramAllocatorName,
+ metrics::FileMetricsProvider::ASSOCIATE_INTERNAL_PROFILE_OR_PREVIOUS_RUN,
+ file_metrics_provider.get());
+
+ base::FilePath browser_metrics_upload_dir =
+ user_data_dir.AppendASCII(kBrowserMetricsName);
+ if (metrics_reporting_enabled) {
+ metrics::FileMetricsProvider::Params browser_metrics_params(
+ browser_metrics_upload_dir,
+ metrics::FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_DIR,
+ metrics::FileMetricsProvider::ASSOCIATE_INTERNAL_PROFILE,
+ kBrowserMetricsName);
+ browser_metrics_params.max_dir_kib = kMaxHistogramStorageKiB;
+ browser_metrics_params.filter =
+ base::BindRepeating(FilterBrowserMetricsFiles);
+ file_metrics_provider->RegisterSource(browser_metrics_params);
+
+ base::FilePath active_path;
+ base::GlobalHistogramAllocator::ConstructFilePaths(
+ user_data_dir, kCrashpadHistogramAllocatorName, nullptr, &active_path,
+ nullptr);
+ // Register data that will be populated for the current run. "Active"
+ // files need an empty "prefs_key" because they update the file itself.
+ file_metrics_provider->RegisterSource(metrics::FileMetricsProvider::Params(
+ active_path,
+ metrics::FileMetricsProvider::SOURCE_HISTOGRAMS_ACTIVE_FILE,
+ metrics::FileMetricsProvider::ASSOCIATE_CURRENT_RUN));
+ }
+
+ return file_metrics_provider;
+}
+
} // namespace
+// Needs to be kept in sync with the writer in
+// third_party/crashpad/crashpad/handler/handler_main.cc.
+const char kCrashpadHistogramAllocatorName[] = "CrashpadMetrics";
+
AndroidMetricsServiceClient::AndroidMetricsServiceClient() = default;
AndroidMetricsServiceClient::~AndroidMetricsServiceClient() = default;
// static
void AndroidMetricsServiceClient::RegisterPrefs(PrefRegistrySimple* registry) {
- MetricsService::RegisterPrefs(registry);
- StabilityMetricsHelper::RegisterPrefs(registry);
+ metrics::MetricsService::RegisterPrefs(registry);
+ metrics::FileMetricsProvider::RegisterPrefs(registry, kBrowserMetricsName);
+ metrics::FileMetricsProvider::RegisterPrefs(registry,
+ kCrashpadHistogramAllocatorName);
+ metrics::StabilityMetricsHelper::RegisterPrefs(registry);
+ ukm::UkmService::RegisterPrefs(registry);
}
void AndroidMetricsServiceClient::Initialize(PrefService* pref_service) {
@@ -95,8 +222,7 @@ void AndroidMetricsServiceClient::MaybeStartMetrics() {
bool user_consent_or_flag = user_consent_ || IsMetricsReportingForceEnabled();
if (IsConsentDetermined()) {
if (app_consent_ && user_consent_or_flag) {
- metrics_service_ = CreateMetricsService(metrics_state_manager_.get(),
- this, pref_service_);
+ CreateMetricsService(metrics_state_manager_.get(), this, pref_service_);
// Register for notifications so we can detect when the user or app are
// interacting with the embedder. We use these as signals to wake up the
// MetricsService.
@@ -109,6 +235,8 @@ void AndroidMetricsServiceClient::MaybeStartMetrics() {
// for a matching Stop() call.
metrics_service_->Start();
}
+
+ CreateUkmService();
} else {
OnMetricsNotStarted();
pref_service_->ClearPref(prefs::kMetricsClientID);
@@ -116,29 +244,61 @@ void AndroidMetricsServiceClient::MaybeStartMetrics() {
}
}
-std::unique_ptr<MetricsService>
-AndroidMetricsServiceClient::CreateMetricsService(
+void AndroidMetricsServiceClient::CreateMetricsService(
MetricsStateManager* state_manager,
AndroidMetricsServiceClient* client,
PrefService* prefs) {
- auto service = std::make_unique<MetricsService>(state_manager, client, prefs);
- service->RegisterMetricsProvider(std::make_unique<NetworkMetricsProvider>(
- content::CreateNetworkConnectionTrackerAsyncGetter()));
- service->RegisterMetricsProvider(std::make_unique<CPUMetricsProvider>());
- service->RegisterMetricsProvider(
+ metrics_service_ =
+ std::make_unique<MetricsService>(state_manager, client, prefs);
+ metrics_service_->RegisterMetricsProvider(
+ std::make_unique<metrics::SubprocessMetricsProvider>());
+ metrics_service_->RegisterMetricsProvider(
+ std::make_unique<NetworkMetricsProvider>(
+ content::CreateNetworkConnectionTrackerAsyncGetter()));
+ metrics_service_->RegisterMetricsProvider(
+ std::make_unique<CPUMetricsProvider>());
+ metrics_service_->RegisterMetricsProvider(
std::make_unique<ScreenInfoMetricsProvider>());
- service->RegisterMetricsProvider(
+ if (client->EnablePersistentHistograms()) {
+ metrics_service_->RegisterMetricsProvider(CreateFileMetricsProvider(
+ pref_service_, metrics_state_manager_->IsMetricsReportingEnabled()));
+ }
+ metrics_service_->RegisterMetricsProvider(
std::make_unique<CallStackProfileMetricsProvider>());
- service->RegisterMetricsProvider(
+ metrics_service_->RegisterMetricsProvider(
std::make_unique<metrics::AndroidMetricsProvider>());
- service->RegisterMetricsProvider(
+ metrics_service_->RegisterMetricsProvider(
std::make_unique<metrics::DriveMetricsProvider>(
base::DIR_ANDROID_APP_DATA));
- service->RegisterMetricsProvider(
+ metrics_service_->RegisterMetricsProvider(
std::make_unique<metrics::GPUMetricsProvider>());
- RegisterAdditionalMetricsProviders(service.get());
- service->InitializeMetricsRecordingState();
- return service;
+ RegisterAdditionalMetricsProviders(metrics_service_.get());
+
+ // The file metrics provider makes IO.
+ base::ScopedAllowBlocking allow_io;
+ metrics_service_->InitializeMetricsRecordingState();
+}
+
+void AndroidMetricsServiceClient::CreateUkmService() {
+ ukm_service_ = std::make_unique<ukm::UkmService>(
+ pref_service_, this, /*demographics_provider=*/nullptr);
+
+ ukm_service_->RegisterMetricsProvider(
+ std::make_unique<metrics::NetworkMetricsProvider>(
+ content::CreateNetworkConnectionTrackerAsyncGetter()));
+
+ ukm_service_->RegisterMetricsProvider(
+ std::make_unique<metrics::GPUMetricsProvider>());
+
+ ukm_service_->RegisterMetricsProvider(
+ std::make_unique<metrics::CPUMetricsProvider>());
+
+ ukm_service_->RegisterMetricsProvider(
+ std::make_unique<metrics::ScreenInfoMetricsProvider>());
+
+ ukm_service_->RegisterMetricsProvider(ukm::CreateFieldTrialsProviderForUkm());
+
+ UpdateUkmService();
}
void AndroidMetricsServiceClient::RegisterForNotifications() {
@@ -179,6 +339,34 @@ AndroidMetricsServiceClient::CreateLowEntropyProvider() {
return metrics_state_manager_->CreateLowEntropyProvider();
}
+void AndroidMetricsServiceClient::UpdateUkm(bool must_purge) {
+ if (!ukm_service_)
+ return;
+ if (must_purge) {
+ ukm_service_->Purge();
+ ukm_service_->ResetClientState(ukm::ResetReason::kOnUkmAllowedStateChanged);
+ }
+
+ UpdateUkmService();
+}
+
+void AndroidMetricsServiceClient::UpdateUkmService() {
+ if (!ukm_service_)
+ return;
+
+ bool consent_or_flag = IsConsentGiven() || IsMetricsReportingForceEnabled();
+ bool allowed = IsUkmAllowedForAllProfiles();
+ bool is_incognito = IsOffTheRecordSessionActive();
+
+ if (consent_or_flag && allowed && !is_incognito) {
+ ukm_service_->EnableRecording(/*extensions=*/false);
+ ukm_service_->EnableReporting();
+ } else {
+ ukm_service_->DisableRecording();
+ ukm_service_->DisableReporting();
+ }
+}
+
bool AndroidMetricsServiceClient::IsConsentDetermined() const {
return init_finished_ && set_consent_finished_;
}
@@ -203,6 +391,10 @@ MetricsService* AndroidMetricsServiceClient::GetMetricsService() {
return metrics_service_.get();
}
+ukm::UkmService* AndroidMetricsServiceClient::GetUkmService() {
+ return ukm_service_.get();
+}
+
// In Chrome, UMA and Crashpad are enabled/disabled together by the same
// checkbox and they share the same client ID (a.k.a. GUID). SetMetricsClientId
// is intended to provide the ID to Breakpad. In AndroidMetricsServiceClients
@@ -229,7 +421,20 @@ std::string AndroidMetricsServiceClient::GetVersionString() {
void AndroidMetricsServiceClient::CollectFinalMetricsForLog(
base::OnceClosure done_callback) {
- std::move(done_callback).Run();
+ // Merge histograms from metrics providers into StatisticsRecorder.
+ base::StatisticsRecorder::ImportProvidedHistograms();
+
+ base::TimeDelta timeout =
+ base::TimeDelta::FromMilliseconds(kMaxHistogramGatheringWaitDuration);
+
+ // Set up the callback task to call after we receive histograms from all
+ // child processes. |timeout| specifies how long to wait before absolutely
+ // calling us back on the task.
+ content::FetchHistogramsAsynchronously(base::ThreadTaskRunnerHandle::Get(),
+ std::move(done_callback), timeout);
+
+ if (collect_final_metrics_for_log_closure_)
+ std::move(collect_final_metrics_for_log_closure_).Run();
}
std::unique_ptr<MetricsLogUploader> AndroidMetricsServiceClient::CreateUploader(
@@ -238,6 +443,15 @@ std::unique_ptr<MetricsLogUploader> AndroidMetricsServiceClient::CreateUploader(
base::StringPiece mime_type,
MetricsLogUploader::MetricServiceType service_type,
const MetricsLogUploader::UploadCallback& on_upload_complete) {
+ if (service_type == metrics::MetricsLogUploader::UKM) {
+ // Clearcut doesn't handle UKMs.
+ auto url_loader_factory = GetURLLoaderFactory();
+ DCHECK(url_loader_factory);
+ return std::make_unique<metrics::NetMetricsLogUploader>(
+ url_loader_factory, server_url, insecure_server_url, mime_type,
+ service_type, on_upload_complete);
+ }
+
// |server_url|, |insecure_server_url|, and |mime_type| are unused because
// AndroidMetricsServiceClients send metrics to the platform logging mechanism
// rather than to Chrome's metrics server.
@@ -261,6 +475,10 @@ base::TimeDelta AndroidMetricsServiceClient::GetStandardUploadInterval() {
return metrics::GetUploadInterval(false /* use_cellular_upload_interval */);
}
+bool AndroidMetricsServiceClient::IsUkmAllowedForAllProfiles() {
+ return false;
+}
+
bool AndroidMetricsServiceClient::ShouldStartUpFastForTesting() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return fast_startup_for_testing_;
@@ -284,6 +502,11 @@ void AndroidMetricsServiceClient::Observe(
}
}
+void AndroidMetricsServiceClient::SetCollectFinalMetricsForLogClosureForTesting(
+ base::OnceClosure closure) {
+ collect_final_metrics_for_log_closure_ = std::move(closure);
+}
+
int AndroidMetricsServiceClient::GetSampleBucketValue() {
return UintToPerMille(base::PersistentHash(metrics_service_->GetClientId()));
}
@@ -315,6 +538,10 @@ bool AndroidMetricsServiceClient::IsInPackageNameSample() {
void AndroidMetricsServiceClient::RegisterAdditionalMetricsProviders(
MetricsService* service) {}
+bool AndroidMetricsServiceClient::EnablePersistentHistograms() {
+ return false;
+}
+
std::string AndroidMetricsServiceClient::GetAppPackageName() {
if (IsInPackageNameSample() && CanRecordPackageNameForAppType())
return GetAppPackageNameInternal();
@@ -330,4 +557,13 @@ std::string AndroidMetricsServiceClient::GetAppPackageNameInternal() {
return std::string();
}
+bool AndroidMetricsServiceClient::IsOffTheRecordSessionActive() {
+ return false;
+}
+
+scoped_refptr<network::SharedURLLoaderFactory>
+AndroidMetricsServiceClient::GetURLLoaderFactory() {
+ return nullptr;
+}
+
} // namespace metrics
diff --git a/chromium/components/embedder_support/android/metrics/android_metrics_service_client.h b/chromium/components/embedder_support/android/metrics/android_metrics_service_client.h
index eba14e98dd6..c5052d706ce 100644
--- a/chromium/components/embedder_support/android/metrics/android_metrics_service_client.h
+++ b/chromium/components/embedder_support/android/metrics/android_metrics_service_client.h
@@ -8,6 +8,8 @@
#include <memory>
#include <string>
+#include "base/callback_forward.h"
+#include "base/memory/scoped_refptr.h"
#include "base/metrics/field_trial.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
@@ -22,9 +24,15 @@
class PrefRegistrySimple;
class PrefService;
+namespace network {
+class SharedURLLoaderFactory;
+}
+
namespace metrics {
class MetricsStateManager;
+extern const char kCrashpadHistogramAllocatorName[];
+
// AndroidMetricsServiceClient is a singleton which manages metrics collection
// intended for use by WebView & WebLayer.
//
@@ -99,6 +107,16 @@ class AndroidMetricsServiceClient : public MetricsServiceClient,
std::unique_ptr<const base::FieldTrial::EntropyProvider>
CreateLowEntropyProvider();
+ // Updates the state of whether UKM is enabled or not by calling back into
+ // IsUkmAllowedForAllProfiles(). If |must_purge| is true then currently
+ // collected data will be purged.
+ void UpdateUkm(bool must_purge);
+
+ // Updates the state of the UKM service if it's running. This should be called
+ // when a BrowserContext is created or destroyed which would change the value
+ // of IsOffTheRecordSessionActive().
+ void UpdateUkmService();
+
// Whether or not consent state has been determined, regardless of whether
// it is positive or negative.
bool IsConsentDetermined() const;
@@ -109,6 +127,7 @@ class AndroidMetricsServiceClient : public MetricsServiceClient,
// MetricsServiceClient
MetricsService* GetMetricsService() override;
+ ukm::UkmService* GetUkmService() override;
void SetMetricsClientId(const std::string& client_id) override;
std::string GetApplicationLocale() override;
bool GetBrand(std::string* brand_code) override;
@@ -123,6 +142,7 @@ class AndroidMetricsServiceClient : public MetricsServiceClient,
MetricsLogUploader::MetricServiceType service_type,
const MetricsLogUploader::UploadCallback& on_upload_complete) override;
base::TimeDelta GetStandardUploadInterval() override;
+ bool IsUkmAllowedForAllProfiles() override;
bool ShouldStartUpFastForTesting() const override;
// Gets the embedding app's package name if it's OK to log. Otherwise, this
@@ -134,6 +154,9 @@ class AndroidMetricsServiceClient : public MetricsServiceClient,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
+ // Runs |closure| when CollectFinalMetricsForLog() is called.
+ void SetCollectFinalMetricsForLogClosureForTesting(base::OnceClosure closure);
+
metrics::MetricsStateManager* metrics_state_manager() const {
return metrics_state_manager_.get();
}
@@ -185,10 +208,22 @@ class AndroidMetricsServiceClient : public MetricsServiceClient,
// MetricsProviders. Does nothing by default.
virtual void RegisterAdditionalMetricsProviders(MetricsService* service);
+ // Called by CreateMetricsService if metrics should be persisted. If the
+ // client returns true then its
+ // variations::PlatformFieldTrials::SetupFieldTrials needs to also call
+ // InstantiatePersistentHistograms.
+ virtual bool EnablePersistentHistograms();
+
// Returns the embedding application's package name (unconditionally). Virtual
// for testing.
virtual std::string GetAppPackageNameInternal();
+ // Returns whether there are any OffTheRecord browsers/tabs open.
+ virtual bool IsOffTheRecordSessionActive();
+
+ // Returns a URLLoaderFactory when the system uploader isn't used.
+ virtual scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory();
+
void EnsureOnValidSequence() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
@@ -199,13 +234,14 @@ class AndroidMetricsServiceClient : public MetricsServiceClient,
void MaybeStartMetrics();
void RegisterForNotifications();
- std::unique_ptr<MetricsService> CreateMetricsService(
- MetricsStateManager* state_manager,
- AndroidMetricsServiceClient* client,
- PrefService* prefs);
+ void CreateMetricsService(MetricsStateManager* state_manager,
+ AndroidMetricsServiceClient* client,
+ PrefService* prefs);
+ void CreateUkmService();
std::unique_ptr<MetricsStateManager> metrics_state_manager_;
std::unique_ptr<MetricsService> metrics_service_;
+ std::unique_ptr<ukm::UkmService> ukm_service_;
content::NotificationRegistrar registrar_;
PrefService* pref_service_ = nullptr;
bool init_finished_ = false;
@@ -219,6 +255,8 @@ class AndroidMetricsServiceClient : public MetricsServiceClient,
// GetStandardUploadInterval().
base::TimeDelta overridden_upload_interval_;
+ base::OnceClosure collect_final_metrics_for_log_closure_;
+
// MetricsServiceClient may be created before the UI thread is promoted to
// BrowserThread::UI. Use |sequence_checker_| to enforce that the
// MetricsServiceClient is used on a single thread.
diff --git a/chromium/components/embedder_support/android/metrics/android_metrics_service_client_unittest.cc b/chromium/components/embedder_support/android/metrics/android_metrics_service_client_unittest.cc
index 60c1afa6a46..ac23eda0abe 100644
--- a/chromium/components/embedder_support/android/metrics/android_metrics_service_client_unittest.cc
+++ b/chromium/components/embedder_support/android/metrics/android_metrics_service_client_unittest.cc
@@ -104,7 +104,7 @@ class TestClient : public AndroidMetricsServiceClient {
std::unique_ptr<TestingPrefServiceSimple> CreateTestPrefs() {
auto prefs = std::make_unique<TestingPrefServiceSimple>();
- metrics::MetricsService::RegisterPrefs(prefs->registry());
+ AndroidMetricsServiceClient::RegisterPrefs(prefs->registry());
return prefs;
}
diff --git a/chromium/components/embedder_support/android/view/content_view_render_view.h b/chromium/components/embedder_support/android/view/content_view_render_view.h
index fe2feffd897..f56473ddf36 100644
--- a/chromium/components/embedder_support/android/view/content_view_render_view.h
+++ b/chromium/components/embedder_support/android/view/content_view_render_view.h
@@ -8,7 +8,6 @@
#include <memory>
#include "base/android/jni_weak_ref.h"
-#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/public/browser/android/compositor_client.h"
diff --git a/chromium/components/embedder_support/origin_trials/BUILD.gn b/chromium/components/embedder_support/origin_trials/BUILD.gn
index 05c82ec0843..db5d7668cd6 100644
--- a/chromium/components/embedder_support/origin_trials/BUILD.gn
+++ b/chromium/components/embedder_support/origin_trials/BUILD.gn
@@ -4,6 +4,8 @@
source_set("origin_trials") {
sources = [
+ "features.cc",
+ "features.h",
"origin_trial_policy_impl.cc",
"origin_trial_policy_impl.h",
]
diff --git a/chromium/components/embedder_support/origin_trials/features.cc b/chromium/components/embedder_support/origin_trials/features.cc
new file mode 100644
index 00000000000..4dba61a0203
--- /dev/null
+++ b/chromium/components/embedder_support/origin_trials/features.cc
@@ -0,0 +1,20 @@
+// Copyright (c) 2020 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.
+
+#include "components/embedder_support/origin_trials/features.h"
+
+#include "base/feature_list.h"
+
+namespace embedder_support {
+
+// The feature is enabled by default, ensuring user from no-op groups have
+// access to the underlying origin trial.
+// Users from experiment group will behave the same as default.
+// Users from control group will have the feature disabled, excluding them
+// from the origin trial.
+const base::Feature kOriginTrialsSampleAPIThirdPartyAlternativeUsage{
+ "OriginTrialsSampleAPIThirdPartyAlternativeUsage",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
+} // namespace embedder_support \ No newline at end of file
diff --git a/chromium/components/embedder_support/origin_trials/features.h b/chromium/components/embedder_support/origin_trials/features.h
new file mode 100644
index 00000000000..ff06364dd90
--- /dev/null
+++ b/chromium/components/embedder_support/origin_trials/features.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2020 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.
+
+#ifndef COMPONENTS_EMBEDDER_SUPPORT_ORIGIN_TRIALS_FEATURES_H_
+#define COMPONENTS_EMBEDDER_SUPPORT_ORIGIN_TRIALS_FEATURES_H_
+
+namespace base {
+struct Feature;
+}
+
+namespace embedder_support {
+
+// Sample field trial feature for testing alternative usage restriction in
+// origin trial third party tokens.
+extern const base::Feature kOriginTrialsSampleAPIThirdPartyAlternativeUsage;
+
+} // namespace embedder_support
+
+#endif // COMPONENTS_EMBEDDER_SUPPORT_ORIGIN_TRIALS_FEATURES_H_ \ No newline at end of file
diff --git a/chromium/components/embedder_support/origin_trials/origin_trial_policy_impl.cc b/chromium/components/embedder_support/origin_trials/origin_trial_policy_impl.cc
index ff7c911adcd..cf0d8433937 100644
--- a/chromium/components/embedder_support/origin_trials/origin_trial_policy_impl.cc
+++ b/chromium/components/embedder_support/origin_trials/origin_trial_policy_impl.cc
@@ -12,6 +12,7 @@
#include "base/feature_list.h"
#include "base/stl_util.h"
#include "base/strings/string_split.h"
+#include "components/embedder_support/origin_trials/features.h"
#include "components/embedder_support/switches.h"
#include "content/public/common/content_features.h"
#include "content/public/common/origin_util.h"
@@ -73,6 +74,25 @@ bool OriginTrialPolicyImpl::IsTokenDisabled(
return disabled_tokens_.count(token_signature.as_string()) > 0;
}
+// Exclude users in Field trial control group from the corresponding origin
+// trial. Users from experiment group/default group will have access to the
+// origin trial.
+bool OriginTrialPolicyImpl::IsFeatureDisabledForUser(
+ base::StringPiece feature) const {
+ struct OriginTrialFeatureToBaseFeatureMap {
+ const char* origin_trial_feature_name;
+ const base::Feature field_trial_feature;
+ } origin_trial_feature_to_field_trial_feature_map[] = {
+ {"FrobulateThirdParty",
+ kOriginTrialsSampleAPIThirdPartyAlternativeUsage}};
+ for (const auto& mapping : origin_trial_feature_to_field_trial_feature_map) {
+ if (feature == mapping.origin_trial_feature_name) {
+ return !base::FeatureList::IsEnabled(mapping.field_trial_feature);
+ }
+ }
+ return false;
+}
+
bool OriginTrialPolicyImpl::IsOriginSecure(const GURL& url) const {
return content::IsOriginSecure(url);
}
diff --git a/chromium/components/embedder_support/origin_trials/origin_trial_policy_impl.h b/chromium/components/embedder_support/origin_trials/origin_trial_policy_impl.h
index a5286a9a256..945f675b662 100644
--- a/chromium/components/embedder_support/origin_trials/origin_trial_policy_impl.h
+++ b/chromium/components/embedder_support/origin_trials/origin_trial_policy_impl.h
@@ -25,6 +25,7 @@ class OriginTrialPolicyImpl : public blink::OriginTrialPolicy {
bool IsOriginTrialsSupported() const override;
std::vector<base::StringPiece> GetPublicKeys() const override;
bool IsFeatureDisabled(base::StringPiece feature) const override;
+ bool IsFeatureDisabledForUser(base::StringPiece feature) const override;
bool IsTokenDisabled(base::StringPiece token_signature) const override;
bool IsOriginSecure(const GURL& url) const override;
diff --git a/chromium/components/embedder_support/origin_trials/origin_trial_policy_impl_unittest.cc b/chromium/components/embedder_support/origin_trials/origin_trial_policy_impl_unittest.cc
index 0407bb02544..38139fe75ec 100644
--- a/chromium/components/embedder_support/origin_trials/origin_trial_policy_impl_unittest.cc
+++ b/chromium/components/embedder_support/origin_trials/origin_trial_policy_impl_unittest.cc
@@ -11,6 +11,8 @@
#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
+#include "base/test/scoped_feature_list.h"
+#include "components/embedder_support/origin_trials/features.h"
#include "components/embedder_support/switches.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -265,6 +267,17 @@ TEST_F(OriginTrialPolicyImplTest, DisableThreeTokens) {
EXPECT_TRUE(manager()->IsTokenDisabled(token3_signature_));
}
+TEST_F(OriginTrialPolicyImplTest, DisableFeatureForUser) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ kOriginTrialsSampleAPIThirdPartyAlternativeUsage);
+ EXPECT_FALSE(manager()->IsFeatureDisabledForUser("FrobulateThirdParty"));
+ feature_list.Reset();
+ feature_list.InitAndDisableFeature(
+ kOriginTrialsSampleAPIThirdPartyAlternativeUsage);
+ EXPECT_TRUE(manager()->IsFeatureDisabledForUser("FrobulateThirdParty"));
+}
+
// Tests for initialization from command line
class OriginTrialPolicyImplInitializationTest
: public OriginTrialPolicyImplTest {