- add sources.
[platform/framework/web/crosswalk.git] / src / android_webview / java / src / org / chromium / android_webview / AwContentsClient.java
1 // Copyright (c) 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.Context;
8 import android.content.pm.ActivityInfo;
9 import android.graphics.Bitmap;
10 import android.graphics.Picture;
11 import android.graphics.Rect;
12 import android.graphics.RectF;
13 import android.net.http.SslError;
14 import android.os.Handler;
15 import android.os.Looper;
16 import android.os.Message;
17 import android.util.Log;
18 import android.view.KeyEvent;
19 import android.view.View;
20 import android.webkit.ConsoleMessage;
21 import android.webkit.GeolocationPermissions;
22 import android.webkit.SslErrorHandler;
23 import android.webkit.ValueCallback;
24 import android.webkit.WebChromeClient;
25
26 import org.chromium.content.browser.ContentVideoView;
27 import org.chromium.content.browser.ContentVideoViewClient;
28 import org.chromium.content.browser.ContentVideoViewControls;
29 import org.chromium.content.browser.ContentViewClient;
30 import org.chromium.content.browser.ContentViewCore;
31 import org.chromium.content.browser.WebContentsObserverAndroid;
32 import org.chromium.net.NetError;
33
34 /**
35  * Base-class that an AwContents embedder derives from to receive callbacks.
36  * This extends ContentViewClient, as in many cases we want to pass-thru ContentViewCore
37  * callbacks right to our embedder, and this setup facilities that.
38  * For any other callbacks we need to make transformations of (e.g. adapt parameters
39  * or perform filtering) we can provide final overrides for methods here, and then introduce
40  * new abstract methods that the our own client must implement.
41  * i.e.: all methods in this class should either be final, or abstract.
42  */
43 public abstract class AwContentsClient {
44
45     private static final String TAG = "AwContentsClient";
46     private final AwContentsClientCallbackHelper mCallbackHelper;
47
48     private AwWebContentsObserver mWebContentsObserver;
49
50     private AwContentViewClient mContentViewClient = new AwContentViewClient();
51
52     // Last background color reported from the renderer. Holds the sentinal value INVALID_COLOR
53     // if not valid.
54     private int mCachedRendererBackgroundColor = INVALID_COLOR;
55
56     private static final int INVALID_COLOR = 0;
57
58     public AwContentsClient() {
59         this(Looper.myLooper());
60     }
61
62     // Alllow injection of the callback thread, for testing.
63     public AwContentsClient(Looper looper) {
64         mCallbackHelper = new AwContentsClientCallbackHelper(looper, this);
65     }
66
67     class AwWebContentsObserver extends WebContentsObserverAndroid {
68         public AwWebContentsObserver(ContentViewCore contentViewCore) {
69             super(contentViewCore);
70         }
71
72         @Override
73         public void didStopLoading(String url) {
74             AwContentsClient.this.onPageFinished(url);
75         }
76
77         @Override
78         public void didFailLoad(boolean isProvisionalLoad,
79                 boolean isMainFrame, int errorCode, String description, String failingUrl) {
80             if (errorCode == NetError.ERR_ABORTED) {
81                 // This error code is generated for the following reasons:
82                 // - WebView.stopLoading is called,
83                 // - the navigation is intercepted by the embedder via shouldOverrideNavigation.
84                 //
85                 // The Android WebView does not notify the embedder of these situations using this
86                 // error code with the WebViewClient.onReceivedError callback.
87                 return;
88             }
89             if (!isMainFrame) {
90                 // The Android WebView does not notify the embedder of sub-frame failures.
91                 return;
92             }
93             AwContentsClient.this.onReceivedError(
94                     ErrorCodeConversionHelper.convertErrorCode(errorCode), description, failingUrl);
95         }
96
97         @Override
98         public void didNavigateAnyFrame(String url, String baseUrl, boolean isReload) {
99             AwContentsClient.this.doUpdateVisitedHistory(url, isReload);
100         }
101
102     }
103
104     private class AwContentViewClient extends ContentViewClient {
105         @Override
106         public void onBackgroundColorChanged(int color) {
107             // Avoid storing the sentinal INVALID_COLOR (note that both 0 and 1 are both
108             // fully transparent so this transpose makes no visible difference).
109             mCachedRendererBackgroundColor = color == INVALID_COLOR ? 1 : color;
110         }
111
112         @Override
113         public void onStartContentIntent(Context context, String contentUrl) {
114             //  Callback when detecting a click on a content link.
115             AwContentsClient.this.shouldOverrideUrlLoading(contentUrl);
116         }
117
118         @Override
119         public void onRendererCrash(boolean crashedWhileOomProtected) {
120             // This is not possible so long as the webview is run single process!
121             throw new RuntimeException("Renderer crash reported.");
122         }
123
124         @Override
125         public void onUpdateTitle(String title) {
126             AwContentsClient.this.onReceivedTitle(title);
127         }
128
129         @Override
130         public boolean shouldOverrideKeyEvent(KeyEvent event) {
131             return AwContentsClient.this.shouldOverrideKeyEvent(event);
132         }
133
134         @Override
135         final public ContentVideoViewClient getContentVideoViewClient() {
136             return new AwContentVideoViewClient();
137         }
138     }
139
140     final void installWebContentsObserver(ContentViewCore contentViewCore) {
141         if (mWebContentsObserver != null) {
142             mWebContentsObserver.detachFromWebContents();
143         }
144         mWebContentsObserver = new AwWebContentsObserver(contentViewCore);
145     }
146
147     private class AwContentVideoViewClient implements ContentVideoViewClient {
148         @Override
149         public void onShowCustomView(View view) {
150             WebChromeClient.CustomViewCallback cb = new WebChromeClient.CustomViewCallback() {
151                 @Override
152                 public void onCustomViewHidden() {
153                     ContentVideoView contentVideoView = ContentVideoView.getContentVideoView();
154                     if (contentVideoView != null)
155                         contentVideoView.exitFullscreen(false);
156                 }
157             };
158             AwContentsClient.this.onShowCustomView(view, cb);
159         }
160
161         @Override
162         public void onDestroyContentVideoView() {
163             AwContentsClient.this.onHideCustomView();
164         }
165
166         @Override
167         public View getVideoLoadingProgressView() {
168             return AwContentsClient.this.getVideoLoadingProgressView();
169         }
170
171         @Override
172         public ContentVideoViewControls createControls() {
173             return null;
174         }
175     }
176
177     final AwContentsClientCallbackHelper getCallbackHelper() {
178         return mCallbackHelper;
179     }
180
181     final ContentViewClient getContentViewClient() {
182         return mContentViewClient;
183     }
184
185     final int getCachedRendererBackgroundColor() {
186         assert isCachedRendererBackgroundColorValid();
187         return mCachedRendererBackgroundColor;
188     }
189
190     final boolean isCachedRendererBackgroundColorValid() {
191         return mCachedRendererBackgroundColor != INVALID_COLOR;
192     }
193
194     //--------------------------------------------------------------------------------------------
195     //             WebView specific methods that map directly to WebViewClient / WebChromeClient
196     //--------------------------------------------------------------------------------------------
197
198     public static class FileChooserParams {
199         public int mode;
200         public String acceptTypes;
201         public String title;
202         public String defaultFilename;
203         public boolean capture;
204     }
205
206     public abstract void getVisitedHistory(ValueCallback<String[]> callback);
207
208     public abstract void doUpdateVisitedHistory(String url, boolean isReload);
209
210     public abstract void onProgressChanged(int progress);
211
212     public abstract InterceptedRequestData shouldInterceptRequest(String url);
213
214     public abstract boolean shouldOverrideKeyEvent(KeyEvent event);
215
216     public abstract boolean shouldOverrideUrlLoading(String url);
217
218     public abstract void onLoadResource(String url);
219
220     public abstract void onUnhandledKeyEvent(KeyEvent event);
221
222     public abstract boolean onConsoleMessage(ConsoleMessage consoleMessage);
223
224     public abstract void onReceivedHttpAuthRequest(AwHttpAuthHandler handler,
225             String host, String realm);
226
227     public abstract void onReceivedSslError(ValueCallback<Boolean> callback, SslError error);
228
229     public abstract void onReceivedLoginRequest(String realm, String account, String args);
230
231     public abstract void onFormResubmission(Message dontResend, Message resend);
232
233     public abstract void onDownloadStart(String url, String userAgent, String contentDisposition,
234             String mimeType, long contentLength);
235
236     // TODO(joth): Make abstract once this has rolled in downstream.
237     public /*abstract*/ void showFileChooser(ValueCallback<String[]> uploadFilePathsCallback,
238             FileChooserParams fileChooserParams) { }
239
240     public abstract void onGeolocationPermissionsShowPrompt(String origin,
241             GeolocationPermissions.Callback callback);
242
243     public abstract void onGeolocationPermissionsHidePrompt();
244
245     public abstract void onScaleChangedScaled(float oldScale, float newScale);
246
247     protected abstract void handleJsAlert(String url, String message, JsResultReceiver receiver);
248
249     protected abstract void handleJsBeforeUnload(String url, String message,
250             JsResultReceiver receiver);
251
252     protected abstract void handleJsConfirm(String url, String message, JsResultReceiver receiver);
253
254     protected abstract void handleJsPrompt(String url, String message, String defaultValue,
255             JsPromptResultReceiver receiver);
256
257     protected abstract boolean onCreateWindow(boolean isDialog, boolean isUserGesture);
258
259     protected abstract void onCloseWindow();
260
261     public abstract void onReceivedTouchIconUrl(String url, boolean precomposed);
262
263     public abstract void onReceivedIcon(Bitmap bitmap);
264
265     public abstract void onReceivedTitle(String title);
266
267     protected abstract void onRequestFocus();
268
269     protected abstract View getVideoLoadingProgressView();
270
271     public abstract void onPageStarted(String url);
272
273     public abstract void onPageFinished(String url);
274
275     public abstract void onReceivedError(int errorCode, String description, String failingUrl);
276
277     // TODO (michaelbai): Remove this method once the same method remove from
278     // WebViewContentsClientAdapter.
279     public void onShowCustomView(View view,
280            int requestedOrientation, WebChromeClient.CustomViewCallback callback) {
281     }
282
283     // TODO (michaelbai): This method should be abstract, having empty body here
284     // makes the merge to the Android easy.
285     public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
286         onShowCustomView(view, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, callback);
287     }
288
289     public abstract void onHideCustomView();
290
291     public abstract Bitmap getDefaultVideoPoster();
292
293     //--------------------------------------------------------------------------------------------
294     //                              Other WebView-specific methods
295     //--------------------------------------------------------------------------------------------
296     //
297     public abstract void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
298             boolean isDoneCounting);
299
300     /**
301      * Called whenever there is a new content picture available.
302      * @param picture New picture.
303      */
304     public abstract void onNewPicture(Picture picture);
305
306 }