Upstream version 6.34.113.0
[platform/framework/web/crosswalk.git] / src / xwalk / runtime / android / core / src / org / xwalk / core / XWalkContentsClientBridge.java
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.
5
6 package org.xwalk.core;
7
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;
20
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;
29
30 // Help bridge callback in XWalkContentsClient to XWalkViewClient and
31 // WebChromeClient; Also handle the JNI conmmunication logic.
32 @JNINamespace("xwalk")
33 class XWalkContentsClientBridge extends XWalkContentsClient
34         implements ContentViewDownloadDelegate {
35
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;
45
46     // The native peer of the object
47     private int mNativeContentsClientBridge;
48
49     private class InterceptNavigationDelegateImpl implements InterceptNavigationDelegate {
50         private XWalkContentsClient mContentsClient;
51
52         public InterceptNavigationDelegateImpl(XWalkContentsClient client) {
53             mContentsClient = client;
54         }
55
56         public boolean shouldIgnoreNavigation(NavigationParams navigationParams) {
57             final String url = navigationParams.url;
58             boolean ignoreNavigation = shouldOverrideUrlLoading(url) ||
59                      (mNavigationHandler != null &&
60                       mNavigationHandler.handleNavigation(navigationParams));
61
62             if (!ignoreNavigation) {
63                 // Post a message to UI thread to notify the page is starting to load.
64                 mContentsClient.getCallbackHelper().postOnPageStarted(url);
65             }
66
67             return ignoreNavigation;
68         }
69     }
70
71     public XWalkContentsClientBridge(XWalkView xwView) {
72         mXWalkView = xwView;
73
74         mInterceptNavigationDelegate = new InterceptNavigationDelegateImpl(this);
75     }
76
77     public void setXWalkWebChromeClient(XWalkWebChromeClient client) {
78         mXWalkWebChromeClient = client;
79     }
80
81     public XWalkWebChromeClient getXWalkWebChromeClient() {
82         return mXWalkWebChromeClient;
83     }
84
85     public void setXWalkClient(XWalkClient client) {
86         mXWalkClient = client;
87     }
88
89     public void setNavigationHandler(XWalkNavigationHandler handler) {
90         mNavigationHandler = handler;
91     }
92
93     void registerPageLoadListener(PageLoadListener listener) {
94         mPageLoadListener = listener;
95     }
96
97     public void setNotificationService(XWalkNotificationService service) {
98         if (mNotificationService != null) mNotificationService.shutdown();
99         mNotificationService = service;
100         if (mNotificationService != null) mNotificationService.setBridge(this);
101     }
102
103     public boolean onNewIntent(Intent intent) {
104         return mNotificationService.maybeHandleIntent(intent);
105     }
106
107     public InterceptNavigationDelegate getInterceptNavigationDelegate() {
108         return mInterceptNavigationDelegate;
109     }
110
111     // TODO(Xingnan): All the empty functions need to be implemented.
112     @Override
113     public boolean shouldOverrideUrlLoading(String url) {
114         if (mXWalkClient != null && mXWalkView != null)
115             return mXWalkClient.shouldOverrideUrlLoading(mXWalkView, url);
116         return false;
117     }
118
119     @Override
120     public void onUnhandledKeyEvent(KeyEvent event) {
121     }
122
123     @Override
124     public void getVisitedHistory(ValueCallback<String[]> callback) {
125     }
126
127     @Override
128     public void doUpdateVisitedHistory(String url, boolean isReload) {
129     }
130
131     @Override
132     public void onProgressChanged(int progress) {
133         if (mXWalkWebChromeClient != null && mXWalkView != null)
134             mXWalkWebChromeClient.onProgressChanged(mXWalkView, progress);
135     }
136
137     @Override
138     public WebResourceResponse shouldInterceptRequest(String url) {
139         if (mXWalkClient != null && mXWalkView != null)
140             return mXWalkClient.shouldInterceptRequest(mXWalkView, url);
141         return null;
142     }
143
144     @Override
145     public void onLoadResource(String url) {
146         if (mXWalkClient != null && mXWalkView != null)
147             mXWalkClient.onLoadResource(mXWalkView, url);
148     }
149
150     @Override
151     public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
152         return false;
153     }
154
155     @CalledByNative
156     public void onReceivedHttpAuthRequest(XWalkHttpAuthHandler handler, String host, String realm) {
157         if (mXWalkClient != null && mXWalkView != null)
158             mXWalkClient.onReceivedHttpAuthRequest(mXWalkView, handler, host, realm);
159     }
160
161     @Override
162     public void onReceivedSslError(ValueCallback<Boolean> callback, SslError error) {
163         if (mXWalkClient != null && mXWalkView != null) {
164             mXWalkClient.onReceivedSslError(mXWalkView, callback, error);
165         }
166     }
167
168     @Override
169     public void onReceivedLoginRequest(String realm, String account, String args) {
170     }
171
172     @Override
173     public void onGeolocationPermissionsShowPrompt(String origin,
174             XWalkGeolocationPermissions.Callback callback) {
175         if (mXWalkWebChromeClient != null) {
176             mXWalkWebChromeClient.onGeolocationPermissionsShowPrompt(origin, callback);
177         }
178     }
179
180     @Override
181     public void onGeolocationPermissionsHidePrompt() {
182         if (mXWalkWebChromeClient != null) {
183             mXWalkWebChromeClient.onGeolocationPermissionsHidePrompt();
184         }
185     }
186
187     @Override
188     public void handleJsAlert(String url, String message, JsResult result) {
189         if (mXWalkWebChromeClient != null && mXWalkView != null) {
190             mXWalkWebChromeClient.onJsAlert(mXWalkView, url, message, result);
191         }
192     }
193
194     @Override
195     public void handleJsBeforeUnload(String url, String message, JsResult result) {
196         if (mXWalkWebChromeClient != null && mXWalkView != null) {
197             mXWalkWebChromeClient.onJsBeforeUnload(mXWalkView, url, message, result);
198         }
199     }
200
201     @Override
202     public void handleJsConfirm(String url, String message, JsResult result) {
203         if (mXWalkWebChromeClient != null && mXWalkView != null) {
204             mXWalkWebChromeClient.onJsConfirm(mXWalkView, url, message, result);
205         }
206     }
207
208     @Override
209     public void handleJsPrompt(
210             String url, String message, String defaultValue, JsPromptResult result) {
211         if (mXWalkWebChromeClient != null && mXWalkView != null) {
212             mXWalkWebChromeClient.onJsPrompt(mXWalkView, url, message, defaultValue, result);
213         }
214     }
215
216     @Override
217     public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
218             boolean isDoneCounting) {
219     }
220
221     @Override
222     public void onNewPicture(Picture picture) {
223     }
224
225     @Override
226     public void onPageStarted(String url) {
227         if (mXWalkClient != null && mXWalkView != null) {
228             mXWalkClient.onPageStarted(mXWalkView, url, mFavicon);
229         }
230     }
231
232     @Override
233     public void onPageFinished(String url) {
234         if (mPageLoadListener != null) mPageLoadListener.onPageFinished(url);
235         if (mXWalkClient != null && mXWalkView != null) {
236             mXWalkClient.onPageFinished(mXWalkView, url);
237         }
238     }
239
240     @Override
241     public void onReceivedError(int errorCode, String description, String failingUrl) {
242         if (mXWalkClient != null && mXWalkView != null) {
243             mXWalkClient.onReceivedError(mXWalkView, errorCode, description, failingUrl);
244         }
245     }
246
247     @Override
248     public void onRendererUnresponsive() {
249         if (mXWalkClient != null && mXWalkView != null) {
250             mXWalkClient.onRendererUnresponsive(mXWalkView);
251         }
252     }
253
254     @Override
255     public void onRendererResponsive() {
256         if (mXWalkClient != null && mXWalkView != null) {
257             mXWalkClient.onRendererResponsive(mXWalkView);
258         }
259     }
260
261     @Override
262     public void onFormResubmission(Message dontResend, Message resend) {
263         dontResend.sendToTarget();
264     }
265
266     @Override
267     public void onDownloadStart(String url,
268                                 String userAgent,
269                                 String contentDisposition,
270                                 String mimeType,
271                                 long contentLength) {
272     }
273
274     @Override
275     public boolean onCreateWindow(boolean isDialog, boolean isUserGesture) {
276         return false;
277     }
278
279     @Override
280     public void onCloseWindow() {
281         if (mXWalkClient != null) {
282             mXWalkClient.onCloseWindow(mXWalkView);
283         }
284     }
285
286     @Override
287     public void onRequestFocus() {
288     }
289
290     @Override
291     public void onReceivedTouchIconUrl(String url, boolean precomposed) {
292         if (mXWalkWebChromeClient != null && mXWalkView != null) {
293             mXWalkWebChromeClient.onReceivedTouchIconUrl(mXWalkView, url, precomposed);
294         }
295     }
296
297     @Override
298     public void onReceivedIcon(Bitmap bitmap) {
299         if (mXWalkWebChromeClient != null && mXWalkView != null) {
300             mXWalkWebChromeClient.onReceivedIcon(mXWalkView, bitmap);
301         }
302         mFavicon = bitmap;
303     }
304
305     @Override
306     public void onShowCustomView(View view, XWalkWebChromeClient.CustomViewCallback callback) {
307         if (mXWalkWebChromeClient != null) {
308             mXWalkWebChromeClient.onShowCustomView(view, callback);
309         }
310     }
311
312     @Override
313     public void onHideCustomView() {
314         if (mXWalkWebChromeClient != null) {
315             mXWalkWebChromeClient.onHideCustomView();
316         }
317     }
318
319     @Override
320     public void onScaleChangedScaled(float oldScale, float newScale) {
321     }
322
323     @Override
324     protected View getVideoLoadingProgressView() {
325         if (mXWalkWebChromeClient != null)
326             return mXWalkWebChromeClient.getVideoLoadingProgressView();
327         return null;
328     }
329
330     @Override
331     public Bitmap getDefaultVideoPoster() {
332         return null;
333     }
334
335     @Override
336     public void didFinishLoad(String url) {
337     }
338
339     @Override
340     public void onTitleChanged(String title) {
341         if (mXWalkWebChromeClient != null && mXWalkView != null) {
342             mXWalkWebChromeClient.onReceivedTitle(mXWalkView, title);
343         }
344     }
345
346     @Override
347     public void onToggleFullscreen(boolean enterFullscreen) {
348         if (mXWalkWebChromeClient != null) {
349             mXWalkWebChromeClient.onToggleFullscreen(enterFullscreen);
350         }
351     }
352
353     @Override
354     public boolean isFullscreen() {
355         if (mXWalkWebChromeClient != null) return mXWalkWebChromeClient.isFullscreen();
356
357         return false;
358     }
359
360     @Override
361     public ContentVideoViewClient getContentVideoViewClient() {
362         return new XWalkContentVideoViewClient(this, mXWalkView.getActivity());
363     }
364
365     // Used by the native peer to set/reset a weak ref to the native peer.
366     @CalledByNative
367     private void setNativeContentsClientBridge(int nativeContentsClientBridge) {
368         mNativeContentsClientBridge = nativeContentsClientBridge;
369     }
370
371     // If returns false, the request is immediately canceled, and any call to proceedSslError
372     // has no effect. If returns true, the request should be canceled or proceeded using
373     // proceedSslError().
374     // Unlike the webview classic, we do not keep keep a database of certificates that
375     // are allowed by the user, because this functionality is already handled via
376     // ssl_policy in native layers.
377     @CalledByNative
378     private boolean allowCertificateError(int certError, byte[] derBytes, final String url,
379             final int id) {
380         final SslCertificate cert = SslUtil.getCertificateFromDerBytes(derBytes);
381         if (cert == null) {
382             // if the certificate or the client is null, cancel the request
383             return false;
384         }
385         final SslError sslError = SslUtil.sslErrorFromNetErrorCode(certError, cert, url);
386         ValueCallback<Boolean> callback = new ValueCallback<Boolean>() {
387             @Override
388             public void onReceiveValue(Boolean value) {
389                 proceedSslError(value.booleanValue(), id);
390             }
391         };
392         onReceivedSslError(callback, sslError);
393         return true;
394     }
395
396     private void proceedSslError(boolean proceed, int id) {
397         if (mNativeContentsClientBridge == 0) return;
398         nativeProceedSslError(mNativeContentsClientBridge, proceed, id);
399     }
400
401     @CalledByNative
402     private void handleJsAlert(String url, String message, int id) {
403         JsResultHandler handler = new JsResultHandler(this, id);
404         handleJsAlert(url, message, handler);
405     }
406
407     @CalledByNative
408     private void handleJsConfirm(String url, String message, int id) {
409         JsResultHandler handler = new JsResultHandler(this, id);
410         handleJsConfirm(url, message, handler);
411     }
412
413     @CalledByNative
414     private void handleJsPrompt(String url, String message, String defaultValue, int id) {
415         JsResultHandler handler = new JsResultHandler(this, id);
416         handleJsPrompt(url, message, defaultValue, handler);
417     }
418
419     @CalledByNative
420     private void handleJsBeforeUnload(String url, String message, int id) {
421         JsResultHandler handler = new JsResultHandler(this, id);
422         handleJsBeforeUnload(url, message, handler);
423     }
424
425     @CalledByNative
426     private void updateNotificationIcon(int notificationId, Bitmap icon) {
427         mNotificationService.updateNotificationIcon(notificationId, icon);
428     }
429
430     @CalledByNative
431     private void showNotification(String title, String message, String replaceId,
432             int notificationId, int processId, int routeId) {
433         // FIXME(wang16): use replaceId to replace exist notification. It happens when
434         //                a notification with same name and tag fires.
435         mNotificationService.showNotification(
436                 title, message, notificationId, processId, routeId);
437     }
438
439     @CalledByNative
440     private void cancelNotification(int notificationId, int processId, int routeId) {
441         mNotificationService.cancelNotification(notificationId, processId, routeId);
442     }
443
444     void confirmJsResult(int id, String prompt) {
445         if (mNativeContentsClientBridge == 0) return;
446         nativeConfirmJsResult(mNativeContentsClientBridge, id, prompt);
447     }
448
449     void cancelJsResult(int id) {
450         if (mNativeContentsClientBridge == 0) return;
451         nativeCancelJsResult(mNativeContentsClientBridge, id);
452     }
453
454     void exitFullscreen(int nativeWebContents) {
455         if (mNativeContentsClientBridge == 0) return;
456         nativeExitFullscreen(mNativeContentsClientBridge, nativeWebContents);
457     }
458
459     public void notificationDisplayed(int id, int processId, int routeId) {
460         if (mNativeContentsClientBridge == 0) return;
461         nativeNotificationDisplayed(mNativeContentsClientBridge, id, processId, routeId);
462     }
463
464     public void notificationError(int id, String error, int processId, int routeId) {
465         if (mNativeContentsClientBridge == 0) return;
466         nativeNotificationError(mNativeContentsClientBridge, id, error, processId, routeId);
467     }
468
469     public void notificationClicked(int id, int processId, int routeId) {
470         if (mNativeContentsClientBridge == 0) return;
471         nativeNotificationClicked(mNativeContentsClientBridge, id, processId, routeId);
472     }
473
474     public void notificationClosed(int id, boolean byUser, int processId, int routeId) {
475         if (mNativeContentsClientBridge == 0) return;
476         nativeNotificationClosed(mNativeContentsClientBridge, id, byUser, processId, routeId);
477     }
478
479     void setDownloadListener(DownloadListener listener) {
480         mDownloadListener = listener;
481     }
482
483     // Implement ContentViewDownloadDelegate methods.
484     public void requestHttpGetDownload(DownloadInfo downloadInfo) {
485         if (mDownloadListener != null) {
486             mDownloadListener.onDownloadStart(downloadInfo.getUrl(), downloadInfo.getUserAgent(),
487             downloadInfo.getContentDisposition(), downloadInfo.getMimeType(), downloadInfo.getContentLength());
488         }
489     }
490
491     public void onDownloadStarted(String filename, String mimeType) {
492     }
493
494     public void onDangerousDownload(String filename, int downloadId) {
495     }
496
497     //--------------------------------------------------------------------------------------------
498     //  Native methods
499     //--------------------------------------------------------------------------------------------
500     private native void nativeProceedSslError(int nativeXWalkContentsClientBridge,
501             boolean proceed, int id);
502
503     private native void nativeConfirmJsResult(int nativeXWalkContentsClientBridge, int id,
504             String prompt);
505     private native void nativeCancelJsResult(int nativeXWalkContentsClientBridge, int id);
506     private native void nativeExitFullscreen(int nativeXWalkContentsClientBridge, int nativeWebContents);
507     private native void nativeNotificationDisplayed(int nativeXWalkContentsClientBridge, int id,
508             int processId, int routeId);
509     private native void nativeNotificationError(int nativeXWalkContentsClientBridge, int id,
510             String error, int processId, int routeId);
511     private native void nativeNotificationClicked(int nativeXWalkContentsClientBridge, int id,
512             int processId, int routeId);
513     private native void nativeNotificationClosed(int nativeXWalkContentsClientBridge, int id,
514             boolean byUser, int processId, int routeId);
515 }