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