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