Chromium Code Reviews| 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)) { | |
|
boliu
2015/03/06 22:10:41
New implementation uses the ContextWrapper, so thi
| |
| 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 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 609 } | 562 } |
| 610 } | 563 } |
| 611 | 564 |
| 612 /** | 565 /** |
| 613 * @see ContentViewClient#shouldOverrideKeyEvent(KeyEvent) | 566 * @see ContentViewClient#shouldOverrideKeyEvent(KeyEvent) |
| 614 */ | 567 */ |
| 615 @Override | 568 @Override |
| 616 public boolean shouldOverrideKeyEvent(KeyEvent event) { | 569 public boolean shouldOverrideKeyEvent(KeyEvent event) { |
| 617 try { | 570 try { |
| 618 TraceEvent.begin("WebViewContentsClientAdapter.shouldOverrideKeyEven t"); | 571 TraceEvent.begin("WebViewContentsClientAdapter.shouldOverrideKeyEven t"); |
| 619 // The check below is reflecting Clank's behavior and is a workaroun d for | |
| 620 // http://b/7697782. | |
| 621 // 1. The check for system key should be made in AwContents or Conte ntViewCore, before | |
| 622 // shouldOverrideKeyEvent() is called at all. | |
| 623 // 2. shouldOverrideKeyEvent() should be called in onKeyDown/onKeyUp , not from | |
| 624 // dispatchKeyEvent(). | |
| 625 if (!ContentViewClient.shouldPropagateKey(event.getKeyCode())) retur n true; | |
| 626 if (TRACE) Log.d(TAG, "shouldOverrideKeyEvent"); | 572 if (TRACE) Log.d(TAG, "shouldOverrideKeyEvent"); |
| 627 boolean result = mWebViewClient.shouldOverrideKeyEvent(mWebView, eve nt); | 573 return mWebViewClient.shouldOverrideKeyEvent(mWebView, event); |
| 628 return result; | |
| 629 } finally { | 574 } finally { |
| 630 TraceEvent.end("WebViewContentsClientAdapter.shouldOverrideKeyEvent" ); | 575 TraceEvent.end("WebViewContentsClientAdapter.shouldOverrideKeyEvent" ); |
| 631 } | 576 } |
| 632 } | 577 } |
| 633 | 578 |
| 634 /** | |
| 635 * @see ContentViewClient#onStartContentIntent(Context, String) | |
| 636 * Callback when detecting a click on a content link. | |
| 637 */ | |
| 638 // TODO: Delete this method when removed from base class. | |
| 639 public void onStartContentIntent(Context context, String contentUrl) { | |
| 640 try { | |
| 641 TraceEvent.begin("WebViewContentsClientAdapter.onStartContentIntent" ); | |
| 642 if (TRACE) Log.d(TAG, "shouldOverrideUrlLoading=" + contentUrl); | |
| 643 mWebViewClient.shouldOverrideUrlLoading(mWebView, contentUrl); | |
| 644 } finally { | |
| 645 TraceEvent.end("WebViewContentsClientAdapter.onStartContentIntent"); | |
| 646 } | |
| 647 } | |
| 648 | |
| 649 @Override | 579 @Override |
| 650 public void onGeolocationPermissionsShowPrompt(String origin, | 580 public void onGeolocationPermissionsShowPrompt(String origin, |
| 651 GeolocationPermissions.Callback callback) { | 581 GeolocationPermissions.Callback callback) { |
| 652 try { | 582 try { |
| 653 TraceEvent.begin("WebViewContentsClientAdapter.onGeolocationPermissi onsShowPrompt"); | 583 TraceEvent.begin("WebViewContentsClientAdapter.onGeolocationPermissi onsShowPrompt"); |
| 654 if (mWebChromeClient != null) { | 584 if (mWebChromeClient != null) { |
| 655 if (TRACE) Log.d(TAG, "onGeolocationPermissionsShowPrompt"); | 585 if (TRACE) Log.d(TAG, "onGeolocationPermissionsShowPrompt"); |
| 656 mWebChromeClient.onGeolocationPermissionsShowPrompt(origin, call back); | 586 mWebChromeClient.onGeolocationPermissionsShowPrompt(origin, call back); |
| 657 } | 587 } |
| 658 } finally { | 588 } finally { |
| (...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1246 else | 1176 else |
| 1247 mAwPermissionRequest.deny(); | 1177 mAwPermissionRequest.deny(); |
| 1248 } | 1178 } |
| 1249 | 1179 |
| 1250 @Override | 1180 @Override |
| 1251 public void deny() { | 1181 public void deny() { |
| 1252 mAwPermissionRequest.deny(); | 1182 mAwPermissionRequest.deny(); |
| 1253 } | 1183 } |
| 1254 } | 1184 } |
| 1255 } | 1185 } |
| OLD | NEW |