1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.chrome.browser.tasks;
6 
7 import android.content.Context;
8 import android.view.LayoutInflater;
9 import android.view.View;
10 import android.view.ViewGroup;
11 import android.widget.LinearLayout;
12 
13 import androidx.annotation.Nullable;
14 
15 import com.google.android.material.appbar.AppBarLayout;
16 
17 import org.chromium.base.library_loader.LibraryLoader;
18 import org.chromium.base.supplier.Supplier;
19 import org.chromium.chrome.browser.app.ChromeActivity;
20 import org.chromium.chrome.browser.feedback.HelpAndFeedbackLauncherImpl;
21 import org.chromium.chrome.browser.ntp.FakeboxDelegate;
22 import org.chromium.chrome.browser.ntp.IncognitoCookieControlsManager;
23 import org.chromium.chrome.browser.profiles.Profile;
24 import org.chromium.chrome.browser.tab.Tab;
25 import org.chromium.chrome.browser.tasks.tab_management.TabManagementDelegate.TabSwitcherType;
26 import org.chromium.chrome.browser.tasks.tab_management.TabManagementModuleProvider;
27 import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
28 import org.chromium.chrome.tab_ui.R;
29 import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator;
30 import org.chromium.ui.modelutil.PropertyModel;
31 import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
32 
33 /**
34  * Coordinator for displaying task-related surfaces (Tab Switcher, MV Tiles, Omnibox, etc.).
35  *  Concrete implementation of {@link TasksSurface}.
36  */
37 public class TasksSurfaceCoordinator implements TasksSurface {
38     private final TabSwitcher mTabSwitcher;
39     private final TasksView mView;
40     private final PropertyModelChangeProcessor mPropertyModelChangeProcessor;
41     private final TasksSurfaceMediator mMediator;
42     private MostVisitedListCoordinator mMostVisitedList;
43     private TrendyTermsCoordinator mTrendyTermsCoordinator;
44     private final PropertyModel mPropertyModel;
45     private final boolean mHasTrendyTerm;
46     private final @TabSwitcherType int mTabSwitcherType;
47 
TasksSurfaceCoordinator(ChromeActivity activity, ScrimCoordinator scrimCoordinator, PropertyModel propertyModel, @TabSwitcherType int tabSwitcherType, Supplier<Tab> parentTabSupplier, boolean hasMVTiles, boolean hasTrendyTerms)48     public TasksSurfaceCoordinator(ChromeActivity activity, ScrimCoordinator scrimCoordinator,
49             PropertyModel propertyModel, @TabSwitcherType int tabSwitcherType,
50             Supplier<Tab> parentTabSupplier, boolean hasMVTiles, boolean hasTrendyTerms) {
51         mView = (TasksView) LayoutInflater.from(activity).inflate(R.layout.tasks_view_layout, null);
52         mView.initialize(activity.getLifecycleDispatcher());
53         mPropertyModelChangeProcessor =
54                 PropertyModelChangeProcessor.create(propertyModel, mView, TasksViewBinder::bind);
55         mPropertyModel = propertyModel;
56         mHasTrendyTerm = hasTrendyTerms;
57         mTabSwitcherType = tabSwitcherType;
58         if (tabSwitcherType == TabSwitcherType.CAROUSEL) {
59             mTabSwitcher = TabManagementModuleProvider.getDelegate().createCarouselTabSwitcher(
60                     activity, mView.getCarouselTabSwitcherContainer(), scrimCoordinator);
61         } else if (tabSwitcherType == TabSwitcherType.GRID) {
62             mTabSwitcher = TabManagementModuleProvider.getDelegate().createGridTabSwitcher(
63                     activity, mView.getBodyViewContainer(), scrimCoordinator);
64         } else if (tabSwitcherType == TabSwitcherType.SINGLE) {
65             mTabSwitcher = new SingleTabSwitcherCoordinator(
66                     activity, mView.getCarouselTabSwitcherContainer());
67         } else if (tabSwitcherType == TabSwitcherType.NONE) {
68             mTabSwitcher = null;
69         } else {
70             mTabSwitcher = null;
71             assert false : "Unsupported tab switcher type";
72         }
73 
74         View.OnClickListener incognitoLearnMoreClickListener = v -> {
75             HelpAndFeedbackLauncherImpl.getInstance().show(activity,
76                     activity.getString(R.string.help_context_incognito_learn_more),
77                     Profile.getLastUsedRegularProfile().getPrimaryOTRProfile(), null);
78         };
79         IncognitoCookieControlsManager incognitoCookieControlsManager =
80                 new IncognitoCookieControlsManager();
81         Runnable trendyTermsUpdater = null;
82         if (hasTrendyTerms) {
83             mTrendyTermsCoordinator = new TrendyTermsCoordinator(activity,
84                     getView().findViewById(R.id.trendy_terms_recycler_view), parentTabSupplier);
85 
86             trendyTermsUpdater = () -> {
87                 TrendyTermsCache.maybeFetch(Profile.getLastUsedRegularProfile());
88                 mTrendyTermsCoordinator.populateTrendyTerms();
89             };
90         }
91         mMediator = new TasksSurfaceMediator(propertyModel, incognitoLearnMoreClickListener,
92                 incognitoCookieControlsManager, tabSwitcherType == TabSwitcherType.CAROUSEL,
93                 trendyTermsUpdater);
94 
95         if (hasMVTiles) {
96             LinearLayout mvTilesLayout = mView.findViewById(R.id.mv_tiles_layout);
97             mMostVisitedList = new MostVisitedListCoordinator(
98                     activity, mvTilesLayout, mPropertyModel, parentTabSupplier);
99         }
100     }
101 
102     /** TasksSurface implementation. */
103     @Override
initialize()104     public void initialize() {
105         assert LibraryLoader.getInstance().isInitialized();
106 
107         if (mMostVisitedList != null) mMostVisitedList.initialize();
108         mMediator.initialize();
109     }
110 
111     @Override
setOnTabSelectingListener(TabSwitcher.OnTabSelectingListener listener)112     public void setOnTabSelectingListener(TabSwitcher.OnTabSelectingListener listener) {
113         if (mTabSwitcher != null) {
114             mTabSwitcher.setOnTabSelectingListener(listener);
115         }
116     }
117 
118     @Override
getController()119     public @Nullable TabSwitcher.Controller getController() {
120         return mTabSwitcher != null ? mTabSwitcher.getController() : null;
121     }
122 
123     @Override
getTabListDelegate()124     public @Nullable TabSwitcher.TabListDelegate getTabListDelegate() {
125         return mTabSwitcher != null ? mTabSwitcher.getTabListDelegate() : null;
126     }
127 
128     @Override
getTabGridDialogVisibilitySupplier()129     public Supplier<Boolean> getTabGridDialogVisibilitySupplier() {
130         if (mTabSwitcherType != TabSwitcherType.CAROUSEL
131                 && mTabSwitcherType != TabSwitcherType.GRID) {
132             return null;
133         }
134         assert mTabSwitcher != null;
135         return mTabSwitcher.getTabGridDialogVisibilitySupplier();
136     }
137 
138     @Override
getBodyViewContainer()139     public ViewGroup getBodyViewContainer() {
140         return mView.getBodyViewContainer();
141     }
142 
143     @Override
getView()144     public View getView() {
145         return mView;
146     }
147 
148     @Override
getTopToolbarPlaceholderView()149     public View getTopToolbarPlaceholderView() {
150         return mView != null ? mView.findViewById(R.id.top_toolbar_placeholder) : null;
151     }
152 
153     @Override
onFinishNativeInitialization(Context context, FakeboxDelegate fakeboxDelegate)154     public void onFinishNativeInitialization(Context context, FakeboxDelegate fakeboxDelegate) {
155         if (mTabSwitcher != null) {
156             ChromeActivity activity = (ChromeActivity) context;
157             mTabSwitcher.initWithNative(activity, activity.getTabContentManager(),
158                     activity.getCompositorViewHolder().getDynamicResourceLoader(), activity,
159                     activity.getModalDialogManager());
160         }
161 
162         mMediator.initWithNative(fakeboxDelegate);
163 
164         if (mHasTrendyTerm && mTabSwitcher != null) {
165             mTabSwitcher.getController().addOverviewModeObserver(mMediator);
166             TrendyTermsCache.maybeFetch(Profile.getLastUsedRegularProfile());
167         }
168     }
169 
170     @Override
addHeaderOffsetChangeListener( AppBarLayout.OnOffsetChangedListener onOffsetChangedListener)171     public void addHeaderOffsetChangeListener(
172             AppBarLayout.OnOffsetChangedListener onOffsetChangedListener) {
173         mView.addHeaderOffsetChangeListener(onOffsetChangedListener);
174     }
175 
176     @Override
removeHeaderOffsetChangeListener( AppBarLayout.OnOffsetChangedListener onOffsetChangedListener)177     public void removeHeaderOffsetChangeListener(
178             AppBarLayout.OnOffsetChangedListener onOffsetChangedListener) {
179         mView.removeHeaderOffsetChangeListener(onOffsetChangedListener);
180     }
181 
182     @Override
addFakeSearchBoxShrinkAnimation()183     public void addFakeSearchBoxShrinkAnimation() {
184         mView.addFakeSearchBoxShrinkAnimation();
185     }
186 
187     @Override
removeFakeSearchBoxShrinkAnimation()188     public void removeFakeSearchBoxShrinkAnimation() {
189         mView.removeFakeSearchBoxShrinkAnimation();
190     }
191 }
192