Add validateRelationship() to the support library. This allows a client to request an origin to be validated as first-party with respect to the calling app. Validation is asynchronous. BUG=739165 Change-Id: I1a3543a773de9285217ec331759f8a94535b07a0 Review-Url: https://codereview.chromium.org/2978593002
diff --git a/Application/build.gradle b/Application/build.gradle index c67a37e..8ac3a6b 100644 --- a/Application/build.gradle +++ b/Application/build.gradle
@@ -2,7 +2,7 @@ android { compileSdkVersion 23 - buildToolsVersion "23.0.1" + buildToolsVersion '25.0.0' defaultConfig { applicationId "org.chromium.customtabsclient.example" minSdkVersion 16
diff --git a/build.gradle b/build.gradle index 1b7886d..5966013 100644 --- a/build.gradle +++ b/build.gradle
@@ -5,7 +5,7 @@ jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:1.3.0' + classpath 'com.android.tools.build:gradle:2.3.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files
diff --git a/customtabs/build.gradle b/customtabs/build.gradle index b75c346..a4c6f47 100644 --- a/customtabs/build.gradle +++ b/customtabs/build.gradle
@@ -1,13 +1,21 @@ apply plugin: 'android-library' dependencies { - compile 'com.android.support:support-annotations:22.2.0+' - compile 'com.android.support:support-v4:25.0.1' + compile 'com.android.support:support-annotations:24.2.0+' + compile 'com.android.support:support-v4:25.3.1' + + androidTestCompile 'junit:junit:4.12' + androidTestCompile 'com.android.support.test:runner:0.5' + androidTestCompile 'com.android.support.test:rules:0.5' } android { compileSdkVersion 23 - buildToolsVersion "23.0.1" + buildToolsVersion '25.0.0' + + defaultConfig { + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } sourceSets { main.manifest.srcFile 'AndroidManifest.xml'
diff --git a/customtabs/src/android/support/customtabs/CustomTabsCallback.java b/customtabs/src/android/support/customtabs/CustomTabsCallback.java index 818118a..14bec65 100644 --- a/customtabs/src/android/support/customtabs/CustomTabsCallback.java +++ b/customtabs/src/android/support/customtabs/CustomTabsCallback.java
@@ -16,7 +16,9 @@ package android.support.customtabs; +import android.net.Uri; import android.os.Bundle; +import android.support.customtabs.CustomTabsService.Relation; /** * A callback class for custom tabs client to get messages regarding events in their custom tabs. In @@ -98,4 +100,15 @@ * @param extras Reserved for future use. */ public void onPostMessage(String message, Bundle extras) {} + + /** + * Called when a relationship validation result is available. + * + * @param relation As in {@link CustomTabsSession#validateRelationship(int, Uri, Bundle)} + * @param requestedOrigin As in {@link CustomTabsSession#validateRelationship(int, Uri, Bundle)} + * @param result Whether the relation was validated. + * @param extras Reserved for future use. + */ + public void onRelationshipValidationResult(@Relation int relation, Uri requestedOrigin, + boolean result, Bundle extras) {} }
diff --git a/customtabs/src/android/support/customtabs/CustomTabsClient.java b/customtabs/src/android/support/customtabs/CustomTabsClient.java index 5d7bb9b..d53d3a2 100644 --- a/customtabs/src/android/support/customtabs/CustomTabsClient.java +++ b/customtabs/src/android/support/customtabs/CustomTabsClient.java
@@ -29,6 +29,7 @@ import android.os.RemoteException; import android.support.annotation.Nullable; import android.support.annotation.RestrictTo; +import android.support.customtabs.CustomTabsService.Relation; import android.text.TextUtils; import java.util.ArrayList; @@ -231,6 +232,20 @@ } }); } + + @Override + public void onRelationshipValidationResult( + final @Relation int relation, final Uri requestedOrigin, final boolean result, + final @Nullable Bundle extras) throws RemoteException { + if (callback == null) return; + mHandler.post(new Runnable() { + @Override + public void run() { + callback.onRelationshipValidationResult( + relation, requestedOrigin, result, extras); + } + }); + } }; try {
diff --git a/customtabs/src/android/support/customtabs/CustomTabsService.java b/customtabs/src/android/support/customtabs/CustomTabsService.java index 5a940cf..aad174c 100644 --- a/customtabs/src/android/support/customtabs/CustomTabsService.java +++ b/customtabs/src/android/support/customtabs/CustomTabsService.java
@@ -78,6 +78,23 @@ */ public static final int RESULT_FAILURE_MESSAGING_ERROR = -3; + @Retention(RetentionPolicy.SOURCE) + @IntDef({RELATION_USE_AS_ORIGIN, RELATION_HANDLE_ALL_URLS}) + public @interface Relation { + } + + /** + * Used for {@link CustomTabsSession#validateRelationship(int, Uri, Bundle)}. For + * App -> Web transitions, requests the app to use the declared origin to be used as origin for + * the client app in the web APIs context. + */ + public static final int RELATION_USE_AS_ORIGIN = 1; + /** + * Used for {@link CustomTabsSession#validateRelationship(int, Uri, Bundle)}. Requests the + * ability to handle all URLs from a given origin. + */ + public static final int RELATION_HANDLE_ALL_URLS = 2; + private final Map<IBinder, DeathRecipient> mDeathRecipientMap = new ArrayMap<>(); private ICustomTabsService.Stub mBinder = new ICustomTabsService.Stub() { @@ -137,6 +154,13 @@ return CustomTabsService.this.postMessage( new CustomTabsSessionToken(callback), message, extras); } + + @Override + public boolean validateRelationship( + ICustomTabsCallback callback, @Relation int relation, Uri origin, Bundle extras) { + return CustomTabsService.this.validateRelationship( + new CustomTabsSessionToken(callback), relation, origin, extras); + } }; @Override @@ -268,4 +292,23 @@ @Result protected abstract int postMessage( CustomTabsSessionToken sessionToken, String message, Bundle extras); + + /** + * Request to validate a relationship between the application and an origin. + * + * If this method returns true, the validation result will be provided through + * {@link CustomTabsCallback#onRelationshipValidationResult(int, Uri, boolean, Bundle)}. + * Otherwise the request didn't succeed. The client must call + * {@link CustomTabsClient#warmup(long)} before this. + * + * @param sessionToken The unique identifier for the session. Can not be null. + * @param relation Relation to check, must be one of the {@code CustomTabsService#RELATION_* } + * constants. + * @param origin Origin for the relation query. + * @param extras Reserved for future use. + * @return true if the request has been submitted successfully. + */ + protected abstract boolean validateRelationship( + CustomTabsSessionToken sessionToken, @Relation int relation, Uri origin, + Bundle extras); }
diff --git a/customtabs/src/android/support/customtabs/CustomTabsSession.java b/customtabs/src/android/support/customtabs/CustomTabsSession.java index a0df820..5275c22 100644 --- a/customtabs/src/android/support/customtabs/CustomTabsSession.java +++ b/customtabs/src/android/support/customtabs/CustomTabsSession.java
@@ -25,6 +25,7 @@ import android.os.RemoteException; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.customtabs.CustomTabsService.Relation; import android.support.customtabs.CustomTabsService.Result; import android.support.customtabs.CustomTabsSessionToken.DummyCallback; import android.view.View; @@ -197,6 +198,33 @@ } } + /** + * Request to validate a relationship between the application and an origin. + * + * If this method returns true, the validation result will be provided through + * {@link CustomTabsCallback#onRelationshipValidationResult(int, Uri, boolean, Bundle)}. + * Otherwise the request didn't succeed. The client must call + * {@link CustomTabsClient#warmup(long)} before this. + * + * @param relation Relation to check, must be one of the {@code CustomTabsService#RELATION_* } + * constants. + * @param origin Origin. + * @param extras Reserved for future use. + * @return true if the request has been submitted successfully. + */ + public boolean validateRelationship(@Relation int relation, Uri origin, + @Nullable Bundle extras) { + if (relation < CustomTabsService.RELATION_USE_AS_ORIGIN || + relation > CustomTabsService.RELATION_HANDLE_ALL_URLS) { + return false; + } + try { + return mService.validateRelationship(mCallback, relation, origin, extras); + } catch (RemoteException e) { + return false; + } + } + /* package */ IBinder getBinder() { return mCallback.asBinder(); }
diff --git a/customtabs/src/android/support/customtabs/CustomTabsSessionToken.java b/customtabs/src/android/support/customtabs/CustomTabsSessionToken.java index 749edc2..d43349b 100644 --- a/customtabs/src/android/support/customtabs/CustomTabsSessionToken.java +++ b/customtabs/src/android/support/customtabs/CustomTabsSessionToken.java
@@ -17,9 +17,11 @@ package android.support.customtabs; import android.content.Intent; +import android.net.Uri; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; +import android.support.customtabs.CustomTabsService.Relation; import android.support.v4.app.BundleCompat; import android.util.Log; @@ -46,6 +48,10 @@ public void onPostMessage(String message, Bundle extras) {} @Override + public void onRelationshipValidationResult(int relation, Uri origin, boolean result, + Bundle extras) {} + + @Override public IBinder asBinder() { return this; } @@ -114,6 +120,17 @@ Log.e(TAG, "RemoteException during ICustomTabsCallback transaction"); } } + + @Override + public void onRelationshipValidationResult(@Relation int relation, Uri origin, + boolean result, Bundle extras) { + try { + mCallbackBinder.onRelationshipValidationResult(relation, origin, result, extras); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException during ICustomTabsCallback transaction"); + } + } + }; }
diff --git a/customtabs/src/android/support/customtabs/ICustomTabsCallback.aidl b/customtabs/src/android/support/customtabs/ICustomTabsCallback.aidl index 32b6e9b..3e2c48c 100644 --- a/customtabs/src/android/support/customtabs/ICustomTabsCallback.aidl +++ b/customtabs/src/android/support/customtabs/ICustomTabsCallback.aidl
@@ -27,4 +27,5 @@ void extraCallback(String callbackName, in Bundle args) = 2; void onMessageChannelReady(in Bundle extras) = 3; void onPostMessage(String message, in Bundle extras) = 4; + void onRelationshipValidationResult(int relation, in Uri origin, boolean result, in Bundle extras) = 5; }
diff --git a/customtabs/src/android/support/customtabs/ICustomTabsService.aidl b/customtabs/src/android/support/customtabs/ICustomTabsService.aidl index b24b0dd..376c2a4 100644 --- a/customtabs/src/android/support/customtabs/ICustomTabsService.aidl +++ b/customtabs/src/android/support/customtabs/ICustomTabsService.aidl
@@ -36,4 +36,5 @@ boolean updateVisuals(in ICustomTabsCallback callback, in Bundle bundle) = 5; boolean requestPostMessageChannel(in ICustomTabsCallback callback, in Uri postMessageOrigin) = 6; int postMessage(in ICustomTabsCallback callback, String message, in Bundle extras) = 7; + boolean validateRelationship(in ICustomTabsCallback callback, int relation, in Uri origin, in Bundle extras) = 8; }
diff --git a/customtabs/tests/src/android/support/customtabs/TestCustomTabsCallback.java b/customtabs/tests/src/android/support/customtabs/TestCustomTabsCallback.java index 56b1817..804d354 100644 --- a/customtabs/tests/src/android/support/customtabs/TestCustomTabsCallback.java +++ b/customtabs/tests/src/android/support/customtabs/TestCustomTabsCallback.java
@@ -16,6 +16,7 @@ package android.support.customtabs; +import android.net.Uri; import android.os.Bundle; import android.os.RemoteException; @@ -50,6 +51,13 @@ throws RemoteException { TestCustomTabsCallback.this.onPostMessage(message, extras); } + + @Override + public void onRelationshipValidationResult(int relation, Uri origin, boolean result, + Bundle extras) throws RemoteException { + TestCustomTabsCallback.this.onRelationshipValidationResult( + relation, origin, result, extras); + } }; /* package */ ICustomTabsCallback getStub() {
diff --git a/customtabs/tests/src/android/support/customtabs/TestCustomTabsService.java b/customtabs/tests/src/android/support/customtabs/TestCustomTabsService.java index b5c5e86..e3d5fa8 100644 --- a/customtabs/tests/src/android/support/customtabs/TestCustomTabsService.java +++ b/customtabs/tests/src/android/support/customtabs/TestCustomTabsService.java
@@ -71,4 +71,10 @@ if (!mPostMessageRequested) return CustomTabsService.RESULT_FAILURE_DISALLOWED; return CustomTabsService.RESULT_SUCCESS; } + + @Override + protected boolean validateRelationship(CustomTabsSessionToken sessionToken, + @Relation int relation, Uri origin, Bundle extras) { + return false; + } }
diff --git a/demos/build.gradle b/demos/build.gradle index 5271d71..690abae 100644 --- a/demos/build.gradle +++ b/demos/build.gradle
@@ -2,7 +2,7 @@ android { compileSdkVersion 23 - buildToolsVersion "23.0.2" + buildToolsVersion '25.0.0' defaultConfig { applicationId "org.chromium.customtabsdemos"
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0c71e76..91989c2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@ -#Wed Apr 10 15:27:10 PDT 2013 +#Wed Jul 12 17:48:04 CEST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
diff --git a/shared/build.gradle b/shared/build.gradle index b3cc1a7..b7de081 100644 --- a/shared/build.gradle +++ b/shared/build.gradle
@@ -2,7 +2,7 @@ android { compileSdkVersion 23 - buildToolsVersion "23.0.2" + buildToolsVersion '25.0.0' defaultConfig { minSdkVersion 15