1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Copyright (c) 2013 Intel Corporation. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
6 package org.xwalk.core;
8 import android.content.Intent;
9 import android.graphics.Bitmap;
10 import android.graphics.Picture;
11 import android.net.http.SslCertificate;
12 import android.net.http.SslError;
13 import android.os.Message;
14 import android.util.Log;
15 import android.view.KeyEvent;
16 import android.view.View;
17 import android.webkit.ConsoleMessage;
18 import android.webkit.ValueCallback;
19 import android.webkit.WebResourceResponse;
21 import org.chromium.base.CalledByNative;
22 import org.chromium.base.JNINamespace;
23 import org.chromium.base.ThreadUtils;
24 import org.chromium.components.navigation_interception.InterceptNavigationDelegate;
25 import org.chromium.components.navigation_interception.NavigationParams;
26 import org.chromium.content.browser.ContentVideoViewClient;
27 import org.chromium.content.browser.ContentViewDownloadDelegate;
28 import org.chromium.content.browser.DownloadInfo;
30 // Help bridge callback in XWalkContentsClient to XWalkViewClient and
31 // WebChromeClient; Also handle the JNI conmmunication logic.
32 @JNINamespace("xwalk")
33 public class XWalkContentsClientBridge extends XWalkContentsClient
34 implements ContentViewDownloadDelegate {
36 private XWalkView mXWalkView;
37 private XWalkClient mXWalkClient;
38 private XWalkWebChromeClient mXWalkWebChromeClient;
39 private Bitmap mFavicon;
40 private DownloadListener mDownloadListener;
41 private InterceptNavigationDelegate mInterceptNavigationDelegate;
42 private PageLoadListener mPageLoadListener;
43 private XWalkNavigationHandler mNavigationHandler;
44 private XWalkNotificationService mNotificationService;
46 // The native peer of the object
47 private int mNativeContentsClientBridge;
49 private class InterceptNavigationDelegateImpl implements InterceptNavigationDelegate {
50 private XWalkContentsClient mContentsClient;
52 public InterceptNavigationDelegateImpl(XWalkContentsClient client) {
53 mContentsClient = client;
56 public boolean shouldIgnoreNavigation(NavigationParams navigationParams) {
57 final String url = navigationParams.url;
58 boolean ignoreNavigation = shouldOverrideUrlLoading(url) ||
59 (mNavigationHandler != null &&
60 mNavigationHandler.handleNavigation(navigationParams));
62 if (!ignoreNavigation) {
63 // Post a message to UI thread to notify the page is starting to load.
64 mContentsClient.getCallbackHelper().postOnPageStarted(url);
67 return ignoreNavigation;
71 public XWalkContentsClientBridge(XWalkView xwView) {
74 mInterceptNavigationDelegate = new InterceptNavigationDelegateImpl(this);
77 public void setXWalkWebChromeClient(XWalkWebChromeClient client) {
78 mXWalkWebChromeClient = client;
81 public XWalkWebChromeClient getXWalkWebChromeClient() {
82 return mXWalkWebChromeClient;
85 public void setXWalkClient(XWalkClient client) {
86 mXWalkClient = client;
89 public void setNavigationHandler(XWalkNavigationHandler handler) {
90 mNavigationHandler = handler;
93 void registerPageLoadListener(PageLoadListener listener) {
94 mPageLoadListener = listener;
97 public void setNotificationService(XWalkNotificationService service) {
98 if (mNotificationService != null) mNotificationService.shutdown();
99 mNotificationService = service;
100 if (mNotificationService != null) mNotificationService.setBridge(this);
103 public boolean onNewIntent(Intent intent) {
104 return mNotificationService.maybeHandleIntent(intent);
107 public InterceptNavigationDelegate getInterceptNavigationDelegate() {
108 return mInterceptNavigationDelegate;
111 // TODO(Xingnan): All the empty functions need to be implemented.
113 public boolean shouldOverrideUrlLoading(String url) {
114 if (mXWalkClient != null && mXWalkView != null)
115 return mXWalkClient.shouldOverrideUrlLoading(mXWalkView, url);
120 public void onUnhandledKeyEvent(KeyEvent event) {
124 public void getVisitedHistory(ValueCallback<String[]> callback) {
128 public void doUpdateVisitedHistory(String url, boolean isReload) {
132 public void onProgressChanged(int progress) {
133 if (mXWalkWebChromeClient != null && mXWalkView != null)
134 mXWalkWebChromeClient.onProgressChanged(mXWalkView, progress);
138 public WebResourceResponse shouldInterceptRequest(String url) {
139 if (mXWalkClient != null && mXWalkView != null)
140 return mXWalkClient.shouldInterceptRequest(mXWalkView, url);
145 public void onLoadResource(String url) {
146 if (mXWalkClient != null && mXWalkView != null)
147 mXWalkClient.onLoadResource(mXWalkView, url);
151 public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
156 public void onReceivedHttpAuthRequest(XWalkHttpAuthHandler handler, String host, String realm) {
157 if (mXWalkClient != null && mXWalkView != null)
158 mXWalkClient.onReceivedHttpAuthRequest(mXWalkView, handler, host, realm);
161 public void onReceivedSslError(SslErrorHandler handler, SslError error) {
162 if (mXWalkClient != null && mXWalkView != null)
163 mXWalkClient.onReceivedSslError(mXWalkView, handler, error);
167 public void onReceivedLoginRequest(String realm, String account, String args) {
171 public void onGeolocationPermissionsShowPrompt(String origin,
172 XWalkGeolocationPermissions.Callback callback) {
173 if (mXWalkWebChromeClient != null) {
174 mXWalkWebChromeClient.onGeolocationPermissionsShowPrompt(origin, callback);
179 public void onGeolocationPermissionsHidePrompt() {
180 if (mXWalkWebChromeClient != null) {
181 mXWalkWebChromeClient.onGeolocationPermissionsHidePrompt();
186 public void handleJsAlert(String url, String message, JsResult result) {
187 if (mXWalkWebChromeClient != null && mXWalkView != null) {
188 mXWalkWebChromeClient.onJsAlert(mXWalkView, url, message, result);
193 public void handleJsBeforeUnload(String url, String message, JsResult result) {
194 if (mXWalkWebChromeClient != null && mXWalkView != null) {
195 mXWalkWebChromeClient.onJsBeforeUnload(mXWalkView, url, message, result);
200 public void handleJsConfirm(String url, String message, JsResult result) {
201 if (mXWalkWebChromeClient != null && mXWalkView != null) {
202 mXWalkWebChromeClient.onJsConfirm(mXWalkView, url, message, result);
207 public void handleJsPrompt(
208 String url, String message, String defaultValue, JsPromptResult result) {
209 if (mXWalkWebChromeClient != null && mXWalkView != null) {
210 mXWalkWebChromeClient.onJsPrompt(mXWalkView, url, message, defaultValue, result);
215 public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
216 boolean isDoneCounting) {
220 public void onNewPicture(Picture picture) {
224 public void onPageStarted(String url) {
225 if (mXWalkClient != null && mXWalkView != null) {
226 mXWalkClient.onPageStarted(mXWalkView, url, mFavicon);
231 public void onPageFinished(String url) {
232 if (mPageLoadListener != null) mPageLoadListener.onPageFinished(url);
233 if (mXWalkClient != null && mXWalkView != null) {
234 mXWalkClient.onPageFinished(mXWalkView, url);
239 public void onReceivedError(int errorCode, String description, String failingUrl) {
240 if (mXWalkClient != null && mXWalkView != null) {
241 mXWalkClient.onReceivedError(mXWalkView, errorCode, description, failingUrl);
246 public void onRendererUnresponsive() {
247 if (mXWalkClient != null && mXWalkView != null) {
248 mXWalkClient.onRendererUnresponsive(mXWalkView);
253 public void onRendererResponsive() {
254 if (mXWalkClient != null && mXWalkView != null) {
255 mXWalkClient.onRendererResponsive(mXWalkView);
260 public void onFormResubmission(Message dontResend, Message resend) {
261 dontResend.sendToTarget();
265 public void onDownloadStart(String url,
267 String contentDisposition,
269 long contentLength) {
273 public boolean onCreateWindow(boolean isDialog, boolean isUserGesture) {
278 public void onCloseWindow() {
279 if (mXWalkClient != null) {
280 mXWalkClient.onCloseWindow(mXWalkView);
285 public void onRequestFocus() {
289 public void onReceivedTouchIconUrl(String url, boolean precomposed) {
290 if (mXWalkWebChromeClient != null && mXWalkView != null) {
291 mXWalkWebChromeClient.onReceivedTouchIconUrl(mXWalkView, url, precomposed);
296 public void onReceivedIcon(Bitmap bitmap) {
297 if (mXWalkWebChromeClient != null && mXWalkView != null) {
298 mXWalkWebChromeClient.onReceivedIcon(mXWalkView, bitmap);
304 public void onShowCustomView(View view, XWalkWebChromeClient.CustomViewCallback callback) {
305 if (mXWalkWebChromeClient != null) {
306 mXWalkWebChromeClient.onShowCustomView(view, callback);
311 public void onHideCustomView() {
312 if (mXWalkWebChromeClient != null) {
313 mXWalkWebChromeClient.onHideCustomView();
318 public void onScaleChangedScaled(float oldScale, float newScale) {
322 protected View getVideoLoadingProgressView() {
323 if (mXWalkWebChromeClient != null)
324 return mXWalkWebChromeClient.getVideoLoadingProgressView();
329 public Bitmap getDefaultVideoPoster() {
334 public void didFinishLoad(String url) {
338 public void onTitleChanged(String title) {
339 if (mXWalkWebChromeClient != null && mXWalkView != null) {
340 mXWalkWebChromeClient.onReceivedTitle(mXWalkView, title);
345 public void onToggleFullscreen(boolean enterFullscreen) {
346 if (mXWalkWebChromeClient != null) {
347 mXWalkWebChromeClient.onToggleFullscreen(enterFullscreen);
352 public boolean isFullscreen() {
353 if (mXWalkWebChromeClient != null) return mXWalkWebChromeClient.isFullscreen();
359 public ContentVideoViewClient getContentVideoViewClient() {
360 return new XWalkContentVideoViewClient(this, mXWalkView.getActivity());
363 // Used by the native peer to set/reset a weak ref to the native peer.
365 private void setNativeContentsClientBridge(int nativeContentsClientBridge) {
366 mNativeContentsClientBridge = nativeContentsClientBridge;
369 // If returns false, the request is immediately canceled, and any call to proceedSslError
370 // has no effect. If returns true, the request should be canceled or proceeded using
371 // proceedSslError().
372 // Unlike the webview classic, we do not keep keep a database of certificates that
373 // are allowed by the user, because this functionality is already handled via
374 // ssl_policy in native layers.
376 private boolean allowCertificateError(int certError, byte[] derBytes, final String url,
378 // TODO(yongsheng): Implement this.
382 private void proceedSslError(boolean proceed, int id) {
383 if (mNativeContentsClientBridge == 0) return;
384 nativeProceedSslError(mNativeContentsClientBridge, proceed, id);
388 private void handleJsAlert(String url, String message, int id) {
389 JsResultHandler handler = new JsResultHandler(this, id);
390 handleJsAlert(url, message, handler);
394 private void handleJsConfirm(String url, String message, int id) {
395 JsResultHandler handler = new JsResultHandler(this, id);
396 handleJsConfirm(url, message, handler);
400 private void handleJsPrompt(String url, String message, String defaultValue, int id) {
401 JsResultHandler handler = new JsResultHandler(this, id);
402 handleJsPrompt(url, message, defaultValue, handler);
406 private void handleJsBeforeUnload(String url, String message, int id) {
407 JsResultHandler handler = new JsResultHandler(this, id);
408 handleJsBeforeUnload(url, message, handler);
412 private void updateNotificationIcon(int notificationId, Bitmap icon) {
413 mNotificationService.updateNotificationIcon(notificationId, icon);
417 private void showNotification(String title, String message, String replaceId,
418 int notificationId, int processId, int routeId) {
419 // FIXME(wang16): use replaceId to replace exist notification. It happens when
420 // a notification with same name and tag fires.
421 mNotificationService.showNotification(
422 title, message, notificationId, processId, routeId);
426 private void cancelNotification(int notificationId, int processId, int routeId) {
427 mNotificationService.cancelNotification(notificationId, processId, routeId);
430 void confirmJsResult(int id, String prompt) {
431 if (mNativeContentsClientBridge == 0) return;
432 nativeConfirmJsResult(mNativeContentsClientBridge, id, prompt);
435 void cancelJsResult(int id) {
436 if (mNativeContentsClientBridge == 0) return;
437 nativeCancelJsResult(mNativeContentsClientBridge, id);
440 void exitFullscreen(int nativeWebContents) {
441 if (mNativeContentsClientBridge == 0) return;
442 nativeExitFullscreen(mNativeContentsClientBridge, nativeWebContents);
445 public void notificationDisplayed(int id, int processId, int routeId) {
446 if (mNativeContentsClientBridge == 0) return;
447 nativeNotificationDisplayed(mNativeContentsClientBridge, id, processId, routeId);
450 public void notificationError(int id, String error, int processId, int routeId) {
451 if (mNativeContentsClientBridge == 0) return;
452 nativeNotificationError(mNativeContentsClientBridge, id, error, processId, routeId);
455 public void notificationClicked(int id, int processId, int routeId) {
456 if (mNativeContentsClientBridge == 0) return;
457 nativeNotificationClicked(mNativeContentsClientBridge, id, processId, routeId);
460 public void notificationClosed(int id, boolean byUser, int processId, int routeId) {
461 if (mNativeContentsClientBridge == 0) return;
462 nativeNotificationClosed(mNativeContentsClientBridge, id, byUser, processId, routeId);
465 void setDownloadListener(DownloadListener listener) {
466 mDownloadListener = listener;
469 // Implement ContentViewDownloadDelegate methods.
470 public void requestHttpGetDownload(DownloadInfo downloadInfo) {
471 if (mDownloadListener != null) {
472 mDownloadListener.onDownloadStart(downloadInfo.getUrl(), downloadInfo.getUserAgent(),
473 downloadInfo.getContentDisposition(), downloadInfo.getMimeType(), downloadInfo.getContentLength());
477 public void onDownloadStarted(String filename, String mimeType) {
480 public void onDangerousDownload(String filename, int downloadId) {
483 //--------------------------------------------------------------------------------------------
485 //--------------------------------------------------------------------------------------------
486 private native void nativeProceedSslError(int nativeXWalkContentsClientBridge,
487 boolean proceed, int id);
489 private native void nativeConfirmJsResult(int nativeXWalkContentsClientBridge, int id,
491 private native void nativeCancelJsResult(int nativeXWalkContentsClientBridge, int id);
492 private native void nativeExitFullscreen(int nativeXWalkContentsClientBridge, int nativeWebContents);
493 private native void nativeNotificationDisplayed(int nativeXWalkContentsClientBridge, int id,
494 int processId, int routeId);
495 private native void nativeNotificationError(int nativeXWalkContentsClientBridge, int id,
496 String error, int processId, int routeId);
497 private native void nativeNotificationClicked(int nativeXWalkContentsClientBridge, int id,
498 int processId, int routeId);
499 private native void nativeNotificationClosed(int nativeXWalkContentsClientBridge, int id,
500 boolean byUser, int processId, int routeId);