blob: 6ae6f1babb0abbfd88aade478f092a6ec18ae70c [file] [log] [blame]
Michael Kolb8233fac2010-10-26 16:08:53 -07001/*
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
17package com.android.browser;
18
19import android.app.ActionBar;
20import android.app.Activity;
21import android.content.Context;
22import android.content.res.Configuration;
23import android.content.res.Resources;
24import android.graphics.Bitmap;
25import android.graphics.BitmapFactory;
26import android.graphics.PixelFormat;
27import android.graphics.drawable.Drawable;
28import android.os.Bundle;
29import android.text.TextUtils;
30import android.util.Log;
31import android.view.ActionMode;
32import android.view.Gravity;
33import android.view.LayoutInflater;
34import android.view.Menu;
35import android.view.MenuItem;
36import android.view.View;
Michael Kolb1514bb72010-11-22 09:11:48 -080037import android.view.View.OnClickListener;
Michael Kolb8233fac2010-10-26 16:08:53 -070038import android.view.ViewGroup;
Michael Kolb1514bb72010-11-22 09:11:48 -080039import android.view.ViewGroup.LayoutParams;
Michael Kolb8233fac2010-10-26 16:08:53 -070040import android.view.WindowManager;
41import android.webkit.WebChromeClient;
42import android.webkit.WebHistoryItem;
43import android.webkit.WebView;
44import android.widget.FrameLayout;
Michael Kolb1514bb72010-11-22 09:11:48 -080045import android.widget.ImageButton;
Michael Kolb8233fac2010-10-26 16:08:53 -070046import android.widget.LinearLayout;
47import android.widget.Toast;
48
Michael Kolb1bf23132010-11-19 12:55:12 -080049import java.util.List;
50
Michael Kolb8233fac2010-10-26 16:08:53 -070051/**
52 * UI interface definitions
53 */
54public class BaseUi implements UI, WebViewFactory {
55
56 private static final String LOGTAG = "BaseUi";
57
58 private static final FrameLayout.LayoutParams COVER_SCREEN_PARAMS =
59 new FrameLayout.LayoutParams(
60 ViewGroup.LayoutParams.MATCH_PARENT,
61 ViewGroup.LayoutParams.MATCH_PARENT);
62
63 private static final FrameLayout.LayoutParams COVER_SCREEN_GRAVITY_CENTER =
64 new FrameLayout.LayoutParams(
65 ViewGroup.LayoutParams.MATCH_PARENT,
66 ViewGroup.LayoutParams.MATCH_PARENT,
67 Gravity.CENTER);
68
69 Activity mActivity;
70 UiController mUiController;
71 TabControl mTabControl;
Michael Kolb77df4562010-11-19 14:49:34 -080072 private Tab mActiveTab;
Michael Kolb8233fac2010-10-26 16:08:53 -070073
74 private Drawable mSecLockIcon;
75 private Drawable mMixLockIcon;
76
77 private boolean mXLargeScreenSize;
78 private FrameLayout mBrowserFrameLayout;
79 private FrameLayout mContentView;
80 private FrameLayout mCustomViewContainer;
81 private TitleBarBase mTitleBar;
82 private TitleBarBase mFakeTitleBar;
83 private TabBar mTabBar;
84
85 private View mCustomView;
86 private WebChromeClient.CustomViewCallback mCustomViewCallback;
87
88 private CombinedBookmarkHistoryView mComboView;
89
90 private LinearLayout mErrorConsoleContainer = null;
91
92 private Toast mStopToast;
93 private ActiveTabsPage mActiveTabsPage;
94
95 // the default <video> poster
96 private Bitmap mDefaultVideoPoster;
97 // the video progress view
98 private View mVideoProgressView;
99
100 boolean mExtendedMenuOpen;
101 boolean mOptionsMenuOpen;
102
103 private boolean mActivityPaused;
104
105 public BaseUi(Activity browser, UiController controller) {
106 mActivity = browser;
107 mUiController = controller;
108 mTabControl = controller.getTabControl();
109 Resources res = mActivity.getResources();
110 mSecLockIcon = res.getDrawable(R.drawable.ic_secure);
111 mMixLockIcon = res.getDrawable(R.drawable.ic_partial_secure);
112
113
114 mXLargeScreenSize = (res.getConfiguration().screenLayout
115 & Configuration.SCREENLAYOUT_SIZE_MASK)
116 == Configuration.SCREENLAYOUT_SIZE_XLARGE;
117
118 FrameLayout frameLayout = (FrameLayout) mActivity.getWindow()
119 .getDecorView().findViewById(android.R.id.content);
120 mBrowserFrameLayout = (FrameLayout) LayoutInflater.from(mActivity)
121 .inflate(R.layout.custom_screen, null);
122 mContentView = (FrameLayout) mBrowserFrameLayout.findViewById(
123 R.id.main_content);
124 mErrorConsoleContainer = (LinearLayout) mBrowserFrameLayout
125 .findViewById(R.id.error_console);
126 mCustomViewContainer = (FrameLayout) mBrowserFrameLayout
127 .findViewById(R.id.fullscreen_custom_content);
128 frameLayout.addView(mBrowserFrameLayout, COVER_SCREEN_PARAMS);
129
130 if (mXLargeScreenSize) {
131 mTitleBar = new TitleBarXLarge(mActivity, mUiController);
132 mTitleBar.setProgress(100);
133 mFakeTitleBar = new TitleBarXLarge(mActivity, mUiController);
134 ActionBar actionBar = mActivity.getActionBar();
135 mTabBar = new TabBar(mActivity, mUiController, this);
136 actionBar.setCustomNavigationMode(mTabBar);
137 } else {
138 mTitleBar = new TitleBar(mActivity, mUiController);
139 // mTitleBar will be always be shown in the fully loaded mode on
140 // phone
141 mTitleBar.setProgress(100);
142 mFakeTitleBar = new TitleBar(mActivity, mUiController);
143 }
144 }
145
146 // webview factory
147
148 @Override
149 public WebView createWebView(boolean privateBrowsing) {
150 // Create a new WebView
151 ScrollWebView w = new ScrollWebView(mActivity, null,
152 android.R.attr.webViewStyle, privateBrowsing);
153 w.setScrollbarFadingEnabled(true);
154 w.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);
155 w.setMapTrackballToArrowKeys(false); // use trackball directly
156 // Enable the built-in zoom
157 w.getSettings().setBuiltInZoomControls(true);
158 if (mXLargeScreenSize) {
159 w.setScrollListener(mTabBar);
160 w.getSettings().setDisplayZoomControls(false);
161 }
162
163 // Add this WebView to the settings observer list and update the
164 // settings
165 final BrowserSettings s = BrowserSettings.getInstance();
166 s.addObserver(w.getSettings()).update(s, null);
167 return w;
168 }
169
Michael Kolb1514bb72010-11-22 09:11:48 -0800170 @Override
171 public WebView createSubWebView(boolean privateBrowsing) {
172 ScrollWebView web = (ScrollWebView) createWebView(privateBrowsing);
173 if (mXLargeScreenSize) {
174 // no scroll listener for subview
175 web.setScrollListener(null);
176 }
177 return web;
178 }
179
Michael Kolb8233fac2010-10-26 16:08:53 -0700180 void stopWebViewScrolling() {
181 ScrollWebView web = (ScrollWebView) mUiController.getCurrentWebView();
182 if (web != null) {
183 web.stopScroll();
184 }
185 }
186
187 private void cancelStopToast() {
188 if (mStopToast != null) {
189 mStopToast.cancel();
190 mStopToast = null;
191 }
192 }
193
194 // lifecycle
195
196 public void onPause() {
197 // FIXME: This removes the active tabs page and resets the menu to
198 // MAIN_MENU. A better solution might be to do this work in onNewIntent
199 // but then we would need to save it in onSaveInstanceState and restore
200 // it in onCreate/onRestoreInstanceState
201 if (mActiveTabsPage != null) {
202 mUiController.removeActiveTabsPage(true);
203 }
Michael Kolb7a5cf472010-11-30 13:23:53 -0800204 if (isCustomViewShowing()) {
205 onHideCustomView();
206 }
Michael Kolb8233fac2010-10-26 16:08:53 -0700207 cancelStopToast();
208 mActivityPaused = true;
209 }
210
211 public void onResume() {
212 mActivityPaused = false;
213 }
214
215 public void onDestroy() {
216 hideFakeTitleBar();
217 }
218
219 public void onConfigurationChanged(Configuration config) {
220 }
221
222 // key handling
223
224 @Override
225 public boolean onBackKey() {
226 if (mActiveTabsPage != null) {
227 // if tab page is showing, hide it
228 mUiController.removeActiveTabsPage(true);
229 return true;
230 }
231 if (mComboView != null) {
232 if (!mComboView.onBackPressed()) {
233 mUiController.removeComboView();
234 }
235 return true;
236 }
237 if (mCustomView != null) {
238 mUiController.hideCustomView();
239 return true;
240 }
241 return false;
242 }
243
244 // WebView callbacks
245
246 @Override
247 public void onPageStarted(Tab tab, String url, Bitmap favicon) {
Michael Kolb8233fac2010-10-26 16:08:53 -0700248 if (tab.inForeground()) {
249 resetLockIcon(tab, url);
250 setUrlTitle(tab, url, null);
251 setFavicon(tab, favicon);
252 }
John Reckef074262010-12-02 16:09:14 -0800253 if (mXLargeScreenSize) {
254 mTabBar.onPageStarted(tab, url, favicon);
255 }
Michael Kolb8233fac2010-10-26 16:08:53 -0700256 }
257
258 @Override
Leon Scroggins4cd97792010-12-03 15:31:56 -0500259 public void bookmarkedStatusHasChanged(Tab tab) {
260 if (tab.inForeground() && mXLargeScreenSize) {
261 boolean isBookmark = tab.isBookmarkedSite();
262 ((TitleBarXLarge) mTitleBar).setCurrentUrlIsBookmark(isBookmark);
263 ((TitleBarXLarge) mFakeTitleBar).setCurrentUrlIsBookmark(isBookmark);
264 }
265 }
266
267 @Override
Michael Kolb8233fac2010-10-26 16:08:53 -0700268 public void onPageFinished(Tab tab, String url) {
269 if (mXLargeScreenSize) {
270 mTabBar.onPageFinished(tab);
271 }
272 if (tab.inForeground()) {
273 // Reset the title and icon in case we stopped a provisional load.
274 resetTitleAndIcon(tab);
275 // Update the lock icon image only once we are done loading
276 updateLockIconToLatest(tab);
277 }
278 }
279
280 @Override
281 public void onPageStopped(Tab tab) {
282 cancelStopToast();
283 if (tab.inForeground()) {
284 mStopToast = Toast
285 .makeText(mActivity, R.string.stopping, Toast.LENGTH_SHORT);
286 mStopToast.show();
287 }
288 }
289
290 @Override
291 public void onProgressChanged(Tab tab, int progress) {
292 if (mXLargeScreenSize) {
293 mTabBar.onProgress(tab, progress);
294 }
295 if (tab.inForeground()) {
296 mFakeTitleBar.setProgress(progress);
297 if (progress == 100) {
298 if (!mOptionsMenuOpen || !mExtendedMenuOpen) {
299 hideFakeTitleBar();
300 }
301 } else {
302 if (!mOptionsMenuOpen || mExtendedMenuOpen) {
303 showFakeTitleBar();
304 }
305 }
306 }
307 }
308
309 @Override
Michael Kolb1bf23132010-11-19 12:55:12 -0800310 public boolean needsRestoreAllTabs() {
311 return mXLargeScreenSize;
312 }
313
314 @Override
Michael Kolb8233fac2010-10-26 16:08:53 -0700315 public void addTab(Tab tab) {
316 if (mXLargeScreenSize) {
317 mTabBar.onNewTab(tab);
318 }
319 }
320
321 @Override
322 public void setActiveTab(Tab tab) {
Michael Kolb77df4562010-11-19 14:49:34 -0800323 if ((tab != mActiveTab) && (mActiveTab != null)) {
324 removeTabFromContentView(mActiveTab);
Michael Kolb8233fac2010-10-26 16:08:53 -0700325 }
Michael Kolb77df4562010-11-19 14:49:34 -0800326 mActiveTab = tab;
Michael Kolb8233fac2010-10-26 16:08:53 -0700327 attachTabToContentView(tab);
328 setShouldShowErrorConsole(tab, mUiController.shouldShowErrorConsole());
329
330 WebView view = tab.getWebView();
Michael Kolb77df4562010-11-19 14:49:34 -0800331 // TabControl.setCurrentTab has been called before this,
332 // so the tab is guaranteed to have a webview
333 if (view == null) {
334 Log.e(LOGTAG, "active tab with no webview detected");
335 return;
336 }
Michael Kolb8233fac2010-10-26 16:08:53 -0700337 view.setEmbeddedTitleBar(mTitleBar);
338 if (tab.isInVoiceSearchMode()) {
339 showVoiceTitleBar(tab.getVoiceDisplayTitle());
340 } else {
341 revertVoiceTitleBar(tab);
342 }
343
344 if (mXLargeScreenSize) {
345 // Request focus on the top window.
346 mTabBar.onSetActiveTab(tab);
347 }
Leon Scroggins4cd97792010-12-03 15:31:56 -0500348 bookmarkedStatusHasChanged(tab);
Michael Kolb8233fac2010-10-26 16:08:53 -0700349 resetTitleIconAndProgress(tab);
350 updateLockIconToLatest(tab);
351 tab.getTopWindow().requestFocus();
352 }
353
354 @Override
Michael Kolb1bf23132010-11-19 12:55:12 -0800355 public void updateTabs(List<Tab> tabs) {
356 if (mXLargeScreenSize) {
357 mTabBar.updateTabs(tabs);
358 }
359 }
360
361 @Override
Michael Kolb8233fac2010-10-26 16:08:53 -0700362 public void removeTab(Tab tab) {
Michael Kolb77df4562010-11-19 14:49:34 -0800363 if (mActiveTab == tab) {
Michael Kolb8233fac2010-10-26 16:08:53 -0700364 removeTabFromContentView(tab);
Michael Kolb77df4562010-11-19 14:49:34 -0800365 mActiveTab = null;
Michael Kolb8233fac2010-10-26 16:08:53 -0700366 }
367 if (mXLargeScreenSize) {
368 mTabBar.onRemoveTab(tab);
369 }
370 }
371
372 @Override
373 public void detachTab(Tab tab) {
374 removeTabFromContentView(tab);
375 }
376
377 @Override
378 public void attachTab(Tab tab) {
379 attachTabToContentView(tab);
380 }
381
382 private void attachTabToContentView(Tab tab) {
383 if (tab.getWebView() == null) {
384 return;
385 }
386 View container = tab.getViewContainer();
387 WebView mainView = tab.getWebView();
388 // Attach the WebView to the container and then attach the
389 // container to the content view.
390 FrameLayout wrapper =
391 (FrameLayout) container.findViewById(R.id.webview_wrapper);
392 ViewGroup parent = (ViewGroup) mainView.getParent();
393 if (parent != wrapper) {
394 if (parent != null) {
395 Log.w(LOGTAG, "mMainView already has a parent in"
396 + " attachTabToContentView!");
397 parent.removeView(mainView);
398 }
399 wrapper.addView(mainView);
400 } else {
401 Log.w(LOGTAG, "mMainView is already attached to wrapper in"
402 + " attachTabToContentView!");
403 }
404 parent = (ViewGroup) container.getParent();
405 if (parent != mContentView) {
406 if (parent != null) {
407 Log.w(LOGTAG, "mContainer already has a parent in"
408 + " attachTabToContentView!");
409 parent.removeView(container);
410 }
411 mContentView.addView(container, COVER_SCREEN_PARAMS);
412 } else {
413 Log.w(LOGTAG, "mContainer is already attached to content in"
414 + " attachTabToContentView!");
415 }
416 mUiController.attachSubWindow(tab);
417 }
418
419 private void removeTabFromContentView(Tab tab) {
420 // Remove the container that contains the main WebView.
421 WebView mainView = tab.getWebView();
422 View container = tab.getViewContainer();
423 if (mainView == null) {
424 return;
425 }
426 // Remove the container from the content and then remove the
427 // WebView from the container. This will trigger a focus change
428 // needed by WebView.
429 FrameLayout wrapper =
430 (FrameLayout) container.findViewById(R.id.webview_wrapper);
431 wrapper.removeView(mainView);
432 mContentView.removeView(container);
433 mUiController.endActionMode();
434 mUiController.removeSubWindow(tab);
435 ErrorConsoleView errorConsole = tab.getErrorConsole(false);
436 if (errorConsole != null) {
437 mErrorConsoleContainer.removeView(errorConsole);
438 }
439 mainView.setEmbeddedTitleBar(null);
440 }
441
Michael Kolba713ec82010-11-29 17:27:06 -0800442 @Override
443 public void onSetWebView(Tab tab, WebView webView) {
444 View container = tab.getViewContainer();
445 if (container == null) {
446 // The tab consists of a container view, which contains the main
447 // WebView, as well as any other UI elements associated with the tab.
448 container = mActivity.getLayoutInflater().inflate(R.layout.tab,
449 null);
450 tab.setViewContainer(container);
451 }
452 if (tab.getWebView() != webView) {
453 // Just remove the old one.
454 FrameLayout wrapper =
455 (FrameLayout) container.findViewById(R.id.webview_wrapper);
456 wrapper.removeView(tab.getWebView());
457 }
458 }
459
Michael Kolb8233fac2010-10-26 16:08:53 -0700460 /**
Michael Kolb1514bb72010-11-22 09:11:48 -0800461 * create a sub window container and webview for the tab
462 * Note: this methods operates through side-effects for now
463 * it sets both the subView and subViewContainer for the given tab
464 * @param tab tab to create the sub window for
465 * @param subView webview to be set as a subwindow for the tab
466 */
467 @Override
468 public void createSubWindow(Tab tab, WebView subView) {
469 View subViewContainer = mActivity.getLayoutInflater().inflate(
470 R.layout.browser_subwindow, null);
471 ViewGroup inner = (ViewGroup) subViewContainer
472 .findViewById(R.id.inner_container);
473 inner.addView(subView, new LayoutParams(LayoutParams.MATCH_PARENT,
474 LayoutParams.MATCH_PARENT));
475 final ImageButton cancel = (ImageButton) subViewContainer
476 .findViewById(R.id.subwindow_close);
477 final WebView cancelSubView = subView;
478 cancel.setOnClickListener(new OnClickListener() {
479 public void onClick(View v) {
480 cancelSubView.getWebChromeClient().onCloseWindow(cancelSubView);
481 }
482 });
483 tab.setSubWebView(subView);
484 tab.setSubViewContainer(subViewContainer);
485 }
486
487 /**
Michael Kolb8233fac2010-10-26 16:08:53 -0700488 * Remove the sub window from the content view.
489 */
490 @Override
491 public void removeSubWindow(View subviewContainer) {
492 mContentView.removeView(subviewContainer);
493 mUiController.endActionMode();
494 }
495
496 /**
497 * Attach the sub window to the content view.
498 */
499 @Override
500 public void attachSubWindow(View container) {
Michael Kolb1514bb72010-11-22 09:11:48 -0800501 if (container.getParent() != null) {
502 // already attached, remove first
503 ((ViewGroup) container.getParent()).removeView(container);
504 }
Michael Kolb8233fac2010-10-26 16:08:53 -0700505 mContentView.addView(container, COVER_SCREEN_PARAMS);
506 }
507
508 void showFakeTitleBar() {
509 if (!isFakeTitleBarShowing() && mActiveTabsPage == null &&
510 !mActivityPaused) {
511 WebView mainView = mUiController.getCurrentWebView();
512 // if there is no current WebView, don't show the faked title bar;
513 if (mainView == null) {
514 return;
515 }
516 // Do not need to check for null, since the current tab will have
517 // at least a main WebView, or we would have returned above.
518 if (mUiController.isInCustomActionMode()) {
519 // Do not show the fake title bar, while a custom ActionMode
520 // (i.e. find or select) is showing.
521 return;
522 }
523 if (mXLargeScreenSize) {
524 mContentView.addView(mFakeTitleBar);
525 mTabBar.onShowTitleBar();
526 } else {
527 WindowManager manager = (WindowManager)
528 mActivity.getSystemService(Context.WINDOW_SERVICE);
529
530 // Add the title bar to the window manager so it can receive
531 // touches
532 // while the menu is up
533 WindowManager.LayoutParams params =
534 new WindowManager.LayoutParams(
535 ViewGroup.LayoutParams.MATCH_PARENT,
536 ViewGroup.LayoutParams.WRAP_CONTENT,
537 WindowManager.LayoutParams.TYPE_APPLICATION,
538 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
539 PixelFormat.TRANSLUCENT);
540 params.gravity = Gravity.TOP;
541 boolean atTop = mainView.getScrollY() == 0;
542 params.windowAnimations = atTop ? 0 : R.style.TitleBar;
543 manager.addView(mFakeTitleBar, params);
544 }
545 }
546 }
547
548 void hideFakeTitleBar() {
549 if (!isFakeTitleBarShowing()) return;
550 if (mXLargeScreenSize) {
551 mContentView.removeView(mFakeTitleBar);
552 mTabBar.onHideTitleBar();
553 } else {
554 WindowManager.LayoutParams params =
555 (WindowManager.LayoutParams) mFakeTitleBar.getLayoutParams();
556 WebView mainView = mUiController.getCurrentWebView();
557 // Although we decided whether or not to animate based on the
558 // current
559 // scroll position, the scroll position may have changed since the
560 // fake title bar was displayed. Make sure it has the appropriate
561 // animation/lack thereof before removing.
562 params.windowAnimations =
563 mainView != null && mainView.getScrollY() == 0 ?
564 0 : R.style.TitleBar;
565 WindowManager manager = (WindowManager) mActivity
566 .getSystemService(Context.WINDOW_SERVICE);
567 manager.updateViewLayout(mFakeTitleBar, params);
568 manager.removeView(mFakeTitleBar);
569 }
570 }
571
572 boolean isFakeTitleBarShowing() {
573 return (mFakeTitleBar.getParent() != null);
574 }
575
576 @Override
577 public void showComboView(boolean startWithHistory, Bundle extras) {
578 mComboView = new CombinedBookmarkHistoryView(mActivity,
579 mUiController,
580 startWithHistory ?
581 CombinedBookmarkHistoryView.FRAGMENT_ID_HISTORY
582 : CombinedBookmarkHistoryView.FRAGMENT_ID_BOOKMARKS,
583 extras);
584 mTitleBar.setVisibility(View.GONE);
585 hideFakeTitleBar();
586 mContentView.addView(mComboView, COVER_SCREEN_PARAMS);
587 }
588
589 /**
590 * dismiss the ComboPage
591 */
592 @Override
593 public void hideComboView() {
594 if (mComboView != null) {
595 mContentView.removeView(mComboView);
596 mTitleBar.setVisibility(View.VISIBLE);
597 mComboView = null;
598 }
599 }
600
601 @Override
602 public void showCustomView(View view,
603 WebChromeClient.CustomViewCallback callback) {
604 // if a view already exists then immediately terminate the new one
605 if (mCustomView != null) {
606 callback.onCustomViewHidden();
607 return;
608 }
609
610 // Add the custom view to its container.
611 mCustomViewContainer.addView(view, COVER_SCREEN_GRAVITY_CENTER);
612 mCustomView = view;
613 mCustomViewCallback = callback;
614 // Hide the content view.
615 mContentView.setVisibility(View.GONE);
616 // Finally show the custom view container.
617 setStatusBarVisibility(false);
618 mCustomViewContainer.setVisibility(View.VISIBLE);
619 mCustomViewContainer.bringToFront();
620 }
621
622 @Override
623 public void onHideCustomView() {
624 if (mCustomView == null)
625 return;
626
627 // Hide the custom view.
628 mCustomView.setVisibility(View.GONE);
629 // Remove the custom view from its container.
630 mCustomViewContainer.removeView(mCustomView);
631 mCustomView = null;
632 mCustomViewContainer.setVisibility(View.GONE);
633 mCustomViewCallback.onCustomViewHidden();
634 // Show the content view.
635 setStatusBarVisibility(true);
636 mContentView.setVisibility(View.VISIBLE);
637 }
638
639 @Override
640 public boolean isCustomViewShowing() {
641 return mCustomView != null;
642 }
643
644 @Override
645 public void showVoiceTitleBar(String title) {
646 mTitleBar.setInVoiceMode(true);
647 mTitleBar.setDisplayTitle(title);
648 mFakeTitleBar.setInVoiceMode(true);
649 mFakeTitleBar.setDisplayTitle(title);
650 }
651
652 @Override
653 public void revertVoiceTitleBar(Tab tab) {
654 mTitleBar.setInVoiceMode(false);
655 String url = tab.getCurrentUrl();
656 mTitleBar.setDisplayTitle(url);
657 mFakeTitleBar.setInVoiceMode(false);
658 mFakeTitleBar.setDisplayTitle(url);
659 }
660
661 // -------------------------------------------------------------------------
662
663 @Override
664 public void resetTitleAndRevertLockIcon(Tab tab) {
665 tab.revertLockIcon();
666 updateLockIconToLatest(tab);
667 resetTitleIconAndProgress(tab);
668 }
669
670 /**
671 * Resets the lock icon. This method is called when we start a new load and
672 * know the url to be loaded.
673 */
674 private void resetLockIcon(Tab tab, String url) {
675 // Save the lock-icon state (we revert to it if the load gets cancelled)
676 tab.resetLockIcon(url);
677 updateLockIconImage(Tab.LOCK_ICON_UNSECURE);
678 }
679
680 /**
681 * Update the lock icon to correspond to our latest state.
682 */
683 private void updateLockIconToLatest(Tab t) {
684 if (t != null) {
685 updateLockIconImage(t.getLockIconType());
686 }
687 }
688
689 /**
690 * Reset the title, favicon, and progress.
691 */
692 private void resetTitleIconAndProgress(Tab tab) {
693 WebView current = tab.getWebView();
694 if (current == null) {
695 return;
696 }
Michael Kolb41d3b942010-12-05 11:35:20 -0800697 resetTitleAndIcon(tab, current);
Michael Kolb8233fac2010-10-26 16:08:53 -0700698 int progress = current.getProgress();
699 current.getWebChromeClient().onProgressChanged(current, progress);
700 }
701
702 @Override
703 public void resetTitleAndIcon(Tab tab) {
704 WebView current = tab.getWebView();
705 if (current != null) {
Michael Kolb41d3b942010-12-05 11:35:20 -0800706 resetTitleAndIcon(tab, current);
Michael Kolb8233fac2010-10-26 16:08:53 -0700707 }
708 }
709
710 // Reset the title and the icon based on the given item.
Michael Kolb41d3b942010-12-05 11:35:20 -0800711 private void resetTitleAndIcon(Tab tab, WebView view) {
Michael Kolb8233fac2010-10-26 16:08:53 -0700712 WebHistoryItem item = view.copyBackForwardList().getCurrentItem();
Michael Kolb8233fac2010-10-26 16:08:53 -0700713 if (item != null) {
714 setUrlTitle(tab, item.getUrl(), item.getTitle());
715 setFavicon(tab, item.getFavicon());
716 } else {
John Reckef074262010-12-02 16:09:14 -0800717 setUrlTitle(tab, null, mActivity.getString(R.string.new_tab));
Michael Kolb8233fac2010-10-26 16:08:53 -0700718 setFavicon(tab, null);
719 }
720 }
721
722 /**
723 * Updates the lock-icon image in the title-bar.
724 */
725 private void updateLockIconImage(int lockIconType) {
726 Drawable d = null;
727 if (lockIconType == Tab.LOCK_ICON_SECURE) {
728 d = mSecLockIcon;
729 } else if (lockIconType == Tab.LOCK_ICON_MIXED) {
730 d = mMixLockIcon;
731 }
732 mTitleBar.setLock(d);
733 mFakeTitleBar.setLock(d);
734 }
735
736 // active tabs page
737
738 public void showActiveTabsPage() {
739 mActiveTabsPage = new ActiveTabsPage(mActivity, mUiController);
740 mTitleBar.setVisibility(View.GONE);
741 hideFakeTitleBar();
742 mContentView.addView(mActiveTabsPage, COVER_SCREEN_PARAMS);
743 mActiveTabsPage.requestFocus();
744 }
745
746 /**
747 * Remove the active tabs page.
748 * @param needToAttach If true, the active tabs page did not attach a tab
749 * to the content view, so we need to do that here.
750 */
751 public void removeActiveTabsPage() {
752 mContentView.removeView(mActiveTabsPage);
753 mTitleBar.setVisibility(View.VISIBLE);
754 mActiveTabsPage = null;
755 }
756
757 // action mode callbacks
758
759 @Override
760 public void onActionModeStarted(ActionMode mode) {
761 // hide the fake title bar when CAB is shown
762 hideFakeTitleBar();
763 }
764
765 @Override
766 public void onActionModeFinished(boolean inLoad) {
767 if (inLoad) {
768 // the titlebar was removed when the CAB was shown
769 // if the page is loading, show it again
770 showFakeTitleBar();
771 }
772 }
773
774 // menu handling callbacks
775
776 @Override
777 public void onOptionsMenuOpened() {
778 mOptionsMenuOpen = true;
779 // options menu opened, show fake title bar
780 showFakeTitleBar();
781 }
782
783 @Override
784 public void onExtendedMenuOpened() {
785 // Switching the menu to expanded view, so hide the
786 // title bar.
787 mExtendedMenuOpen = true;
788 hideFakeTitleBar();
789 }
790
791 @Override
792 public void onOptionsMenuClosed(boolean inLoad) {
793 mOptionsMenuOpen = false;
794 if (!inLoad) {
795 hideFakeTitleBar();
796 }
797 }
798
799 @Override
800 public void onExtendedMenuClosed(boolean inLoad) {
801 mExtendedMenuOpen = false;
802 if (inLoad) {
803 showFakeTitleBar();
804 }
805 }
806
807 @Override
808 public void onContextMenuCreated(Menu menu) {
809 hideFakeTitleBar();
810 }
811
812 @Override
813 public void onContextMenuClosed(Menu menu, boolean inLoad) {
814 if (inLoad) {
815 showFakeTitleBar();
816 }
817 }
818
819 @Override
820 public void onScroll(boolean titleVisible) {
821 if (mTabBar != null) {
822 mTabBar.onScroll(titleVisible);
823 }
824 }
825
826 // error console
827
828 @Override
829 public void setShouldShowErrorConsole(Tab tab, boolean flag) {
830 ErrorConsoleView errorConsole = tab.getErrorConsole(true);
831 if (flag) {
832 // Setting the show state of the console will cause it's the layout
833 // to be inflated.
834 if (errorConsole.numberOfErrors() > 0) {
835 errorConsole.showConsole(ErrorConsoleView.SHOW_MINIMIZED);
836 } else {
837 errorConsole.showConsole(ErrorConsoleView.SHOW_NONE);
838 }
839 if (errorConsole.getParent() != null) {
840 mErrorConsoleContainer.removeView(errorConsole);
841 }
842 // Now we can add it to the main view.
843 mErrorConsoleContainer.addView(errorConsole,
844 new LinearLayout.LayoutParams(
845 ViewGroup.LayoutParams.MATCH_PARENT,
846 ViewGroup.LayoutParams.WRAP_CONTENT));
847 } else {
848 mErrorConsoleContainer.removeView(errorConsole);
849 }
850 }
851
852 private void setStatusBarVisibility(boolean visible) {
853 int flag = visible ? 0 : WindowManager.LayoutParams.FLAG_FULLSCREEN;
854 mActivity.getWindow().setFlags(flag,
855 WindowManager.LayoutParams.FLAG_FULLSCREEN);
856 }
857
858 @Override
859 public void setUrlTitle(Tab tab, String url, String title) {
860 if (TextUtils.isEmpty(title)) {
John Reckef074262010-12-02 16:09:14 -0800861 title = url;
Michael Kolb8233fac2010-10-26 16:08:53 -0700862 }
863 if (tab.isInVoiceSearchMode()) return;
864 if (tab.inForeground()) {
865 mTitleBar.setDisplayTitle(url);
866 mFakeTitleBar.setDisplayTitle(url);
867 }
868 if (mXLargeScreenSize) {
869 mTabBar.onUrlAndTitle(tab, url, title);
870 }
871 }
872
873 // Set the favicon in the title bar.
874 @Override
875 public void setFavicon(Tab tab, Bitmap icon) {
876 mTitleBar.setFavicon(icon);
877 mFakeTitleBar.setFavicon(icon);
878 if (mXLargeScreenSize) {
879 mTabBar.onFavicon(tab, icon);
880 }
881 }
882 @Override
883 public boolean showsWeb() {
884 return mCustomView == null && mActiveTabsPage == null
885 && mComboView == null;
886 }
887
888 @Override
889 public void onPrepareOptionsMenu(Menu menu) {
890 if (!mXLargeScreenSize) {
891 final MenuItem newtab = menu.findItem(R.id.new_tab_menu_id);
892 newtab.setEnabled(mUiController.getTabControl().canCreateNewTab());
893 }
894 }
895
896 // -------------------------------------------------------------------------
897 // Helper function for WebChromeClient
898 // -------------------------------------------------------------------------
899
900 @Override
901 public Bitmap getDefaultVideoPoster() {
902 if (mDefaultVideoPoster == null) {
903 mDefaultVideoPoster = BitmapFactory.decodeResource(
904 mActivity.getResources(), R.drawable.default_video_poster);
905 }
906 return mDefaultVideoPoster;
907 }
908
909 @Override
910 public View getVideoLoadingProgressView() {
911 if (mVideoProgressView == null) {
912 LayoutInflater inflater = LayoutInflater.from(mActivity);
913 mVideoProgressView = inflater.inflate(
914 R.layout.video_loading_progress, null);
915 }
916 return mVideoProgressView;
917 }
918
919}