[WebView Support Library] Implement onReceivedError
This is the second CL in a series to implement WebViewClientCompat.
This implements WebViewClientCompat#onReceivedError() and adds the
abstract class WebResourceErrorCompat.
We define 3 signatures for onReceivedError():
1. Inheriting the WebViewClient method with WebResourceError (called by
legacy WebView APKs on 23+)
2. Implementing the boundary interface method with an InvocationHandler
(called by up-to-date WebView APKs)
3. A new signature which uses WebResourceErrorCompat (which apps may
override)
Signatures 1 and 2 convert their parameter into a WebResourceErrorCompat
and invoke signature 3. Signature 3 also implements default behavior
resembling the corresponding WebViewClient method.
Design doc: http://go/wv-support-library-callbacks
Bug: 73151460
Test: Manual - build a test app with WebViewClientCompat
Change-Id: Ib8d9bbcaf15d770530b46e00d4dd1bb432ef862b
diff --git a/webkit/api/current.txt b/webkit/api/current.txt
index 08c6a55..5271a24 100644
--- a/webkit/api/current.txt
+++ b/webkit/api/current.txt
@@ -22,6 +22,11 @@
method public abstract void setCacheMode(int);
}
+ public abstract class WebResourceErrorCompat {
+ method public abstract java.lang.CharSequence getDescription();
+ method public abstract int getErrorCode();
+ }
+
public class WebSettingsCompat {
method public static int getDisabledActionModeMenuItems(android.webkit.WebSettings);
method public static boolean getOffscreenPreRaster(android.webkit.WebSettings);
@@ -33,6 +38,8 @@
public class WebViewClientCompat extends android.webkit.WebViewClient {
ctor public WebViewClientCompat();
+ method public final void onReceivedError(android.webkit.WebView, android.webkit.WebResourceRequest, android.webkit.WebResourceError);
+ method public void onReceivedError(android.webkit.WebView, android.webkit.WebResourceRequest, androidx.webkit.WebResourceErrorCompat);
}
public class WebViewCompat {
diff --git a/webkit/src/main/java/androidx/webkit/WebResourceErrorCompat.java b/webkit/src/main/java/androidx/webkit/WebResourceErrorCompat.java
new file mode 100644
index 0000000..32ea840
--- /dev/null
+++ b/webkit/src/main/java/androidx/webkit/WebResourceErrorCompat.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2018 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.WebResourceError;
+import android.webkit.WebViewClient;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.annotation.RestrictTo;
+
+import org.chromium.support_lib_boundary.WebResourceErrorBoundaryInterface;
+import org.chromium.support_lib_boundary.util.BoundaryInterfaceReflectionUtil;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.InvocationHandler;
+
+/**
+ * Compatibility version of {@link WebResourceError}.
+ */
+public abstract class WebResourceErrorCompat {
+ /** @hide */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ @IntDef(value = {
+ WebViewClient.ERROR_UNKNOWN,
+ WebViewClient.ERROR_HOST_LOOKUP,
+ WebViewClient.ERROR_UNSUPPORTED_AUTH_SCHEME,
+ WebViewClient.ERROR_AUTHENTICATION,
+ WebViewClient.ERROR_PROXY_AUTHENTICATION,
+ WebViewClient.ERROR_CONNECT,
+ WebViewClient.ERROR_IO,
+ WebViewClient.ERROR_TIMEOUT,
+ WebViewClient.ERROR_REDIRECT_LOOP,
+ WebViewClient.ERROR_UNSUPPORTED_SCHEME,
+ WebViewClient.ERROR_FAILED_SSL_HANDSHAKE,
+ WebViewClient.ERROR_BAD_URL,
+ WebViewClient.ERROR_FILE,
+ WebViewClient.ERROR_FILE_NOT_FOUND,
+ WebViewClient.ERROR_TOO_MANY_REQUESTS,
+ WebViewClient.ERROR_UNSAFE_RESOURCE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface NetErrorCode {}
+
+ /**
+ * Gets the error code of the error. The code corresponds to one
+ * of the {@code ERROR_*} constants in {@link WebViewClient}.
+ *
+ * @return The error code of the error
+ */
+ public abstract @NetErrorCode int getErrorCode();
+
+ /**
+ * Gets the string describing the error. Descriptions are localized,
+ * and thus can be used for communicating the problem to the user.
+ *
+ * @return The description of the error
+ */
+ @NonNull
+ public abstract CharSequence getDescription();
+
+ /**
+ * This class cannot be created by applications. The support library should instantiate this
+ * with {@link #fromInvocationHandler} or {@link #fromWebResourceError}.
+ */
+ private WebResourceErrorCompat() {
+ }
+
+ /**
+ * Conversion helper to create a WebResourceErrorCompat which delegates calls to {@param
+ * handler}. The InvocationHandler must be created by {@link
+ * BoundaryInterfaceReflectionUtil#createInvocationHandlerFor} using {@link
+ * WebResourceErrorBoundaryInterface}.
+ *
+ * @param handler The InvocationHandler that chromium passed in the callback.
+ */
+ @NonNull
+ /* package */ static WebResourceErrorCompat fromInvocationHandler(InvocationHandler handler) {
+ final WebResourceErrorBoundaryInterface errorDelegate =
+ BoundaryInterfaceReflectionUtil.castToSuppLibClass(
+ WebResourceErrorBoundaryInterface.class, handler);
+ return new WebResourceErrorCompat() {
+ @Override
+ public @NetErrorCode int getErrorCode() {
+ return errorDelegate.getErrorCode();
+ }
+
+ @Override
+ @NonNull
+ public CharSequence getDescription() {
+ return errorDelegate.getDescription();
+ }
+ };
+ }
+
+ /**
+ * Conversion helper to create a WebResourceErrorCompat which delegates calls to {@param error}.
+ *
+ * @param error The WebResourceError that chromium passed in the callback.
+ */
+ @NonNull
+ @RequiresApi(23)
+ /* package */ static WebResourceErrorCompat fromWebResourceError(final WebResourceError error) {
+ return new WebResourceErrorCompat() {
+ @Override
+ public @NetErrorCode int getErrorCode() {
+ return error.getErrorCode();
+ }
+
+ @Override
+ @NonNull
+ public CharSequence getDescription() {
+ return error.getDescription();
+ }
+ };
+ }
+}
diff --git a/webkit/src/main/java/androidx/webkit/WebViewClientCompat.java b/webkit/src/main/java/androidx/webkit/WebViewClientCompat.java
index 8c690f9..22a19fa 100644
--- a/webkit/src/main/java/androidx/webkit/WebViewClientCompat.java
+++ b/webkit/src/main/java/androidx/webkit/WebViewClientCompat.java
@@ -17,6 +17,7 @@
package androidx.webkit;
import android.os.Build;
+import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
@@ -57,17 +58,56 @@
}
/**
- * Invoked by chromium for the {@code onReceivedError} event. Applications are not meant to
- * override this, and should instead override the non-final {@code onReceivedError} method.
- * TODO(ntfschr): link to that method once it's implemented.
+ * Invoked by chromium (for up-to-date WebView APKs) for the {@code onReceivedError} event.
+ * Applications are not meant to override this, and should instead override the non-final {@link
+ * onReceivedError(WebView, WebResourceRequest, WebResourceErrorCompat)} method.
*
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@Override
+ @RequiresApi(21)
public final void onReceivedError(@NonNull WebView view, @NonNull WebResourceRequest request,
- /* WebResourceError */ @NonNull InvocationHandler error) {
- // TODO(ntfschr): implement this (b/73151460).
+ /* WebResourceError */ @NonNull InvocationHandler handler) {
+ onReceivedError(view, request, WebResourceErrorCompat.fromInvocationHandler(handler));
+ }
+
+ /**
+ * Invoked by chromium (in legacy WebView APKs) for the {@code onReceivedError} event on {@link
+ * Build.VERSION_CODES.M} and above. Applications are not meant to override this, and should
+ * instead override the non-final {@link onReceivedError(WebView, WebResourceRequest,
+ * WebResourceErrorCompat)} method.
+ *
+ * @hide
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ @Override
+ @RequiresApi(23)
+ public final void onReceivedError(@NonNull WebView view, @NonNull WebResourceRequest request,
+ @NonNull WebResourceError error) {
+ if (Build.VERSION.SDK_INT < 23) return;
+ onReceivedError(view, request, WebResourceErrorCompat.fromWebResourceError(error));
+ }
+
+ /**
+ * Report web resource loading error to the host application. These errors usually indicate
+ * inability to connect to the server. Note that unlike the deprecated version of the callback,
+ * the new version will be called for any resource (iframe, image, etc.), not just for the main
+ * page. Thus, it is recommended to perform minimum required work in this callback.
+ * @param view The WebView that is initiating the callback.
+ * @param request The originating request.
+ * @param error Information about the error occurred.
+ */
+ @SuppressWarnings("deprecation") // for invoking the old onReceivedError.
+ @RequiresApi(21)
+ public void onReceivedError(@NonNull WebView view, @NonNull WebResourceRequest request,
+ @NonNull WebResourceErrorCompat error) {
+ if (Build.VERSION.SDK_INT < 21) return;
+ if (request.isForMainFrame()) {
+ onReceivedError(view,
+ error.getErrorCode(), error.getDescription().toString(),
+ request.getUrl().toString());
+ }
}
@Override
@@ -90,10 +130,8 @@
// TODO(ntfschr): implement this (b/73151460).
}
- // Default behavior in WebViewClient is to invoke the other (deprecated)
- // shouldOverrideUrlLoading method.
@Override
- @SuppressWarnings("deprecation")
+ @SuppressWarnings("deprecation") // for invoking the old shouldOverrideUrlLoading.
@RequiresApi(21)
public boolean shouldOverrideUrlLoading(@NonNull WebView view,
@NonNull WebResourceRequest request) {