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 44 public AwContentsClient() { 45 this(Looper.myLooper()); 46 } 47 48 // Alllow injection of the callback thread, for testing. 49 public AwContentsClient(Looper looper) { 50 mCallbackHelper = new AwContentsClientCallbackHelper(looper, this); 51 } 52 53 final AwContentsClientCallbackHelper getCallbackHelper() { 54 return mCallbackHelper; 55 } 56 57 final int getCachedRendererBackgroundColor() { 58 assert isCachedRendererBackgroundColorValid(); 59 return mCachedRendererBackgroundColor; 60 } 61 62 final boolean isCachedRendererBackgroundColorValid() { 63 return mCachedRendererBackgroundColor != INVALID_COLOR; 64 } 65 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 103 public abstract void getVisitedHistory(ValueCallback<String[]> callback); 104 105 public abstract void doUpdateVisitedHistory(String url, boolean isReload); 106 107 public abstract void onProgressChanged(int progress); 108 109 public abstract AwWebResourceResponse shouldInterceptRequest( 110 ShouldInterceptRequestParams params); 111 112 public abstract boolean shouldOverrideKeyEvent(KeyEvent event); 113 114 public abstract boolean shouldOverrideUrlLoading(String url); 115 116 public abstract void onLoadResource(String url); 117 118 public abstract void onUnhandledKeyEvent(KeyEvent event); 119 120 public abstract boolean onConsoleMessage(ConsoleMessage consoleMessage); 121 122 public abstract void onReceivedHttpAuthRequest(AwHttpAuthHandler handler, 123 String host, String realm); 124 125 public abstract void onReceivedSslError(ValueCallback<Boolean> callback, SslError error); 126 127 // TODO(sgurun): Make abstract once this has rolled in downstream. 128 public void onReceivedClientCertRequest( 129 final AwContentsClientBridge.ClientCertificateRequestCallback callback, 130 final String[] keyTypes, final Principal[] principals, final String host, 131 final int port) { } 132 133 public abstract void onReceivedLoginRequest(String realm, String account, String args); 134 135 public abstract void onFormResubmission(Message dontResend, Message resend); 136 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. 141 public /*abstract*/ void showFileChooser(ValueCallback<String[]> uploadFilePathsCallback, 142 FileChooserParams fileChooserParams) { } 143 144 public abstract void onGeolocationPermissionsShowPrompt(String origin, 145 GeolocationPermissions.Callback callback); 146 147 public abstract void onGeolocationPermissionsHidePrompt(); 148 149 // TODO(michaelbai): Change the abstract once merged 150 public /*abstract*/ void onPermissionRequest(AwPermissionRequest awPermissionRequest) {} 151 152 // TODO(michaelbai): Change the abstract once merged 153 public /*abstract*/ void onPermissionRequestCanceled( 154 AwPermissionRequest awPermissionRequest) {} 155 156 public abstract void onScaleChangedScaled(float oldScale, float newScale); 157 158 protected abstract void handleJsAlert(String url, String message, JsResultReceiver receiver); 159 160 protected abstract void handleJsBeforeUnload(String url, String message, 161 JsResultReceiver receiver); 162 163 protected abstract void handleJsConfirm(String url, String message, JsResultReceiver receiver); 164 165 protected abstract void handleJsPrompt(String url, String message, String defaultValue, 166 JsPromptResultReceiver receiver); 167 168 protected abstract boolean onCreateWindow(boolean isDialog, boolean isUserGesture); 169 170 protected abstract void onCloseWindow(); 171 172 public abstract void onReceivedTouchIconUrl(String url, boolean precomposed); 173 174 public abstract void onReceivedIcon(Bitmap bitmap); 175 176 public abstract void onReceivedTitle(String title); 177 178 protected abstract void onRequestFocus(); 179 180 protected abstract View getVideoLoadingProgressView(); 181 182 public abstract void onPageStarted(String url); 183 184 public abstract void onPageFinished(String url); 185 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. 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. 196 public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) { 197 onShowCustomView(view, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, callback); 198 } 199 200 public abstract void onHideCustomView(); 201 202 public abstract Bitmap getDefaultVideoPoster(); 203 204 //-------------------------------------------------------------------------------------------- 205 // Other WebView-specific methods 206 //-------------------------------------------------------------------------------------------- 207 // 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 */ 215 public abstract void onNewPicture(Picture picture); 216 217 } 218