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.widget.FrameLayout;
50 import android.widget.ImageButton;
51 import android.widget.LinearLayout;
52 import android.widget.Toast;
53 
54 import com.android.browser.Tab.SecurityState;
55 import com.android.internal.view.menu.MenuBuilder;
56 
57 import java.util.List;
58 
59 /**
60  * UI interface definitions
61  */
62 public abstract class BaseUi implements UI {
63 
64     private static final String LOGTAG = "BaseUi";
65 
66     protected static final FrameLayout.LayoutParams COVER_SCREEN_PARAMS =
67         new FrameLayout.LayoutParams(
68         ViewGroup.LayoutParams.MATCH_PARENT,
69         ViewGroup.LayoutParams.MATCH_PARENT);
70 
71     protected static final FrameLayout.LayoutParams COVER_SCREEN_GRAVITY_CENTER =
72         new FrameLayout.LayoutParams(
73         ViewGroup.LayoutParams.MATCH_PARENT,
74         ViewGroup.LayoutParams.MATCH_PARENT,
75         Gravity.CENTER);
76 
77     private static final int MSG_HIDE_TITLEBAR = 1;
78     public static final int HIDE_TITLEBAR_DELAY = 1500; // in ms
79 
80     Activity mActivity;
81     UiController mUiController;
82     TabControl mTabControl;
83     protected Tab mActiveTab;
84     private InputMethodManager mInputManager;
85 
86     private Drawable mLockIconSecure;
87     private Drawable mLockIconMixed;
88     protected Drawable mGenericFavicon;
89 
90     protected FrameLayout mContentView;
91     protected FrameLayout mCustomViewContainer;
92     protected FrameLayout mFullscreenContainer;
93     private FrameLayout mFixedTitlebarContainer;
94 
95     private View mCustomView;
96     private WebChromeClient.CustomViewCallback mCustomViewCallback;
97     private int mOriginalOrientation;
98 
99     private LinearLayout mErrorConsoleContainer = null;
100 
101     private UrlBarAutoShowManager mUrlBarAutoShowManager;
102 
103     private Toast mStopToast;
104 
105     // the default <video> poster
106     private Bitmap mDefaultVideoPoster;
107     // the video progress view
108     private View mVideoProgressView;
109 
110     private boolean mActivityPaused;
111     protected boolean mUseQuickControls;
112     protected TitleBar mTitleBar;
113     private NavigationBarBase mNavigationBar;
114     protected PieControl mPieControl;
115     private boolean mBlockFocusAnimations;
116 
BaseUi(Activity browser, UiController controller)117     public BaseUi(Activity browser, UiController controller) {
118         mActivity = browser;
119         mUiController = controller;
120         mTabControl = controller.getTabControl();
121         Resources res = mActivity.getResources();
122         mInputManager = (InputMethodManager)
123                 browser.getSystemService(Activity.INPUT_METHOD_SERVICE);
124         mLockIconSecure = res.getDrawable(R.drawable.ic_secure_holo_dark);
125         mLockIconMixed = res.getDrawable(R.drawable.ic_secure_partial_holo_dark);
126         FrameLayout frameLayout = (FrameLayout) mActivity.getWindow()
127                 .getDecorView().findViewById(android.R.id.content);
128         LayoutInflater.from(mActivity)
129                 .inflate(R.layout.custom_screen, frameLayout);
130         mFixedTitlebarContainer = (FrameLayout) frameLayout.findViewById(
131                 R.id.fixed_titlebar_container);
132         mContentView = (FrameLayout) frameLayout.findViewById(
133                 R.id.main_content);
134         mCustomViewContainer = (FrameLayout) frameLayout.findViewById(
135                 R.id.fullscreen_custom_content);
136         mErrorConsoleContainer = (LinearLayout) frameLayout
137                 .findViewById(R.id.error_console);
138         setFullscreen(BrowserSettings.getInstance().useFullscreen());
139         mGenericFavicon = res.getDrawable(
140                 R.drawable.app_web_browser_sm);
141         mTitleBar = new TitleBar(mActivity, mUiController, this,
142                 mContentView);
143         mTitleBar.setProgress(100);
144         mNavigationBar = mTitleBar.getNavigationBar();
145         mUrlBarAutoShowManager = new UrlBarAutoShowManager(this);
146     }
147 
cancelStopToast()148     private void cancelStopToast() {
149         if (mStopToast != null) {
150             mStopToast.cancel();
151             mStopToast = null;
152         }
153     }
154 
155     // lifecycle
156 
onPause()157     public void onPause() {
158         if (isCustomViewShowing()) {
159             onHideCustomView();
160         }
161         cancelStopToast();
162         mActivityPaused = true;
163     }
164 
onResume()165     public void onResume() {
166         mActivityPaused = false;
167         // check if we exited without setting active tab
168         // b: 5188145
169         final Tab ct = mTabControl.getCurrentTab();
170         if (ct != null) {
171             setActiveTab(ct);
172         }
173         mTitleBar.onResume();
174     }
175 
isActivityPaused()176     protected boolean isActivityPaused() {
177         return mActivityPaused;
178     }
179 
onConfigurationChanged(Configuration config)180     public void onConfigurationChanged(Configuration config) {
181     }
182 
getActivity()183     public Activity getActivity() {
184         return mActivity;
185     }
186 
187     // key handling
188 
189     @Override
onBackKey()190     public boolean onBackKey() {
191         if (mCustomView != null) {
192             mUiController.hideCustomView();
193             return true;
194         }
195         return false;
196     }
197 
198     @Override
onMenuKey()199     public boolean onMenuKey() {
200         return false;
201     }
202 
203     @Override
setUseQuickControls(boolean useQuickControls)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
onTabDataChanged(Tab tab)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
onProgressChanged(Tab tab)231     public void onProgressChanged(Tab tab) {
232         int progress = tab.getLoadProgress();
233         if (tab.inForeground()) {
234             mTitleBar.setProgress(progress);
235         }
236     }
237 
238     @Override
bookmarkedStatusHasChanged(Tab tab)239     public void bookmarkedStatusHasChanged(Tab tab) {
240         if (tab.inForeground()) {
241             boolean isBookmark = tab.isBookmarkedSite();
242             mNavigationBar.setCurrentUrlIsBookmark(isBookmark);
243         }
244     }
245 
246     @Override
onPageStopped(Tab tab)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
needsRestoreAllTabs()257     public boolean needsRestoreAllTabs() {
258         return true;
259     }
260 
261     @Override
addTab(Tab tab)262     public void addTab(Tab tab) {
263     }
264 
265     @Override
setActiveTab(final Tab tab)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 
updateUrlBarAutoShowManagerTarget()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 
getActiveTab()312     Tab getActiveTab() {
313         return mActiveTab;
314     }
315 
316     @Override
updateTabs(List<Tab> tabs)317     public void updateTabs(List<Tab> tabs) {
318     }
319 
320     @Override
removeTab(Tab tab)321     public void removeTab(Tab tab) {
322         if (mActiveTab == tab) {
323             removeTabFromContentView(tab);
324             mActiveTab = null;
325         }
326     }
327 
328     @Override
detachTab(Tab tab)329     public void detachTab(Tab tab) {
330         removeTabFromContentView(tab);
331     }
332 
333     @Override
attachTab(Tab tab)334     public void attachTab(Tab tab) {
335         attachTabToContentView(tab);
336     }
337 
attachTabToContentView(Tab tab)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 
removeTabFromContentView(Tab tab)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
onSetWebView(Tab tab, WebView webView)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
createSubWindow(Tab tab, WebView subView)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             @Override
426             public void onClick(View v) {
427                 ((BrowserWebView) cancelSubView).getWebChromeClient().onCloseWindow(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
removeSubWindow(View subviewContainer)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
attachSubWindow(View container)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 
refreshWebView()455     protected void refreshWebView() {
456         WebView web = getWebView();
457         if (web != null) {
458             web.invalidate();
459         }
460     }
461 
editUrl(boolean clearInput, boolean forceIME)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 
canShowTitleBar()472     boolean canShowTitleBar() {
473         return !isTitleBarShowing()
474                 && !isActivityPaused()
475                 && (getActiveTab() != null)
476                 && (getWebView() != null)
477                 && !mUiController.isInCustomActionMode();
478     }
479 
showTitleBar()480     protected void showTitleBar() {
481         mHandler.removeMessages(MSG_HIDE_TITLEBAR);
482         if (canShowTitleBar()) {
483             mTitleBar.show();
484         }
485     }
486 
hideTitleBar()487     protected void hideTitleBar() {
488         if (mTitleBar.isShowing()) {
489             mTitleBar.hide();
490         }
491     }
492 
isTitleBarShowing()493     protected boolean isTitleBarShowing() {
494         return mTitleBar.isShowing();
495     }
496 
isEditingUrl()497     public boolean isEditingUrl() {
498         return mTitleBar.isEditingUrl();
499     }
500 
stopEditingUrl()501     public void stopEditingUrl() {
502         mTitleBar.getNavigationBar().stopEditingUrl();
503     }
504 
getTitleBar()505     public TitleBar getTitleBar() {
506         return mTitleBar;
507     }
508 
509     @Override
showComboView(ComboViews startingView, Bundle extras)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
showCustomView(View view, int requestedOrientation, WebChromeClient.CustomViewCallback callback)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
onHideCustomView()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
isCustomViewShowing()558     public boolean isCustomViewShowing() {
559         return mCustomView != null;
560     }
561 
dismissIME()562     protected void dismissIME() {
563         if (mInputManager.isActive()) {
564             mInputManager.hideSoftInputFromWindow(mContentView.getWindowToken(),
565                     0);
566         }
567     }
568 
569     @Override
isWebShowing()570     public boolean isWebShowing() {
571         return mCustomView == null;
572     }
573 
574     @Override
showAutoLogin(Tab tab)575     public void showAutoLogin(Tab tab) {
576         updateAutoLogin(tab, true);
577     }
578 
579     @Override
hideAutoLogin(Tab tab)580     public void hideAutoLogin(Tab tab) {
581         updateAutoLogin(tab, true);
582     }
583 
584     // -------------------------------------------------------------------------
585 
updateNavigationState(Tab tab)586     protected void updateNavigationState(Tab tab) {
587     }
588 
updateAutoLogin(Tab tab, boolean animate)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      */
updateLockIconToLatest(Tab t)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      */
updateLockIconImage(SecurityState securityState)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 
setUrlTitle(Tab tab)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.
setFavicon(Tab tab)630     protected void setFavicon(Tab tab) {
631         if (tab.inForeground()) {
632             Bitmap icon = tab.getFavicon();
633             mNavigationBar.setFavicon(icon);
634         }
635     }
636 
637     @Override
onActionModeFinished(boolean inLoad)638     public void onActionModeFinished(boolean inLoad) {
639     }
640 
641     // active tabs page
642 
showActiveTabsPage()643     public void showActiveTabsPage() {
644     }
645 
646     /**
647      * Remove the active tabs page.
648      */
removeActiveTabsPage()649     public void removeActiveTabsPage() {
650     }
651 
652     // menu handling callbacks
653 
654     @Override
onPrepareOptionsMenu(Menu menu)655     public boolean onPrepareOptionsMenu(Menu menu) {
656         return true;
657     }
658 
659     @Override
updateMenuState(Tab tab, Menu menu)660     public void updateMenuState(Tab tab, Menu menu) {
661     }
662 
663     @Override
onOptionsMenuOpened()664     public void onOptionsMenuOpened() {
665     }
666 
667     @Override
onExtendedMenuOpened()668     public void onExtendedMenuOpened() {
669     }
670 
671     @Override
onOptionsItemSelected(MenuItem item)672     public boolean onOptionsItemSelected(MenuItem item) {
673         return false;
674     }
675 
676     @Override
onOptionsMenuClosed(boolean inLoad)677     public void onOptionsMenuClosed(boolean inLoad) {
678     }
679 
680     @Override
onExtendedMenuClosed(boolean inLoad)681     public void onExtendedMenuClosed(boolean inLoad) {
682     }
683 
684     @Override
onContextMenuCreated(Menu menu)685     public void onContextMenuCreated(Menu menu) {
686     }
687 
688     @Override
onContextMenuClosed(Menu menu, boolean inLoad)689     public void onContextMenuClosed(Menu menu, boolean inLoad) {
690     }
691 
692     // error console
693 
694     @Override
setShouldShowErrorConsole(Tab tab, boolean flag)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
getDefaultVideoPoster()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
getVideoLoadingProgressView()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
showMaxTabsWarning()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 
getWebView()750     protected WebView getWebView() {
751         if (mActiveTab != null) {
752             return mActiveTab.getWebView();
753         } else {
754             return null;
755         }
756     }
757 
getMenu()758     protected Menu getMenu() {
759         MenuBuilder menu = new MenuBuilder(mActivity);
760         mActivity.getMenuInflater().inflate(R.menu.browser, menu);
761         return menu;
762     }
763 
setFullscreen(boolean enabled)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 
getFaviconDrawable(Bitmap icon)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 
isLoading()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      */
suggestHideTitleBar()806     public void suggestHideTitleBar() {
807         if (!isLoading() && !isEditingUrl() && !mTitleBar.wantsToBeVisible()
808                 && !mNavigationBar.isMenuShowing()) {
809             hideTitleBar();
810         }
811     }
812 
showTitleBarForDuration()813     protected final void showTitleBarForDuration() {
814         showTitleBarForDuration(HIDE_TITLEBAR_DELAY);
815     }
816 
showTitleBarForDuration(long duration)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 
handleMessage(Message msg)834     protected void handleMessage(Message msg) {}
835 
836     @Override
showWeb(boolean animate)837     public void showWeb(boolean animate) {
838         mUiController.hideCustomView();
839     }
840 
841     static class FullscreenHolder extends FrameLayout {
842 
FullscreenHolder(Context ctx)843         public FullscreenHolder(Context ctx) {
844             super(ctx);
845             setBackgroundColor(ctx.getResources().getColor(R.color.black));
846         }
847 
848         @Override
onTouchEvent(MotionEvent evt)849         public boolean onTouchEvent(MotionEvent evt) {
850             return true;
851         }
852 
853     }
854 
addFixedTitleBar(View view)855     public void addFixedTitleBar(View view) {
856         mFixedTitlebarContainer.addView(view);
857     }
858 
setContentViewMarginTop(int margin)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
blockFocusAnimations()869     public boolean blockFocusAnimations() {
870         return mBlockFocusAnimations;
871     }
872 
873     @Override
onVoiceResult(String result)874     public void onVoiceResult(String result) {
875         mNavigationBar.onVoiceResult(result);
876     }
877 
878 }
879