Commit 61515bd2 authored by Mei Liang's avatar Mei Liang Committed by Commit Bot

[TabModelFilter] Integrate TabModelFilter into existed UI

This CL integrates TabModelFilter into the following UI:
  * TabCountProvider
  * LayoutManager
and changes these UIs to wait for events from TabModelFilter instead
of TabModel.

TabModelFilters are provided by TabModelFilterProvider class. They
observe TabModel changes and notify their observers about the changes.

Bug: 930960
Change-Id: Iad95594f9b3f9002103fcac564f2197468cbee58
Reviewed-on: https://chromium-review.googlesource.com/c/1464118
Commit-Queue: Mei Liang <meiliang@chromium.org>
Reviewed-by: default avatarDavid Trainor <dtrainor@chromium.org>
Reviewed-by: default avatarYusuf Ozuysal <yusufo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#635215}
parent 5e12be67
......@@ -90,9 +90,12 @@ public class LayoutManager implements LayoutUpdateHost, LayoutProvider,
// External Dependencies
private TabModelSelector mTabModelSelector;
private TabModelObserver mTabModelObserver;
private TabModelSelectorObserver mTabModelSelectorObserver;
private TabModelSelectorTabObserver mTabModelSelectorTabObserver;
// An observer for watching TabModelFilters changes events.
private TabModelObserver mTabModelFilterObserver;
private ViewGroup mContentContainer;
// External Observers
......@@ -442,8 +445,9 @@ public class LayoutManager implements LayoutUpdateHost, LayoutProvider,
selector.addObserver(mTabModelSelectorObserver);
selector.setCloseAllTabsDelegate(this);
mTabModelObserver = createTabModelObserver();
for (TabModel model : selector.getModels()) model.addObserver(mTabModelObserver);
mTabModelFilterObserver = createTabModelObserver();
getTabModelSelector().getTabModelFilterProvider().addTabModelFilterObserver(
mTabModelFilterObserver);
}
/**
......@@ -458,10 +462,9 @@ public class LayoutManager implements LayoutUpdateHost, LayoutProvider,
if (mTabModelSelectorObserver != null) {
getTabModelSelector().removeObserver(mTabModelSelectorObserver);
}
if (mTabModelObserver != null) {
for (TabModel model : getTabModelSelector().getModels()) {
model.removeObserver(mTabModelObserver);
}
if (mTabModelFilterObserver != null) {
getTabModelSelector().getTabModelFilterProvider().removeTabModelFilterObserver(
mTabModelFilterObserver);
}
}
......
......@@ -107,16 +107,18 @@ public class LayoutManagerChrome extends LayoutManager implements OverviewModeBe
TabContentManager content, ViewGroup androidContentContainer,
ContextualSearchManagementDelegate contextualSearchDelegate,
DynamicResourceLoader dynamicResourceLoader) {
super.init(selector, creator, content, androidContentContainer, contextualSearchDelegate,
dynamicResourceLoader);
// TODO: TitleCache should be a part of the ResourceManager.
mTitleCache = mHost.getTitleCache();
// Initialize Layouts
mToolbarSwipeLayout.setTabModelSelector(selector, content);
mOverviewListLayout.setTabModelSelector(selector, content);
if (mOverviewLayout != null) mOverviewLayout.setTabModelSelector(selector, content);
super.init(selector, creator, content, androidContentContainer, contextualSearchDelegate,
dynamicResourceLoader);
if (mOverviewLayout != null) {
mOverviewLayout.setTabModelSelector(selector, content);
}
}
/**
......
......@@ -49,11 +49,11 @@ public class LayoutManagerChromePhone extends LayoutManagerChrome {
TabContentManager content, ViewGroup androidContentContainer,
ContextualSearchManagementDelegate contextualSearchDelegate,
DynamicResourceLoader dynamicResourceLoader) {
// Initialize Layouts
mSimpleAnimationLayout.setTabModelSelector(selector, content);
super.init(selector, creator, content, androidContentContainer, contextualSearchDelegate,
dynamicResourceLoader);
// Initialize Layouts
mSimpleAnimationLayout.setTabModelSelector(selector, content);
}
@Override
......
......@@ -53,8 +53,8 @@ public class StackLayout extends StackLayoutBase {
public void setTabModelSelector(TabModelSelector modelSelector, TabContentManager manager) {
super.setTabModelSelector(modelSelector, manager);
ArrayList<TabList> tabLists = new ArrayList<TabList>();
tabLists.add(modelSelector.getModel(false));
tabLists.add(modelSelector.getModel(true));
tabLists.add(modelSelector.getTabModelFilterProvider().getTabModelFilter(false));
tabLists.add(modelSelector.getTabModelFilterProvider().getTabModelFilter(true));
setTabLists(tabLists);
}
......
......@@ -30,6 +30,13 @@ public class IncognitoTabModel implements TabModel {
/** @return Whether Incognito Tabs exist. */
boolean doIncognitoTabsExist();
/**
* @param model {@link TabModel} to act on.
* @return Whether the provided {@link TabModel} is currently selected in the corresponding
* {@link IncognitoTabModelDelegate}.
*/
boolean isCurrentModel(TabModel model);
}
private final IncognitoTabModelDelegate mDelegate;
......@@ -166,7 +173,7 @@ public class IncognitoTabModel implements TabModel {
@Override
public boolean isCurrentModel() {
return mDelegateModel.isCurrentModel();
return mDelegate.isCurrentModel(this);
}
@Override
......
......@@ -59,4 +59,9 @@ class IncognitoTabModelImplCreator implements IncognitoTabModelDelegate {
public boolean doIncognitoTabsExist() {
return IncognitoUtils.doIncognitoTabsExist();
}
@Override
public boolean isCurrentModel(TabModel model) {
return mModelDelegate.isCurrentModel(model);
}
}
......@@ -25,7 +25,7 @@ public abstract class TabModelFilter extends EmptyTabModelObserver implements Ta
private static final List<Tab> sEmptyRelatedTabList =
Collections.unmodifiableList(new ArrayList<Tab>());
private TabModel mTabModel;
protected ObserverList<TabModelFilterObserver> mFilteredObservers = new ObserverList<>();
protected ObserverList<TabModelObserver> mFilteredObservers = new ObserverList<>();
public TabModelFilter(TabModel tabModel) {
mTabModel = tabModel;
......@@ -33,21 +33,33 @@ public abstract class TabModelFilter extends EmptyTabModelObserver implements Ta
}
/**
* Adds a {@link TabModelFilterObserver} to be notified on {@link TabModelFilter} changes.
* @param observer The {@link TabModelFilterObserver} to add.
* Adds a {@link TabModelObserver} to be notified on {@link TabModelFilter} changes.
* @param observer The {@link TabModelObserver} to add.
*/
public void addObserver(TabModelFilterObserver observer) {
public void addObserver(TabModelObserver observer) {
mFilteredObservers.addObserver(observer);
}
/**
* Removes a {@link TabModelFilterObserver}.
* @param observer The {@link TabModelFilterObserver} to remove.
* Removes a {@link TabModelObserver}.
* @param observer The {@link TabModelObserver} to remove.
*/
public void removeObserver(TabModelFilterObserver observer) {
public void removeObserver(TabModelObserver observer) {
mFilteredObservers.removeObserver(observer);
}
public boolean isCurrentlySelectedFilter() {
return mTabModel.isCurrentModel();
}
/**
* To be called when this filter should be destroyed. This filter should no longer be used after
* this.
*/
public void destroy() {
mFilteredObservers.clear();
}
/**
* @return The {@link TabModel} that the filter is acting on.
*/
......@@ -88,38 +100,92 @@ public abstract class TabModelFilter extends EmptyTabModelObserver implements Ta
*/
protected abstract void selectTab(Tab tab);
// TabModelObserver implementation
// TODO(meiliang): All these implementations should notify each individual listener, after they
// had added to TabModelFilterObserver.
// TabModelObserver implementation.
@Override
public void didSelectTab(Tab tab, int type, int lastId) {
selectTab(tab);
for (TabModelFilterObserver observer : mFilteredObservers) {
observer.update();
for (TabModelObserver observer : mFilteredObservers) {
observer.didSelectTab(tab, type, lastId);
}
}
@Override
public void willCloseTab(Tab tab, boolean animate) {
closeTab(tab);
for (TabModelFilterObserver observer : mFilteredObservers) {
observer.update();
for (TabModelObserver observer : mFilteredObservers) {
observer.willCloseTab(tab, animate);
}
}
@Override
public void didCloseTab(int tabId, boolean incognito) {
for (TabModelObserver observer : mFilteredObservers) {
observer.didCloseTab(tabId, incognito);
}
}
@Override
public void willAddTab(Tab tab, int type) {
for (TabModelObserver observer : mFilteredObservers) {
observer.willAddTab(tab, type);
}
}
@Override
public void didAddTab(Tab tab, int type) {
addTab(tab);
for (TabModelFilterObserver observer : mFilteredObservers) {
observer.update();
for (TabModelObserver observer : mFilteredObservers) {
observer.didAddTab(tab, type);
}
}
@Override
public void didMoveTab(Tab tab, int newIndex, int curIndex) {
for (TabModelObserver observer : mFilteredObservers) {
observer.didMoveTab(tab, newIndex, curIndex);
}
}
@Override
public void tabPendingClosure(Tab tab) {
for (TabModelObserver observer : mFilteredObservers) {
observer.tabPendingClosure(tab);
}
}
@Override
public void tabClosureUndone(Tab tab) {
addTab(tab);
for (TabModelFilterObserver observer : mFilteredObservers) {
observer.update();
for (TabModelObserver observer : mFilteredObservers) {
observer.tabClosureUndone(tab);
}
}
@Override
public void tabClosureCommitted(Tab tab) {
for (TabModelObserver observer : mFilteredObservers) {
observer.tabClosureCommitted(tab);
}
}
@Override
public void allTabsPendingClosure(List<Tab> tabs) {
for (TabModelObserver observer : mFilteredObservers) {
observer.allTabsPendingClosure(tabs);
}
}
@Override
public void allTabsClosureCommitted() {
for (TabModelObserver observer : mFilteredObservers) {
observer.allTabsClosureCommitted();
}
}
@Override
public void tabRemoved(Tab tab) {
for (TabModelObserver observer : mFilteredObservers) {
observer.tabRemoved(tab);
}
}
}
// Copyright 2019 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;
/**
* An interface to be notified about changes to a {@linkt TabModelFilter}.
*/
public interface TabModelFilterObserver {
// TODO(meiliang): Add individual update listener, like addTab, closeTab, etc.
/**
* Called whenever {@link TabModelFilter} changes.
*/
void update();
}
// Copyright 2019 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 java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* This class is responsible for creating {@link TabModelFilter}s to be applied on the
* {@link TabModel}s. It always owns two {@link TabModelFilter}s, one for normal {@link TabModel}
* and one for incognito {@link TabModel}.
*/
public class TabModelFilterProvider {
private List<TabModelFilter> mTabModelFilterList = Collections.emptyList();
TabModelFilterProvider() {}
TabModelFilterProvider(List<TabModel> tabModels) {
List<TabModelFilter> filters = new ArrayList<>();
for (int i = 0; i < tabModels.size(); i++) {
filters.add(createTabModelFilter(tabModels.get(i)));
}
mTabModelFilterList = Collections.unmodifiableList(filters);
}
/**
* This method adds {@link TabModelObserver} to both {@link TabModelFilter}s.
* @param observer {@link TabModelObserver} to add.
*/
public void addTabModelFilterObserver(TabModelObserver observer) {
for (int i = 0; i < mTabModelFilterList.size(); i++) {
mTabModelFilterList.get(i).addObserver(observer);
}
}
/**
* This method removes {@link TabModelObserver} from both {@link TabModelFilter}s.
* @param observer {@link TabModelObserver} to remove.
*/
public void removeTabModelFilterObserver(TabModelObserver observer) {
for (int i = 0; i < mTabModelFilterList.size(); i++) {
mTabModelFilterList.get(i).removeObserver(observer);
}
}
/**
* This method returns a specific {@link TabModelFilter}.
* @param isIncognito Use to indicate which {@link TabModelFilter} to return.
* @return A {@link TabModelFilter}. This returns null, if this called before native library is
* initialized.
*/
public TabModelFilter getTabModelFilter(boolean isIncognito) {
for (int i = 0; i < mTabModelFilterList.size(); i++) {
if (mTabModelFilterList.get(i).isIncognito() == isIncognito)
return mTabModelFilterList.get(i);
}
return null;
}
/**
* This method returns the current {@link TabModelFilter}.
* @return The current {@link TabModelFilter}. This returns null, if this called before native
* library is initialized.
*/
public TabModelFilter getCurrentTabModelFilter() {
for (int i = 0; i < mTabModelFilterList.size(); i++) {
if (mTabModelFilterList.get(i).isCurrentlySelectedFilter())
return mTabModelFilterList.get(i);
}
return null;
}
/**
* This method destroys all owned {@link TabModelFilter}.
*/
public void destroy() {
for (int i = 0; i < mTabModelFilterList.size(); i++) {
mTabModelFilterList.get(i).destroy();
}
}
/**
* Return a {@link TabModelFilter} based on feature flags.
* @param model The {@link TabModel} that the {@link TabModelFilter} acts on.
* @return a {@link TabModelFilter}.
*/
private TabModelFilter createTabModelFilter(TabModel model) {
// TODO(meiliang): build based on chrome feature.
return new EmptyTabModelFilter(model);
}
}
......@@ -43,6 +43,12 @@ public interface TabModelSelector {
*/
TabModel getModel(boolean incognito);
/**
* Get the {@link TabModelFilterProvider} that provides {@link TabModelFilter}.
* @return Never returns null. Returns a stub when real model is uninitialized.
*/
TabModelFilterProvider getTabModelFilterProvider();
/**
* @return a list for the underlying models
*/
......
......@@ -22,6 +22,13 @@ public abstract class TabModelSelectorBase implements TabModelSelector {
private static TabModelSelectorObserver sObserver;
private List<TabModel> mTabModels = Collections.emptyList();
/**
* This is a dummy implementation intended to stub out TabModelFilterProvider before native is
* ready.
*/
private TabModelFilterProvider mTabModelFilterProvider = new TabModelFilterProvider();
private int mActiveModelIndex = NORMAL_TAB_MODEL_INDEX;
private final ObserverList<TabModelSelectorObserver> mObservers =
new ObserverList<TabModelSelectorObserver>();
......@@ -41,6 +48,7 @@ public abstract class TabModelSelectorBase implements TabModelSelector {
}
mActiveModelIndex = startIncognito ? INCOGNITO_TAB_MODEL_INDEX : NORMAL_TAB_MODEL_INDEX;
mTabModels = Collections.unmodifiableList(tabModels);
mTabModelFilterProvider = new TabModelFilterProvider(mTabModels);
TabModelObserver tabModelObserver = new EmptyTabModelObserver() {
@Override
......@@ -132,6 +140,11 @@ public abstract class TabModelSelectorBase implements TabModelSelector {
return getModelAt(index);
}
@Override
public TabModelFilterProvider getTabModelFilterProvider() {
return mTabModelFilterProvider;
}
@Override
public boolean isIncognitoSelected() {
return mActiveModelIndex == INCOGNITO_TAB_MODEL_INDEX;
......@@ -222,6 +235,7 @@ public abstract class TabModelSelectorBase implements TabModelSelector {
@Override
public void destroy() {
mTabModelFilterProvider.destroy();
for (int i = 0; i < getModels().size(); i++) getModelAt(i).destroy();
}
......
......@@ -108,6 +108,13 @@ public class DocumentTabModelSelector extends TabModelSelectorBase
// Revisit this when we have a Samsung L multi-instance device.
return mIncognitoTabModel.getCount() > 0;
}
@Override
public boolean isCurrentModel(TabModel model) {
return DocumentTabModelSelector.this.isCurrentModel(model);
}
}, mActivityDelegate);
initializeTabIdCounter();
......
......@@ -6,12 +6,13 @@ package org.chromium.chrome.browser.toolbar;
import org.chromium.base.ObserverList;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
import org.chromium.chrome.browser.tabmodel.TabLaunchType;
import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.chrome.browser.tabmodel.TabModelObserver;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabModelObserver;
import java.util.List;
......@@ -35,11 +36,8 @@ public class TabCountProvider {
/** The {@link TabModelSelectorObserver} that observes when the tab count may have changed. */
private TabModelSelectorObserver mTabModelSelectorObserver;
/**
* The {@link TabModelSelectorTabModelObserver} that observes when the tab count may have
* changed.
*/
private TabModelSelectorTabModelObserver mTabModelSelectorTabModelObserver;
/** The {@link TabModelObserver} that observes when the tab count may have changed. */
private TabModelObserver mTabModelFilterObserver;
private int mTabCount;
......@@ -65,7 +63,9 @@ public class TabCountProvider {
addObserver(observer);
if (mTabModelSelector != null) {
observer.onTabCountChanged(mTabModelSelector.getCurrentModel().getCount(),
observer.onTabCountChanged(mTabModelSelector.getTabModelFilterProvider()
.getCurrentTabModelFilter()
.getCount(),
mTabModelSelector.isIncognitoSelected());
}
}
......@@ -97,8 +97,7 @@ public class TabCountProvider {
};
mTabModelSelector.addObserver(mTabModelSelectorObserver);
mTabModelSelectorTabModelObserver =
new TabModelSelectorTabModelObserver(mTabModelSelector) {
mTabModelFilterObserver = new EmptyTabModelObserver() {
@Override
public void didAddTab(Tab tab, @TabLaunchType int type) {
updateTabCount();
......@@ -130,6 +129,8 @@ public class TabCountProvider {
}
};
mTabModelSelector.getTabModelFilterProvider().addTabModelFilterObserver(
mTabModelFilterObserver);
updateTabCount();
}
......@@ -137,19 +138,21 @@ public class TabCountProvider {
* Clean up any state when the TabCountProvider is destroyed.
*/
void destroy() {
if (mTabModelFilterObserver != null) {
mTabModelSelector.getTabModelFilterProvider().removeTabModelFilterObserver(
mTabModelFilterObserver);
}
if (mTabModelSelector != null) {
mTabModelSelector.removeObserver(mTabModelSelectorObserver);
mTabModelSelector = null;
}
if (mTabModelSelectorTabModelObserver != null) {
mTabModelSelectorTabModelObserver.destroy();
mTabModelSelectorTabModelObserver = null;
}
mTabCountObservers.clear();
}
private void updateTabCount() {
final int tabCount = mTabModelSelector.getCurrentModel().getCount();
final int tabCount =
mTabModelSelector.getTabModelFilterProvider().getCurrentTabModelFilter().getCount();
final boolean isIncognito = mTabModelSelector.isIncognitoSelected();
if (mTabCount == tabCount && mIsIncognito == isIncognito) return;
......
......@@ -1592,7 +1592,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/tabmodel/TabModel.java",
"java/src/org/chromium/chrome/browser/tabmodel/TabModelDelegate.java",
"java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java",
"java/src/org/chromium/chrome/browser/tabmodel/TabModelFilterObserver.java",
"java/src/org/chromium/chrome/browser/tabmodel/TabModelFilterProvider.java",
"java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java",
"java/src/org/chromium/chrome/browser/tabmodel/TabModelJniBridge.java",
"java/src/org/chromium/chrome/browser/tabmodel/TabModelObserver.java",
......
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