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