| Index: chrome/android/java_staging/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
|
| diff --git a/chrome/android/java_staging/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java b/chrome/android/java_staging/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..36706cefbb278836d1ff2c0ef52439c0fbd568b1
|
| --- /dev/null
|
| +++ b/chrome/android/java_staging/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
|
| @@ -0,0 +1,315 @@
|
| +// 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.tabmodel;
|
| +
|
| +import android.content.Intent;
|
| +import android.text.TextUtils;
|
| +
|
| +import org.chromium.base.SysUtils;
|
| +import org.chromium.base.TraceEvent;
|
| +import org.chromium.chrome.browser.ChromeActivity;
|
| +import org.chromium.chrome.browser.Tab;
|
| +import org.chromium.chrome.browser.TabState;
|
| +import org.chromium.chrome.browser.UrlConstants;
|
| +import org.chromium.chrome.browser.UrlUtilities;
|
| +import org.chromium.chrome.browser.WarmupManager;
|
| +import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
|
| +import org.chromium.chrome.browser.tab.ChromeTab;
|
| +import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
|
| +import org.chromium.components.service_tab_launcher.ServiceTabLauncher;
|
| +import org.chromium.content_public.browser.LoadUrlParams;
|
| +import org.chromium.content_public.browser.WebContents;
|
| +import org.chromium.ui.base.PageTransition;
|
| +import org.chromium.ui.base.WindowAndroid;
|
| +
|
| +/**
|
| + * This class creates various kinds of new tabs and adds them to the right {@link TabModel}.
|
| + */
|
| +public class ChromeTabCreator implements TabCreatorManager.TabCreator {
|
| +
|
| + private final ChromeActivity mActivity;
|
| + private final WindowAndroid mNativeWindow;
|
| + private final TabModelOrderController mOrderController;
|
| + private final TabPersistentStore mTabSaver;
|
| + private final boolean mIncognito;
|
| +
|
| + private TabModel mTabModel;
|
| + private TabContentManager mTabContentManager;
|
| +
|
| + public ChromeTabCreator(ChromeActivity activity, WindowAndroid nativeWindow,
|
| + TabModelOrderController orderController, TabPersistentStore tabSaver,
|
| + boolean incognito) {
|
| + mActivity = activity;
|
| + mNativeWindow = nativeWindow;
|
| + mOrderController = orderController;
|
| + mTabSaver = tabSaver;
|
| + mIncognito = incognito;
|
| + }
|
| +
|
| + /**
|
| + * Creates a new tab and posts to UI.
|
| + * @param loadUrlParams parameters of the url load.
|
| + * @param type Information about how the tab was launched.
|
| + * @param parent the parent tab, if present.
|
| + * @return The new tab.
|
| + */
|
| + public ChromeTab createNewTab(LoadUrlParams loadUrlParams, TabModel.TabLaunchType type,
|
| + Tab parent) {
|
| + return createNewTab(loadUrlParams, type, parent, null);
|
| + }
|
| +
|
| + /**
|
| + * Creates a new tab and posts to UI.
|
| + * @param loadUrlParams parameters of the url load.
|
| + * @param type Information about how the tab was launched.
|
| + * @param parent the parent tab, if present.
|
| + * @param intent the source of the url if it isn't null.
|
| + * @return The new tab.
|
| + */
|
| + public ChromeTab createNewTab(LoadUrlParams loadUrlParams, TabModel.TabLaunchType type,
|
| + Tab parent, Intent intent) {
|
| + // If parent is in the same tab model, place the new tab next to it.
|
| + int index = mTabModel.indexOf(parent);
|
| + if (index != TabModel.INVALID_TAB_INDEX) {
|
| + return createNewTab(loadUrlParams, type, parent, index + 1, intent);
|
| + }
|
| + return createNewTab(loadUrlParams, type, parent, TabModel.INVALID_TAB_INDEX, intent);
|
| + }
|
| +
|
| + /**
|
| + * Creates a new tab and posts to UI.
|
| + * @param loadUrlParams parameters of the url load.
|
| + * @param type Information about how the tab was launched.
|
| + * @param parent the parent tab, if present.
|
| + * @param position the requested position (index in the tab model)
|
| + * @return The new tab.
|
| + */
|
| + public ChromeTab createNewTab(LoadUrlParams loadUrlParams, TabModel.TabLaunchType type,
|
| + Tab parent, int position) {
|
| + return createNewTab(loadUrlParams, type, parent, position, null);
|
| + }
|
| +
|
| + /**
|
| + * Creates a new tab and posts to UI.
|
| + * @param loadUrlParams parameters of the url load.
|
| + * @param type Information about how the tab was launched.
|
| + * @param parent the parent tab, if present.
|
| + * @param position the requested position (index in the tab model)
|
| + * @param intent the source of the url if it isn't null.
|
| + * @return The new tab.
|
| + */
|
| + public ChromeTab createNewTab(LoadUrlParams loadUrlParams, TabModel.TabLaunchType type,
|
| + Tab parent, int position, Intent intent) {
|
| + try {
|
| + TraceEvent.begin("ChromeTabCreator.createNewTab");
|
| + int parentId = parent != null ? parent.getId() : Tab.INVALID_TAB_ID;
|
| + // Sanitize the url.
|
| + loadUrlParams.setUrl(UrlUtilities.fixupUrl(loadUrlParams.getUrl()));
|
| + loadUrlParams.setTransitionType(getTransitionType(type));
|
| +
|
| + boolean openInForeground = mOrderController.willOpenInForeground(type, mIncognito);
|
| + ChromeTab tab;
|
| + // On low memory devices the tabs opened in background are not loaded automatically to
|
| + // preserve resources (cpu, memory, strong renderer binding) for the foreground tab.
|
| + if (!openInForeground && SysUtils.isLowEndDevice()) {
|
| + tab = ChromeTab.createTabForLazyLoad(mActivity, mIncognito, mNativeWindow, type,
|
| + parentId, loadUrlParams);
|
| + tab.initialize(null, mTabContentManager, !openInForeground);
|
| + mTabSaver.addTabToSaveQueue(tab);
|
| + tab.getTabRedirectHandler().updateIntent(intent);
|
| + } else {
|
| + tab = ChromeTab.createLiveTab(Tab.INVALID_TAB_ID, mActivity, mIncognito,
|
| + mNativeWindow, type, parentId, !openInForeground);
|
| +
|
| + WebContents webContents =
|
| + WarmupManager.getInstance().hasPrerenderedUrl(loadUrlParams.getUrl())
|
| + ? WarmupManager.getInstance().takePrerenderedWebContents() : null;
|
| + tab.initialize(webContents, mTabContentManager, !openInForeground);
|
| + tab.getTabRedirectHandler().updateIntent(intent);
|
| + tab.loadUrl(loadUrlParams);
|
| + }
|
| +
|
| + if (intent != null && intent.hasExtra(ServiceTabLauncher.LAUNCH_REQUEST_ID_EXTRA)) {
|
| + ServiceTabLauncher.onWebContentsForRequestAvailable(
|
| + intent.getIntExtra(ServiceTabLauncher.LAUNCH_REQUEST_ID_EXTRA, 0),
|
| + tab.getWebContents());
|
| + }
|
| +
|
| + mTabModel.addTab(tab, position, type);
|
| +
|
| + return tab;
|
| + } finally {
|
| + TraceEvent.end("ChromeTabCreator.createNewTab");
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Creates a tab around the native web contents pointer.
|
| + * @param webContents The web contents to create a tab around.
|
| + * @param parentId The id of the parent tab.
|
| + * @param type The TabLaunchType describing how this tab was created.
|
| + * @return The created tab.
|
| + */
|
| + public ChromeTab createTabWithWebContents(WebContents webContents, int parentId,
|
| + TabLaunchType type) {
|
| + TabModel model = mTabModel;
|
| +
|
| + // The parent tab was already closed. Do not open child tabs.
|
| + if (model.isClosurePending(parentId)) return null;
|
| +
|
| + int index = TabModelUtils.getTabIndexById(model, parentId);
|
| +
|
| + // If we have a valid parent index increment by one so we add this tab directly after
|
| + // the parent tab.
|
| + if (index >= 0) index++;
|
| +
|
| + boolean selectTab = mOrderController.willOpenInForeground(type, mIncognito);
|
| + ChromeTab tab = ChromeTab.createLiveTab(Tab.INVALID_TAB_ID, mActivity, mIncognito,
|
| + mNativeWindow, type, parentId, !selectTab);
|
| + tab.initialize(webContents, mTabContentManager, !selectTab);
|
| + model.addTab(tab, index, type);
|
| + return tab;
|
| + }
|
| +
|
| + @Override
|
| + public Tab launchNTP() {
|
| + try {
|
| + TraceEvent.begin("ChromeTabCreator.launchNTP");
|
| + ChromeTab tab = launchUrl(UrlConstants.NTP_URL,
|
| + TabModel.TabLaunchType.FROM_MENU_OR_OVERVIEW);
|
| + return tab;
|
| + } finally {
|
| + TraceEvent.end("ChromeTabCreator.launchNTP");
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Creates a new tab and loads the specified URL in it. This is a convenience method for
|
| + * {@link #createNewTab} with the default {@link LoadUrlParams} and no parent tab.
|
| + *
|
| + * @param url the URL to open.
|
| + * @param type the type of action that triggered that launch. Determines how the tab is opened
|
| + * (for example, in the foreground or background).
|
| + * @return the created tab.
|
| + */
|
| + public ChromeTab launchUrl(String url, TabModel.TabLaunchType type) {
|
| + return launchUrl(url, type, null, 0);
|
| + }
|
| +
|
| + /**
|
| + * Creates a new tab and loads the specified URL in it. This is a convenience method for
|
| + * {@link #createNewTab} with the default {@link LoadUrlParams} and no parent tab.
|
| + *
|
| + * @param url the URL to open.
|
| + * @param type the type of action that triggered that launch. Determines how the tab is opened
|
| + * (for example, in the foreground or background).
|
| + * @param intent the source of url if it isn't null.
|
| + * @param intentTimestamp the time the intent was received.
|
| + * @return the created tab.
|
| + */
|
| + public ChromeTab launchUrl(String url, TabModel.TabLaunchType type, Intent intent,
|
| + long intentTimestamp) {
|
| + LoadUrlParams loadUrlParams = new LoadUrlParams(url);
|
| + loadUrlParams.setIntentReceivedTimestamp(intentTimestamp);
|
| + return createNewTab(loadUrlParams, type, null, intent);
|
| + }
|
| +
|
| + /**
|
| + * Opens the specified URL into a tab, potentially reusing a tab. Typically if a user opens
|
| + * several link from the same application, we reuse the same tab so as to not open too many
|
| + * tabs.
|
| + * @param url the URL to open
|
| + * @param headers HTTP headers to send alongside the URL.
|
| + * @param appId the ID of the application that triggered that URL navigation.
|
| + * @param forceNewTab whether the URL should be opened in a new tab. If false, an existing tab
|
| + * already opened by the same app will be reused.
|
| + * @param intent the source of url if it isn't null.
|
| + * @param intentTimestamp the time the intent was received.
|
| + * @return the tab the URL was opened in, could be a new tab or a reused one.
|
| + */
|
| + public ChromeTab launchUrlFromExternalApp(String url, String headers, String appId,
|
| + boolean forceNewTab, Intent intent, long intentTimestamp) {
|
| + assert !mIncognito;
|
| + boolean isLaunchedFromChrome = TextUtils.equals(appId, mActivity.getPackageName());
|
| + if (forceNewTab && !isLaunchedFromChrome) {
|
| + // We don't associate the tab with that app ID, as it is assumed that if the
|
| + // application wanted to open this tab as a new tab, it probably does not want it
|
| + // reused either.
|
| + LoadUrlParams loadUrlParams = new LoadUrlParams(url);
|
| + loadUrlParams.setIntentReceivedTimestamp(intentTimestamp);
|
| + loadUrlParams.setVerbatimHeaders(headers);
|
| + return createNewTab(loadUrlParams, TabLaunchType.FROM_EXTERNAL_APP, null, intent);
|
| + }
|
| +
|
| + if (appId == null) {
|
| + // If we have no application ID, we use a made-up one so that these tabs can be
|
| + // reused.
|
| + appId = TabModelImpl.UNKNOWN_APP_ID;
|
| + }
|
| + // Let's try to find an existing tab that was started by that app.
|
| + for (int i = 0; i < mTabModel.getCount(); i++) {
|
| + Tab tab = mTabModel.getTabAt(i);
|
| + if (appId.equals(tab.getAppAssociatedWith())) {
|
| + // We don't reuse the tab, we create a new one at the same index instead.
|
| + // Reusing a tab would require clearing the navigation history and clearing the
|
| + // contents (we would not want the previous content to show).
|
| + LoadUrlParams loadUrlParams = new LoadUrlParams(url);
|
| + loadUrlParams.setIntentReceivedTimestamp(intentTimestamp);
|
| + ChromeTab newTab = createNewTab(
|
| + loadUrlParams, TabLaunchType.FROM_EXTERNAL_APP, null, i, intent);
|
| + newTab.setAppAssociatedWith(appId);
|
| + mTabModel.closeTab(tab, false, false, false);
|
| + return newTab;
|
| + }
|
| + }
|
| +
|
| + // No tab for that app, we'll have to create a new one.
|
| + ChromeTab tab = launchUrl(url, TabLaunchType.FROM_EXTERNAL_APP, intent, intentTimestamp);
|
| + tab.setAppAssociatedWith(appId);
|
| + return tab;
|
| + }
|
| +
|
| + @Override
|
| + public void createFrozenTab(TabState state, int id, int index) {
|
| + ChromeTab tab = ChromeTab.createFrozenTabFromState(
|
| + id, mActivity, state.isIncognito(), mNativeWindow, state.parentId, state);
|
| + boolean selectTab = mOrderController.willOpenInForeground(TabLaunchType.FROM_RESTORE,
|
| + state.isIncognito());
|
| + tab.initialize(null, mTabContentManager, !selectTab);
|
| + assert state.isIncognito() == mIncognito;
|
| + mTabModel.addTab(tab, index, TabLaunchType.FROM_RESTORE);
|
| + }
|
| +
|
| + /**
|
| + * @param type Type of the tab launch.
|
| + * @return The page transition type constant.
|
| + */
|
| + private static int getTransitionType(TabLaunchType type) {
|
| + switch (type) {
|
| + case FROM_LINK:
|
| + case FROM_EXTERNAL_APP:
|
| + return PageTransition.LINK | PageTransition.FROM_API;
|
| + case FROM_MENU_OR_OVERVIEW:
|
| + case FROM_LONGPRESS_FOREGROUND:
|
| + case FROM_LONGPRESS_BACKGROUND:
|
| + case FROM_KEYBOARD:
|
| + return PageTransition.AUTO_TOPLEVEL;
|
| + default:
|
| + assert false;
|
| + return PageTransition.LINK;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Sets the tab model and tab content manager to use.
|
| + * @param model The new {@link TabModel} to use.
|
| + * @param manager The new {@link TabContentManager} to use.
|
| + */
|
| + public void setTabModel(TabModel model, TabContentManager manager) {
|
| + mTabModel = model;
|
| + mTabContentManager = manager;
|
| + }
|
| +
|
| +}
|
|
|