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