Home | History | Annotate | Download | only in content_shell
      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.content_shell;
      6 
      7 import android.content.Context;
      8 import android.graphics.drawable.ClipDrawable;
      9 import android.text.TextUtils;
     10 import android.util.AttributeSet;
     11 import android.view.KeyEvent;
     12 import android.view.View;
     13 import android.view.inputmethod.EditorInfo;
     14 import android.view.inputmethod.InputMethodManager;
     15 import android.widget.EditText;
     16 import android.widget.FrameLayout;
     17 import android.widget.ImageButton;
     18 import android.widget.LinearLayout;
     19 import android.widget.TextView;
     20 import android.widget.TextView.OnEditorActionListener;
     21 
     22 import org.chromium.base.CalledByNative;
     23 import org.chromium.base.JNINamespace;
     24 import org.chromium.content.browser.ContentView;
     25 import org.chromium.content.browser.ContentViewRenderView;
     26 import org.chromium.content.browser.LoadUrlParams;
     27 import org.chromium.ui.WindowAndroid;
     28 
     29 /**
     30  * Container for the various UI components that make up a shell window.
     31  */
     32 @JNINamespace("content")
     33 public class Shell extends LinearLayout {
     34 
     35     private static final long COMPLETED_PROGRESS_TIMEOUT_MS = 200;
     36 
     37     private Runnable mClearProgressRunnable = new Runnable() {
     38         @Override
     39         public void run() {
     40             mProgressDrawable.setLevel(0);
     41         }
     42     };
     43 
     44     // TODO(jrg): a mContentView.destroy() call is needed, both upstream and downstream.
     45     private ContentView mContentView;
     46     private EditText mUrlTextView;
     47     private ImageButton mPrevButton;
     48     private ImageButton mNextButton;
     49 
     50     private ClipDrawable mProgressDrawable;
     51 
     52     private ContentViewRenderView mContentViewRenderView;
     53     private WindowAndroid mWindow;
     54 
     55     private boolean mLoading = false;
     56 
     57     /**
     58      * Constructor for inflating via XML.
     59      */
     60     public Shell(Context context, AttributeSet attrs) {
     61         super(context, attrs);
     62     }
     63 
     64     /**
     65      * Set the SurfaceView being renderered to as soon as it is available.
     66      */
     67     public void setContentViewRenderView(ContentViewRenderView contentViewRenderView) {
     68         FrameLayout contentViewHolder = (FrameLayout) findViewById(R.id.contentview_holder);
     69         if (contentViewRenderView == null) {
     70             if (mContentViewRenderView != null) {
     71                 contentViewHolder.removeView(mContentViewRenderView);
     72             }
     73         } else {
     74             contentViewHolder.addView(contentViewRenderView,
     75                     new FrameLayout.LayoutParams(
     76                             FrameLayout.LayoutParams.MATCH_PARENT,
     77                             FrameLayout.LayoutParams.MATCH_PARENT));
     78         }
     79         mContentViewRenderView = contentViewRenderView;
     80     }
     81 
     82     /**
     83      * @param window The owning window for this shell.
     84      */
     85     public void setWindow(WindowAndroid window) {
     86         mWindow = window;
     87     }
     88 
     89     /**
     90      * @return Whether or not the Shell is loading content.
     91      */
     92     public boolean isLoading() {
     93         return mLoading;
     94     }
     95 
     96     @Override
     97     protected void onFinishInflate() {
     98         super.onFinishInflate();
     99 
    100         mProgressDrawable = (ClipDrawable) findViewById(R.id.toolbar).getBackground();
    101         initializeUrlField();
    102         initializeNavigationButtons();
    103     }
    104 
    105     private void initializeUrlField() {
    106         mUrlTextView = (EditText) findViewById(R.id.url);
    107         mUrlTextView.setOnEditorActionListener(new OnEditorActionListener() {
    108             @Override
    109             public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
    110                 if ((actionId != EditorInfo.IME_ACTION_GO) && (event == null ||
    111                         event.getKeyCode() != KeyEvent.KEYCODE_ENTER ||
    112                         event.getAction() != KeyEvent.ACTION_DOWN)) {
    113                     return false;
    114                 }
    115                 loadUrl(mUrlTextView.getText().toString());
    116                 setKeyboardVisibilityForUrl(false);
    117                 mContentView.requestFocus();
    118                 return true;
    119             }
    120         });
    121         mUrlTextView.setOnFocusChangeListener(new OnFocusChangeListener() {
    122             @Override
    123             public void onFocusChange(View v, boolean hasFocus) {
    124                 setKeyboardVisibilityForUrl(hasFocus);
    125                 mNextButton.setVisibility(hasFocus ? GONE : VISIBLE);
    126                 mPrevButton.setVisibility(hasFocus ? GONE : VISIBLE);
    127                 if (!hasFocus) {
    128                     mUrlTextView.setText(mContentView.getUrl());
    129                 }
    130             }
    131         });
    132     }
    133 
    134     /**
    135      * Loads an URL.  This will perform minimal amounts of sanitizing of the URL to attempt to
    136      * make it valid.
    137      *
    138      * @param url The URL to be loaded by the shell.
    139      */
    140     public void loadUrl(String url) {
    141         if (url == null) return;
    142 
    143         if (TextUtils.equals(url, mContentView.getUrl())) {
    144             mContentView.reload();
    145         } else {
    146             mContentView.loadUrl(new LoadUrlParams(sanitizeUrl(url)));
    147         }
    148         mUrlTextView.clearFocus();
    149         // TODO(aurimas): Remove this when crbug.com/174541 is fixed.
    150         mContentView.clearFocus();
    151         mContentView.requestFocus();
    152     }
    153 
    154     /**
    155      * Given an URL, this performs minimal sanitizing to ensure it will be valid.
    156      * @param url The url to be sanitized.
    157      * @return The sanitized URL.
    158      */
    159     public static String sanitizeUrl(String url) {
    160         if (url == null) return url;
    161         if (url.startsWith("www.") || url.indexOf(":") == -1) url = "http://" + url;
    162         return url;
    163     }
    164 
    165     private void initializeNavigationButtons() {
    166         mPrevButton = (ImageButton) findViewById(R.id.prev);
    167         mPrevButton.setOnClickListener(new OnClickListener() {
    168             @Override
    169             public void onClick(View v) {
    170                 if (mContentView.canGoBack()) mContentView.goBack();
    171             }
    172         });
    173 
    174         mNextButton = (ImageButton) findViewById(R.id.next);
    175         mNextButton.setOnClickListener(new OnClickListener() {
    176             @Override
    177             public void onClick(View v) {
    178                 if (mContentView.canGoForward()) mContentView.goForward();
    179             }
    180         });
    181     }
    182 
    183     @SuppressWarnings("unused")
    184     @CalledByNative
    185     private void onUpdateUrl(String url) {
    186         mUrlTextView.setText(url);
    187     }
    188 
    189     @SuppressWarnings("unused")
    190     @CalledByNative
    191     private void onLoadProgressChanged(double progress) {
    192         removeCallbacks(mClearProgressRunnable);
    193         mProgressDrawable.setLevel((int) (10000.0 * progress));
    194         if (progress == 1.0) postDelayed(mClearProgressRunnable, COMPLETED_PROGRESS_TIMEOUT_MS);
    195     }
    196 
    197     @CalledByNative
    198     private void toggleFullscreenModeForTab(boolean enterFullscreen) {
    199     }
    200 
    201     @CalledByNative
    202     private boolean isFullscreenForTabOrPending() {
    203         return false;
    204     }
    205 
    206     @SuppressWarnings("unused")
    207     @CalledByNative
    208     private void setIsLoading(boolean loading) {
    209         mLoading = loading;
    210     }
    211 
    212     /**
    213      * Initializes the ContentView based on the native tab contents pointer passed in.
    214      * @param nativeTabContents The pointer to the native tab contents object.
    215      */
    216     @SuppressWarnings("unused")
    217     @CalledByNative
    218     private void initFromNativeTabContents(int nativeTabContents) {
    219         mContentView = ContentView.newInstance(getContext(), nativeTabContents, mWindow);
    220         if (mContentView.getUrl() != null) mUrlTextView.setText(mContentView.getUrl());
    221         ((FrameLayout) findViewById(R.id.contentview_holder)).addView(mContentView,
    222                 new FrameLayout.LayoutParams(
    223                         FrameLayout.LayoutParams.MATCH_PARENT,
    224                         FrameLayout.LayoutParams.MATCH_PARENT));
    225         mContentView.requestFocus();
    226         mContentViewRenderView.setCurrentContentView(mContentView);
    227     }
    228 
    229     /**
    230      * @return The {@link ContentView} currently shown by this Shell.
    231      */
    232     public ContentView getContentView() {
    233         return mContentView;
    234     }
    235 
    236     private void setKeyboardVisibilityForUrl(boolean visible) {
    237         InputMethodManager imm = (InputMethodManager) getContext().getSystemService(
    238                 Context.INPUT_METHOD_SERVICE);
    239         if (visible) {
    240             imm.showSoftInput(mUrlTextView, InputMethodManager.SHOW_IMPLICIT);
    241         } else {
    242             imm.hideSoftInputFromWindow(mUrlTextView.getWindowToken(), 0);
    243         }
    244     }
    245 }
    246