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