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. 4 5 package org.chromium.android_webview; 6 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; 19 20 import org.chromium.android_webview.permission.AwPermissionRequest; 21 22 import java.security.Principal; 23 import java.util.HashMap; 24 25 /** 26 * Base-class that an AwContents embedder derives from to receive callbacks. 27 * This extends ContentViewClient, as in many cases we want to pass-thru ContentViewCore 28 * callbacks right to our embedder, and this setup facilities that. 29 * For any other callbacks we need to make transformations of (e.g. adapt parameters 30 * or perform filtering) we can provide final overrides for methods here, and then introduce 31 * new abstract methods that the our own client must implement. 32 * i.e.: all methods in this class should either be final, or abstract. 33 */ 34 public abstract class AwContentsClient { 35 36 private final AwContentsClientCallbackHelper mCallbackHelper; 37 38 // Last background color reported from the renderer. Holds the sentinal value INVALID_COLOR 39 // if not valid. 40 private int mCachedRendererBackgroundColor = INVALID_COLOR; 41 42 private static final int INVALID_COLOR = 0; 43 AwContentsClient()44 public AwContentsClient() { 45 this(Looper.myLooper()); 46 } 47 48 // Alllow injection of the callback thread, for testing. AwContentsClient(Looper looper)49 public AwContentsClient(Looper looper) { 50 mCallbackHelper = new AwContentsClientCallbackHelper(looper, this); 51 } 52 getCallbackHelper()53 final AwContentsClientCallbackHelper getCallbackHelper() { 54 return mCallbackHelper; 55 } 56 getCachedRendererBackgroundColor()57 final int getCachedRendererBackgroundColor() { 58 assert isCachedRendererBackgroundColorValid(); 59 return mCachedRendererBackgroundColor; 60 } 61 isCachedRendererBackgroundColorValid()62 final boolean isCachedRendererBackgroundColorValid() { 63 return mCachedRendererBackgroundColor != INVALID_COLOR; 64 } 65 onBackgroundColorChanged(int color)66 final void onBackgroundColorChanged(int color) { 67 // Avoid storing the sentinal INVALID_COLOR (note that both 0 and 1 are both 68 // fully transparent so this transpose makes no visible difference). 69 mCachedRendererBackgroundColor = color == INVALID_COLOR ? 1 : color; 70 } 71 72 //-------------------------------------------------------------------------------------------- 73 // WebView specific methods that map directly to WebViewClient / WebChromeClient 74 //-------------------------------------------------------------------------------------------- 75 76 /** 77 * Parameters for the {@link AwContentsClient#showFileChooser} method. 78 */ 79 public static class FileChooserParams { 80 public int mode; 81 public String acceptTypes; 82 public String title; 83 public String defaultFilename; 84 public boolean capture; 85 } 86 87 /** 88 * Parameters for the {@link AwContentsClient#shouldInterceptRequest} method. 89 */ 90 public static class ShouldInterceptRequestParams { 91 // Url of the request. 92 public String url; 93 // Is this for the main frame or a child iframe? 94 public boolean isMainFrame; 95 // Was a gesture associated with the request? Don't trust can easily be spoofed. 96 public boolean hasUserGesture; 97 // Method used (GET/POST/OPTIONS) 98 public String method; 99 // Headers that would have been sent to server. 100 public HashMap<String, String> requestHeaders; 101 } 102 getVisitedHistory(ValueCallback<String[]> callback)103 public abstract void getVisitedHistory(ValueCallback<String[]> callback); 104 doUpdateVisitedHistory(String url, boolean isReload)105 public abstract void doUpdateVisitedHistory(String url, boolean isReload); 106 onProgressChanged(int progress)107 public abstract void onProgressChanged(int progress); 108 shouldInterceptRequest( ShouldInterceptRequestParams params)109 public abstract AwWebResourceResponse shouldInterceptRequest( 110 ShouldInterceptRequestParams params); 111 shouldOverrideKeyEvent(KeyEvent event)112 public abstract boolean shouldOverrideKeyEvent(KeyEvent event); 113 shouldOverrideUrlLoading(String url)114 public abstract boolean shouldOverrideUrlLoading(String url); 115 onLoadResource(String url)116 public abstract void onLoadResource(String url); 117 onUnhandledKeyEvent(KeyEvent event)118 public abstract void onUnhandledKeyEvent(KeyEvent event); 119 onConsoleMessage(ConsoleMessage consoleMessage)120 public abstract boolean onConsoleMessage(ConsoleMessage consoleMessage); 121 onReceivedHttpAuthRequest(AwHttpAuthHandler handler, String host, String realm)122 public abstract void onReceivedHttpAuthRequest(AwHttpAuthHandler handler, 123 String host, String realm); 124 onReceivedSslError(ValueCallback<Boolean> callback, SslError error)125 public abstract void onReceivedSslError(ValueCallback<Boolean> callback, SslError error); 126 127 // TODO(sgurun): Make abstract once this has rolled in downstream. onReceivedClientCertRequest( final AwContentsClientBridge.ClientCertificateRequestCallback callback, final String[] keyTypes, final Principal[] principals, final String host, final int port)128 public void onReceivedClientCertRequest( 129 final AwContentsClientBridge.ClientCertificateRequestCallback callback, 130 final String[] keyTypes, final Principal[] principals, final String host, 131 final int port) { } 132 onReceivedLoginRequest(String realm, String account, String args)133 public abstract void onReceivedLoginRequest(String realm, String account, String args); 134 onFormResubmission(Message dontResend, Message resend)135 public abstract void onFormResubmission(Message dontResend, Message resend); 136 onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength)137 public abstract void onDownloadStart(String url, String userAgent, String contentDisposition, 138 String mimeType, long contentLength); 139 140 // TODO(joth): Make abstract once this has rolled in downstream. showFileChooser(ValueCallback<String[]> uploadFilePathsCallback, FileChooserParams fileChooserParams)141 public /*abstract*/ void showFileChooser(ValueCallback<String[]> uploadFilePathsCallback, 142 FileChooserParams fileChooserParams) { } 143 onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback)144 public abstract void onGeolocationPermissionsShowPrompt(String origin, 145 GeolocationPermissions.Callback callback); 146 onGeolocationPermissionsHidePrompt()147 public abstract void onGeolocationPermissionsHidePrompt(); 148 149 // TODO(michaelbai): Change the abstract once merged onPermissionRequest(AwPermissionRequest awPermissionRequest)150 public /*abstract*/ void onPermissionRequest(AwPermissionRequest awPermissionRequest) {} 151 152 // TODO(michaelbai): Change the abstract once merged onPermissionRequestCanceled( AwPermissionRequest awPermissionRequest)153 public /*abstract*/ void onPermissionRequestCanceled( 154 AwPermissionRequest awPermissionRequest) {} 155 onScaleChangedScaled(float oldScale, float newScale)156 public abstract void onScaleChangedScaled(float oldScale, float newScale); 157 handleJsAlert(String url, String message, JsResultReceiver receiver)158 protected abstract void handleJsAlert(String url, String message, JsResultReceiver receiver); 159 handleJsBeforeUnload(String url, String message, JsResultReceiver receiver)160 protected abstract void handleJsBeforeUnload(String url, String message, 161 JsResultReceiver receiver); 162 handleJsConfirm(String url, String message, JsResultReceiver receiver)163 protected abstract void handleJsConfirm(String url, String message, JsResultReceiver receiver); 164 handleJsPrompt(String url, String message, String defaultValue, JsPromptResultReceiver receiver)165 protected abstract void handleJsPrompt(String url, String message, String defaultValue, 166 JsPromptResultReceiver receiver); 167 onCreateWindow(boolean isDialog, boolean isUserGesture)168 protected abstract boolean onCreateWindow(boolean isDialog, boolean isUserGesture); 169 onCloseWindow()170 protected abstract void onCloseWindow(); 171 onReceivedTouchIconUrl(String url, boolean precomposed)172 public abstract void onReceivedTouchIconUrl(String url, boolean precomposed); 173 onReceivedIcon(Bitmap bitmap)174 public abstract void onReceivedIcon(Bitmap bitmap); 175 onReceivedTitle(String title)176 public abstract void onReceivedTitle(String title); 177 onRequestFocus()178 protected abstract void onRequestFocus(); 179 getVideoLoadingProgressView()180 protected abstract View getVideoLoadingProgressView(); 181 onPageStarted(String url)182 public abstract void onPageStarted(String url); 183 onPageFinished(String url)184 public abstract void onPageFinished(String url); 185 onReceivedError(int errorCode, String description, String failingUrl)186 public abstract void onReceivedError(int errorCode, String description, String failingUrl); 187 188 // TODO (michaelbai): Remove this method once the same method remove from 189 // WebViewContentsClientAdapter. onShowCustomView(View view, int requestedOrientation, WebChromeClient.CustomViewCallback callback)190 public void onShowCustomView(View view, 191 int requestedOrientation, WebChromeClient.CustomViewCallback callback) { 192 } 193 194 // TODO (michaelbai): This method should be abstract, having empty body here 195 // makes the merge to the Android easy. onShowCustomView(View view, WebChromeClient.CustomViewCallback callback)196 public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) { 197 onShowCustomView(view, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, callback); 198 } 199 onHideCustomView()200 public abstract void onHideCustomView(); 201 getDefaultVideoPoster()202 public abstract Bitmap getDefaultVideoPoster(); 203 204 //-------------------------------------------------------------------------------------------- 205 // Other WebView-specific methods 206 //-------------------------------------------------------------------------------------------- 207 // onFindResultReceived(int activeMatchOrdinal, int numberOfMatches, boolean isDoneCounting)208 public abstract void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches, 209 boolean isDoneCounting); 210 211 /** 212 * Called whenever there is a new content picture available. 213 * @param picture New picture. 214 */ onNewPicture(Picture picture)215 public abstract void onNewPicture(Picture picture); 216 217 } 218