| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package com.android.webview.chromium; | 5 package com.android.webview.chromium; |
| 6 | 6 |
| 7 import android.app.Activity; | |
| 8 import android.content.ActivityNotFoundException; | |
| 9 import android.content.Context; | 7 import android.content.Context; |
| 10 import android.content.Intent; | |
| 11 import android.graphics.Bitmap; | 8 import android.graphics.Bitmap; |
| 12 import android.graphics.BitmapFactory; | 9 import android.graphics.BitmapFactory; |
| 13 import android.graphics.Canvas; | 10 import android.graphics.Canvas; |
| 14 import android.graphics.Color; | 11 import android.graphics.Color; |
| 15 import android.graphics.Picture; | 12 import android.graphics.Picture; |
| 16 import android.net.Uri; | 13 import android.net.Uri; |
| 17 import android.net.http.SslError; | 14 import android.net.http.SslError; |
| 18 import android.os.Build; | 15 import android.os.Build; |
| 19 import android.os.Handler; | 16 import android.os.Handler; |
| 20 import android.os.Message; | 17 import android.os.Message; |
| 21 import android.provider.Browser; | |
| 22 import android.util.Log; | 18 import android.util.Log; |
| 23 import android.view.KeyEvent; | 19 import android.view.KeyEvent; |
| 24 import android.view.View; | 20 import android.view.View; |
| 25 import android.webkit.ClientCertRequest; | 21 import android.webkit.ClientCertRequest; |
| 26 import android.webkit.ConsoleMessage; | 22 import android.webkit.ConsoleMessage; |
| 27 import android.webkit.DownloadListener; | 23 import android.webkit.DownloadListener; |
| 28 import android.webkit.GeolocationPermissions; | 24 import android.webkit.GeolocationPermissions; |
| 29 import android.webkit.JsDialogHelper; | 25 import android.webkit.JsDialogHelper; |
| 30 import android.webkit.JsPromptResult; | 26 import android.webkit.JsPromptResult; |
| 31 import android.webkit.JsResult; | 27 import android.webkit.JsResult; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 48 import org.chromium.android_webview.JsPromptResultReceiver; | 44 import org.chromium.android_webview.JsPromptResultReceiver; |
| 49 import org.chromium.android_webview.JsResultReceiver; | 45 import org.chromium.android_webview.JsResultReceiver; |
| 50 import org.chromium.android_webview.permission.AwPermissionRequest; | 46 import org.chromium.android_webview.permission.AwPermissionRequest; |
| 51 import org.chromium.base.ThreadUtils; | 47 import org.chromium.base.ThreadUtils; |
| 52 import org.chromium.base.TraceEvent; | 48 import org.chromium.base.TraceEvent; |
| 53 import org.chromium.content.browser.ContentView; | 49 import org.chromium.content.browser.ContentView; |
| 54 import org.chromium.content.browser.ContentViewClient; | 50 import org.chromium.content.browser.ContentViewClient; |
| 55 import org.chromium.content.browser.ContentViewCore; | 51 import org.chromium.content.browser.ContentViewCore; |
| 56 | 52 |
| 57 import java.lang.ref.WeakReference; | 53 import java.lang.ref.WeakReference; |
| 58 import java.net.URISyntaxException; | |
| 59 import java.security.Principal; | 54 import java.security.Principal; |
| 60 import java.security.PrivateKey; | 55 import java.security.PrivateKey; |
| 61 import java.security.cert.X509Certificate; | 56 import java.security.cert.X509Certificate; |
| 62 import java.util.ArrayList; | 57 import java.util.ArrayList; |
| 63 import java.util.HashMap; | 58 import java.util.HashMap; |
| 64 import java.util.Map; | 59 import java.util.Map; |
| 65 import java.util.WeakHashMap; | 60 import java.util.WeakHashMap; |
| 66 | 61 |
| 67 /** | 62 /** |
| 68 * An adapter class that forwards the callbacks from {@link ContentViewClient} | 63 * An adapter class that forwards the callbacks from {@link ContentViewClient} |
| (...skipping 11 matching lines...) Expand all Loading... |
| 80 * or use an instance of ContentViewClientAdapter per WebViewChromium, to | 75 * or use an instance of ContentViewClientAdapter per WebViewChromium, to |
| 81 * allow the source WebView to be injected by ContentViewClientAdapter. We | 76 * allow the source WebView to be injected by ContentViewClientAdapter. We |
| 82 * choose the latter, because it makes for a cleaner design. | 77 * choose the latter, because it makes for a cleaner design. |
| 83 */ | 78 */ |
| 84 @SuppressWarnings("deprecation") | 79 @SuppressWarnings("deprecation") |
| 85 public class WebViewContentsClientAdapter extends AwContentsClient { | 80 public class WebViewContentsClientAdapter extends AwContentsClient { |
| 86 // TAG is chosen for consistency with classic webview tracing. | 81 // TAG is chosen for consistency with classic webview tracing. |
| 87 private static final String TAG = "WebViewCallback"; | 82 private static final String TAG = "WebViewCallback"; |
| 88 // Enables API callback tracing | 83 // Enables API callback tracing |
| 89 private static final boolean TRACE = false; | 84 private static final boolean TRACE = false; |
| 85 // Default WebViewClient used to avoid null checks. |
| 86 private static WebViewClient sNullWebViewClient = new WebViewClient(); |
| 90 // The WebView instance that this adapter is serving. | 87 // The WebView instance that this adapter is serving. |
| 91 private final WebView mWebView; | 88 private final WebView mWebView; |
| 92 // The Context to use. This is different from mWebView.getContext(), which s
hould not be used. | 89 // The Context to use. This is different from mWebView.getContext(), which s
hould not be used. |
| 93 private final Context mContext; | 90 private final Context mContext; |
| 94 // The WebViewClient instance that was passed to WebView.setWebViewClient(). | 91 // The WebViewClient instance that was passed to WebView.setWebViewClient(). |
| 95 private WebViewClient mWebViewClient; | 92 private WebViewClient mWebViewClient = sNullWebViewClient; |
| 96 // The WebChromeClient instance that was passed to WebView.setContentViewCli
ent(). | 93 // The WebChromeClient instance that was passed to WebView.setContentViewCli
ent(). |
| 97 private WebChromeClient mWebChromeClient; | 94 private WebChromeClient mWebChromeClient; |
| 98 // The listener receiving find-in-page API results. | 95 // The listener receiving find-in-page API results. |
| 99 private WebView.FindListener mFindListener; | 96 private WebView.FindListener mFindListener; |
| 100 // The listener receiving notifications of screen updates. | 97 // The listener receiving notifications of screen updates. |
| 101 private WebView.PictureListener mPictureListener; | 98 private WebView.PictureListener mPictureListener; |
| 102 | 99 |
| 103 private WebViewDelegate mWebViewDelegate; | 100 private WebViewDelegate mWebViewDelegate; |
| 104 | 101 |
| 105 private DownloadListener mDownloadListener; | 102 private DownloadListener mDownloadListener; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 | 148 |
| 152 WebViewChromium.completeWindowCreation(mWebView, newWebV
iew); | 149 WebViewChromium.completeWindowCreation(mWebView, newWebV
iew); |
| 153 break; | 150 break; |
| 154 default: | 151 default: |
| 155 throw new IllegalStateException(); | 152 throw new IllegalStateException(); |
| 156 } | 153 } |
| 157 } | 154 } |
| 158 }; | 155 }; |
| 159 } | 156 } |
| 160 | 157 |
| 161 // WebViewClassic is coded in such a way that even if a null WebViewClient i
s set, | |
| 162 // certain actions take place. | |
| 163 // We choose to replicate this behavior by using a NullWebViewClient impleme
ntation (also known | |
| 164 // as the Null Object pattern) rather than duplicating the WebViewClassic ap
proach in | |
| 165 // ContentView. | |
| 166 static class NullWebViewClient extends WebViewClient { | |
| 167 @Override | |
| 168 public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) { | |
| 169 // TODO: Investigate more and add a test case. | |
| 170 // This is reflecting Clank's behavior. | |
| 171 int keyCode = event.getKeyCode(); | |
| 172 return !ContentViewClient.shouldPropagateKey(keyCode); | |
| 173 } | |
| 174 | |
| 175 @Override | |
| 176 public boolean shouldOverrideUrlLoading(WebView view, String url) { | |
| 177 Intent intent; | |
| 178 // Perform generic parsing of the URI to turn it into an Intent. | |
| 179 try { | |
| 180 intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME); | |
| 181 } catch (URISyntaxException ex) { | |
| 182 Log.w(TAG, "Bad URI " + url + ": " + ex.getMessage()); | |
| 183 return false; | |
| 184 } | |
| 185 // Sanitize the Intent, ensuring web pages can not bypass browser | |
| 186 // security (only access to BROWSABLE activities). | |
| 187 intent.addCategory(Intent.CATEGORY_BROWSABLE); | |
| 188 intent.setComponent(null); | |
| 189 Intent selector = intent.getSelector(); | |
| 190 if (selector != null) { | |
| 191 selector.addCategory(Intent.CATEGORY_BROWSABLE); | |
| 192 selector.setComponent(null); | |
| 193 } | |
| 194 // Pass the package name as application ID so that the intent from t
he | |
| 195 // same application can be opened in the same tab. | |
| 196 intent.putExtra(Browser.EXTRA_APPLICATION_ID, view.getContext().getP
ackageName()); | |
| 197 | |
| 198 Context context = view.getContext(); | |
| 199 if (!(context instanceof Activity)) { | |
| 200 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | |
| 201 } | |
| 202 | |
| 203 try { | |
| 204 context.startActivity(intent); | |
| 205 } catch (ActivityNotFoundException ex) { | |
| 206 Log.w(TAG, "No application can handle " + url); | |
| 207 return false; | |
| 208 } | |
| 209 return true; | |
| 210 } | |
| 211 } | |
| 212 | |
| 213 void setWebViewClient(WebViewClient client) { | 158 void setWebViewClient(WebViewClient client) { |
| 214 if (client != null) { | 159 if (client != null) { |
| 215 mWebViewClient = client; | 160 mWebViewClient = client; |
| 216 } else { | 161 } else { |
| 217 mWebViewClient = new NullWebViewClient(); | 162 mWebViewClient = sNullWebViewClient; |
| 218 } | 163 } |
| 219 } | 164 } |
| 220 | 165 |
| 221 void setWebChromeClient(WebChromeClient client) { | 166 void setWebChromeClient(WebChromeClient client) { |
| 222 mWebChromeClient = client; | 167 mWebChromeClient = client; |
| 223 } | 168 } |
| 224 | 169 |
| 225 void setDownloadListener(DownloadListener listener) { | 170 void setDownloadListener(DownloadListener listener) { |
| 226 mDownloadListener = listener; | 171 mDownloadListener = listener; |
| 227 } | 172 } |
| 228 | 173 |
| 229 void setFindListener(WebView.FindListener listener) { | 174 void setFindListener(WebView.FindListener listener) { |
| 230 mFindListener = listener; | 175 mFindListener = listener; |
| 231 } | 176 } |
| 232 | 177 |
| 233 void setPictureListener(WebView.PictureListener listener) { | 178 void setPictureListener(WebView.PictureListener listener) { |
| 234 mPictureListener = listener; | 179 mPictureListener = listener; |
| 235 } | 180 } |
| 236 | 181 |
| 237 //--------------------------------------------------------------------------
------------------ | 182 //--------------------------------------------------------------------------
------------------ |
| 238 // Adapter for all the methods. | 183 // Adapter for all the methods. |
| 239 //--------------------------------------------------------------------------
------------------ | 184 //--------------------------------------------------------------------------
------------------ |
| 240 | 185 |
| 241 /** | 186 /** |
| 242 * @see AwContentsClient#getVisitedHistory | 187 * @see AwContentsClient#hasWebViewClient. |
| 188 */ |
| 189 @Override |
| 190 public boolean hasWebViewClient() { |
| 191 return mWebViewClient != sNullWebViewClient; |
| 192 } |
| 193 |
| 194 /** |
| 195 * @see AwContentsClient#getVisitedHistory. |
| 243 */ | 196 */ |
| 244 @Override | 197 @Override |
| 245 public void getVisitedHistory(ValueCallback<String[]> callback) { | 198 public void getVisitedHistory(ValueCallback<String[]> callback) { |
| 246 try { | 199 try { |
| 247 TraceEvent.begin("WebViewContentsClientAdapter.getVisitedHistory"); | 200 TraceEvent.begin("WebViewContentsClientAdapter.getVisitedHistory"); |
| 248 if (mWebChromeClient != null) { | 201 if (mWebChromeClient != null) { |
| 249 if (TRACE) Log.d(TAG, "getVisitedHistory"); | 202 if (TRACE) Log.d(TAG, "getVisitedHistory"); |
| 250 mWebChromeClient.getVisitedHistory(callback); | 203 mWebChromeClient.getVisitedHistory(callback); |
| 251 } | 204 } |
| 252 } finally { | 205 } finally { |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 641 } | 594 } |
| 642 } | 595 } |
| 643 | 596 |
| 644 /** | 597 /** |
| 645 * @see ContentViewClient#shouldOverrideKeyEvent(KeyEvent) | 598 * @see ContentViewClient#shouldOverrideKeyEvent(KeyEvent) |
| 646 */ | 599 */ |
| 647 @Override | 600 @Override |
| 648 public boolean shouldOverrideKeyEvent(KeyEvent event) { | 601 public boolean shouldOverrideKeyEvent(KeyEvent event) { |
| 649 try { | 602 try { |
| 650 TraceEvent.begin("WebViewContentsClientAdapter.shouldOverrideKeyEven
t"); | 603 TraceEvent.begin("WebViewContentsClientAdapter.shouldOverrideKeyEven
t"); |
| 651 // The check below is reflecting Clank's behavior and is a workaroun
d for | |
| 652 // http://b/7697782. | |
| 653 // 1. The check for system key should be made in AwContents or Conte
ntViewCore, before | |
| 654 // shouldOverrideKeyEvent() is called at all. | |
| 655 // 2. shouldOverrideKeyEvent() should be called in onKeyDown/onKeyUp
, not from | |
| 656 // dispatchKeyEvent(). | |
| 657 if (!ContentViewClient.shouldPropagateKey(event.getKeyCode())) retur
n true; | |
| 658 if (TRACE) Log.d(TAG, "shouldOverrideKeyEvent"); | 604 if (TRACE) Log.d(TAG, "shouldOverrideKeyEvent"); |
| 659 boolean result = mWebViewClient.shouldOverrideKeyEvent(mWebView, eve
nt); | 605 return mWebViewClient.shouldOverrideKeyEvent(mWebView, event); |
| 660 return result; | |
| 661 } finally { | 606 } finally { |
| 662 TraceEvent.end("WebViewContentsClientAdapter.shouldOverrideKeyEvent"
); | 607 TraceEvent.end("WebViewContentsClientAdapter.shouldOverrideKeyEvent"
); |
| 663 } | 608 } |
| 664 } | 609 } |
| 665 | 610 |
| 666 /** | |
| 667 * @see ContentViewClient#onStartContentIntent(Context, String) | |
| 668 * Callback when detecting a click on a content link. | |
| 669 */ | |
| 670 // TODO: Delete this method when removed from base class. | |
| 671 public void onStartContentIntent(Context context, String contentUrl) { | |
| 672 try { | |
| 673 TraceEvent.begin("WebViewContentsClientAdapter.onStartContentIntent"
); | |
| 674 if (TRACE) Log.d(TAG, "shouldOverrideUrlLoading=" + contentUrl); | |
| 675 mWebViewClient.shouldOverrideUrlLoading(mWebView, contentUrl); | |
| 676 } finally { | |
| 677 TraceEvent.end("WebViewContentsClientAdapter.onStartContentIntent"); | |
| 678 } | |
| 679 } | |
| 680 | |
| 681 @Override | 611 @Override |
| 682 public void onGeolocationPermissionsShowPrompt(String origin, | 612 public void onGeolocationPermissionsShowPrompt(String origin, |
| 683 GeolocationPermissions.Callback callback) { | 613 GeolocationPermissions.Callback callback) { |
| 684 try { | 614 try { |
| 685 TraceEvent.begin("WebViewContentsClientAdapter.onGeolocationPermissi
onsShowPrompt"); | 615 TraceEvent.begin("WebViewContentsClientAdapter.onGeolocationPermissi
onsShowPrompt"); |
| 686 if (mWebChromeClient != null) { | 616 if (mWebChromeClient != null) { |
| 687 if (TRACE) Log.d(TAG, "onGeolocationPermissionsShowPrompt"); | 617 if (TRACE) Log.d(TAG, "onGeolocationPermissionsShowPrompt"); |
| 688 mWebChromeClient.onGeolocationPermissionsShowPrompt(origin, call
back); | 618 mWebChromeClient.onGeolocationPermissionsShowPrompt(origin, call
back); |
| 689 } | 619 } |
| 690 } finally { | 620 } finally { |
| (...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1278 else | 1208 else |
| 1279 mAwPermissionRequest.deny(); | 1209 mAwPermissionRequest.deny(); |
| 1280 } | 1210 } |
| 1281 | 1211 |
| 1282 @Override | 1212 @Override |
| 1283 public void deny() { | 1213 public void deny() { |
| 1284 mAwPermissionRequest.deny(); | 1214 mAwPermissionRequest.deny(); |
| 1285 } | 1215 } |
| 1286 } | 1216 } |
| 1287 } | 1217 } |
| OLD | NEW |