Merge "Add AndroidX API to get/set status for WebView Media Integrity Api" into androidx-main
diff --git a/webkit/integration-tests/instrumentation/src/androidTest/java/androidx/webkit/WebSettingsCompatTest.java b/webkit/integration-tests/instrumentation/src/androidTest/java/androidx/webkit/WebSettingsCompatTest.java
index 23a422c..71b3d68 100644
--- a/webkit/integration-tests/instrumentation/src/androidTest/java/androidx/webkit/WebSettingsCompatTest.java
+++ b/webkit/integration-tests/instrumentation/src/androidTest/java/androidx/webkit/WebSettingsCompatTest.java
@@ -16,6 +16,10 @@
package androidx.webkit;
+import static androidx.webkit.WebViewMediaIntegrityApiStatusConfig.WEBVIEW_MEDIA_INTEGRITY_API_DISABLED;
+import static androidx.webkit.WebViewMediaIntegrityApiStatusConfig.WEBVIEW_MEDIA_INTEGRITY_API_ENABLED;
+import static androidx.webkit.WebViewMediaIntegrityApiStatusConfig.WEBVIEW_MEDIA_INTEGRITY_API_ENABLED_WITHOUT_APP_IDENTITY;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -194,4 +198,69 @@
}
+ @Test
+ public void testWebViewMediaIntegrityApiDefaultStatus() throws Throwable {
+ WebkitUtils.checkFeature(WebViewFeature.WEBVIEW_MEDIA_INTEGRITY_API_STATUS);
+ WebSettings settings = mWebViewOnUiThread.getSettings();
+ Assert.assertEquals(WEBVIEW_MEDIA_INTEGRITY_API_ENABLED,
+ WebSettingsCompat.getWebViewMediaIntegrityApiStatus(settings).getDefaultStatus());
+ Assert.assertTrue(
+ WebSettingsCompat.getWebViewMediaIntegrityApiStatus(settings)
+ .getOverrideRules().isEmpty());
+ }
+
+ @Test
+ public void testSetWebViewMediaIntegrityApiWithNoRules() throws Throwable {
+ WebkitUtils.checkFeature(WebViewFeature.WEBVIEW_MEDIA_INTEGRITY_API_STATUS);
+ WebSettings settings = mWebViewOnUiThread.getSettings();
+
+ WebViewMediaIntegrityApiStatusConfig config =
+ new WebViewMediaIntegrityApiStatusConfig.Builder(
+ WEBVIEW_MEDIA_INTEGRITY_API_DISABLED)
+ .build();
+ WebSettingsCompat.setWebViewMediaIntegrityApiStatus(settings, config);
+ Assert.assertEquals(
+ WEBVIEW_MEDIA_INTEGRITY_API_DISABLED,
+ WebSettingsCompat.getWebViewMediaIntegrityApiStatus(settings)
+ .getDefaultStatus());
+ Assert.assertTrue(
+ WebSettingsCompat.getWebViewMediaIntegrityApiStatus(settings)
+ .getOverrideRules().isEmpty());
+ }
+
+ @Test
+ public void testSetWebViewMediaIntegrityApiWithRules() throws Throwable {
+ WebkitUtils.checkFeature(WebViewFeature.WEBVIEW_MEDIA_INTEGRITY_API_STATUS);
+ WebSettings settings = mWebViewOnUiThread.getSettings();
+
+ WebViewMediaIntegrityApiStatusConfig config =
+ new WebViewMediaIntegrityApiStatusConfig.Builder(
+ WEBVIEW_MEDIA_INTEGRITY_API_ENABLED_WITHOUT_APP_IDENTITY)
+ .addOverrideRule("http://*.example.com",
+ WEBVIEW_MEDIA_INTEGRITY_API_ENABLED)
+ .build();
+ WebSettingsCompat.setWebViewMediaIntegrityApiStatus(settings, config);
+ Assert.assertEquals(
+ WEBVIEW_MEDIA_INTEGRITY_API_ENABLED_WITHOUT_APP_IDENTITY,
+ WebSettingsCompat.getWebViewMediaIntegrityApiStatus(settings).getDefaultStatus());
+ Assert.assertEquals(1,
+ WebSettingsCompat.getWebViewMediaIntegrityApiStatus(settings)
+ .getOverrideRules().size());
+ }
+
+ @Test
+ public void testSetWebViewMediaIntegrityApiWithInvalidStatus() throws Throwable {
+ WebkitUtils.checkFeature(WebViewFeature.WEBVIEW_MEDIA_INTEGRITY_API_STATUS);
+ WebSettings settings = mWebViewOnUiThread.getSettings();
+ int invalidStatus = 15;
+
+ WebViewMediaIntegrityApiStatusConfig config =
+ new WebViewMediaIntegrityApiStatusConfig.Builder(invalidStatus).build();
+ Assert.assertThrows(
+ IllegalArgumentException.class,
+ () -> WebSettingsCompat.setWebViewMediaIntegrityApiStatus(settings, config));
+ Assert.assertTrue(
+ WebSettingsCompat.getWebViewMediaIntegrityApiStatus(settings)
+ .getOverrideRules().isEmpty());
+ }
}
diff --git a/webkit/webkit/src/main/java/androidx/webkit/WebSettingsCompat.java b/webkit/webkit/src/main/java/androidx/webkit/WebSettingsCompat.java
index 08ed011..d44c282 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/WebSettingsCompat.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/WebSettingsCompat.java
@@ -874,6 +874,44 @@
}
}
+ /**
+ * Sets permissions provided through
+ * {@link WebViewMediaIntegrityApiStatusConfig} for using the
+ * WebView Integrity API.
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ @RequiresFeature(name = WebViewFeature.WEBVIEW_MEDIA_INTEGRITY_API_STATUS,
+ enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
+ public static void setWebViewMediaIntegrityApiStatus(
+ @NonNull WebSettings settings,
+ @NonNull WebViewMediaIntegrityApiStatusConfig permissionConfig) {
+ final ApiFeature.NoFramework feature =
+ WebViewFeatureInternal.WEBVIEW_MEDIA_INTEGRITY_API_STATUS;
+ if (feature.isSupportedByWebView()) {
+ getAdapter(settings).setWebViewMediaIntegrityApiStatus(permissionConfig);
+ } else {
+ throw WebViewFeatureInternal.getUnsupportedOperationException();
+ }
+ }
+
+ /**
+ * Returns the {@link WebViewMediaIntegrityApiStatusConfig} currently in use.
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ @RequiresFeature(name = WebViewFeature.WEBVIEW_MEDIA_INTEGRITY_API_STATUS,
+ enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
+ @NonNull
+ public static WebViewMediaIntegrityApiStatusConfig getWebViewMediaIntegrityApiStatus(
+ @NonNull WebSettings settings) {
+ final ApiFeature.NoFramework feature =
+ WebViewFeatureInternal.WEBVIEW_MEDIA_INTEGRITY_API_STATUS;
+ if (feature.isSupportedByWebView()) {
+ return getAdapter(settings).getWebViewMediaIntegrityApiStatus();
+ } else {
+ throw WebViewFeatureInternal.getUnsupportedOperationException();
+ }
+ }
+
private static WebSettingsAdapter getAdapter(WebSettings settings) {
return WebViewGlueCommunicator.getCompatConverter().convertSettings(settings);
}
diff --git a/webkit/webkit/src/main/java/androidx/webkit/WebViewFeature.java b/webkit/webkit/src/main/java/androidx/webkit/WebViewFeature.java
index fa09c22..8fa0356d 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/WebViewFeature.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/WebViewFeature.java
@@ -569,6 +569,16 @@
"ATTRIBUTION_REGISTRATION_BEHAVIOR";
/**
+ * Feature for {@link #isFeatureSupported(String)}.
+ * This feature covers
+ * {@link androidx.webkit.WebSettingsCompat#setWebViewMediaIntegrityApiStatus(WebSettings, WebViewMediaIntegrityApiStatusConfig)}
+ * {@link androidx.webkit.WebSettingsCompat#getWebViewMediaIntegrityApiStatus(WebSettings)}
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ public static final String WEBVIEW_MEDIA_INTEGRITY_API_STATUS =
+ "WEBVIEW_MEDIA_INTEGRITY_API_STATUS";
+
+ /**
* Return whether a feature is supported at run-time. On devices running Android version {@link
* android.os.Build.VERSION_CODES#LOLLIPOP} and higher, this will check whether a feature is
* supported, depending on the combination of the desired feature, the Android version of
diff --git a/webkit/webkit/src/main/java/androidx/webkit/WebViewMediaIntegrityApiStatusConfig.java b/webkit/webkit/src/main/java/androidx/webkit/WebViewMediaIntegrityApiStatusConfig.java
new file mode 100644
index 0000000..df7396d
--- /dev/null
+++ b/webkit/webkit/src/main/java/androidx/webkit/WebViewMediaIntegrityApiStatusConfig.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.webkit;
+
+import android.webkit.WebView;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresFeature;
+import androidx.annotation.RestrictTo;
+
+import org.chromium.support_lib_boundary.WebSettingsBoundaryInterface;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Configuration to set API enablement status for site origins through override rules.
+ *
+ * <p>Websites will follow the default status supplied in the builder constructor,
+ * unless the site origin matches one of the origin patterns supplied in the override rules.
+ *
+ * <p>The override rules are a map from origin patterns to the desired
+ * {@link WebViewMediaIntegrityApiStatus}.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+@RequiresFeature(name = WebViewFeature.WEBVIEW_MEDIA_INTEGRITY_API_STATUS,
+ enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
+public class WebViewMediaIntegrityApiStatusConfig {
+ /**
+ * @hide
+ */
+ @Target(ElementType.TYPE_USE)
+ @IntDef({WEBVIEW_MEDIA_INTEGRITY_API_DISABLED,
+ WEBVIEW_MEDIA_INTEGRITY_API_ENABLED_WITHOUT_APP_IDENTITY,
+ WEBVIEW_MEDIA_INTEGRITY_API_ENABLED})
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ @Retention(RetentionPolicy.SOURCE)
+ @interface WebViewMediaIntegrityApiStatus {
+ }
+
+ /**
+ * {@link WebViewMediaIntegrityApiStatus} that enables the API and allows sharing of the app
+ * package name with the JavaScript caller.
+ *
+ * <p>This is the default value.
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ public static final int WEBVIEW_MEDIA_INTEGRITY_API_ENABLED =
+ WebSettingsBoundaryInterface.WebViewMediaIntegrityApiStatus.ENABLED;
+
+ /**
+ * {@link WebViewMediaIntegrityApiStatus} that enables the API for JavaScript callers but
+ * disables sharing app package name in generated tokens.
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ public static final int WEBVIEW_MEDIA_INTEGRITY_API_ENABLED_WITHOUT_APP_IDENTITY =
+ WebSettingsBoundaryInterface.WebViewMediaIntegrityApiStatus
+ .ENABLED_WITHOUT_APP_IDENTITY;
+
+ /**
+ * {@link WebViewMediaIntegrityApiStatus} that disables the API and causes it to return an
+ * error code to the JavaScript callers indicating that the app has disabled it.
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ public static final int WEBVIEW_MEDIA_INTEGRITY_API_DISABLED =
+ WebSettingsBoundaryInterface.WebViewMediaIntegrityApiStatus.DISABLED;
+
+ private @WebViewMediaIntegrityApiStatus int mDefaultStatus;
+ private Map<String, @WebViewMediaIntegrityApiStatus Integer> mOverrideRules;
+
+ public WebViewMediaIntegrityApiStatusConfig(@NonNull Builder builder) {
+ this.mDefaultStatus = builder.mDefaultStatus;
+ this.mOverrideRules = builder.mOverrideRules;
+ }
+
+ /**
+ * Builds a {@link WebViewMediaIntegrityApiStatusConfig} having a default API status and
+ * a map of origin pattern rules to their {@link WebViewMediaIntegrityApiStatus}.
+ *
+ * <p>
+ * Example:
+ * <pre class="prettyprint">
+ * // Create a config with default API status being DISABLED and API status is ENABLED for
+ * // Uris matching origin pattern "http://*.example.com"
+ * new WebViewMediaIntegrityApiStatusConfig.Builder(WEBVIEW_MEDIA_INTEGRITY_API_DISABLED)
+ * .addOverrideRule("http://*.example.com", WEBVIEW_MEDIA_INTEGRITY_API_ENABLED)
+ * .build();
+ * </pre>
+ */
+ public static final class Builder {
+ private @WebViewMediaIntegrityApiStatus int mDefaultStatus;
+ private Map<String, @WebViewMediaIntegrityApiStatus Integer> mOverrideRules;
+
+ /**
+ * @param defaultStatus Default {@link WebViewMediaIntegrityApiStatus} that will be
+ * used for URIs that don't match any origin pattern rule.
+ */
+ public Builder(@WebViewMediaIntegrityApiStatus int defaultStatus) {
+ this.mDefaultStatus = defaultStatus;
+ this.mOverrideRules = new HashMap<>();
+ }
+
+ /**
+ * Add an override rule to set a specific {@link WebViewMediaIntegrityApiStatus} for
+ * origin sites matching the origin pattern stated in the rule. Origin patterns
+ * should be supplied in the same format as those in
+ * {@link androidx.webkit.WebViewCompat.WebMessageListener#addWebMessageListener(WebView, String, Set, WebViewCompat.WebMessageListener)}
+ *
+ * If two or more origin patterns match a given origin site, the least permissive option
+ * will be chosen.
+ */
+
+ @NonNull
+ public Builder addOverrideRule(@NonNull String originPattern,
+ @WebViewMediaIntegrityApiStatus int permission) {
+ mOverrideRules.put(originPattern, permission);
+ return this;
+ }
+
+ /**
+ * Set all required override rules at once using a map of origin patterns to
+ * {@link WebViewMediaIntegrityApiStatus}. This overwrites existing rules.
+ *
+ * If two or more origin patterns match a given origin site, the least permissive option
+ * will be chosen.
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY)
+ @NonNull
+ public Builder setOverrideRules(@NonNull Map<String,
+ @WebViewMediaIntegrityApiStatus Integer> overrideRules) {
+ mOverrideRules = overrideRules;
+ return this;
+ }
+
+ /**
+ * Build the config.
+ */
+ @NonNull
+ public WebViewMediaIntegrityApiStatusConfig build() {
+ return new WebViewMediaIntegrityApiStatusConfig(this);
+ }
+ }
+
+ /**
+ * Returns the default value for origins that don't match any override rules.
+ */
+ public @WebViewMediaIntegrityApiStatus int getDefaultStatus() {
+ return mDefaultStatus;
+ }
+
+ /**
+ * Get the explicitly set override rules.
+ * <p> This is a map from origin pattern to {@link WebViewMediaIntegrityApiStatus}.
+ *
+ */
+ @NonNull
+ public Map<String, @WebViewMediaIntegrityApiStatus Integer> getOverrideRules() {
+ return mOverrideRules;
+ }
+}
diff --git a/webkit/webkit/src/main/java/androidx/webkit/internal/WebSettingsAdapter.java b/webkit/webkit/src/main/java/androidx/webkit/internal/WebSettingsAdapter.java
index f99861b..64e29ec 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/internal/WebSettingsAdapter.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/internal/WebSettingsAdapter.java
@@ -20,6 +20,8 @@
import androidx.annotation.NonNull;
import androidx.webkit.UserAgentMetadata;
+import androidx.webkit.WebViewMediaIntegrityApiStatusConfig;
+
import org.chromium.support_lib_boundary.WebSettingsBoundaryInterface;
@@ -191,5 +193,26 @@
mBoundaryInterface.setAttributionBehavior(behavior);
}
+ /**
+ * Adapter method for
+ * {@link androidx.webkit.WebSettingsCompat#setWebViewMediaIntegrityApiStatus(WebSettings, WebViewMediaIntegrityApiStatusConfig)}
+ */
+ public void setWebViewMediaIntegrityApiStatus(
+ @NonNull WebViewMediaIntegrityApiStatusConfig permissionConfig) {
+ mBoundaryInterface.setWebViewMediaIntegrityApiStatus(permissionConfig.getDefaultStatus(),
+ permissionConfig.getOverrideRules());
+ }
+
+ /**
+ * Adapter method for
+ * {@link androidx.webkit.WebSettingsCompat#getWebViewMediaIntegrityApiStatus(WebSettings)}
+ */
+ @NonNull
+ public WebViewMediaIntegrityApiStatusConfig getWebViewMediaIntegrityApiStatus() {
+ return new WebViewMediaIntegrityApiStatusConfig
+ .Builder(mBoundaryInterface.getWebViewMediaIntegrityApiDefaultStatus())
+ .setOverrideRules(mBoundaryInterface.getWebViewMediaIntegrityApiOverrideRules())
+ .build();
+ }
}
diff --git a/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewFeatureInternal.java b/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewFeatureInternal.java
index 4790c176..802a76b 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewFeatureInternal.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewFeatureInternal.java
@@ -42,6 +42,7 @@
import androidx.webkit.WebMessagePortCompat;
import androidx.webkit.WebResourceErrorCompat;
import androidx.webkit.WebResourceRequestCompat;
+import androidx.webkit.WebSettingsCompat;
import androidx.webkit.WebViewClientCompat;
import androidx.webkit.WebViewCompat;
import androidx.webkit.WebViewFeature;
@@ -583,6 +584,17 @@
new ApiFeature.NoFramework(WebViewFeature.ATTRIBUTION_REGISTRATION_BEHAVIOR,
Features.ATTRIBUTION_BEHAVIOR);
+ /**
+ * Feature for {@link WebViewFeature#isFeatureSupported(String)}.
+ * This feature covers
+ * {@link androidx.webkit.WebSettingsCompat#setWebViewMediaIntegrityApiStatus(WebSettings, WebSettingsCompat.WebViewMediaIntegrityApiStatusConfig)}
+ * {@link androidx.webkit.WebSettingsCompat#getWebViewMediaIntegrityApiStatus(WebSettings)}
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ public static final ApiFeature.NoFramework WEBVIEW_MEDIA_INTEGRITY_API_STATUS =
+ new ApiFeature.NoFramework(WebViewFeature.WEBVIEW_MEDIA_INTEGRITY_API_STATUS,
+ Features.WEBVIEW_MEDIA_INTEGRITY_API_STATUS);
+
// --- Add new feature constants above this line ---
private WebViewFeatureInternal() {