Index: chrome/android/java_staging/src/org/chromium/chrome/browser/tabmodel/TabWindowManager.java |
diff --git a/chrome/android/java_staging/src/org/chromium/chrome/browser/tabmodel/TabWindowManager.java b/chrome/android/java_staging/src/org/chromium/chrome/browser/tabmodel/TabWindowManager.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a7f623b2fc5f8f29d31d7822a0d14562879c544b |
--- /dev/null |
+++ b/chrome/android/java_staging/src/org/chromium/chrome/browser/tabmodel/TabWindowManager.java |
@@ -0,0 +1,180 @@ |
+// 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.app.Activity; |
+ |
+import org.chromium.base.ActivityState; |
+import org.chromium.base.ApplicationStatus; |
+import org.chromium.base.ApplicationStatus.ActivityStateListener; |
+import org.chromium.base.ThreadUtils; |
+import org.chromium.base.VisibleForTesting; |
+import org.chromium.chrome.browser.ChromeActivity; |
+import org.chromium.ui.base.WindowAndroid; |
+ |
+import java.util.ArrayList; |
+import java.util.HashMap; |
+import java.util.List; |
+import java.util.Map; |
+ |
+/** |
+ * Manages multiple {@link TabModelSelector} instances, each owned by different {@link Activity}s. |
+ */ |
+public class TabWindowManager implements ActivityStateListener { |
+ /** |
+ * An index that represents the invalid state (i.e. when the window wasn't found in the list. |
+ */ |
+ public static final int INVALID_WINDOW_INDEX = -1; |
+ |
+ /** The maximum number of simultaneous TabModelSelector instances in this Application. */ |
+ @VisibleForTesting |
+ public static final int MAX_SIMULTANEOUS_SELECTORS = 3; |
+ |
+ /** |
+ * A factory interface for building a {@link TabModelSelector} instance. |
+ */ |
+ public interface TabModelSelectorFactory { |
+ /** |
+ * Builds a {@link TabModelSelector}. |
+ * @param activity A {@link ChromeActivity} instance. |
+ * @param windowAndroid A {@link WindowAndroid} instance that should connect to |
+ * {@code activity}. |
+ * @param selectorIndex The index of the {@link TabModelSelector}. |
+ * @return A new {@link TabModelSelector} instance. |
+ */ |
+ TabModelSelector buildSelector(ChromeActivity activity, WindowAndroid windowAndroid, |
+ int selectorIndex); |
+ } |
+ |
+ /** The singleton reference. */ |
+ private static TabWindowManager sInstance; |
+ |
+ private TabModelSelectorFactory mSelectorFactory = new DefaultTabModelSelectorFactory(); |
+ |
+ private List<TabModelSelector> mSelectors = new ArrayList<TabModelSelector>(); |
+ |
+ private Map<Activity, TabModelSelector> mAssignments = |
+ new HashMap<Activity, TabModelSelector>(); |
+ |
+ /** |
+ * @return The singleton instance of {@link TabWindowManager}. |
+ */ |
+ public static TabWindowManager getInstance() { |
+ ThreadUtils.assertOnUiThread(); |
+ if (sInstance == null) sInstance = new TabWindowManager(); |
+ return sInstance; |
+ } |
+ |
+ /** |
+ * Called to request a {@link TabModelSelector} based on {@code index}. Note that the |
+ * {@link TabModelSelector} returned might not actually be the one related to {@code index} |
+ * and {@link #getIndexForWindow(Activity)} should be called to grab the actual index if |
+ * required. |
+ * @param activity An instance of {@link ChromeActivity}. Must be the same {@link Activity} as |
+ * the one referenced by {@code window}. |
+ * @param window A {@link WindowAndroid} as an instance. The {@link TabModelSelector} that is |
+ * created is bound to the {@link Activity} stored inside this window. |
+ * @param index The index of the requested {@link TabModelSelector}. Not guaranteed to be |
+ * the index of the {@link TabModelSelector} returned. |
+ * @return A {@link TabModelSelector} index, or {@code null} if there are too many |
+ * {@link TabModelSelector}s already built. |
+ */ |
+ public TabModelSelector requestSelector(ChromeActivity activity, WindowAndroid window, |
+ int index) { |
+ if (mAssignments.get(activity) != null) { |
+ return mAssignments.get(activity); |
+ } |
+ |
+ if (index < 0 || index >= mSelectors.size()) index = 0; |
+ |
+ if (mSelectors.get(index) != null) { |
+ for (int i = 0; i < mSelectors.size(); i++) { |
+ if (mSelectors.get(i) == null) { |
+ index = i; |
+ break; |
+ } |
+ } |
+ } |
+ |
+ // Too many activities going at once. |
+ if (mSelectors.get(index) != null) return null; |
+ |
+ TabModelSelector selector = mSelectorFactory.buildSelector(activity, window, index); |
+ mSelectors.set(index, selector); |
+ mAssignments.put(activity, selector); |
+ |
+ return selector; |
+ } |
+ |
+ /** |
+ * Finds the current index of the {@link TabModelSelector} bound to {@code window}. |
+ * @param activity The {@link Activity} to find the index of the {@link TabModelSelector} |
+ * for. This uses the underlying {@link Activity} stored in the |
+ * {@link WindowAndroid}. |
+ * @return The index of the {@link TabModelSelector} or {@link #INVALID_WINDOW_INDEX} if |
+ * not found. |
+ */ |
+ public int getIndexForWindow(Activity activity) { |
+ if (activity == null) return INVALID_WINDOW_INDEX; |
+ TabModelSelector selector = mAssignments.get(activity); |
+ if (selector == null) return INVALID_WINDOW_INDEX; |
+ int index = mSelectors.indexOf(selector); |
+ return index == -1 ? INVALID_WINDOW_INDEX : index; |
+ } |
+ |
+ /** |
+ * @return The number of {@link TabModelSelector}s currently assigned to {@link Activity}s. |
+ */ |
+ public int getNumberOfAssignedTabModelSelectors() { |
+ return mAssignments.size(); |
+ } |
+ |
+ /** |
+ * @return The total number of incognito tabs across all tab model selectors. |
+ */ |
+ public int getIncognitoTabCount() { |
+ int count = 0; |
+ for (int i = 0; i < mSelectors.size(); i++) { |
+ if (mSelectors.get(i) != null) { |
+ count += mSelectors.get(i).getModel(true).getCount(); |
+ } |
+ } |
+ return count; |
+ } |
+ |
+ @Override |
+ public void onActivityStateChange(Activity activity, int newState) { |
+ if (newState == ActivityState.DESTROYED && mAssignments.containsKey(activity)) { |
+ int index = mSelectors.indexOf(mAssignments.remove(activity)); |
+ if (index >= 0) mSelectors.set(index, null); |
+ // TODO(dtrainor): Move TabModelSelector#destroy() calls here. |
+ } |
+ } |
+ |
+ /** |
+ * Allows overriding the default {@link TabModelSelectorFactory} with another one. Typically |
+ * for testing. |
+ * @param factory A {@link TabModelSelectorFactory} instance. |
+ */ |
+ @VisibleForTesting |
+ public void setTabModelSelectorFactory(TabModelSelectorFactory factory) { |
+ mSelectorFactory = factory; |
+ } |
+ |
+ private TabWindowManager() { |
+ ApplicationStatus.registerStateListenerForAllActivities(this); |
+ |
+ for (int i = 0; i < MAX_SIMULTANEOUS_SELECTORS; i++) mSelectors.add(null); |
+ } |
+ |
+ private static class DefaultTabModelSelectorFactory implements TabModelSelectorFactory { |
+ @Override |
+ public TabModelSelector buildSelector(ChromeActivity activity, WindowAndroid windowAndroid, |
+ int selectorIndex) { |
+ assert activity == windowAndroid.getActivity().get(); |
+ return new TabModelSelectorImpl(activity, selectorIndex, windowAndroid); |
+ } |
+ } |
+} |