From 41270b79c64250c807f2db6197d314bd131f9b8e Mon Sep 17 00:00:00 2001 From: Carmelo Messina Date: Tue, 24 Mar 2026 11:12:18 +0100 Subject: [PATCH] Patches for v146 (#2511 #256) --- .../Enable-extension-in-incognito.patch | 1675 +++++++++-------- ...al-support-for-extensions-on-Android.patch | 356 +++- 2 files changed, 1191 insertions(+), 840 deletions(-) diff --git a/build/patches/Enable-extension-in-incognito.patch b/build/patches/Enable-extension-in-incognito.patch index 7c78ccfe..da9ce32a 100644 --- a/build/patches/Enable-extension-in-incognito.patch +++ b/build/patches/Enable-extension-in-incognito.patch @@ -6,37 +6,39 @@ Full activation of incognito mode in experimental extension License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- - .../chrome/browser/ChromeTabbedActivity.java | 36 +++++++- - .../chrome/browser/app/ChromeActivity.java | 34 ++++++- - .../customtabs/BaseCustomTabActivity.java | 2 +- - .../BaseCustomTabRootUiCoordinator.java | 4 +- - .../CustomTabIntentDataProvider.java | 3 + - .../tabbed_mode/TabbedRootUiCoordinator.java | 3 +- - .../browser/tabmodel/TabModelJniBridge.java | 4 +- - .../tabmodel/TabModelSelectorBase.java | 7 ++ - .../browser/toolbar/ToolbarManager.java | 13 ++- - .../chrome/browser/ui/RootUiCoordinator.java | 6 +- - .../developer_private_functions.cc | 3 +- - .../browser/extensions/extension_tab_util.cc | 2 +- - .../tabmodel/IncognitoTabModelImpl.java | 10 +- - .../tabmodel/IncognitoTabModelObserver.java | 2 + - .../extensions/extension_actions_bridge.cc | 23 +++-- - .../extensions/extension_actions_bridge.h | 4 +- - .../ui/extensions/ExtensionActionsBridge.java | 26 +++++- - .../android/tab_model/tab_model_jni_bridge.cc | 4 + - .../ExtensionActionListCoordinator.java | 10 +- - .../ExtensionActionListMediator.java | 16 +++- - .../ExtensionActionsUpdateHelper.java | 62 +++++++++++-- - .../ExtensionToolbarCoordinator.java | 11 ++- - .../ExtensionToolbarCoordinatorImpl.java | 37 +++++--- - .../extensions/ExtensionsMenuCoordinator.java | 6 +- - .../extensions/ExtensionsMenuMediator.java | 12 ++- - .../browser_window/ChromeAndroidTaskImpl.java | 3 + - .../ChromeAndroidTaskTrackerImpl.java | 92 ++++++++++++++----- - .../ChromeAndroidTaskTracker.java | 7 +- - components/tabs/impl/tab_collection.cc | 16 ++++ - components/tabs/impl/tab_strip_collection.cc | 4 +- - 30 files changed, 367 insertions(+), 95 deletions(-) + .../chrome/browser/ChromeTabbedActivity.java | 9 ++ + .../chrome/browser/app/ChromeActivity.java | 43 ++++++-- + .../BaseCustomTabRootUiCoordinator.java | 2 + + .../CustomTabIntentDataProvider.java | 3 + + .../tabbed_mode/TabbedRootUiCoordinator.java | 1 + + .../browser/tabmodel/TabModelJniBridge.java | 4 +- + .../tabmodel/TabModelSelectorBase.java | 14 +++ + .../browser/toolbar/ToolbarManager.java | 2 + + .../chrome/browser/ui/RootUiCoordinator.java | 2 + + .../developer_private_functions.cc | 3 +- + .../browser/extensions/extension_tab_util.cc | 2 +- + .../tabmodel/IncognitoTabModelImpl.java | 14 ++- + .../tabmodel/IncognitoTabModelObserver.java | 3 + + .../extensions/extension_actions_bridge.cc | 23 ++-- + .../extensions/extension_actions_bridge.h | 4 +- + .../ExtensionActionContextMenuBridge.java | 2 +- + .../ui/extensions/ExtensionActionsBridge.java | 92 ++++++++++++---- + .../ui/extensions/ExtensionsMenuBridge.java | 70 ++++++++++-- + .../extensions/ExtensionsToolbarBridge.java | 101 +++++++++++++----- + .../android/tab_model/tab_model_jni_bridge.cc | 4 + + .../ExtensionActionListCoordinator.java | 12 +++ + .../ExtensionActionListMediator.java | 14 ++- + .../ExtensionActionsUpdateHelper.java | 3 +- + .../ExtensionToolbarCoordinator.java | 3 + + .../ExtensionToolbarCoordinatorImpl.java | 15 +-- + ...MenuAndAccessControlButtonCoordinator.java | 5 +- + .../extensions/ExtensionsMenuCoordinator.java | 2 + + .../extensions/ExtensionsMenuMediator.java | 21 ++-- + .../browser_window/ChromeAndroidTaskImpl.java | 41 ++++++- + .../ChromeAndroidTaskFeature.java | 2 +- + components/tabs/impl/tab_collection.cc | 16 +++ + components/tabs/impl/tab_strip_collection.cc | 4 +- + 32 files changed, 426 insertions(+), 110 deletions(-) diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java @@ -49,7 +51,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedAct import org.chromium.chrome.browser.data_sharing.DataSharingIntentUtils; import org.chromium.chrome.browser.data_sharing.DataSharingTabGroupUtils; import org.chromium.chrome.browser.data_sharing.DataSharingTabManager; -@@ -310,11 +311,13 @@ import org.chromium.chrome.browser.tasks.tab_management.TabSwitcherPaneBase; +@@ -310,11 +311,15 @@ import org.chromium.chrome.browser.tasks.tab_management.TabSwitcherPaneBase; import org.chromium.chrome.browser.tasks.tab_management.TabUiUtils; import org.chromium.chrome.browser.tasks.tab_management.TabsSettings; import org.chromium.chrome.browser.tasks.tab_management.archived_tabs_auto_delete_promo.ArchivedTabsAutoDeletePromoManager; @@ -59,60 +61,13 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedAct import org.chromium.chrome.browser.toolbar.extensions.ExtensionToolbarCoordinator; import org.chromium.chrome.browser.toolbar.top.ToolbarControlContainer; import org.chromium.chrome.browser.ui.AppLaunchDrawBlocker; -+import org.chromium.chrome.browser.ui.extensions.ExtensionActionsBridge; ++import org.chromium.chrome.browser.ui.extensions.windowing.ExtensionWindowControllerBridge; ++import org.chromium.chrome.browser.ui.extensions.windowing.ExtensionWindowControllerBridgeFactory; ++import org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTaskFeatureKey; import org.chromium.chrome.browser.ui.IncognitoRestoreAppLaunchDrawBlockerFactory; import org.chromium.chrome.browser.ui.RootUiCoordinator; import org.chromium.chrome.browser.ui.appmenu.AppMenuPropertiesDelegate; -@@ -855,12 +858,39 @@ public class ChromeTabbedActivity extends ChromeActivity implements PreAttachInt - mTabModelOrchestrator.onNativeLibraryReady(getTabContentManager()); - - mTabModelNotificationDotManager.initWithNative(mTabModelSelector); -+ - initializeChromeAndroidTask( - BrowserWindowType.NORMAL, - mTabModelSelector, - mSupportedProfileType, - mMultiInstanceManager); - -+ ProfileManager.addObserver( -+ new ProfileManager.Observer() { -+ @Override -+ public void onProfileAdded(Profile profile) {} -+ -+ @Override -+ public void onProfileDestroyed(Profile profile) { -+ } -+ }); -+ -+ mTabModelSelector.addIncognitoTabModelObserver( -+ new IncognitoTabModelObserver() { -+ @Override -+ public void wasFirstTabCreated() { -+ initializeChromeAndroidTask(BrowserWindowType.NORMAL, -+ mTabModelSelector.getModel(true), -+ mMultiInstanceManager); -+ } -+ -+ @Override -+ public void didDestroyed() { -+ destroyIncognitoAndroidTask( -+ mTabModelSelector.getModel(true)); -+ } -+ }); -+ - // For saving non-incognito tab closures for Recent Tabs. - boolean alwaysIncognito = AlwaysIncognitoLinkInterceptor.isAlwaysIncognito(); - PrefService prefService = UserPrefs.get(ProfileManager.getLastUsedRegularProfile()); -@@ -3070,7 +3100,7 @@ public class ChromeTabbedActivity extends ChromeActivity implements PreAttachInt - mLayoutStateProviderSupplier, - getBrowserControlsManager(), - getWindowAndroid(), -- getChromeAndroidTaskSupplier(), -+ (tab) -> getChromeAndroidTask(tab), - getLifecycleDispatcher(), - getLayoutManagerSupplier(), - /* menuOrKeyboardActionController= */ this, -@@ -4009,6 +4039,10 @@ public class ChromeTabbedActivity extends ChromeActivity implements PreAttachInt +@@ -4009,6 +4014,10 @@ public class ChromeTabbedActivity extends ChromeActivity implements PreAttachInt } RecordUserAction.record("MobileMenuRecentTabs"); } else if (id == R.id.extensions_menu_id) { @@ -126,84 +81,76 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedAct diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java -@@ -452,7 +452,7 @@ public abstract class ChromeActivity extends AsyncInitializationActivity - - private @Nullable TabStateThemeResourceProvider mThemeResourceProvider; - -- private final OneshotSupplierImpl mChromeAndroidTaskSupplier = -+ private final OneshotSupplierImpl mChromeAndroidTaskSupplierInternal = - new OneshotSupplierImpl<>(); - - protected ChromeActivity() { -@@ -1130,13 +1130,29 @@ public abstract class ChromeActivity extends AsyncInitializationActivity - chromeAndroidTask, profile)); +@@ -188,6 +188,7 @@ import org.chromium.chrome.browser.tab.TabSelectionType; + import org.chromium.chrome.browser.tab.TabState; + import org.chromium.chrome.browser.tab.TabUtils; + import org.chromium.chrome.browser.tab_ui.TabContentManager; ++import org.chromium.chrome.browser.tabmodel.IncognitoTabModelObserver; + import org.chromium.chrome.browser.tabmodel.SupportedProfileType; + import org.chromium.chrome.browser.tabmodel.TabCreator; + import org.chromium.chrome.browser.tabmodel.TabCreatorManager; +@@ -220,6 +221,9 @@ import org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTaskTrackerFac + import org.chromium.chrome.browser.ui.device_lock.MissingDeviceLockLauncher; + import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeController; + import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeUtils; ++import org.chromium.chrome.browser.ui.extensions.ExtensionActionsBridge; ++import org.chromium.chrome.browser.ui.extensions.ExtensionsMenuBridge; ++import org.chromium.chrome.browser.ui.extensions.ExtensionsToolbarBridge; + import org.chromium.chrome.browser.ui.extensions.windowing.ExtensionWindowControllerBridge; + import org.chromium.chrome.browser.ui.extensions.windowing.ExtensionWindowControllerBridgeFactory; + import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar; +@@ -1123,18 +1127,45 @@ public abstract class ChromeActivity extends AsyncInitializationActivity + // TODO(crbug.com/475200706): Handle multiple profiles for mobile. + Profile profile = tabModelSelector.getCurrentModel().getProfile(); + assert profile != null; +- chromeAndroidTask.addFeature( +- new ChromeAndroidTaskFeatureKey(ExtensionWindowControllerBridge.class, profile), +- () -> +- ExtensionWindowControllerBridgeFactory.create( +- chromeAndroidTask, profile)); ++ addFeatures(chromeAndroidTask, profile); // 5. Make the ChromeAndroidTask available via OneshotSupplier. -- mChromeAndroidTaskSupplier.set(chromeAndroidTask); -+ if (!currentTabModel.isIncognito()) -+ mChromeAndroidTaskSupplierInternal.set(chromeAndroidTask); + mChromeAndroidTaskSupplier.set(chromeAndroidTask); + -+ onTopResumedActivityChangedWithNative(/* isTopResumedActivity= */ true); ++ tabModelSelector.addIncognitoTabModelObserver( ++ new IncognitoTabModelObserver() { ++ @Override ++ public void onAssociateWithBrowserWindow() { ++ var chromeAndroidTask = getChromeAndroidTaskSupplier().get(); ++ var profile = tabModelSelector.getModel(true).getProfile(); ++ addFeatures(chromeAndroidTask, profile); ++ } ++ ++ @Override ++ public void didDestroyed() { ++ } ++ }); } } - /** Returns an {@link OneshotSupplier} for {@link ChromeAndroidTask}. */ -- protected final OneshotSupplier getChromeAndroidTaskSupplier() { -- return mChromeAndroidTaskSupplier; -+ protected final ChromeAndroidTask getChromeAndroidTask(Tab tab) { -+ TabModelSelector modelSelector = getTabModelSelector(); -+ TabModel tabModel = modelSelector.getModelForTabId(tab.getId()); -+ return ChromeAndroidTaskTrackerFactory.getInstance().get( -+ mChromeAndroidTaskSupplierInternal.get().getId(), -+ tabModel); +- /** Returns an {@link OneshotSupplier} for {@link ChromeAndroidTask}. */ ++ private void addFeatures(ChromeAndroidTask task, Profile profile) { ++ task.addFeature( ++ new ChromeAndroidTaskFeatureKey(ExtensionWindowControllerBridge.class, profile), ++ () -> ExtensionWindowControllerBridgeFactory.create(task, profile)); ++ ++ task.addFeature( ++ new ChromeAndroidTaskFeatureKey(ExtensionsToolbarBridge.class, profile), ++ () -> ExtensionsToolbarBridge.create(task, profile)); ++ ++ task.addFeature( ++ new ChromeAndroidTaskFeatureKey(ExtensionActionsBridge.class, profile), ++ () -> ExtensionActionsBridge.create(task, profile)); ++ ++ task.addFeature( ++ new ChromeAndroidTaskFeatureKey(ExtensionsMenuBridge.class, profile), ++ () -> ExtensionsMenuBridge.create(task, profile)); + } + -+ protected final void destroyIncognitoAndroidTask(TabModel tabModel) { -+ ChromeAndroidTask incognitoTask = -+ ChromeAndroidTaskTrackerFactory.getInstance().get( -+ mChromeAndroidTaskSupplierInternal.get().getId(), -+ tabModel); -+ ChromeAndroidTaskTrackerFactory.getInstance() -+ .onActivityWindowAndroidDestroy(incognitoTask, getWindowAndroid()); + protected final OneshotSupplier getChromeAndroidTaskSupplier() { + return mChromeAndroidTaskSupplier; } - - @Override -@@ -1806,6 +1822,14 @@ public abstract class ChromeActivity extends AsyncInitializationActivity - @SuppressLint("NewApi") - @Override - protected final void onDestroy() { -+ ActivityWindowAndroid wAndroid = getWindowAndroid(); -+ if (wAndroid != null) { -+ var chromeAndroidTaskTracker = ChromeAndroidTaskTrackerFactory.getInstance(); -+ if (chromeAndroidTaskTracker != null) { -+ chromeAndroidTaskTracker.onActivityWindowAndroidDestroy(wAndroid); -+ } -+ } -+ - if (mSnackbarManager != null) { - SnackbarManagerProvider.detach(mSnackbarManager); - } -@@ -2062,7 +2086,7 @@ public abstract class ChromeActivity extends AsyncInitializationActivity - - getProfileProviderSupplier().runSyncOrOnAvailable(this::initializeManualFillingComponent); - -- var chromeAndroidTask = getChromeAndroidTaskSupplier().get(); -+ var chromeAndroidTask = mChromeAndroidTaskSupplierInternal.get(); - if (chromeAndroidTask != null) { - chromeAndroidTask.onNativeInitializationFinished(); - } -diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java ---- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java -+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java -@@ -393,7 +393,7 @@ public abstract class BaseCustomTabActivity extends ChromeActivity { - getTabModelSelectorSupplier(), - getBrowserControlsManager(), - getWindowAndroid(), -- getChromeAndroidTaskSupplier(), -+ (tab) -> getChromeAndroidTask(tab), - getLifecycleDispatcher(), - getLayoutManagerSupplier(), - /* menuOrKeyboardActionController= */ this, diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabRootUiCoordinator.java --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabRootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabRootUiCoordinator.java @@ -223,15 +170,6 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/Base /** A {@link RootUiCoordinator} variant that controls UI for {@link BaseCustomTabActivity}. */ public class BaseCustomTabRootUiCoordinator extends RootUiCoordinator { -@@ -214,7 +216,7 @@ public class BaseCustomTabRootUiCoordinator extends RootUiCoordinator { - @NonNull MonotonicObservableSupplier tabModelSelectorSupplier, - @NonNull BrowserControlsManager browserControlsManager, - @NonNull ActivityWindowAndroid windowAndroid, -- @NonNull OneshotSupplier chromeAndroidTaskSupplier, -+ @NonNull Function chromeAndroidTaskSupplier, - @NonNull ActivityLifecycleDispatcher activityLifecycleDispatcher, - @NonNull MonotonicObservableSupplier layoutManagerSupplier, - @NonNull MenuOrKeyboardActionController menuOrKeyboardActionController, diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java @@ -270,15 +208,6 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/Tab import org.chromium.chrome.browser.ui.default_browser_promo.DefaultBrowserPromoUtils; import org.chromium.chrome.browser.ui.desktop_windowing.AppHeaderCoordinator; import org.chromium.chrome.browser.ui.desktop_windowing.AppHeaderUtils; -@@ -446,7 +447,7 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator { - @NonNull OneshotSupplier layoutStateProviderOneshotSupplier, - @NonNull BrowserControlsManager browserControlsManager, - @NonNull ActivityWindowAndroid windowAndroid, -- @NonNull OneshotSupplier chromeAndroidTaskSupplier, -+ @NonNull Function chromeAndroidTaskSupplier, - @NonNull ActivityLifecycleDispatcher activityLifecycleDispatcher, - @NonNull MonotonicObservableSupplier layoutManagerSupplier, - @NonNull MenuOrKeyboardActionController menuOrKeyboardActionController, diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelJniBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelJniBridge.java --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelJniBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelJniBridge.java @@ -298,10 +227,17 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabMod diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java -@@ -488,6 +488,13 @@ public abstract class TabModelSelectorBase +@@ -488,6 +488,20 @@ public abstract class TabModelSelectorBase } } ++ @Override ++ public void onAssociateWithBrowserWindow() { ++ for (IncognitoTabModelObserver observer : mIncognitoObservers) { ++ observer.onAssociateWithBrowserWindow(); ++ } ++ } ++ + @Override + public void didDestroyed() { + for (IncognitoTabModelObserver observer : mIncognitoObservers) { @@ -331,54 +267,10 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/Toolbar import org.chromium.chrome.browser.flags.ChromeFeatureList; import android.view.Gravity; -@@ -365,7 +367,7 @@ public class ToolbarManager - private final TopInsetProvider mTopInsetProvider; - private final SettableNonNullObservableSupplier<@ControlsPosition Integer> - mToolbarPositionSupplier = ObservableSuppliers.createNonNull(ControlsPosition.NONE); -- private final OneshotSupplier mChromeAndroidTaskSupplier; -+ private final Function mChromeAndroidTaskSupplier; - - private @MonotonicNonNull HomeButtonCoordinator mHomeButtonCoordinator; - private @MonotonicNonNull HomePageButtonsCoordinator mHomePageButtonsCoordinator; -@@ -804,7 +806,7 @@ public class ToolbarManager - NonNullObservableSupplier omniboxFocusStateSupplier, - OneshotSupplier promoShownOneshotSupplier, - WindowAndroid windowAndroid, -- OneshotSupplier chromeAndroidTaskSupplier, -+ Function chromeAndroidTaskSupplier, - Supplier isInOverviewModeSupplier, - Supplier<@Nullable ModalDialogManager> modalDialogManagerSupplier, - StatusBarColorController statusBarColorController, -@@ -2403,15 +2405,13 @@ public class ToolbarManager - ViewStub extensionToolbarStub = - mControlContainer.findViewById(R.id.extension_toolbar_container_stub); - if (extensionToolbarStub != null) { -- ChromeAndroidTask task = mChromeAndroidTaskSupplier.get(); -- // ChromeAndroidTask is available only on Desktop Android. -- if (task != null) { - mExtensionToolbarCoordinator = - ExtensionToolbarCoordinator.maybeCreate( - mActivity, - extensionToolbarStub, - mWindowAndroid, -- task, -+ mChromeAndroidTaskSupplier, -+ mProfileSupplier, - assertNonNull(mTabModelSelector.getCurrentModel().getProfile()), - mActivityTabProvider.asObservable(), - mTabCreatorManager.getTabCreator(false), -@@ -2419,7 +2419,6 @@ public class ToolbarManager - if (mExtensionToolbarCoordinator != null) { - mToolbar.setExtensionToolbarCoordinator(mExtensionToolbarCoordinator); - } -- } - } - - // Must be initialized before Toolbar attempts to use it. diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java --- a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java -@@ -155,6 +155,7 @@ import org.chromium.chrome.browser.tab.TabSelectionType; +@@ -154,6 +154,7 @@ import org.chromium.chrome.browser.tab.TabSelectionType; import org.chromium.chrome.browser.tab_ui.RecyclerViewPosition; import org.chromium.chrome.browser.tab_ui.TabContentManager; import org.chromium.chrome.browser.tab_ui.TabSwitcher; @@ -386,7 +278,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordi import org.chromium.chrome.browser.tabmodel.TabCreator; import org.chromium.chrome.browser.tabmodel.TabCreatorManager; import org.chromium.chrome.browser.tabmodel.TabModel; -@@ -253,6 +254,7 @@ import org.chromium.url.GURL; +@@ -252,6 +253,7 @@ import org.chromium.url.GURL; import java.lang.ref.WeakReference; import java.util.function.BooleanSupplier; import java.util.function.Supplier; @@ -394,24 +286,6 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordi /** * The root UI coordinator. This class will eventually be responsible for inflating and managing -@@ -287,7 +289,7 @@ public class RootUiCoordinator - protected @Nullable AppMenuCoordinator mAppMenuCoordinator; - private final MenuOrKeyboardActionController mMenuOrKeyboardActionController; - protected final ActivityWindowAndroid mWindowAndroid; -- private final OneshotSupplier mChromeAndroidTaskSupplier; -+ private final Function mChromeAndroidTaskSupplier; - - protected final ActivityTabProvider mActivityTabProvider; - protected MonotonicObservableSupplier mShareDelegateSupplier; -@@ -483,7 +485,7 @@ public class RootUiCoordinator - @NonNull OneshotSupplier layoutStateProviderOneshotSupplier, - @NonNull BrowserControlsManager browserControlsManager, - @NonNull ActivityWindowAndroid windowAndroid, -- @NonNull OneshotSupplier chromeAndroidTaskSupplier, -+ @NonNull Function chromeAndroidTaskSupplier, - @NonNull ActivityLifecycleDispatcher activityLifecycleDispatcher, - @NonNull MonotonicObservableSupplier layoutManagerSupplier, - @NonNull MenuOrKeyboardActionController menuOrKeyboardActionController, diff --git a/chrome/browser/extensions/api/developer_private/developer_private_functions.cc b/chrome/browser/extensions/api/developer_private/developer_private_functions.cc --- a/chrome/browser/extensions/api/developer_private/developer_private_functions.cc +++ b/chrome/browser/extensions/api/developer_private/developer_private_functions.cc @@ -465,14 +339,26 @@ diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browse mDelegateModel = EmptyTabModel.getInstance(true); for (Callback delegateModelObserver : mDelegateModelObservers) { delegateModelObserver.onResult(mDelegateModel); +@@ -196,6 +204,10 @@ class IncognitoTabModelImpl implements IncognitoTabModelInternal { + assert mNativeAndroidBrowserWindow == 0; + mNativeAndroidBrowserWindow = nativeAndroidBrowserWindow; + mDelegateModel.associateWithBrowserWindow(nativeAndroidBrowserWindow); ++ ++ for (IncognitoTabModelObserver observer : mIncognitoObservers) { ++ observer.onAssociateWithBrowserWindow(); ++ } + } + + @Override diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelObserver.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelObserver.java --- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelObserver.java +++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelObserver.java -@@ -33,4 +33,6 @@ public interface IncognitoTabModelObserver { +@@ -33,4 +33,7 @@ public interface IncognitoTabModelObserver { /** Called when the last tab of the {@link IncognitoTabModel} is closed. */ default void didBecomeEmpty() {} + ++ default void onAssociateWithBrowserWindow() {} + default void didDestroyed() {} } diff --git a/chrome/browser/ui/android/extensions/extension_actions_bridge.cc b/chrome/browser/ui/android/extensions/extension_actions_bridge.cc @@ -559,6 +445,19 @@ diff --git a/chrome/browser/ui/android/extensions/extension_actions_bridge.h b/c const raw_ptr profile_; const base::android::ScopedJavaGlobalRef java_object_; const raw_ptr model_; +diff --git a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/browser/ui/extensions/ExtensionActionContextMenuBridge.java b/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/browser/ui/extensions/ExtensionActionContextMenuBridge.java +--- a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/browser/ui/extensions/ExtensionActionContextMenuBridge.java ++++ b/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/browser/ui/extensions/ExtensionActionContextMenuBridge.java +@@ -35,8 +35,8 @@ public class ExtensionActionContextMenuBridge implements Destroyable { + private final @Nullable LifetimeAssert mLifetimeAssert = LifetimeAssert.create(this); + + public ExtensionActionContextMenuBridge( +- ChromeAndroidTask task, + Profile profile, ++ ChromeAndroidTask task, + String actionId, + WebContents webContents, + @ContextMenuSource int contextMenuSource) { diff --git a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/browser/ui/extensions/ExtensionActionsBridge.java b/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/browser/ui/extensions/ExtensionActionsBridge.java --- a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/browser/ui/extensions/ExtensionActionsBridge.java +++ b/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/browser/ui/extensions/ExtensionActionsBridge.java @@ -570,62 +469,210 @@ diff --git a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/b import androidx.annotation.VisibleForTesting; -@@ -17,14 +18,17 @@ import org.jni_zero.NativeMethods; - import org.chromium.base.ObserverList; - import org.chromium.base.lifetime.Destroyable; - import org.chromium.base.lifetime.LifetimeAssert; -+import org.chromium.base.ThreadUtils; - import org.chromium.build.annotations.NullMarked; - import org.chromium.build.annotations.Nullable; - import org.chromium.chrome.browser.profiles.Profile; -+import org.chromium.chrome.browser.profiles.ProfileKeyedMap; - import org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTask; - import org.chromium.content_public.browser.WebContents; - import org.chromium.extensions.ShowAction; +@@ -26,18 +27,61 @@ import org.chromium.extensions.ShowAction; import java.util.Objects; -+import java.util.Map; ++import android.graphics.Rect; ++import org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTaskFeature; ++import org.chromium.chrome.browser.tabmodel.TabModel; ++import org.chromium.base.Log; ++ /** A JNI bridge to interact with extension actions for the toolbar. */ @NullMarked -@@ -34,10 +38,19 @@ public class ExtensionActionsBridge implements Destroyable { + @JNINamespace("extensions") +-public class ExtensionActionsBridge implements Destroyable { ++public class ExtensionActionsBridge implements ChromeAndroidTaskFeature { + private final @Nullable LifetimeAssert mLifetimeAssert = LifetimeAssert.create(this); private long mNativeExtensionActionsBridge; private final ObserverList mObservers = new ObserverList<>(); - public ExtensionActionsBridge(ChromeAndroidTask task, Profile profile) { -+ private static final ProfileKeyedMap mExtensionActionsBridges = -+ new ProfileKeyedMap<>((e) -> e.destroy()); ++ private static ExtensionActionsBridge currentExtensionActionsBridge; ++ private final Profile mProfile; ++ private final ChromeAndroidTask mTask; + -+ public static ExtensionActionsBridge get(Profile profile) { -+ ThreadUtils.assertOnUiThread(); -+ return mExtensionActionsBridges.getForProfile(profile, -+ ExtensionActionsBridge::new); ++ private ExtensionActionsBridge(ChromeAndroidTask task, Profile profile) { ++ mTask = task; ++ mProfile = profile; + } + -+ private ExtensionActionsBridge(Profile profile, Profile profile) { ++ @Override ++ public void onAddedToTask() { mNativeExtensionActionsBridge = ExtensionActionsBridgeJni.get() - .init(this, task.getOrCreateNativeBrowserWindowPtr(profile)); -+ .init(this, profile); ++ .init(this, mProfile); ++ } ++ ++ @Override ++ public void onFeatureRemoved() { ++ destroy(); ++ } ++ ++ @Override ++ public void onTaskBoundsChanged(Rect newBoundsInDp) {} ++ ++ @Override ++ public void onTaskFocusChanged(boolean hasFocus) {} ++ ++ @Override ++ public void onTabModelSelected(ChromeAndroidTask task, TabModel tabModel) { ++ if (mTask == task && tabModel.getProfile() == mProfile) { ++ Instance().mNativeExtensionActionsBridge = mNativeExtensionActionsBridge; ++ } ++ } ++ ++ public static ExtensionActionsBridge Instance() { ++ if (currentExtensionActionsBridge == null) ++ currentExtensionActionsBridge = new ExtensionActionsBridge(null, null); ++ return currentExtensionActionsBridge; ++ } ++ ++ public static ExtensionActionsBridge create(ChromeAndroidTask task, Profile profile) { ++ return new ExtensionActionsBridge(task, profile); } /** Represents the result of handling a key event. */ -@@ -71,6 +84,7 @@ public class ExtensionActionsBridge implements Destroyable { +@@ -69,8 +113,8 @@ public class ExtensionActionsBridge implements Destroyable { + } + } - @Override - public void destroy() { +- @Override +- public void destroy() { ++ private void destroy() { + closeBackgroundHosts(); assert mNativeExtensionActionsBridge != 0; ExtensionActionsBridgeJni.get().destroy(mNativeExtensionActionsBridge); mNativeExtensionActionsBridge = 0; -@@ -245,11 +259,15 @@ public class ExtensionActionsBridge implements Destroyable { - ExtensionActionsBridgeJni.get().clearExtensionData(mNativeExtensionActionsBridge); +@@ -78,11 +122,11 @@ public class ExtensionActionsBridge implements Destroyable { } -+ public void closeBackgroundHosts() { -+ ExtensionActionsBridgeJni.get().closeBackgroundHosts(mNativeExtensionActionsBridge); + public void addObserver(Observer observer) { +- mObservers.addObserver(observer); ++ Instance().mObservers.addObserver(observer); + } + + public void removeObserver(Observer observer) { +- mObservers.removeObserver(observer); ++ Instance().mObservers.removeObserver(observer); + } + + /** +@@ -91,19 +135,19 @@ public class ExtensionActionsBridge implements Destroyable { + *

If it returns false, you can install an observer to wait for initialization. + */ + public boolean areActionsInitialized() { +- return ExtensionActionsBridgeJni.get().areActionsInitialized(mNativeExtensionActionsBridge); ++ return ExtensionActionsBridgeJni.get().areActionsInitialized(Instance().mNativeExtensionActionsBridge); + } + + /** Returns a sorted list of enabled action IDs. */ + public String[] getActionIds() { +- return ExtensionActionsBridgeJni.get().getActionIds(mNativeExtensionActionsBridge); ++ return ExtensionActionsBridgeJni.get().getActionIds(Instance().mNativeExtensionActionsBridge); + } + + /** Returns the state of an action for a particular tab. */ + @Nullable + public ExtensionAction getAction(String actionId, int tabId) { + return ExtensionActionsBridgeJni.get() +- .getAction(mNativeExtensionActionsBridge, actionId, tabId); ++ .getAction(Instance().mNativeExtensionActionsBridge, actionId, tabId); + } + + /** +@@ -121,7 +165,7 @@ public class ExtensionActionsBridge implements Destroyable { + float scaleFactor) { + return ExtensionActionsBridgeJni.get() + .getActionIcon( +- mNativeExtensionActionsBridge, ++ Instance().mNativeExtensionActionsBridge, + actionId, + tabId, + webContents, +@@ -144,7 +188,7 @@ public class ExtensionActionsBridge implements Destroyable { + // should be easy for callers of this method to find the tab ID, so we ask them to pass it + // as an argument, even though the value is not used in production. + return ExtensionActionsBridgeJni.get() +- .runAction(mNativeExtensionActionsBridge, actionId, tabId, webContents); ++ .runAction(Instance().mNativeExtensionActionsBridge, actionId, tabId, webContents); + } + + /** +@@ -159,13 +203,13 @@ public class ExtensionActionsBridge implements Destroyable { + /** Handles the key down event and returns the result. */ + public HandleKeyEventResult handleKeyDownEvent(KeyEvent event) { + return ExtensionActionsBridgeJni.get() +- .handleKeyDownEvent(mNativeExtensionActionsBridge, event); ++ .handleKeyDownEvent(Instance().mNativeExtensionActionsBridge, event); + } + + @CalledByNative + @VisibleForTesting + public void onActionAdded(@JniType("std::string") String actionId) { +- for (Observer observer : mObservers) { ++ for (Observer observer : Instance().mObservers) { + observer.onActionAdded(actionId); + } + } +@@ -173,7 +217,7 @@ public class ExtensionActionsBridge implements Destroyable { + @CalledByNative + @VisibleForTesting + public void onActionRemoved(@JniType("std::string") String actionId) { +- for (Observer observer : mObservers) { ++ for (Observer observer : Instance().mObservers) { + observer.onActionRemoved(actionId); + } + } +@@ -181,7 +225,7 @@ public class ExtensionActionsBridge implements Destroyable { + @CalledByNative + @VisibleForTesting + public void onActionUpdated(@JniType("std::string") String actionId) { +- for (Observer observer : mObservers) { ++ for (Observer observer : Instance().mObservers) { + observer.onActionUpdated(actionId); + } + } +@@ -189,7 +233,7 @@ public class ExtensionActionsBridge implements Destroyable { + @CalledByNative + @VisibleForTesting + public void onActionModelInitialized() { +- for (Observer observer : mObservers) { ++ for (Observer observer : Instance().mObservers) { + observer.onActionModelInitialized(); + } + } +@@ -197,7 +241,7 @@ public class ExtensionActionsBridge implements Destroyable { + @CalledByNative + @VisibleForTesting + public void onPinnedActionsChanged() { +- for (Observer observer : mObservers) { ++ for (Observer observer : Instance().mObservers) { + observer.onPinnedActionsChanged(); + } + } +@@ -205,7 +249,7 @@ public class ExtensionActionsBridge implements Destroyable { + @CalledByNative + @VisibleForTesting + public void onActionIconUpdated(@JniType("std::string") String actionId) { +- for (Observer observer : mObservers) { ++ for (Observer observer : Instance().mObservers) { + observer.onActionIconUpdated(actionId); + } + } +@@ -242,14 +286,18 @@ public class ExtensionActionsBridge implements Destroyable { + } + + public void clearExtensionData() { +- ExtensionActionsBridgeJni.get().clearExtensionData(mNativeExtensionActionsBridge); ++ ExtensionActionsBridgeJni.get().clearExtensionData(Instance().mNativeExtensionActionsBridge); + } + ++ private void closeBackgroundHosts() { ++ ExtensionActionsBridgeJni.get().closeBackgroundHosts(mNativeExtensionActionsBridge); + } + @NativeMethods public interface Natives { boolean extensionsEnabled(@JniType("Profile*") Profile profile); @@ -635,7 +682,7 @@ diff --git a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/b void destroy(long nativeExtensionActionsBridge); -@@ -281,6 +299,8 @@ public class ExtensionActionsBridge implements Destroyable { +@@ -281,6 +329,8 @@ public class ExtensionActionsBridge implements Destroyable { void clearExtensionData(long nativeExtensionActionsBridge); @@ -644,6 +691,338 @@ diff --git a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/b HandleKeyEventResult handleKeyDownEvent( long nativeExtensionActionsBridge, @JniType("ui::KeyEventAndroid") KeyEvent keyEvent); +diff --git a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/browser/ui/extensions/ExtensionsMenuBridge.java b/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/browser/ui/extensions/ExtensionsMenuBridge.java +--- a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/browser/ui/extensions/ExtensionsMenuBridge.java ++++ b/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/browser/ui/extensions/ExtensionsMenuBridge.java +@@ -16,23 +16,75 @@ import org.chromium.build.annotations.Nullable; + import org.chromium.chrome.browser.profiles.Profile; + import org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTask; + ++import android.graphics.Rect; ++import android.util.ArrayMap; ++import java.util.Map; ++import org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTaskFeature; ++import org.chromium.chrome.browser.tabmodel.TabModel; ++import org.chromium.base.Log; ++ + /** A JNI bridge that provides native extensions menu data to the Java UI. */ + @NullMarked + @JNINamespace("extensions") +-public class ExtensionsMenuBridge implements Destroyable { ++public class ExtensionsMenuBridge implements ChromeAndroidTaskFeature { + private final @Nullable LifetimeAssert mLifetimeAssert = LifetimeAssert.create(this); + private long mNativeExtensionsMenuDelegateAndroid; +- private final Observer mObserver; ++ private Observer mObserver; ++ ++ private static ExtensionsMenuBridge currentExtensionsMenuBridge; ++ private final Map mObservers = new ArrayMap<>(); ++ private final ChromeAndroidTask mTask; ++ private final Profile mProfile; ++ ++ private ExtensionsMenuBridge(ChromeAndroidTask task, Profile profile) { ++ mObserver = null; ++ mProfile = profile; ++ mTask = task; ++ } ++ ++ public static ExtensionsMenuBridge Instance() { ++ if (currentExtensionsMenuBridge == null) ++ currentExtensionsMenuBridge = new ExtensionsMenuBridge(null, null); ++ return currentExtensionsMenuBridge; ++ } ++ ++ public static ExtensionsMenuBridge create(ChromeAndroidTask task, Profile profile) { ++ return new ExtensionsMenuBridge(task, profile); ++ } ++ ++ public void setObserver(ChromeAndroidTask task, Observer observer) { ++ Instance().mObservers.put(task, observer); ++ Instance().mObserver = observer; ++ } + +- public ExtensionsMenuBridge(ChromeAndroidTask task, Profile profile, Observer observer) { +- mObserver = observer; ++ @Override ++ public void onAddedToTask() { + mNativeExtensionsMenuDelegateAndroid = + ExtensionsMenuBridgeJni.get() +- .init(this, task.getOrCreateNativeBrowserWindowPtr(profile)); ++ .init(this, mTask.getOrCreateNativeBrowserWindowPtr(mProfile)); + } + + @Override +- public void destroy() { ++ public void onFeatureRemoved() { ++ Instance().mObservers.remove(mTask); ++ destroy(); ++ } ++ ++ @Override ++ public void onTaskBoundsChanged(Rect newBoundsInDp) {} ++ ++ @Override ++ public void onTaskFocusChanged(boolean hasFocus) {} ++ ++ @Override ++ public void onTabModelSelected(ChromeAndroidTask task, TabModel tabModel) { ++ if (mTask == task && tabModel.getProfile() == mProfile) { ++ Instance().mNativeExtensionsMenuDelegateAndroid = mNativeExtensionsMenuDelegateAndroid; ++ Instance().mObserver = Instance().mObservers.get(mTask); ++ } ++ } ++ ++ private void destroy() { + assert mNativeExtensionsMenuDelegateAndroid != 0; + ExtensionsMenuBridgeJni.get().destroy(mNativeExtensionsMenuDelegateAndroid); + mNativeExtensionsMenuDelegateAndroid = 0; +@@ -41,12 +93,12 @@ public class ExtensionsMenuBridge implements Destroyable { + + /** Returns a flattened list of action IDs and names from native. */ + public String[] getActions() { +- return ExtensionsMenuBridgeJni.get().getActions(mNativeExtensionsMenuDelegateAndroid); ++ return ExtensionsMenuBridgeJni.get().getActions(Instance().mNativeExtensionsMenuDelegateAndroid); + } + + /** Returns whether the native menu model is ready. */ + public boolean isReady() { +- return ExtensionsMenuBridgeJni.get().isReady(mNativeExtensionsMenuDelegateAndroid); ++ return ExtensionsMenuBridgeJni.get().isReady(Instance().mNativeExtensionsMenuDelegateAndroid); + } + + /** +@@ -55,7 +107,7 @@ public class ExtensionsMenuBridge implements Destroyable { + */ + @CalledByNative + public void onReady() { +- mObserver.onReady(); ++ //Instance().mObserver.onReady(); + } + + public interface Observer { +diff --git a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/browser/ui/extensions/ExtensionsToolbarBridge.java b/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/browser/ui/extensions/ExtensionsToolbarBridge.java +--- a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/browser/ui/extensions/ExtensionsToolbarBridge.java ++++ b/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/browser/ui/extensions/ExtensionsToolbarBridge.java +@@ -21,10 +21,17 @@ import org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTask; + import org.chromium.chrome.browser.ui.toolbar.InvocationSource; + import org.chromium.content_public.browser.WebContents; + ++import android.graphics.Rect; ++import android.util.ArrayMap; ++import java.util.Map; ++import org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTaskFeature; ++import org.chromium.chrome.browser.tabmodel.TabModel; ++import org.chromium.base.Log; ++ + /** A JNI bridge to interact with extension actions for the toolbar. */ + @NullMarked + @JNINamespace("extensions") +-public class ExtensionsToolbarBridge implements Destroyable { ++public class ExtensionsToolbarBridge implements ChromeAndroidTaskFeature { + private final @Nullable LifetimeAssert mLifetimeAssert = LifetimeAssert.create(this); + private long mNativeExtensionsToolbarAndroid; + private final ObserverList mObservers = new ObserverList<>(); +@@ -33,14 +40,55 @@ public class ExtensionsToolbarBridge implements Destroyable { + // with {@code ExtensionActionListMediator}. + private @Nullable Delegate mDelegate; + +- public ExtensionsToolbarBridge(ChromeAndroidTask task, Profile profile) { ++ private final ChromeAndroidTask mTask; ++ private final Profile mProfile; ++ ++ private static ExtensionsToolbarBridge toolbarBridgeInstance; ++ private final Map mDelegates = new ArrayMap<>(); ++ ++ @Override ++ public void onAddedToTask() { + mNativeExtensionsToolbarAndroid = + ExtensionsToolbarBridgeJni.get() +- .init(this, task.getOrCreateNativeBrowserWindowPtr(profile)); ++ .init(this, mTask.getOrCreateNativeBrowserWindowPtr(mProfile)); + } + + @Override +- public void destroy() { ++ public void onFeatureRemoved() { ++ Instance().mDelegates.remove(mTask); ++ destroy(); ++ } ++ ++ @Override ++ public void onTaskBoundsChanged(Rect newBoundsInDp) {} ++ ++ @Override ++ public void onTaskFocusChanged(boolean hasFocus) {} ++ ++ @Override ++ public void onTabModelSelected(ChromeAndroidTask task, TabModel tabModel) { ++ if (mTask == task && tabModel.getProfile() == mProfile) { ++ Instance().mNativeExtensionsToolbarAndroid = mNativeExtensionsToolbarAndroid; ++ Instance().mDelegate = Instance().mDelegates.get(mTask); ++ } ++ } ++ ++ public static ExtensionsToolbarBridge Instance() { ++ if (toolbarBridgeInstance == null) ++ toolbarBridgeInstance = new ExtensionsToolbarBridge(null, null); ++ return toolbarBridgeInstance; ++ } ++ ++ private ExtensionsToolbarBridge(ChromeAndroidTask task, Profile profile) { ++ mTask = task; ++ mProfile = profile; ++ } ++ ++ public static ExtensionsToolbarBridge create(ChromeAndroidTask task, Profile profile) { ++ return new ExtensionsToolbarBridge(task, profile); ++ } ++ ++ private void destroy() { + assert mNativeExtensionsToolbarAndroid != 0; + ExtensionsToolbarBridgeJni.get().destroy(mNativeExtensionsToolbarAndroid); + mNativeExtensionsToolbarAndroid = 0; +@@ -48,21 +96,23 @@ public class ExtensionsToolbarBridge implements Destroyable { + } + + public void addObserver(Observer observer) { +- mObservers.addObserver(observer); ++ Instance().mObservers.addObserver(observer); + } + + public void removeObserver(Observer observer) { +- mObservers.removeObserver(observer); ++ Instance().mObservers.removeObserver(observer); + } + +- public void setDelegate(@Nullable Delegate delegate) { +- mDelegate = delegate; ++ public void setDelegate(ChromeAndroidTask task, @Nullable Delegate delegate) { ++ Instance().mDelegates.put(task, delegate); ++ Instance().mDelegate = delegate; + } + + @Nullable + public ExtensionAction getAction(String actionId) { ++ assert Instance().mNativeExtensionsToolbarAndroid != 0; + return ExtensionsToolbarBridgeJni.get() +- .getAction(mNativeExtensionsToolbarAndroid, actionId); ++ .getAction(Instance().mNativeExtensionsToolbarAndroid, actionId); + } + + @Nullable +@@ -72,9 +122,10 @@ public class ExtensionsToolbarBridge implements Destroyable { + int canvasWidthDp, + int canvasHeightDp, + float scaleFactor) { ++ assert Instance().mNativeExtensionsToolbarAndroid != 0; + return ExtensionsToolbarBridgeJni.get() + .getIcon( +- mNativeExtensionsToolbarAndroid, ++ Instance().mNativeExtensionsToolbarAndroid, + actionId, + webContents, + canvasWidthDp, +@@ -83,28 +134,28 @@ public class ExtensionsToolbarBridge implements Destroyable { + } + + public String[] getAllActionIds() { +- return ExtensionsToolbarBridgeJni.get().getAllActionIds(mNativeExtensionsToolbarAndroid); ++ return ExtensionsToolbarBridgeJni.get().getAllActionIds(Instance().mNativeExtensionsToolbarAndroid); + } + + public String[] getPinnedActionIds() { +- return ExtensionsToolbarBridgeJni.get().getPinnedActionIds(mNativeExtensionsToolbarAndroid); ++ return ExtensionsToolbarBridgeJni.get().getPinnedActionIds(Instance().mNativeExtensionsToolbarAndroid); + } + + public void executeUserAction(String actionId, @InvocationSource int source) { + ExtensionsToolbarBridgeJni.get() +- .executeUserAction(mNativeExtensionsToolbarAndroid, actionId, source); ++ .executeUserAction(Instance().mNativeExtensionsToolbarAndroid, actionId, source); + } + + public void movePinnedAction(String actionId, int targetIndex) { + ExtensionsToolbarBridgeJni.get() +- .movePinnedAction(mNativeExtensionsToolbarAndroid, actionId, targetIndex); ++ .movePinnedAction(Instance().mNativeExtensionsToolbarAndroid, actionId, targetIndex); + } + + public RequestAccessButtonParams getRequestAccessButtonParams(WebContents webContents) { +- assert mNativeExtensionsToolbarAndroid != 0; ++ assert Instance().mNativeExtensionsToolbarAndroid != 0; + RequestAccessButtonParams params = + ExtensionsToolbarBridgeJni.get() +- .getRequestAccessButtonParams(mNativeExtensionsToolbarAndroid, webContents); ++ .getRequestAccessButtonParams(Instance().mNativeExtensionsToolbarAndroid, webContents); + assert params != null; + return params; + } +@@ -112,56 +163,56 @@ public class ExtensionsToolbarBridge implements Destroyable { + @CalledByNative + public void triggerPopup(@JniType("std::string") String actionId, long nativeHostPtr) { + // {@link mDelegate} should be set in {@code ExtensionActionListMediator}'s constructor. +- assert mDelegate != null; ++ assert Instance().mDelegate != null; + +- mDelegate.triggerPopup(actionId, nativeHostPtr); ++ Instance().mDelegate.triggerPopup(actionId, nativeHostPtr); + } + + @CalledByNative + public void onRequestAccessButtonParamsChanged() { +- for (Observer observer : mObservers) { ++ for (Observer observer : Instance().mObservers) { + observer.onRequestAccessButtonParamsChanged(); + } + } + + @CalledByNative + public void onActionsInitialized() { +- for (Observer observer : mObservers) { ++ for (Observer observer : Instance().mObservers) { + observer.onActionsInitialized(); + } + } + + @CalledByNative + public void onActionAdded(@JniType("std::string") String actionId) { +- for (Observer observer : mObservers) { ++ for (Observer observer : Instance().mObservers) { + observer.onActionAdded(actionId); + } + } + + @CalledByNative + public void onActionRemoved(@JniType("std::string") String actionId) { +- for (Observer observer : mObservers) { ++ for (Observer observer : Instance().mObservers) { + observer.onActionRemoved(actionId); + } + } + + @CalledByNative + public void onActionUpdated(@JniType("std::string") String actionId) { +- for (Observer observer : mObservers) { ++ for (Observer observer : Instance().mObservers) { + observer.onActionUpdated(actionId); + } + } + + @CalledByNative + public void onPinnedActionsChanged() { +- for (Observer observer : mObservers) { ++ for (Observer observer : Instance().mObservers) { + observer.onPinnedActionsChanged(); + } + } + + @CalledByNative + public void onActiveWebContentsChanged() { +- for (Observer observer : mObservers) { ++ for (Observer observer : Instance().mObservers) { + observer.onActiveWebContentsChanged(); + } + } diff --git a/chrome/browser/ui/android/tab_model/tab_model_jni_bridge.cc b/chrome/browser/ui/android/tab_model/tab_model_jni_bridge.cc --- a/chrome/browser/ui/android/tab_model/tab_model_jni_bridge.cc +++ b/chrome/browser/ui/android/tab_model/tab_model_jni_bridge.cc @@ -670,7 +1049,7 @@ diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/brow /** * Root component for the extension action buttons. Exposes public API for external consumers to * interact with the buttons and affect their states. -@@ -38,6 +40,7 @@ import org.chromium.ui.modelutil.PropertyModel; +@@ -38,14 +40,17 @@ import org.chromium.ui.modelutil.PropertyModel; public class ExtensionActionListCoordinator implements Destroyable { private final Context mContext; private final ExtensionActionListRecyclerView mContainer; @@ -678,34 +1057,33 @@ diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/brow private final ModelList mModels; private final ExtensionActionListMediator mMediator; private final DragReorderableRecyclerViewAdapter mAdapter; -@@ -46,13 +49,15 @@ public class ExtensionActionListCoordinator implements Destroyable { + @Nullable private final LifetimeAssert mLifetimeAssert = LifetimeAssert.create(this); ++ public final ExtensionsToolbarBridge mExtensionsToolbarBridge; + public ExtensionActionListCoordinator( Context context, ExtensionActionListRecyclerView container, + ListMenuButton extensionsMenuButton, WindowAndroid windowAndroid, -- ChromeAndroidTask task, -+ Function task, + ChromeAndroidTask task, Profile profile, - NullableObservableSupplier currentTabSupplier, +@@ -53,6 +58,8 @@ public class ExtensionActionListCoordinator implements Destroyable { ExtensionsToolbarBridge extensionsToolbarBridge) { mContext = context; mContainer = container; + mExtensionsMenuButton = extensionsMenuButton; ++ mExtensionsToolbarBridge = extensionsToolbarBridge; mModels = new ModelList(); mMediator = -@@ -60,7 +65,7 @@ public class ExtensionActionListCoordinator implements Destroyable { - context, - windowAndroid, - mModels, -- task, -+ task, profileSupplier, - profile, - currentTabSupplier, - container, -@@ -124,6 +129,7 @@ public class ExtensionActionListCoordinator implements Destroyable { +@@ -122,8 +129,13 @@ public class ExtensionActionListCoordinator implements Destroyable { + LifetimeAssert.setSafeToGc(mLifetimeAssert, true); + } ++ public void openPopup(String actionId) { ++ mMediator.onPrimaryClick(actionId); ++ } ++ /** Performs a click on the button for the given action. */ public void click(String actionId) { + mExtensionsMenuButton.dismiss(); @@ -715,7 +1093,7 @@ diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/brow diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionListMediator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionListMediator.java --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionListMediator.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionListMediator.java -@@ -37,13 +37,14 @@ import org.chromium.ui.modelutil.PropertyModel; +@@ -37,6 +37,7 @@ import org.chromium.ui.modelutil.PropertyModel; import java.util.Arrays; import java.util.HashSet; import java.util.Set; @@ -723,178 +1101,85 @@ diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/brow @NullMarked class ExtensionActionListMediator implements Destroyable { - private final Context mContext; +@@ -44,7 +45,6 @@ class ExtensionActionListMediator implements Destroyable { private final WindowAndroid mWindowAndroid; private final ModelList mModels; -- private final ChromeAndroidTask mTask; -+ private final FunctionmTaskmTaskSupplier - private final Profile mProfile; + private final ChromeAndroidTask mTask; +- private final Profile mProfile; private final NullableObservableSupplier mCurrentTabSupplier; private final ExtensionActionListRecyclerView mContainer; -@@ -61,7 +62,7 @@ class ExtensionActionListMediator implements Destroyable { - Context context, - WindowAndroid windowAndroid, - ModelList models, -- ChromeAndroidTask task, -+ Function task, - Profile profile, - NullableObservableSupplier currentTabSupplier, - ExtensionActionListRecyclerView container, -@@ -69,7 +70,7 @@ class ExtensionActionListMediator implements Destroyable { - mContext = context; + +@@ -70,12 +70,11 @@ class ExtensionActionListMediator implements Destroyable { mWindowAndroid = windowAndroid; mModels = models; -- mTask = task; -+ mTaskSupplier = task; - mProfile = profile; + mTask = task; +- mProfile = profile; mCurrentTabSupplier = currentTabSupplier; mContainer = container; -@@ -245,6 +246,11 @@ class ExtensionActionListMediator implements Destroyable { + mExtensionsToolbarBridge = extensionsToolbarBridge; - ExtensionActionPopupContents contents = ExtensionActionPopupContents.create(nativeHostPtr); +- mExtensionsToolbarBridge.setDelegate(mToolbarDelegate); ++ mExtensionsToolbarBridge.setDelegate(mTask, mToolbarDelegate); + mExtensionsToolbarBridge.addObserver(mToolbarObserver); + reconcileActionItems(); + } +@@ -85,7 +84,7 @@ class ExtensionActionListMediator implements Destroyable { + closePopup(); + assert mCurrentPopup == null; + mExtensionsToolbarBridge.removeObserver(mToolbarObserver); +- mExtensionsToolbarBridge.setDelegate(null); ++ mExtensionsToolbarBridge.setDelegate(mTask, null); + LifetimeAssert.setSafeToGc(mLifetimeAssert, true); + } + +@@ -234,7 +233,7 @@ class ExtensionActionListMediator implements Destroyable { + return mModels.get(index).model.get(ExtensionActionButtonProperties.ID); + } + +- private void onPrimaryClick(String actionId) { ++ public void onPrimaryClick(String actionId) { + mExtensionsToolbarBridge.executeUserAction(actionId, InvocationSource.TOOLBAR_BUTTON); + } + +@@ -247,8 +246,7 @@ class ExtensionActionListMediator implements Destroyable { -+ ChromeAndroidTask task = mTaskSupplier.apply(currentTab); -+ if (task == null) { -+ return; -+ } -+ View buttonView = getButtonViewForId(actionId); if (buttonView == null) { - contents.destroy(); -@@ -289,9 +295,11 @@ class ExtensionActionListMediator implements Destroyable { - return; +- contents.destroy(); +- return; ++ buttonView = mContainer; } -+ ChromeAndroidTask task = mTaskSupplier.apply(currentTab); -+ + assert mCurrentPopup == null; +@@ -291,7 +289,7 @@ class ExtensionActionListMediator implements Destroyable { + ExtensionActionContextMenuBridge bridge = new ExtensionActionContextMenuBridge( - mTask, mProfile, actionId, webContents, ContextMenuSource.TOOLBAR_ACTION); -+ task, mProfile, actionId, webContents, ContextMenuSource.TOOLBAR_ACTION); ++ currentTab.getProfile(), mTask, actionId, webContents, ContextMenuSource.TOOLBAR_ACTION); ListMenuButton buttonView = (ListMenuButton) getButtonViewForId(actionId); if (buttonView == null) { diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionsUpdateHelper.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionsUpdateHelper.java --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionsUpdateHelper.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionsUpdateHelper.java -@@ -47,19 +47,22 @@ public class ExtensionActionsUpdateHelper implements Destroyable { - void onUpdateFinished(); - } - -+ private final NullableObservableSupplier mProfileSupplier; - private final NullableObservableSupplier mCurrentTabSupplier; - private final ActionsUpdateDelegate mActionsUpdateDelegate; - private final ModelList mModels; -- private final ExtensionActionsBridge mExtensionActionsBridge; - -+ private final Callback<@Nullable Profile> mProfileUpdatedCallback = this::onProfileUpdated; - private final Callback<@Nullable Tab> mTabChangedCallback = this::onTabChanged; - private final ActionsObserver mActionsObserver = new ActionsObserver(); - -+ @Nullable private ExtensionActionsBridge mExtensionActionsBridge; -+ @Nullable private Profile mProfile; - @Nullable private Tab mCurrentTab; - - public ExtensionActionsUpdateHelper( - ModelList models, -- ChromeAndroidTask task, -+ NullableObservableSupplier profileSupplier, - Profile profile, - NullableObservableSupplier currentTabSupplier, - ActionsUpdateDelegate delegate) { -@@ -68,12 +71,13 @@ public class ExtensionActionsUpdateHelper implements Destroyable { +@@ -66,7 +66,7 @@ public class ExtensionActionsUpdateHelper implements Destroyable { + mModels = models; + mCurrentTabSupplier = currentTabSupplier; mActionsUpdateDelegate = delegate; - mExtensionActionsBridge = new ExtensionActionsBridge(task, profile); +- mExtensionActionsBridge = new ExtensionActionsBridge(task, profile); ++ mExtensionActionsBridge = ExtensionActionsBridge.Instance(); -+ mProfileSupplier = profileSupplier; -+ mProfileSupplier.addObserver(mProfileUpdatedCallback); mCurrentTabSupplier.addObserver(mTabChangedCallback); -- mExtensionActionsBridge.addObserver(mActionsObserver); - } - - private void maybeUpdateAllActions() { -- if (mCurrentTab == null) { -+ if (mProfile == null || mExtensionActionsBridge == null || mCurrentTab == null) { - mModels.clear(); - return; - } -@@ -100,6 +104,35 @@ public class ExtensionActionsUpdateHelper implements Destroyable { - mActionsUpdateDelegate.onUpdateFinished(); - } - -+ private void onProfileUpdated(@Nullable Profile profile) { -+ if (profile == mProfile) { -+ return; -+ } -+ -+ mActionsUpdateDelegate.onUpdateStarted(); -+ -+ if (mExtensionActionsBridge != null) { -+ mExtensionActionsBridge.removeObserver(mActionsObserver); -+ } -+ mExtensionActionsBridge = null; -+ mProfile = profile; -+ -+ if (mProfile != null) { -+ mExtensionActionsBridge = ExtensionActionsBridge.get(mProfile); -+ if (mExtensionActionsBridge != null) { -+ mExtensionActionsBridge.addObserver(mActionsObserver); -+ } -+ } -+ -+ mModels.clear(); -+ -+ if (mCurrentTab != null && mCurrentTab.getProfile() != mProfile) { -+ return; -+ } -+ -+ maybeUpdateAllActions(); -+ } -+ - private void onTabChanged(@Nullable Tab tab) { - if (tab == mCurrentTab) { - return; -@@ -118,9 +151,21 @@ public class ExtensionActionsUpdateHelper implements Destroyable { - } - - mCurrentTab = tab; -+ -+ // If the tab belongs to a different profile, onProfileUpdated will be called soon, so -+ // do not update actions now to avoid duplicated updates. -+ if (tab.getProfile() != mProfile) { -+ return; -+ } -+ - maybeUpdateAllActions(); - } - -+ /** Returns the profile. */ -+ public @Nullable Profile getProfile() { -+ return mProfile; -+ } -+ - /** Returns the current tab. */ - public @Nullable Tab getCurrentTab() { - return mCurrentTab; -@@ -133,11 +178,16 @@ public class ExtensionActionsUpdateHelper implements Destroyable { - - @Override + mExtensionActionsBridge.addObserver(mActionsObserver); +@@ -135,7 +135,6 @@ public class ExtensionActionsUpdateHelper implements Destroyable { public void destroy() { -- mExtensionActionsBridge.removeObserver(mActionsObserver); -+ if (mExtensionActionsBridge != null) { -+ mExtensionActionsBridge.removeObserver(mActionsObserver); -+ } -+ -+ mProfileSupplier.removeObserver(mProfileUpdatedCallback); + mExtensionActionsBridge.removeObserver(mActionsObserver); mCurrentTabSupplier.removeObserver(mTabChangedCallback); - mExtensionActionsBridge.destroy(); mCurrentTab = null; -+ mExtensionActionsBridge = null; -+ mProfile = null; } - - private class ActionsObserver implements ExtensionActionsBridge.Observer { diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionToolbarCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionToolbarCoordinator.java --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionToolbarCoordinator.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionToolbarCoordinator.java @@ -914,84 +1199,15 @@ diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/brow /** * The coordinator of the extension-related toolbar UI. * -@@ -42,8 +45,8 @@ public interface ExtensionToolbarCoordinator extends Destroyable { - Context context, - ViewStub extensionToolbarStub, - WindowAndroid windowAndroid, -- ChromeAndroidTask task, -- Profile profile, -+ Function task, -+ NullableObservableSupplier profileSupplier, - NullableObservableSupplier currentTabSupplier, - TabCreator tabCreator, - ThemeColorProvider themeColorProvider) { -@@ -63,6 +66,7 @@ public interface ExtensionToolbarCoordinator extends Destroyable { - windowAndroid, - task, - profile, -+ profileSupplier, - currentTabSupplier, - tabCreator, - themeColorProvider); -@@ -80,8 +84,9 @@ public interface ExtensionToolbarCoordinator extends Destroyable { - Context context, - ViewStub extensionToolbarStub, - WindowAndroid windowAndroid, -- ChromeAndroidTask task, -+ Function task, - Profile profile, -+ NullableObservableSupplier profileSupplier, - NullableObservableSupplier currentTabSupplier, - TabCreator tabCreator, - ThemeColorProvider themeColorProvider); diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionToolbarCoordinatorImpl.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionToolbarCoordinatorImpl.java --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionToolbarCoordinatorImpl.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionToolbarCoordinatorImpl.java -@@ -17,6 +17,7 @@ import org.chromium.build.annotations.Nullable; - import org.chromium.build.annotations.ServiceImpl; - import org.chromium.chrome.browser.profiles.Profile; - import org.chromium.chrome.browser.tab.Tab; -+import org.chromium.chrome.browser.tabmodel.TabModel; - import org.chromium.chrome.browser.tabmodel.TabCreator; - import org.chromium.chrome.browser.theme.ThemeColorProvider; - import org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTask; -@@ -26,6 +27,8 @@ import org.chromium.chrome.browser.ui.extensions.ExtensionUi; - import org.chromium.chrome.browser.ui.extensions.R; - import org.chromium.ui.base.WindowAndroid; - -+import java.util.function.Function; -+ - /** The implementation of {@link ExtensionToolbarCoordinator}. */ - @NullMarked - @ServiceImpl(ExtensionToolbarCoordinator.class) -@@ -33,43 +36,39 @@ public class ExtensionToolbarCoordinatorImpl implements ExtensionToolbarCoordina - private final @Nullable LifetimeAssert mLifetimeAssert = LifetimeAssert.create(this); - - // TODO(crbug.com/473396591): Remove once {link ExtensionActionsBridge} is deprecated. -- private ExtensionActionsBridge mBridge; - - private ExtensionsToolbarBridge mExtensionsToolbarBridge; - private ExtensionActionListCoordinator mExtensionActionListCoordinator; - private ExtensionsMenuAndAccessControlButtonCoordinator - mExtensionsMenuAndAccessControlButtonCoordinator; -+ private NullableObservableSupplier mCurrentTabSupplier; -+ Function mTaskSupplier; - - @Override - public void initializeWithNative( - Context context, - ViewStub extensionToolbarStub, - WindowAndroid windowAndroid, -- ChromeAndroidTask task, -+ Function task, - Profile profile, -+ NullableObservableSupplier profileSupplier, +@@ -50,23 +50,18 @@ public class ExtensionToolbarCoordinatorImpl implements ExtensionToolbarCoordina NullableObservableSupplier currentTabSupplier, TabCreator tabCreator, ThemeColorProvider themeColorProvider) { - mBridge = new ExtensionActionsBridge(task, profile); -+ mCurrentTabSupplier = currentTabSupplier; -+ mTaskSupplier = task; ++ mBridge = ExtensionActionsBridge.Instance(); extensionToolbarStub.setLayoutResource(R.layout.extension_toolbar_container); LinearLayout container = (LinearLayout) extensionToolbarStub.inflate(); @@ -1003,7 +1219,8 @@ diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/brow - container.setVisibility(View.GONE); - } - }); -- ++ mExtensionsToolbarBridge = ExtensionsToolbarBridge.Instance(); + mExtensionActionListCoordinator = new ExtensionActionListCoordinator( context, @@ -1011,46 +1228,40 @@ diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/brow + container.findViewById(R.id.extensions_menu_button), windowAndroid, task, -- profile, -+ profileSupplier, - currentTabSupplier, - mExtensionsToolbarBridge); - mExtensionsMenuAndAccessControlButtonCoordinator = -@@ -79,6 +78,7 @@ public class ExtensionToolbarCoordinatorImpl implements ExtensionToolbarCoordina - themeColorProvider, - task, profile, -+ profileSupplier, - currentTabSupplier, - tabCreator, - mExtensionsToolbarBridge, -@@ -91,7 +91,6 @@ public class ExtensionToolbarCoordinatorImpl implements ExtensionToolbarCoordina +@@ -90,8 +85,8 @@ public class ExtensionToolbarCoordinatorImpl implements ExtensionToolbarCoordina + public void destroy() { mExtensionsMenuAndAccessControlButtonCoordinator.destroy(); mExtensionActionListCoordinator.destroy(); - mExtensionsToolbarBridge.destroy(); +- mExtensionsToolbarBridge.destroy(); - mBridge.destroy(); ++ //mExtensionsToolbarBridge.destroy(); ++ //mBridge.destroy(); LifetimeAssert.setSafeToGc(mLifetimeAssert, true); } -@@ -102,6 +101,18 @@ public class ExtensionToolbarCoordinatorImpl implements ExtensionToolbarCoordina - return false; - } +diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuAndAccessControlButtonCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuAndAccessControlButtonCoordinator.java +--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuAndAccessControlButtonCoordinator.java ++++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuAndAccessControlButtonCoordinator.java +@@ -48,7 +48,8 @@ public class ExtensionsMenuAndAccessControlButtonCoordinator implements Destroya + NullableObservableSupplier currentTabSupplier, + TabCreator tabCreator, + ExtensionsToolbarBridge extensionsToolbarBridge, +- View requestAccessButton) { ++ View requestAccessButton, ++ ExtensionActionListCoordinator extensionActionListCoordinator) { + mExtensionsMenuCoordinator = + new ExtensionsMenuCoordinator( + context, +@@ -57,7 +58,7 @@ public class ExtensionsMenuAndAccessControlButtonCoordinator implements Destroya + task, + profile, + currentTabSupplier, +- tabCreator); ++ tabCreator, extensionActionListCoordinator); -+ Tab currentTab = mCurrentTabSupplier.get(); -+ if (currentTab == null) { -+ return false; -+ } -+ -+ ChromeAndroidTask task = mTaskSupplier.apply(currentTab); -+ if (task == null) { -+ return false; -+ } -+ -+ ExtensionActionsBridge mBridge = ExtensionActionsBridge.get(currentTab.getProfile()); -+ - ExtensionActionsBridge.HandleKeyEventResult result = mBridge.handleKeyDownEvent(event); - if (result.handled) { - return true; + mExtensionAccessControlButtonCoordinator = + new ExtensionAccessControlButtonCoordinator( diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuCoordinator.java --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuCoordinator.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuCoordinator.java @@ -1063,29 +1274,18 @@ diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/brow /** * Coordinator for the extensions menu, accessed from the puzzle icon in the toolbar. This class is * responsible for the button and the menu. -@@ -80,8 +82,9 @@ public class ExtensionsMenuCoordinator implements Destroyable { - Context context, - ListMenuButton extensionsMenuButton, - ThemeColorProvider themeColorProvider, -- ChromeAndroidTask task, -+ Function task, - Profile profile, -+ NullableObservableSupplier profileSupplier, - NullableObservableSupplier currentTabSupplier, - TabCreator tabCreator, - ExtensionActionListCoordinator extensionActionListCoordinator) { -@@ -177,6 +180,7 @@ public class ExtensionsMenuCoordinator implements Destroyable { - mContext, - mTask, - mProfile, -+ profileSupplier, - mCurrentTabSupplier, - mExtensionModels, - mPropertyModel, diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuMediator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuMediator.java --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuMediator.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuMediator.java -@@ -13,6 +13,7 @@ import org.chromium.base.supplier.NullableObservableSupplier; +@@ -5,6 +5,7 @@ + package org.chromium.chrome.browser.toolbar.extensions; + + import android.content.Context; ++import android.graphics.Bitmap; + import android.graphics.Rect; + import android.view.View; + +@@ -13,6 +14,7 @@ import org.chromium.base.supplier.NullableObservableSupplier; import org.chromium.build.annotations.NullMarked; import org.chromium.chrome.browser.extensions.ContextMenuSource; import org.chromium.chrome.browser.profiles.Profile; @@ -1093,7 +1293,7 @@ diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/brow import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.toolbar.extensions.ExtensionActionListCoordinator; import org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTask; -@@ -25,6 +26,8 @@ import org.chromium.ui.modelutil.MVCListAdapter.ModelList; +@@ -25,6 +27,8 @@ import org.chromium.ui.modelutil.MVCListAdapter.ModelList; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.widget.RectProvider; @@ -1102,280 +1302,153 @@ diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/brow /** * Mediator for the extensions menu. This class is responsible for listening to changes in the * extensions and updating the model accordingly. -@@ -33,7 +36,7 @@ import org.chromium.ui.widget.RectProvider; - class ExtensionsMenuMediator implements Destroyable, ExtensionsMenuBridge.Observer { - private final ModelList mActionModels; - private final Context mContext; -- private final NullableObservableSupplier mCurrentTabSupplier; -+ private final Function> mCurrentTabSupplier; - private final ExtensionsMenuBridge mMenuBridge; +@@ -38,7 +42,6 @@ class ExtensionsMenuMediator implements Destroyable, ExtensionsMenuBridge.Observ private final PropertyModel mMenuPropertyModel; private final Runnable mOnReady; -@@ -52,8 +55,9 @@ class ExtensionsMenuMediator implements Destroyable, ExtensionsMenuBridge.Observ - */ - public ExtensionsMenuMediator( - Context context, -- ChromeAndroidTask task, -+ Function task, - Profile profile, -+ NullableObservableSupplier profileSupplier, - NullableObservableSupplier currentTabSupplier, - ModelList actionModels, - PropertyModel propertyModel, -@@ -126,9 +130,11 @@ class ExtensionsMenuMediator implements Destroyable, ExtensionsMenuBridge.Observ - return; - } + private final ChromeAndroidTask mTask; +- private final Profile mProfile; + private final View mRootView; + private final ExtensionActionListCoordinator mExtensionActionListCoordinator; + +@@ -68,9 +71,9 @@ class ExtensionsMenuMediator implements Destroyable, ExtensionsMenuBridge.Observ + mMenuPropertyModel = propertyModel; + mRootView = rootView; + mTask = task; +- mProfile = profile; + +- mMenuBridge = new ExtensionsMenuBridge(mTask, mProfile, /* observer= */ this); ++ mMenuBridge = ExtensionsMenuBridge.Instance(); ++ mMenuBridge.setObserver(task, /* observer= */ this); + if (mMenuBridge.isReady()) { + onReady(); + } +@@ -128,7 +131,7 @@ class ExtensionsMenuMediator implements Destroyable, ExtensionsMenuBridge.Observ -+ ChromeAndroidTask task = mTask.apply(currentTab); -+ ExtensionActionContextMenuBridge contextMenuBridge = new ExtensionActionContextMenuBridge( - mTask, mProfile, actionId, webContents, ContextMenuSource.MENU_ITEM); -+ task, mProfile, actionId, webContents, ContextMenuSource.MENU_ITEM); ++ currentTab.getProfile(), mTask, actionId, webContents, ContextMenuSource.MENU_ITEM); ExtensionActionContextMenuUtils.showContextMenu( mContext, +@@ -141,7 +144,7 @@ class ExtensionsMenuMediator implements Destroyable, ExtensionsMenuBridge.Observ + /** Destroys the mediator. */ + @Override + public void destroy() { +- mMenuBridge.destroy(); ++ //mMenuBridge.destroy(); + } + + /** +@@ -159,12 +162,18 @@ class ExtensionsMenuMediator implements Destroyable, ExtensionsMenuBridge.Observ + final String id = actions[i]; + final String name = actions[i + 1]; + ++ Bitmap icon = ++ ExtensionActionIconUtil.getIcon( ++ mContext, mExtensionActionListCoordinator.mExtensionsToolbarBridge, ++ id, /*webContents*/ null); ++ + PropertyModel model = + new PropertyModel.Builder(ExtensionsMenuItemProperties.ALL_KEYS) + .with(ExtensionsMenuItemProperties.TITLE, name) ++ .with(ExtensionsMenuItemProperties.ICON, icon) + .with( + ExtensionsMenuItemProperties.ITEM_CLICK_LISTENER, +- (view) -> mExtensionActionListCoordinator.click(actionId)) ++ (view) -> mExtensionActionListCoordinator.openPopup(id)) + .with( + ExtensionsMenuItemProperties.CLICK_LISTENER, + (view) -> onContextMenuButtonClicked((ListMenuButton) view, id)) diff --git a/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskImpl.java b/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskImpl.java --- a/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskImpl.java +++ b/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskImpl.java -@@ -525,6 +525,9 @@ final class ChromeAndroidTaskImpl - if (isActivityToRemoveAtTop) { - registerListenersForTopActivity(); - } +@@ -250,7 +250,7 @@ final class ChromeAndroidTaskImpl + // profile is destroyed. This should be fixed. For now we can just defer the + // destruction until the activity is destroyed since there should never be more + // than one profile/window on desktop Android. +- if (!BuildConfig.IS_DESKTOP_ANDROID) { ++ if (!BuildConfig.IS_DESKTOP_ANDROID_CROMITE) { + var browserWindow = mAndroidBrowserWindows.remove(profile); + if (browserWindow != null) { + var ptr = browserWindow.getOrCreateNativePtr(); +@@ -284,6 +284,34 @@ final class ChromeAndroidTaskImpl + + associateTabModelWithBrowserWindow(incognitoModel); + } + -+ // (5) remove UnownedUserDataHost -+ topActivityScopedObjects.mTabModel.associateWithBrowserWindow(0); - } - - @Override -diff --git a/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskTrackerImpl.java b/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskTrackerImpl.java ---- a/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskTrackerImpl.java -+++ b/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskTrackerImpl.java -@@ -22,6 +22,7 @@ import org.chromium.build.annotations.NullMarked; - import org.chromium.build.annotations.Nullable; - import org.chromium.chrome.browser.customtabs.PopupIntentCreatorProvider; - import org.chromium.chrome.browser.incognito.IncognitoUtils; -+import org.chromium.chrome.browser.tabmodel.TabModel; - import org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTask.PendingTaskInfo; - import org.chromium.chrome.browser.util.WindowFeatures; - import org.chromium.ui.base.ActivityWindowAndroid; -@@ -36,6 +37,30 @@ import java.util.Map; - /** Implements {@link ChromeAndroidTaskTracker} as a singleton. */ - @NullMarked - final class ChromeAndroidTaskTrackerImpl implements ChromeAndroidTaskTracker { -+ private static class Key { -+ public final Integer mTaskId; -+ public final TabModel mTabModel; -+ -+ public Key(Integer taskId, TabModel tabModel) { -+ mTaskId = taskId; -+ mTabModel = tabModel; -+ } -+ -+ @Override -+ public boolean equals(Object obj) { -+ assert obj instanceof Key : "Wrong key."; -+ -+ Key ref = (Key) obj; -+ return this.mTaskId.equals(ref.mTaskId) -+ && this.mTabModel.equals(ref.mTabModel); -+ } -+ -+ @Override -+ public int hashCode() { -+ return mTaskId.hashCode() ^ mTabModel.hashCode(); -+ } -+ } -+ - private static @Nullable ChromeAndroidTaskTrackerImpl sInstance; - - private static boolean sPausePendingTaskActivityCreationForTesting; -@@ -53,7 +78,7 @@ final class ChromeAndroidTaskTrackerImpl implements ChromeAndroidTaskTracker { - * Maps {@link ChromeAndroidTask} IDs to their instances. This reflects the {@link - * ChromeAndroidTask}'s ID when it is alive, and is different from its ID in the pending state. - */ -- private final Map mTasks = new ArrayMap<>(); -+ private final Map mTasksCromite = new ArrayMap<>(); - - /** - * Maps pending {@link ChromeAndroidTask} IDs to their instances. This reflects the {@link -@@ -83,7 +108,8 @@ final class ChromeAndroidTaskTrackerImpl implements ChromeAndroidTaskTracker { - ThreadUtils.assertOnUiThread(); - int taskId = getTaskId(activityScopedObjects.mActivityWindowAndroid); - -- var existingTask = mTasks.get(taskId); -+ var key = new Key(taskId, activityScopedObjects.mTabModel); -+ var existingTask = mTasksCromite.get(key); - if (existingTask != null) { - assert existingTask.getBrowserWindowType() == browserWindowType - : "The browser window type of an existing task can't be changed."; -@@ -95,7 +121,7 @@ final class ChromeAndroidTaskTrackerImpl implements ChromeAndroidTaskTracker { - ChromeAndroidTask pendingTask = mPendingTasks.remove(pendingId); - assert pendingTask != null : "Invalid pendingId provided."; - pendingTask.addActivityScopedObjects(activityScopedObjects); -- mTasks.put(taskId, pendingTask); -+ mTasksCromite.put(key, pendingTask); - for (var observer : mObservers) { - observer.onTaskAdded(pendingTask); - } -@@ -103,7 +129,7 @@ final class ChromeAndroidTaskTrackerImpl implements ChromeAndroidTaskTracker { - } - - var newTask = new ChromeAndroidTaskImpl(browserWindowType, activityScopedObjects); -- mTasks.put(taskId, newTask); -+ mTasksCromite.put(key, newTask); - for (var observer : mObservers) { - observer.onTaskAdded(newTask); - } -@@ -143,23 +169,38 @@ final class ChromeAndroidTaskTrackerImpl implements ChromeAndroidTaskTracker { - - @Override - @Nullable -- public ChromeAndroidTask get(int taskId) { -+ public ChromeAndroidTask get(int taskId, TabModel tabModel) { - ThreadUtils.assertOnUiThread(); -- return mTasks.get(taskId); -+ var key = new Key(taskId, tabModel); -+ return mTasksCromite.get(key); - } - -- @Override -- public void remove(int taskId) { -- ThreadUtils.assertOnUiThread(); -- removeInternal(taskId); -- } -+ -+ // @Override -+ // public void remove(int taskId) { -+ // ThreadUtils.assertOnUiThread(); -+ // removeInternal(taskId); -+ // } - - @Override - public void onActivityWindowAndroidDestroy(ActivityWindowAndroid activityWindowAndroid) { - ThreadUtils.assertOnUiThread(); - int taskId = getTaskId(activityWindowAndroid); -- var task = mTasks.get(taskId); - -+ for (Key key : mTasksCromite.keySet()) { -+ if (key == null) continue; -+ if (key.mTaskId != taskId) continue; -+ -+ var task = mTasksCromite.get(key); -+ if (task.getTopActivityWindowAndroid() != activityWindowAndroid) { -+ continue; -+ } -+ onActivityWindowAndroidDestroy(task, activityWindowAndroid); -+ } -+ } -+ -+ @Override -+ public void onActivityWindowAndroidDestroy(ChromeAndroidTask task, ActivityWindowAndroid activityWindowAndroid) { - if (task == null) { - return; - } -@@ -179,7 +220,7 @@ final class ChromeAndroidTaskTrackerImpl implements ChromeAndroidTaskTracker { - // In the future, we can register a Task listener when a ChromeAndroidTask is created, - // then destroy it when notified of the Task removal. - if (task.getTopActivityWindowAndroid() == null) { -- removeInternal(taskId); -+ removeInternal(task); - } - } - -@@ -231,7 +272,7 @@ final class ChromeAndroidTaskTrackerImpl implements ChromeAndroidTaskTracker { - - /** Returns all PENDING and ALIVE Tasks. */ - /*package*/ List getAllTasks() { -- List tasks = new ArrayList<>(mTasks.values()); -+ List tasks = new ArrayList<>(mTasksCromite.values()); - tasks.addAll(mPendingTasks.values()); - return tasks; - } -@@ -246,10 +287,8 @@ final class ChromeAndroidTaskTrackerImpl implements ChromeAndroidTaskTracker { - */ - void removeAllForTesting() { - ThreadUtils.assertOnUiThread(); -- for (var task : mTasks.values()) { -- task.destroy(); -- } -- mTasks.clear(); -+ mTasksCromite.forEach((taskId, task) -> task.destroy()); -+ mTasksCromite.clear(); - for (var task : mPendingTasks.values()) { - task.destroy(); - } -@@ -290,13 +329,17 @@ final class ChromeAndroidTaskTrackerImpl implements ChromeAndroidTaskTracker { - pendingTaskInfo.mIntent, pendingTaskInfo.mCreateParams.getInitialBounds()); - } - -- private void removeInternal(int taskId) { -- var taskRemoved = mTasks.remove(taskId); -+ private void removeInternal(ChromeAndroidTask taskRemoved) { - if (taskRemoved != null) { -- for (var observer : mObservers) { -- observer.onTaskRemoved(taskRemoved); -+ for (Key key : mTasksCromite.keySet()) { -+ if (key == null) continue; -+ if (mTasksCromite.get(key) == taskRemoved) { -+ mTasksCromite.remove(key); -+ -+ mObservers.forEach((observer) -> observer.onTaskRemoved(taskRemoved)); -+ taskRemoved.destroy(); ++ @Override ++ public void didDestroyed() { ++ var activityScopedObjects = mActivityScopedObjectsDeque.peekFirst(); ++ assert activityScopedObjects != null ++ : "ActivityScopedObjects should not be null if the" ++ + " mIncognitoTabModelObserver is registered."; ++ var tabModelSelector = activityScopedObjects.mTabModelSelector; ++ var incognitoModel = tabModelSelector.getModel(/* incognito= */ true); ++ var incognitoProfile = incognitoModel.getProfile(); ++ var iterator = mFeatures.entrySet().iterator(); ++ while (iterator.hasNext()) { ++ var entry = iterator.next(); ++ var key = entry.getKey(); ++ if (incognitoProfile.equals(key.mProfile)) { ++ entry.getValue().onFeatureRemoved(); ++ iterator.remove(); ++ } ++ } ++ var browserWindow = mAndroidBrowserWindows.remove(incognitoProfile); ++ if (browserWindow != null) { ++ var ptr = browserWindow.getOrCreateNativePtr(); ++ for (var observer : mAndroidBrowserWindowObservers) { ++ observer.onBrowserWindowRemoved(ptr); ++ } ++ browserWindow.destroy(); ++ } + } + }; + + private @Nullable Integer mId; +@@ -548,7 +576,7 @@ final class ChromeAndroidTaskImpl + mFeatures.put(featureKey, feature); + feature.onAddedToTask(); + if (tabModelSelector != null) { +- feature.onTabModelSelected(tabModelSelector.getCurrentModel()); ++ feature.onTabModelSelected(this, tabModelSelector.getCurrentModel()); } -- taskRemoved.destroy(); + } + } +@@ -964,6 +992,13 @@ final class ChromeAndroidTaskImpl + for (var feature : mFeatures.values()) { + feature.onTaskFocusChanged(isTopResumedActivity); + } ++ if (isTopResumedActivity) { ++ var topActivityScopedObjects = mActivityScopedObjectsDeque.peekFirst(); ++ TabModelSelector tabModelSelector = topActivityScopedObjects.mTabModelSelector; ++ for (var feature : mFeatures.values()) { ++ feature.onTabModelSelected(this, tabModelSelector.getCurrentModel()); ++ } ++ } + } + + @Override +@@ -1479,7 +1514,7 @@ final class ChromeAndroidTaskImpl + + private void onTabModelSelected(TabModel tabModel) { + for (var feature : mFeatures.values()) { +- feature.onTabModelSelected(tabModel); ++ feature.onTabModelSelected(this, tabModel); } } -@@ -332,7 +375,8 @@ final class ChromeAndroidTaskTrackerImpl implements ChromeAndroidTaskTracker { - @BrowserWindowType int browserWindowType = createParams.getWindowType(); - switch (browserWindowType) { - case BrowserWindowType.NORMAL: -- for (ChromeAndroidTask task : mTasks.values()) { -+ List tasks = new ArrayList<>(mTasksCromite.values()); -+ for (ChromeAndroidTask task : tasks) { - var intent = task.createIntentForNormalBrowserWindow(isIncognito); - if (intent != null) { - return intent; -diff --git a/chrome/browser/ui/browser_window/public/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskTracker.java b/chrome/browser/ui/browser_window/public/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskTracker.java ---- a/chrome/browser/ui/browser_window/public/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskTracker.java -+++ b/chrome/browser/ui/browser_window/public/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskTracker.java -@@ -8,6 +8,7 @@ import org.chromium.base.JniOnceCallback; - import org.chromium.build.annotations.NullMarked; - import org.chromium.build.annotations.Nullable; - import org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTask.ActivityScopedObjects; -+import org.chromium.chrome.browser.tabmodel.TabModel; - import org.chromium.ui.base.ActivityWindowAndroid; - - /** -@@ -83,7 +84,7 @@ public interface ChromeAndroidTaskTracker { +diff --git a/chrome/browser/ui/browser_window/public/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskFeature.java b/chrome/browser/ui/browser_window/public/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskFeature.java +--- a/chrome/browser/ui/browser_window/public/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskFeature.java ++++ b/chrome/browser/ui/browser_window/public/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskFeature.java +@@ -55,5 +55,5 @@ public interface ChromeAndroidTaskFeature { * - * @param taskId Same as defined by {@link android.app.TaskInfo#taskId}. + * @param tabModel The selected {@link TabModel}. */ -- @Nullable ChromeAndroidTask get(int taskId); -+ @Nullable ChromeAndroidTask get(int taskId, TabModel tabModel); - - /** - * Removes from the internal collection the {@link ChromeAndroidTask} with the given {@code -@@ -91,7 +92,7 @@ public interface ChromeAndroidTaskTracker { - * - * @param taskId Same as defined by {@link android.app.TaskInfo#taskId}. - */ -- void remove(int taskId); -+ //void remove(int taskId); - - /** - * Called when an {@link ActivityWindowAndroid} is destroyed. -@@ -100,6 +101,8 @@ public interface ChromeAndroidTaskTracker { - */ - void onActivityWindowAndroidDestroy(ActivityWindowAndroid activityWindowAndroid); - -+ void onActivityWindowAndroidDestroy(ChromeAndroidTask task, ActivityWindowAndroid activityWindowAndroid); -+ - /** - * Adds an observer which will be called on addition or removal of tasks. - * +- default void onTabModelSelected(TabModel tabModel) {} ++ default void onTabModelSelected(ChromeAndroidTask task, TabModel tabModel) {} + } diff --git a/components/tabs/impl/tab_collection.cc b/components/tabs/impl/tab_collection.cc --- a/components/tabs/impl/tab_collection.cc +++ b/components/tabs/impl/tab_collection.cc diff --git a/build/patches/Experimental-support-for-extensions-on-Android.patch b/build/patches/Experimental-support-for-extensions-on-Android.patch index 57b68b1e..43715c6e 100644 --- a/build/patches/Experimental-support-for-extensions-on-Android.patch +++ b/build/patches/Experimental-support-for-extensions-on-Android.patch @@ -13,10 +13,13 @@ folder in case of a crash on startup. License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- android_webview/BUILD.gn | 2 +- + base/allocator/partition_alloc_features.cc | 2 +- + .../src/partition_alloc/BUILD.gn | 3 +- base/android/device_info.cc | 8 ++- base/android/device_info.h | 3 +- - .../src/org/chromium/base/DeviceInfo.java | 6 +- + .../src/org/chromium/base/DeviceInfo.java | 8 ++- build/BUILD.gn | 2 +- + .../java/templates/BuildConfig.template | 8 ++- build/config/android/rules.gni | 4 +- build/config/chrome_build.gni | 7 +- build/config/compiler/BUILD.gn | 2 +- @@ -39,7 +42,7 @@ License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html ...InterceptNavigationDelegateClientImpl.java | 2 +- .../browser/tab/RequestDesktopUtils.java | 2 +- .../TabbedAppMenuPropertiesDelegate.java | 2 +- - .../tabbed_mode/TabbedRootUiCoordinator.java | 2 +- + .../tabbed_mode/TabbedRootUiCoordinator.java | 4 +- chrome/app/extensions_strings.grdp | 7 ++ chrome/app/theme/theme_resources.grd | 4 +- chrome/browser/BUILD.gn | 6 +- @@ -47,6 +50,7 @@ License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html ...chrome_selection_dropdown_menu_delegate.cc | 4 +- .../bookmarks/bar/BookmarkBarUtils.java | 6 +- .../bar/BookmarkBarVisibilityProvider.java | 2 +- + .../BrowserControlsUtils.java | 2 +- chrome/browser/browser_process_impl.cc | 2 +- chrome/browser/chrome_browser_field_trials.cc | 66 +++++++++---------- .../chrome_browser_interface_binders_webui.cc | 4 +- @@ -58,15 +62,18 @@ License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html .../chrome_extensions_api_client_android.cc | 2 +- .../extensions/api/identity/web_auth_flow.cc | 6 +- .../extensions/api/identity/web_auth_flow.h | 4 +- + .../extensions/api/tabs/tabs_event_router.cc | 3 + .../extensions/extension_management.cc | 8 ++- .../browser/extensions/extension_management.h | 2 +- chrome/browser/extensions/extension_util.cc | 11 ++++ .../feedback/DeviceInfoFeedbackSource.java | 2 +- + .../browser/flags/ChromeFeatureList.java | 6 +- chrome/browser/media/router/BUILD.gn | 4 +- .../browser/media/router/discovery/BUILD.gn | 2 +- .../media/router/media_router_feature.cc | 10 +-- .../media/router/media_router_feature.h | 2 +- .../media/webrtc/webrtc_event_log_manager.cc | 4 +- + .../browser/open_in_app/OpenInAppUtils.java | 2 +- .../policy_value_and_status_aggregator.cc | 2 +- ...hrome_browser_main_extra_parts_profiles.cc | 2 +- .../profiles/off_the_record_profile_impl.cc | 9 ++- @@ -75,8 +82,9 @@ License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html chrome/browser/resources/discards/BUILD.gn | 2 +- .../resources/extensions/detail_view.css | 6 ++ .../resources/extensions/extensions.html | 8 ++- - .../resources/extensions/item_list.css | 11 ++++ + .../resources/extensions/item_list.css | 10 +++ .../resources/extensions/toolbar.html.ts | 7 -- + .../sessions/session_restore_android.cc | 4 +- ...omeProvidedSharingOptionsProviderBase.java | 4 +- chrome/browser/startup_data.cc | 6 +- chrome/browser/startup_data.h | 6 +- @@ -85,14 +93,18 @@ License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html .../browser/ui/android/context_menu_helper.cc | 12 +++- .../browser/ui/android/context_menu_helper.h | 4 +- .../desktop_site/DesktopSiteUtils.java | 4 +- + .../TopControlsLockCoordinator.java | 2 +- chrome/browser/ui/android/extensions/BUILD.gn | 4 +- .../extensions/extension_actions_bridge.cc | 23 +++++++ .../extensions/extension_actions_bridge.h | 1 + + .../extensions/extensions_toolbar_android.cc | 1 + .../java/res/layout/extensions_menu.xml | 1 + .../res/layout/extensions_menu_footer.xml | 4 +- .../extensions/java/res/values/dimens.xml | 1 + .../ui/extensions/ExtensionActionsBridge.java | 6 ++ .../extensions/windowing/internal/BUILD.gn | 2 +- + .../extension_window_controller_bridge.cc | 17 ++--- + .../extension_window_controller_bridge.h | 2 +- .../Enable-extensions-Android.grdp | 15 +++++ .../Extensions-Android.grdp | 9 +++ .../browser/ui/android/tab_model/tab_model.cc | 4 +- @@ -120,7 +132,7 @@ License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html chrome/common/webui_url_constants.h | 2 +- .../sandbox_status_extension_android.cc | 3 +- .../sandbox_status_extension_android.h | 1 + - chrome/test/BUILD.gn | 14 ++-- + chrome/test/BUILD.gn | 18 ++--- chrome/version.gni | 4 +- .../core/browser/host_content_settings_map.cc | 6 ++ .../embedder_support/view/ContentView.java | 2 +- @@ -132,7 +144,7 @@ License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html .../components/policy/PolicyCacheUpdater.java | 2 +- .../android/policy_cache_updater_android.cc | 4 +- .../cloud/user_policy_signin_service_base.cc | 2 +- - .../configuration_policy_handler_list.cc | 2 +- + .../configuration_policy_handler_list.cc | 4 +- .../common/cloud/cloud_policy_constants.cc | 2 +- components/policy/core/common/features.cc | 2 +- .../policy/core/common/policy_merger.cc | 4 +- @@ -176,16 +188,16 @@ License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html .../cpp_bundle_generator.py | 2 +- .../ui/widget/PopupSpecCalculator.java | 9 ++- .../ui/test/util/UiDisableIfSkipCheck.java | 8 +-- - .../chromium/ui/test/util/UiRestriction.java | 2 +- + .../chromium/ui/test/util/UiRestriction.java | 4 +- ui/base/accelerators/command.cc | 2 +- ui/base/device_form_factor_android.cc | 2 +- ui/gl/features.gni | 2 +- ui/resources/ui_resources.grd | 2 +- ui/webui/resources/BUILD.gn | 4 +- ui/webui/resources/cr_elements/BUILD.gn | 2 +- - .../cr_elements/cr_toolbar/cr_toolbar.css | 6 ++ + .../cr_elements/cr_toolbar/cr_toolbar.css | 3 + ui/webui/resources/css/BUILD.gn | 2 +- - 173 files changed, 573 insertions(+), 283 deletions(-) + 185 files changed, 605 insertions(+), 311 deletions(-) create mode 100644 chrome/browser/ui/android/strings/cromite_android_chrome_strings_grd/Enable-extensions-Android.grdp create mode 100644 chrome/browser/ui/android/strings/cromite_android_chrome_strings_grd/Extensions-Android.grdp create mode 100644 cromite_flags/chrome/browser/about_flags_cc/Extensions-Android.inc @@ -202,6 +214,31 @@ diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn # For Android Desktop x64, orderfile is disabled, see # https://crbug.com/422005929. webview_orderfile_path = "" +diff --git a/base/allocator/partition_alloc_features.cc b/base/allocator/partition_alloc_features.cc +--- a/base/allocator/partition_alloc_features.cc ++++ b/base/allocator/partition_alloc_features.cc +@@ -190,7 +190,7 @@ BASE_FEATURE_ENUM_PARAM(BackupRefPtrEnabledProcesses, + kBackupRefPtrEnabledProcessesParam, + &kPartitionAllocBackupRefPtr, + kPAFeatureEnabledProcessesStr, +-#if PA_BUILDFLAG(IS_ANDROID) && !PA_BUILDFLAG(IS_DESKTOP_ANDROID) ++#if PA_BUILDFLAG(IS_ANDROID) && !PA_BUILDFLAG(IS_DESKTOP_ANDROID_FALSE) + BackupRefPtrEnabledProcesses::kNonRenderer, + #else + BackupRefPtrEnabledProcesses::kAllProcesses, +diff --git a/base/allocator/partition_allocator/src/partition_alloc/BUILD.gn b/base/allocator/partition_allocator/src/partition_alloc/BUILD.gn +--- a/base/allocator/partition_allocator/src/partition_alloc/BUILD.gn ++++ b/base/allocator/partition_allocator/src/partition_alloc/BUILD.gn +@@ -165,7 +165,8 @@ pa_buildflag_header("buildflags") { + "HAS_64_BIT_POINTERS=$has_64_bit_pointers", + "HAS_MEMORY_TAGGING=$has_memory_tagging", + "IS_ANDROID=$is_android", +- "IS_DESKTOP_ANDROID=$is_desktop_android", ++ "IS_DESKTOP_ANDROID_FALSE=false", ++ "IS_DESKTOP_ANDROID_CROMITE=$is_desktop_android_cromite", + "IS_CASTOS=$is_castos", + "IS_CAST_ANDROID=$is_cast_android", + "IS_CHROMEOS=$is_chromeos", diff --git a/base/android/device_info.cc b/base/android/device_info.cc --- a/base/android/device_info.cc +++ b/base/android/device_info.cc @@ -262,6 +299,15 @@ diff --git a/base/android/java/src/org/chromium/base/DeviceInfo.java b/base/andr public static int getVulkanDeqpLevel() { return getInstance().mIDeviceInfo.vulkanDeqpLevel; } +@@ -283,7 +287,7 @@ public final class DeviceInfo { + } + + mIDeviceInfo.isDesktop = +- (BuildConfig.IS_DESKTOP_ANDROID && pm.hasSystemFeature(PackageManager.FEATURE_PC)) ++ (BuildConfig.IS_DESKTOP_ANDROID_FALSE && pm.hasSystemFeature(PackageManager.FEATURE_PC)) + || CommandLine.getInstance().hasSwitch(BaseSwitches.FORCE_DESKTOP_ANDROID); + + // Detect whether device is foldable. diff --git a/build/BUILD.gn b/build/BUILD.gn --- a/build/BUILD.gn +++ b/build/BUILD.gn @@ -274,6 +320,25 @@ diff --git a/build/BUILD.gn b/build/BUILD.gn } if (build_with_chromium) { +diff --git a/build/android/java/templates/BuildConfig.template b/build/android/java/templates/BuildConfig.template +--- a/build/android/java/templates/BuildConfig.template ++++ b/build/android/java/templates/BuildConfig.template +@@ -110,10 +110,12 @@ public class BuildConfig { + // DeviceInfo.java since this is the source of truth for isDesktop check. + // (TODO: crbug.com/430983585) Clean up this flag once the desktop + // build is fully functional. +-#if defined(_IS_DESKTOP_ANDROID) +- public static boolean IS_DESKTOP_ANDROID = true; ++#if defined(_IS_DESKTOP_ANDROID_CROMITE) ++ public static boolean IS_DESKTOP_ANDROID_CROMITE = true; ++ public static boolean IS_DESKTOP_ANDROID_FALSE; + #else +- public static boolean IS_DESKTOP_ANDROID; ++ public static boolean IS_DESKTOP_ANDROID_CROMITE; ++ public static boolean IS_DESKTOP_ANDROID_FALSE; + #endif + + // Use to check if proguard is enabled for the current build. diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni @@ -355,7 +420,7 @@ diff --git a/cc/resources/ui_resource_bitmap.cc b/cc/resources/ui_resource_bitma diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn -@@ -971,7 +971,7 @@ if (_is_default_toolchain) { +@@ -970,7 +970,7 @@ if (_is_default_toolchain) { "//chrome/browser/password_entry_edit/android/internal:java", ] @@ -364,7 +429,7 @@ diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn deps += [ "//chrome/browser/ui/android/extensions/windowing/internal:java" ] } else { -@@ -2342,7 +2342,7 @@ if (_is_default_toolchain) { +@@ -2341,7 +2341,7 @@ if (_is_default_toolchain) { "//components/embedder_support/android:virtual_structure_javatests", ] @@ -449,7 +514,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActiv diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java --- a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java -@@ -1202,7 +1202,7 @@ public abstract class AppMenuPropertiesDelegateImpl implements AppMenuProperties +@@ -1191,7 +1191,7 @@ public abstract class AppMenuPropertiesDelegateImpl implements AppMenuProperties && !shouldShowReaderModePrefs(currentTab) && currentTab != null && currentTab.getWebContents() != null @@ -580,7 +645,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/site_settings/M + @Override + public void onClick(DialogInterface dialog, int id) { + Profile profile = ProfileManager.getLastUsedRegularProfile(); -+ ExtensionActionsBridge.get(profile).clearExtensionData(); ++ // ExtensionActionsBridge.get(profile).clearExtensionData(); + } + }); + builder.setNegativeButton(R.string.cancel, null); @@ -617,7 +682,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/RequestDesk diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java --- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java -@@ -867,7 +867,7 @@ public class TabbedAppMenuPropertiesDelegate extends AppMenuPropertiesDelegateIm +@@ -863,7 +863,7 @@ public class TabbedAppMenuPropertiesDelegate extends AppMenuPropertiesDelegateIm return false; } @@ -629,6 +694,15 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/Tab diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java --- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java +@@ -647,7 +647,7 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator { + }); + + mCrossDeviceSettingImporter = +- DeviceInfo.isDesktop() ++ ((true)) + ? null + : new CrossDeviceSettingImporter( + activityLifecycleDispatcher, @@ -2133,7 +2133,7 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator { } else if (id == R.id.toggle_bookmark_bar) { // isActivityStateBookmarkBarCompatible already checks the flag sAndroidBookmarkBar. @@ -682,7 +756,7 @@ diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resou diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn -@@ -7615,7 +7615,7 @@ static_library("browser") { +@@ -7613,7 +7613,7 @@ static_library("browser") { deps += [ "//media/mojo/mojom:remoting" ] } @@ -691,7 +765,7 @@ diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn sources += [ "download/download_crx_util_android.cc" ] } -@@ -7946,7 +7946,7 @@ static_library("browser") { +@@ -7944,7 +7944,7 @@ static_library("browser") { # TODO(https://crbug.com/356905053): Add more dependencies here and merge this # block with the `enable_extensions` block above. @@ -700,7 +774,7 @@ diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn sources += [ # TODO(https://crbug.com/356905053): These files are temporary workarounds # allow for a lightweight extensions runtime in desktop-android builds. -@@ -8718,7 +8718,7 @@ static_library("browser_generated_files") { +@@ -8716,7 +8716,7 @@ static_library("browser_generated_files") { [ "//chrome/browser/ui/webui/new_tab_page/foo:mojo_bindings" ] } } @@ -784,6 +858,18 @@ diff --git a/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/brows mDevicePrefsListener = (sharedPreferences, key) -> { if (key != null +diff --git a/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserControlsUtils.java b/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserControlsUtils.java +--- a/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserControlsUtils.java ++++ b/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserControlsUtils.java +@@ -43,7 +43,7 @@ public class BrowserControlsUtils { + return false; + } + +- return DeviceInfo.isDesktop() ++ return DeviceInfo.isDesktopFalse() + || DeviceFormFactor.isNonMultiDisplayContextOnLargeTablet(context); + } + diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc @@ -967,7 +1053,7 @@ diff --git a/chrome/browser/chrome_browser_interface_binders_webui.cc b/chrome/b diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc -@@ -4308,7 +4308,7 @@ base::OnceClosure ChromeContentBrowserClient::SelectClientCertificate( +@@ -4307,7 +4307,7 @@ base::OnceClosure ChromeContentBrowserClient::SelectClientCertificate( // TODO(wenz): This should instead proceed with the selected certificate // when there are matching certificates in the OS. #if BUILDFLAG(ENABLE_EXTENSIONS) && \ @@ -976,7 +1062,7 @@ diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/ch if (matching_certificates.empty() && nonmatching_certificates.empty()) { extensions::ProcessMap* process_map = extensions::ProcessMap::Get(profile); -@@ -4540,7 +4540,7 @@ void ChromeContentBrowserClient::OverrideWebPreferences( +@@ -4539,7 +4539,7 @@ void ChromeContentBrowserClient::OverrideWebPreferences( // Fill font preferences. These are not registered on Android unless we're built // with extensions (the chrome.fontSettings API can change these). // - http://crbug.com/40337093, http://crbug.com/41304476. @@ -1122,6 +1208,19 @@ diff --git a/chrome/browser/extensions/api/identity/web_auth_flow.h b/chrome/bro base::WeakPtrFactory weak_factory_{this}; #endif }; +diff --git a/chrome/browser/extensions/api/tabs/tabs_event_router.cc b/chrome/browser/extensions/api/tabs/tabs_event_router.cc +--- a/chrome/browser/extensions/api/tabs/tabs_event_router.cc ++++ b/chrome/browser/extensions/api/tabs/tabs_event_router.cc +@@ -338,6 +338,9 @@ void TabsEventRouter::DispatchEvent( + + void TabsEventRouter::OnTabAdded(tabs::TabInterface* tab, int index) { + content::WebContents* contents = tab->GetContents(); ++#if BUILDFLAG(IS_ANDROID) ++ if (!contents) return; ++#endif + CHECK(contents); + + // Check if we've ever seen this tab. diff --git a/chrome/browser/extensions/extension_management.cc b/chrome/browser/extensions/extension_management.cc --- a/chrome/browser/extensions/extension_management.cc +++ b/chrome/browser/extensions/extension_management.cc @@ -1200,6 +1299,36 @@ diff --git a/chrome/browser/feedback/android/java/src/org/chromium/chrome/browse type = TYPE_DESKTOP; } else if (DeviceFormFactor.isNonMultiDisplayContextOnTablet( ContextUtils.getApplicationContext())) { +diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java ++++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +@@ -757,7 +757,7 @@ public abstract class ChromeFeatureList { + public static final CachedFlag sAndroidNewMediaPicker = + newCachedFlag(ANDROID_NEW_MEDIA_PICKER, false); + public static final CachedFlag sAndroidOpenIncognitoAsWindow = +- newCachedFlag(ANDROID_OPEN_INCOGNITO_AS_WINDOW, BuildConfig.IS_DESKTOP_ANDROID, true); ++ newCachedFlag(ANDROID_OPEN_INCOGNITO_AS_WINDOW, BuildConfig.IS_DESKTOP_ANDROID_FALSE, false); + public static final CachedFlag sAndroidProgressBarVisualUpdate = + newCachedFlag( + ANDROID_PROGRESS_BAR_VISUAL_UPDATE, +@@ -884,7 +884,7 @@ public abstract class ChromeFeatureList { + public static final CachedFlag sChromeItemPickerUi = + newCachedFlag(CHROME_ITEM_PICKER_UI, /* defaultValue= */ false); + public static final CachedFlag sChromeNativeUrlOverriding = +- newCachedFlag(CHROME_NATIVE_URL_OVERRIDING, BuildConfig.IS_DESKTOP_ANDROID); ++ newCachedFlag(CHROME_NATIVE_URL_OVERRIDING, BuildConfig.IS_DESKTOP_ANDROID_FALSE); + public static final CachedFlag sClampAutomotiveScaling = + newCachedFlag(CLAMP_AUTOMOTIVE_SCALING, true); + public static final CachedFlag sClankStartupLatencyInjection = +@@ -1040,7 +1040,7 @@ public abstract class ChromeFeatureList { + newCachedFlag(POWER_SAVING_MODE_BROADCAST_RECEIVER_IN_BACKGROUND, true); + public static final CachedFlag sPriceChangeModule = newCachedFlag(PRICE_CHANGE_MODULE, true); + public static final CachedFlag sProtectRecentlyVisibleTab = +- newCachedFlag(PROTECT_RECENTLY_VISIBLE_TAB, BuildConfig.IS_DESKTOP_ANDROID); ++ newCachedFlag(PROTECT_RECENTLY_VISIBLE_TAB, BuildConfig.IS_DESKTOP_ANDROID_CROMITE); + public static final CachedFlag sReportNotificationContentDetectionData = + newCachedFlag( + REPORT_NOTIFICATION_CONTENT_DETECTION_DATA, diff --git a/chrome/browser/media/router/BUILD.gn b/chrome/browser/media/router/BUILD.gn --- a/chrome/browser/media/router/BUILD.gn +++ b/chrome/browser/media/router/BUILD.gn @@ -1314,6 +1443,18 @@ diff --git a/chrome/browser/media/webrtc/webrtc_event_log_manager.cc b/chrome/br return std::make_unique( std::make_unique( std::make_unique())); +diff --git a/chrome/browser/open_in_app/android/java/src/org/chromium/chrome/browser/open_in_app/OpenInAppUtils.java b/chrome/browser/open_in_app/android/java/src/org/chromium/chrome/browser/open_in_app/OpenInAppUtils.java +--- a/chrome/browser/open_in_app/android/java/src/org/chromium/chrome/browser/open_in_app/OpenInAppUtils.java ++++ b/chrome/browser/open_in_app/android/java/src/org/chromium/chrome/browser/open_in_app/OpenInAppUtils.java +@@ -14,7 +14,7 @@ public class OpenInAppUtils { + + /** Returns whether Open in App is available. */ + public static boolean isOpenInAppAvailable() { +- return ChromeFeatureList.sDesktopAndroidLinkCapturing.isEnabled() && DeviceInfo.isDesktop(); ++ return ChromeFeatureList.sDesktopAndroidLinkCapturing.isEnabled() && DeviceInfo.isDesktopFalse(); + } + + private OpenInAppUtils() {} diff --git a/chrome/browser/policy/policy_value_and_status_aggregator.cc b/chrome/browser/policy/policy_value_and_status_aggregator.cc --- a/chrome/browser/policy/policy_value_and_status_aggregator.cc +++ b/chrome/browser/policy/policy_value_and_status_aggregator.cc @@ -1456,19 +1597,19 @@ diff --git a/chrome/browser/resources/extensions/item_list.css b/chrome/browser/ } #container { -@@ -28,6 +33,12 @@ - padding-top: 14px; +@@ -20,7 +25,12 @@ + + #content-wrapper { + min-width: var(--extensions-card-width); ++ ++ padding: 0px !important; ++ ++ + padding: 24px 60px 64px; ++ } -+ -+#content-wrapper { -+ padding: 0px !important; -+} -+ -+ - .empty-list-message { - color: #6e6e6e; - font-size: 123%; /* Should be 16px when 100% is 13px. */ + #content-wrapper:has(extensions-review-panel), diff --git a/chrome/browser/resources/extensions/toolbar.html.ts b/chrome/browser/resources/extensions/toolbar.html.ts --- a/chrome/browser/resources/extensions/toolbar.html.ts +++ b/chrome/browser/resources/extensions/toolbar.html.ts @@ -1486,6 +1627,27 @@ diff --git a/chrome/browser/resources/extensions/toolbar.html.ts b/chrome/browse

$i18n{toolbarExtensionUpdateEnabled} $i18n{toolbarExtensionUpdateEnabledNeedRestart} +diff --git a/chrome/browser/sessions/session_restore_android.cc b/chrome/browser/sessions/session_restore_android.cc +--- a/chrome/browser/sessions/session_restore_android.cc ++++ b/chrome/browser/sessions/session_restore_android.cc +@@ -23,7 +23,7 @@ + + namespace { + +-#if BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS) ++#if BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS_FALSE) + BrowserWindowInterface::Type BrowserTypeFromWindowType( + sessions::SessionWindow::WindowType type) { + switch (type) { +@@ -109,7 +109,7 @@ void SessionRestore::RestoreForeignSessionWindows( + std::vector::const_iterator begin, + std::vector::const_iterator end, + base::OnceCallback)> callback) { +-#if BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS) ++#if BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS_FALSE) + // The extensions sessions API can restore foreign windows. + size_t window_count = std::distance(begin, end); + // Wait for `window_count` callbacks. diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/ChromeProvidedSharingOptionsProviderBase.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/ChromeProvidedSharingOptionsProviderBase.java --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/ChromeProvidedSharingOptionsProviderBase.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/ChromeProvidedSharingOptionsProviderBase.java @@ -1690,6 +1852,18 @@ diff --git a/chrome/browser/ui/android/desktop_site/java/src/org/chromium/chrome return; } PrefService prefService = UserPrefs.get(profile); +diff --git a/chrome/browser/ui/android/desktop_windowing/java/src/org/chromium/chrome/browser/ui/desktop_windowing/TopControlsLockCoordinator.java b/chrome/browser/ui/android/desktop_windowing/java/src/org/chromium/chrome/browser/ui/desktop_windowing/TopControlsLockCoordinator.java +--- a/chrome/browser/ui/android/desktop_windowing/java/src/org/chromium/chrome/browser/ui/desktop_windowing/TopControlsLockCoordinator.java ++++ b/chrome/browser/ui/android/desktop_windowing/java/src/org/chromium/chrome/browser/ui/desktop_windowing/TopControlsLockCoordinator.java +@@ -100,7 +100,7 @@ public class TopControlsLockCoordinator { + private boolean shouldLockTopControls() { + // Desktop form factor always take priority. + // TODO(crbug.com/450970998): Explore if we can set this for all large tablets. +- if (DeviceInfo.isDesktop()) return true; ++ if (DeviceInfo.isDesktopFalse()) return true; + + // Enable lock in desktop window mode. Only relevant when the device supports it. + if (mDesktopWindowStateManager != null) { diff --git a/chrome/browser/ui/android/extensions/BUILD.gn b/chrome/browser/ui/android/extensions/BUILD.gn --- a/chrome/browser/ui/android/extensions/BUILD.gn +++ b/chrome/browser/ui/android/extensions/BUILD.gn @@ -1760,6 +1934,17 @@ diff --git a/chrome/browser/ui/android/extensions/extension_actions_bridge.h b/c jni_zero::ScopedJavaLocalRef HandleKeyDownEvent( JNIEnv* env, const ui::KeyEventAndroid& key_event); +diff --git a/chrome/browser/ui/android/extensions/extensions_toolbar_android.cc b/chrome/browser/ui/android/extensions/extensions_toolbar_android.cc +--- a/chrome/browser/ui/android/extensions/extensions_toolbar_android.cc ++++ b/chrome/browser/ui/android/extensions/extensions_toolbar_android.cc +@@ -152,6 +152,7 @@ base::android::ScopedJavaLocalRef ExtensionsToolbarAndroid::GetAction( + const ToolbarActionsModel::ActionId& action_id) { + ToolbarActionViewModel* action = + toolbar_view_model_->GetActionModelForId(action_id); ++ if (!action) return nullptr; + return Java_ExtensionAction_Constructor( + env, action_id, base::UTF16ToUTF8(action->GetActionName())); + } diff --git a/chrome/browser/ui/android/extensions/java/res/layout/extensions_menu.xml b/chrome/browser/ui/android/extensions/java/res/layout/extensions_menu.xml --- a/chrome/browser/ui/android/extensions/java/res/layout/extensions_menu.xml +++ b/chrome/browser/ui/android/extensions/java/res/layout/extensions_menu.xml @@ -1841,6 +2026,66 @@ diff --git a/chrome/browser/ui/android/extensions/windowing/internal/BUILD.gn b/ source_set("internal") { sources = [ +diff --git a/chrome/browser/ui/android/extensions/windowing/internal/extension_window_controller_bridge.cc b/chrome/browser/ui/android/extensions/windowing/internal/extension_window_controller_bridge.cc +--- a/chrome/browser/ui/android/extensions/windowing/internal/extension_window_controller_bridge.cc ++++ b/chrome/browser/ui/android/extensions/windowing/internal/extension_window_controller_bridge.cc +@@ -69,12 +69,13 @@ ExtensionWindowControllerBridge::ExtensionWindowControllerBridge( + java_extension_window_controller_bridge, + BrowserWindowInterface* browser_window) + : extension_window_controller_( +- BrowserExtensionWindowController(browser_window)) { ++ std::make_unique(browser_window)) { + java_extension_window_controller_bridge_.Reset( + env, java_extension_window_controller_bridge); + } + + ExtensionWindowControllerBridge::~ExtensionWindowControllerBridge() { ++ extension_window_controller_.reset(); + Java_ExtensionWindowControllerBridgeImpl_clearNativePtr( + AttachCurrentThread(), java_extension_window_controller_bridge_); + } +@@ -84,22 +85,22 @@ void ExtensionWindowControllerBridge::Destroy(JNIEnv* env) { + } + + void ExtensionWindowControllerBridge::OnTaskBoundsChanged(JNIEnv* env) { +- extension_window_controller_.NotifyWindowBoundsChanged(); ++ extension_window_controller_->NotifyWindowBoundsChanged(); + } + + void ExtensionWindowControllerBridge::OnTaskFocusChanged(JNIEnv* env, + bool has_focus) { +- extension_window_controller_.NotifyWindowFocusChanged(has_focus); ++ extension_window_controller_->NotifyWindowFocusChanged(has_focus); + } + + int ExtensionWindowControllerBridge::GetExtensionWindowIdForTesting( + JNIEnv* env) { +- return extension_window_controller_.GetWindowId(); ++ return extension_window_controller_->GetWindowId(); + } + +-const BrowserExtensionWindowController& +-ExtensionWindowControllerBridge::GetExtensionWindowControllerForTesting() { +- return extension_window_controller_; +-} ++// const BrowserExtensionWindowController& ++// ExtensionWindowControllerBridge::GetExtensionWindowControllerForTesting() { ++// return extension_window_controller_; ++// } + + DEFINE_JNI(ExtensionWindowControllerBridgeImpl) +diff --git a/chrome/browser/ui/android/extensions/windowing/internal/extension_window_controller_bridge.h b/chrome/browser/ui/android/extensions/windowing/internal/extension_window_controller_bridge.h +--- a/chrome/browser/ui/android/extensions/windowing/internal/extension_window_controller_bridge.h ++++ b/chrome/browser/ui/android/extensions/windowing/internal/extension_window_controller_bridge.h +@@ -64,7 +64,7 @@ class ExtensionWindowControllerBridge final { + base::android::ScopedJavaGlobalRef + java_extension_window_controller_bridge_; + +- extensions::BrowserExtensionWindowController extension_window_controller_; ++ std::unique_ptr extension_window_controller_; + + raw_ptr + window_controller_list_observer_for_testing_; diff --git a/chrome/browser/ui/android/strings/cromite_android_chrome_strings_grd/Enable-extensions-Android.grdp b/chrome/browser/ui/android/strings/cromite_android_chrome_strings_grd/Enable-extensions-Android.grdp new file mode 100644 --- /dev/null @@ -2466,6 +2711,15 @@ diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn sources += [ # These API tests can't be part of platform_browser_tests because they # run in interactive_ui_tests on Win/Mac/Linux. +@@ -6333,7 +6333,7 @@ template("performance_test_suite_template_base") { + } + args += [ "--chromium-output-directory=@WrappedPath(.)" ] + +- if (is_desktop_android) { ++ if (is_desktop_android_cromite) { + data = [ "//third_party/crossbench-web-tests" ] + } + @@ -8187,7 +8187,7 @@ test("unit_tests") { deps += [ "//chrome/browser/android/extensions:android" ] } @@ -2475,6 +2729,15 @@ diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn deps += [ # Unit test targets for //chrome/browser/ui/browser_window/internal. # +@@ -10039,7 +10039,7 @@ test("unit_tests") { + ] + } + +- if (!is_android || enable_desktop_android_extensions) { ++ if (!is_android || enable_desktop_android_extensions_cromite) { + sources += + [ "../browser/policy/developer_tools_policy_handler_unittest.cc" ] + } diff --git a/chrome/version.gni b/chrome/version.gni --- a/chrome/version.gni +++ b/chrome/version.gni @@ -2693,6 +2956,15 @@ diff --git a/components/policy/core/browser/cloud/user_policy_signin_service_bas diff --git a/components/policy/core/browser/configuration_policy_handler_list.cc b/components/policy/core/browser/configuration_policy_handler_list.cc --- a/components/policy/core/browser/configuration_policy_handler_list.cc +++ b/components/policy/core/browser/configuration_policy_handler_list.cc +@@ -101,7 +101,7 @@ void ConfigurationPolicyHandlerList::PrepareForDisplaying( + + bool ConfigurationPolicyHandlerList::IsBlockedDesktopAndroidPolicy( + const std::string& policy_name) const { +-#if BUILDFLAG(IS_DESKTOP_ANDROID) ++#if BUILDFLAG(IS_DESKTOP_ANDROID_FALSE) + // The allowlist is not used if kDesktopAndroidPolicy is off. So that all + // policies are allowed by default without Finch config. + if (!base::FeatureList::IsEnabled(features::kDesktopAndroidPolicy)) { @@ -173,7 +173,7 @@ bool ConfigurationPolicyHandlerList::IsBlockedFuturePolicy( const base::flat_set& future_policies_allowed, const PolicyDetails& policy_details, @@ -3465,6 +3737,15 @@ diff --git a/ui/android/javatests/src/org/chromium/ui/test/util/UiRestriction.ja } return sIsDesktop; } +@@ -50,7 +50,7 @@ public final class UiRestriction { + if (sIsDesktopFreeform == null) { + var packageManager = ContextUtils.getApplicationContext().getPackageManager(); + sIsDesktopFreeform = +- BuildConfig.IS_DESKTOP_ANDROID ++ BuildConfig.IS_DESKTOP_ANDROID_FALSE + && packageManager.hasSystemFeature(PackageManager.FEATURE_PC); + } + diff --git a/ui/base/accelerators/command.cc b/ui/base/accelerators/command.cc --- a/ui/base/accelerators/command.cc +++ b/ui/base/accelerators/command.cc @@ -3549,19 +3830,16 @@ diff --git a/ui/webui/resources/cr_elements/BUILD.gn b/ui/webui/resources/cr_ele diff --git a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.css b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.css --- a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.css +++ b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.css -@@ -126,6 +126,12 @@ picture { +@@ -123,6 +123,9 @@ picture { + } + + #menuButton ~ h1 { ++ ++ font-size: 15px !important; ++ margin-inline-start: 0; } -+ -+#menuButton ~ h1 { -+ font-size: 15px !important; -+} -+ -+ - :host([always-show-logo]) picture, - :host(:not([narrow])) picture { - display: initial; diff --git a/ui/webui/resources/css/BUILD.gn b/ui/webui/resources/css/BUILD.gn --- a/ui/webui/resources/css/BUILD.gn +++ b/ui/webui/resources/css/BUILD.gn