1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.chromium.android_webview;
7 import android.content.pm.ActivityInfo;
8 import android.graphics.Bitmap;
9 import android.graphics.Picture;
10 import android.net.http.SslError;
11 import android.os.Looper;
12 import android.os.Message;
13 import android.view.KeyEvent;
14 import android.view.View;
15 import android.webkit.ConsoleMessage;
16 import android.webkit.GeolocationPermissions;
17 import android.webkit.ValueCallback;
18 import android.webkit.WebChromeClient;
20 import org.chromium.android_webview.permission.AwPermissionRequest;
21 import org.chromium.content.browser.ContentViewCore;
22 import org.chromium.content.browser.WebContentsObserverAndroid;
23 import org.chromium.net.NetError;
25 import java.security.Principal;
28 * Base-class that an AwContents embedder derives from to receive callbacks.
29 * This extends ContentViewClient, as in many cases we want to pass-thru ContentViewCore
30 * callbacks right to our embedder, and this setup facilities that.
31 * For any other callbacks we need to make transformations of (e.g. adapt parameters
32 * or perform filtering) we can provide final overrides for methods here, and then introduce
33 * new abstract methods that the our own client must implement.
34 * i.e.: all methods in this class should either be final, or abstract.
36 public abstract class AwContentsClient {
38 private final AwContentsClientCallbackHelper mCallbackHelper;
40 private AwWebContentsObserver mWebContentsObserver;
42 // Last background color reported from the renderer. Holds the sentinal value INVALID_COLOR
44 private int mCachedRendererBackgroundColor = INVALID_COLOR;
46 private static final int INVALID_COLOR = 0;
48 public AwContentsClient() {
49 this(Looper.myLooper());
52 // Alllow injection of the callback thread, for testing.
53 public AwContentsClient(Looper looper) {
54 mCallbackHelper = new AwContentsClientCallbackHelper(looper, this);
57 class AwWebContentsObserver extends WebContentsObserverAndroid {
58 public AwWebContentsObserver(ContentViewCore contentViewCore) {
59 super(contentViewCore);
63 public void didFinishLoad(long frameId, String validatedUrl, boolean isMainFrame) {
65 AwContentsClient.this.onPageFinished(validatedUrl);
70 public void didFailLoad(boolean isProvisionalLoad,
71 boolean isMainFrame, int errorCode, String description, String failingUrl) {
73 if (errorCode != NetError.ERR_ABORTED) {
74 // This error code is generated for the following reasons:
75 // - WebView.stopLoading is called,
76 // - the navigation is intercepted by the embedder via shouldOverrideNavigation.
78 // The Android WebView does not notify the embedder of these situations using
79 // this error code with the WebViewClient.onReceivedError callback.
80 AwContentsClient.this.onReceivedError(
81 ErrorCodeConversionHelper.convertErrorCode(errorCode), description,
84 // Need to call onPageFinished after onReceivedError (if there is an error) for
85 // backwards compatibility with the classic webview.
86 AwContentsClient.this.onPageFinished(failingUrl);
91 public void didNavigateMainFrame(String url, String baseUrl,
92 boolean isNavigationToDifferentPage, boolean isNavigationInPage) {
93 // This is here to emulate the Classic WebView firing onPageFinished for main frame
94 // navigations where only the hash fragment changes.
95 if (isNavigationInPage) {
96 AwContentsClient.this.onPageFinished(url);
101 public void didNavigateAnyFrame(String url, String baseUrl, boolean isReload) {
102 AwContentsClient.this.doUpdateVisitedHistory(url, isReload);
107 final void installWebContentsObserver(ContentViewCore contentViewCore) {
108 if (mWebContentsObserver != null) {
109 mWebContentsObserver.detachFromWebContents();
111 mWebContentsObserver = new AwWebContentsObserver(contentViewCore);
114 final AwContentsClientCallbackHelper getCallbackHelper() {
115 return mCallbackHelper;
118 final int getCachedRendererBackgroundColor() {
119 assert isCachedRendererBackgroundColorValid();
120 return mCachedRendererBackgroundColor;
123 final boolean isCachedRendererBackgroundColorValid() {
124 return mCachedRendererBackgroundColor != INVALID_COLOR;
127 final void onBackgroundColorChanged(int color) {
128 // Avoid storing the sentinal INVALID_COLOR (note that both 0 and 1 are both
129 // fully transparent so this transpose makes no visible difference).
130 mCachedRendererBackgroundColor = color == INVALID_COLOR ? 1 : color;
133 //--------------------------------------------------------------------------------------------
134 // WebView specific methods that map directly to WebViewClient / WebChromeClient
135 //--------------------------------------------------------------------------------------------
138 * Parameters for the {@link AwContentsClient#showFileChooser} method.
140 public static class FileChooserParams {
142 public String acceptTypes;
144 public String defaultFilename;
145 public boolean capture;
148 public abstract void getVisitedHistory(ValueCallback<String[]> callback);
150 public abstract void doUpdateVisitedHistory(String url, boolean isReload);
152 public abstract void onProgressChanged(int progress);
154 public abstract InterceptedRequestData shouldInterceptRequest(String url);
156 public abstract boolean shouldOverrideKeyEvent(KeyEvent event);
158 public abstract boolean shouldOverrideUrlLoading(String url);
160 public abstract void onLoadResource(String url);
162 public abstract void onUnhandledKeyEvent(KeyEvent event);
164 public abstract boolean onConsoleMessage(ConsoleMessage consoleMessage);
166 public abstract void onReceivedHttpAuthRequest(AwHttpAuthHandler handler,
167 String host, String realm);
169 public abstract void onReceivedSslError(ValueCallback<Boolean> callback, SslError error);
171 // TODO(sgurun): Make abstract once this has rolled in downstream.
172 public void onReceivedClientCertRequest(
173 final AwContentsClientBridge.ClientCertificateRequestCallback callback,
174 final String[] keyTypes, final Principal[] principals, final String host,
177 public abstract void onReceivedLoginRequest(String realm, String account, String args);
179 public abstract void onFormResubmission(Message dontResend, Message resend);
181 public abstract void onDownloadStart(String url, String userAgent, String contentDisposition,
182 String mimeType, long contentLength);
184 // TODO(joth): Make abstract once this has rolled in downstream.
185 public /*abstract*/ void showFileChooser(ValueCallback<String[]> uploadFilePathsCallback,
186 FileChooserParams fileChooserParams) { }
188 public abstract void onGeolocationPermissionsShowPrompt(String origin,
189 GeolocationPermissions.Callback callback);
191 public abstract void onGeolocationPermissionsHidePrompt();
193 // TODO(michaelbai): Change the abstract once merged
194 public /*abstract*/ void onPermissionRequest(AwPermissionRequest awPermissionRequest) {}
196 // TODO(michaelbai): Change the abstract once merged
197 public /*abstract*/ void onPermissionRequestCanceled(
198 AwPermissionRequest awPermissionRequest) {}
200 public abstract void onScaleChangedScaled(float oldScale, float newScale);
202 protected abstract void handleJsAlert(String url, String message, JsResultReceiver receiver);
204 protected abstract void handleJsBeforeUnload(String url, String message,
205 JsResultReceiver receiver);
207 protected abstract void handleJsConfirm(String url, String message, JsResultReceiver receiver);
209 protected abstract void handleJsPrompt(String url, String message, String defaultValue,
210 JsPromptResultReceiver receiver);
212 protected abstract boolean onCreateWindow(boolean isDialog, boolean isUserGesture);
214 protected abstract void onCloseWindow();
216 public abstract void onReceivedTouchIconUrl(String url, boolean precomposed);
218 public abstract void onReceivedIcon(Bitmap bitmap);
220 public abstract void onReceivedTitle(String title);
222 protected abstract void onRequestFocus();
224 protected abstract View getVideoLoadingProgressView();
226 public abstract void onPageStarted(String url);
228 public abstract void onPageFinished(String url);
230 public abstract void onReceivedError(int errorCode, String description, String failingUrl);
232 // TODO (michaelbai): Remove this method once the same method remove from
233 // WebViewContentsClientAdapter.
234 public void onShowCustomView(View view,
235 int requestedOrientation, WebChromeClient.CustomViewCallback callback) {
238 // TODO (michaelbai): This method should be abstract, having empty body here
239 // makes the merge to the Android easy.
240 public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
241 onShowCustomView(view, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, callback);
244 public abstract void onHideCustomView();
246 public abstract Bitmap getDefaultVideoPoster();
248 //--------------------------------------------------------------------------------------------
249 // Other WebView-specific methods
250 //--------------------------------------------------------------------------------------------
252 public abstract void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
253 boolean isDoneCounting);
256 * Called whenever there is a new content picture available.
257 * @param picture New picture.
259 public abstract void onNewPicture(Picture picture);