1 // Copyright (c) 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.Context;
8 import android.content.pm.ActivityInfo;
9 import android.graphics.Bitmap;
10 import android.graphics.Picture;
11 import android.graphics.Rect;
12 import android.graphics.RectF;
13 import android.net.http.SslError;
14 import android.os.Handler;
15 import android.os.Looper;
16 import android.os.Message;
17 import android.util.Log;
18 import android.view.KeyEvent;
19 import android.view.View;
20 import android.webkit.ConsoleMessage;
21 import android.webkit.GeolocationPermissions;
22 import android.webkit.SslErrorHandler;
23 import android.webkit.ValueCallback;
24 import android.webkit.WebChromeClient;
26 import org.chromium.content.browser.ContentVideoView;
27 import org.chromium.content.browser.ContentVideoViewClient;
28 import org.chromium.content.browser.ContentVideoViewControls;
29 import org.chromium.content.browser.ContentViewClient;
30 import org.chromium.content.browser.ContentViewCore;
31 import org.chromium.content.browser.WebContentsObserverAndroid;
32 import org.chromium.net.NetError;
35 * Base-class that an AwContents embedder derives from to receive callbacks.
36 * This extends ContentViewClient, as in many cases we want to pass-thru ContentViewCore
37 * callbacks right to our embedder, and this setup facilities that.
38 * For any other callbacks we need to make transformations of (e.g. adapt parameters
39 * or perform filtering) we can provide final overrides for methods here, and then introduce
40 * new abstract methods that the our own client must implement.
41 * i.e.: all methods in this class should either be final, or abstract.
43 public abstract class AwContentsClient {
45 private static final String TAG = "AwContentsClient";
46 private final AwContentsClientCallbackHelper mCallbackHelper;
48 private AwWebContentsObserver mWebContentsObserver;
50 private AwContentViewClient mContentViewClient = new AwContentViewClient();
52 // Last background color reported from the renderer. Holds the sentinal value INVALID_COLOR
54 private int mCachedRendererBackgroundColor = INVALID_COLOR;
56 private static final int INVALID_COLOR = 0;
58 public AwContentsClient() {
59 this(Looper.myLooper());
62 // Alllow injection of the callback thread, for testing.
63 public AwContentsClient(Looper looper) {
64 mCallbackHelper = new AwContentsClientCallbackHelper(looper, this);
67 class AwWebContentsObserver extends WebContentsObserverAndroid {
68 public AwWebContentsObserver(ContentViewCore contentViewCore) {
69 super(contentViewCore);
73 public void didStopLoading(String url) {
74 AwContentsClient.this.onPageFinished(url);
78 public void didFailLoad(boolean isProvisionalLoad,
79 boolean isMainFrame, int errorCode, String description, String failingUrl) {
80 if (errorCode == NetError.ERR_ABORTED) {
81 // This error code is generated for the following reasons:
82 // - WebView.stopLoading is called,
83 // - the navigation is intercepted by the embedder via shouldOverrideNavigation.
85 // The Android WebView does not notify the embedder of these situations using this
86 // error code with the WebViewClient.onReceivedError callback.
90 // The Android WebView does not notify the embedder of sub-frame failures.
93 AwContentsClient.this.onReceivedError(
94 ErrorCodeConversionHelper.convertErrorCode(errorCode), description, failingUrl);
98 public void didNavigateAnyFrame(String url, String baseUrl, boolean isReload) {
99 AwContentsClient.this.doUpdateVisitedHistory(url, isReload);
104 private class AwContentViewClient extends ContentViewClient {
106 public void onBackgroundColorChanged(int color) {
107 // Avoid storing the sentinal INVALID_COLOR (note that both 0 and 1 are both
108 // fully transparent so this transpose makes no visible difference).
109 mCachedRendererBackgroundColor = color == INVALID_COLOR ? 1 : color;
113 public void onStartContentIntent(Context context, String contentUrl) {
114 // Callback when detecting a click on a content link.
115 AwContentsClient.this.shouldOverrideUrlLoading(contentUrl);
119 public void onRendererCrash(boolean crashedWhileOomProtected) {
120 // This is not possible so long as the webview is run single process!
121 throw new RuntimeException("Renderer crash reported.");
125 public void onUpdateTitle(String title) {
126 AwContentsClient.this.onReceivedTitle(title);
130 public boolean shouldOverrideKeyEvent(KeyEvent event) {
131 return AwContentsClient.this.shouldOverrideKeyEvent(event);
135 final public ContentVideoViewClient getContentVideoViewClient() {
136 return new AwContentVideoViewClient();
140 final void installWebContentsObserver(ContentViewCore contentViewCore) {
141 if (mWebContentsObserver != null) {
142 mWebContentsObserver.detachFromWebContents();
144 mWebContentsObserver = new AwWebContentsObserver(contentViewCore);
147 private class AwContentVideoViewClient implements ContentVideoViewClient {
149 public void onShowCustomView(View view) {
150 WebChromeClient.CustomViewCallback cb = new WebChromeClient.CustomViewCallback() {
152 public void onCustomViewHidden() {
153 ContentVideoView contentVideoView = ContentVideoView.getContentVideoView();
154 if (contentVideoView != null)
155 contentVideoView.exitFullscreen(false);
158 AwContentsClient.this.onShowCustomView(view, cb);
162 public void onDestroyContentVideoView() {
163 AwContentsClient.this.onHideCustomView();
167 public View getVideoLoadingProgressView() {
168 return AwContentsClient.this.getVideoLoadingProgressView();
172 public ContentVideoViewControls createControls() {
177 final AwContentsClientCallbackHelper getCallbackHelper() {
178 return mCallbackHelper;
181 final ContentViewClient getContentViewClient() {
182 return mContentViewClient;
185 final int getCachedRendererBackgroundColor() {
186 assert isCachedRendererBackgroundColorValid();
187 return mCachedRendererBackgroundColor;
190 final boolean isCachedRendererBackgroundColorValid() {
191 return mCachedRendererBackgroundColor != INVALID_COLOR;
194 //--------------------------------------------------------------------------------------------
195 // WebView specific methods that map directly to WebViewClient / WebChromeClient
196 //--------------------------------------------------------------------------------------------
198 public static class FileChooserParams {
200 public String acceptTypes;
202 public String defaultFilename;
203 public boolean capture;
206 public abstract void getVisitedHistory(ValueCallback<String[]> callback);
208 public abstract void doUpdateVisitedHistory(String url, boolean isReload);
210 public abstract void onProgressChanged(int progress);
212 public abstract InterceptedRequestData shouldInterceptRequest(String url);
214 public abstract boolean shouldOverrideKeyEvent(KeyEvent event);
216 public abstract boolean shouldOverrideUrlLoading(String url);
218 public abstract void onLoadResource(String url);
220 public abstract void onUnhandledKeyEvent(KeyEvent event);
222 public abstract boolean onConsoleMessage(ConsoleMessage consoleMessage);
224 public abstract void onReceivedHttpAuthRequest(AwHttpAuthHandler handler,
225 String host, String realm);
227 public abstract void onReceivedSslError(ValueCallback<Boolean> callback, SslError error);
229 public abstract void onReceivedLoginRequest(String realm, String account, String args);
231 public abstract void onFormResubmission(Message dontResend, Message resend);
233 public abstract void onDownloadStart(String url, String userAgent, String contentDisposition,
234 String mimeType, long contentLength);
236 // TODO(joth): Make abstract once this has rolled in downstream.
237 public /*abstract*/ void showFileChooser(ValueCallback<String[]> uploadFilePathsCallback,
238 FileChooserParams fileChooserParams) { }
240 public abstract void onGeolocationPermissionsShowPrompt(String origin,
241 GeolocationPermissions.Callback callback);
243 public abstract void onGeolocationPermissionsHidePrompt();
245 public abstract void onScaleChangedScaled(float oldScale, float newScale);
247 protected abstract void handleJsAlert(String url, String message, JsResultReceiver receiver);
249 protected abstract void handleJsBeforeUnload(String url, String message,
250 JsResultReceiver receiver);
252 protected abstract void handleJsConfirm(String url, String message, JsResultReceiver receiver);
254 protected abstract void handleJsPrompt(String url, String message, String defaultValue,
255 JsPromptResultReceiver receiver);
257 protected abstract boolean onCreateWindow(boolean isDialog, boolean isUserGesture);
259 protected abstract void onCloseWindow();
261 public abstract void onReceivedTouchIconUrl(String url, boolean precomposed);
263 public abstract void onReceivedIcon(Bitmap bitmap);
265 public abstract void onReceivedTitle(String title);
267 protected abstract void onRequestFocus();
269 protected abstract View getVideoLoadingProgressView();
271 public abstract void onPageStarted(String url);
273 public abstract void onPageFinished(String url);
275 public abstract void onReceivedError(int errorCode, String description, String failingUrl);
277 // TODO (michaelbai): Remove this method once the same method remove from
278 // WebViewContentsClientAdapter.
279 public void onShowCustomView(View view,
280 int requestedOrientation, WebChromeClient.CustomViewCallback callback) {
283 // TODO (michaelbai): This method should be abstract, having empty body here
284 // makes the merge to the Android easy.
285 public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
286 onShowCustomView(view, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, callback);
289 public abstract void onHideCustomView();
291 public abstract Bitmap getDefaultVideoPoster();
293 //--------------------------------------------------------------------------------------------
294 // Other WebView-specific methods
295 //--------------------------------------------------------------------------------------------
297 public abstract void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
298 boolean isDoneCounting);
301 * Called whenever there is a new content picture available.
302 * @param picture New picture.
304 public abstract void onNewPicture(Picture picture);