@Override public TabModel getModelForTabId(int id) { for (int i = 0; i < mTabModels.size(); i++) { TabModel model = mTabModels.get(i); if (TabModelUtils.getTabById(model, id) != null || model.isClosurePending(id)) { return model; } } return null; }
@Override public boolean closeTab(Tab tab) { for (int i = 0; i < getModels().size(); i++) { TabModel model = getModelAt(i); if (model.indexOf(tab) >= 0) { return model.closeTab(tab); } } assert false : "Tried to close a tab that is not in any model!"; return false; }
/** * 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 referer The referer url if provided, null otherwise. * @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 Tab launchUrlFromExternalApp( String url, String referer, 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); if (referer != null) { loadUrlParams.setReferrer(new Referrer(referer, Referrer.REFERRER_POLICY_DEFAULT)); } 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. Tab tab = launchUrl(url, TabLaunchType.FROM_EXTERNAL_APP, intent, intentTimestamp); tab.setAppAssociatedWith(appId); return tab; }
public InspectorModel getInspectorModel() { if (tabModel != null) { return tabModel.getInspectorModel(); } else { logger.warning("TabModel is null !"); return 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); }
@Override public Tab 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); return tab; }
@Override public void selectModel(boolean incognito) { TabModel oldModel = getCurrentModel(); super.selectModel(incognito); TabModel newModel = getCurrentModel(); if (oldModel != newModel) { TabModelUtils.setIndex(newModel, newModel.index()); // Make the call to notifyDataSetChanged() after any delayed events // have had a chance to fire. Otherwise, this may result in some // drawing to occur before animations have a chance to work. new Handler() .post( new Runnable() { @Override public void run() { notifyChanged(); } }); } }
@Override public ChromeTab createTabWithWebContents( WebContents webContents, int parentId, TabLaunchType type, String url) { 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; }
protected final void initialize(boolean startIncognito, TabModel... models) { // Only normal and incognito supported for now. assert mTabModels.isEmpty(); assert models.length > 0; if (startIncognito) { assert models.length > INCOGNITO_TAB_MODEL_INDEX; } List<TabModel> tabModels = new ArrayList<TabModel>(); for (int i = 0; i < models.length; i++) { tabModels.add(models[i]); } mActiveModelIndex = startIncognito ? INCOGNITO_TAB_MODEL_INDEX : NORMAL_TAB_MODEL_INDEX; mTabModels = Collections.unmodifiableList(tabModels); TabModelObserver tabModelObserver = new EmptyTabModelObserver() { @Override public void didAddTab(Tab tab, TabLaunchType type) { notifyChanged(); notifyNewTabCreated(tab); } @Override public void didSelectTab(Tab tab, TabSelectionType type, int lastId) { notifyChanged(); } @Override public void didMoveTab(Tab tab, int newIndex, int curIndex) { notifyChanged(); } }; for (TabModel model : models) { model.addObserver(tabModelObserver); } notifyChanged(); }
/** * 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; WebContents webContents = IntentHandler.getWebContentsFromIntent(intent); boolean isWebContentsPaused = false; if (webContents != null) { // The WebContents comes with additional data, but it shouldn't be used if the // WebContents itself couldn't be parsed out. parentId = IntentUtils.safeGetIntExtra( intent, IntentHandler.EXTRA_PARENT_TAB_ID, Tab.INVALID_TAB_ID); isWebContentsPaused = IntentUtils.safeGetBooleanExtra(intent, IntentHandler.EXTRA_WEB_CONTENTS_PAUSED, false); } // Sanitize the url. loadUrlParams.setUrl(UrlUtilities.fixupUrl(loadUrlParams.getUrl())); loadUrlParams.setTransitionType(getTransitionType(type)); boolean openInForeground = mOrderController.willOpenInForeground(type, mIncognito) || webContents != null; ChromeTab tab; if (webContents != null) { tab = ChromeTab.createLiveTab( Tab.INVALID_TAB_ID, mActivity, mIncognito, mNativeWindow, type, parentId, !openInForeground); tab.initialize(webContents, mTabContentManager, !openInForeground); tab.getTabRedirectHandler().updateIntent(intent); if (isWebContentsPaused) webContents.resumeLoadingCreatedWebContents(); } else if (!openInForeground && SysUtils.isLowEndDevice()) { // 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. 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 = 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"); } }