Commit e7b649e2 authored by Peter E Conn's avatar Peter E Conn Committed by Commit Bot

🤝 Permeate Origin use.

Use the Origin class a bit more thoroughly. Basically after verifying
a CustomTabSession with an origin, a Trusted Web Activity would succeed
navigating to the origin but fail (fall back to a Custom Tab UI)
navigating to a subpath under the origin.

Bug: 800422
Change-Id: I1877477bcf307b00cf87386ed7787b217a734512
Reviewed-on: https://chromium-review.googlesource.com/978006
Commit-Queue: Peter Conn <peconn@chromium.org>
Reviewed-by: default avatarBernhard Bauer <bauerb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#546137}
parent 7765662e
...@@ -27,7 +27,7 @@ public class Origin { ...@@ -27,7 +27,7 @@ public class Origin {
* Constructs a canonical Origin from an Uri. * Constructs a canonical Origin from an Uri.
*/ */
public Origin(Uri uri) { public Origin(Uri uri) {
if (uri.getScheme() == null || uri.getAuthority() == null) { if (uri == null || uri.getScheme() == null || uri.getAuthority() == null) {
mOrigin = Uri.EMPTY; mOrigin = Uri.EMPTY;
return; return;
} }
......
...@@ -102,7 +102,7 @@ class ClientManager { ...@@ -102,7 +102,7 @@ class ClientManager {
} }
/** /**
* Disconnects from the remote process. Safe to call even if {@link connect()} returned * Disconnects from the remote process. Safe to call even if {@link #connect} returned
* false, or if the remote service died. * false, or if the remote service died.
*/ */
public void disconnect() { public void disconnect() {
...@@ -133,7 +133,7 @@ class ClientManager { ...@@ -133,7 +133,7 @@ class ClientManager {
public final int uid; public final int uid;
public final DisconnectCallback disconnectCallback; public final DisconnectCallback disconnectCallback;
public final PostMessageHandler postMessageHandler; public final PostMessageHandler postMessageHandler;
public final Set<Uri> mLinkedUrls = new HashSet<>(); public final Set<Origin> mLinkedOrigins = new HashSet<>();
public OriginVerifier originVerifier; public OriginVerifier originVerifier;
public boolean mIgnoreFragments; public boolean mIgnoreFragments;
public boolean lowConfidencePrediction; public boolean lowConfidencePrediction;
...@@ -382,7 +382,7 @@ class ClientManager { ...@@ -382,7 +382,7 @@ class ClientManager {
} }
public synchronized boolean validateRelationship( public synchronized boolean validateRelationship(
CustomTabsSessionToken session, int relation, Uri origin, Bundle extras) { CustomTabsSessionToken session, int relation, Origin origin, Bundle extras) {
return validateRelationshipInternal(session, relation, origin, false); return validateRelationshipInternal(session, relation, origin, false);
} }
...@@ -390,7 +390,7 @@ class ClientManager { ...@@ -390,7 +390,7 @@ class ClientManager {
* Validates the link between the client and the origin. * Validates the link between the client and the origin.
*/ */
public synchronized void verifyAndInitializeWithPostMessageOriginForSession( public synchronized void verifyAndInitializeWithPostMessageOriginForSession(
CustomTabsSessionToken session, Uri origin, @Relation int relation) { CustomTabsSessionToken session, Origin origin, @Relation int relation) {
validateRelationshipInternal(session, relation, origin, true); validateRelationshipInternal(session, relation, origin, true);
} }
...@@ -398,18 +398,18 @@ class ClientManager { ...@@ -398,18 +398,18 @@ class ClientManager {
* Can't be called on UI Thread. * Can't be called on UI Thread.
*/ */
private synchronized boolean validateRelationshipInternal(CustomTabsSessionToken session, private synchronized boolean validateRelationshipInternal(CustomTabsSessionToken session,
int relation, Uri origin, boolean initializePostMessageChannel) { int relation, Origin origin, boolean initializePostMessageChannel) {
SessionParams params = mSessionParams.get(session); SessionParams params = mSessionParams.get(session);
if (params == null || TextUtils.isEmpty(params.getPackageName())) return false; if (params == null || TextUtils.isEmpty(params.getPackageName())) return false;
OriginVerificationListener listener = null; OriginVerificationListener listener = null;
if (initializePostMessageChannel) listener = params.postMessageHandler; if (initializePostMessageChannel) listener = params.postMessageHandler;
params.originVerifier = new OriginVerifier(listener, params.getPackageName(), relation); params.originVerifier = new OriginVerifier(listener, params.getPackageName(), relation);
ThreadUtils.runOnUiThread(() -> { params.originVerifier.start(new Origin(origin)); }); ThreadUtils.runOnUiThread(() -> { params.originVerifier.start(origin); });
if (relation == CustomTabsService.RELATION_HANDLE_ALL_URLS if (relation == CustomTabsService.RELATION_HANDLE_ALL_URLS
&& InstalledAppProviderImpl.isAppInstalledAndAssociatedWithOrigin( && InstalledAppProviderImpl.isAppInstalledAndAssociatedWithOrigin(
params.getPackageName(), URI.create(origin.toString()), params.getPackageName(), URI.create(origin.toString()),
mContext.getPackageManager())) { mContext.getPackageManager())) {
params.mLinkedUrls.add(origin); params.mLinkedOrigins.add(origin);
} }
return true; return true;
} }
...@@ -433,11 +433,11 @@ class ClientManager { ...@@ -433,11 +433,11 @@ class ClientManager {
if (params == null) return false; if (params == null) return false;
String packageName = params.getPackageName(); String packageName = params.getPackageName();
if (TextUtils.isEmpty(packageName)) return false; if (TextUtils.isEmpty(packageName)) return false;
boolean isAppAssociatedWithOrigin = params.mLinkedUrls.contains(url); Origin origin = new Origin(url);
boolean isAppAssociatedWithOrigin = params.mLinkedOrigins.contains(origin);
if (!isAppAssociatedWithOrigin) return false; if (!isAppAssociatedWithOrigin) return false;
// Split path from the given Uri to get only the origin before web->native verification. // Split path from the given Uri to get only the origin before web->native verification.
Origin origin = new Origin(url);
if (OriginVerifier.isValidOrigin( if (OriginVerifier.isValidOrigin(
packageName, origin, CustomTabsService.RELATION_HANDLE_ALL_URLS)) { packageName, origin, CustomTabsService.RELATION_HANDLE_ALL_URLS)) {
return true; return true;
...@@ -637,9 +637,9 @@ class ClientManager { ...@@ -637,9 +637,9 @@ class ClientManager {
* @param origin Origin to verify * @param origin Origin to verify
*/ */
public synchronized boolean isFirstPartyOriginForSession( public synchronized boolean isFirstPartyOriginForSession(
CustomTabsSessionToken session, Uri origin) { CustomTabsSessionToken session, Origin origin) {
return OriginVerifier.isValidOrigin(getClientPackageNameForSession(session), return OriginVerifier.isValidOrigin(getClientPackageNameForSession(session), origin,
new Origin(origin), CustomTabsService.RELATION_USE_AS_ORIGIN); CustomTabsService.RELATION_USE_AS_ORIGIN);
} }
/** Tries to bind to a client to keep it alive, and returns true for success. */ /** Tries to bind to a client to keep it alive, and returns true for success. */
......
...@@ -50,6 +50,7 @@ import org.chromium.chrome.browser.IntentHandler; ...@@ -50,6 +50,7 @@ import org.chromium.chrome.browser.IntentHandler;
import org.chromium.chrome.browser.UrlConstants; import org.chromium.chrome.browser.UrlConstants;
import org.chromium.chrome.browser.WarmupManager; import org.chromium.chrome.browser.WarmupManager;
import org.chromium.chrome.browser.browserservices.BrowserSessionContentUtils; import org.chromium.chrome.browser.browserservices.BrowserSessionContentUtils;
import org.chromium.chrome.browser.browserservices.Origin;
import org.chromium.chrome.browser.browserservices.PostMessageHandler; import org.chromium.chrome.browser.browserservices.PostMessageHandler;
import org.chromium.chrome.browser.device.DeviceClassManager; import org.chromium.chrome.browser.device.DeviceClassManager;
import org.chromium.chrome.browser.init.ChainedTasks; import org.chromium.chrome.browser.init.ChainedTasks;
...@@ -67,7 +68,6 @@ import org.chromium.content.browser.ChildProcessLauncherHelper; ...@@ -67,7 +68,6 @@ import org.chromium.content.browser.ChildProcessLauncherHelper;
import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.common.Referrer; import org.chromium.content_public.common.Referrer;
import org.chromium.net.GURLUtils;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.FileReader; import java.io.FileReader;
...@@ -668,7 +668,7 @@ public class CustomTabsConnection { ...@@ -668,7 +668,7 @@ public class CustomTabsConnection {
} }
public boolean requestPostMessageChannel(CustomTabsSessionToken session, public boolean requestPostMessageChannel(CustomTabsSessionToken session,
Uri postMessageOrigin) { Origin postMessageOrigin) {
boolean success = requestPostMessageChannelInternal(session, postMessageOrigin); boolean success = requestPostMessageChannelInternal(session, postMessageOrigin);
logCall("requestPostMessageChannel() with origin " logCall("requestPostMessageChannel() with origin "
+ (postMessageOrigin != null ? postMessageOrigin.toString() : ""), success); + (postMessageOrigin != null ? postMessageOrigin.toString() : ""), success);
...@@ -676,7 +676,7 @@ public class CustomTabsConnection { ...@@ -676,7 +676,7 @@ public class CustomTabsConnection {
} }
private boolean requestPostMessageChannelInternal(final CustomTabsSessionToken session, private boolean requestPostMessageChannelInternal(final CustomTabsSessionToken session,
final Uri postMessageOrigin) { final Origin postMessageOrigin) {
if (!mWarmupHasBeenCalled.get()) return false; if (!mWarmupHasBeenCalled.get()) return false;
if (!isCallerForegroundOrSelf() && !BrowserSessionContentUtils.isActiveSession(session)) { if (!isCallerForegroundOrSelf() && !BrowserSessionContentUtils.isActiveSession(session)) {
return false; return false;
...@@ -711,7 +711,7 @@ public class CustomTabsConnection { ...@@ -711,7 +711,7 @@ public class CustomTabsConnection {
* @return The validated origin {@link Uri} for the given session's client. * @return The validated origin {@link Uri} for the given session's client.
*/ */
protected Uri verifyOriginForSession( protected Uri verifyOriginForSession(
CustomTabsSessionToken session, int clientUid, Uri origin) { CustomTabsSessionToken session, int clientUid, Origin origin) {
if (clientUid == Process.myUid()) return Uri.EMPTY; if (clientUid == Process.myUid()) return Uri.EMPTY;
return null; return null;
} }
...@@ -738,7 +738,7 @@ public class CustomTabsConnection { ...@@ -738,7 +738,7 @@ public class CustomTabsConnection {
} }
public boolean validateRelationship( public boolean validateRelationship(
CustomTabsSessionToken sessionToken, int relation, Uri origin, Bundle extras) { CustomTabsSessionToken sessionToken, int relation, Origin origin, Bundle extras) {
// Essential parts of the verification will depend on native code and will be run sync on UI // Essential parts of the verification will depend on native code and will be run sync on UI
// thread. Make sure the client has called warmup() beforehand. // thread. Make sure the client has called warmup() beforehand.
if (!mWarmupHasBeenCalled.get()) return false; if (!mWarmupHasBeenCalled.get()) return false;
...@@ -920,9 +920,9 @@ public class CustomTabsConnection { ...@@ -920,9 +920,9 @@ public class CustomTabsConnection {
Uri redirectEndpoint = intent.getParcelableExtra(REDIRECT_ENDPOINT_KEY); Uri redirectEndpoint = intent.getParcelableExtra(REDIRECT_ENDPOINT_KEY);
if (redirectEndpoint == null || !isValid(redirectEndpoint)) return; if (redirectEndpoint == null || !isValid(redirectEndpoint)) return;
String origin = GURLUtils.getOrigin(url); Origin origin = new Origin(url);
if (origin == null) return; if (origin == null) return;
if (!mClientManager.isFirstPartyOriginForSession(session, Uri.parse(origin))) return; if (!mClientManager.isFirstPartyOriginForSession(session, origin)) return;
WarmupManager.getInstance().maybePreconnectUrlAndSubResources( WarmupManager.getInstance().maybePreconnectUrlAndSubResources(
Profile.getLastUsedProfile(), redirectEndpoint.toString()); Profile.getLastUsedProfile(), redirectEndpoint.toString());
...@@ -953,7 +953,7 @@ public class CustomTabsConnection { ...@@ -953,7 +953,7 @@ public class CustomTabsConnection {
// TODO(lizeb): Relax the restrictions. // TODO(lizeb): Relax the restrictions.
return ChromeBrowserInitializer.getInstance(mContext).hasNativeInitializationCompleted() return ChromeBrowserInitializer.getInstance(mContext).hasNativeInitializationCompleted()
&& ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_PARALLEL_REQUEST) && ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_PARALLEL_REQUEST)
&& mClientManager.isFirstPartyOriginForSession(session, referrer); && mClientManager.isFirstPartyOriginForSession(session, new Origin(referrer));
} }
/** /**
......
...@@ -11,6 +11,7 @@ import android.os.IBinder; ...@@ -11,6 +11,7 @@ import android.os.IBinder;
import android.support.customtabs.CustomTabsService; import android.support.customtabs.CustomTabsService;
import android.support.customtabs.CustomTabsSessionToken; import android.support.customtabs.CustomTabsSessionToken;
import org.chromium.chrome.browser.browserservices.Origin;
import org.chromium.chrome.browser.firstrun.FirstRunFlowSequencer; import org.chromium.chrome.browser.firstrun.FirstRunFlowSequencer;
import org.chromium.chrome.browser.init.ProcessInitializationHandler; import org.chromium.chrome.browser.init.ProcessInitializationHandler;
...@@ -78,7 +79,7 @@ public class CustomTabsConnectionService extends CustomTabsService { ...@@ -78,7 +79,7 @@ public class CustomTabsConnectionService extends CustomTabsService {
@Override @Override
protected boolean requestPostMessageChannel(CustomTabsSessionToken sessionToken, protected boolean requestPostMessageChannel(CustomTabsSessionToken sessionToken,
Uri postMessageOrigin) { Uri postMessageOrigin) {
return mConnection.requestPostMessageChannel(sessionToken, postMessageOrigin); return mConnection.requestPostMessageChannel(sessionToken, new Origin(postMessageOrigin));
} }
@Override @Override
...@@ -91,7 +92,7 @@ public class CustomTabsConnectionService extends CustomTabsService { ...@@ -91,7 +92,7 @@ public class CustomTabsConnectionService extends CustomTabsService {
@Override @Override
protected boolean validateRelationship( protected boolean validateRelationship(
CustomTabsSessionToken sessionToken, int relation, Uri origin, Bundle extras) { CustomTabsSessionToken sessionToken, int relation, Uri origin, Bundle extras) {
return mConnection.validateRelationship(sessionToken, relation, origin, extras); return mConnection.validateRelationship(sessionToken, relation, new Origin(origin), extras);
} }
@Override @Override
......
...@@ -181,7 +181,7 @@ public class ClientManagerTest { ...@@ -181,7 +181,7 @@ public class ClientManagerTest {
public void run() { public void run() {
// With no prepopulated origins, this verification should fail. // With no prepopulated origins, this verification should fail.
cm.verifyAndInitializeWithPostMessageOriginForSession( cm.verifyAndInitializeWithPostMessageOriginForSession(
mSession, Uri.parse(URL), CustomTabsService.RELATION_USE_AS_ORIGIN); mSession, new Origin(URL), CustomTabsService.RELATION_USE_AS_ORIGIN);
Assert.assertNull(cm.getPostMessageOriginForSessionForTesting(mSession)); Assert.assertNull(cm.getPostMessageOriginForSessionForTesting(mSession));
// If there is a prepopulated origin, we should get a synchronous verification. // If there is a prepopulated origin, we should get a synchronous verification.
...@@ -189,7 +189,7 @@ public class ClientManagerTest { ...@@ -189,7 +189,7 @@ public class ClientManagerTest {
ContextUtils.getApplicationContext().getPackageName(), new Origin(URL), ContextUtils.getApplicationContext().getPackageName(), new Origin(URL),
CustomTabsService.RELATION_USE_AS_ORIGIN); CustomTabsService.RELATION_USE_AS_ORIGIN);
cm.verifyAndInitializeWithPostMessageOriginForSession( cm.verifyAndInitializeWithPostMessageOriginForSession(
mSession, Uri.parse(URL), CustomTabsService.RELATION_USE_AS_ORIGIN); mSession, new Origin(URL), CustomTabsService.RELATION_USE_AS_ORIGIN);
} }
}); });
...@@ -223,21 +223,23 @@ public class ClientManagerTest { ...@@ -223,21 +223,23 @@ public class ClientManagerTest {
// Should always start with no origin. // Should always start with no origin.
Assert.assertNull(cm.getPostMessageOriginForSessionForTesting(mSession)); Assert.assertNull(cm.getPostMessageOriginForSessionForTesting(mSession));
Origin origin = new Origin(URL);
// With no prepopulated origins, this verification should fail. // With no prepopulated origins, this verification should fail.
cm.verifyAndInitializeWithPostMessageOriginForSession( cm.verifyAndInitializeWithPostMessageOriginForSession(
mSession, Uri.parse(URL), CustomTabsService.RELATION_USE_AS_ORIGIN); mSession, origin, CustomTabsService.RELATION_USE_AS_ORIGIN);
Assert.assertNull(cm.getPostMessageOriginForSessionForTesting(mSession)); Assert.assertNull(cm.getPostMessageOriginForSessionForTesting(mSession));
ThreadUtils.runOnUiThreadBlocking(() -> { ThreadUtils.runOnUiThreadBlocking(() -> {
// Prepopulated origins should depend on the relation used. // Prepopulated origins should depend on the relation used.
OriginVerifier.addVerifiedOriginForPackage( OriginVerifier.addVerifiedOriginForPackage(
ContextUtils.getApplicationContext().getPackageName(), new Origin(URL), ContextUtils.getApplicationContext().getPackageName(), origin,
CustomTabsService.RELATION_HANDLE_ALL_URLS); CustomTabsService.RELATION_HANDLE_ALL_URLS);
// This uses CustomTabsService.RELATION_USE_AS_ORIGIN by default. // This uses CustomTabsService.RELATION_USE_AS_ORIGIN by default.
Assert.assertFalse(cm.isFirstPartyOriginForSession(mSession, Uri.parse(URL))); Assert.assertFalse(cm.isFirstPartyOriginForSession(mSession, origin));
}); });
cm.verifyAndInitializeWithPostMessageOriginForSession( cm.verifyAndInitializeWithPostMessageOriginForSession(
mSession, Uri.parse(URL), CustomTabsService.RELATION_HANDLE_ALL_URLS); mSession, origin, CustomTabsService.RELATION_HANDLE_ALL_URLS);
ThreadUtils.runOnUiThreadBlocking(() -> { ThreadUtils.runOnUiThreadBlocking(() -> {
Uri verifiedOrigin = cm.getPostMessageOriginForSessionForTesting(mSession); Uri verifiedOrigin = cm.getPostMessageOriginForSessionForTesting(mSession);
...@@ -261,19 +263,19 @@ public class ClientManagerTest { ...@@ -261,19 +263,19 @@ public class ClientManagerTest {
ThreadUtils.runOnUiThreadBlocking(new Runnable() { ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@Override @Override
public void run() { public void run() {
Uri uri = Uri.parse(HTTP_URL); Origin origin = new Origin(HTTP_URL);
// With no prepopulated origins, this verification should fail. // With no prepopulated origins, this verification should fail.
cm.verifyAndInitializeWithPostMessageOriginForSession( cm.verifyAndInitializeWithPostMessageOriginForSession(
mSession, uri, CustomTabsService.RELATION_USE_AS_ORIGIN); mSession, origin, CustomTabsService.RELATION_USE_AS_ORIGIN);
Assert.assertNull(cm.getPostMessageOriginForSessionForTesting(mSession)); Assert.assertNull(cm.getPostMessageOriginForSessionForTesting(mSession));
// Even if there is a prepopulated origin, non-https origins should get an early // Even if there is a prepopulated origin, non-https origins should get an early
// return with false. // return with false.
OriginVerifier.addVerifiedOriginForPackage( OriginVerifier.addVerifiedOriginForPackage(
ContextUtils.getApplicationContext().getPackageName(), new Origin(uri), ContextUtils.getApplicationContext().getPackageName(), origin,
CustomTabsService.RELATION_USE_AS_ORIGIN); CustomTabsService.RELATION_USE_AS_ORIGIN);
cm.verifyAndInitializeWithPostMessageOriginForSession( cm.verifyAndInitializeWithPostMessageOriginForSession(
mSession, uri, CustomTabsService.RELATION_USE_AS_ORIGIN); mSession, origin, CustomTabsService.RELATION_USE_AS_ORIGIN);
Assert.assertNull(cm.getPostMessageOriginForSessionForTesting(mSession)); Assert.assertNull(cm.getPostMessageOriginForSessionForTesting(mSession));
} }
}); });
......
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