Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Unified Diff: chrome/android/java_staging/src/org/chromium/chrome/browser/tab/ChromeTab.java

Issue 1206673003: Merge java_staging/src into java/src. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/java_staging/src/org/chromium/chrome/browser/tab/ChromeTab.java
diff --git a/chrome/android/java_staging/src/org/chromium/chrome/browser/tab/ChromeTab.java b/chrome/android/java_staging/src/org/chromium/chrome/browser/tab/ChromeTab.java
deleted file mode 100644
index 63ac32f2ed315ed406e85d48a13bf47f8652a215..0000000000000000000000000000000000000000
--- a/chrome/android/java_staging/src/org/chromium/chrome/browser/tab/ChromeTab.java
+++ /dev/null
@@ -1,1414 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.tab;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Rect;
-import android.media.AudioManager;
-import android.os.Build;
-import android.os.Handler;
-import android.os.Message;
-import android.text.TextUtils;
-import android.view.ActionMode;
-import android.view.ContextMenu;
-import android.view.KeyEvent;
-import android.view.View;
-
-import org.chromium.base.Log;
-import org.chromium.base.TraceEvent;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.base.metrics.RecordUserAction;
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.ChromeMobileApplication;
-import org.chromium.chrome.browser.EmptyTabObserver;
-import org.chromium.chrome.browser.FrozenNativePage;
-import org.chromium.chrome.browser.IntentHandler.TabOpenType;
-import org.chromium.chrome.browser.NativePage;
-import org.chromium.chrome.browser.Tab;
-import org.chromium.chrome.browser.TabObserver;
-import org.chromium.chrome.browser.TabState;
-import org.chromium.chrome.browser.TabUma;
-import org.chromium.chrome.browser.TabUma.TabCreationState;
-import org.chromium.chrome.browser.UrlConstants;
-import org.chromium.chrome.browser.contextmenu.ChromeContextMenuPopulator;
-import org.chromium.chrome.browser.contextmenu.ContextMenuParams;
-import org.chromium.chrome.browser.contextmenu.ContextMenuPopulator;
-import org.chromium.chrome.browser.contextualsearch.ContextualSearchTabHelper;
-import org.chromium.chrome.browser.crash.MinidumpUploadService;
-import org.chromium.chrome.browser.dom_distiller.ReaderModeActivityDelegate;
-import org.chromium.chrome.browser.dom_distiller.ReaderModeManager;
-import org.chromium.chrome.browser.download.ChromeDownloadDelegate;
-import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler;
-import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler.OverrideUrlLoadingResult;
-import org.chromium.chrome.browser.externalnav.ExternalNavigationParams;
-import org.chromium.chrome.browser.fullscreen.FullscreenManager;
-import org.chromium.chrome.browser.media.MediaNotificationService;
-import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
-import org.chromium.chrome.browser.ntp.NativePageAssassin;
-import org.chromium.chrome.browser.ntp.NativePageFactory;
-import org.chromium.chrome.browser.omnibox.geo.GeolocationHeader;
-import org.chromium.chrome.browser.policy.PolicyAuditor;
-import org.chromium.chrome.browser.policy.PolicyAuditor.AuditEvent;
-import org.chromium.chrome.browser.preferences.PrefServiceBridge;
-import org.chromium.chrome.browser.rlz.RevenueStats;
-import org.chromium.chrome.browser.search_engines.TemplateUrlService;
-import org.chromium.chrome.browser.tab.BackgroundContentViewHelper.BackgroundContentViewDelegate;
-import org.chromium.chrome.browser.tabmodel.TabModel;
-import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
-import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
-import org.chromium.chrome.browser.tabmodel.TabModelUtils;
-import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
-import org.chromium.components.navigation_interception.InterceptNavigationDelegate;
-import org.chromium.components.navigation_interception.NavigationParams;
-import org.chromium.content.browser.ActivityContentVideoViewClient;
-import org.chromium.content.browser.ContentVideoViewClient;
-import org.chromium.content.browser.ContentViewClient;
-import org.chromium.content.browser.ContentViewCore;
-import org.chromium.content.browser.SelectActionMode;
-import org.chromium.content.browser.SelectActionModeCallback.ActionHandler;
-import org.chromium.content.browser.crypto.CipherFactory;
-import org.chromium.content_public.browser.GestureStateListener;
-import org.chromium.content_public.browser.InvalidateTypes;
-import org.chromium.content_public.browser.LoadUrlParams;
-import org.chromium.content_public.browser.NavigationController;
-import org.chromium.content_public.browser.WebContents;
-import org.chromium.content_public.browser.WebContentsObserver;
-import org.chromium.content_public.common.ConsoleMessageLevel;
-import org.chromium.content_public.common.Referrer;
-import org.chromium.ui.WindowOpenDisposition;
-import org.chromium.ui.base.PageTransition;
-import org.chromium.ui.base.WindowAndroid;
-
-import java.util.Locale;
-
-/**
- * A representation of a Tab for Chrome. This manages wrapping a WebContents and interacting with
- * most of Chromium while representing a consistent version of web content to the front end.
- */
-public class ChromeTab extends Tab {
- public static final int NTP_TAB_ID = -2;
-
- private static final String TAG = "ChromeTab";
-
- // URL didFailLoad error code. Should match the value in net_error_list.h.
- public static final int BLOCKED_BY_ADMINISTRATOR = -22;
-
- public static final String PAGESPEED_PASSTHROUGH_HEADER = "Chrome-Proxy: pass-through";
-
- private static final int MSG_ID_ENABLE_FULLSCREEN_AFTER_LOAD = 1;
-
- /** The maximum amount of time to wait for a page to load before entering fullscreen. -1 means
- * wait until the page finishes loading. */
- private static final long MAX_FULLSCREEN_LOAD_DELAY_MS = 3000;
-
- private ReaderModeManager mReaderModeManager;
-
- private TabRedirectHandler mTabRedirectHandler;
-
- private ChromeDownloadDelegate mDownloadDelegate;
-
- private boolean mIsFullscreenWaitingForLoad = false;
- private ExternalNavigationHandler.OverrideUrlLoadingResult mLastOverrideUrlLoadingResult =
- ExternalNavigationHandler.OverrideUrlLoadingResult.NO_OVERRIDE;
-
- /**
- * Whether didCommitProvisionalLoadForFrame() hasn't yet been called for the current native page
- * (page A). To decrease latency, we show native pages in both loadUrl() and
- * didCommitProvisionalLoadForFrame(). However, we mustn't show a new native page (page B) in
- * loadUrl() if the current native page hasn't yet been committed. Otherwise, we'll show each
- * page twice (A, B, A, B): the first two times in loadUrl(), the second two times in
- * didCommitProvisionalLoadForFrame().
- */
- private boolean mIsNativePageCommitPending;
-
- protected final ChromeActivity mActivity;
-
- private WebContentsObserver mWebContentsObserver;
-
- private Handler mHandler;
-
- private final Runnable mCloseContentsRunnable = new Runnable() {
- @Override
- public void run() {
- mActivity.getTabModelSelector().closeTab(ChromeTab.this);
- }
- };
-
- /**
- * The data reduction proxy was in use on the last page load if true.
- */
- protected boolean mUsedSpdyProxy;
-
- /**
- * The data reduction proxy was in pass through mode on the last page load if true.
- */
- protected boolean mUsedSpdyProxyWithPassthrough;
-
- /**
- * The last page load had request headers indicating that the data reduction proxy should
- * be put in pass through mode, if true.
- */
- private boolean mLastPageLoadHasSpdyProxyPassthroughHeaders;
-
- /**
- * Listens to gesture events fired by the ContentViewCore.
- */
- private GestureStateListener mGestureStateListener;
-
- /**
- * The background content view helper which loads the original page in background content view.
- */
- private BackgroundContentViewHelper mBackgroundContentViewHelper;
-
- /**
- * The load progress of swapped in content view at the time of swap.
- */
- private int mLoadProgressAtViewSwapInTime;
-
- /**
- * Whether forward history should be cleared after navigation is committed.
- */
- private boolean mClearAllForwardHistoryRequired;
-
- private boolean mShouldClearRedirectHistoryForTabClobbering;
-
- /**
- * Basic constructor. This is hidden, so that explicitly named factory methods are used to
- * create tabs. initialize() needs to be called afterwards to complete the second level
- * initialization.
- * @param creationState State in which the tab is created, needed to initialize TabUma
- * accounting. When null, TabUma will not be initialized.
- * @param frozenState TabState that was saved when the Tab was last persisted to storage.
- */
- protected ChromeTab(
- int id, ChromeActivity activity, boolean incognito, WindowAndroid nativeWindow,
- TabLaunchType type, int parentId, TabCreationState creationState,
- TabState frozenState) {
- super(id, parentId, incognito, activity, nativeWindow, type, frozenState);
-
- if (frozenState == null) {
- assert type != TabLaunchType.FROM_RESTORE
- && creationState != TabCreationState.FROZEN_ON_RESTORE;
- } else {
- assert type == TabLaunchType.FROM_RESTORE
- && creationState == TabCreationState.FROZEN_ON_RESTORE;
- }
-
- addObserver(mTabObserver);
- mActivity = activity;
- mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- if (msg == null) return;
- if (msg.what == MSG_ID_ENABLE_FULLSCREEN_AFTER_LOAD) {
- enableFullscreenAfterLoad();
- }
- }
- };
- setContentViewClient(createContentViewClient());
- if (mActivity != null && creationState != null) {
- setTabUma(new TabUma(
- this, creationState, mActivity.getTabModelSelector().getModel(incognito)));
- }
-
- if (incognito) {
- CipherFactory.getInstance().triggerKeyGeneration();
- }
-
- mReaderModeManager = new ReaderModeManager(this, activity);
- RevenueStats.getInstance().tabCreated(this);
-
- mTabRedirectHandler = new TabRedirectHandler(activity);
-
- ContextualSearchTabHelper.createForTab(this);
- if (nativeWindow != null) ThumbnailTabHelper.createForTab(this);
- }
-
- /**
- * Creates a minimal {@link ChromeTab} for testing. Do not use outside testing.
- *
- * @param id The id of the tab.
- * @param incognito Whether the tab is incognito.
- */
- @VisibleForTesting
- public ChromeTab(int id, boolean incognito) {
- super(id, incognito, null, null);
- mActivity = null;
- mTabRedirectHandler = new TabRedirectHandler(null);
- }
-
- /**
- * Creates a fresh tab. initialize() needs to be called afterwards to complete the second level
- * initialization.
- * @param initiallyHidden true iff the tab being created is initially in background
- */
- public static ChromeTab createLiveTab(int id, ChromeActivity activity, boolean incognito,
- WindowAndroid nativeWindow, TabLaunchType type, int parentId, boolean initiallyHidden) {
- return new ChromeTab(id, activity, incognito, nativeWindow, type, parentId,
- initiallyHidden ? TabCreationState.LIVE_IN_BACKGROUND :
- TabCreationState.LIVE_IN_FOREGROUND, null);
- }
-
- /**
- * Creates a new, "frozen" tab from a saved state. This can be used for background tabs restored
- * on cold start that should be loaded when switched to. initialize() needs to be called
- * afterwards to complete the second level initialization.
- */
- public static ChromeTab createFrozenTabFromState(
- int id, ChromeActivity activity, boolean incognito,
- WindowAndroid nativeWindow, int parentId, TabState state) {
- assert state != null;
- return new ChromeTab(id, activity, incognito, nativeWindow,
- TabLaunchType.FROM_RESTORE, parentId, TabCreationState.FROZEN_ON_RESTORE,
- state);
- }
-
- /**
- * Creates a new tab to be loaded lazily. This can be used for tabs opened in the background
- * that should be loaded when switched to. initialize() needs to be called afterwards to
- * complete the second level initialization.
- */
- public static ChromeTab createTabForLazyLoad(ChromeActivity activity, boolean incognito,
- WindowAndroid nativeWindow, TabLaunchType type, int parentId,
- LoadUrlParams loadUrlParams) {
- ChromeTab tab = new ChromeTab(
- INVALID_TAB_ID, activity, incognito, nativeWindow, type, parentId,
- TabCreationState.FROZEN_FOR_LAZY_LOAD, null);
- tab.setPendingLoadParams(loadUrlParams);
- return tab;
- }
-
- public static ChromeTab fromTab(Tab tab) {
- return (ChromeTab) tab;
- }
-
- /**
- * Initializes the ChromeTab after construction with an existing ContentViewCore.
- */
- @Override
- protected void internalInit() {
- super.internalInit();
- if (mBackgroundContentViewHelper == null) {
- BackgroundContentViewDelegate delegate = new BackgroundContentViewDelegate() {
- @Override
- public void onBackgroundViewReady(
- ContentViewCore cvc, boolean didStartLoad, boolean didFinishLoad,
- int progress) {
- WebContents previewWebContents = getWebContents();
- swapContentViewCore(cvc, false, didStartLoad, didFinishLoad);
- mLoadProgressAtViewSwapInTime = progress;
- mBackgroundContentViewHelper.unloadAndDeleteWebContents(previewWebContents);
-
- // Enter to fullscreen.
- mHandler.removeMessages(MSG_ID_ENABLE_FULLSCREEN_AFTER_LOAD);
- mHandler.sendEmptyMessageDelayed(
- MSG_ID_ENABLE_FULLSCREEN_AFTER_LOAD, MAX_FULLSCREEN_LOAD_DELAY_MS);
- updateFullscreenEnabledState();
- }
-
- @Override
- public void onLoadProgressChanged(int progress) {
- notifyLoadProgress(getProgress());
- }
- };
- mBackgroundContentViewHelper = new BackgroundContentViewHelper(
- getWindowAndroid(), this, delegate);
- }
- }
-
- /**
- * Remember if the last load used the data reduction proxy, and if so,
- * also remember if it used pass through mode.
- */
- private void maybeSetDataReductionProxyUsed() {
- // Ignore internal URLs.
- String url = getUrl();
- if (url != null && url.toLowerCase(Locale.US).startsWith("chrome://")) {
- return;
- }
- mUsedSpdyProxy = false;
- mUsedSpdyProxyWithPassthrough = false;
- if (isSpdyProxyEnabledForUrl(url)) {
- mUsedSpdyProxy = true;
- if (mLastPageLoadHasSpdyProxyPassthroughHeaders) {
- mLastPageLoadHasSpdyProxyPassthroughHeaders = false;
- mUsedSpdyProxyWithPassthrough = true;
- }
- }
- }
-
- @Override
- protected void openNewTab(
- LoadUrlParams params, TabLaunchType launchType, Tab parentTab, boolean incognito) {
- mActivity.getTabModelSelector().openNewTab(params, launchType, parentTab, incognito);
- }
-
- @Override
- protected TabChromeWebContentsDelegateAndroid createWebContentsDelegate() {
- return new TabChromeWebContentsDelegateAndroidImpl();
- }
-
- /**
- * An implementation for this tab's web contents delegate.
- */
- public class TabChromeWebContentsDelegateAndroidImpl
- extends TabChromeWebContentsDelegateAndroid {
- /**
- * This method is meant to be overridden by DocumentTab because the
- * TabModelSelector returned by the activity is not correct.
- * TODO(dfalcantara): remove this when DocumentActivity.getTabModelSelector()
- * will return the right TabModelSelector.
- */
- protected TabModel getTabModel() {
- return mActivity.getTabModelSelector().getModel(isIncognito());
- }
-
- @Override
- public boolean addNewContents(WebContents sourceWebContents, WebContents webContents,
- int disposition, Rect initialPosition, boolean userGesture) {
- if (isClosing()) return false;
-
- // TODO(johnme): Open tabs in same order as Chrome.
- Tab tab = mActivity.getTabCreator(isIncognito()).createTabWithWebContents(
- webContents, getId(), TabLaunchType.FROM_LONGPRESS_FOREGROUND);
-
- if (tab == null) return false;
-
- if (disposition == WindowOpenDisposition.NEW_POPUP) {
- PolicyAuditor auditor =
- ((ChromeMobileApplication) getApplicationContext()).getPolicyAuditor();
- auditor.notifyAuditEvent(getApplicationContext(), AuditEvent.OPEN_POPUP_URL_SUCCESS,
- tab.getUrl(), "");
- }
-
- return true;
- }
-
- @Override
- public void activateContents() {
- boolean activityIsDestroyed = false;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- activityIsDestroyed = mActivity.isDestroyed();
- }
- if (activityIsDestroyed || !isInitialized()) {
- Log.e(TAG, "Activity destroyed before calling activateContents(). Bailing out.");
- return;
- }
-
- TabModel model = getTabModel();
- int index = model.indexOf(ChromeTab.this);
- if (index == TabModel.INVALID_TAB_INDEX) return;
-
- TabModelUtils.setIndex(model, index);
-
- // This intent is sent in order to get the activity back to the foreground if it was
- // not already. The previous call will activate the right tab in the context of the
- // TabModel but will only show the tab to the user if Chrome was already in the
- // foreground.
- // The intent is getting the tabId mostly because it does not cost much to do so.
- // When receiving the intent, the tab associated with the tabId should already be
- // active.
- // Note that calling only the intent in order to activate the tab is slightly slower
- // because it will change the tab when the intent is handled, which happens after
- // Chrome gets back to the foreground.
- Intent newIntent = new Intent();
- newIntent.setAction(Intent.ACTION_MAIN);
- newIntent.setPackage(mActivity.getPackageName());
- newIntent.putExtra(TabOpenType.BRING_TAB_TO_FRONT.name(),
- ChromeTab.this.getId());
-
- newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- getApplicationContext().startActivity(newIntent);
- }
-
- @Override
- public void navigationStateChanged(int flags) {
- if ((flags & InvalidateTypes.TAB) != 0) {
- MediaNotificationService.updateMediaNotificationForTab(
- getApplicationContext(), getId(), isCapturingAudio(),
- isCapturingVideo(), hasAudibleAudio(), getUrl());
- }
- super.navigationStateChanged(flags);
- }
-
- @Override
- public void onLoadProgressChanged(int progress) {
- if (!isLoading()) return;
- if (progress >= mLoadProgressAtViewSwapInTime) mLoadProgressAtViewSwapInTime = 0;
- notifyLoadProgress(getProgress());
- }
-
- @Override
- public void closeContents() {
- // Execute outside of callback, otherwise we end up deleting the native
- // objects in the middle of executing methods on them.
- mHandler.removeCallbacks(mCloseContentsRunnable);
- mHandler.post(mCloseContentsRunnable);
- }
-
- @Override
- public boolean takeFocus(boolean reverse) {
- if (reverse) {
- View menuButton = mActivity.findViewById(R.id.menu_button);
- if (menuButton == null || !menuButton.isShown()) {
- menuButton = mActivity.findViewById(R.id.document_menu_button);
- }
- if (menuButton != null && menuButton.isShown()) {
- return menuButton.requestFocus();
- }
-
- View tabSwitcherButton = mActivity.findViewById(R.id.tab_switcher_button);
- if (tabSwitcherButton != null && tabSwitcherButton.isShown()) {
- return tabSwitcherButton.requestFocus();
- }
- } else {
- View urlBar = mActivity.findViewById(R.id.url_bar);
- if (urlBar != null) return urlBar.requestFocus();
- }
- return false;
- }
-
- @Override
- public void handleKeyboardEvent(KeyEvent event) {
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- if (mActivity.onKeyDown(event.getKeyCode(), event)) return;
-
- // Handle the Escape key here (instead of in KeyboardShortcuts.java), so it doesn't
- // interfere with other parts of the activity (e.g. the URL bar).
- if (event.getKeyCode() == KeyEvent.KEYCODE_ESCAPE && event.hasNoModifiers()) {
- WebContents wc = getWebContents();
- if (wc != null) wc.stop();
- return;
- }
- }
- handleMediaKey(event);
- }
-
- /**
- * Redispatches unhandled media keys. This allows bluetooth headphones with play/pause or
- * other buttons to function correctly.
- */
- @TargetApi(19)
- private void handleMediaKey(KeyEvent e) {
- if (Build.VERSION.SDK_INT < 19) return;
- switch (e.getKeyCode()) {
- case KeyEvent.KEYCODE_MUTE:
- case KeyEvent.KEYCODE_HEADSETHOOK:
- case KeyEvent.KEYCODE_MEDIA_PLAY:
- case KeyEvent.KEYCODE_MEDIA_PAUSE:
- case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
- case KeyEvent.KEYCODE_MEDIA_STOP:
- case KeyEvent.KEYCODE_MEDIA_NEXT:
- case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
- case KeyEvent.KEYCODE_MEDIA_REWIND:
- case KeyEvent.KEYCODE_MEDIA_RECORD:
- case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
- case KeyEvent.KEYCODE_MEDIA_CLOSE:
- case KeyEvent.KEYCODE_MEDIA_EJECT:
- case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
- AudioManager am = (AudioManager) mActivity.getSystemService(
- Context.AUDIO_SERVICE);
- am.dispatchMediaKeyEvent(e);
- break;
- default:
- break;
- }
- }
-
- /**
- * @return Whether audio is being captured.
- */
- private boolean isCapturingAudio() {
- return !isClosing() && super.nativeIsCapturingAudio(getWebContents());
- }
-
- /**
- * @return Whether video is being captured.
- */
- private boolean isCapturingVideo() {
- return !isClosing() && super.nativeIsCapturingVideo(getWebContents());
- }
-
- /**
- * @return Whether audio is being played.
- */
- private boolean hasAudibleAudio() {
- return !isClosing() && super.nativeHasAudibleAudio(getWebContents());
- }
-
- }
-
- /**
- * Check whether the context menu download should be intercepted.
- *
- * @param url URL to be downloaded.
- * @return whether the download should be intercepted.
- */
- protected boolean shouldInterceptContextMenuDownload(String url) {
- return mDownloadDelegate.shouldInterceptContextMenuDownload(url);
- }
-
- private class ChromeTabChromeContextMenuItemDelegate extends TabChromeContextMenuItemDelegate {
- private boolean mIsImage;
- private boolean mIsVideo;
-
- public void setParamsInfo(boolean isImage, boolean isVideo) {
- mIsImage = isImage;
- mIsVideo = isVideo;
- }
-
- @Override
- public boolean isIncognitoSupported() {
- return PrefServiceBridge.getInstance().isIncognitoModeEnabled();
- }
-
- @Override
- public boolean canLoadOriginalImage() {
- return mUsedSpdyProxy && !mUsedSpdyProxyWithPassthrough;
- }
-
- @Override
- public boolean isDataReductionProxyEnabledForURL(String url) {
- return isSpdyProxyEnabledForUrl(url);
- }
-
- @Override
- public boolean startDownload(String url, boolean isLink) {
- if (isLink) {
- RecordUserAction.record("MobileContextMenuDownloadLink");
- if (shouldInterceptContextMenuDownload(url)) {
- return false;
- }
- } else if (mIsImage) {
- RecordUserAction.record("MobileContextMenuDownloadImage");
- } else if (mIsVideo) {
- RecordUserAction.record("MobileContextMenuDownloadVideo");
- }
- return true;
- }
-
- @Override
- public void onSaveToClipboard(String text, boolean isUrl) {
- if (isUrl) {
- RecordUserAction.record("MobileContextMenuCopyLinkAddress");
- } else {
- RecordUserAction.record("MobileContextMenuCopyLinkText");
- }
- super.onSaveToClipboard(text, isUrl);
- }
-
- @Override
- public void onSaveImageToClipboard(String url) {
- RecordUserAction.record("MobileContextMenuSaveImage");
- super.onSaveImageToClipboard(url);
- }
-
- @Override
- public void onOpenInNewTab(String url, Referrer referrer) {
- RecordUserAction.record("MobileContextMenuOpenLinkInNewTab");
- RecordUserAction.record("MobileNewTabOpened");
- LoadUrlParams loadUrlParams = new LoadUrlParams(url);
- loadUrlParams.setReferrer(referrer);
- mActivity.getTabModelSelector().openNewTab(loadUrlParams,
- TabLaunchType.FROM_LONGPRESS_BACKGROUND, ChromeTab.this, isIncognito());
- }
-
- @Override
- public void onOpenInNewIncognitoTab(String url) {
- RecordUserAction.record("MobileContextMenuOpenLinkInIncognito");
- RecordUserAction.record("MobileNewTabOpened");
- mActivity.getTabModelSelector().openNewTab(new LoadUrlParams(url),
- TabLaunchType.FROM_LONGPRESS_FOREGROUND, ChromeTab.this, true);
- }
-
- @Override
- public void onOpenImageUrl(String url, Referrer referrer) {
- RecordUserAction.record("MobileContextMenuViewImage");
- super.onOpenImageUrl(url, referrer);
- }
-
- @Override
- public void onOpenImageInNewTab(String url, Referrer referrer) {
- boolean useOriginal = isSpdyProxyEnabledForUrl(url);
- RecordUserAction.record("MobileContextMenuOpenImageInNewTab");
- if (useOriginal) {
- RecordUserAction.record("MobileContextMenuOpenOriginalImageInNewTab");
- }
-
- LoadUrlParams loadUrlParams = new LoadUrlParams(url);
- loadUrlParams.setVerbatimHeaders(useOriginal ? PAGESPEED_PASSTHROUGH_HEADER : null);
- loadUrlParams.setReferrer(referrer);
- mActivity.getTabModelSelector().openNewTab(loadUrlParams,
- TabLaunchType.FROM_LONGPRESS_BACKGROUND, ChromeTab.this, isIncognito());
- }
-
- @Override
- public void onSearchByImageInNewTab() {
- RecordUserAction.record("MobileContextMenuSearchByImage");
- super.onSearchByImageInNewTab();
- }
- }
-
- /**
- * This class is solely to track UMA stats. When we upstream UMA stats we can remove this.
- */
- private static class ChromeTabChromeContextMenuPopulator extends ChromeContextMenuPopulator {
- private final ChromeTabChromeContextMenuItemDelegate mDelegate;
-
- public ChromeTabChromeContextMenuPopulator(
- ChromeTabChromeContextMenuItemDelegate delegate) {
- super(delegate);
-
- mDelegate = delegate;
- }
-
- @Override
- public void buildContextMenu(ContextMenu menu, Context context,
- ContextMenuParams params) {
- if (params.isAnchor()) {
- RecordUserAction.record("MobileContextMenuLink");
- } else if (params.isImage()) {
- RecordUserAction.record("MobileContextMenuImage");
- } else if (params.isSelectedText()) {
- RecordUserAction.record("MobileContextMenuText");
- } else if (params.isVideo()) {
- RecordUserAction.record("MobileContextMenuVideo");
- }
-
- mDelegate.setParamsInfo(params.isImage(), params.isVideo());
- super.buildContextMenu(menu, context, params);
- }
- }
-
- @Override
- protected ContextMenuPopulator createContextMenuPopulator() {
- return new ChromeTabChromeContextMenuPopulator(
- new ChromeTabChromeContextMenuItemDelegate());
- }
-
- /** @return The {@link BackgroundContentViewHelper} associated with the current tab. */
- public BackgroundContentViewHelper getBackgroundContentViewHelper() {
- return mBackgroundContentViewHelper;
- }
-
- @VisibleForTesting
- public void setViewClientForTesting(ContentViewClient client) {
- setContentViewClient(client);
- }
-
- @VisibleForTesting
- public ContentViewClient getViewClientForTesting() {
- return getContentViewClient();
- }
-
- private ContentViewClient createContentViewClient() {
- return new TabContentViewClient() {
- @Override
- public void onBackgroundColorChanged(int color) {
- ChromeTab.this.onBackgroundColorChanged(color);
- }
-
- @Override
- public void onOffsetsForFullscreenChanged(
- float topControlsOffsetY, float contentOffsetY, float overdrawBottomHeight) {
- onOffsetsChanged(topControlsOffsetY, contentOffsetY, overdrawBottomHeight,
- isShowingSadTab());
- }
-
- @Override
- public void performWebSearch(String searchQuery) {
- if (TextUtils.isEmpty(searchQuery)) return;
- String url = TemplateUrlService.getInstance().getUrlForSearchQuery(searchQuery);
- String headers = GeolocationHeader.getGeoHeader(getApplicationContext(), url,
- isIncognito());
-
- LoadUrlParams loadUrlParams = new LoadUrlParams(url);
- loadUrlParams.setVerbatimHeaders(headers);
- loadUrlParams.setTransitionType(PageTransition.GENERATED);
- mActivity.getTabModelSelector().openNewTab(loadUrlParams,
- TabLaunchType.FROM_LONGPRESS_FOREGROUND, ChromeTab.this, isIncognito());
- }
-
- @Override
- public boolean doesPerformWebSearch() {
- return true;
- }
-
- @Override
- public SelectActionMode startActionMode(
- View view, ActionHandler actionHandler, boolean floating) {
- if (floating) return null;
- ChromeSelectActionModeCallback callback =
- new ChromeSelectActionModeCallback(view.getContext(), actionHandler);
- ActionMode actionMode = view.startActionMode(callback);
- return actionMode != null ? new SelectActionMode(actionMode) : null;
- }
-
- @Override
- public boolean supportsFloatingActionMode() {
- return false;
- }
-
- @Override
- public ContentVideoViewClient getContentVideoViewClient() {
- return new ActivityContentVideoViewClient(mActivity) {
- @Override
- public void enterFullscreenVideo(View view) {
- super.enterFullscreenVideo(view);
- FullscreenManager fullscreenManager = getFullscreenManager();
- if (fullscreenManager != null) {
- fullscreenManager.setOverlayVideoMode(true);
- // Disable double tap for video.
- if (getContentViewCore() != null) {
- getContentViewCore().updateDoubleTapSupport(false);
- }
- }
- }
-
- @Override
- public void exitFullscreenVideo() {
- FullscreenManager fullscreenManager = getFullscreenManager();
- if (fullscreenManager != null) {
- fullscreenManager.setOverlayVideoMode(false);
- // Disable double tap for video.
- if (getContentViewCore() != null) {
- getContentViewCore().updateDoubleTapSupport(true);
- }
- }
- super.exitFullscreenVideo();
- }
- };
- }
- };
- }
-
- private WebContentsObserver createWebContentsObserver(WebContents webContents) {
- return new WebContentsObserver(webContents) {
- @Override
- public void didFinishLoad(long frameId, String validatedUrl, boolean isMainFrame) {
- PolicyAuditor auditor =
- ((ChromeMobileApplication) getApplicationContext()).getPolicyAuditor();
- auditor.notifyAuditEvent(
- getApplicationContext(), AuditEvent.OPEN_URL_SUCCESS, validatedUrl, "");
- }
-
- @Override
- public void didFailLoad(boolean isProvisionalLoad, boolean isMainFrame, int errorCode,
- String description, String failingUrl, boolean wasIgnoredByHandler) {
- if (isMainFrame) {
- if (failingUrl.startsWith("chrome://newtab/")
- || failingUrl.startsWith("chrome://welcome/")) {
- // If a tab was showing the old NTP or welcome page in a previous version
- // of Chrome, that tab will appear as a blank page after Chrome updates.
- // To fix this, these obsolete URLs are redirected to the NTP.
- // TODO(newt): remove this once most users have upgraded past M39.
- // http://crbug.com/491878
- loadUrl(new LoadUrlParams(UrlConstants.NTP_URL,
- PageTransition.AUTO_TOPLEVEL));
- return;
- }
- }
-
- PolicyAuditor auditor =
- ((ChromeMobileApplication) getApplicationContext()).getPolicyAuditor();
- auditor.notifyAuditEvent(getApplicationContext(), AuditEvent.OPEN_URL_FAILURE,
- failingUrl, description);
- if (errorCode == BLOCKED_BY_ADMINISTRATOR) {
- auditor.notifyAuditEvent(
- getApplicationContext(), AuditEvent.OPEN_URL_BLOCKED, failingUrl, "");
- }
- }
-
- @Override
- public void didCommitProvisionalLoadForFrame(
- long frameId, boolean isMainFrame, String url, int transitionType) {
- if (!isMainFrame) return;
-
- mIsNativePageCommitPending = false;
- boolean isReload = (transitionType == PageTransition.RELOAD);
- if (!maybeShowNativePage(url, isReload)) {
- showRenderedPage();
- }
-
- if (!mBackgroundContentViewHelper.hasPendingBackgroundPage()) {
- mHandler.removeMessages(MSG_ID_ENABLE_FULLSCREEN_AFTER_LOAD);
- mHandler.sendEmptyMessageDelayed(
- MSG_ID_ENABLE_FULLSCREEN_AFTER_LOAD, MAX_FULLSCREEN_LOAD_DELAY_MS);
- updateFullscreenEnabledState();
- }
-
- // http://crbug/426679 : if navigation is canceled due to intent handling, we want
- // to go back to the last committed entry index which was saved before the
- // navigation, and remove the empty entries from the navigation history.
- if (mClearAllForwardHistoryRequired && getWebContents() != null) {
- NavigationController navigationController =
- getWebContents().getNavigationController();
- int lastCommittedEntryIndex = getLastCommittedEntryIndex();
- while (navigationController.canGoForward()) {
- boolean ret = navigationController.removeEntryAtIndex(
- lastCommittedEntryIndex + 1);
- assert ret;
- }
- } else if (mShouldClearRedirectHistoryForTabClobbering
- && getWebContents() != null) {
- // http://crbug/479056: Even if we clobber the current tab, we want to remove
- // redirect history to be consistent.
- NavigationController navigationController =
- getWebContents().getNavigationController();
- int indexBeforeRedirection = mTabRedirectHandler
- .getLastCommittedEntryIndexBeforeStartingNavigation();
- int lastCommittedEntryIndex = getLastCommittedEntryIndex();
- for (int i = lastCommittedEntryIndex - 1; i > indexBeforeRedirection; --i) {
- boolean ret = navigationController.removeEntryAtIndex(i);
- assert ret;
- }
- }
- mClearAllForwardHistoryRequired = false;
- mShouldClearRedirectHistoryForTabClobbering = false;
- }
-
- @Override
- public void didAttachInterstitialPage() {
- PolicyAuditor auditor =
- ((ChromeMobileApplication) getApplicationContext()).getPolicyAuditor();
- auditor.notifyCertificateFailure(getWebContents(), getApplicationContext());
- }
-
- @Override
- public void didDetachInterstitialPage() {
- if (!maybeShowNativePage(getUrl(), false)) {
- showRenderedPage();
- }
- }
-
- @Override
- public void destroy() {
- MediaNotificationService.updateMediaNotificationForTab(
- getApplicationContext(), getId(), false, false, false, getUrl());
- super.destroy();
- }
- };
- }
-
- @Override
- protected void didStartPageLoad(String validatedUrl, boolean showingErrorPage) {
- if (mBackgroundContentViewHelper.isPageSwappingInProgress()) {
- mLoadProgressAtViewSwapInTime = 0;
- }
-
- mIsFullscreenWaitingForLoad = !DomDistillerUrlUtils.isDistilledPage(validatedUrl);
- mLoadProgressAtViewSwapInTime = 0;
-
- super.didStartPageLoad(validatedUrl, showingErrorPage);
- }
-
- @Override
- protected void didFinishPageLoad() {
- // We should not mark finished if we have pending background page to swap in.
- // We'll instead call didFinishPageLoad after the background page is swapped in.
- if (mBackgroundContentViewHelper.hasPendingBackgroundPage()) return;
-
- mLoadProgressAtViewSwapInTime = 0;
-
- super.didFinishPageLoad();
-
- // Handle the case where we were pre-renderered and the enable fullscreen message was
- // never enqueued.
- if (mIsFullscreenWaitingForLoad
- && !mHandler.hasMessages(MSG_ID_ENABLE_FULLSCREEN_AFTER_LOAD)
- && !mBackgroundContentViewHelper.hasPendingBackgroundPage()) {
- mHandler.sendEmptyMessageDelayed(
- MSG_ID_ENABLE_FULLSCREEN_AFTER_LOAD, MAX_FULLSCREEN_LOAD_DELAY_MS);
- }
-
- maybeSetDataReductionProxyUsed();
- }
-
- @Override
- protected void didFailPageLoad(int errorCode) {
- mLoadProgressAtViewSwapInTime = 0;
- cancelEnableFullscreenLoadDelay();
- super.didFailPageLoad(errorCode);
- updateFullscreenEnabledState();
- }
-
- private void cancelEnableFullscreenLoadDelay() {
- mHandler.removeMessages(MSG_ID_ENABLE_FULLSCREEN_AFTER_LOAD);
- mIsFullscreenWaitingForLoad = false;
- }
-
- /**
- * Removes the enable fullscreen runnable from the UI queue and runs it immediately.
- */
- @VisibleForTesting
- public void processEnableFullscreenRunnableForTest() {
- if (mHandler.hasMessages(MSG_ID_ENABLE_FULLSCREEN_AFTER_LOAD)) {
- mHandler.removeMessages(MSG_ID_ENABLE_FULLSCREEN_AFTER_LOAD);
- enableFullscreenAfterLoad();
- }
- }
-
- private void enableFullscreenAfterLoad() {
- if (!mIsFullscreenWaitingForLoad) return;
-
- mIsFullscreenWaitingForLoad = false;
- updateFullscreenEnabledState();
- }
-
- @Override
- protected boolean isHidingTopControlsEnabled() {
- return super.isHidingTopControlsEnabled() && !mIsFullscreenWaitingForLoad;
- }
-
- @Override
- protected void handleTabCrash() {
- super.handleTabCrash();
-
- // Update the most recent minidump file with the logcat. Doing this asynchronously
- // adds a race condition in the case of multiple simultaneously renderer crashses
- // but because the data will be the same for all of them it is innocuous. We can
- // attempt to do this regardless of whether it was a foreground tab in the event
- // that it's a real crash and not just android killing the tab.
- Context context = getApplicationContext();
- Intent intent = MinidumpUploadService.createFindAndUploadLastCrashIntent(context);
- context.startService(intent);
- RecordUserAction.record("MobileBreakpadUploadAttempt");
- }
-
- @Override
- protected void setContentViewCore(ContentViewCore cvc) {
- try {
- TraceEvent.begin("ChromeTab.setContentViewCore");
- super.setContentViewCore(cvc);
- mWebContentsObserver = createWebContentsObserver(cvc.getWebContents());
-
- mDownloadDelegate = new ChromeDownloadDelegate(mActivity,
- mActivity.getTabModelSelector(), this);
- cvc.setDownloadDelegate(mDownloadDelegate);
- setInterceptNavigationDelegate(createInterceptNavigationDelegate());
-
- if (mGestureStateListener == null) mGestureStateListener = createGestureStateListener();
- cvc.addGestureStateListener(mGestureStateListener);
- } finally {
- TraceEvent.end("ChromeTab.setContentViewCore");
- }
- }
-
- private GestureStateListener createGestureStateListener() {
- return new GestureStateListener() {
- @Override
- public void onFlingStartGesture(int vx, int vy, int scrollOffsetY, int scrollExtentY) {
- onScrollingStateChanged();
- }
-
- @Override
- public void onFlingEndGesture(int scrollOffsetY, int scrollExtentY) {
- onScrollingStateChanged();
- }
-
- @Override
- public void onScrollStarted(int scrollOffsetY, int scrollExtentY) {
- onScrollingStateChanged();
- }
-
- @Override
- public void onScrollEnded(int scrollOffsetY, int scrollExtentY) {
- onScrollingStateChanged();
- }
-
- private void onScrollingStateChanged() {
- FullscreenManager fullscreenManager = getFullscreenManager();
- if (fullscreenManager == null) return;
- fullscreenManager.onContentViewScrollingStateChanged(
- getContentViewCore() != null && getContentViewCore().isScrollInProgress());
- }
- };
- }
-
- @Override
- protected void destroyContentViewCoreInternal(ContentViewCore cvc) {
- super.destroyContentViewCoreInternal(cvc);
-
- if (mGestureStateListener != null) {
- cvc.removeGestureStateListener(mGestureStateListener);
- }
- if (mWebContentsObserver != null) {
- mWebContentsObserver.destroy();
- }
- mWebContentsObserver = null;
- }
-
- @Override
- public void stopLoading() {
- super.stopLoading();
- mBackgroundContentViewHelper.stopLoading();
- }
-
- @Override
- public int getProgress() {
- if (mBackgroundContentViewHelper.hasPendingBackgroundPage()
- || mBackgroundContentViewHelper.isPageSwappingInProgress()) {
- return mBackgroundContentViewHelper.getProgress();
- }
- int currentTabProgress = super.getProgress();
- return Math.max(mLoadProgressAtViewSwapInTime, currentTabProgress);
- }
-
- /**
- * @return Whether the tab is ready to display or it should be faded in as it loads.
- */
- public boolean shouldStall() {
- return (isFrozen() || needsReload())
- && !NativePageFactory.isNativePageUrl(getUrl(), isIncognito());
- }
-
- @Override
- protected void showInternal(TabSelectionType type) {
- super.showInternal(type);
-
- // If the NativePage was frozen while in the background (see NativePageAssassin),
- // recreate the NativePage now.
- if (getNativePage() instanceof FrozenNativePage) {
- maybeShowNativePage(getUrl(), true);
- }
- NativePageAssassin.getInstance().tabShown(this);
- }
-
- @Override
- protected void restoreIfNeededInternal() {
- super.restoreIfNeededInternal();
- }
-
- @Override
- protected void hideInternal() {
- super.hideInternal();
- cancelEnableFullscreenLoadDelay();
-
- // Allow this tab's NativePage to be frozen if it stays hidden for a while.
- NativePageAssassin.getInstance().tabHidden(this);
-
- mTabRedirectHandler.clear();
- }
-
- /**
- * Checks if spdy proxy is enabled for input url.
- * @param url Input url to check for spdy setting.
- * @return true if url is enabled for spdy proxy.
- */
- protected boolean isSpdyProxyEnabledForUrl(String url) {
- if (DataReductionProxySettings.getInstance().isDataReductionProxyEnabled()
- && url != null && !url.toLowerCase(Locale.US).startsWith("https://")
- && !isIncognito()) {
- return true;
- }
- return false;
- }
-
- @Override
- public void goBack() {
- mBackgroundContentViewHelper.recordBack();
- super.goBack();
- }
-
- @Override
- public void reload() {
- mBackgroundContentViewHelper.recordReload();
- super.reload();
- }
-
- @Override
- public void reloadIgnoringCache() {
- mBackgroundContentViewHelper.recordReload();
- super.reloadIgnoringCache();
- }
-
- @Override
- public int loadUrl(LoadUrlParams params) {
- try {
- TraceEvent.begin("ChromeTab.loadUrl");
-
- // The data reduction proxy can only be set to pass through mode via loading an image in
- // a new tab. We squirrel away whether pass through mode was set, and check it in:
- // @see ChromeWebContentsDelegateAndroid#onLoadStopped()
- mLastPageLoadHasSpdyProxyPassthroughHeaders = false;
- if (TextUtils.equals(params.getVerbatimHeaders(), PAGESPEED_PASSTHROUGH_HEADER)) {
- mLastPageLoadHasSpdyProxyPassthroughHeaders = true;
- }
-
- // TODO(tedchoc): When showing the android NTP, delay the call to nativeLoadUrl until
- // the android view has entirely rendered.
- if (!mIsNativePageCommitPending) {
- mIsNativePageCommitPending = maybeShowNativePage(params.getUrl(), false);
- }
-
- return super.loadUrl(params);
- } finally {
- TraceEvent.end("ChromeTab.loadUrl");
- }
- }
-
- @VisibleForTesting
- public AuthenticatorNavigationInterceptor getAuthenticatorHelper() {
- return getInterceptNavigationDelegate().mAuthenticatorHelper;
- }
-
- /**
- * @return the TabRedirectHandler for the tab.
- */
- public TabRedirectHandler getTabRedirectHandler() {
- return mTabRedirectHandler;
- }
-
- /**
- * Delegate that handles intercepting top-level navigation.
- */
- protected class InterceptNavigationDelegateImpl implements InterceptNavigationDelegate {
- final ExternalNavigationHandler mExternalNavHandler;
- final AuthenticatorNavigationInterceptor mAuthenticatorHelper;
-
- /**
- * Defualt constructor of {@link InterceptNavigationDelegateImpl}.
- */
- public InterceptNavigationDelegateImpl() {
- this(new ExternalNavigationHandler(mActivity));
- }
-
- /**
- * Constructs a new instance of {@link InterceptNavigationDelegateImpl} with the given
- * {@link ExternalNavigationHandler}.
- */
- public InterceptNavigationDelegateImpl(ExternalNavigationHandler externalNavHandler) {
- mExternalNavHandler = externalNavHandler;
- mAuthenticatorHelper = ((ChromeMobileApplication) getApplicationContext())
- .createAuthenticatorNavigationInterceptor(ChromeTab.this);
- }
-
- public boolean shouldIgnoreNewTab(String url, boolean incognito) {
- if (mAuthenticatorHelper != null && mAuthenticatorHelper.handleAuthenticatorUrl(url)) {
- return true;
- }
-
- ExternalNavigationParams params = new ExternalNavigationParams.Builder(url, incognito)
- .setTab(ChromeTab.this)
- .setOpenInNewTab(true)
- .build();
- return mExternalNavHandler.shouldOverrideUrlLoading(params)
- != ExternalNavigationHandler.OverrideUrlLoadingResult.NO_OVERRIDE;
- }
-
- @Override
- public boolean shouldIgnoreNavigation(NavigationParams navigationParams) {
- final String url = navigationParams.url;
-
- if (mAuthenticatorHelper != null && mAuthenticatorHelper.handleAuthenticatorUrl(url)) {
- return true;
- }
-
- mTabRedirectHandler.updateNewUrlLoading(navigationParams.pageTransitionType,
- navigationParams.isRedirect,
- navigationParams.hasUserGesture || navigationParams.hasUserGestureCarryover,
- mActivity.getLastUserInteractionTime(), getLastCommittedEntryIndex());
- final boolean shouldCloseTab = shouldCloseContentsOnOverrideUrlLoadingAndLaunchIntent();
- boolean isInitialTabLaunchInBackground =
- getLaunchType() == TabLaunchType.FROM_LONGPRESS_BACKGROUND && shouldCloseTab;
- // http://crbug.com/448977: If a new tab is closed by this overriding, we should open an
- // Intent in a new tab when Chrome receives it again.
- ExternalNavigationParams params = new ExternalNavigationParams.Builder(
- url, isIncognito(), navigationParams.referrer,
- navigationParams.pageTransitionType,
- navigationParams.isRedirect)
- .setTab(ChromeTab.this)
- .setApplicationMustBeInForeground(true)
- .setRedirectHandler(mTabRedirectHandler)
- .setOpenInNewTab(shouldCloseTab)
- .setIsBackgroundTabNavigation(isHidden() && !isInitialTabLaunchInBackground)
- .setIsMainFrame(navigationParams.isMainFrame)
- .setNeedsToCloseTabAfterIncognitoDialog(shouldCloseTab
- && navigationParams.isMainFrame)
- .build();
- ExternalNavigationHandler.OverrideUrlLoadingResult result =
- mExternalNavHandler.shouldOverrideUrlLoading(params);
- mLastOverrideUrlLoadingResult = result;
- switch (result) {
- case OVERRIDE_WITH_EXTERNAL_INTENT:
- assert mExternalNavHandler.canExternalAppHandleUrl(url);
- if (navigationParams.isMainFrame) {
- onOverrideUrlLoadingAndLaunchIntent();
- }
- return true;
- case OVERRIDE_WITH_CLOBBERING_TAB:
- mShouldClearRedirectHistoryForTabClobbering = true;
- return true;
- case OVERRIDE_WITH_INCOGNITO_MODE:
- if (!shouldCloseTab && navigationParams.isMainFrame) {
- onOverrideUrlLoadingAndLaunchIntent();
- }
- return true;
- case NO_OVERRIDE:
- default:
- if (navigationParams.isExternalProtocol) {
- logBlockedNavigationToDevToolsConsole(url);
- return true;
- }
- return false;
- }
- }
-
- private void logBlockedNavigationToDevToolsConsole(String url) {
- int resId = mExternalNavHandler.canExternalAppHandleUrl(url)
- ? R.string.blocked_navigation_warning
- : R.string.unreachable_navigation_warning;
- getWebContents().addMessageToDevToolsConsole(
- ConsoleMessageLevel.WARNING, getApplicationContext().getString(resId, url));
- }
- }
-
- @Override
- protected boolean shouldIgnoreNewTab(String url, boolean incognito) {
- InterceptNavigationDelegateImpl delegate = getInterceptNavigationDelegate();
- return delegate != null && delegate.shouldIgnoreNewTab(url, incognito);
- }
-
- private int getLastCommittedEntryIndex() {
- if (getWebContents() == null) return -1;
- return getWebContents().getNavigationController().getLastCommittedEntryIndex();
- }
-
- /**
- * @return A potential fallback texture id to use when trying to draw this tab.
- */
- public int getFallbackTextureId() {
- return INVALID_TAB_ID;
- }
-
- private boolean shouldCloseContentsOnOverrideUrlLoadingAndLaunchIntent() {
- if (getWebContents() == null) return false;
- if (!getWebContents().getNavigationController().canGoToOffset(0)) return true;
-
- // http://crbug/415948 : if the last committed entry index which was saved before this
- // navigation is invalid, it means that this navigation is the first one since this tab was
- // created.
- // In such case, we would like to close this tab.
- if (mTabRedirectHandler.isOnNavigation()) {
- return mTabRedirectHandler.getLastCommittedEntryIndexBeforeStartingNavigation()
- == TabRedirectHandler.INVALID_ENTRY_INDEX;
- }
- return false;
- }
-
- /**
- * Called when Chrome decides to override URL loading and show an intent picker.
- */
- protected void onOverrideUrlLoadingAndLaunchIntent() {
- if (getWebContents() == null) return;
-
- // Before leaving Chrome, close the empty child tab.
- // If a new tab is created through JavaScript open to load this
- // url, we would like to close it as we will load this url in a
- // different Activity.
- if (shouldCloseContentsOnOverrideUrlLoadingAndLaunchIntent()) {
- getChromeWebContentsDelegateAndroid().closeContents();
- } else if (mTabRedirectHandler.isOnNavigation()) {
- int lastCommittedEntryIndexBeforeNavigation =
- mTabRedirectHandler.getLastCommittedEntryIndexBeforeStartingNavigation();
- if (getLastCommittedEntryIndex() > lastCommittedEntryIndexBeforeNavigation) {
- // http://crbug/426679 : we want to go back to the last committed entry index which
- // was saved before this navigation, and remove the empty entries from the
- // navigation history.
- mClearAllForwardHistoryRequired = true;
- getWebContents().getNavigationController().goToNavigationIndex(
- lastCommittedEntryIndexBeforeNavigation);
- }
- }
- }
-
- @Override
- protected InterceptNavigationDelegateImpl getInterceptNavigationDelegate() {
- return (InterceptNavigationDelegateImpl) super.getInterceptNavigationDelegate();
- }
-
- /**
- * Factory method for {@link InterceptNavigationDelegateImpl}. Meant to be overridden by
- * subclasses.
- * @return A new instance of {@link InterceptNavigationDelegateImpl}.
- */
- protected InterceptNavigationDelegateImpl createInterceptNavigationDelegate() {
- return new InterceptNavigationDelegateImpl();
- }
-
- @Override
- public void setClosing(boolean closing) {
- if (closing) mBackgroundContentViewHelper.recordTabClose();
- super.setClosing(closing);
- }
-
- /**
- * @return The reader mode manager for this tab that handles UI events for reader mode.
- */
- public ReaderModeManager getReaderModeManager() {
- return mReaderModeManager;
- }
-
- public ReaderModeActivityDelegate getReaderModeActivityDelegate() {
- return mActivity == null ? null : mActivity.getReaderModeActivityDelegate();
- }
-
- /**
- * Shows a native page for url if it's a valid chrome-native URL. Otherwise, does nothing.
- * @param url The url of the current navigation.
- * @param isReload Whether the current navigation is a reload.
- * @return True, if a native page was displayed for url.
- */
- private boolean maybeShowNativePage(String url, boolean isReload) {
- NativePage candidateForReuse = isReload ? null : getNativePage();
- NativePage nativePage = NativePageFactory.createNativePageForURL(url, candidateForReuse,
- this, mActivity.getTabModelSelector(), mActivity);
- if (nativePage != null) {
- showNativePage(nativePage);
- notifyPageTitleChanged();
- notifyFaviconChanged();
- return true;
- }
- return false;
- }
-
- // TODO(dtrainor): Port more methods to the observer.
- private final TabObserver mTabObserver = new EmptyTabObserver() {
- @Override
- public void onContentChanged(Tab tab) {
- mLoadProgressAtViewSwapInTime = 0;
- }
-
- @Override
- public void onSSLStateUpdated(Tab tab) {
- PolicyAuditor auditor =
- ((ChromeMobileApplication) getApplicationContext()).getPolicyAuditor();
- auditor.notifyCertificateFailure(getWebContents(), getApplicationContext());
- updateFullscreenEnabledState();
- }
-
- @Override
- public void onWebContentsSwapped(Tab tab, boolean didStartLoad, boolean didFinishLoad) {
- if (!didStartLoad) return;
-
- String url = tab.getUrl();
- // Simulate the PAGE_LOAD_STARTED notification that we did not get.
- didStartPageLoad(url, false);
- if (didFinishLoad) {
- // Simulate the PAGE_LOAD_FINISHED notification that we did not get.
- didFinishPageLoad();
- }
- }
- };
-
- @VisibleForTesting
- public OverrideUrlLoadingResult getLastOverrideUrlLoadingResultForTests() {
- return mLastOverrideUrlLoadingResult;
- }
-}

Powered by Google App Engine
This is Rietveld 408576698