Commit 27a0245d authored by bauerb@chromium.org's avatar bauerb@chromium.org

Upstream TabModel and related classes.

BUG=318769

Review URL: https://codereview.chromium.org/207743004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@269598 0039d316-1c4b-4281-b951-d872f2087c98
parent 53f18455
// Copyright 2014 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 org.chromium.chrome.browser.Tab;
/**
* A read only list of {@link Tab}s. This list understands the concept of an incognito list as
* well as a currently selected tab (see {@link #index}).
*/
public interface TabList {
public static final int INVALID_TAB_INDEX = -1;
/**
* @return Whether this tab model contains only incognito tabs or only normal tabs.
*/
boolean isIncognito();
/**
* @return The index of the current tab, or {@link #INVALID_TAB_INDEX} if there are no tabs.
*/
int index();
/**
* @return the number of open tabs in this model
*/
int getCount();
/**
* Get the tab at the specified position
*
* @param index The index of the {@link Tab} to return.
* @return The {@code Tab} at position {@code index}, or {@code null} if {@code index} < 0
* or {@code index} >= {@link #getCount()}.
*/
Tab getTabAt(int index);
/**
* @return index of the given tab in the order of the tab stack.
*/
int indexOf(Tab tab);
/**
* @param tabId The id of the {@link Tab} that might have a pending closure.
* @return Whether or not the {@link Tab} specified by {@code tabId} has a pending
* closure.
*/
boolean isClosurePending(int tabId);
}
\ No newline at end of file
// Copyright 2014 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 org.chromium.chrome.browser.Tab;
import org.chromium.chrome.browser.profiles.Profile;
/**
* TabModel organizes all the open tabs and allows you to create new ones. There are two TabModels
* in the app at this time: normal and incognito. More could be added to allow for windows or
* something.
*/
public interface TabModel extends TabList {
/**
* A list of the various ways tabs can be launched.
*/
public enum TabLaunchType {
FROM_LINK, // Opened from a link.
FROM_EXTERNAL_APP, // Opened by and external app.
FROM_MENU_OR_OVERVIEW, // Opened from the options menu or the tab stack overview.
FROM_RESTORE, // Opened after restoring state from storage.
// Opened from the long press menu. Like FROM_MENU but also sets up a parent/child
// relationship like FROM_LINK. FOREGROUND and BACKGROUND indicates whether the current tab
// should be automatically switched to the new tab or not.
FROM_LONGPRESS_FOREGROUND,
FROM_LONGPRESS_BACKGROUND,
FROM_INSTANT, // Tab was created by instant.
FROM_KEYBOARD // Opened from a physical keyboard via shortcut.
}
/**
* A list of the various ways tabs can eb selected.
*/
public enum TabSelectionType {
FROM_CLOSE, // Selection of adjacent tab when the active tab is closed in foreground.
FROM_EXIT, // Selection of adjacent tab when the active tab is closed upon app exit.
FROM_NEW, // Selection of newly created tab (e.g. for a url intent or NTP).
FROM_USER // User-originated switch to existing tab or selection of main tab on app
// startup.
}
/**
* @return The profile associated with the current model.
*/
public Profile getProfile();
/**
* Unregisters and destroys the specified tab, and then switches to the previous tab.
* @param tab The non-null tab to close
* @return true if the tab was found
*/
public boolean closeTab(Tab tab);
/**
* Unregisters and destroys the specified tab, and then switches to the previous tab.
*
* @param tab The non-null tab to close
* @param animate true iff the closing animation should be displayed
* @param uponExit true iff the tab is being closed upon application exit (after user presses
* the system back button)
* @param canUndo Whether or not this action can be undone. If this is {@code true} and
* {@link #supportsPendingClosures()} is {@code true}, this {@link Tab}
* will not actually be closed until {@link #commitTabClosure(int)} or
* {@link #commitAllTabClosures()} is called, but it will be effectively removed
* from this list. To get a comprehensive list of all tabs, including ones that
* have been partially closed, use the {@link TabList} from
* {@link #getComprehensiveModel()}.
* @return true if the tab was found
*/
public boolean closeTab(Tab tab, boolean animate, boolean uponExit, boolean canUndo);
/**
* Returns which tab would be selected if the specified tab {@code id} were closed.
* @param id The ID of tab which would be closed.
* @return The id of the next tab that would be visible.
*/
public Tab getNextTabIfClosed(int id);
/**
* Close all the tabs on this model.
*/
public void closeAllTabs();
/**
* @return Whether or not this model supports pending closures.
*/
public boolean supportsPendingClosures();
/**
* Commits all pending closures, closing all tabs that had a chance to be undone.
*/
public void commitAllTabClosures();
/**
* Commits a pending closure specified by {@code tabId}.
* @param tabId The id of the {@link Tab} to commit the pending closure.
*/
public void commitTabClosure(int tabId);
/**
* Cancels a pending {@link Tab} closure, bringing the tab back into this model. Note that this
* will select the rewound {@link Tab}.
* @param tabId The id of the {@link Tab} to undo.
*/
public void cancelTabClosure(int tabId);
/**
* @return The complete {@link TabList} this {@link TabModel} represents. Note that this may
* be different than this actual {@link TabModel} if it supports pending closures
* {@link #supportsPendingClosures()}, as this will include all pending closure tabs.
*/
public TabList getComprehensiveModel();
/**
* Selects a tab by its index.
* @param i The index of the tab to select.
* @param type The type of selection.
*/
public void setIndex(int i, final TabSelectionType type);
/**
* Moves a tab to a new index.
* @param id The id of the tab to move.
* @param newIndex The new place to put the tab.
*/
public void moveTab(int id, int newIndex);
/**
* To be called when this model should be destroyed. The model should no longer be used after
* this.
*/
public void destroy();
/**
* Adds a newly created tab to this model.
* @param tab The tab to be added.
* @param index The index where the tab should be inserted. The model may override the index.
* @param type How the tab was opened.
*/
void addTab(Tab tab, int index, TabLaunchType type);
/**
* Subscribes a {@link TabModelObserver} to be notified about changes to this model.
* @param observer The observer to be subscribed.
*/
void addObserver(TabModelObserver observer);
/**
* Unsubscribes a previously subscribed {@link TabModelObserver}.
* @param observer The observer to be unsubscribed.
*/
void removeObserver(TabModelObserver observer);
}
// Copyright 2014 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 org.chromium.chrome.browser.Tab;
import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
/**
* An interface to be notified about changes to a TabModel.
*/
public interface TabModelObserver {
/**
* Called when a tab is selected.
*
* @param tab The newly selected tab.
* @param type The type of selection.
* @param lastId The ID of the last selected tab, or {@link Tab#INVALID_TAB_ID} if no tab was
* selected.
*/
void didSelectTab(Tab tab, TabSelectionType type, int lastId);
/**
* Called when a tab starts closing.
*
* @param tab The tab to close.
* @param animate Whether or not to animate the closing.
*/
void willCloseTab(Tab tab, boolean animate);
/**
* Called right after {@code tab} has been destroyed.
*
* @param tab The tab that has been destroyed.
*/
void didCloseTab(Tab tab);
/**
* Called before a tab will be added to the {@link TabModel}.
*
* @param tab The tab about to be added.
* @param type The type of tab launch.
*/
void willAddTab(Tab tab, TabLaunchType type);
/**
* Called after a tab has been added to the {@link TabModel}.
*
* @param tab The newly added tab.
* @param type The type of tab launch.
*/
void didAddTab(Tab tab, TabLaunchType type);
/**
* Called after a tab has been moved from one position in the {@link TabModel} to another.
*
* @param tab The tab which has been moved.
* @param newIndex The new index of the tab in the model.
* @param curIndex The old index of the tab in the model.
*/
void didMoveTab(Tab tab, int newIndex, int curIndex);
/**
* Called when a tab is pending closure, i.e. the user has just closed it, but it can still be
* undone.
*
* @param tab The tab that is pending closure.
*/
void tabPendingClosure(Tab tab);
/**
* Called when a tab closure is undone.
*
* @param tab The tab that has been reopened.
*/
void tabClosureUndone(Tab tab);
/**
* Called when a tab closure is committed and can't be undone anymore.
*
* @param tab The tab that has been closed.
*/
void tabClosureCommitted(Tab tab);
}
// Copyright 2014 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 org.chromium.chrome.browser.Tab;
import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
import org.chromium.content.browser.LoadUrlParams;
import java.util.List;
/**
* TabModelSelector is a wrapper class containing both a normal and an incognito TabModel.
* This class helps the app know which mode it is currently in, and which TabModel it should
* be using.
*/
public interface TabModelSelector {
/**
* Interface of listener that get notified on changes in the {@link TabModel}s.
*/
public interface ChangeListener {
/**
* Called whenever the {@link TabModel} has changed.
*/
void onChange();
/**
* Called when a new tab is created.
*/
void onNewTabCreated(Tab tab);
}
/**
* Set the current model. This won't cause an animation, but will still change the stack that is
* currently visible if the tab switcher is open.
*/
void selectModel(boolean incognito);
/**
* Get a specific tab model
* @return Never returns null. Returns a stub when real model is uninitialized.
*/
TabModel getModel(boolean incognito);
/**
* @return a list for the underlying models
*/
List<TabModel> getModels();
/**
* @return the model at {@code index} or null if no model exist for that index.
*/
TabModel getModelAt(int index);
/**
* Get the current tab model.
* @return Never returns null. Returns a stub when real model is uninitialized.
*/
TabModel getCurrentModel();
/**
* Convenience function to get the current tab on the current model
* @return Current tab or null if none exists or if the model is not initialized.
*/
Tab getCurrentTab();
/**
* Convenience function to get the current tab id on the current model.
* @return Id of the current tab or {@link Tab#INVALID_TAB_ID} if no tab is selected or the
* model is not initialized.
*/
int getCurrentTabId();
/**
* Convenience function to get the {@link TabModel} for a {@link Tab} specified by
* {@code id}.
* @param id The id of the {@link Tab} to find the {@link TabModel} for.
* @return The {@link TabModel} that owns the {@link Tab} specified by {@code id}.
*/
TabModel getModelForTabId(int id);
/**
* @return The index of the current {@link TabModel}.
*/
int getCurrentModelIndex();
/**
* @return If the incognito {@link TabModel} is current.
*/
boolean isIncognitoSelected();
/**
* Opens a new tab.
*
* @param loadUrlParams parameters of the url load
* @param type Describes how the new tab is being opened.
* @param parent The parent tab for this new tab (or null if one does not exist).
* @param incognito Whether to open the new tab in incognito mode.
* @return The newly opened tab.
*/
Tab openNewTab(LoadUrlParams loadUrlParams, TabLaunchType type, Tab parent, boolean incognito);
/**
* Searches through all children models for the specified Tab and closes the tab if it exists.
* @param tab the non-null tab to close
* @return true if the tab was found
*/
boolean closeTab(Tab tab);
/**
* Close all tabs across all tab models
*/
void closeAllTabs();
/**
* Get total tab count across all tab models
*/
int getTotalTabCount();
/**
* Search all TabModels for a tab with the specified id.
* @return specified tab or null if tab is not found
*/
Tab getTabById(int id);
/**
* Registers a listener that get notified when the {@link TabModel} changes. Multiple listeners
* can be registered at the same time.
* @param changeListener The {@link TabModelSelector.ChangeListener} to notify.
*/
void registerChangeListener(ChangeListener changeListener);
/**
* Unregisters the listener.
* @param changeListener The {@link TabModelSelector.ChangeListener} to remove.
*/
void unregisterChangeListener(ChangeListener changeListener);
/**
* Calls {@link TabModel#commitAllTabClosures()} on all {@link TabModel}s owned by this
* selector.
*/
void commitAllTabClosures();
}
// Copyright 2014 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 org.chromium.chrome.browser.Tab;
import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
import org.chromium.content.browser.ContentViewCore;
/**
* A set of convenience methods used for interacting with {@link TabList}s and {@link TabModel}s.
*/
public class TabModelUtils {
private TabModelUtils() { }
/**
* @param model The {@link TabModel} to act on.
* @param index The index of the {@link Tab} to close.
* @return {@code true} if the {@link Tab} was found.
*/
public static boolean closeTabByIndex(TabModel model, int index) {
Tab tab = model.getTabAt(index);
if (tab == null) return false;
return model.closeTab(tab);
}
/**
* @param model The {@link TabModel} to act on.
* @param tabId The id of the {@link Tab} to close.
* @return {@code true} if the {@link Tab} was found.
*/
public static boolean closeTabById(TabModel model, int tabId) {
return closeTabById(model, tabId, false);
}
/**
* @param model The {@link TabModel} to act on.
* @param tabId The id of the {@link Tab} to close.
* @param canUndo Whether or not this closure can be undone.
* @return {@code true} if the {@link Tab} was found.
*/
public static boolean closeTabById(TabModel model, int tabId, boolean canUndo) {
Tab tab = TabModelUtils.getTabById(model, tabId);
if (tab == null) return false;
return model.closeTab(tab, true, false, canUndo);
}
/**
* @param model The {@link TabModel} to act on.
* @return {@code true} if the {@link Tab} was found.
*/
public static boolean closeCurrentTab(TabModel model) {
Tab tab = TabModelUtils.getCurrentTab(model);
if (tab == null) return false;
return model.closeTab(tab);
}
/**
* Find the index of the {@link Tab} with the specified id.
* @param model The {@link TabModel} to act on.
* @param tabId The id of the {@link Tab} to find.
* @return Specified {@link Tab} index or {@link TabList#INVALID_TAB_INDEX} if the
* {@link Tab} is not found
*/
public static int getTabIndexById(TabList model, int tabId) {
int count = model.getCount();
for (int i = 0; i < count; i++) {
Tab tab = model.getTabAt(i);
if (tab.getId() == tabId) return i;
}
return TabModel.INVALID_TAB_INDEX;
}
/**
* Find the {@link Tab} with the specified id.
* @param model The {@link TabModel} to act on.
* @param tabId The id of the {@link Tab} to find.
* @return Specified {@link Tab} or {@code null} if the {@link Tab} is not found
*/
public static Tab getTabById(TabList model, int tabId) {
int index = getTabIndexById(model, tabId);
if (index == TabModel.INVALID_TAB_INDEX) return null;
return model.getTabAt(index);
}
/**
* Find the {@link Tab} index whose URL matches the specified URL.
* @param model The {@link TabModel} to act on.
* @param url The URL to search for.
* @return Specified {@link Tab} or {@code null} if the {@link Tab} is not found
*/
public static int getTabIndexByUrl(TabList model, String url) {
int count = model.getCount();
for (int i = 0; i < count; i++) {
if (model.getTabAt(i).getUrl().contentEquals(url)) return i;
}
return TabModel.INVALID_TAB_INDEX;
}
/**
* Get the currently selected {@link Tab} id.
* @param model The {@link TabModel} to act on.
* @return The id of the currently selected {@link Tab}.
*/
public static int getCurrentTabId(TabList model) {
Tab tab = getCurrentTab(model);
if (tab == null) return Tab.INVALID_TAB_ID;
return tab.getId();
}
/**
* Get the currently selected {@link Tab}.
* @param model The {@link TabModel} to act on.
* @returns The current {@link Tab} or {@code null} if no {@link Tab} is selected
*/
public static Tab getCurrentTab(TabList model) {
int index = model.index();
if (index == TabModel.INVALID_TAB_INDEX) return null;
return model.getTabAt(index);
}
/**
* @param model The {@link TabModel} to act on.
* @return The currently active {@link ContentViewCore}, or {@code null} if no {@link Tab}
* is selected or the selected {@link Tab} has no current {@link ContentViewCore}.
*/
public static ContentViewCore getCurrentContentViewCore(TabList model) {
Tab tab = getCurrentTab(model);
if (tab == null) return null;
return tab.getContentViewCore();
}
/**
* A helper method that automatically passes {@link TabSelectionType#FROM_USER} as the selection
* type to {@link TabModel#setIndex(int, TabSelectionType)}.
* @param model The {@link TabModel} to act on.
* @param index The index of the {@link Tab} to select.
*/
public static void setIndex(TabModel model, int index) {
model.setIndex(index, TabSelectionType.FROM_USER);
}
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment