Home | History | Annotate | Download | only in browser
      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.os.Bundle;
     13 import android.os.Handler;
     14 import android.os.Message;
     15 import android.util.Log;
     16 import android.view.KeyEvent;
     17 import android.view.MotionEvent;
     18 import android.view.View;
     19 import android.view.accessibility.AccessibilityEvent;
     20 import android.view.accessibility.AccessibilityNodeInfo;
     21 import android.view.inputmethod.EditorInfo;
     22 import android.view.inputmethod.InputConnection;
     23 import android.widget.FrameLayout;
     24 
     25 import org.chromium.base.TraceEvent;
     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 public class ContentView extends FrameLayout
     32         implements ContentViewCore.InternalAccessDelegate, SmartClipProvider {
     33 
     34     private static final String TAG = "ContentView";
     35 
     36     protected final ContentViewCore mContentViewCore;
     37 
     38     /**
     39      * Creates an instance of a ContentView.
     40      * @param context The Context the view is running in, through which it can
     41      *                access the current theme, resources, etc.
     42      * @param cvc A pointer to the content view core managing this content view.
     43      * @return A ContentView instance.
     44      */
     45     public static ContentView newInstance(Context context, ContentViewCore cvc) {
     46         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
     47             return new ContentView(context, cvc);
     48         } else {
     49             return new JellyBeanContentView(context, cvc);
     50         }
     51     }
     52 
     53     protected ContentView(Context context, ContentViewCore cvc) {
     54         super(context, null, android.R.attr.webViewStyle);
     55 
     56         if (getScrollBarStyle() == View.SCROLLBARS_INSIDE_OVERLAY) {
     57             setHorizontalScrollBarEnabled(false);
     58             setVerticalScrollBarEnabled(false);
     59         }
     60 
     61         setFocusable(true);
     62         setFocusableInTouchMode(true);
     63 
     64         mContentViewCore = cvc;
     65     }
     66 
     67     // Needed by ContentViewCore.InternalAccessDelegate
     68     @Override
     69     public boolean drawChild(Canvas canvas, View child, long drawingTime) {
     70         return super.drawChild(canvas, child, drawingTime);
     71     }
     72 
     73     // Needed by ContentViewCore.InternalAccessDelegate
     74     @Override
     75     public void onScrollChanged(int l, int t, int oldl, int oldt) {
     76         super.onScrollChanged(l, t, oldl, oldt);
     77     }
     78 
     79     @Override
     80     protected void onSizeChanged(int w, int h, int ow, int oh) {
     81         TraceEvent.begin();
     82         super.onSizeChanged(w, h, ow, oh);
     83         mContentViewCore.onSizeChanged(w, h, ow, oh);
     84         TraceEvent.end();
     85     }
     86 
     87     @Override
     88     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
     89         return mContentViewCore.onCreateInputConnection(outAttrs);
     90     }
     91 
     92     @Override
     93     public boolean onCheckIsTextEditor() {
     94         return mContentViewCore.onCheckIsTextEditor();
     95     }
     96 
     97     @Override
     98     protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
     99         TraceEvent.begin();
    100         super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
    101         mContentViewCore.onFocusChanged(gainFocus);
    102         TraceEvent.end();
    103     }
    104 
    105     @Override
    106     public void onWindowFocusChanged(boolean hasWindowFocus) {
    107         super.onWindowFocusChanged(hasWindowFocus);
    108         mContentViewCore.onWindowFocusChanged(hasWindowFocus);
    109     }
    110 
    111     @Override
    112     public boolean onKeyUp(int keyCode, KeyEvent event) {
    113         return mContentViewCore.onKeyUp(keyCode, event);
    114     }
    115 
    116     @Override
    117     public boolean dispatchKeyEventPreIme(KeyEvent event) {
    118         return mContentViewCore.dispatchKeyEventPreIme(event);
    119     }
    120 
    121     @Override
    122     public boolean dispatchKeyEvent(KeyEvent event) {
    123         if (isFocused()) {
    124             return mContentViewCore.dispatchKeyEvent(event);
    125         } else {
    126             return super.dispatchKeyEvent(event);
    127         }
    128     }
    129 
    130     @Override
    131     public boolean onTouchEvent(MotionEvent event) {
    132         return mContentViewCore.onTouchEvent(event);
    133     }
    134 
    135     /**
    136      * Mouse move events are sent on hover enter, hover move and hover exit.
    137      * They are sent on hover exit because sometimes it acts as both a hover
    138      * move and hover exit.
    139      */
    140     @Override
    141     public boolean onHoverEvent(MotionEvent event) {
    142         boolean consumed = mContentViewCore.onHoverEvent(event);
    143         if (!mContentViewCore.isTouchExplorationEnabled()) super.onHoverEvent(event);
    144         return consumed;
    145     }
    146 
    147     @Override
    148     public boolean onGenericMotionEvent(MotionEvent event) {
    149         return mContentViewCore.onGenericMotionEvent(event);
    150     }
    151 
    152     @Override
    153     public boolean performLongClick() {
    154         return false;
    155     }
    156 
    157     @Override
    158     protected void onConfigurationChanged(Configuration newConfig) {
    159         mContentViewCore.onConfigurationChanged(newConfig);
    160     }
    161 
    162     /**
    163      * Currently the ContentView scrolling happens in the native side. In
    164      * the Java view system, it is always pinned at (0, 0). scrollBy() and scrollTo()
    165      * are overridden, so that View's mScrollX and mScrollY will be unchanged at
    166      * (0, 0). This is critical for drawing ContentView correctly.
    167      */
    168     @Override
    169     public void scrollBy(int x, int y) {
    170         mContentViewCore.scrollBy(x, y);
    171     }
    172 
    173     @Override
    174     public void scrollTo(int x, int y) {
    175         mContentViewCore.scrollTo(x, y);
    176     }
    177 
    178     @Override
    179     protected int computeHorizontalScrollExtent() {
    180         // TODO(dtrainor): Need to expose scroll events properly to public. Either make getScroll*
    181         // work or expose computeHorizontalScrollOffset()/computeVerticalScrollOffset as public.
    182         return mContentViewCore.computeHorizontalScrollExtent();
    183     }
    184 
    185     @Override
    186     protected int computeHorizontalScrollOffset() {
    187         return mContentViewCore.computeHorizontalScrollOffset();
    188     }
    189 
    190     @Override
    191     protected int computeHorizontalScrollRange() {
    192         return mContentViewCore.computeHorizontalScrollRange();
    193     }
    194 
    195     @Override
    196     protected int computeVerticalScrollExtent() {
    197         return mContentViewCore.computeVerticalScrollExtent();
    198     }
    199 
    200     @Override
    201     protected int computeVerticalScrollOffset() {
    202         return mContentViewCore.computeVerticalScrollOffset();
    203     }
    204 
    205     @Override
    206     protected int computeVerticalScrollRange() {
    207         return mContentViewCore.computeVerticalScrollRange();
    208     }
    209 
    210     // End FrameLayout overrides.
    211 
    212     @Override
    213     public boolean awakenScrollBars(int startDelay, boolean invalidate) {
    214         return mContentViewCore.awakenScrollBars(startDelay, invalidate);
    215     }
    216 
    217     @Override
    218     public boolean awakenScrollBars() {
    219         return super.awakenScrollBars();
    220     }
    221 
    222     @Override
    223     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
    224         super.onInitializeAccessibilityNodeInfo(info);
    225         mContentViewCore.onInitializeAccessibilityNodeInfo(info);
    226     }
    227 
    228     /**
    229      * Fills in scrolling values for AccessibilityEvents.
    230      * @param event Event being fired.
    231      */
    232     @Override
    233     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
    234         super.onInitializeAccessibilityEvent(event);
    235         mContentViewCore.onInitializeAccessibilityEvent(event);
    236     }
    237 
    238     @Override
    239     protected void onAttachedToWindow() {
    240         super.onAttachedToWindow();
    241         mContentViewCore.onAttachedToWindow();
    242     }
    243 
    244     @Override
    245     protected void onDetachedFromWindow() {
    246         super.onDetachedFromWindow();
    247         mContentViewCore.onDetachedFromWindow();
    248     }
    249 
    250     @Override
    251     protected void onVisibilityChanged(View changedView, int visibility) {
    252         super.onVisibilityChanged(changedView, visibility);
    253         mContentViewCore.onVisibilityChanged(changedView, visibility);
    254     }
    255 
    256     // Implements SmartClipProvider
    257     @Override
    258     public void extractSmartClipData(int x, int y, int width, int height) {
    259         mContentViewCore.extractSmartClipData(x, y, width, height);
    260     }
    261 
    262     // Implements SmartClipProvider
    263     @Override
    264     public void setSmartClipResultHandler(final Handler resultHandler) {
    265         if (resultHandler == null) {
    266             mContentViewCore.setSmartClipDataListener(null);
    267             return;
    268         }
    269         mContentViewCore.setSmartClipDataListener(new ContentViewCore.SmartClipDataListener() {
    270             public void onSmartClipDataExtracted(String text, String html, Rect clipRect) {
    271                 Bundle bundle = new Bundle();
    272                 bundle.putString("url", mContentViewCore.getWebContents().getVisibleUrl());
    273                 bundle.putString("title", mContentViewCore.getWebContents().getTitle());
    274                 bundle.putParcelable("rect", clipRect);
    275                 bundle.putString("text", text);
    276                 bundle.putString("html", html);
    277                 try {
    278                     Message msg = Message.obtain(resultHandler, 0);
    279                     msg.setData(bundle);
    280                     msg.sendToTarget();
    281                 } catch (Exception e) {
    282                     Log.e(TAG, "Error calling handler for smart clip data: ", e);
    283                 }
    284             }
    285         });
    286     }
    287 
    288     ///////////////////////////////////////////////////////////////////////////////////////////////
    289     //              Start Implementation of ContentViewCore.InternalAccessDelegate               //
    290     ///////////////////////////////////////////////////////////////////////////////////////////////
    291 
    292     @Override
    293     public boolean super_onKeyUp(int keyCode, KeyEvent event) {
    294         return super.onKeyUp(keyCode, event);
    295     }
    296 
    297     @Override
    298     public boolean super_dispatchKeyEventPreIme(KeyEvent event) {
    299         return super.dispatchKeyEventPreIme(event);
    300     }
    301 
    302     @Override
    303     public boolean super_dispatchKeyEvent(KeyEvent event) {
    304         return super.dispatchKeyEvent(event);
    305     }
    306 
    307     @Override
    308     public boolean super_onGenericMotionEvent(MotionEvent event) {
    309         return super.onGenericMotionEvent(event);
    310     }
    311 
    312     @Override
    313     public void super_onConfigurationChanged(Configuration newConfig) {
    314         super.onConfigurationChanged(newConfig);
    315     }
    316 
    317     @Override
    318     public boolean super_awakenScrollBars(int startDelay, boolean invalidate) {
    319         return super.awakenScrollBars(startDelay, invalidate);
    320     }
    321 
    322     ///////////////////////////////////////////////////////////////////////////////////////////////
    323     //                End Implementation of ContentViewCore.InternalAccessDelegate               //
    324     ///////////////////////////////////////////////////////////////////////////////////////////////
    325 }
    326