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