OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.chrome.browser; |
| 6 |
| 7 import android.app.Activity; |
| 8 import android.content.Intent; |
| 9 import android.graphics.Bitmap; |
| 10 import android.graphics.Color; |
| 11 import android.os.Bundle; |
| 12 import android.os.Process; |
| 13 import android.os.SystemClock; |
| 14 import android.support.v7.app.AlertDialog; |
| 15 import android.util.Log; |
| 16 import android.view.View; |
| 17 import android.view.ViewGroup; |
| 18 import android.view.ViewStub; |
| 19 import android.view.ViewTreeObserver; |
| 20 import android.view.ViewTreeObserver.OnPreDrawListener; |
| 21 |
| 22 import com.google.android.apps.chrome.R; |
| 23 |
| 24 import org.chromium.base.ApiCompatibilityUtils; |
| 25 import org.chromium.base.CommandLine; |
| 26 import org.chromium.base.TraceEvent; |
| 27 import org.chromium.base.VisibleForTesting; |
| 28 import org.chromium.base.metrics.RecordHistogram; |
| 29 import org.chromium.base.metrics.RecordUserAction; |
| 30 import org.chromium.chrome.browser.BookmarksBridge.BookmarkModelObserver; |
| 31 import org.chromium.chrome.browser.appmenu.AppMenuHandler; |
| 32 import org.chromium.chrome.browser.bookmark.ManageBookmarkActivity; |
| 33 import org.chromium.chrome.browser.compositor.CompositorViewHolder; |
| 34 import org.chromium.chrome.browser.compositor.layouts.Layout; |
| 35 import org.chromium.chrome.browser.compositor.layouts.LayoutManager; |
| 36 import org.chromium.chrome.browser.compositor.layouts.LayoutManagerDocument; |
| 37 import org.chromium.chrome.browser.compositor.layouts.SceneChangeObserver; |
| 38 import org.chromium.chrome.browser.compositor.layouts.content.ContentOffsetProvi
der; |
| 39 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; |
| 40 import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial; |
| 41 import org.chromium.chrome.browser.contextualsearch.ContextualSearchManager; |
| 42 import org.chromium.chrome.browser.contextualsearch.ContextualSearchManager.Cont
extualSearchTabPromotionDelegate; |
| 43 import org.chromium.chrome.browser.device.DeviceClassManager; |
| 44 import org.chromium.chrome.browser.dom_distiller.DistilledPagePrefsView; |
| 45 import org.chromium.chrome.browser.dom_distiller.ReaderModeActivityDelegate; |
| 46 import org.chromium.chrome.browser.dom_distiller.ReaderModeManager; |
| 47 import org.chromium.chrome.browser.enhanced_bookmarks.EnhancedBookmarksModel; |
| 48 import org.chromium.chrome.browser.enhancedbookmarks.EnhancedBookmarkUtils; |
| 49 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; |
| 50 import org.chromium.chrome.browser.help.HelpAndFeedback; |
| 51 import org.chromium.chrome.browser.preferences.PrefServiceBridge; |
| 52 import org.chromium.chrome.browser.preferences.PreferencesLauncher; |
| 53 import org.chromium.chrome.browser.printing.TabPrinter; |
| 54 import org.chromium.chrome.browser.snackbar.SnackbarManager; |
| 55 import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarManageable; |
| 56 import org.chromium.chrome.browser.tabmodel.ChromeTabCreator; |
| 57 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; |
| 58 import org.chromium.chrome.browser.tabmodel.TabModelSelector; |
| 59 import org.chromium.chrome.browser.util.FeatureUtilities; |
| 60 import org.chromium.chrome.browser.webapps.AddToHomescreenDialog; |
| 61 import org.chromium.chrome.browser.widget.ControlContainer; |
| 62 import org.chromium.components.bookmarks.BookmarkId; |
| 63 import org.chromium.components.bookmarks.BookmarkType; |
| 64 import org.chromium.content.browser.ContentReadbackHandler; |
| 65 import org.chromium.content.browser.ContentReadbackHandler.GetBitmapCallback; |
| 66 import org.chromium.content.browser.ContentViewCore; |
| 67 import org.chromium.content_public.browser.LoadUrlParams; |
| 68 import org.chromium.content_public.browser.readback_types.ReadbackResponse; |
| 69 import org.chromium.printing.PrintManagerDelegateImpl; |
| 70 import org.chromium.printing.PrintingController; |
| 71 import org.chromium.ui.base.DeviceFormFactor; |
| 72 import org.chromium.ui.base.PageTransition; |
| 73 import org.chromium.ui.base.WindowAndroid; |
| 74 |
| 75 import java.util.Locale; |
| 76 import java.util.concurrent.TimeUnit; |
| 77 |
| 78 /** |
| 79 * A {@link ChromeActivity} that builds and manages a {@link CompositorViewHolde
r} and associated |
| 80 * classes. |
| 81 */ |
| 82 public abstract class CompositorChromeActivity extends ChromeActivity |
| 83 implements ContextualSearchTabPromotionDelegate, SnackbarManageable, Sce
neChangeObserver { |
| 84 /** |
| 85 * No control container to inflate during initialization. |
| 86 */ |
| 87 private static final int NO_CONTROL_CONTAINER = -1; |
| 88 |
| 89 private static final String TAG = "CompositorChromeActivity"; |
| 90 |
| 91 private WindowAndroid mWindowAndroid; |
| 92 private ChromeFullscreenManager mFullscreenManager; |
| 93 private CompositorViewHolder mCompositorViewHolder; |
| 94 private ContextualSearchManager mContextualSearchManager; |
| 95 private ReaderModeActivityDelegate mReaderModeActivityDelegate; |
| 96 private SnackbarManager mSnackbarManager; |
| 97 |
| 98 // Time in ms that it took took us to inflate the initial layout |
| 99 private long mInflateInitialLayoutDurationMs; |
| 100 |
| 101 private OnPreDrawListener mFirstDrawListener; |
| 102 |
| 103 private final Locale mCurrentLocale = Locale.getDefault(); |
| 104 |
| 105 @Override |
| 106 public void postInflationStartup() { |
| 107 mWindowAndroid = new ChromeWindow(this); |
| 108 mWindowAndroid.restoreInstanceState(getSavedInstanceState()); |
| 109 mSnackbarManager = new SnackbarManager(findViewById(android.R.id.content
)); |
| 110 super.postInflationStartup(); |
| 111 |
| 112 // Set up the animation placeholder to be the SurfaceView. This disables
the |
| 113 // SurfaceView's 'hole' clipping during animations that are notified to
the window. |
| 114 mWindowAndroid.setAnimationPlaceholderView(mCompositorViewHolder.getSurf
aceView()); |
| 115 |
| 116 // Inform the WindowAndroid of the keyboard accessory view. |
| 117 mWindowAndroid.setKeyboardAccessoryView((ViewGroup) findViewById(R.id.ke
yboard_accessory)); |
| 118 final View controlContainer = findViewById(R.id.control_container); |
| 119 if (controlContainer != null) { |
| 120 mFirstDrawListener = new ViewTreeObserver.OnPreDrawListener() { |
| 121 @Override |
| 122 public boolean onPreDraw() { |
| 123 controlContainer.getViewTreeObserver() |
| 124 .removeOnPreDrawListener(mFirstDrawListener); |
| 125 mFirstDrawListener = null; |
| 126 onFirstDrawComplete(); |
| 127 return true; |
| 128 } |
| 129 }; |
| 130 controlContainer.getViewTreeObserver().addOnPreDrawListener(mFirstDr
awListener); |
| 131 } |
| 132 } |
| 133 |
| 134 /** |
| 135 * This function builds the {@link CompositorViewHolder}. Subclasses *must*
call |
| 136 * super.setContentView() before using {@link #getTabModelSelector()} or |
| 137 * {@link #getCompositorViewHolder()}. |
| 138 */ |
| 139 @Override |
| 140 protected final void setContentView() { |
| 141 final long begin = SystemClock.elapsedRealtime(); |
| 142 TraceEvent.begin("onCreate->setContentView()"); |
| 143 if (WarmupManager.getInstance().hasBuiltViewHierarchy()) { |
| 144 View placeHolderView = new View(this); |
| 145 setContentView(placeHolderView); |
| 146 ViewGroup contentParent = (ViewGroup) placeHolderView.getParent(); |
| 147 WarmupManager.getInstance().transferViewHierarchyTo(contentParent); |
| 148 contentParent.removeView(placeHolderView); |
| 149 } else { |
| 150 setContentView(R.layout.main); |
| 151 if (getControlContainerLayoutId() != NO_CONTROL_CONTAINER) { |
| 152 ViewStub toolbarContainerStub = |
| 153 ((ViewStub) findViewById(R.id.control_container_stub)); |
| 154 toolbarContainerStub.setLayoutResource(getControlContainerLayout
Id()); |
| 155 toolbarContainerStub.inflate(); |
| 156 } |
| 157 } |
| 158 TraceEvent.end("onCreate->setContentView()"); |
| 159 mInflateInitialLayoutDurationMs = SystemClock.elapsedRealtime() - begin; |
| 160 |
| 161 // Set the status bar color to black by default. This is an optimization
for |
| 162 // Chrome not to draw under status and navigation bars when we use the d
efault |
| 163 // black status bar |
| 164 ApiCompatibilityUtils.setStatusBarColor(getWindow(), Color.BLACK); |
| 165 |
| 166 mCompositorViewHolder = (CompositorViewHolder) findViewById(R.id.composi
tor_view_holder); |
| 167 mCompositorViewHolder.setRootView(getWindow().getDecorView().getRootView
()); |
| 168 } |
| 169 |
| 170 /** |
| 171 * @return The resource id for the layout to use for {@link ControlContainer
}. 0 by default. |
| 172 */ |
| 173 protected int getControlContainerLayoutId() { |
| 174 return NO_CONTROL_CONTAINER; |
| 175 } |
| 176 |
| 177 /** |
| 178 * @return Whether contextual search is allowed for this activity or not. |
| 179 */ |
| 180 protected boolean isContextualSearchAllowed() { |
| 181 return true; |
| 182 } |
| 183 |
| 184 @Override |
| 185 public void initializeCompositor() { |
| 186 TraceEvent.begin("CompositorChromeActivity:CompositorInitialization"); |
| 187 super.initializeCompositor(); |
| 188 |
| 189 setTabContentManager(new TabContentManager(this, getContentOffsetProvide
r(), |
| 190 DeviceClassManager.enableSnapshots())); |
| 191 mCompositorViewHolder.onNativeLibraryReady(mWindowAndroid, getTabContent
Manager()); |
| 192 |
| 193 if (isContextualSearchAllowed() && ContextualSearchFieldTrial.isEnabled(
this) |
| 194 && !DeviceFormFactor.isTablet(this)) { |
| 195 mContextualSearchManager = new ContextualSearchManager(this, mWindow
Android, this); |
| 196 } |
| 197 |
| 198 if (ReaderModeManager.isEnabled(this)) { |
| 199 mReaderModeActivityDelegate = new ReaderModeActivityDelegate(this); |
| 200 } |
| 201 |
| 202 TraceEvent.end("CompositorChromeActivity:CompositorInitialization"); |
| 203 } |
| 204 |
| 205 @Override |
| 206 public void onStartWithNative() { |
| 207 super.onStartWithNative(); |
| 208 mCompositorViewHolder.resetFlags(); |
| 209 } |
| 210 |
| 211 @Override |
| 212 protected void onDeferredStartup() { |
| 213 super.onDeferredStartup(); |
| 214 RecordHistogram.recordTimesHistogram("MobileStartup.ToolbarInflationTime
", |
| 215 mInflateInitialLayoutDurationMs, TimeUnit.MILLISECONDS); |
| 216 } |
| 217 |
| 218 @Override |
| 219 public void onStart() { |
| 220 super.onStart(); |
| 221 if (mCompositorViewHolder != null) mCompositorViewHolder.onStart(); |
| 222 } |
| 223 |
| 224 @Override |
| 225 public void onStop() { |
| 226 super.onStop(); |
| 227 if (mCompositorViewHolder != null) mCompositorViewHolder.onStop(); |
| 228 } |
| 229 |
| 230 @Override |
| 231 public void onPause() { |
| 232 super.onPause(); |
| 233 if (mSnackbarManager != null) mSnackbarManager.dismissSnackbar(false); |
| 234 } |
| 235 |
| 236 @Override |
| 237 public long getOnCreateTimestampMs() { |
| 238 return super.getOnCreateTimestampMs(); |
| 239 } |
| 240 |
| 241 /** |
| 242 * This cannot be overridden in order to preserve destruction order. Overri
de |
| 243 * {@link #onDestroyInternal()} instead to perform clean up tasks. |
| 244 */ |
| 245 @Override |
| 246 protected final void onDestroy() { |
| 247 if (mReaderModeActivityDelegate != null) mReaderModeActivityDelegate.des
troy(); |
| 248 if (mContextualSearchManager != null) mContextualSearchManager.destroy()
; |
| 249 if (mCompositorViewHolder != null) { |
| 250 if (mCompositorViewHolder.getLayoutManager() != null) { |
| 251 mCompositorViewHolder.getLayoutManager().removeSceneChangeObserv
er(this); |
| 252 } |
| 253 mCompositorViewHolder.shutDown(); |
| 254 } |
| 255 onDestroyInternal(); |
| 256 |
| 257 TabModelSelector selector = getTabModelSelector(); |
| 258 if (selector != null) selector.destroy(); |
| 259 |
| 260 if (mWindowAndroid != null) mWindowAndroid.destroy(); |
| 261 if (!Locale.getDefault().equals(mCurrentLocale)) { |
| 262 // This is a hack to relaunch renderer processes. Killing the main p
rocess also kills |
| 263 // its dependent (renderer) processes, and Android's activity manage
r service seems to |
| 264 // still relaunch the activity even when process dies in onDestroy()
. |
| 265 // This shouldn't be moved to ChromeActivity since it may cause a cr
ash if |
| 266 // you kill the process from EmbedContentViewActivity since Preferen
ces looks up |
| 267 // ChildAccountManager#hasChildAccount() when it is not set. |
| 268 // TODO(changwan): Implement a more generic and safe relaunch mechan
ism such as |
| 269 // killing dependent processes on onDestroy and launching them at on
Create(). |
| 270 Log.w(TAG, "Forcefully killing process..."); |
| 271 Process.killProcess(Process.myPid()); |
| 272 } |
| 273 super.onDestroy(); |
| 274 } |
| 275 |
| 276 /** |
| 277 * Override this to perform destruction tasks. Note that by the time this i
s called, the |
| 278 * {@link CompositorViewHolder} will be destroyed, but the {@link WindowAndr
oid} and |
| 279 * {@link TabModelSelector} will not. |
| 280 * <p> |
| 281 * After returning from this, the {@link TabModelSelector} will be destroyed
followed |
| 282 * by the {@link WindowAndroid}. |
| 283 */ |
| 284 protected void onDestroyInternal() { |
| 285 } |
| 286 |
| 287 /** |
| 288 * This will handle passing {@link Intent} results back to the {@link Window
Android}. It will |
| 289 * return whether or not the {@link WindowAndroid} has consumed the event or
not. |
| 290 */ |
| 291 @Override |
| 292 public boolean onActivityResultWithNative(int requestCode, int resultCode, I
ntent intent) { |
| 293 if (super.onActivityResultWithNative(requestCode, resultCode, intent)) r
eturn true; |
| 294 return mWindowAndroid.onActivityResult(requestCode, resultCode, intent); |
| 295 } |
| 296 |
| 297 @Override |
| 298 protected void onSaveInstanceState(Bundle outState) { |
| 299 super.onSaveInstanceState(outState); |
| 300 mWindowAndroid.saveInstanceState(outState); |
| 301 } |
| 302 |
| 303 /** |
| 304 * @return The unified manager for all snackbar related operations. |
| 305 */ |
| 306 @Override |
| 307 public SnackbarManager getSnackbarManager() { |
| 308 return mSnackbarManager; |
| 309 } |
| 310 |
| 311 /** |
| 312 * Add the specified tab to bookmarks or allows to edit the bookmark if the
specified tab is |
| 313 * already bookmarked. If a new bookmark is added, a snackbar will be shown. |
| 314 * @param tabToBookmark The tab that needs to be bookmarked. |
| 315 */ |
| 316 public void addOrEditBookmark(final Tab tabToBookmark) { |
| 317 if (tabToBookmark == null || tabToBookmark.isFrozen()) { |
| 318 return; |
| 319 } |
| 320 |
| 321 // Managed bookmarks can't be edited. If the current URL is only bookmar
ked by managed |
| 322 // bookmarks then fall back on adding a new bookmark instead. |
| 323 final long bookmarkId = tabToBookmark.getUserBookmarkId(); |
| 324 |
| 325 if (EnhancedBookmarkUtils.isEnhancedBookmarkEnabled(tabToBookmark.getPro
file())) { |
| 326 final EnhancedBookmarksModel bookmarkModel = new EnhancedBookmarksMo
del(); |
| 327 |
| 328 BookmarkModelObserver modelObserver = new BookmarkModelObserver() { |
| 329 @Override |
| 330 public void bookmarkModelChanged() {} |
| 331 |
| 332 @Override |
| 333 public void bookmarkModelLoaded() { |
| 334 if (bookmarkId == ChromeBrowserProviderClient.INVALID_BOOKMA
RK_ID) { |
| 335 EnhancedBookmarkUtils.addBookmarkAndShowSnackbar(bookmar
kModel, |
| 336 tabToBookmark, getSnackbarManager(), CompositorC
hromeActivity.this); |
| 337 } else { |
| 338 EnhancedBookmarkUtils.startDetailActivity(CompositorChro
meActivity.this, |
| 339 new BookmarkId(bookmarkId, BookmarkType.NORMAL))
; |
| 340 } |
| 341 bookmarkModel.removeModelObserver(this); |
| 342 } |
| 343 }; |
| 344 |
| 345 if (bookmarkModel.isBookmarkModelLoaded()) { |
| 346 modelObserver.bookmarkModelLoaded(); |
| 347 } else { |
| 348 bookmarkModel.addModelObserver(modelObserver); |
| 349 } |
| 350 } else { |
| 351 Intent intent = new Intent(this, ManageBookmarkActivity.class); |
| 352 // Managed bookmarks can't be edited. Fallback on adding a new bookm
ark if the current |
| 353 // URL is bookmarked by a managed bookmark. |
| 354 |
| 355 if (bookmarkId == ChromeBrowserProviderClient.INVALID_BOOKMARK_ID) { |
| 356 intent.putExtra(ManageBookmarkActivity.BOOKMARK_INTENT_IS_FOLDER
, false); |
| 357 intent.putExtra(ManageBookmarkActivity.BOOKMARK_INTENT_TITLE, |
| 358 tabToBookmark.getTitle()); |
| 359 intent.putExtra(ManageBookmarkActivity.BOOKMARK_INTENT_URL, tabT
oBookmark.getUrl()); |
| 360 } else { |
| 361 intent.putExtra(ManageBookmarkActivity.BOOKMARK_INTENT_IS_FOLDER
, false); |
| 362 intent.putExtra(ManageBookmarkActivity.BOOKMARK_INTENT_ID, bookm
arkId); |
| 363 } |
| 364 startActivity(intent); |
| 365 } |
| 366 } |
| 367 |
| 368 /** |
| 369 * @return A {@link WindowAndroid} instance. |
| 370 */ |
| 371 public WindowAndroid getWindowAndroid() { |
| 372 return mWindowAndroid; |
| 373 } |
| 374 |
| 375 /** |
| 376 * @return A {@link CompositorViewHolder} instance. |
| 377 */ |
| 378 public CompositorViewHolder getCompositorViewHolder() { |
| 379 return mCompositorViewHolder; |
| 380 } |
| 381 |
| 382 @Override |
| 383 public ChromeFullscreenManager getFullscreenManager() { |
| 384 return mFullscreenManager; |
| 385 } |
| 386 |
| 387 @Override |
| 388 public ContentOffsetProvider getContentOffsetProvider() { |
| 389 return mCompositorViewHolder.getContentOffsetProvider(); |
| 390 } |
| 391 |
| 392 @Override |
| 393 public ContentReadbackHandler getContentReadbackHandler() { |
| 394 return mCompositorViewHolder.getContentReadbackHandler(); |
| 395 } |
| 396 |
| 397 /** |
| 398 * Starts asynchronously taking the compositor activity screenshot. |
| 399 * @param getBitmapCallback The callback to call once the screenshot is take
n, or when failed. |
| 400 */ |
| 401 public void startTakingCompositorActivityScreenshot(GetBitmapCallback getBit
mapCallback) { |
| 402 ContentReadbackHandler readbackHandler = getContentReadbackHandler(); |
| 403 if (readbackHandler == null || getWindowAndroid() == null) { |
| 404 getBitmapCallback.onFinishGetBitmap(null, ReadbackResponse.SURFACE_U
NAVAILABLE); |
| 405 } else { |
| 406 readbackHandler.getCompositorBitmapAsync(getWindowAndroid(), getBitm
apCallback); |
| 407 } |
| 408 } |
| 409 |
| 410 @Override |
| 411 public ContextualSearchManager getContextualSearchManager() { |
| 412 return mContextualSearchManager; |
| 413 } |
| 414 |
| 415 /** |
| 416 * @return A {@link ReaderModeActivityDelegate} instance or {@code null} if
reader mode is |
| 417 * not enabled. |
| 418 */ |
| 419 public ReaderModeActivityDelegate getReaderModeActivityDelegate() { |
| 420 return mReaderModeActivityDelegate; |
| 421 } |
| 422 |
| 423 /** |
| 424 * Create a full-screen manager to be used by this activity. |
| 425 * @param controlContainer The control container that will be controlled by
the full-screen |
| 426 * manager. |
| 427 * @return A {@link ChromeFullscreenManager} instance that's been created. |
| 428 */ |
| 429 protected ChromeFullscreenManager createFullscreenManager(View controlContai
ner) { |
| 430 return new ChromeFullscreenManager(this, controlContainer, getTabModelSe
lector(), |
| 431 getControlContainerHeightResource(), true); |
| 432 } |
| 433 |
| 434 /** |
| 435 * Initializes the {@link CompositorViewHolder} with the relevant content it
needs to properly |
| 436 * show content on the screen. |
| 437 * @param layoutManager A {@link LayoutManagerDocument} instance
. This class is |
| 438 * responsible for driving all high level s
creen content and |
| 439 * determines which {@link Layout} is shown
when. |
| 440 * @param urlBar The {@link View} representing the URL ba
r (must be |
| 441 * focusable) or {@code null} if none exist
s. |
| 442 * @param contentContainer A {@link ViewGroup} that can have conten
t attached by |
| 443 * {@link Layout}s. |
| 444 * @param controlContainer A {@link ControlContainer} instance to d
raw. |
| 445 */ |
| 446 protected void initializeCompositorContent( |
| 447 LayoutManagerDocument layoutManager, View urlBar, ViewGroup contentC
ontainer, |
| 448 ControlContainer controlContainer) { |
| 449 CommandLine commandLine = CommandLine.getInstance(); |
| 450 boolean enableFullscreen = !commandLine.hasSwitch(ChromeSwitches.DISABLE
_FULLSCREEN); |
| 451 |
| 452 if (enableFullscreen && controlContainer != null) { |
| 453 mFullscreenManager = createFullscreenManager((View) controlContainer
); |
| 454 } |
| 455 |
| 456 if (mContextualSearchManager != null) { |
| 457 mContextualSearchManager.initialize(contentContainer); |
| 458 mContextualSearchManager.setSearchContentViewDelegate(layoutManager)
; |
| 459 } |
| 460 |
| 461 if (mReaderModeActivityDelegate != null) { |
| 462 mReaderModeActivityDelegate.initialize(contentContainer); |
| 463 mReaderModeActivityDelegate.setDynamicResourceLoader( |
| 464 mCompositorViewHolder.getDynamicResourceLoader()); |
| 465 mReaderModeActivityDelegate.getReaderModeControl(); |
| 466 } |
| 467 |
| 468 layoutManager.addSceneChangeObserver(this); |
| 469 mCompositorViewHolder.setLayoutManager(layoutManager); |
| 470 mCompositorViewHolder.setFocusable(false); |
| 471 mCompositorViewHolder.setControlContainer(controlContainer); |
| 472 mCompositorViewHolder.setFullscreenHandler(mFullscreenManager); |
| 473 mCompositorViewHolder.setUrlBar(urlBar); |
| 474 mCompositorViewHolder.onFinishNativeInitialization(getTabModelSelector()
, this, |
| 475 getTabContentManager(), contentContainer, mContextualSearchManag
er); |
| 476 |
| 477 if (controlContainer != null |
| 478 && DeviceClassManager.enableToolbarSwipe(FeatureUtilities.isDocu
mentMode(this))) { |
| 479 controlContainer.setSwipeHandler( |
| 480 getCompositorViewHolder().getLayoutManager().getTopSwipeHand
ler()); |
| 481 } |
| 482 } |
| 483 |
| 484 /** |
| 485 * Called when the back button is pressed. |
| 486 * @return Whether or not the back button was handled. |
| 487 */ |
| 488 protected abstract boolean handleBackPressed(); |
| 489 |
| 490 @Override |
| 491 public void onOrientationChange(int orientation) { |
| 492 if (mContextualSearchManager != null) { |
| 493 mContextualSearchManager.onOrientationChange(); |
| 494 } |
| 495 } |
| 496 |
| 497 @Override |
| 498 public final void onBackPressed() { |
| 499 if (mCompositorViewHolder != null) { |
| 500 LayoutManager layoutManager = mCompositorViewHolder.getLayoutManager
(); |
| 501 boolean layoutConsumed = layoutManager != null && layoutManager.onBa
ckPressed(); |
| 502 if (layoutConsumed || mContextualSearchManager != null |
| 503 && mContextualSearchManager.onBackPressed()) { |
| 504 RecordUserAction.record("SystemBack"); |
| 505 return; |
| 506 } |
| 507 } |
| 508 if (!isSelectActionBarShowing() && handleBackPressed()) { |
| 509 return; |
| 510 } |
| 511 // This will close the select action bar if it is showing, otherwise clo
se the activity. |
| 512 super.onBackPressed(); |
| 513 } |
| 514 |
| 515 private boolean isSelectActionBarShowing() { |
| 516 Tab tab = getActivityTab(); |
| 517 if (tab == null) return false; |
| 518 ContentViewCore contentViewCore = tab.getContentViewCore(); |
| 519 if (contentViewCore == null) return false; |
| 520 return contentViewCore.isSelectActionBarShowing(); |
| 521 } |
| 522 |
| 523 @Override |
| 524 public boolean createContextualSearchTab(ContentViewCore searchContentViewCo
re) { |
| 525 Tab currentTab = getActivityTab(); |
| 526 if (currentTab == null) return false; |
| 527 |
| 528 ChromeTabCreator tabCreator = getTabCreator(currentTab.isIncognito()); |
| 529 if (tabCreator == null) return false; |
| 530 |
| 531 tabCreator.createTabWithWebContents(searchContentViewCore.getWebContents
(), |
| 532 currentTab.getId(), TabLaunchType.FROM_LONGPRESS_FOREGROUND); |
| 533 return true; |
| 534 } |
| 535 |
| 536 @VisibleForTesting |
| 537 public AppMenuHandler getAppMenuHandler() { |
| 538 return null; |
| 539 } |
| 540 |
| 541 @Override |
| 542 public boolean shouldShowAppMenu() { |
| 543 // Do not show the menu if Contextual Search Panel is opened. |
| 544 if (mContextualSearchManager != null && mContextualSearchManager.isSearc
hPanelOpened()) { |
| 545 return false; |
| 546 } |
| 547 |
| 548 return true; |
| 549 } |
| 550 |
| 551 @Override |
| 552 public boolean onMenuOrKeyboardAction(int id, boolean fromMenu) { |
| 553 if (id == R.id.preferences_id) { |
| 554 PreferencesLauncher.launchSettingsPage(this, null); |
| 555 RecordUserAction.record("MobileMenuSettings"); |
| 556 } |
| 557 |
| 558 // All the code below assumes currentTab is not null, so return early if
it is null. |
| 559 final Tab currentTab = getActivityTab(); |
| 560 if (currentTab == null) { |
| 561 return false; |
| 562 } else if (id == R.id.forward_menu_id) { |
| 563 if (currentTab.canGoForward()) { |
| 564 currentTab.goForward(); |
| 565 RecordUserAction.record("MobileMenuForward"); |
| 566 RecordUserAction.record("MobileTabClobbered"); |
| 567 } |
| 568 } else if (id == R.id.bookmark_this_page_id) { |
| 569 addOrEditBookmark(currentTab); |
| 570 RecordUserAction.record("MobileMenuAddToBookmarks"); |
| 571 } else if (id == R.id.reload_menu_id) { |
| 572 if (currentTab.isLoading()) { |
| 573 currentTab.stopLoading(); |
| 574 } else { |
| 575 currentTab.reload(); |
| 576 RecordUserAction.record("MobileToolbarReload"); |
| 577 } |
| 578 } else if (id == R.id.info_menu_id) { |
| 579 WebsiteSettingsPopup.show(this, currentTab.getProfile(), currentTab.
getWebContents()); |
| 580 } else if (id == R.id.open_history_menu_id) { |
| 581 currentTab.loadUrl( |
| 582 new LoadUrlParams(UrlConstants.HISTORY_URL, PageTransition.A
UTO_TOPLEVEL)); |
| 583 } else if (id == R.id.share_menu_id || id == R.id.direct_share_menu_id)
{ |
| 584 onShareMenuItemSelected(currentTab, getWindowAndroid(), |
| 585 id == R.id.direct_share_menu_id, getCurrentTabModel().isInco
gnito()); |
| 586 } else if (id == R.id.print_id) { |
| 587 PrintingController printingController = getChromeApplication().getPr
intingController(); |
| 588 if (printingController != null && !printingController.isBusy() |
| 589 && PrefServiceBridge.getInstance().isPrintingEnabled()) { |
| 590 printingController.startPrint(new TabPrinter(currentTab), |
| 591 new PrintManagerDelegateImpl(this)); |
| 592 RecordUserAction.record("MobileMenuPrint"); |
| 593 } |
| 594 } else if (id == R.id.add_to_homescreen_id) { |
| 595 AddToHomescreenDialog.show(this, currentTab); |
| 596 RecordUserAction.record("MobileMenuAddToHomescreen"); |
| 597 } else if (id == R.id.request_desktop_site_id) { |
| 598 final boolean reloadOnChange = !currentTab.isNativePage(); |
| 599 final boolean usingDesktopUserAgent = currentTab.getUseDesktopUserAg
ent(); |
| 600 currentTab.setUseDesktopUserAgent(!usingDesktopUserAgent, reloadOnCh
ange); |
| 601 RecordUserAction.record("MobileMenuRequestDesktopSite"); |
| 602 } else if (id == R.id.reader_mode_prefs_id) { |
| 603 if (currentTab.getWebContents() != null) { |
| 604 RecordUserAction.record("DomDistiller_DistilledPagePrefsOpened")
; |
| 605 AlertDialog.Builder builder = |
| 606 new AlertDialog.Builder(this, R.style.AlertDialogTheme); |
| 607 builder.setView(DistilledPagePrefsView.create(this)); |
| 608 builder.show(); |
| 609 } |
| 610 } else if (id == R.id.help_id) { |
| 611 // Since reading back the compositor is asynchronous, we need to do
the readback |
| 612 // before starting the GoogleHelp. |
| 613 final String helpContextId = HelpAndFeedback.getHelpContextIdFromUrl
( |
| 614 currentTab.getUrl(), getCurrentTabModel().isIncognito()); |
| 615 final Activity mainActivity = this; |
| 616 startTakingCompositorActivityScreenshot(new GetBitmapCallback() { |
| 617 @Override |
| 618 public void onFinishGetBitmap(Bitmap bitmap, int response) { |
| 619 HelpAndFeedback.getInstance(mainActivity).show( |
| 620 mainActivity, helpContextId, bitmap, currentTab.getU
rl()); |
| 621 RecordUserAction.record("MobileMenuFeedback"); |
| 622 } |
| 623 }); |
| 624 } else { |
| 625 return false; |
| 626 } |
| 627 return true; |
| 628 } |
| 629 |
| 630 @Override |
| 631 public void onTabSelectionHinted(int tabId) { } |
| 632 |
| 633 @Override |
| 634 public void onSceneChange(Layout layout) { } |
| 635 } |
OLD | NEW |