Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / content / public / android / java / src / org / chromium / content / browser / ContentView.java
1 // Copyright 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.content.browser;
6
7 import android.content.Context;
8 import android.content.res.Configuration;
9 import android.graphics.Bitmap;
10 import android.graphics.Canvas;
11 import android.graphics.Rect;
12 import android.os.Build;
13 import android.util.AttributeSet;
14 import android.view.KeyEvent;
15 import android.view.MotionEvent;
16 import android.view.View;
17 import android.view.accessibility.AccessibilityEvent;
18 import android.view.accessibility.AccessibilityNodeInfo;
19 import android.view.inputmethod.EditorInfo;
20 import android.view.inputmethod.InputConnection;
21 import android.widget.FrameLayout;
22
23 import com.google.common.annotations.VisibleForTesting;
24
25 import org.chromium.base.TraceEvent;
26 import org.chromium.ui.base.WindowAndroid;
27
28 /**
29  * The containing view for {@link ContentViewCore} that exists in the Android UI hierarchy and
30  * exposes the various {@link View} functionality to it.
31  *
32  * TODO(joth): Remove any methods overrides from this class that were added for WebView
33  *             compatibility.
34  */
35 public class ContentView extends FrameLayout
36         implements ContentViewCore.InternalAccessDelegate, PageInfo {
37
38     private final ContentViewCore mContentViewCore;
39
40     private float mCurrentTouchOffsetX;
41     private float mCurrentTouchOffsetY;
42     private final int[] mLocationInWindow = new int[2];
43
44     /**
45      * Creates an instance of a ContentView.
46      * @param context The Context the view is running in, through which it can
47      *                access the current theme, resources, etc.
48      * @param nativeWebContents A pointer to the native web contents.
49      * @param windowAndroid An instance of the WindowAndroid.
50      * @return A ContentView instance.
51      */
52     public static ContentView newInstance(Context context, long nativeWebContents,
53             WindowAndroid windowAndroid) {
54         return newInstance(context, nativeWebContents, windowAndroid, null,
55                 android.R.attr.webViewStyle);
56     }
57
58     /**
59      * Creates an instance of a ContentView.
60      * @param context The Context the view is running in, through which it can
61      *                access the current theme, resources, etc.
62      * @param nativeWebContents A pointer to the native web contents.
63      * @param windowAndroid An instance of the WindowAndroid.
64      * @param attrs The attributes of the XML tag that is inflating the view.
65      * @return A ContentView instance.
66      */
67     public static ContentView newInstance(Context context, long nativeWebContents,
68             WindowAndroid windowAndroid, AttributeSet attrs) {
69         // TODO(klobag): use the WebViewStyle as the default style for now. It enables scrollbar.
70         // When ContentView is moved to framework, we can define its own style in the res.
71         return newInstance(context, nativeWebContents, windowAndroid, attrs,
72                 android.R.attr.webViewStyle);
73     }
74
75     /**
76      * Creates an instance of a ContentView.
77      * @param context The Context the view is running in, through which it can
78      *                access the current theme, resources, etc.
79      * @param nativeWebContents A pointer to the native web contents.
80      * @param windowAndroid An instance of the WindowAndroid.
81      * @param attrs The attributes of the XML tag that is inflating the view.
82      * @param defStyle The default style to apply to this view.
83      * @return A ContentView instance.
84      */
85     public static ContentView newInstance(Context context, long nativeWebContents,
86             WindowAndroid windowAndroid, AttributeSet attrs, int defStyle) {
87         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
88             return new ContentView(context, nativeWebContents, windowAndroid, attrs, defStyle);
89         } else {
90             return new JellyBeanContentView(context, nativeWebContents, windowAndroid, attrs,
91                     defStyle);
92         }
93     }
94
95     protected ContentView(Context context, long nativeWebContents, WindowAndroid windowAndroid,
96             AttributeSet attrs, int defStyle) {
97         super(context, attrs, defStyle);
98
99         if (getScrollBarStyle() == View.SCROLLBARS_INSIDE_OVERLAY) {
100             setHorizontalScrollBarEnabled(false);
101             setVerticalScrollBarEnabled(false);
102         }
103
104         setFocusable(true);
105         setFocusableInTouchMode(true);
106
107         mContentViewCore = new ContentViewCore(context);
108         mContentViewCore.initialize(this, this, nativeWebContents, windowAndroid);
109     }
110
111     /**
112      * @return The URL of the page.
113      */
114     public String getUrl() {
115         return mContentViewCore.getUrl();
116     }
117
118     // PageInfo implementation.
119
120     @Override
121     public String getTitle() {
122         return mContentViewCore.getTitle();
123     }
124
125     @Override
126     public boolean isReadyForSnapshot() {
127         return mContentViewCore.isReady();
128     }
129
130     @Override
131     public Bitmap getBitmap() {
132         return getBitmap(getWidth(), getHeight());
133     }
134
135     @Override
136     public Bitmap getBitmap(int width, int height) {
137         return mContentViewCore.getBitmap(width, height);
138     }
139
140     @Override
141     public int getBackgroundColor() {
142         return mContentViewCore.getBackgroundColor();
143     }
144
145     @Override
146     public View getView() {
147         return this;
148     }
149
150     /**
151      * @return The core component of the ContentView that handles JNI communication.  Should only be
152      *         used for passing to native.
153      */
154     public ContentViewCore getContentViewCore() {
155         return mContentViewCore;
156     }
157
158     /**
159      * @return The cache of scales and positions used to convert coordinates from/to CSS.
160      */
161     public RenderCoordinates getRenderCoordinates() {
162         return mContentViewCore.getRenderCoordinates();
163     }
164
165     /**
166      * Destroy the internal state of the WebView. This method may only be called
167      * after the WebView has been removed from the view system. No other methods
168      * may be called on this WebView after this method has been called.
169      */
170     public void destroy() {
171         mContentViewCore.destroy();
172     }
173
174     /**
175      * Returns true initially, false after destroy() has been called.
176      * It is illegal to call any other public method after destroy().
177      */
178     public boolean isAlive() {
179         return mContentViewCore.isAlive();
180     }
181
182     public void setContentViewClient(ContentViewClient client) {
183         mContentViewCore.setContentViewClient(client);
184     }
185
186     @VisibleForTesting
187     public ContentViewClient getContentViewClient() {
188         return mContentViewCore.getContentViewClient();
189     }
190
191     /**
192      * Load url without fixing up the url string. Consumers of ContentView are responsible for
193      * ensuring the URL passed in is properly formatted (i.e. the scheme has been added if left
194      * off during user input).
195      *
196      * @param params Parameters for this load.
197      */
198     public void loadUrl(LoadUrlParams params) {
199         mContentViewCore.loadUrl(params);
200     }
201
202     /**
203      * @return Whether the current WebContents has a previous navigation entry.
204      */
205     public boolean canGoBack() {
206         return mContentViewCore.canGoBack();
207     }
208
209     /**
210      * @return Whether the current WebContents has a navigation entry after the current one.
211      */
212     public boolean canGoForward() {
213         return mContentViewCore.canGoForward();
214     }
215
216     /**
217      * Goes to the navigation entry before the current one.
218      */
219     public void goBack() {
220         mContentViewCore.goBack();
221     }
222
223     /**
224      * Goes to the navigation entry following the current one.
225      */
226     public void goForward() {
227         mContentViewCore.goForward();
228     }
229
230     /**
231      * Fling the ContentView from the current position.
232      * @param x Fling touch starting position
233      * @param y Fling touch starting position
234      * @param velocityX Initial velocity of the fling (X) measured in pixels per second.
235      * @param velocityY Initial velocity of the fling (Y) measured in pixels per second.
236      */
237     @VisibleForTesting
238     public void fling(long timeMs, int x, int y, int velocityX, int velocityY) {
239         mContentViewCore.flingForTest(timeMs, x, y, velocityX, velocityY);
240     }
241
242     /**
243      * Injects the passed JavaScript code in the current page and evaluates it.
244      *
245      * @throws IllegalStateException If the ContentView has been destroyed.
246      */
247     public void evaluateJavaScript(String script) throws IllegalStateException {
248         mContentViewCore.evaluateJavaScript(script, null);
249     }
250
251     /**
252      * To be called when the ContentView is shown.
253      **/
254     public void onShow() {
255         mContentViewCore.onShow();
256     }
257
258     /**
259      * To be called when the ContentView is hidden.
260      **/
261     public void onHide() {
262         mContentViewCore.onHide();
263     }
264
265     /**
266      * Hides the select action bar.
267      */
268     public void hideSelectActionBar() {
269         mContentViewCore.hideSelectActionBar();
270     }
271
272     // FrameLayout overrides.
273
274     // Needed by ContentViewCore.InternalAccessDelegate
275     @Override
276     public boolean drawChild(Canvas canvas, View child, long drawingTime) {
277         return super.drawChild(canvas, child, drawingTime);
278     }
279
280     // Needed by ContentViewCore.InternalAccessDelegate
281     @Override
282     public void onScrollChanged(int l, int t, int oldl, int oldt) {
283         super.onScrollChanged(l, t, oldl, oldt);
284     }
285
286     @Override
287     protected void onSizeChanged(int w, int h, int ow, int oh) {
288         TraceEvent.begin();
289         super.onSizeChanged(w, h, ow, oh);
290         mContentViewCore.onSizeChanged(w, h, ow, oh);
291         TraceEvent.end();
292     }
293
294     @Override
295     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
296         super.onLayout(changed, left, top, right, bottom);
297         if (changed) {
298             getLocationInWindow(mLocationInWindow);
299             mContentViewCore.onLocationInWindowChanged(mLocationInWindow[0], mLocationInWindow[1]);
300         }
301     }
302
303     @Override
304     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
305         return mContentViewCore.onCreateInputConnection(outAttrs);
306     }
307
308     @Override
309     public boolean onCheckIsTextEditor() {
310         return mContentViewCore.onCheckIsTextEditor();
311     }
312
313     @Override
314     protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
315         TraceEvent.begin();
316         super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
317         mContentViewCore.onFocusChanged(gainFocus);
318         TraceEvent.end();
319     }
320
321     @Override
322     public void onWindowFocusChanged(boolean hasWindowFocus) {
323         super.onWindowFocusChanged(hasWindowFocus);
324         mContentViewCore.onWindowFocusChanged(hasWindowFocus);
325     }
326
327     @Override
328     public boolean onKeyUp(int keyCode, KeyEvent event) {
329         return mContentViewCore.onKeyUp(keyCode, event);
330     }
331
332     @Override
333     public boolean dispatchKeyEventPreIme(KeyEvent event) {
334         return mContentViewCore.dispatchKeyEventPreIme(event);
335     }
336
337     @Override
338     public boolean dispatchKeyEvent(KeyEvent event) {
339         if (isFocused()) {
340             return mContentViewCore.dispatchKeyEvent(event);
341         } else {
342             return super.dispatchKeyEvent(event);
343         }
344     }
345
346     @Override
347     public boolean onTouchEvent(MotionEvent event) {
348         MotionEvent offset = createOffsetMotionEvent(event);
349         boolean consumed = mContentViewCore.onTouchEvent(offset);
350         offset.recycle();
351         return consumed;
352     }
353
354     /**
355      * Mouse move events are sent on hover enter, hover move and hover exit.
356      * They are sent on hover exit because sometimes it acts as both a hover
357      * move and hover exit.
358      */
359     @Override
360     public boolean onHoverEvent(MotionEvent event) {
361         MotionEvent offset = createOffsetMotionEvent(event);
362         boolean consumed = mContentViewCore.onHoverEvent(offset);
363         offset.recycle();
364         super.onHoverEvent(event);
365         return consumed;
366     }
367
368     @Override
369     public boolean onGenericMotionEvent(MotionEvent event) {
370         return mContentViewCore.onGenericMotionEvent(event);
371     }
372
373     @Override
374     public boolean performLongClick() {
375         return false;
376     }
377
378     /**
379      * Sets the current amount to offset incoming touch events by.  This is used to handle content
380      * moving and not lining up properly with the android input system.
381      * @param dx The X offset in pixels to shift touch events.
382      * @param dy The Y offset in pixels to shift touch events.
383      */
384     public void setCurrentMotionEventOffsets(float dx, float dy) {
385         mCurrentTouchOffsetX = dx;
386         mCurrentTouchOffsetY = dy;
387     }
388
389     private MotionEvent createOffsetMotionEvent(MotionEvent src) {
390         MotionEvent dst = MotionEvent.obtain(src);
391         dst.offsetLocation(mCurrentTouchOffsetX, mCurrentTouchOffsetY);
392         return dst;
393     }
394
395     @Override
396     protected void onConfigurationChanged(Configuration newConfig) {
397         mContentViewCore.onConfigurationChanged(newConfig);
398     }
399
400     /**
401      * Currently the ContentView scrolling happens in the native side. In
402      * the Java view system, it is always pinned at (0, 0). scrollBy() and scrollTo()
403      * are overridden, so that View's mScrollX and mScrollY will be unchanged at
404      * (0, 0). This is critical for drawing ContentView correctly.
405      */
406     @Override
407     public void scrollBy(int x, int y) {
408         mContentViewCore.scrollBy(x, y);
409     }
410
411     @Override
412     public void scrollTo(int x, int y) {
413         mContentViewCore.scrollTo(x, y);
414     }
415
416     @Override
417     protected int computeHorizontalScrollExtent() {
418         // TODO(dtrainor): Need to expose scroll events properly to public. Either make getScroll*
419         // work or expose computeHorizontalScrollOffset()/computeVerticalScrollOffset as public.
420         return mContentViewCore.computeHorizontalScrollExtent();
421     }
422
423     @Override
424     protected int computeHorizontalScrollOffset() {
425         return mContentViewCore.computeHorizontalScrollOffset();
426     }
427
428     @Override
429     protected int computeHorizontalScrollRange() {
430         return mContentViewCore.computeHorizontalScrollRange();
431     }
432
433     @Override
434     protected int computeVerticalScrollExtent() {
435         return mContentViewCore.computeVerticalScrollExtent();
436     }
437
438     @Override
439     protected int computeVerticalScrollOffset() {
440         return mContentViewCore.computeVerticalScrollOffset();
441     }
442
443     @Override
444     protected int computeVerticalScrollRange() {
445         return mContentViewCore.computeVerticalScrollRange();
446     }
447
448     // End FrameLayout overrides.
449
450     @Override
451     public boolean awakenScrollBars(int startDelay, boolean invalidate) {
452         return mContentViewCore.awakenScrollBars(startDelay, invalidate);
453     }
454
455     @Override
456     public boolean awakenScrollBars() {
457         return super.awakenScrollBars();
458     }
459
460     public int getSingleTapX()  {
461         return mContentViewCore.getSingleTapX();
462     }
463
464     public int getSingleTapY()  {
465         return mContentViewCore.getSingleTapY();
466     }
467
468     @Override
469     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
470         super.onInitializeAccessibilityNodeInfo(info);
471         mContentViewCore.onInitializeAccessibilityNodeInfo(info);
472     }
473
474     /**
475      * Fills in scrolling values for AccessibilityEvents.
476      * @param event Event being fired.
477      */
478     @Override
479     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
480         super.onInitializeAccessibilityEvent(event);
481         mContentViewCore.onInitializeAccessibilityEvent(event);
482     }
483
484     @Override
485     protected void onAttachedToWindow() {
486         super.onAttachedToWindow();
487         mContentViewCore.onAttachedToWindow();
488     }
489
490     @Override
491     protected void onDetachedFromWindow() {
492         super.onDetachedFromWindow();
493         mContentViewCore.onDetachedFromWindow();
494     }
495
496     @Override
497     protected void onVisibilityChanged(View changedView, int visibility) {
498         super.onVisibilityChanged(changedView, visibility);
499         mContentViewCore.onVisibilityChanged(changedView, visibility);
500     }
501
502     /**
503      * Return the current scale of the WebView
504      * @return The current scale.
505      */
506     public float getScale() {
507         return mContentViewCore.getScale();
508     }
509
510     /**
511      * Enable or disable accessibility features.
512      */
513     public void setAccessibilityState(boolean state) {
514         mContentViewCore.setAccessibilityState(state);
515     }
516
517     /**
518      * Inform WebKit that Fullscreen mode has been exited by the user.
519      */
520     public void exitFullscreen() {
521         mContentViewCore.exitFullscreen();
522     }
523
524     /**
525      * Return content scroll y.
526      *
527      * @return The vertical scroll position in pixels.
528      */
529     public int getContentScrollY() {
530         return mContentViewCore.computeVerticalScrollOffset();
531     }
532
533     /**
534      * Return content height.
535      *
536      * @return The height of the content in pixels.
537      */
538     public int getContentHeight() {
539         return mContentViewCore.computeVerticalScrollRange();
540     }
541
542     ///////////////////////////////////////////////////////////////////////////////////////////////
543     //              Start Implementation of ContentViewCore.InternalAccessDelegate               //
544     ///////////////////////////////////////////////////////////////////////////////////////////////
545
546     @Override
547     public boolean super_onKeyUp(int keyCode, KeyEvent event) {
548         return super.onKeyUp(keyCode, event);
549     }
550
551     @Override
552     public boolean super_dispatchKeyEventPreIme(KeyEvent event) {
553         return super.dispatchKeyEventPreIme(event);
554     }
555
556     @Override
557     public boolean super_dispatchKeyEvent(KeyEvent event) {
558         return super.dispatchKeyEvent(event);
559     }
560
561     @Override
562     public boolean super_onGenericMotionEvent(MotionEvent event) {
563         return super.onGenericMotionEvent(event);
564     }
565
566     @Override
567     public void super_onConfigurationChanged(Configuration newConfig) {
568         super.onConfigurationChanged(newConfig);
569     }
570
571     @Override
572     public boolean super_awakenScrollBars(int startDelay, boolean invalidate) {
573         return super.awakenScrollBars(startDelay, invalidate);
574     }
575
576     ///////////////////////////////////////////////////////////////////////////////////////////////
577     //                End Implementation of ContentViewCore.InternalAccessDelegate               //
578     ///////////////////////////////////////////////////////////////////////////////////////////////
579 }