| 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;
|
| - }
|
| -}
|
|
|