Commit f9f209f5 authored by Peter E Conn's avatar Peter E Conn Committed by Chromium LUCI CQ

🍱 Remove OriginVerifier dependency on BrowserServicesMetrics.

Change-Id: I785b071c73e7006bf68b25c3fbd6f852d470299a
Bug: 1164866
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2621062Reviewed-by: default avatarElla Ge <eirage@chromium.org>
Commit-Queue: Peter Conn <peconn@chromium.org>
Cr-Commit-Position: refs/heads/master@{#842058}
parent 0d10e5c7
...@@ -6,44 +6,23 @@ package org.chromium.chrome.browser.browserservices; ...@@ -6,44 +6,23 @@ package org.chromium.chrome.browser.browserservices;
import android.os.SystemClock; import android.os.SystemClock;
import androidx.annotation.IntDef;
import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordHistogram;
import org.chromium.chrome.browser.browserservices.verification.OriginVerifier;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/** /**
* Class to contain metrics recording constants and behaviour for Browser Services. * Class to contain metrics recording constants and behaviour for Browser Services.
*/ */
public class BrowserServicesMetrics { public class BrowserServicesMetrics {
@IntDef({VerificationResult.ONLINE_SUCCESS, VerificationResult.ONLINE_FAILURE, /** Implementation of {@link OriginVerifier.MetricsListener}. */
VerificationResult.OFFLINE_SUCCESS, VerificationResult.OFFLINE_FAILURE, public static class OriginVerifierMetricsListener implements OriginVerifier.MetricsListener {
VerificationResult.HTTPS_FAILURE, VerificationResult.REQUEST_FAILURE, @Override
VerificationResult.CACHED_SUCCESS}) public void recordVerificationResult(@OriginVerifier.VerificationResult int result) {
@Retention(RetentionPolicy.SOURCE) RecordHistogram.recordEnumeratedHistogram("BrowserServices.VerificationResult", result,
public @interface VerificationResult { OriginVerifier.VerificationResult.NUM_ENTRIES);
// Don't reuse values or reorder values. If you add something new, change NUM_ENTRIES as
// well.
int ONLINE_SUCCESS = 0;
int ONLINE_FAILURE = 1;
int OFFLINE_SUCCESS = 2;
int OFFLINE_FAILURE = 3;
int HTTPS_FAILURE = 4;
int REQUEST_FAILURE = 5;
int CACHED_SUCCESS = 6;
int NUM_ENTRIES = 7;
}
/**
* Records the verification result for Trusted Web Activity verification.
*/
public static void recordVerificationResult(@VerificationResult int result) {
RecordHistogram.recordEnumeratedHistogram(
"BrowserServices.VerificationResult", result, VerificationResult.NUM_ENTRIES);
} }
public static void recordVerificationTime(long duration, boolean online) { @Override
public void recordVerificationTime(long duration, boolean online) {
if (online) { if (online) {
RecordHistogram.recordTimesHistogram( RecordHistogram.recordTimesHistogram(
"BrowserServices.VerificationTime.Online", duration); "BrowserServices.VerificationTime.Online", duration);
...@@ -52,6 +31,7 @@ public class BrowserServicesMetrics { ...@@ -52,6 +31,7 @@ public class BrowserServicesMetrics {
"BrowserServices.VerificationTime.Offline", duration); "BrowserServices.VerificationTime.Offline", duration);
} }
} }
}
/** /**
* Returns a {@link TimingMetric} that records the amount of time spent querying the Android * Returns a {@link TimingMetric} that records the amount of time spent querying the Android
......
...@@ -9,6 +9,7 @@ import androidx.browser.customtabs.CustomTabsService; ...@@ -9,6 +9,7 @@ import androidx.browser.customtabs.CustomTabsService;
import org.chromium.base.Promise; import org.chromium.base.Promise;
import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider; import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider;
import org.chromium.chrome.browser.browserservices.BrowserServicesMetrics;
import org.chromium.chrome.browser.browserservices.ui.controller.Verifier; import org.chromium.chrome.browser.browserservices.ui.controller.Verifier;
import org.chromium.chrome.browser.browserservices.verification.OriginVerifier; import org.chromium.chrome.browser.browserservices.verification.OriginVerifier;
import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider; import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider;
...@@ -62,8 +63,9 @@ public class TwaVerifier implements Verifier, Destroyable { ...@@ -62,8 +63,9 @@ public class TwaVerifier implements Verifier, Destroyable {
// TODO(peconn): See if we can get rid of the dependency on Web Contents. // TODO(peconn): See if we can get rid of the dependency on Web Contents.
WebContents webContents = WebContents webContents =
tabProvider.getTab() != null ? tabProvider.getTab().getWebContents() : null; tabProvider.getTab() != null ? tabProvider.getTab().getWebContents() : null;
mOriginVerifier = originVerifierFactory.create( mOriginVerifier = originVerifierFactory.create(clientPackageNameProvider.get(),
clientPackageNameProvider.get(), RELATIONSHIP, webContents, externalAuthUtils); RELATIONSHIP, webContents, externalAuthUtils,
new BrowserServicesMetrics.OriginVerifierMetricsListener());
lifecycleDispatcher.register(this); lifecycleDispatcher.register(this);
} }
......
...@@ -2,7 +2,6 @@ noparent = True ...@@ -2,7 +2,6 @@ noparent = True
include_rules = [ include_rules = [
"+base/android/java/src/org/chromium/base", "+base/android/java/src/org/chromium/base",
"!chrome/android/java/src/org/chromium/chrome/browser/browserservices",
"+chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences", "+chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences",
"+chrome/browser/profiles/android/java/src/org/chromium/chrome/browser/profiles", "+chrome/browser/profiles/android/java/src/org/chromium/chrome/browser/profiles",
"+components/embedder_support/android/java/src/org/chromium/components/embedder_support/util", "+components/embedder_support/android/java/src/org/chromium/components/embedder_support/util",
......
...@@ -11,6 +11,7 @@ import android.net.Uri; ...@@ -11,6 +11,7 @@ import android.net.Uri;
import android.os.SystemClock; import android.os.SystemClock;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
...@@ -27,7 +28,6 @@ import org.chromium.base.annotations.CalledByNative; ...@@ -27,7 +28,6 @@ import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods; import org.chromium.base.annotations.NativeMethods;
import org.chromium.base.task.PostTask; import org.chromium.base.task.PostTask;
import org.chromium.chrome.browser.browserservices.BrowserServicesMetrics;
import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.components.embedder_support.util.Origin; import org.chromium.components.embedder_support.util.Origin;
...@@ -39,6 +39,8 @@ import org.chromium.content_public.browser.WebContents; ...@@ -39,6 +39,8 @@ import org.chromium.content_public.browser.WebContents;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.InputStream; import java.io.InputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateEncodingException;
...@@ -81,6 +83,7 @@ public class OriginVerifier { ...@@ -81,6 +83,7 @@ public class OriginVerifier {
private long mNativeOriginVerifier; private long mNativeOriginVerifier;
private final Map<Origin, Set<OriginVerificationListener>> mListeners = new HashMap<>(); private final Map<Origin, Set<OriginVerificationListener>> mListeners = new HashMap<>();
private long mVerificationStartTime; private long mVerificationStartTime;
private final MetricsListener mMetricsListener;
@Nullable @Nullable
private WebContents mWebContents; private WebContents mWebContents;
@Nullable @Nullable
...@@ -93,6 +96,38 @@ public class OriginVerifier { ...@@ -93,6 +96,38 @@ public class OriginVerifier {
private static final AtomicReference<Set<String>> sVerificationOverrides = private static final AtomicReference<Set<String>> sVerificationOverrides =
new AtomicReference<>(); new AtomicReference<>();
@IntDef({VerificationResult.ONLINE_SUCCESS, VerificationResult.ONLINE_FAILURE,
VerificationResult.OFFLINE_SUCCESS, VerificationResult.OFFLINE_FAILURE,
VerificationResult.HTTPS_FAILURE, VerificationResult.REQUEST_FAILURE,
VerificationResult.CACHED_SUCCESS})
@Retention(RetentionPolicy.SOURCE)
public @interface VerificationResult {
// Don't reuse values or reorder values. If you add something new, change NUM_ENTRIES as
// well.
int ONLINE_SUCCESS = 0;
int ONLINE_FAILURE = 1;
int OFFLINE_SUCCESS = 2;
int OFFLINE_FAILURE = 3;
int HTTPS_FAILURE = 4;
int REQUEST_FAILURE = 5;
int CACHED_SUCCESS = 6;
int NUM_ENTRIES = 7;
}
/**
* Interface for recording metrics.
*/
public interface MetricsListener {
/** Called with the result of every verification attempt. */
default void recordVerificationResult(@VerificationResult int result) {}
/**
* Records the time verification takes. This is not recorded for HTTPS_FAILURE,
* HTTPS_FAILURE or CACHED_SUCCESS.
*/
default void recordVerificationTime(long duration, boolean online) {}
}
/** /**
* Factory that can be injected by Dagger. * Factory that can be injected by Dagger.
*/ */
...@@ -101,9 +136,17 @@ public class OriginVerifier { ...@@ -101,9 +136,17 @@ public class OriginVerifier {
@Inject @Inject
public Factory() {} public Factory() {}
public OriginVerifier create(String packageName, @Relation int relation,
@Nullable WebContents webContents, @Nullable ExternalAuthUtils externalAuthUtils,
MetricsListener metricsListener) {
return new OriginVerifier(
packageName, relation, webContents, externalAuthUtils, metricsListener);
}
public OriginVerifier create(String packageName, @Relation int relation, public OriginVerifier create(String packageName, @Relation int relation,
@Nullable WebContents webContents, @Nullable ExternalAuthUtils externalAuthUtils) { @Nullable WebContents webContents, @Nullable ExternalAuthUtils externalAuthUtils) {
return new OriginVerifier(packageName, relation, webContents, externalAuthUtils); return create(packageName, relation, webContents, externalAuthUtils,
new MetricsListener() {});
} }
} }
...@@ -225,12 +268,14 @@ public class OriginVerifier { ...@@ -225,12 +268,14 @@ public class OriginVerifier {
* verification. Can be null. * verification. Can be null.
*/ */
public OriginVerifier(String packageName, @Relation int relation, public OriginVerifier(String packageName, @Relation int relation,
@Nullable WebContents webContents, @Nullable ExternalAuthUtils externalAuthUtils) { @Nullable WebContents webContents, @Nullable ExternalAuthUtils externalAuthUtils,
MetricsListener metricsListener) {
mPackageName = packageName; mPackageName = packageName;
mSignatureFingerprint = getCertificateSHA256FingerprintForPackage(mPackageName); mSignatureFingerprint = getCertificateSHA256FingerprintForPackage(mPackageName);
mRelation = relation; mRelation = relation;
mWebContents = webContents; mWebContents = webContents;
mExternalAuthUtils = externalAuthUtils; mExternalAuthUtils = externalAuthUtils;
mMetricsListener = metricsListener;
} }
/** /**
...@@ -266,8 +311,7 @@ public class OriginVerifier { ...@@ -266,8 +311,7 @@ public class OriginVerifier {
if (TextUtils.isEmpty(scheme) if (TextUtils.isEmpty(scheme)
|| !UrlConstants.HTTPS_SCHEME.equals(scheme.toLowerCase(Locale.US))) { || !UrlConstants.HTTPS_SCHEME.equals(scheme.toLowerCase(Locale.US))) {
Log.i(TAG, "Verification failed for %s as not https.", origin); Log.i(TAG, "Verification failed for %s as not https.", origin);
BrowserServicesMetrics.recordVerificationResult( mMetricsListener.recordVerificationResult(VerificationResult.HTTPS_FAILURE);
BrowserServicesMetrics.VerificationResult.HTTPS_FAILURE);
PostTask.runOrPostTask( PostTask.runOrPostTask(
UiThreadTaskTraits.DEFAULT, new VerifiedCallback(origin, false, null)); UiThreadTaskTraits.DEFAULT, new VerifiedCallback(origin, false, null));
return; return;
...@@ -318,8 +362,7 @@ public class OriginVerifier { ...@@ -318,8 +362,7 @@ public class OriginVerifier {
OriginVerifierJni.get().verifyOrigin(mNativeOriginVerifier, OriginVerifier.this, OriginVerifierJni.get().verifyOrigin(mNativeOriginVerifier, OriginVerifier.this,
mPackageName, mSignatureFingerprint, origin.toString(), relationship); mPackageName, mSignatureFingerprint, origin.toString(), relationship);
if (!requestSent) { if (!requestSent) {
BrowserServicesMetrics.recordVerificationResult( mMetricsListener.recordVerificationResult(VerificationResult.REQUEST_FAILURE);
BrowserServicesMetrics.VerificationResult.REQUEST_FAILURE);
PostTask.runOrPostTask( PostTask.runOrPostTask(
UiThreadTaskTraits.DEFAULT, new VerifiedCallback(origin, false, false)); UiThreadTaskTraits.DEFAULT, new VerifiedCallback(origin, false, false));
} }
...@@ -414,13 +457,11 @@ public class OriginVerifier { ...@@ -414,13 +457,11 @@ public class OriginVerifier {
Origin origin = Origin.createOrThrow(originAsString); Origin origin = Origin.createOrThrow(originAsString);
switch (result) { switch (result) {
case RelationshipCheckResult.SUCCESS: case RelationshipCheckResult.SUCCESS:
BrowserServicesMetrics.recordVerificationResult( mMetricsListener.recordVerificationResult(VerificationResult.ONLINE_SUCCESS);
BrowserServicesMetrics.VerificationResult.ONLINE_SUCCESS);
originVerified(origin, true, true); originVerified(origin, true, true);
break; break;
case RelationshipCheckResult.FAILURE: case RelationshipCheckResult.FAILURE:
BrowserServicesMetrics.recordVerificationResult( mMetricsListener.recordVerificationResult(VerificationResult.ONLINE_FAILURE);
BrowserServicesMetrics.VerificationResult.ONLINE_FAILURE);
originVerified(origin, false, true); originVerified(origin, false, true);
break; break;
case RelationshipCheckResult.NO_CONNECTION: case RelationshipCheckResult.NO_CONNECTION:
...@@ -459,7 +500,7 @@ public class OriginVerifier { ...@@ -459,7 +500,7 @@ public class OriginVerifier {
if (online != null) { if (online != null) {
long duration = SystemClock.uptimeMillis() - mVerificationStartTime; long duration = SystemClock.uptimeMillis() - mVerificationStartTime;
BrowserServicesMetrics.recordVerificationTime(duration, online); mMetricsListener.recordVerificationTime(duration, online);
} }
cleanUp(); cleanUp();
...@@ -486,9 +527,9 @@ public class OriginVerifier { ...@@ -486,9 +527,9 @@ public class OriginVerifier {
boolean verified = VerificationResultStore.isRelationshipSaved( boolean verified = VerificationResultStore.isRelationshipSaved(
new Relationship(mPackageName, mSignatureFingerprint, origin, mRelation)); new Relationship(mPackageName, mSignatureFingerprint, origin, mRelation));
BrowserServicesMetrics.recordVerificationResult(verified mMetricsListener.recordVerificationResult(verified
? BrowserServicesMetrics.VerificationResult.OFFLINE_SUCCESS ? VerificationResult.OFFLINE_SUCCESS
: BrowserServicesMetrics.VerificationResult.OFFLINE_FAILURE); : VerificationResult.OFFLINE_FAILURE);
originVerified(origin, verified, false); originVerified(origin, verified, false);
} }
......
...@@ -30,6 +30,7 @@ import org.chromium.base.ContextUtils; ...@@ -30,6 +30,7 @@ import org.chromium.base.ContextUtils;
import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.task.PostTask; import org.chromium.base.task.PostTask;
import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.IntentHandler;
import org.chromium.chrome.browser.browserservices.BrowserServicesMetrics;
import org.chromium.chrome.browser.browserservices.PostMessageHandler; import org.chromium.chrome.browser.browserservices.PostMessageHandler;
import org.chromium.chrome.browser.browserservices.verification.OriginVerifier; import org.chromium.chrome.browser.browserservices.verification.OriginVerifier;
import org.chromium.chrome.browser.browserservices.verification.OriginVerifier.OriginVerificationListener; import org.chromium.chrome.browser.browserservices.verification.OriginVerifier.OriginVerificationListener;
...@@ -272,6 +273,9 @@ class ClientManager { ...@@ -272,6 +273,9 @@ class ClientManager {
} }
} }
// TODO(crbug.com/1164866): Inject the Factory/Supplier.
private final OriginVerifier.Factory mOriginVerifierFactory = new OriginVerifier.Factory();
private final Map<CustomTabsSessionToken, SessionParams> mSessionParams = new HashMap<>(); private final Map<CustomTabsSessionToken, SessionParams> mSessionParams = new HashMap<>();
private final SparseBooleanArray mUidHasCalledWarmup = new SparseBooleanArray(); private final SparseBooleanArray mUidHasCalledWarmup = new SparseBooleanArray();
...@@ -477,8 +481,10 @@ class ClientManager { ...@@ -477,8 +481,10 @@ class ClientManager {
} }
}; };
params.originVerifier = new OriginVerifier(params.getPackageName(), relation, params.originVerifier = mOriginVerifierFactory.create(params.getPackageName(), relation,
/* webContents= */ null, /* externalAuthUtils= */ null); /* webContents= */ null, /* externalAuthUtils= */ null,
new BrowserServicesMetrics.OriginVerifierMetricsListener());
PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT,
() -> { params.originVerifier.start(listener, origin); }); () -> { params.originVerifier.start(listener, origin); });
if (relation == CustomTabsService.RELATION_HANDLE_ALL_URLS if (relation == CustomTabsService.RELATION_HANDLE_ALL_URLS
......
...@@ -61,6 +61,8 @@ public class OriginVerifierTest { ...@@ -61,6 +61,8 @@ public class OriginVerifierTest {
"19:75:B2:F1:71:77:BC:89:A5:DF:F3:1F:9E:64:A6:CA:E2:81:A5" "19:75:B2:F1:71:77:BC:89:A5:DF:F3:1F:9E:64:A6:CA:E2:81:A5"
+ ":3D:C1:D1:D5:9B:1D:14:7F:E1:C8:2A:FA:00"; + ":3D:C1:D1:D5:9B:1D:14:7F:E1:C8:2A:FA:00";
private final OriginVerifier.Factory mFactory = new OriginVerifier.Factory();
private Origin mHttpsOrigin; private Origin mHttpsOrigin;
private Origin mHttpOrigin; private Origin mHttpOrigin;
private TestExternalAuthUtils mExternalAuthUtils; private TestExternalAuthUtils mExternalAuthUtils;
...@@ -103,9 +105,9 @@ public class OriginVerifierTest { ...@@ -103,9 +105,9 @@ public class OriginVerifierTest {
mHttpsOrigin = Origin.create("https://www.example.com"); mHttpsOrigin = Origin.create("https://www.example.com");
mHttpOrigin = Origin.create("http://www.android.com"); mHttpOrigin = Origin.create("http://www.android.com");
mHandleAllUrlsVerifier = new OriginVerifier(PACKAGE_NAME, mHandleAllUrlsVerifier = mFactory.create(PACKAGE_NAME,
CustomTabsService.RELATION_HANDLE_ALL_URLS, new MockWebContents(), null); CustomTabsService.RELATION_HANDLE_ALL_URLS, new MockWebContents(), null);
mUseAsOriginVerifier = new OriginVerifier(PACKAGE_NAME, mUseAsOriginVerifier = mFactory.create(PACKAGE_NAME,
CustomTabsService.RELATION_USE_AS_ORIGIN, /* webContents= */ null, null); CustomTabsService.RELATION_USE_AS_ORIGIN, /* webContents= */ null, null);
mVerificationResultSemaphore = new Semaphore(0); mVerificationResultSemaphore = new Semaphore(0);
...@@ -191,7 +193,7 @@ public class OriginVerifierTest { ...@@ -191,7 +193,7 @@ public class OriginVerifierTest {
@Test @Test
@SmallTest @SmallTest
public void testVerificationBypass() throws InterruptedException { public void testVerificationBypass() throws InterruptedException {
OriginVerifier verifier = new OriginVerifier( OriginVerifier verifier = mFactory.create(
PACKAGE_NAME, CustomTabsService.RELATION_HANDLE_ALL_URLS, null, mExternalAuthUtils); PACKAGE_NAME, CustomTabsService.RELATION_HANDLE_ALL_URLS, null, mExternalAuthUtils);
PostTask.postTask(UiThreadTaskTraits.DEFAULT, PostTask.postTask(UiThreadTaskTraits.DEFAULT,
......
...@@ -84,7 +84,7 @@ public class TwaVerifierTest { ...@@ -84,7 +84,7 @@ public class TwaVerifierTest {
when(mIntentDataProvider.getTrustedWebActivityAdditionalOrigins()) when(mIntentDataProvider.getTrustedWebActivityAdditionalOrigins())
.thenReturn(Collections.singletonList(ADDITIONAL_ORIGIN)); .thenReturn(Collections.singletonList(ADDITIONAL_ORIGIN));
when(mOriginVerifierFactory.create(anyString(), anyInt(), any(), any())) when(mOriginVerifierFactory.create(anyString(), anyInt(), any(), any(), any()))
.thenReturn(mOriginVerifier); .thenReturn(mOriginVerifier);
when(mClientPackageNameProvider.get()).thenReturn("some.package.name"); when(mClientPackageNameProvider.get()).thenReturn("some.package.name");
......
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