Commit 6575a81c authored by Benoit Lize's avatar Benoit Lize Committed by Commit Bot

customtabs: Report parallel request initial and final status.

Reports whether a parallel request successfully started, and its final
completion status.

Bug: 884751
Change-Id: Ic4c975bd22b7fca98c066970cb202b93e8c7ca8c
Reviewed-on: https://chromium-review.googlesource.com/c/1273150Reviewed-by: default avatarAlexandr Ilin <alexilin@chromium.org>
Commit-Queue: Benoit L <lizeb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#598757}
parent 580a0129
...@@ -167,6 +167,8 @@ public abstract class ChromeFeatureList { ...@@ -167,6 +167,8 @@ public abstract class ChromeFeatureList {
public static final String CCT_POST_MESSAGE_API = "CCTPostMessageAPI"; public static final String CCT_POST_MESSAGE_API = "CCTPostMessageAPI";
public static final String CCT_REDIRECT_PRECONNECT = "CCTRedirectPreconnect"; public static final String CCT_REDIRECT_PRECONNECT = "CCTRedirectPreconnect";
public static final String CCT_RESOURCE_PREFETCH = "CCTResourcePrefetch"; public static final String CCT_RESOURCE_PREFETCH = "CCTResourcePrefetch";
public static final String CCT_REPORT_PARALLEL_REQUEST_STATUS =
"CCTReportParallelRequestStatus";
public static final String CHROME_DUET = "ChromeDuet"; public static final String CHROME_DUET = "ChromeDuet";
// TODO(mdjones): Remove CHROME_HOME_SWIPE_VELOCITY_FEATURE or rename. // TODO(mdjones): Remove CHROME_HOME_SWIPE_VELOCITY_FEATURE or rename.
public static final String CHROME_HOME_SWIPE_VELOCITY_FEATURE = "ChromeHomeSwipeLogicVelocity"; public static final String CHROME_HOME_SWIPE_VELOCITY_FEATURE = "ChromeHomeSwipeLogicVelocity";
......
...@@ -37,6 +37,7 @@ import org.chromium.base.ThreadUtils; ...@@ -37,6 +37,7 @@ import org.chromium.base.ThreadUtils;
import org.chromium.base.TimeUtils; import org.chromium.base.TimeUtils;
import org.chromium.base.TraceEvent; import org.chromium.base.TraceEvent;
import org.chromium.base.VisibleForTesting; import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.library_loader.LibraryProcessType; import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.base.library_loader.ProcessInitException; import org.chromium.base.library_loader.ProcessInitException;
...@@ -96,6 +97,7 @@ public class CustomTabsConnection { ...@@ -96,6 +97,7 @@ public class CustomTabsConnection {
private static final String TAG = "ChromeConnection"; private static final String TAG = "ChromeConnection";
private static final String LOG_SERVICE_REQUESTS = "custom-tabs-log-service-requests"; private static final String LOG_SERVICE_REQUESTS = "custom-tabs-log-service-requests";
// Callback names for |extraCallback()|.
@VisibleForTesting @VisibleForTesting
static final String PAGE_LOAD_METRICS_CALLBACK = "NavigationMetrics"; static final String PAGE_LOAD_METRICS_CALLBACK = "NavigationMetrics";
static final String BOTTOM_BAR_SCROLL_STATE_CALLBACK = "onBottomBarScrollStateChanged"; static final String BOTTOM_BAR_SCROLL_STATE_CALLBACK = "onBottomBarScrollStateChanged";
...@@ -103,6 +105,10 @@ public class CustomTabsConnection { ...@@ -103,6 +105,10 @@ public class CustomTabsConnection {
static final String OPEN_IN_BROWSER_CALLBACK = "onOpenInBrowser"; static final String OPEN_IN_BROWSER_CALLBACK = "onOpenInBrowser";
@VisibleForTesting @VisibleForTesting
static final String ON_WARMUP_COMPLETED = "onWarmupCompleted"; static final String ON_WARMUP_COMPLETED = "onWarmupCompleted";
@VisibleForTesting
static final String ON_DETACHED_REQUEST_REQUESTED = "onDetachedRequestRequested";
@VisibleForTesting
static final String ON_DETACHED_REQUEST_COMPLETED = "onDetachedRequestCompleted";
// For CustomTabs.SpeculationStatusOnStart, see tools/metrics/enums.xml. Append only. // For CustomTabs.SpeculationStatusOnStart, see tools/metrics/enums.xml. Append only.
private static final int SPECULATION_STATUS_ON_START_ALLOWED = 0; private static final int SPECULATION_STATUS_ON_START_ALLOWED = 0;
...@@ -876,6 +882,19 @@ public class CustomTabsConnection { ...@@ -876,6 +882,19 @@ public class CustomTabsConnection {
if (mLogRequests) { if (mLogRequests) {
Log.w(TAG, "handleParallelRequest() = " + PARALLEL_REQUEST_MESSAGES[status]); Log.w(TAG, "handleParallelRequest() = " + PARALLEL_REQUEST_MESSAGES[status]);
} }
if ((status != ParallelRequestStatus.NO_REQUEST)
&& (status != ParallelRequestStatus.FAILURE_NOT_INITIALIZED)
&& (status != ParallelRequestStatus.FAILURE_NOT_AUTHORIZED)
&& ChromeFeatureList.isEnabled(
ChromeFeatureList.CCT_REPORT_PARALLEL_REQUEST_STATUS)) {
Bundle args = new Bundle();
Uri url = intent.getParcelableExtra(PARALLEL_REQUEST_URL_KEY);
args.putParcelable("url", url);
args.putInt("status", status);
safeExtraCallback(session, ON_DETACHED_REQUEST_REQUESTED, args);
}
return status; return status;
} }
...@@ -914,11 +933,13 @@ public class CustomTabsConnection { ...@@ -914,11 +933,13 @@ public class CustomTabsConnection {
String urlString = url.toString(); String urlString = url.toString();
String referrerString = referrer.toString(); String referrerString = referrer.toString();
nativeCreateAndStartDetachedResourceRequest(Profile.getLastUsedProfile(), urlString, nativeCreateAndStartDetachedResourceRequest(Profile.getLastUsedProfile(), session,
referrerString, policy, DetachedResourceRequestMotivation.PARALLEL_REQUEST); urlString, referrerString, policy,
DetachedResourceRequestMotivation.PARALLEL_REQUEST);
if (mLogRequests) { if (mLogRequests) {
Log.w(TAG, "startParallelRequest(%s, %s, %d)", urlString, referrerString, policy); Log.w(TAG, "startParallelRequest(%s, %s, %d)", urlString, referrerString, policy);
} }
return ParallelRequestStatus.SUCCESS; return ParallelRequestStatus.SUCCESS;
} }
...@@ -951,8 +972,10 @@ public class CustomTabsConnection { ...@@ -951,8 +972,10 @@ public class CustomTabsConnection {
String urlString = url.toString(); String urlString = url.toString();
if (urlString.isEmpty() || !isValid(url)) continue; if (urlString.isEmpty() || !isValid(url)) continue;
nativeCreateAndStartDetachedResourceRequest(Profile.getLastUsedProfile(), urlString, // Session is null because we don't need completion notifications.
referrerString, policy, DetachedResourceRequestMotivation.RESOURCE_PREFETCH); nativeCreateAndStartDetachedResourceRequest(Profile.getLastUsedProfile(), null,
urlString, referrerString, policy,
DetachedResourceRequestMotivation.RESOURCE_PREFETCH);
++requestsSent; ++requestsSent;
if (mLogRequests) { if (mLogRequests) {
...@@ -1489,7 +1512,8 @@ public class CustomTabsConnection { ...@@ -1489,7 +1512,8 @@ public class CustomTabsConnection {
} }
private static native void nativeCreateAndStartDetachedResourceRequest(Profile profile, private static native void nativeCreateAndStartDetachedResourceRequest(Profile profile,
String url, String origin, @WebReferrerPolicy int referrerPolicy, CustomTabsSessionToken session, String url, String origin,
@WebReferrerPolicy int referrerPolicy,
@DetachedResourceRequestMotivation int motivation); @DetachedResourceRequestMotivation int motivation);
public ModuleLoader getModuleLoader(ComponentName componentName) { public ModuleLoader getModuleLoader(ComponentName componentName) {
...@@ -1506,4 +1530,16 @@ public class CustomTabsConnection { ...@@ -1506,4 +1530,16 @@ public class CustomTabsConnection {
ActivityDelegate activityDelegate, int moduleVersion) { ActivityDelegate activityDelegate, int moduleVersion) {
mClientManager.setActivityDelegateForSession(sessionToken, activityDelegate, moduleVersion); mClientManager.setActivityDelegateForSession(sessionToken, activityDelegate, moduleVersion);
} }
@CalledByNative
public static void notifyClientOfDetachedRequestCompletion(
CustomTabsSessionToken session, String url, int status) {
if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_REPORT_PARALLEL_REQUEST_STATUS)) {
return;
}
Bundle args = new Bundle();
args.putParcelable("url", Uri.parse(url));
args.putInt("net_error", status);
getInstance().safeExtraCallback(session, ON_DETACHED_REQUEST_COMPLETED, args);
}
} }
...@@ -7,7 +7,11 @@ package org.chromium.chrome.browser.customtabs; ...@@ -7,7 +7,11 @@ package org.chromium.chrome.browser.customtabs;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle;
import android.support.customtabs.CustomTabsCallback;
import android.support.customtabs.CustomTabsIntent;
import android.support.customtabs.CustomTabsService; import android.support.customtabs.CustomTabsService;
import android.support.customtabs.CustomTabsSession;
import android.support.customtabs.CustomTabsSessionToken; import android.support.customtabs.CustomTabsSessionToken;
import android.support.test.InstrumentationRegistry; import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest; import android.support.test.filters.SmallTest;
...@@ -17,6 +21,7 @@ import org.junit.Assert; ...@@ -17,6 +21,7 @@ import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.chromium.base.PathUtils; import org.chromium.base.PathUtils;
...@@ -33,11 +38,13 @@ import org.chromium.chrome.browser.firstrun.FirstRunStatus; ...@@ -33,11 +38,13 @@ import org.chromium.chrome.browser.firstrun.FirstRunStatus;
import org.chromium.chrome.browser.preferences.PrefServiceBridge; import org.chromium.chrome.browser.preferences.PrefServiceBridge;
import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.util.browser.Features;
import org.chromium.chrome.test.util.browser.Features.EnableFeatures; import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
import org.chromium.components.safe_browsing.SafeBrowsingApiBridge; import org.chromium.components.safe_browsing.SafeBrowsingApiBridge;
import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.JavaScriptUtils; import org.chromium.content_public.browser.test.util.JavaScriptUtils;
import org.chromium.net.NetError;
import org.chromium.net.test.EmbeddedTestServer; import org.chromium.net.test.EmbeddedTestServer;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -50,6 +57,8 @@ import java.util.concurrent.TimeoutException; ...@@ -50,6 +57,8 @@ import java.util.concurrent.TimeoutException;
public class DetachedResourceRequestTest { public class DetachedResourceRequestTest {
@Rule @Rule
public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule(); public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule();
@Rule
public TestRule mProcessor = new Features.InstrumentationProcessor();
private CustomTabsConnection mConnection; private CustomTabsConnection mConnection;
private Context mContext; private Context mContext;
...@@ -57,6 +66,7 @@ public class DetachedResourceRequestTest { ...@@ -57,6 +66,7 @@ public class DetachedResourceRequestTest {
private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "chrome"; private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "chrome";
private static final Uri ORIGIN = Uri.parse("http://cats.google.com"); private static final Uri ORIGIN = Uri.parse("http://cats.google.com");
private static final int NET_OK = 0;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
...@@ -78,7 +88,6 @@ public class DetachedResourceRequestTest { ...@@ -78,7 +88,6 @@ public class DetachedResourceRequestTest {
@Test @Test
@SmallTest @SmallTest
@EnableFeatures(ChromeFeatureList.CCT_PARALLEL_REQUEST)
public void testCanDoParallelRequest() throws Exception { public void testCanDoParallelRequest() throws Exception {
CustomTabsSessionToken session = CustomTabsSessionToken.createMockSessionTokenForTesting(); CustomTabsSessionToken session = CustomTabsSessionToken.createMockSessionTokenForTesting();
Assert.assertTrue(mConnection.newSession(session)); Assert.assertTrue(mConnection.newSession(session));
...@@ -126,7 +135,6 @@ public class DetachedResourceRequestTest { ...@@ -126,7 +135,6 @@ public class DetachedResourceRequestTest {
@Test @Test
@SmallTest @SmallTest
@EnableFeatures(ChromeFeatureList.CCT_PARALLEL_REQUEST)
public void testStartParallelRequestValidation() throws Exception { public void testStartParallelRequestValidation() throws Exception {
CustomTabsSessionToken session = prepareSession(); CustomTabsSessionToken session = prepareSession();
...@@ -203,9 +211,8 @@ public class DetachedResourceRequestTest { ...@@ -203,9 +211,8 @@ public class DetachedResourceRequestTest {
@Test @Test
@SmallTest @SmallTest
@EnableFeatures(ChromeFeatureList.CCT_PARALLEL_REQUEST) @EnableFeatures(ChromeFeatureList.CCT_REPORT_PARALLEL_REQUEST_STATUS)
public void testCanStartParallelRequest() throws Exception { public void testCanStartParallelRequest() throws Exception {
CustomTabsSessionToken session = prepareSession();
final CallbackHelper cb = new CallbackHelper(); final CallbackHelper cb = new CallbackHelper();
setUpTestServerWithListener(new EmbeddedTestServer.ConnectionListener() { setUpTestServerWithListener(new EmbeddedTestServer.ConnectionListener() {
@Override @Override
...@@ -213,18 +220,71 @@ public class DetachedResourceRequestTest { ...@@ -213,18 +220,71 @@ public class DetachedResourceRequestTest {
cb.notifyCalled(); cb.notifyCalled();
} }
}); });
Uri url = Uri.parse(mServer.getURL("/echotitle")); Uri url = Uri.parse(mServer.getURL("/echotitle"));
DetachedResourceRequestCheckCallback customTabsCallback =
new DetachedResourceRequestCheckCallback(
url, CustomTabsConnection.ParallelRequestStatus.SUCCESS, NET_OK);
CustomTabsSessionToken session = prepareSession(ORIGIN, customTabsCallback);
ThreadUtils.runOnUiThread(() -> { ThreadUtils.runOnUiThread(() -> {
Assert.assertEquals(CustomTabsConnection.ParallelRequestStatus.SUCCESS, Assert.assertEquals(CustomTabsConnection.ParallelRequestStatus.SUCCESS,
mConnection.handleParallelRequest(session, prepareIntent(url, ORIGIN))); mConnection.handleParallelRequest(session, prepareIntent(url, ORIGIN)));
}); });
customTabsCallback.waitForRequest();
cb.waitForCallback(0, 1); cb.waitForCallback(0, 1);
customTabsCallback.waitForCompletion();
}
@Test
@SmallTest
@EnableFeatures(ChromeFeatureList.CCT_REPORT_PARALLEL_REQUEST_STATUS)
public void testParallelRequestFailureCallback() throws Exception {
Uri url = Uri.parse("http://request-url");
int status =
CustomTabsConnection.ParallelRequestStatus.FAILURE_INVALID_REFERRER_FOR_SESSION;
DetachedResourceRequestCheckCallback customTabsCallback =
new DetachedResourceRequestCheckCallback(url, status, 0);
CustomTabsSessionToken session = prepareSession(ORIGIN, customTabsCallback);
ThreadUtils.runOnUiThread(() -> {
Assert.assertEquals(status,
mConnection.handleParallelRequest(
session, prepareIntent(url, Uri.parse("http://not-the-right-origin"))));
});
customTabsCallback.waitForRequest();
}
@Test
@SmallTest
@EnableFeatures(ChromeFeatureList.CCT_REPORT_PARALLEL_REQUEST_STATUS)
public void testParallelRequestCompletionFailureCallback() throws Exception {
final CallbackHelper cb = new CallbackHelper();
setUpTestServerWithListener(new EmbeddedTestServer.ConnectionListener() {
@Override
public void readFromSocket(long socketId) {
cb.notifyCalled();
}
});
Uri url = Uri.parse(mServer.getURL("/close-socket"));
DetachedResourceRequestCheckCallback customTabsCallback =
new DetachedResourceRequestCheckCallback(url,
CustomTabsConnection.ParallelRequestStatus.SUCCESS,
Math.abs(NetError.ERR_EMPTY_RESPONSE));
CustomTabsSessionToken session = prepareSession(ORIGIN, customTabsCallback);
ThreadUtils.runOnUiThread(() -> {
Assert.assertEquals(CustomTabsConnection.ParallelRequestStatus.SUCCESS,
mConnection.handleParallelRequest(session, prepareIntent(url, ORIGIN)));
});
customTabsCallback.waitForRequest();
cb.waitForCallback(0, 1);
customTabsCallback.waitForCompletion();
} }
@Test @Test
@SmallTest @SmallTest
@EnableFeatures(ChromeFeatureList.CCT_RESOURCE_PREFETCH)
public void testCanStartResourcePrefetch() throws Exception { public void testCanStartResourcePrefetch() throws Exception {
CustomTabsSessionToken session = prepareSession(); CustomTabsSessionToken session = prepareSession();
final CallbackHelper cb = new CallbackHelper(); final CallbackHelper cb = new CallbackHelper();
...@@ -249,15 +309,22 @@ public class DetachedResourceRequestTest { ...@@ -249,15 +309,22 @@ public class DetachedResourceRequestTest {
@Test @Test
@SmallTest @SmallTest
@EnableFeatures(ChromeFeatureList.CCT_PARALLEL_REQUEST) @EnableFeatures(ChromeFeatureList.CCT_REPORT_PARALLEL_REQUEST_STATUS)
public void testCanSetCookie() throws Exception { public void testCanSetCookie() throws Exception {
CustomTabsSessionToken session = prepareSession();
mServer = EmbeddedTestServer.createAndStartServer(mContext); mServer = EmbeddedTestServer.createAndStartServer(mContext);
final Uri url = Uri.parse(mServer.getURL("/set-cookie?acookie")); final Uri url = Uri.parse(mServer.getURL("/set-cookie?acookie"));
DetachedResourceRequestCheckCallback customTabsCallback =
new DetachedResourceRequestCheckCallback(
url, CustomTabsConnection.ParallelRequestStatus.SUCCESS, NET_OK);
CustomTabsSessionToken session = prepareSession(ORIGIN, customTabsCallback);
ThreadUtils.runOnUiThreadBlocking(() -> { ThreadUtils.runOnUiThreadBlocking(() -> {
Assert.assertEquals(CustomTabsConnection.ParallelRequestStatus.SUCCESS, Assert.assertEquals(CustomTabsConnection.ParallelRequestStatus.SUCCESS,
mConnection.handleParallelRequest(session, prepareIntent(url, ORIGIN))); mConnection.handleParallelRequest(session, prepareIntent(url, ORIGIN)));
}); });
customTabsCallback.waitForRequest();
customTabsCallback.waitForCompletion();
String echoUrl = mServer.getURL("/echoheader?Cookie"); String echoUrl = mServer.getURL("/echoheader?Cookie");
Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(mContext, echoUrl); Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(mContext, echoUrl);
...@@ -275,7 +342,6 @@ public class DetachedResourceRequestTest { ...@@ -275,7 +342,6 @@ public class DetachedResourceRequestTest {
*/ */
@Test @Test
@SmallTest @SmallTest
@EnableFeatures(ChromeFeatureList.CCT_PARALLEL_REQUEST)
public void testSafeBrowsingMainResource() throws Exception { public void testSafeBrowsingMainResource() throws Exception {
SafeBrowsingApiBridge.setSafeBrowsingHandlerType( SafeBrowsingApiBridge.setSafeBrowsingHandlerType(
new MockSafeBrowsingApiHandler().getClass()); new MockSafeBrowsingApiHandler().getClass());
...@@ -309,7 +375,6 @@ public class DetachedResourceRequestTest { ...@@ -309,7 +375,6 @@ public class DetachedResourceRequestTest {
*/ */
@Test @Test
@SmallTest @SmallTest
@EnableFeatures(ChromeFeatureList.CCT_PARALLEL_REQUEST)
public void testSafeBrowsingSubresource() throws Exception { public void testSafeBrowsingSubresource() throws Exception {
SafeBrowsingApiBridge.setSafeBrowsingHandlerType( SafeBrowsingApiBridge.setSafeBrowsingHandlerType(
new MockSafeBrowsingApiHandler().getClass()); new MockSafeBrowsingApiHandler().getClass());
...@@ -337,7 +402,6 @@ public class DetachedResourceRequestTest { ...@@ -337,7 +402,6 @@ public class DetachedResourceRequestTest {
@Test @Test
@SmallTest @SmallTest
@EnableFeatures(ChromeFeatureList.CCT_PARALLEL_REQUEST)
public void testCanBlockThirdPartyCookies() throws Exception { public void testCanBlockThirdPartyCookies() throws Exception {
CustomTabsSessionToken session = prepareSession(); CustomTabsSessionToken session = prepareSession();
mServer = EmbeddedTestServer.createAndStartServer(mContext); mServer = EmbeddedTestServer.createAndStartServer(mContext);
...@@ -364,7 +428,6 @@ public class DetachedResourceRequestTest { ...@@ -364,7 +428,6 @@ public class DetachedResourceRequestTest {
@Test @Test
@SmallTest @SmallTest
@EnableFeatures(ChromeFeatureList.CCT_PARALLEL_REQUEST)
public void testThirdPartyCookieBlockingAllowsFirstParty() throws Exception { public void testThirdPartyCookieBlockingAllowsFirstParty() throws Exception {
CustomTabsTestUtils.warmUpAndWait(); CustomTabsTestUtils.warmUpAndWait();
mServer = EmbeddedTestServer.createAndStartServer(mContext); mServer = EmbeddedTestServer.createAndStartServer(mContext);
...@@ -393,22 +456,28 @@ public class DetachedResourceRequestTest { ...@@ -393,22 +456,28 @@ public class DetachedResourceRequestTest {
} }
private CustomTabsSessionToken prepareSession() throws Exception { private CustomTabsSessionToken prepareSession() throws Exception {
return prepareSession(ORIGIN); return prepareSession(ORIGIN, null);
} }
private CustomTabsSessionToken prepareSession(Uri origin) throws Exception { private CustomTabsSessionToken prepareSession(Uri origin) throws Exception {
final CustomTabsSessionToken session = return prepareSession(origin, null);
CustomTabsSessionToken.createMockSessionTokenForTesting(); }
Assert.assertTrue(mConnection.newSession(session));
mConnection.mClientManager.setAllowParallelRequestForSession(session, true); private CustomTabsSessionToken prepareSession(Uri origin, CustomTabsCallback callback)
mConnection.mClientManager.setAllowResourcePrefetchForSession(session, true); throws Exception {
CustomTabsSession session = CustomTabsTestUtils.bindWithCallback(callback);
Intent intent = (new CustomTabsIntent.Builder(session)).build().intent;
CustomTabsSessionToken token = CustomTabsSessionToken.getSessionTokenFromIntent(intent);
Assert.assertTrue(mConnection.newSession(token));
mConnection.mClientManager.setAllowParallelRequestForSession(token, true);
mConnection.mClientManager.setAllowResourcePrefetchForSession(token, true);
CustomTabsTestUtils.warmUpAndWait(); CustomTabsTestUtils.warmUpAndWait();
ThreadUtils.runOnUiThreadBlocking(() -> { ThreadUtils.runOnUiThreadBlocking(() -> {
OriginVerifier.addVerifiedOriginForPackage(mContext.getPackageName(), OriginVerifier.addVerifiedOriginForPackage(mContext.getPackageName(),
new Origin(origin.toString()), CustomTabsService.RELATION_USE_AS_ORIGIN); new Origin(origin.toString()), CustomTabsService.RELATION_USE_AS_ORIGIN);
Assert.assertTrue(mConnection.canDoParallelRequest(session, origin)); Assert.assertTrue(mConnection.canDoParallelRequest(token, origin));
}); });
return session; return token;
} }
private void setUpTestServerWithListener(EmbeddedTestServer.ConnectionListener listener) private void setUpTestServerWithListener(EmbeddedTestServer.ConnectionListener listener)
...@@ -456,4 +525,45 @@ public class DetachedResourceRequestTest { ...@@ -456,4 +525,45 @@ public class DetachedResourceRequestTest {
intent.putExtra(CustomTabsConnection.PARALLEL_REQUEST_REFERRER_KEY, referrer); intent.putExtra(CustomTabsConnection.PARALLEL_REQUEST_REFERRER_KEY, referrer);
return intent; return intent;
} }
private static class DetachedResourceRequestCheckCallback extends CustomTabsCallback {
private final Uri mExpectedUrl;
private final int mExpectedRequestStatus;
private final int mExpectedFinalStatus;
private final CallbackHelper mRequestedWaiter = new CallbackHelper();
private final CallbackHelper mCompletionWaiter = new CallbackHelper();
public DetachedResourceRequestCheckCallback(
Uri expectedUrl, int expectedRequestStatus, int expectedFinalStatus) {
super();
mExpectedUrl = expectedUrl;
mExpectedRequestStatus = expectedRequestStatus;
mExpectedFinalStatus = expectedFinalStatus;
}
@Override
public void extraCallback(String callbackName, Bundle args) {
if (CustomTabsConnection.ON_DETACHED_REQUEST_REQUESTED.equals(callbackName)) {
Uri url = args.getParcelable("url");
int status = args.getInt("status");
Assert.assertEquals(mExpectedUrl, url);
Assert.assertEquals(mExpectedRequestStatus, status);
mRequestedWaiter.notifyCalled();
} else if (CustomTabsConnection.ON_DETACHED_REQUEST_COMPLETED.equals(callbackName)) {
Uri url = args.getParcelable("url");
int status = args.getInt("net_error");
Assert.assertEquals(mExpectedUrl, url);
Assert.assertEquals(mExpectedFinalStatus, status);
mCompletionWaiter.notifyCalled();
}
}
public void waitForRequest() throws InterruptedException, TimeoutException {
mRequestedWaiter.waitForCallback(0, 1);
}
public void waitForCompletion() throws InterruptedException, TimeoutException {
mCompletionWaiter.waitForCallback(0, 1);
}
}
} }
...@@ -85,6 +85,7 @@ const base::Feature* kFeaturesExposedToJava[] = { ...@@ -85,6 +85,7 @@ const base::Feature* kFeaturesExposedToJava[] = {
&kCCTParallelRequest, &kCCTParallelRequest,
&kCCTPostMessageAPI, &kCCTPostMessageAPI,
&kCCTRedirectPreconnect, &kCCTRedirectPreconnect,
&kCCTReportParallelRequestStatus,
&kCCTResourcePrefetch, &kCCTResourcePrefetch,
&kChromeDuetFeature, &kChromeDuetFeature,
&kChromeHomeSwipeLogic, &kChromeHomeSwipeLogic,
...@@ -230,6 +231,9 @@ const base::Feature kCCTPostMessageAPI{"CCTPostMessageAPI", ...@@ -230,6 +231,9 @@ const base::Feature kCCTPostMessageAPI{"CCTPostMessageAPI",
const base::Feature kCCTRedirectPreconnect{"CCTRedirectPreconnect", const base::Feature kCCTRedirectPreconnect{"CCTRedirectPreconnect",
base::FEATURE_ENABLED_BY_DEFAULT}; base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kCCTReportParallelRequestStatus{
"CCTReportParallelRequestStatus", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kCCTResourcePrefetch{"CCTResourcePrefetch", const base::Feature kCCTResourcePrefetch{"CCTResourcePrefetch",
base::FEATURE_ENABLED_BY_DEFAULT}; base::FEATURE_ENABLED_BY_DEFAULT};
......
...@@ -27,6 +27,7 @@ extern const base::Feature kCCTModuleCache; ...@@ -27,6 +27,7 @@ extern const base::Feature kCCTModuleCache;
extern const base::Feature kCCTParallelRequest; extern const base::Feature kCCTParallelRequest;
extern const base::Feature kCCTPostMessageAPI; extern const base::Feature kCCTPostMessageAPI;
extern const base::Feature kCCTRedirectPreconnect; extern const base::Feature kCCTRedirectPreconnect;
extern const base::Feature kCCTReportParallelRequestStatus;
extern const base::Feature kCCTResourcePrefetch; extern const base::Feature kCCTResourcePrefetch;
extern const base::Feature kChromeDuetFeature; extern const base::Feature kChromeDuetFeature;
extern const base::Feature kChromeHomeSwipeLogic; extern const base::Feature kChromeHomeSwipeLogic;
......
...@@ -139,7 +139,9 @@ void DetachedResourceRequest::OnResponseCallback( ...@@ -139,7 +139,9 @@ void DetachedResourceRequest::OnResponseCallback(
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
int net_error = url_loader_->NetError(); int net_error = url_loader_->NetError();
bool success = net_error == net::OK; bool success = net_error == net::OK;
net_error = std::abs(net_error);
auto duration = base::TimeTicks::Now() - start_time_; auto duration = base::TimeTicks::Now() - start_time_;
switch (motivation_) { switch (motivation_) {
case Motivation::kParallelRequest: { case Motivation::kParallelRequest: {
if (success) { if (success) {
...@@ -158,7 +160,7 @@ void DetachedResourceRequest::OnResponseCallback( ...@@ -158,7 +160,7 @@ void DetachedResourceRequest::OnResponseCallback(
} }
base::UmaHistogramSparse("CustomTabs.DetachedResourceRequest.FinalStatus", base::UmaHistogramSparse("CustomTabs.DetachedResourceRequest.FinalStatus",
std::abs(net_error)); net_error);
break; break;
} }
case Motivation::kResourcePrefetch: { case Motivation::kResourcePrefetch: {
...@@ -171,12 +173,12 @@ void DetachedResourceRequest::OnResponseCallback( ...@@ -171,12 +173,12 @@ void DetachedResourceRequest::OnResponseCallback(
} }
base::UmaHistogramSparse("CustomTabs.ResourcePrefetch.FinalStatus", base::UmaHistogramSparse("CustomTabs.ResourcePrefetch.FinalStatus",
std::abs(net_error)); net_error);
break; break;
} }
} }
std::move(cb_).Run(success); std::move(cb_).Run(net_error);
} }
} // namespace customtabs } // namespace customtabs
...@@ -44,13 +44,13 @@ class DetachedResourceRequest { ...@@ -44,13 +44,13 @@ class DetachedResourceRequest {
// GENERATED_JAVA_CLASS_NAME_OVERRIDE: DetachedResourceRequestMotivation // GENERATED_JAVA_CLASS_NAME_OVERRIDE: DetachedResourceRequestMotivation
enum class Motivation { kParallelRequest, kResourcePrefetch }; enum class Motivation { kParallelRequest, kResourcePrefetch };
using OnResultCallback = base::OnceCallback<void(bool success)>; using OnResultCallback = base::OnceCallback<void(int net_error)>;
~DetachedResourceRequest(); ~DetachedResourceRequest();
// Creates a detached request to a |url|, with a given initiating URL, // Creates a detached request to a |url|, with a given initiating URL,
// |first_party_for_cookies|. Called on the UI thread. // |first_party_for_cookies|. Called on the UI thread.
// Optional |cb| to get notified about the fetch result, for testing. // Optional |cb| to get notified about the fetch result.
static void CreateAndStart(content::BrowserContext* browser_context, static void CreateAndStart(content::BrowserContext* browser_context,
const GURL& url, const GURL& url,
const GURL& first_party_for_cookies, const GURL& first_party_for_cookies,
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "base/android/jni_android.h" #include "base/android/jni_android.h"
#include "base/android/jni_string.h" #include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h" #include "base/android/scoped_java_ref.h"
#include "base/bind.h"
#include "chrome/browser/android/customtabs/detached_resource_request.h" #include "chrome/browser/android/customtabs/detached_resource_request.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_android.h" #include "chrome/browser/profiles/profile_android.h"
...@@ -15,10 +16,25 @@ ...@@ -15,10 +16,25 @@
namespace customtabs { namespace customtabs {
namespace {
void NotifyClientOfDetachedRequestCompletion(
const base::android::ScopedJavaGlobalRef<jobject>& session,
const GURL& url,
int net_error) {
JNIEnv* env = base::android::AttachCurrentThread();
Java_CustomTabsConnection_notifyClientOfDetachedRequestCompletion(
env, session, base::android::ConvertUTF8ToJavaString(env, url.spec()),
net_error);
}
} // namespace
static void JNI_CustomTabsConnection_CreateAndStartDetachedResourceRequest( static void JNI_CustomTabsConnection_CreateAndStartDetachedResourceRequest(
JNIEnv* env, JNIEnv* env,
const base::android::JavaParamRef<jclass>& jcaller, const base::android::JavaParamRef<jclass>& jcaller,
const base::android::JavaParamRef<jobject>& profile, const base::android::JavaParamRef<jobject>& profile,
const base::android::JavaParamRef<jobject>& session,
const base::android::JavaParamRef<jstring>& url, const base::android::JavaParamRef<jstring>& url,
const base::android::JavaParamRef<jstring>& origin, const base::android::JavaParamRef<jstring>& origin,
jint referrer_policy, jint referrer_policy,
...@@ -39,9 +55,17 @@ static void JNI_CustomTabsConnection_CreateAndStartDetachedResourceRequest( ...@@ -39,9 +55,17 @@ static void JNI_CustomTabsConnection_CreateAndStartDetachedResourceRequest(
static_cast<blink::WebReferrerPolicy>(referrer_policy)); static_cast<blink::WebReferrerPolicy>(referrer_policy));
DetachedResourceRequest::Motivation request_motivation = DetachedResourceRequest::Motivation request_motivation =
static_cast<DetachedResourceRequest::Motivation>(motivation); static_cast<DetachedResourceRequest::Motivation>(motivation);
DetachedResourceRequest::OnResultCallback cb =
session.is_null()
? base::DoNothing()
: base::BindOnce(&NotifyClientOfDetachedRequestCompletion,
base::android::ScopedJavaGlobalRef<jobject>(session),
native_url);
DetachedResourceRequest::CreateAndStart( DetachedResourceRequest::CreateAndStart(
native_profile, native_url, native_origin, url_request_referrer_policy, native_profile, native_url, native_origin, url_request_referrer_policy,
request_motivation); request_motivation, std::move(cb));
} }
} // namespace customtabs } // namespace customtabs
...@@ -228,8 +228,8 @@ class DetachedResourceRequestTest : public ::testing::Test { ...@@ -228,8 +228,8 @@ class DetachedResourceRequestTest : public ::testing::Test {
DetachedResourceRequest::CreateAndStart( DetachedResourceRequest::CreateAndStart(
browser_context(), url, site_for_cookies, policy, kMotivation, browser_context(), url, site_for_cookies, policy, kMotivation,
base::BindLambdaForTesting([&](bool success) { base::BindLambdaForTesting([&](int net_error) {
EXPECT_TRUE(success); EXPECT_EQ(net::OK, net_error);
request_completion_waiter.Quit(); request_completion_waiter.Quit();
})); }));
server_request_waiter.Run(); server_request_waiter.Run();
...@@ -260,8 +260,8 @@ TEST_F(DetachedResourceRequestTest, Simple) { ...@@ -260,8 +260,8 @@ TEST_F(DetachedResourceRequestTest, Simple) {
DetachedResourceRequest::CreateAndStart( DetachedResourceRequest::CreateAndStart(
browser_context(), url, site_for_cookies, browser_context(), url, site_for_cookies,
content::Referrer::GetDefaultReferrerPolicy(), kMotivation, content::Referrer::GetDefaultReferrerPolicy(), kMotivation,
base::BindLambdaForTesting([&](bool success) { base::BindLambdaForTesting([&](int net_error) {
EXPECT_TRUE(success); EXPECT_EQ(net::OK, net_error);
request_completion_waiter.Quit(); request_completion_waiter.Quit();
})); }));
server_request_waiter.Run(); server_request_waiter.Run();
...@@ -285,8 +285,8 @@ TEST_F(DetachedResourceRequestTest, SimpleFailure) { ...@@ -285,8 +285,8 @@ TEST_F(DetachedResourceRequestTest, SimpleFailure) {
DetachedResourceRequest::CreateAndStart( DetachedResourceRequest::CreateAndStart(
browser_context(), url, site_for_cookies, browser_context(), url, site_for_cookies,
content::Referrer::GetDefaultReferrerPolicy(), kMotivation, content::Referrer::GetDefaultReferrerPolicy(), kMotivation,
base::BindLambdaForTesting([&](bool success) { base::BindLambdaForTesting([&](int net_error) {
EXPECT_FALSE(success); EXPECT_NE(net::OK, net_error);
request_waiter.Quit(); request_waiter.Quit();
})); }));
request_waiter.Run(); request_waiter.Run();
...@@ -389,8 +389,8 @@ TEST_F(DetachedResourceRequestTest, NoContentCanSetCookie) { ...@@ -389,8 +389,8 @@ TEST_F(DetachedResourceRequestTest, NoContentCanSetCookie) {
DetachedResourceRequest::CreateAndStart( DetachedResourceRequest::CreateAndStart(
browser_context(), url, site_for_cookies, browser_context(), url, site_for_cookies,
content::Referrer::GetDefaultReferrerPolicy(), kMotivation, content::Referrer::GetDefaultReferrerPolicy(), kMotivation,
base::BindLambdaForTesting([&](bool success) { base::BindLambdaForTesting([&](int net_error) {
EXPECT_TRUE(success); EXPECT_EQ(net::OK, net_error);
request_completion_waiter.Quit(); request_completion_waiter.Quit();
})); }));
...@@ -450,8 +450,8 @@ TEST_F(DetachedResourceRequestTest, MultipleOrigins) { ...@@ -450,8 +450,8 @@ TEST_F(DetachedResourceRequestTest, MultipleOrigins) {
DetachedResourceRequest::CreateAndStart( DetachedResourceRequest::CreateAndStart(
browser_context(), url, site_for_cookies, browser_context(), url, site_for_cookies,
content::Referrer::GetDefaultReferrerPolicy(), kMotivation, content::Referrer::GetDefaultReferrerPolicy(), kMotivation,
base::BindLambdaForTesting([&](bool success) { base::BindLambdaForTesting([&](int net_error) {
EXPECT_TRUE(success); EXPECT_EQ(net::OK, net_error);
detached_request_waiter.Quit(); detached_request_waiter.Quit();
})); }));
first_request_waiter.Run(); first_request_waiter.Run();
...@@ -481,8 +481,8 @@ TEST_F(DetachedResourceRequestTest, ManyRedirects) { ...@@ -481,8 +481,8 @@ TEST_F(DetachedResourceRequestTest, ManyRedirects) {
DetachedResourceRequest::CreateAndStart( DetachedResourceRequest::CreateAndStart(
browser_context(), url, site_for_cookies, browser_context(), url, site_for_cookies,
content::Referrer::GetDefaultReferrerPolicy(), kMotivation, content::Referrer::GetDefaultReferrerPolicy(), kMotivation,
base::BindLambdaForTesting([&](bool success) { base::BindLambdaForTesting([&](int net_error) {
EXPECT_TRUE(success); EXPECT_EQ(net::OK, net_error);
request_waiter.Quit(); request_waiter.Quit();
})); }));
request_waiter.Run(); request_waiter.Run();
...@@ -505,8 +505,8 @@ TEST_F(DetachedResourceRequestTest, TooManyRedirects) { ...@@ -505,8 +505,8 @@ TEST_F(DetachedResourceRequestTest, TooManyRedirects) {
DetachedResourceRequest::CreateAndStart( DetachedResourceRequest::CreateAndStart(
browser_context(), url, site_for_cookies, browser_context(), url, site_for_cookies,
content::Referrer::GetDefaultReferrerPolicy(), kMotivation, content::Referrer::GetDefaultReferrerPolicy(), kMotivation,
base::BindLambdaForTesting([&](bool success) { base::BindLambdaForTesting([&](int net_error) {
EXPECT_FALSE(success); EXPECT_EQ(-net::ERR_TOO_MANY_REDIRECTS, net_error);
request_waiter.Quit(); request_waiter.Quit();
})); }));
request_waiter.Run(); request_waiter.Run();
...@@ -534,8 +534,8 @@ TEST_F(DetachedResourceRequestTest, CachedResponse) { ...@@ -534,8 +534,8 @@ TEST_F(DetachedResourceRequestTest, CachedResponse) {
DetachedResourceRequest::CreateAndStart( DetachedResourceRequest::CreateAndStart(
browser_context(), url, site_for_cookies, browser_context(), url, site_for_cookies,
content::Referrer::GetDefaultReferrerPolicy(), kMotivation, content::Referrer::GetDefaultReferrerPolicy(), kMotivation,
base::BindLambdaForTesting([&](bool success) { base::BindLambdaForTesting([&](int net_error) {
EXPECT_TRUE(success); EXPECT_EQ(net::OK, net_error);
first_request_waiter.Quit(); first_request_waiter.Quit();
})); }));
first_request_waiter.Run(); first_request_waiter.Run();
...@@ -543,8 +543,8 @@ TEST_F(DetachedResourceRequestTest, CachedResponse) { ...@@ -543,8 +543,8 @@ TEST_F(DetachedResourceRequestTest, CachedResponse) {
DetachedResourceRequest::CreateAndStart( DetachedResourceRequest::CreateAndStart(
browser_context(), url, site_for_cookies, browser_context(), url, site_for_cookies,
content::Referrer::GetDefaultReferrerPolicy(), kMotivation, content::Referrer::GetDefaultReferrerPolicy(), kMotivation,
base::BindLambdaForTesting([&](bool success) { base::BindLambdaForTesting([&](int net_error) {
EXPECT_TRUE(success); EXPECT_EQ(net::OK, net_error);
second_request_waiter.Quit(); second_request_waiter.Quit();
})); }));
second_request_waiter.Run(); second_request_waiter.Run();
......
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