1543 lines
75 KiB
Diff
1543 lines
75 KiB
Diff
From: uazo <uazo@users.noreply.github.com>
|
|
Date: Thu, 20 Nov 2025 12:53:28 +0000
|
|
Subject: Enable extensions in incognito
|
|
|
|
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 | 5 +
|
|
.../chrome/browser/app/ChromeActivity.java | 42 +++++-
|
|
.../CustomTabIntentDataProvider.java | 3 +
|
|
.../browser/tabmodel/TabModelJniBridge.java | 3 +-
|
|
.../tabmodel/TabModelSelectorBase.java | 14 ++
|
|
.../browser/toolbar/ToolbarManager.java | 8 +-
|
|
.../developer_private_functions.cc | 3 +-
|
|
.../browser/extensions/extension_tab_util.cc | 2 +-
|
|
.../tabmodel/IncognitoTabModelImpl.java | 10 +-
|
|
.../tabmodel/IncognitoTabModelObserver.java | 3 +
|
|
.../extensions/extension_actions_bridge.cc | 23 ++-
|
|
.../extensions/extension_actions_bridge.h | 4 +-
|
|
.../ui/extensions/ExtensionActionsBridge.java | 62 +++++++-
|
|
.../ui/extensions/ExtensionsMenuBridge.java | 103 ++++++++++---
|
|
.../extensions/ExtensionsToolbarBridge.java | 137 ++++++++++++------
|
|
.../ExtensionActionListCoordinator.java | 12 +-
|
|
.../ExtensionActionListMediator.java | 24 +--
|
|
.../extensions/ExtensionsMenuCoordinator.java | 14 +-
|
|
.../extensions/ExtensionsMenuMediator.java | 12 +-
|
|
.../ExtensionsToolbarCoordinator.java | 10 +-
|
|
.../ExtensionsToolbarCoordinatorImpl.java | 21 ++-
|
|
.../browser/toolbar/top/ToolbarPhone.java | 16 ++
|
|
.../browser_window/ChromeAndroidTaskImpl.java | 18 ++-
|
|
.../ChromeAndroidTaskFeature.java | 2 +-
|
|
components/tabs/impl/tab_collection.cc | 16 ++
|
|
components/tabs/impl/tab_strip_collection.cc | 4 +-
|
|
26 files changed, 449 insertions(+), 122 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
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
|
|
@@ -125,6 +125,7 @@ import org.chromium.chrome.browser.contextmenu.ChromeContextMenuPopulator;
|
|
import org.chromium.chrome.browser.contextmenu.ChromeContextMenuPopulatorFactory;
|
|
import org.chromium.chrome.browser.cookies.CookiesFetcher;
|
|
import org.chromium.chrome.browser.crypto.CipherFactory;
|
|
+import org.chromium.chrome.browser.customtabs.CustomTabActivity;
|
|
import org.chromium.chrome.browser.data_sharing.DataSharingIntentUtils;
|
|
import org.chromium.chrome.browser.data_sharing.DataSharingTabGroupUtils;
|
|
import org.chromium.chrome.browser.data_sharing.DataSharingTabManager;
|
|
@@ -4165,6 +4166,10 @@ public class ChromeTabbedActivity extends ChromeActivity implements PreAttachInt
|
|
coordinator.showExtensionsMenu();
|
|
RecordUserAction.record("MobileMenuExtensionsMenu");
|
|
} else if (id == R.id.manage_extensions_menu_id) {
|
|
+ if (getCurrentTabModel().isIncognito()) {
|
|
+ CustomTabActivity.showInfoPage(this, UrlConstants.CHROME_EXTENSIONS_URL);
|
|
+ return true;
|
|
+ }
|
|
LoadUrlParams params =
|
|
new LoadUrlParams(
|
|
UrlConstants.CHROME_EXTENSIONS_URL, PageTransition.AUTO_TOPLEVEL);
|
|
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
|
|
@@ -190,6 +190,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;
|
|
@@ -222,6 +223,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;
|
|
@@ -1136,16 +1140,46 @@ public abstract class ChromeActivity extends AsyncInitializationActivity
|
|
// TODO(crbug.com/491791326): Handle multiple profiles for mobile.
|
|
Profile profile = tabModelSelector.getCurrentModel().getProfile();
|
|
assert profile != null;
|
|
- chromeAndroidTask.addFeature(
|
|
- new ChromeAndroidTaskFeatureKey(
|
|
- ExtensionWindowControllerBridge.class, profile, activityWindowAndroid),
|
|
- ExtensionWindowControllerBridgeFactory::create);
|
|
+ addFeatures(chromeAndroidTask, profile);
|
|
|
|
// 5. Make the ChromeAndroidTask available via OneshotSupplier.
|
|
mChromeAndroidTaskSupplier.set(chromeAndroidTask);
|
|
+
|
|
+ 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() {
|
|
+ }
|
|
+ });
|
|
}
|
|
}
|
|
|
|
+ private void addFeatures(ChromeAndroidTask task, Profile profile) {
|
|
+ task.addFeature(
|
|
+ new ChromeAndroidTaskFeatureKey(
|
|
+ ExtensionWindowControllerBridge.class, profile, getWindowAndroid()),
|
|
+ ExtensionWindowControllerBridgeFactory::create);
|
|
+
|
|
+ task.addFeature(
|
|
+ new ChromeAndroidTaskFeatureKey(ExtensionsToolbarBridge.class, profile, getWindowAndroid()),
|
|
+ () -> ExtensionsToolbarBridge.create(task, profile));
|
|
+
|
|
+ task.addFeature(
|
|
+ new ChromeAndroidTaskFeatureKey(ExtensionActionsBridge.class, profile, getWindowAndroid()),
|
|
+ () -> ExtensionActionsBridge.create(task, profile));
|
|
+
|
|
+ task.addFeature(
|
|
+ new ChromeAndroidTaskFeatureKey(ExtensionsMenuBridge.class, profile, getWindowAndroid()),
|
|
+ () -> ExtensionsMenuBridge.create(task, profile));
|
|
+ }
|
|
+
|
|
/** Returns an {@link OneshotSupplier} for {@link ChromeAndroidTask}. */
|
|
protected final OneshotSupplier<ChromeAndroidTask> getChromeAndroidTaskSupplier() {
|
|
return mChromeAndroidTaskSupplier;
|
|
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
|
|
@@ -349,6 +349,7 @@ public class CustomTabIntentDataProvider extends BrowserServicesIntentDataProvid
|
|
|
|
private final boolean mEnableUrlBarHiding;
|
|
private boolean mInteractWithBackground;
|
|
+ private boolean mIsExtension = false;
|
|
private List<CustomButtonParams> mCustomButtonParams;
|
|
private @Nullable Drawable mCloseButtonIcon;
|
|
private final boolean mIsCloseButtonEnabled;
|
|
@@ -754,6 +755,7 @@ public class CustomTabIntentDataProvider extends BrowserServicesIntentDataProvid
|
|
mSideSheetRoundedCornersPosition =
|
|
getActivitySideSheetRoundedCornersPositionFromIntent(intent);
|
|
|
|
+ mIsExtension = getUrlToLoad().startsWith(UrlConstants.CHROME_EXTENSIONS_URL);
|
|
logCustomTabFeatures(intent, colorScheme);
|
|
String packageName = getClientPackageNameFromSessionOrCallingActivity(mIntent, mSession);
|
|
RecordHistogram.recordBooleanHistogram(
|
|
@@ -1408,6 +1410,7 @@ public class CustomTabIntentDataProvider extends BrowserServicesIntentDataProvid
|
|
|
|
@Override
|
|
public @CustomTabProfileType int getCustomTabMode() {
|
|
+ if (mIsExtension) return CustomTabProfileType.REGULAR;
|
|
return AlwaysIncognitoLinkInterceptor.isAlwaysIncognito()
|
|
? CustomTabProfileType.INCOGNITO
|
|
: (ChromeFeatureList.sMayLaunchurlUsesSeparateStoragePartition.isEnabled()
|
|
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
|
|
@@ -145,8 +145,7 @@ public abstract class TabModelJniBridge implements TabModelInternal {
|
|
|
|
@Override
|
|
public void dissociateWithBrowserWindow() {
|
|
- assert mNativeAndroidBrowserWindow != 0;
|
|
-
|
|
+ if (mNativeTabModelJniBridge == 0 || mNativeAndroidBrowserWindow == 0) return;
|
|
TabModelJniBridgeJni.get().dissociateWithBrowserWindow(mNativeTabModelJniBridge);
|
|
mNativeAndroidBrowserWindow = 0;
|
|
}
|
|
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,20 @@ public abstract class TabModelSelectorBase
|
|
}
|
|
}
|
|
|
|
+ @Override
|
|
+ public void onAssociateWithBrowserWindow() {
|
|
+ for (IncognitoTabModelObserver observer : mIncognitoObservers) {
|
|
+ observer.onAssociateWithBrowserWindow();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void didDestroyed() {
|
|
+ for (IncognitoTabModelObserver observer : mIncognitoObservers) {
|
|
+ observer.didDestroyed();
|
|
+ }
|
|
+ }
|
|
+
|
|
@Override
|
|
public void didBecomeEmpty() {
|
|
for (IncognitoTabModelObserver observer : mIncognitoObservers) {
|
|
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
|
|
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
|
|
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
|
|
@@ -80,6 +80,7 @@ import org.chromium.chrome.browser.compositor.layouts.Layout;
|
|
import org.chromium.chrome.browser.compositor.layouts.LayoutManagerImpl;
|
|
import org.chromium.chrome.browser.compositor.overlay_panel.OverlayPanelManager.OverlayPanelManagerObserver;
|
|
import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutHelperManager;
|
|
+import org.chromium.chrome.browser.customtabs.CustomTabActivity;
|
|
import org.chromium.chrome.browser.customtabs.features.toolbar.CustomTabToolbar;
|
|
import org.chromium.chrome.browser.data_sharing.DataSharingTabManager;
|
|
import org.chromium.chrome.browser.dom_distiller.DomDistillerTabUtils;
|
|
@@ -2524,11 +2525,14 @@ public class ToolbarManager
|
|
task,
|
|
assertNonNull(mTabModelSelector.getCurrentModel().getProfile()),
|
|
mActivityTabProvider.asObservable(),
|
|
- mTabCreatorManager.getTabCreator(false),
|
|
+ mTabCreatorManager.getTabCreator(AlwaysIncognitoLinkInterceptor.isAlwaysIncognito()),
|
|
getBrowsingModeThemeColorProvider(),
|
|
mToolbarLayout,
|
|
contextMenuPopulatorFactory,
|
|
- selectionDropdownMenuDelegate);
|
|
+ selectionDropdownMenuDelegate,
|
|
+ AlwaysIncognitoLinkInterceptor.isAlwaysIncognito()
|
|
+ ? (url) -> CustomTabActivity.showInfoPage(mActivity, url)
|
|
+ : null);
|
|
if (mExtensionsToolbarCoordinator != null) {
|
|
mToolbar.setExtensionsToolbarCoordinator(mExtensionsToolbarCoordinator);
|
|
}
|
|
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
|
|
@@ -1756,7 +1756,8 @@ DeveloperPrivateDismissSafetyHubExtensionsMenuNotificationFunction::Run() {
|
|
}
|
|
|
|
Profile* profile = Profile::FromBrowserContext(browser_context());
|
|
- SafetyHubMenuNotificationServiceFactory::GetForProfile(profile)
|
|
+ if (auto* menu_notification_service_factory = SafetyHubMenuNotificationServiceFactory::GetForProfile(profile))
|
|
+ menu_notification_service_factory
|
|
->DismissActiveNotificationOfModule(
|
|
safety_hub::SafetyHubModuleType::EXTENSIONS);
|
|
return RespondNow(NoArguments());
|
|
diff --git a/chrome/browser/extensions/extension_tab_util.cc b/chrome/browser/extensions/extension_tab_util.cc
|
|
--- a/chrome/browser/extensions/extension_tab_util.cc
|
|
+++ b/chrome/browser/extensions/extension_tab_util.cc
|
|
@@ -1150,7 +1150,7 @@ bool ExtensionTabUtil::OpenOptionsPageFromWebContents(
|
|
if (!url) {
|
|
return false;
|
|
}
|
|
- const bool open_in_tab = ShouldOpenInTab(extension);
|
|
+ const bool open_in_tab = false; //ShouldOpenInTab(extension);
|
|
BrowserWindowInterface* browser =
|
|
browser_window_util::GetBrowserForTabContents(*web_contents);
|
|
CHECK(browser);
|
|
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImpl.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImpl.java
|
|
--- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImpl.java
|
|
+++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImpl.java
|
|
@@ -155,7 +155,7 @@ class IncognitoTabModelImpl implements IncognitoTabModelInternal {
|
|
}
|
|
|
|
for (IncognitoTabModelObserver observer : mIncognitoObservers) {
|
|
- observer.didBecomeEmpty();
|
|
+ observer.didDestroyed();
|
|
}
|
|
|
|
mDelegateModel
|
|
@@ -166,6 +166,10 @@ class IncognitoTabModelImpl implements IncognitoTabModelInternal {
|
|
mCurrentTabSupplier.set(null);
|
|
mTabCountSupplier.set(0);
|
|
|
|
+ for (IncognitoTabModelObserver observer : mIncognitoObservers) {
|
|
+ observer.didBecomeEmpty();
|
|
+ }
|
|
+
|
|
mDelegateModel = EmptyTabModel.getInstance(true);
|
|
for (Callback<TabModelInternal> delegateModelObserver : mDelegateModelObservers) {
|
|
delegateModelObserver.onResult(mDelegateModel);
|
|
@@ -203,6 +207,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,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
|
|
--- a/chrome/browser/ui/android/extensions/extension_actions_bridge.cc
|
|
+++ b/chrome/browser/ui/android/extensions/extension_actions_bridge.cc
|
|
@@ -12,6 +12,8 @@
|
|
#include "base/task/thread_pool.h"
|
|
#include "chrome/browser/extensions/extension_management.h"
|
|
#include "chrome/browser/profiles/profile.h"
|
|
+#include "extensions/browser/process_manager.h"
|
|
+#include "extensions/browser/process_manager_factory.h"
|
|
#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
|
|
#include "ui/events/android/key_event_android.h"
|
|
|
|
@@ -23,10 +25,9 @@
|
|
namespace extensions {
|
|
|
|
ExtensionActionsBridge::ExtensionActionsBridge(
|
|
- BrowserWindowInterface* browser,
|
|
+ Profile* profile,
|
|
const base::android::JavaRef<jobject>& java_object)
|
|
- : browser_(browser),
|
|
- profile_(browser->GetProfile()),
|
|
+ : profile_(profile),
|
|
java_object_(java_object) {}
|
|
|
|
ExtensionActionsBridge::~ExtensionActionsBridge() = default;
|
|
@@ -51,6 +52,16 @@ void ExtensionActionsBridge::ClearExtensionData(JNIEnv* env) {
|
|
install_directory, install_updacked_directory));
|
|
}
|
|
|
|
+void ExtensionActionsBridge::CloseBackgroundHosts(JNIEnv* env) {
|
|
+ extensions::ProcessManager* manager =
|
|
+ extensions::ProcessManagerFactory::GetForBrowserContextIfExists(profile_);
|
|
+ if (manager) {
|
|
+ manager->CloseBackgroundHosts();
|
|
+ ProcessManager::Get(profile_->GetOriginalProfile())
|
|
+ ->MaybeCreateStartupBackgroundHosts();
|
|
+ }
|
|
+}
|
|
+
|
|
void ExtensionActionsBridge::Destroy(JNIEnv* env) {
|
|
delete this;
|
|
}
|
|
@@ -58,11 +69,9 @@ void ExtensionActionsBridge::Destroy(JNIEnv* env) {
|
|
static int64_t JNI_ExtensionActionsBridge_Init(
|
|
JNIEnv* env,
|
|
const base::android::JavaRef<jobject>& java_object,
|
|
- int64_t j_browser_window_interface) {
|
|
- BrowserWindowInterface* browser =
|
|
- reinterpret_cast<BrowserWindowInterface*>(j_browser_window_interface);
|
|
+ Profile* profile) {
|
|
return reinterpret_cast<int64_t>(
|
|
- new ExtensionActionsBridge(browser, java_object));
|
|
+ new ExtensionActionsBridge(profile, java_object));
|
|
}
|
|
|
|
static bool JNI_ExtensionActionsBridge_ExtensionsEnabled(JNIEnv* env,
|
|
diff --git a/chrome/browser/ui/android/extensions/extension_actions_bridge.h b/chrome/browser/ui/android/extensions/extension_actions_bridge.h
|
|
--- a/chrome/browser/ui/android/extensions/extension_actions_bridge.h
|
|
+++ b/chrome/browser/ui/android/extensions/extension_actions_bridge.h
|
|
@@ -19,7 +19,7 @@ namespace extensions {
|
|
// This bridge is created and owned by Java UI code.
|
|
class ExtensionActionsBridge {
|
|
public:
|
|
- ExtensionActionsBridge(BrowserWindowInterface* browser,
|
|
+ ExtensionActionsBridge(Profile* profile,
|
|
const base::android::JavaRef<jobject>& java_object);
|
|
ExtensionActionsBridge(const ExtensionActionsBridge&) = delete;
|
|
ExtensionActionsBridge& operator=(const ExtensionActionsBridge&) = delete;
|
|
@@ -27,10 +27,10 @@ class ExtensionActionsBridge {
|
|
|
|
// JNI implementations.
|
|
void ClearExtensionData(JNIEnv* env);
|
|
+ void CloseBackgroundHosts(JNIEnv* env);
|
|
void Destroy(JNIEnv* env);
|
|
|
|
private:
|
|
- const raw_ptr<BrowserWindowInterface> browser_;
|
|
const raw_ptr<Profile> profile_;
|
|
const base::android::ScopedJavaGlobalRef<jobject> java_object_;
|
|
};
|
|
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
|
|
@@ -15,21 +15,64 @@ 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 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 ExtensionActionsBridge implements Destroyable {
|
|
+public class ExtensionActionsBridge implements ChromeAndroidTaskFeature {
|
|
private final @Nullable LifetimeAssert mLifetimeAssert = LifetimeAssert.create(this);
|
|
private long mNativeExtensionActionsBridge;
|
|
|
|
- public ExtensionActionsBridge(ChromeAndroidTask task, Profile profile) {
|
|
+ private static ExtensionActionsBridge currentExtensionActionsBridge;
|
|
+ private final Profile mProfile;
|
|
+ private final ChromeAndroidTask mTask;
|
|
+
|
|
+ private ExtensionActionsBridge(ChromeAndroidTask task, Profile profile) {
|
|
+ mTask = task;
|
|
+ mProfile = profile;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void onAddedToTask(long nativeBrowserWindowPtr) {
|
|
mNativeExtensionActionsBridge =
|
|
ExtensionActionsBridgeJni.get()
|
|
- .init(this, task.getOrCreateNativeBrowserWindowPtr(profile));
|
|
+ .init(this, mProfile);
|
|
}
|
|
|
|
@Override
|
|
- public void destroy() {
|
|
+ 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);
|
|
+ }
|
|
+
|
|
+ void destroy() {
|
|
+ closeBackgroundHosts();
|
|
assert mNativeExtensionActionsBridge != 0;
|
|
ExtensionActionsBridgeJni.get().destroy(mNativeExtensionActionsBridge);
|
|
mNativeExtensionActionsBridge = 0;
|
|
@@ -46,17 +89,24 @@ public class ExtensionActionsBridge implements Destroyable {
|
|
}
|
|
|
|
public void clearExtensionData() {
|
|
- ExtensionActionsBridgeJni.get().clearExtensionData(mNativeExtensionActionsBridge);
|
|
+ ExtensionActionsBridgeJni.get().clearExtensionData(Instance().mNativeExtensionActionsBridge);
|
|
+ }
|
|
+
|
|
+ private void closeBackgroundHosts() {
|
|
+ if (mProfile.isIncognitoBranded())
|
|
+ ExtensionActionsBridgeJni.get().closeBackgroundHosts(mNativeExtensionActionsBridge);
|
|
}
|
|
|
|
@NativeMethods
|
|
public interface Natives {
|
|
boolean extensionsEnabled(@JniType("Profile*") Profile profile);
|
|
|
|
- long init(ExtensionActionsBridge bridge, long browserWindowInterfacePtr);
|
|
+ long init(ExtensionActionsBridge bridge, @JniType("Profile*") Profile profile);
|
|
|
|
void clearExtensionData(long nativeExtensionActionsBridge);
|
|
|
|
+ void closeBackgroundHosts(long nativeExtensionActionsBridge);
|
|
+
|
|
void destroy(long nativeExtensionActionsBridge);
|
|
}
|
|
}
|
|
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
|
|
@@ -20,24 +20,76 @@ import org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTask;
|
|
|
|
import java.util.List;
|
|
|
|
+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<ChromeAndroidTask, Observer> mObservers = new ArrayMap<>();
|
|
+ private final ChromeAndroidTask mTask;
|
|
+ private final Profile mProfile;
|
|
+
|
|
+ private ExtensionsMenuBridge(ChromeAndroidTask task, Profile profile) {
|
|
+ mObserver = null;
|
|
+ mProfile = profile;
|
|
+ mTask = task;
|
|
+ }
|
|
|
|
- public ExtensionsMenuBridge(ChromeAndroidTask task, Profile profile, Observer observer) {
|
|
- mObserver = observer;
|
|
+ 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;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void onAddedToTask(long nativeBrowserWindowPtr) {
|
|
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;
|
|
@@ -47,12 +99,12 @@ public class ExtensionsMenuBridge implements Destroyable {
|
|
/** Returns the icon for the given extension index from native. */
|
|
public @Nullable Bitmap getActionIcon(int actionIndex) {
|
|
return ExtensionsMenuBridgeJni.get()
|
|
- .getActionIcon(mNativeExtensionsMenuDelegateAndroid, actionIndex);
|
|
+ .getActionIcon(Instance().mNativeExtensionsMenuDelegateAndroid, actionIndex);
|
|
}
|
|
|
|
/** Returns the list of menu entries with their states from native. */
|
|
public List<ExtensionsMenuTypes.MenuEntryState> getMenuEntries() {
|
|
- return ExtensionsMenuBridgeJni.get().getMenuEntries(mNativeExtensionsMenuDelegateAndroid);
|
|
+ return ExtensionsMenuBridgeJni.get().getMenuEntries(Instance().mNativeExtensionsMenuDelegateAndroid);
|
|
}
|
|
|
|
/**
|
|
@@ -62,12 +114,12 @@ public class ExtensionsMenuBridge implements Destroyable {
|
|
*/
|
|
public ExtensionsMenuTypes.MenuEntryState getMenuEntry(int actionIndex) {
|
|
return ExtensionsMenuBridgeJni.get()
|
|
- .getMenuEntry(mNativeExtensionsMenuDelegateAndroid, actionIndex);
|
|
+ .getMenuEntry(Instance().mNativeExtensionsMenuDelegateAndroid, actionIndex);
|
|
}
|
|
|
|
/** Returns the site settings state from native. */
|
|
public ExtensionsMenuTypes.SiteSettingsState getSiteSettingsState() {
|
|
- return ExtensionsMenuBridgeJni.get().getSiteSettings(mNativeExtensionsMenuDelegateAndroid);
|
|
+ return ExtensionsMenuBridgeJni.get().getSiteSettings(Instance().mNativeExtensionsMenuDelegateAndroid);
|
|
}
|
|
|
|
/**
|
|
@@ -118,12 +170,12 @@ public class ExtensionsMenuBridge implements Destroyable {
|
|
/** Called when the reload page button is clicked. */
|
|
public void onReloadPageButtonClicked() {
|
|
ExtensionsMenuBridgeJni.get()
|
|
- .onReloadPageButtonClicked(mNativeExtensionsMenuDelegateAndroid);
|
|
+ .onReloadPageButtonClicked(Instance().mNativeExtensionsMenuDelegateAndroid);
|
|
}
|
|
|
|
/** Returns whether the native menu model is ready. */
|
|
public boolean isReady() {
|
|
- return ExtensionsMenuBridgeJni.get().isReady(mNativeExtensionsMenuDelegateAndroid);
|
|
+ return ExtensionsMenuBridgeJni.get().isReady(Instance().mNativeExtensionsMenuDelegateAndroid);
|
|
}
|
|
|
|
/**
|
|
@@ -133,7 +185,10 @@ public class ExtensionsMenuBridge implements Destroyable {
|
|
*/
|
|
@CalledByNative
|
|
public void onActionAdded(int actionIndex) {
|
|
- mObserver.onActionAdded(actionIndex);
|
|
+ if (Instance().mNativeExtensionsMenuDelegateAndroid != mNativeExtensionsMenuDelegateAndroid) return;
|
|
+ if (Instance().mObserver != null) {
|
|
+ Instance().mObserver.onActionAdded(actionIndex);
|
|
+ }
|
|
}
|
|
|
|
/**
|
|
@@ -144,7 +199,10 @@ public class ExtensionsMenuBridge implements Destroyable {
|
|
*/
|
|
@CalledByNative
|
|
public void onActionIconUpdated(int actionIndex) {
|
|
- mObserver.onActionIconUpdated(actionIndex);
|
|
+ if (Instance().mNativeExtensionsMenuDelegateAndroid != mNativeExtensionsMenuDelegateAndroid) return;
|
|
+ if (Instance().mObserver != null) {
|
|
+ Instance().mObserver.onActionIconUpdated(actionIndex);
|
|
+ }
|
|
}
|
|
|
|
/**
|
|
@@ -155,7 +213,10 @@ public class ExtensionsMenuBridge implements Destroyable {
|
|
*/
|
|
@CalledByNative
|
|
public void onActionRemoved(int actionIndex) {
|
|
- mObserver.onActionRemoved(actionIndex);
|
|
+ if (Instance().mNativeExtensionsMenuDelegateAndroid != mNativeExtensionsMenuDelegateAndroid) return;
|
|
+ if (Instance().mObserver != null) {
|
|
+ Instance().mObserver.onActionRemoved(actionIndex);
|
|
+ }
|
|
}
|
|
|
|
/**
|
|
@@ -166,7 +227,10 @@ public class ExtensionsMenuBridge implements Destroyable {
|
|
*/
|
|
@CalledByNative
|
|
public void onActionUpdated(int actionIndex) {
|
|
- mObserver.onActionUpdated(actionIndex);
|
|
+ if (Instance().mNativeExtensionsMenuDelegateAndroid != mNativeExtensionsMenuDelegateAndroid) return;
|
|
+ if (Instance().mObserver != null) {
|
|
+ Instance().mObserver.onActionUpdated(actionIndex);
|
|
+ }
|
|
}
|
|
|
|
/**
|
|
@@ -175,13 +239,14 @@ public class ExtensionsMenuBridge implements Destroyable {
|
|
*/
|
|
@CalledByNative
|
|
public void onReady() {
|
|
- mObserver.onReady();
|
|
+ //Instance().mObserver.onReady();
|
|
}
|
|
|
|
@CalledByNative
|
|
private void onModelChanged() {
|
|
- if (mObserver != null) {
|
|
- mObserver.onModelChanged();
|
|
+ if (Instance().mNativeExtensionsMenuDelegateAndroid != mNativeExtensionsMenuDelegateAndroid) return;
|
|
+ if (Instance().mObserver != null) {
|
|
+ Instance().mObserver.onModelChanged();
|
|
}
|
|
}
|
|
|
|
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
|
|
@@ -27,10 +27,17 @@ import org.chromium.content_public.browser.WebContents;
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
|
|
+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 {
|
|
// TODO(crbug.com/423483658): Consider moving ExtensionsMenuButtonState and related types
|
|
// (e.g., RequestAccessButtonParams) into a new ExtensionControls.java file.
|
|
@IntDef({
|
|
@@ -48,21 +55,61 @@ public class ExtensionsToolbarBridge implements Destroyable {
|
|
private final @Nullable LifetimeAssert mLifetimeAssert = LifetimeAssert.create(this);
|
|
private long mNativeExtensionsToolbarAndroid;
|
|
private final ObserverList<Observer> mObservers = new ObserverList<>();
|
|
- private final Profile mProfile;
|
|
+ private Profile mProfile;
|
|
|
|
// The delegate is set via a setter because of a bidirectional dependency
|
|
// with {@code ExtensionActionListMediator}.
|
|
private @Nullable Delegate mDelegate;
|
|
|
|
- public ExtensionsToolbarBridge(ChromeAndroidTask task, Profile profile) {
|
|
- mProfile = profile;
|
|
+ private final ChromeAndroidTask mTask;
|
|
+
|
|
+ private static ExtensionsToolbarBridge toolbarBridgeInstance;
|
|
+ private final Map<ChromeAndroidTask, Delegate> mDelegates = new ArrayMap<>();
|
|
+
|
|
+ @Override
|
|
+ public void onAddedToTask(long nativeBrowserWindowPtr) {
|
|
mNativeExtensionsToolbarAndroid =
|
|
ExtensionsToolbarBridgeJni.get()
|
|
- .init(this, task.getOrCreateNativeBrowserWindowPtr(profile));
|
|
+ .init(this, mTask.getOrCreateNativeBrowserWindowPtr(mProfile));
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void onFeatureRemoved() {
|
|
+ //Instance().mDelegates.remove(mTask);
|
|
+ destroy();
|
|
}
|
|
|
|
@Override
|
|
- public void destroy() {
|
|
+ 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);
|
|
+ Instance().mProfile = mProfile;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ 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;
|
|
@@ -70,27 +117,30 @@ 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) {
|
|
+ if (delegate == null) return;
|
|
+ Instance().mDelegates.put(task, delegate);
|
|
+ Instance().mDelegate = delegate;
|
|
}
|
|
|
|
@Nullable
|
|
public ExtensionAction getAction(String actionId, @Nullable WebContents webContents) {
|
|
- if (mProfile.shutdownStarted()) {
|
|
+ assert Instance().mNativeExtensionsToolbarAndroid != 0;
|
|
+ if (Instance().mProfile.shutdownStarted()) {
|
|
// TODO(crbug.com/459079170): This is to prevent tests from breaking. {@code
|
|
// ExtensionsToolbarCoordinatorImpl} should ideally be destroyed following {@code
|
|
// ChromeAndroidTask}'s destruction, and it is currently being worked on.
|
|
return null;
|
|
}
|
|
return ExtensionsToolbarBridgeJni.get()
|
|
- .getAction(mNativeExtensionsToolbarAndroid, actionId, webContents);
|
|
+ .getAction(Instance().mNativeExtensionsToolbarAndroid, actionId, webContents);
|
|
}
|
|
|
|
@Nullable
|
|
@@ -106,9 +156,10 @@ public class ExtensionsToolbarBridge implements Destroyable {
|
|
// ChromeAndroidTask}'s destruction, and it is currently being worked on.
|
|
return null;
|
|
}
|
|
+ assert Instance().mNativeExtensionsToolbarAndroid != 0;
|
|
return ExtensionsToolbarBridgeJni.get()
|
|
.getIcon(
|
|
- mNativeExtensionsToolbarAndroid,
|
|
+ Instance().mNativeExtensionsToolbarAndroid,
|
|
actionId,
|
|
webContents,
|
|
canvasWidthDp,
|
|
@@ -127,52 +178,52 @@ public class ExtensionsToolbarBridge implements Destroyable {
|
|
}
|
|
|
|
public String[] getPinnedActionIds() {
|
|
- if (mProfile.shutdownStarted()) {
|
|
+ if (Instance().mProfile.shutdownStarted()) {
|
|
// TODO(crbug.com/459079170): This is to prevent tests from breaking. {@code
|
|
// ExtensionsToolbarCoordinatorImpl} should ideally be destroyed following {@code
|
|
// ChromeAndroidTask}'s destruction, and it is currently being worked on.
|
|
return new String[0];
|
|
}
|
|
- return ExtensionsToolbarBridgeJni.get().getPinnedActionIds(mNativeExtensionsToolbarAndroid);
|
|
+ return ExtensionsToolbarBridgeJni.get().getPinnedActionIds(Instance().mNativeExtensionsToolbarAndroid);
|
|
}
|
|
|
|
public boolean isActionDraggable(String actionId) {
|
|
- if (mProfile.shutdownStarted()) {
|
|
+ if (Instance().mProfile.shutdownStarted()) {
|
|
// TODO(crbug.com/459079170): This is to prevent tests from breaking. {@code
|
|
// ExtensionsToolbarCoordinatorImpl} should ideally be destroyed following {@code
|
|
// ChromeAndroidTask}'s destruction, and it is currently being worked on.
|
|
return false;
|
|
}
|
|
return ExtensionsToolbarBridgeJni.get()
|
|
- .isActionDraggable(mNativeExtensionsToolbarAndroid, actionId);
|
|
+ .isActionDraggable(Instance().mNativeExtensionsToolbarAndroid, actionId);
|
|
}
|
|
|
|
public void executeUserAction(String actionId, @InvocationSource int source) {
|
|
- if (mProfile.shutdownStarted()) {
|
|
+ if (Instance().mProfile.shutdownStarted()) {
|
|
// TODO(crbug.com/459079170): This is to prevent tests from breaking. {@code
|
|
// ExtensionsToolbarCoordinatorImpl} should ideally be destroyed following {@code
|
|
// ChromeAndroidTask}'s destruction, and it is currently being worked on.
|
|
return;
|
|
}
|
|
ExtensionsToolbarBridgeJni.get()
|
|
- .executeUserAction(mNativeExtensionsToolbarAndroid, actionId, source);
|
|
+ .executeUserAction(Instance().mNativeExtensionsToolbarAndroid, actionId, source);
|
|
}
|
|
|
|
public void movePinnedAction(String actionId, int targetIndex) {
|
|
- if (mProfile.shutdownStarted()) {
|
|
+ if (Instance().mProfile.shutdownStarted()) {
|
|
// TODO(crbug.com/459079170): This is to prevent tests from breaking. {@code
|
|
// ExtensionsToolbarCoordinatorImpl} should ideally be destroyed following {@code
|
|
// ChromeAndroidTask}'s destruction, and it is currently being worked on.
|
|
return;
|
|
}
|
|
ExtensionsToolbarBridgeJni.get()
|
|
- .movePinnedAction(mNativeExtensionsToolbarAndroid, actionId, targetIndex);
|
|
+ .movePinnedAction(Instance().mNativeExtensionsToolbarAndroid, actionId, targetIndex);
|
|
}
|
|
|
|
public @ExtensionsMenuButtonState int getExtensionsMenuButtonState(WebContents webContents) {
|
|
- assert mNativeExtensionsToolbarAndroid != 0;
|
|
+ assert Instance().mNativeExtensionsToolbarAndroid != 0;
|
|
return ExtensionsToolbarBridgeJni.get()
|
|
- .getExtensionsMenuButtonState(mNativeExtensionsToolbarAndroid, webContents);
|
|
+ .getExtensionsMenuButtonState(Instance().mNativeExtensionsToolbarAndroid, webContents);
|
|
}
|
|
|
|
public void onRequestAccessButtonClicked(WebContents webContents) {
|
|
@@ -184,10 +235,10 @@ public class ExtensionsToolbarBridge implements Destroyable {
|
|
}
|
|
|
|
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;
|
|
}
|
|
@@ -201,29 +252,29 @@ 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
|
|
void showContextMenu(@JniType("std::string") String actionId) {
|
|
// {@link mDelegate} should be set in {@code ExtensionActionListMediator}'s constructor.
|
|
- assert mDelegate != null;
|
|
+ assert Instance().mDelegate != null;
|
|
|
|
- mDelegate.showContextMenu(actionId);
|
|
+ Instance().mDelegate.showContextMenu(actionId);
|
|
}
|
|
|
|
@CalledByNative
|
|
public void onRequestAccessButtonParamsChanged() {
|
|
- for (Observer observer : mObservers) {
|
|
+ for (Observer observer : Instance().mObservers) {
|
|
observer.onRequestAccessButtonParamsChanged();
|
|
}
|
|
}
|
|
|
|
@CalledByNative
|
|
public void onToolbarControlStateUpdated() {
|
|
- for (Observer observer : mObservers) {
|
|
+ for (Observer observer : Instance().mObservers) {
|
|
observer.onToolbarControlStateUpdated();
|
|
}
|
|
}
|
|
@@ -231,65 +282,65 @@ public class ExtensionsToolbarBridge implements Destroyable {
|
|
@CalledByNative
|
|
public boolean hasPoppedOutAction() {
|
|
// {@link mDelegate} should be set in {@code ExtensionActionListMediator}'s constructor.
|
|
- assert mDelegate != null;
|
|
+ assert Instance().mDelegate != null;
|
|
|
|
- return mDelegate.hasPoppedOutAction();
|
|
+ return Instance().mDelegate.hasPoppedOutAction();
|
|
}
|
|
|
|
@CalledByNative
|
|
public void hideActivePopup() {
|
|
// {@link mDelegate} should be set in {@code ExtensionActionListMediator}'s constructor.
|
|
- assert mDelegate != null;
|
|
+ assert Instance().mDelegate != null;
|
|
|
|
- mDelegate.hideActivePopup();
|
|
+ Instance().mDelegate.hideActivePopup();
|
|
}
|
|
|
|
@CalledByNative
|
|
public boolean hasActivePopup() {
|
|
// {@link mDelegate} should be set in {@code ExtensionActionListMediator}'s constructor.
|
|
- assert mDelegate != null;
|
|
+ assert Instance().mDelegate != null;
|
|
|
|
- return mDelegate.hasActivePopup();
|
|
+ return Instance().mDelegate.hasActivePopup();
|
|
}
|
|
|
|
@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(WebContents webContents) {
|
|
- for (Observer observer : mObservers) {
|
|
+ for (Observer observer : Instance().mObservers) {
|
|
observer.onActiveWebContentsChanged(webContents);
|
|
}
|
|
}
|
|
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionListCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionListCoordinator.java
|
|
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionListCoordinator.java
|
|
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionListCoordinator.java
|
|
@@ -44,17 +44,20 @@ public class ExtensionActionListCoordinator implements Destroyable {
|
|
|
|
private final Context mContext;
|
|
private final ExtensionActionListRecyclerView mContainer;
|
|
+ private final ListMenuButton mExtensionsMenuButton;
|
|
private final ModelList mModels;
|
|
private final ExtensionActionListMediator mMediator;
|
|
private final DragReorderableRecyclerViewAdapter mAdapter;
|
|
@Nullable private final LifetimeAssert mLifetimeAssert = LifetimeAssert.create(this);
|
|
private final RecyclerViewDelegate mRecyclerViewDelegate = new RecyclerViewDelegate();
|
|
+ public final ExtensionsToolbarBridge mExtensionsToolbarBridge;
|
|
|
|
private boolean mIsDragging;
|
|
|
|
public ExtensionActionListCoordinator(
|
|
Context context,
|
|
ExtensionActionListRecyclerView container,
|
|
+ ListMenuButton extensionsMenuButton,
|
|
WindowAndroid windowAndroid,
|
|
ChromeAndroidTask task,
|
|
Profile profile,
|
|
@@ -65,6 +68,8 @@ public class ExtensionActionListCoordinator implements Destroyable {
|
|
@Nullable SelectionDropdownMenuDelegate selectionDropdownMenuDelegate) {
|
|
mContext = context;
|
|
mContainer = container;
|
|
+ mExtensionsMenuButton = extensionsMenuButton;
|
|
+ mExtensionsToolbarBridge = extensionsToolbarBridge;
|
|
|
|
mModels = new ModelList();
|
|
mMediator =
|
|
@@ -78,7 +83,8 @@ public class ExtensionActionListCoordinator implements Destroyable {
|
|
mRecyclerViewDelegate,
|
|
extensionsToolbarBridge,
|
|
contextMenuPopulatorFactory,
|
|
- selectionDropdownMenuDelegate);
|
|
+ selectionDropdownMenuDelegate,
|
|
+ extensionsMenuButton);
|
|
|
|
ExtensionsToolbarDragTouchHandler dragTouchHandler =
|
|
new ExtensionsToolbarDragTouchHandler(context, mModels);
|
|
@@ -134,6 +140,10 @@ public class ExtensionActionListCoordinator implements Destroyable {
|
|
LifetimeAssert.setSafeToGc(mLifetimeAssert, true);
|
|
}
|
|
|
|
+ public void openPopup(String actionId) {
|
|
+ mMediator.onPrimaryClick(actionId);
|
|
+ }
|
|
+
|
|
/**
|
|
* Executes the given action.
|
|
*
|
|
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
|
|
@@ -87,11 +87,11 @@ class ExtensionActionListMediator implements Destroyable {
|
|
private final WindowAndroid mWindowAndroid;
|
|
private final ModelList mModels;
|
|
private final ChromeAndroidTask mTask;
|
|
- private final Profile mProfile;
|
|
private final NullableObservableSupplier<Tab> mCurrentTabSupplier;
|
|
private final @Nullable ContextMenuPopulatorFactory mContextMenuPopulatorFactory;
|
|
private final @Nullable SelectionDropdownMenuDelegate mSelectionDropdownMenuDelegate;
|
|
private final ExtensionActionListCoordinator.RecyclerViewDelegate mRecyclerViewDelegate;
|
|
+ private final ListMenuButton mExtensionsMenuButton;
|
|
|
|
private final ExtensionsToolbarBridge mExtensionsToolbarBridge;
|
|
private final ToolbarDelegate mToolbarDelegate = new ToolbarDelegate();
|
|
@@ -124,19 +124,20 @@ class ExtensionActionListMediator implements Destroyable {
|
|
ExtensionActionListCoordinator.RecyclerViewDelegate recyclerViewDelegate,
|
|
ExtensionsToolbarBridge extensionsToolbarBridge,
|
|
@Nullable ContextMenuPopulatorFactory contextMenuPopulatorFactory,
|
|
- @Nullable SelectionDropdownMenuDelegate selectionDropdownMenuDelegate) {
|
|
+ @Nullable SelectionDropdownMenuDelegate selectionDropdownMenuDelegate,
|
|
+ ListMenuButton extensionsMenuButton) {
|
|
mContext = context;
|
|
mWindowAndroid = windowAndroid;
|
|
mModels = models;
|
|
mTask = task;
|
|
- mProfile = profile;
|
|
mCurrentTabSupplier = currentTabSupplier;
|
|
mRecyclerViewDelegate = recyclerViewDelegate;
|
|
mExtensionsToolbarBridge = extensionsToolbarBridge;
|
|
mContextMenuPopulatorFactory = contextMenuPopulatorFactory;
|
|
mSelectionDropdownMenuDelegate = selectionDropdownMenuDelegate;
|
|
+ mExtensionsMenuButton = extensionsMenuButton;
|
|
|
|
- mExtensionsToolbarBridge.setDelegate(mToolbarDelegate);
|
|
+ mExtensionsToolbarBridge.setDelegate(mTask, mToolbarDelegate);
|
|
mExtensionsToolbarBridge.addObserver(mToolbarObserver);
|
|
reconcileActionItems();
|
|
}
|
|
@@ -149,7 +150,7 @@ class ExtensionActionListMediator implements Destroyable {
|
|
assert mActionState instanceof ActionState.Idle;
|
|
|
|
mExtensionsToolbarBridge.removeObserver(mToolbarObserver);
|
|
- mExtensionsToolbarBridge.setDelegate(null);
|
|
+ mExtensionsToolbarBridge.setDelegate(mTask, null);
|
|
LifetimeAssert.setSafeToGc(mLifetimeAssert, true);
|
|
}
|
|
|
|
@@ -401,7 +402,8 @@ class ExtensionActionListMediator implements Destroyable {
|
|
return mModels.get(index).model.get(ExtensionActionButtonProperties.ID);
|
|
}
|
|
|
|
- private void onPrimaryClick(String actionId) {
|
|
+ public void onPrimaryClick(String actionId) {
|
|
+ if (!mTask.isActive()) return;
|
|
if (mActionState instanceof ActionState.PopupActive activeState) {
|
|
boolean closeOnly = activeState.getActionId().equals(actionId);
|
|
closePopup();
|
|
@@ -470,16 +472,14 @@ class ExtensionActionListMediator implements Destroyable {
|
|
closeContextMenu();
|
|
|
|
ExtensionActionPopupContents contents = ExtensionActionPopupContents.create(nativeHostPtr);
|
|
- requestActionVisibility(actionId, () -> showPopupOnAnchor(actionId, contents));
|
|
+ showPopupOnAnchor(actionId, contents);
|
|
}
|
|
|
|
private void showPopupOnAnchor(String actionId, ExtensionActionPopupContents contents) {
|
|
ListMenuButton buttonView =
|
|
(ListMenuButton) mRecyclerViewDelegate.getButtonViewForId(actionId);
|
|
if (buttonView == null) {
|
|
- contents.destroy();
|
|
- undoPopout();
|
|
- return;
|
|
+ buttonView = mExtensionsMenuButton;
|
|
}
|
|
|
|
Activity activity = mWindowAndroid.getActivity().get();
|
|
@@ -564,7 +564,7 @@ class ExtensionActionListMediator implements Destroyable {
|
|
assert mActionState instanceof ActionState.Idle;
|
|
ExtensionActionContextMenuBridge bridge =
|
|
new ExtensionActionContextMenuBridge(
|
|
- mTask, mProfile, actionId, webContents, ContextMenuSource.TOOLBAR_ACTION);
|
|
+ mTask, currentTab.getProfile(), actionId, webContents, ContextMenuSource.TOOLBAR_ACTION);
|
|
ExtensionActionContextMenuUtils.showContextMenu(
|
|
mContext,
|
|
buttonView,
|
|
@@ -597,7 +597,7 @@ class ExtensionActionListMediator implements Destroyable {
|
|
|
|
/** Updates the list of displayed actions to fit within the provided width constraint. */
|
|
public void fitActionsWithinWidth(int availableWidth) {
|
|
- mAvailableWidthForPinnedActions = availableWidth;
|
|
+ // mAvailableWidthForPinnedActions = availableWidth;
|
|
|
|
// If this is called during an animation (e.g. the user resizes window during pinning /
|
|
// unpinning animation), we abandon the animation and update to the new state instantly.
|
|
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
|
|
@@ -14,6 +14,7 @@ import androidx.core.widget.ImageViewCompat;
|
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
import androidx.recyclerview.widget.RecyclerView;
|
|
|
|
+import org.chromium.base.Callback;
|
|
import org.chromium.base.lifetime.Destroyable;
|
|
import org.chromium.base.supplier.NullableObservableSupplier;
|
|
import org.chromium.build.annotations.NullMarked;
|
|
@@ -71,6 +72,7 @@ public class ExtensionsMenuCoordinator implements Destroyable, ExtensionsToolbar
|
|
private final ExtensionActionListCoordinator mExtensionActionListCoordinator;
|
|
|
|
@Nullable @VisibleForTesting ExtensionsMenuMediator mMediator;
|
|
+ private Callback<String> mOpenUrlInCustomTab;
|
|
|
|
/**
|
|
* Constructor.
|
|
@@ -96,7 +98,9 @@ public class ExtensionsMenuCoordinator implements Destroyable, ExtensionsToolbar
|
|
TabCreator tabCreator,
|
|
ExtensionsToolbarBridge extensionsToolbarBridge,
|
|
MenuButtonPinningDelegate menuButtonPinningDelegate,
|
|
- ExtensionActionListCoordinator extensionActionListCoordinator) {
|
|
+ ExtensionActionListCoordinator extensionActionListCoordinator,
|
|
+ Callback<String> openUrlInCustomTab) {
|
|
+ mOpenUrlInCustomTab = openUrlInCustomTab;
|
|
mExtensionActionListCoordinator = extensionActionListCoordinator;
|
|
mContext = context;
|
|
mCurrentTabSupplier = currentTabSupplier;
|
|
@@ -234,6 +238,14 @@ public class ExtensionsMenuCoordinator implements Destroyable, ExtensionsToolbar
|
|
private void openUrlFromMenu(String url) {
|
|
mExtensionsMenuButton.dismiss();
|
|
|
|
+ if (mOpenUrlInCustomTab != null) {
|
|
+ Tab currentTab = mCurrentTabSupplier.get();
|
|
+ if (currentTab != null && currentTab.isIncognitoBranded()) {
|
|
+ mOpenUrlInCustomTab.onResult(url);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
LoadUrlParams params = new LoadUrlParams(url, PageTransition.AUTO_TOPLEVEL);
|
|
|
|
mTabCreator.createNewTab(params, TabLaunchType.FROM_CHROME_UI, null);
|
|
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
|
|
@@ -44,7 +44,6 @@ class ExtensionsMenuMediator implements Destroyable, ExtensionsMenuBridge.Observ
|
|
private final PropertyModel mSitePermissionsPageModel;
|
|
private final Runnable mOnReady;
|
|
private final ChromeAndroidTask mTask;
|
|
- private final Profile mProfile;
|
|
private final ExtensionActionListCoordinator mExtensionActionListCoordinator;
|
|
|
|
/**
|
|
@@ -73,8 +72,8 @@ class ExtensionsMenuMediator implements Destroyable, ExtensionsMenuBridge.Observ
|
|
mCurrentTabSupplier = currentTabSupplier;
|
|
mOnReady = onReady;
|
|
mTask = task;
|
|
- mProfile = profile;
|
|
- mMenuBridge = new ExtensionsMenuBridge(mTask, mProfile, /* observer= */ this);
|
|
+ mMenuBridge = ExtensionsMenuBridge.Instance();
|
|
+ mMenuBridge.setObserver(task, /* observer= */ this);
|
|
|
|
mMainPageModel = mainPageModel;
|
|
mMainPageModel.set(
|
|
@@ -112,7 +111,7 @@ class ExtensionsMenuMediator implements Destroyable, ExtensionsMenuBridge.Observ
|
|
|
|
ExtensionActionContextMenuBridge contextMenuBridge =
|
|
new ExtensionActionContextMenuBridge(
|
|
- mTask, mProfile, actionId, webContents, ContextMenuSource.MENU_ITEM);
|
|
+ mTask, currentTab.getProfile(), actionId, webContents, ContextMenuSource.MENU_ITEM);
|
|
|
|
ExtensionActionContextMenuUtils.showContextMenu(
|
|
mContext,
|
|
@@ -142,7 +141,7 @@ class ExtensionsMenuMediator implements Destroyable, ExtensionsMenuBridge.Observ
|
|
public void destroy() {
|
|
mMainPageModel.set(ExtensionsMenuProperties.SITE_SETTINGS_TOGGLE_CLICK_LISTENER, null);
|
|
mSitePermissionsPageModel.set(SitePermissionsPageProperties.BACK_CLICK_LISTENER, null);
|
|
- mMenuBridge.destroy();
|
|
+ //mMenuBridge.destroy();
|
|
}
|
|
|
|
/**
|
|
@@ -253,6 +252,7 @@ class ExtensionsMenuMediator implements Destroyable, ExtensionsMenuBridge.Observ
|
|
break;
|
|
}
|
|
}
|
|
+ if (oldIndex < 0) return;
|
|
assert oldIndex != -1
|
|
: "Action model with ID " + entry.id + " should exist in mActionModels.";
|
|
|
|
@@ -479,7 +479,7 @@ class ExtensionsMenuMediator implements Destroyable, ExtensionsMenuBridge.Observ
|
|
// open web store button present in the zero state view.
|
|
mMainPageModel.set(ExtensionsMenuProperties.DISCOVER_EXTENSIONS_VISIBLE, false);
|
|
} else {
|
|
- mMainPageModel.set(ExtensionsMenuProperties.DISCOVER_EXTENSIONS_VISIBLE, true);
|
|
+ mMainPageModel.set(ExtensionsMenuProperties.DISCOVER_EXTENSIONS_VISIBLE, false);
|
|
updateSiteSettingsToggle();
|
|
}
|
|
}
|
|
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsToolbarCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsToolbarCoordinator.java
|
|
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsToolbarCoordinator.java
|
|
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsToolbarCoordinator.java
|
|
@@ -9,6 +9,7 @@ import android.view.KeyEvent;
|
|
import android.view.ViewGroup;
|
|
import android.view.ViewStub;
|
|
|
|
+import org.chromium.base.Callback;
|
|
import org.chromium.base.ServiceLoaderUtil;
|
|
import org.chromium.base.lifetime.Destroyable;
|
|
import org.chromium.base.supplier.NullableObservableSupplier;
|
|
@@ -53,7 +54,8 @@ public interface ExtensionsToolbarCoordinator extends Destroyable {
|
|
ThemeColorProvider themeColorProvider,
|
|
ViewGroup rootView,
|
|
@Nullable ContextMenuPopulatorFactory contextMenuPopulatorFactory,
|
|
- @Nullable SelectionDropdownMenuDelegate selectionDropdownMenuDelegate) {
|
|
+ @Nullable SelectionDropdownMenuDelegate selectionDropdownMenuDelegate,
|
|
+ Callback<String> openUrlInCustomTab) {
|
|
// Check if the extension UI is enabled first.
|
|
if (!ExtensionUi.isEnabled(profile)) {
|
|
return null;
|
|
@@ -75,7 +77,8 @@ public interface ExtensionsToolbarCoordinator extends Destroyable {
|
|
themeColorProvider,
|
|
rootView,
|
|
contextMenuPopulatorFactory,
|
|
- selectionDropdownMenuDelegate);
|
|
+ selectionDropdownMenuDelegate,
|
|
+ openUrlInCustomTab);
|
|
return coordinator;
|
|
}
|
|
|
|
@@ -97,7 +100,8 @@ public interface ExtensionsToolbarCoordinator extends Destroyable {
|
|
ThemeColorProvider themeColorProvider,
|
|
ViewGroup rootView,
|
|
@Nullable ContextMenuPopulatorFactory contextMenuPopulatorFactory,
|
|
- @Nullable SelectionDropdownMenuDelegate selectionDropdownMenuDelegate);
|
|
+ @Nullable SelectionDropdownMenuDelegate selectionDropdownMenuDelegate,
|
|
+ Callback<String> openUrlInCustomTab);
|
|
|
|
/**
|
|
* Dispatches the key event to trigger the corresponding extension action if any.
|
|
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsToolbarCoordinatorImpl.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsToolbarCoordinatorImpl.java
|
|
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsToolbarCoordinatorImpl.java
|
|
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsToolbarCoordinatorImpl.java
|
|
@@ -6,6 +6,7 @@ package org.chromium.chrome.browser.toolbar.extensions;
|
|
|
|
import android.animation.Animator;
|
|
import android.content.Context;
|
|
+import android.content.res.ColorStateList;
|
|
import android.view.KeyEvent;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
@@ -13,6 +14,7 @@ import android.view.ViewStub;
|
|
import android.widget.LinearLayout;
|
|
import android.widget.TextView;
|
|
|
|
+import org.chromium.base.Callback;
|
|
import org.chromium.base.lifetime.LifetimeAssert;
|
|
import org.chromium.base.supplier.NullableObservableSupplier;
|
|
import org.chromium.build.annotations.NullMarked;
|
|
@@ -25,6 +27,8 @@ import org.chromium.chrome.browser.profiles.Profile;
|
|
import org.chromium.chrome.browser.tab.Tab;
|
|
import org.chromium.chrome.browser.tabmodel.TabCreator;
|
|
import org.chromium.chrome.browser.theme.ThemeColorProvider;
|
|
+import org.chromium.chrome.browser.theme.ThemeUtils;
|
|
+import org.chromium.chrome.browser.ui.theme.BrandedColorScheme;
|
|
import org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTask;
|
|
import org.chromium.chrome.browser.ui.extensions.ExtensionActionsBridge;
|
|
import org.chromium.chrome.browser.ui.extensions.ExtensionsToolbarBridge;
|
|
@@ -58,6 +62,8 @@ public class ExtensionsToolbarCoordinatorImpl implements ExtensionsToolbarCoordi
|
|
private ExtensionAccessControlButtonCoordinator mExtensionAccessControlButtonCoordinator;
|
|
private PropertyModel mToolbarModel;
|
|
private PropertyModelChangeProcessor mMenuButtonChangeProcessor;
|
|
+ private Context mContext;
|
|
+ private ThemeColorProvider mThemeColorProvider;
|
|
|
|
private final MenuButtonWidthConsumer mMenuButtonWidthConsumer = new MenuButtonWidthConsumer();
|
|
private final RequestAccessButtonWidthConsumer mRequestAccessButtonWidthConsumer =
|
|
@@ -86,7 +92,9 @@ public class ExtensionsToolbarCoordinatorImpl implements ExtensionsToolbarCoordi
|
|
ThemeColorProvider themeColorProvider,
|
|
ViewGroup rootView,
|
|
@Nullable ContextMenuPopulatorFactory contextMenuPopulatorFactory,
|
|
- @Nullable SelectionDropdownMenuDelegate selectionDropdownMenuDelegate) {
|
|
+ @Nullable SelectionDropdownMenuDelegate selectionDropdownMenuDelegate,
|
|
+ Callback<String> openUrlInCustomTab) {
|
|
+ mThemeColorProvider = themeColorProvider;
|
|
mBridge = ExtensionActionsBridge.Instance();
|
|
mProfile = profile;
|
|
|
|
@@ -127,7 +135,8 @@ public class ExtensionsToolbarCoordinatorImpl implements ExtensionsToolbarCoordi
|
|
currentTabSupplier,
|
|
tabCreator,
|
|
mExtensionsToolbarBridge,
|
|
- mMenuButtonPinningDelegate);
|
|
+ mMenuButtonPinningDelegate,
|
|
+ mExtensionActionListCoordinator, openUrlInCustomTab);
|
|
|
|
mExtensionAccessControlButtonCoordinator =
|
|
new ExtensionAccessControlButtonCoordinator(
|
|
@@ -174,6 +183,8 @@ public class ExtensionsToolbarCoordinatorImpl implements ExtensionsToolbarCoordi
|
|
mToolbarModel.set(
|
|
ExtensionsToolbarProperties.EXTENSIONS_MENU_BUTTON_DEFAULT_BACKGROUND,
|
|
backgroundResource);
|
|
+ mExtensionsMenuCoordinator.onTintChanged(
|
|
+ /*tintList*/ null, mThemeColorProvider.getTint(), BrandedColorScheme.APP_DEFAULT);
|
|
}
|
|
|
|
@Override
|
|
@@ -202,6 +213,8 @@ public class ExtensionsToolbarCoordinatorImpl implements ExtensionsToolbarCoordi
|
|
mExtensionsMenuCoordinator.setMenuButtonPinned(isMenuButtonPinned());
|
|
}
|
|
|
|
+ updateMenuIconVisibility();
|
|
+
|
|
// Trigger layout and wait for the toolbar to provide us with width allocation.
|
|
ViewUtils.requestLayout(
|
|
mContainer, "ExtensionsToolbarCoordinatorImpl.updateMenuButtonPinState()");
|
|
@@ -223,9 +236,7 @@ public class ExtensionsToolbarCoordinatorImpl implements ExtensionsToolbarCoordi
|
|
}
|
|
|
|
private boolean shouldShowMenuIcon() {
|
|
- return mExtensionsMenuCoordinator.isExtensionsMenuOpen()
|
|
- || mShowExtensionsMenuPending
|
|
- || (mCanShowMenuIcon && isMenuButtonPinned());
|
|
+ return isMenuButtonPinned();
|
|
}
|
|
|
|
public class MenuButtonPinningDelegate {
|
|
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
|
|
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
|
|
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
|
|
@@ -87,6 +87,7 @@ import org.chromium.chrome.browser.toolbar.ToolbarDataProvider;
|
|
import org.chromium.chrome.browser.toolbar.ToolbarProgressBar;
|
|
import org.chromium.chrome.browser.toolbar.ToolbarTabController;
|
|
import org.chromium.chrome.browser.toolbar.back_button.BackButtonCoordinator;
|
|
+import org.chromium.chrome.browser.toolbar.extensions.ExtensionsToolbarCoordinator;
|
|
import org.chromium.chrome.browser.toolbar.forward_button.ForwardButtonCoordinator;
|
|
import org.chromium.chrome.browser.toolbar.home_button.HomeButtonCoordinator;
|
|
import org.chromium.chrome.browser.toolbar.menu_button.MenuButtonCoordinator;
|
|
@@ -324,6 +325,8 @@ public class ToolbarPhone extends ToolbarLayout
|
|
// to webpages.
|
|
private boolean mIsInLoadingPhaseFromNtpToWebpage;
|
|
|
|
+ private @Nullable ExtensionsToolbarCoordinator mExtensionsToolbarCoordinator;
|
|
+
|
|
// The following are some properties used during animation. We use explicit property classes
|
|
// to avoid the cost of reflection for each animation setup.
|
|
|
|
@@ -514,6 +517,14 @@ public class ToolbarPhone extends ToolbarLayout
|
|
}
|
|
}
|
|
|
|
+ @Override
|
|
+ public void setExtensionsToolbarCoordinator(
|
|
+ ExtensionsToolbarCoordinator extensionsToolbarCoordinator) {
|
|
+ mExtensionsToolbarCoordinator = extensionsToolbarCoordinator;
|
|
+ mExtensionsToolbarCoordinator.getMenuButtonWidthConsumer().updateVisibility(99999);
|
|
+ updateRippleBackground();
|
|
+ }
|
|
+
|
|
@Override
|
|
public void destroy() {
|
|
cancelAnimations();
|
|
@@ -2894,6 +2905,7 @@ public class ToolbarPhone extends ToolbarLayout
|
|
@Override
|
|
public void onTabOrModelChanged() {
|
|
super.onTabOrModelChanged();
|
|
+ updateRippleBackground();
|
|
updateNtpAnimationState();
|
|
updateVisualsForLocationBarState();
|
|
}
|
|
@@ -2911,6 +2923,10 @@ public class ToolbarPhone extends ToolbarLayout
|
|
mHomeButton.setBackgroundResource(toolbarIconRippleId);
|
|
getMenuButtonCoordinator().updateButtonBackground(toolbarIconRippleId);
|
|
mLocationBar.updateButtonBackground(omniboxIconRippleId);
|
|
+ if (mExtensionsToolbarCoordinator != null) {
|
|
+ mExtensionsToolbarCoordinator.updateMenuButtonBackground(
|
|
+ ToolbarUtils.getToolbarIconRippleId(isIncognitoBranded()));
|
|
+ }
|
|
}
|
|
|
|
private static boolean isVisualStateValidForBrandColorTransition(@VisualState int state) {
|
|
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
|
|
@@ -329,7 +329,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 ((true)) {
|
|
if (mPendingBrowserWindow != null
|
|
&& mPendingBrowserWindow.getProfile() == profile) {
|
|
assert mActivityScopedObjectsDeque.isEmpty();
|
|
@@ -425,6 +425,10 @@ final class ChromeAndroidTaskImpl
|
|
}
|
|
}
|
|
}
|
|
+
|
|
+ @Override
|
|
+ public void didDestroyed() {
|
|
+ }
|
|
}
|
|
|
|
private @Nullable Integer mId;
|
|
@@ -738,7 +742,7 @@ final class ChromeAndroidTaskImpl
|
|
? null
|
|
: topActivityScopedObjects.mTabModelSelector;
|
|
if (tabModelSelector != null) {
|
|
- feature.onTabModelSelected(tabModelSelector.getCurrentModel());
|
|
+ feature.onTabModelSelected(this, tabModelSelector.getCurrentModel());
|
|
}
|
|
}
|
|
|
|
@@ -1208,6 +1212,14 @@ final class ChromeAndroidTaskImpl
|
|
for (var feature : mFeatures.values()) {
|
|
feature.onTaskFocusChanged(isTopResumedActivity);
|
|
}
|
|
+ if (isTopResumedActivity) {
|
|
+ var internalActivityScopedObjects = mActivityScopedObjectsDeque.peekFirst();
|
|
+ var topActivityScopedObjects = internalActivityScopedObjects.mActivityScopedObjects;
|
|
+ TabModelSelector tabModelSelector = topActivityScopedObjects.mTabModelSelector;
|
|
+ for (var feature : mFeatures.values()) {
|
|
+ feature.onTabModelSelected(this, tabModelSelector.getCurrentModel());
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
@Override
|
|
@@ -1867,7 +1879,7 @@ final class ChromeAndroidTaskImpl
|
|
|
|
private void onTabModelSelected(TabModel tabModel) {
|
|
for (var feature : mFeatures.values()) {
|
|
- feature.onTabModelSelected(tabModel);
|
|
+ feature.onTabModelSelected(this, tabModel);
|
|
}
|
|
}
|
|
|
|
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
|
|
@@ -72,5 +72,5 @@ public interface ChromeAndroidTaskFeature {
|
|
*
|
|
* @param tabModel The selected {@link TabModel}.
|
|
*/
|
|
- 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
|
|
@@ -137,6 +137,22 @@ TabCollection::TabCollection(Type type,
|
|
|
|
TabCollection::~TabCollection() {
|
|
DispatchPendingNotifications();
|
|
+
|
|
+ auto& childrens = GetChildren();
|
|
+ for (auto it = childrens.begin(); it != childrens.end(); ) {
|
|
+ auto& child = *it;
|
|
+ if (std::holds_alternative<std::unique_ptr<TabInterface>>(child)) {
|
|
+ TabInterface* tab =
|
|
+ std::get<std::unique_ptr<TabInterface>>(child).get();
|
|
+ auto removed_tab = MaybeRemoveTab(tab);
|
|
+ } else if (std::holds_alternative<std::unique_ptr<TabCollection>>(child)) {
|
|
+ TabCollection* collection =
|
|
+ std::get<std::unique_ptr<TabCollection>>(child).get();
|
|
+ auto removed_collection = MaybeRemoveCollection(collection);
|
|
+ } else {
|
|
+ it++;
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
void TabCollection::AddObserver(TabCollectionObserver* observer) const {
|
|
diff --git a/components/tabs/impl/tab_strip_collection.cc b/components/tabs/impl/tab_strip_collection.cc
|
|
--- a/components/tabs/impl/tab_strip_collection.cc
|
|
+++ b/components/tabs/impl/tab_strip_collection.cc
|
|
@@ -329,13 +329,13 @@ std::unique_ptr<TabInterface> TabStripCollection::RemoveTabAtIndexRecursive(
|
|
std::unique_ptr<TabInterface> TabStripCollection::MaybeRemoveTab(
|
|
TabInterface* tab) {
|
|
CHECK(tab);
|
|
- return nullptr;
|
|
+ return RemoveTabImpl(tab);
|
|
}
|
|
|
|
std::unique_ptr<TabCollection> TabStripCollection::MaybeRemoveCollection(
|
|
TabCollection* collection) {
|
|
CHECK(collection);
|
|
- return nullptr;
|
|
+ return TabStripCollection::RemoveTabCollection(collection);
|
|
}
|
|
|
|
void TabStripCollection::InsertTabCollectionAt(
|
|
--
|