Home | History | Annotate | Download | only in browser
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.browser;
     18 
     19 import android.app.Activity;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.content.res.Configuration;
     23 import android.content.res.Resources;
     24 import android.graphics.Bitmap;
     25 import android.graphics.BitmapFactory;
     26 import android.graphics.Color;
     27 import android.graphics.drawable.BitmapDrawable;
     28 import android.graphics.drawable.Drawable;
     29 import android.graphics.drawable.LayerDrawable;
     30 import android.graphics.drawable.PaintDrawable;
     31 import android.os.Bundle;
     32 import android.os.Handler;
     33 import android.os.Message;
     34 import android.text.TextUtils;
     35 import android.view.Gravity;
     36 import android.view.LayoutInflater;
     37 import android.view.Menu;
     38 import android.view.MenuItem;
     39 import android.view.MotionEvent;
     40 import android.view.View;
     41 import android.view.View.OnClickListener;
     42 import android.view.ViewGroup;
     43 import android.view.ViewGroup.LayoutParams;
     44 import android.view.Window;
     45 import android.view.WindowManager;
     46 import android.view.inputmethod.InputMethodManager;
     47 import android.webkit.WebChromeClient;
     48 import android.webkit.WebView;
     49 import android.webkit.WebViewClassic;
     50 import android.widget.FrameLayout;
     51 import android.widget.ImageButton;
     52 import android.widget.LinearLayout;
     53 import android.widget.Toast;
     54 
     55 import com.android.browser.Tab.SecurityState;
     56 import com.android.internal.view.menu.MenuBuilder;
     57 
     58 import java.util.List;
     59 
     60 /**
     61  * UI interface definitions
     62  */
     63 public abstract class BaseUi implements UI {
     64 
     65     private static final String LOGTAG = "BaseUi";
     66 
     67     protected static final FrameLayout.LayoutParams COVER_SCREEN_PARAMS =
     68         new FrameLayout.LayoutParams(
     69         ViewGroup.LayoutParams.MATCH_PARENT,
     70         ViewGroup.LayoutParams.MATCH_PARENT);
     71 
     72     protected static final FrameLayout.LayoutParams COVER_SCREEN_GRAVITY_CENTER =
     73         new FrameLayout.LayoutParams(
     74         ViewGroup.LayoutParams.MATCH_PARENT,
     75         ViewGroup.LayoutParams.MATCH_PARENT,
     76         Gravity.CENTER);
     77 
     78     private static final int MSG_HIDE_TITLEBAR = 1;
     79     public static final int HIDE_TITLEBAR_DELAY = 1500; // in ms
     80 
     81     Activity mActivity;
     82     UiController mUiController;
     83     TabControl mTabControl;
     84     protected Tab mActiveTab;
     85     private InputMethodManager mInputManager;
     86 
     87     private Drawable mLockIconSecure;
     88     private Drawable mLockIconMixed;
     89     protected Drawable mGenericFavicon;
     90 
     91     protected FrameLayout mContentView;
     92     protected FrameLayout mCustomViewContainer;
     93     protected FrameLayout mFullscreenContainer;
     94     private FrameLayout mFixedTitlebarContainer;
     95 
     96     private View mCustomView;
     97     private WebChromeClient.CustomViewCallback mCustomViewCallback;
     98     private int mOriginalOrientation;
     99 
    100     private LinearLayout mErrorConsoleContainer = null;
    101 
    102     private UrlBarAutoShowManager mUrlBarAutoShowManager;
    103 
    104     private Toast mStopToast;
    105 
    106     // the default <video> poster
    107     private Bitmap mDefaultVideoPoster;
    108     // the video progress view
    109     private View mVideoProgressView;
    110 
    111     private boolean mActivityPaused;
    112     protected boolean mUseQuickControls;
    113     protected TitleBar mTitleBar;
    114     private NavigationBarBase mNavigationBar;
    115     protected PieControl mPieControl;
    116     private boolean mBlockFocusAnimations;
    117 
    118     public BaseUi(Activity browser, UiController controller) {
    119         mActivity = browser;
    120         mUiController = controller;
    121         mTabControl = controller.getTabControl();
    122         Resources res = mActivity.getResources();
    123         mInputManager = (InputMethodManager)
    124                 browser.getSystemService(Activity.INPUT_METHOD_SERVICE);
    125         mLockIconSecure = res.getDrawable(R.drawable.ic_secure_holo_dark);
    126         mLockIconMixed = res.getDrawable(R.drawable.ic_secure_partial_holo_dark);
    127         FrameLayout frameLayout = (FrameLayout) mActivity.getWindow()
    128                 .getDecorView().findViewById(android.R.id.content);
    129         LayoutInflater.from(mActivity)
    130                 .inflate(R.layout.custom_screen, frameLayout);
    131         mFixedTitlebarContainer = (FrameLayout) frameLayout.findViewById(
    132                 R.id.fixed_titlebar_container);
    133         mContentView = (FrameLayout) frameLayout.findViewById(
    134                 R.id.main_content);
    135         mCustomViewContainer = (FrameLayout) frameLayout.findViewById(
    136                 R.id.fullscreen_custom_content);
    137         mErrorConsoleContainer = (LinearLayout) frameLayout
    138                 .findViewById(R.id.error_console);
    139         setFullscreen(BrowserSettings.getInstance().useFullscreen());
    140         mGenericFavicon = res.getDrawable(
    141                 R.drawable.app_web_browser_sm);
    142         mTitleBar = new TitleBar(mActivity, mUiController, this,
    143                 mContentView);
    144         mTitleBar.setProgress(100);
    145         mNavigationBar = mTitleBar.getNavigationBar();
    146         mUrlBarAutoShowManager = new UrlBarAutoShowManager(this);
    147     }
    148 
    149     private void cancelStopToast() {
    150         if (mStopToast != null) {
    151             mStopToast.cancel();
    152             mStopToast = null;
    153         }
    154     }
    155 
    156     // lifecycle
    157 
    158     public void onPause() {
    159         if (isCustomViewShowing()) {
    160             onHideCustomView();
    161         }
    162         cancelStopToast();
    163         mActivityPaused = true;
    164     }
    165 
    166     public void onResume() {
    167         mActivityPaused = false;
    168         // check if we exited without setting active tab
    169         // b: 5188145
    170         final Tab ct = mTabControl.getCurrentTab();
    171         if (ct != null) {
    172             setActiveTab(ct);
    173         }
    174     }
    175 
    176     protected boolean isActivityPaused() {
    177         return mActivityPaused;
    178     }
    179 
    180     public void onConfigurationChanged(Configuration config) {
    181     }
    182 
    183     public Activity getActivity() {
    184         return mActivity;
    185     }
    186 
    187     // key handling
    188 
    189     @Override
    190     public boolean onBackKey() {
    191         if (mCustomView != null) {
    192             mUiController.hideCustomView();
    193             return true;
    194         }
    195         return false;
    196     }
    197 
    198     @Override
    199     public boolean onMenuKey() {
    200         return false;
    201     }
    202 
    203     @Override
    204     public void setUseQuickControls(boolean useQuickControls) {
    205         mUseQuickControls = useQuickControls;
    206         mTitleBar.setUseQuickControls(mUseQuickControls);
    207         if (useQuickControls) {
    208             mPieControl = new PieControl(mActivity, mUiController, this);
    209             mPieControl.attachToContainer(mContentView);
    210         } else {
    211             if (mPieControl != null) {
    212                 mPieControl.removeFromContainer(mContentView);
    213             }
    214         }
    215         updateUrlBarAutoShowManagerTarget();
    216     }
    217 
    218     // Tab callbacks
    219     @Override
    220     public void onTabDataChanged(Tab tab) {
    221         setUrlTitle(tab);
    222         setFavicon(tab);
    223         updateLockIconToLatest(tab);
    224         updateNavigationState(tab);
    225         mTitleBar.onTabDataChanged(tab);
    226         mNavigationBar.onTabDataChanged(tab);
    227         onProgressChanged(tab);
    228     }
    229 
    230     @Override
    231     public void onProgressChanged(Tab tab) {
    232         int progress = tab.getLoadProgress();
    233         if (tab.inForeground()) {
    234             mTitleBar.setProgress(progress);
    235         }
    236     }
    237 
    238     @Override
    239     public void bookmarkedStatusHasChanged(Tab tab) {
    240         if (tab.inForeground()) {
    241             boolean isBookmark = tab.isBookmarkedSite();
    242             mNavigationBar.setCurrentUrlIsBookmark(isBookmark);
    243         }
    244     }
    245 
    246     @Override
    247     public void onPageStopped(Tab tab) {
    248         cancelStopToast();
    249         if (tab.inForeground()) {
    250             mStopToast = Toast
    251                     .makeText(mActivity, R.string.stopping, Toast.LENGTH_SHORT);
    252             mStopToast.show();
    253         }
    254     }
    255 
    256     @Override
    257     public boolean needsRestoreAllTabs() {
    258         return true;
    259     }
    260 
    261     @Override
    262     public void addTab(Tab tab) {
    263     }
    264 
    265     @Override
    266     public void setActiveTab(final Tab tab) {
    267         if (tab == null) return;
    268         // block unnecessary focus change animations during tab switch
    269         mBlockFocusAnimations = true;
    270         mHandler.removeMessages(MSG_HIDE_TITLEBAR);
    271         if ((tab != mActiveTab) && (mActiveTab != null)) {
    272             removeTabFromContentView(mActiveTab);
    273             WebView web = mActiveTab.getWebView();
    274             if (web != null) {
    275                 web.setOnTouchListener(null);
    276             }
    277         }
    278         mActiveTab = tab;
    279         BrowserWebView web = (BrowserWebView) mActiveTab.getWebView();
    280         updateUrlBarAutoShowManagerTarget();
    281         attachTabToContentView(tab);
    282         if (web != null) {
    283             // Request focus on the top window.
    284             if (mUseQuickControls) {
    285                 mPieControl.forceToTop(mContentView);
    286                 web.setTitleBar(null);
    287                 mTitleBar.hide();
    288             } else {
    289                 web.setTitleBar(mTitleBar);
    290                 mTitleBar.onScrollChanged();
    291             }
    292         }
    293         mTitleBar.bringToFront();
    294         tab.getTopWindow().requestFocus();
    295         setShouldShowErrorConsole(tab, mUiController.shouldShowErrorConsole());
    296         onTabDataChanged(tab);
    297         onProgressChanged(tab);
    298         mNavigationBar.setIncognitoMode(tab.isPrivateBrowsingEnabled());
    299         updateAutoLogin(tab, false);
    300         mBlockFocusAnimations = false;
    301     }
    302 
    303     protected void updateUrlBarAutoShowManagerTarget() {
    304         WebView web = mActiveTab != null ? mActiveTab.getWebView() : null;
    305         if (!mUseQuickControls && web instanceof BrowserWebView) {
    306             mUrlBarAutoShowManager.setTarget((BrowserWebView) web);
    307         } else {
    308             mUrlBarAutoShowManager.setTarget(null);
    309         }
    310     }
    311 
    312     Tab getActiveTab() {
    313         return mActiveTab;
    314     }
    315 
    316     @Override
    317     public void updateTabs(List<Tab> tabs) {
    318     }
    319 
    320     @Override
    321     public void removeTab(Tab tab) {
    322         if (mActiveTab == tab) {
    323             removeTabFromContentView(tab);
    324             mActiveTab = null;
    325         }
    326     }
    327 
    328     @Override
    329     public void detachTab(Tab tab) {
    330         removeTabFromContentView(tab);
    331     }
    332 
    333     @Override
    334     public void attachTab(Tab tab) {
    335         attachTabToContentView(tab);
    336     }
    337 
    338     protected void attachTabToContentView(Tab tab) {
    339         if ((tab == null) || (tab.getWebView() == null)) {
    340             return;
    341         }
    342         View container = tab.getViewContainer();
    343         WebView mainView  = tab.getWebView();
    344         // Attach the WebView to the container and then attach the
    345         // container to the content view.
    346         FrameLayout wrapper =
    347                 (FrameLayout) container.findViewById(R.id.webview_wrapper);
    348         ViewGroup parent = (ViewGroup) mainView.getParent();
    349         if (parent != wrapper) {
    350             if (parent != null) {
    351                 parent.removeView(mainView);
    352             }
    353             wrapper.addView(mainView);
    354         }
    355         parent = (ViewGroup) container.getParent();
    356         if (parent != mContentView) {
    357             if (parent != null) {
    358                 parent.removeView(container);
    359             }
    360             mContentView.addView(container, COVER_SCREEN_PARAMS);
    361         }
    362         mUiController.attachSubWindow(tab);
    363     }
    364 
    365     private void removeTabFromContentView(Tab tab) {
    366         hideTitleBar();
    367         // Remove the container that contains the main WebView.
    368         WebView mainView = tab.getWebView();
    369         View container = tab.getViewContainer();
    370         if (mainView == null) {
    371             return;
    372         }
    373         // Remove the container from the content and then remove the
    374         // WebView from the container. This will trigger a focus change
    375         // needed by WebView.
    376         FrameLayout wrapper =
    377                 (FrameLayout) container.findViewById(R.id.webview_wrapper);
    378         wrapper.removeView(mainView);
    379         mContentView.removeView(container);
    380         mUiController.endActionMode();
    381         mUiController.removeSubWindow(tab);
    382         ErrorConsoleView errorConsole = tab.getErrorConsole(false);
    383         if (errorConsole != null) {
    384             mErrorConsoleContainer.removeView(errorConsole);
    385         }
    386     }
    387 
    388     @Override
    389     public void onSetWebView(Tab tab, WebView webView) {
    390         View container = tab.getViewContainer();
    391         if (container == null) {
    392             // The tab consists of a container view, which contains the main
    393             // WebView, as well as any other UI elements associated with the tab.
    394             container = mActivity.getLayoutInflater().inflate(R.layout.tab,
    395                     mContentView, false);
    396             tab.setViewContainer(container);
    397         }
    398         if (tab.getWebView() != webView) {
    399             // Just remove the old one.
    400             FrameLayout wrapper =
    401                     (FrameLayout) container.findViewById(R.id.webview_wrapper);
    402             wrapper.removeView(tab.getWebView());
    403         }
    404     }
    405 
    406     /**
    407      * create a sub window container and webview for the tab
    408      * Note: this methods operates through side-effects for now
    409      * it sets both the subView and subViewContainer for the given tab
    410      * @param tab tab to create the sub window for
    411      * @param subView webview to be set as a subwindow for the tab
    412      */
    413     @Override
    414     public void createSubWindow(Tab tab, WebView subView) {
    415         View subViewContainer = mActivity.getLayoutInflater().inflate(
    416                 R.layout.browser_subwindow, null);
    417         ViewGroup inner = (ViewGroup) subViewContainer
    418                 .findViewById(R.id.inner_container);
    419         inner.addView(subView, new LayoutParams(LayoutParams.MATCH_PARENT,
    420                 LayoutParams.MATCH_PARENT));
    421         final ImageButton cancel = (ImageButton) subViewContainer
    422                 .findViewById(R.id.subwindow_close);
    423         final WebView cancelSubView = subView;
    424         cancel.setOnClickListener(new OnClickListener() {
    425             public void onClick(View v) {
    426                 WebViewClassic.fromWebView(cancelSubView).getWebChromeClient().onCloseWindow(
    427                         cancelSubView);
    428             }
    429         });
    430         tab.setSubWebView(subView);
    431         tab.setSubViewContainer(subViewContainer);
    432     }
    433 
    434     /**
    435      * Remove the sub window from the content view.
    436      */
    437     @Override
    438     public void removeSubWindow(View subviewContainer) {
    439         mContentView.removeView(subviewContainer);
    440         mUiController.endActionMode();
    441     }
    442 
    443     /**
    444      * Attach the sub window to the content view.
    445      */
    446     @Override
    447     public void attachSubWindow(View container) {
    448         if (container.getParent() != null) {
    449             // already attached, remove first
    450             ((ViewGroup) container.getParent()).removeView(container);
    451         }
    452         mContentView.addView(container, COVER_SCREEN_PARAMS);
    453     }
    454 
    455     protected void refreshWebView() {
    456         WebView web = getWebView();
    457         if (web != null) {
    458             web.invalidate();
    459         }
    460     }
    461 
    462     public void editUrl(boolean clearInput, boolean forceIME) {
    463         if (mUiController.isInCustomActionMode()) {
    464             mUiController.endActionMode();
    465         }
    466         showTitleBar();
    467         if ((getActiveTab() != null) && !getActiveTab().isSnapshot()) {
    468             mNavigationBar.startEditingUrl(clearInput, forceIME);
    469         }
    470     }
    471 
    472     boolean canShowTitleBar() {
    473         return !isTitleBarShowing()
    474                 && !isActivityPaused()
    475                 && (getActiveTab() != null)
    476                 && (getWebView() != null)
    477                 && !mUiController.isInCustomActionMode();
    478     }
    479 
    480     protected void showTitleBar() {
    481         mHandler.removeMessages(MSG_HIDE_TITLEBAR);
    482         if (canShowTitleBar()) {
    483             mTitleBar.show();
    484         }
    485     }
    486 
    487     protected void hideTitleBar() {
    488         if (mTitleBar.isShowing()) {
    489             mTitleBar.hide();
    490         }
    491     }
    492 
    493     protected boolean isTitleBarShowing() {
    494         return mTitleBar.isShowing();
    495     }
    496 
    497     public boolean isEditingUrl() {
    498         return mTitleBar.isEditingUrl();
    499     }
    500 
    501     public void stopEditingUrl() {
    502         mTitleBar.getNavigationBar().stopEditingUrl();
    503     }
    504 
    505     public TitleBar getTitleBar() {
    506         return mTitleBar;
    507     }
    508 
    509     @Override
    510     public void showComboView(ComboViews startingView, Bundle extras) {
    511         Intent intent = new Intent(mActivity, ComboViewActivity.class);
    512         intent.putExtra(ComboViewActivity.EXTRA_INITIAL_VIEW, startingView.name());
    513         intent.putExtra(ComboViewActivity.EXTRA_COMBO_ARGS, extras);
    514         Tab t = getActiveTab();
    515         if (t != null) {
    516             intent.putExtra(ComboViewActivity.EXTRA_CURRENT_URL, t.getUrl());
    517         }
    518         mActivity.startActivityForResult(intent, Controller.COMBO_VIEW);
    519     }
    520 
    521     @Override
    522     public void showCustomView(View view, int requestedOrientation,
    523             WebChromeClient.CustomViewCallback callback) {
    524         // if a view already exists then immediately terminate the new one
    525         if (mCustomView != null) {
    526             callback.onCustomViewHidden();
    527             return;
    528         }
    529 
    530         mOriginalOrientation = mActivity.getRequestedOrientation();
    531         FrameLayout decor = (FrameLayout) mActivity.getWindow().getDecorView();
    532         mFullscreenContainer = new FullscreenHolder(mActivity);
    533         mFullscreenContainer.addView(view, COVER_SCREEN_PARAMS);
    534         decor.addView(mFullscreenContainer, COVER_SCREEN_PARAMS);
    535         mCustomView = view;
    536         setFullscreen(true);
    537         ((BrowserWebView) getWebView()).setVisibility(View.INVISIBLE);
    538         mCustomViewCallback = callback;
    539         mActivity.setRequestedOrientation(requestedOrientation);
    540     }
    541 
    542     @Override
    543     public void onHideCustomView() {
    544         ((BrowserWebView) getWebView()).setVisibility(View.VISIBLE);
    545         if (mCustomView == null)
    546             return;
    547         setFullscreen(false);
    548         FrameLayout decor = (FrameLayout) mActivity.getWindow().getDecorView();
    549         decor.removeView(mFullscreenContainer);
    550         mFullscreenContainer = null;
    551         mCustomView = null;
    552         mCustomViewCallback.onCustomViewHidden();
    553         // Show the content view.
    554         mActivity.setRequestedOrientation(mOriginalOrientation);
    555     }
    556 
    557     @Override
    558     public boolean isCustomViewShowing() {
    559         return mCustomView != null;
    560     }
    561 
    562     protected void dismissIME() {
    563         if (mInputManager.isActive()) {
    564             mInputManager.hideSoftInputFromWindow(mContentView.getWindowToken(),
    565                     0);
    566         }
    567     }
    568 
    569     @Override
    570     public boolean isWebShowing() {
    571         return mCustomView == null;
    572     }
    573 
    574     @Override
    575     public void showAutoLogin(Tab tab) {
    576         updateAutoLogin(tab, true);
    577     }
    578 
    579     @Override
    580     public void hideAutoLogin(Tab tab) {
    581         updateAutoLogin(tab, true);
    582     }
    583 
    584     // -------------------------------------------------------------------------
    585 
    586     protected void updateNavigationState(Tab tab) {
    587     }
    588 
    589     protected void updateAutoLogin(Tab tab, boolean animate) {
    590         mTitleBar.updateAutoLogin(tab, animate);
    591     }
    592 
    593     /**
    594      * Update the lock icon to correspond to our latest state.
    595      */
    596     protected void updateLockIconToLatest(Tab t) {
    597         if (t != null && t.inForeground()) {
    598             updateLockIconImage(t.getSecurityState());
    599         }
    600     }
    601 
    602     /**
    603      * Updates the lock-icon image in the title-bar.
    604      */
    605     private void updateLockIconImage(SecurityState securityState) {
    606         Drawable d = null;
    607         if (securityState == SecurityState.SECURITY_STATE_SECURE) {
    608             d = mLockIconSecure;
    609         } else if (securityState == SecurityState.SECURITY_STATE_MIXED
    610                 || securityState == SecurityState.SECURITY_STATE_BAD_CERTIFICATE) {
    611             // TODO: It would be good to have different icons for insecure vs mixed content.
    612             // See http://b/5403800
    613             d = mLockIconMixed;
    614         }
    615         mNavigationBar.setLock(d);
    616     }
    617 
    618     protected void setUrlTitle(Tab tab) {
    619         String url = tab.getUrl();
    620         String title = tab.getTitle();
    621         if (TextUtils.isEmpty(title)) {
    622             title = url;
    623         }
    624         if (tab.inForeground()) {
    625             mNavigationBar.setDisplayTitle(url);
    626         }
    627     }
    628 
    629     // Set the favicon in the title bar.
    630     protected void setFavicon(Tab tab) {
    631         if (tab.inForeground()) {
    632             Bitmap icon = tab.getFavicon();
    633             mNavigationBar.setFavicon(icon);
    634         }
    635     }
    636 
    637     @Override
    638     public void onActionModeFinished(boolean inLoad) {
    639     }
    640 
    641     // active tabs page
    642 
    643     public void showActiveTabsPage() {
    644     }
    645 
    646     /**
    647      * Remove the active tabs page.
    648      */
    649     public void removeActiveTabsPage() {
    650     }
    651 
    652     // menu handling callbacks
    653 
    654     @Override
    655     public boolean onPrepareOptionsMenu(Menu menu) {
    656         return true;
    657     }
    658 
    659     @Override
    660     public void updateMenuState(Tab tab, Menu menu) {
    661     }
    662 
    663     @Override
    664     public void onOptionsMenuOpened() {
    665     }
    666 
    667     @Override
    668     public void onExtendedMenuOpened() {
    669     }
    670 
    671     @Override
    672     public boolean onOptionsItemSelected(MenuItem item) {
    673         return false;
    674     }
    675 
    676     @Override
    677     public void onOptionsMenuClosed(boolean inLoad) {
    678     }
    679 
    680     @Override
    681     public void onExtendedMenuClosed(boolean inLoad) {
    682     }
    683 
    684     @Override
    685     public void onContextMenuCreated(Menu menu) {
    686     }
    687 
    688     @Override
    689     public void onContextMenuClosed(Menu menu, boolean inLoad) {
    690     }
    691 
    692     // error console
    693 
    694     @Override
    695     public void setShouldShowErrorConsole(Tab tab, boolean flag) {
    696         if (tab == null) return;
    697         ErrorConsoleView errorConsole = tab.getErrorConsole(true);
    698         if (flag) {
    699             // Setting the show state of the console will cause it's the layout
    700             // to be inflated.
    701             if (errorConsole.numberOfErrors() > 0) {
    702                 errorConsole.showConsole(ErrorConsoleView.SHOW_MINIMIZED);
    703             } else {
    704                 errorConsole.showConsole(ErrorConsoleView.SHOW_NONE);
    705             }
    706             if (errorConsole.getParent() != null) {
    707                 mErrorConsoleContainer.removeView(errorConsole);
    708             }
    709             // Now we can add it to the main view.
    710             mErrorConsoleContainer.addView(errorConsole,
    711                     new LinearLayout.LayoutParams(
    712                             ViewGroup.LayoutParams.MATCH_PARENT,
    713                             ViewGroup.LayoutParams.WRAP_CONTENT));
    714         } else {
    715             mErrorConsoleContainer.removeView(errorConsole);
    716         }
    717     }
    718 
    719     // -------------------------------------------------------------------------
    720     // Helper function for WebChromeClient
    721     // -------------------------------------------------------------------------
    722 
    723     @Override
    724     public Bitmap getDefaultVideoPoster() {
    725         if (mDefaultVideoPoster == null) {
    726             mDefaultVideoPoster = BitmapFactory.decodeResource(
    727                     mActivity.getResources(), R.drawable.default_video_poster);
    728         }
    729         return mDefaultVideoPoster;
    730     }
    731 
    732     @Override
    733     public View getVideoLoadingProgressView() {
    734         if (mVideoProgressView == null) {
    735             LayoutInflater inflater = LayoutInflater.from(mActivity);
    736             mVideoProgressView = inflater.inflate(
    737                     R.layout.video_loading_progress, null);
    738         }
    739         return mVideoProgressView;
    740     }
    741 
    742     @Override
    743     public void showMaxTabsWarning() {
    744         Toast warning = Toast.makeText(mActivity,
    745                 mActivity.getString(R.string.max_tabs_warning),
    746                 Toast.LENGTH_SHORT);
    747         warning.show();
    748     }
    749 
    750     protected WebView getWebView() {
    751         if (mActiveTab != null) {
    752             return mActiveTab.getWebView();
    753         } else {
    754             return null;
    755         }
    756     }
    757 
    758     protected Menu getMenu() {
    759         MenuBuilder menu = new MenuBuilder(mActivity);
    760         mActivity.getMenuInflater().inflate(R.menu.browser, menu);
    761         return menu;
    762     }
    763 
    764     public void setFullscreen(boolean enabled) {
    765         Window win = mActivity.getWindow();
    766         WindowManager.LayoutParams winParams = win.getAttributes();
    767         final int bits = WindowManager.LayoutParams.FLAG_FULLSCREEN;
    768         if (enabled) {
    769             winParams.flags |=  bits;
    770         } else {
    771             winParams.flags &= ~bits;
    772             if (mCustomView != null) {
    773                 mCustomView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
    774             } else {
    775                 mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
    776             }
    777         }
    778         win.setAttributes(winParams);
    779     }
    780 
    781     public Drawable getFaviconDrawable(Bitmap icon) {
    782         Drawable[] array = new Drawable[3];
    783         array[0] = new PaintDrawable(Color.BLACK);
    784         PaintDrawable p = new PaintDrawable(Color.WHITE);
    785         array[1] = p;
    786         if (icon == null) {
    787             array[2] = mGenericFavicon;
    788         } else {
    789             array[2] = new BitmapDrawable(icon);
    790         }
    791         LayerDrawable d = new LayerDrawable(array);
    792         d.setLayerInset(1, 1, 1, 1, 1);
    793         d.setLayerInset(2, 2, 2, 2, 2);
    794         return d;
    795     }
    796 
    797     public boolean isLoading() {
    798         return mActiveTab != null ? mActiveTab.inPageLoad() : false;
    799     }
    800 
    801     /**
    802      * Suggest to the UI that the title bar can be hidden. The UI will then
    803      * decide whether or not to hide based off a number of factors, such
    804      * as if the user is editing the URL bar or if the page is loading
    805      */
    806     public void suggestHideTitleBar() {
    807         if (!isLoading() && !isEditingUrl() && !mTitleBar.wantsToBeVisible()
    808                 && !mNavigationBar.isMenuShowing()) {
    809             hideTitleBar();
    810         }
    811     }
    812 
    813     protected final void showTitleBarForDuration() {
    814         showTitleBarForDuration(HIDE_TITLEBAR_DELAY);
    815     }
    816 
    817     protected final void showTitleBarForDuration(long duration) {
    818         showTitleBar();
    819         Message msg = Message.obtain(mHandler, MSG_HIDE_TITLEBAR);
    820         mHandler.sendMessageDelayed(msg, duration);
    821     }
    822 
    823     protected Handler mHandler = new Handler() {
    824 
    825         @Override
    826         public void handleMessage(Message msg) {
    827             if (msg.what == MSG_HIDE_TITLEBAR) {
    828                 suggestHideTitleBar();
    829             }
    830             BaseUi.this.handleMessage(msg);
    831         }
    832     };
    833 
    834     protected void handleMessage(Message msg) {}
    835 
    836     @Override
    837     public void showWeb(boolean animate) {
    838         mUiController.hideCustomView();
    839     }
    840 
    841     static class FullscreenHolder extends FrameLayout {
    842 
    843         public FullscreenHolder(Context ctx) {
    844             super(ctx);
    845             setBackgroundColor(ctx.getResources().getColor(R.color.black));
    846         }
    847 
    848         @Override
    849         public boolean onTouchEvent(MotionEvent evt) {
    850             return true;
    851         }
    852 
    853     }
    854 
    855     public void addFixedTitleBar(View view) {
    856         mFixedTitlebarContainer.addView(view);
    857     }
    858 
    859     public void setContentViewMarginTop(int margin) {
    860         LinearLayout.LayoutParams params =
    861                 (LinearLayout.LayoutParams) mContentView.getLayoutParams();
    862         if (params.topMargin != margin) {
    863             params.topMargin = margin;
    864             mContentView.setLayoutParams(params);
    865         }
    866     }
    867 
    868     @Override
    869     public boolean blockFocusAnimations() {
    870         return mBlockFocusAnimations;
    871     }
    872 
    873     @Override
    874     public void onVoiceResult(String result) {
    875         mNavigationBar.onVoiceResult(result);
    876     }
    877 
    878 }
    879