From ff33bbeb526156572819742d24576046323c77fe Mon Sep 17 00:00:00 2001 From: Carmelo Messina Date: Thu, 11 Dec 2025 14:40:17 +0100 Subject: [PATCH] Enable extensions in android: allow use with always incognito (#2519 #2511) and fix dangling raw_ptr on destruction --- ...port-v144-android-extensions-changes.patch | 111 +++++++++++++++++- .../Enable-extension-in-incognito.patch | 76 ++++++++++-- ...al-support-for-extensions-on-Android.patch | 79 ++++++++++++- 3 files changed, 252 insertions(+), 14 deletions(-) diff --git a/build/patches/Backport-v144-android-extensions-changes.patch b/build/patches/Backport-v144-android-extensions-changes.patch index 4a6bb78f..b4a19d39 100644 --- a/build/patches/Backport-v144-android-extensions-changes.patch +++ b/build/patches/Backport-v144-android-extensions-changes.patch @@ -3,8 +3,12 @@ Date: Thu, 6 Nov 2025 13:22:24 +0000 Subject: Backport-v144-android-extensions-changes Enable support for anonymous browsing. -Backport of bugid 7089957 extensions Use BrowserWindowInterface in ExtensionViewHost +Backport of bugid +7089957: extensions Use BrowserWindowInterface in ExtensionViewHost https://chromium-review.googlesource.com/c/chromium/src/+/7089957 + +7126008: Destroy ExtensionWindowControllerBridge when its Profile is destroyed +https://chromium-review.googlesource.com/c/chromium/src/+/7126008 --- .../chrome/browser/ChromeTabbedActivity.java | 1 + .../chrome/browser/app/ChromeActivity.java | 12 ++ @@ -20,13 +24,15 @@ https://chromium-review.googlesource.com/c/chromium/src/+/7089957 chrome/browser/ui/android/extensions/BUILD.gn | 1 + .../extension_action_popup_contents.cc | 9 +- .../ExtensionActionPopupContents.java | 14 +- + .../extensions/windowing/internal/BUILD.gn | 1 + + .../ExtensionWindowControllerBridgeImpl.java | 45 ++++++- chrome/browser/ui/android/toolbar/BUILD.gn | 2 + .../ExtensionActionListCoordinator.java | 10 +- .../ExtensionActionListMediator.java | 16 ++- .../ExtensionActionListMediatorTest.java | 11 +- .../ExtensionToolbarCoordinator.java | 5 + .../ExtensionToolbarCoordinatorImpl.java | 4 + - 20 files changed, 160 insertions(+), 92 deletions(-) + 22 files changed, 201 insertions(+), 97 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 @@ -597,6 +603,107 @@ diff --git a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/b /** * Destroys the native ExtensionActionPopupContents object. +diff --git a/chrome/browser/ui/android/extensions/windowing/internal/BUILD.gn b/chrome/browser/ui/android/extensions/windowing/internal/BUILD.gn +--- a/chrome/browser/ui/android/extensions/windowing/internal/BUILD.gn ++++ b/chrome/browser/ui/android/extensions/windowing/internal/BUILD.gn +@@ -38,6 +38,7 @@ android_library("java") { + ] + deps = [ + "//build/android:build_java", ++ "//chrome/browser/profiles/android:java", + "//chrome/browser/ui/android/extensions/windowing:java", + "//chrome/browser/ui/browser_window/public/android:java", + "//third_party/androidx:androidx_annotation_annotation_java", +diff --git a/chrome/browser/ui/android/extensions/windowing/internal/java/src/org/chromium/chrome/browser/ui/extensions/windowing/ExtensionWindowControllerBridgeImpl.java b/chrome/browser/ui/android/extensions/windowing/internal/java/src/org/chromium/chrome/browser/ui/extensions/windowing/ExtensionWindowControllerBridgeImpl.java +--- a/chrome/browser/ui/android/extensions/windowing/internal/java/src/org/chromium/chrome/browser/ui/extensions/windowing/ExtensionWindowControllerBridgeImpl.java ++++ b/chrome/browser/ui/android/extensions/windowing/internal/java/src/org/chromium/chrome/browser/ui/extensions/windowing/ExtensionWindowControllerBridgeImpl.java +@@ -11,6 +11,8 @@ import org.jni_zero.CalledByNative; + import org.jni_zero.NativeMethods; + + import org.chromium.build.annotations.NullMarked; ++import org.chromium.chrome.browser.profiles.Profile; ++import org.chromium.chrome.browser.profiles.ProfileManager; + import org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTask; + + import java.util.ArrayList; +@@ -19,7 +21,8 @@ import java.util.Map; + + /** Implements {@link ExtensionWindowControllerBridge}. */ + @NullMarked +-final class ExtensionWindowControllerBridgeImpl implements ExtensionWindowControllerBridge { ++final class ExtensionWindowControllerBridgeImpl ++ implements ExtensionWindowControllerBridge, ProfileManager.Observer { + + /** + * Events received by the native singleton {@code WindowControllerListObserverForTesting}. +@@ -82,6 +85,7 @@ final class ExtensionWindowControllerBridgeImpl implements ExtensionWindowContro + assert mNativeExtensionWindowControllerBridge == 0 + : "ExtensionWindowControllerBridge is already added to a task."; + ++ ProfileManager.addObserver(this); + mNativeExtensionWindowControllerBridge = + ExtensionWindowControllerBridgeImplJni.get() + .create( +@@ -91,10 +95,8 @@ final class ExtensionWindowControllerBridgeImpl implements ExtensionWindowContro + + @Override + public void onTaskRemoved() { +- if (mNativeExtensionWindowControllerBridge != 0) { +- ExtensionWindowControllerBridgeImplJni.get() +- .destroy(mNativeExtensionWindowControllerBridge); +- } ++ destroyNativeExtensionWindowControllerBridge(); ++ ProfileManager.removeObserver(this); + } + + @Override +@@ -113,6 +115,32 @@ final class ExtensionWindowControllerBridgeImpl implements ExtensionWindowContro + } + } + ++ @Override ++ public void onProfileAdded(Profile profile) {} ++ ++ @Override ++ public void onProfileDestroyed(Profile profile) { ++ // This is a short-term fix for http://crbug.com/450234852. ++ // ++ // The native extension code is cross-platform and depends on BrowserWindowInterface. Per ++ // documentation of BrowserWindowInterface::GetProfile(), cross-platform code assumes ++ // BrowserWindowInterface will always be destroyed *before* its Profile. ++ // ++ // See: ++ // https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/ui/browser_window/public/browser_window_interface.h;l=108;drc=c8dc70b538f1bb0862f1be58237d6e945ee81819 ++ // ++ // However, on Android, http://crbug.com/450234852 reveals a case where the Profile is ++ // destroyed before its BrowserWindowInterface, which caused native extension code to ++ // dereference an invalid Profile pointer. ++ // ++ // To avoid this issue, we destroy the native objects for extensions as soon as the native ++ // Profile is about to be destroyed. The long-term fix should be to correct the object ++ // destruction order for the case described in http://crbug.com/450234852. ++ if (profile == mChromeAndroidTask.getProfile()) { ++ destroyNativeExtensionWindowControllerBridge(); ++ } ++ } ++ + long getNativePtrForTesting() { + return mNativeExtensionWindowControllerBridge; + } +@@ -123,6 +151,13 @@ final class ExtensionWindowControllerBridgeImpl implements ExtensionWindowContro + .getExtensionWindowIdForTesting(mNativeExtensionWindowControllerBridge); // IN-TEST + } + ++ private void destroyNativeExtensionWindowControllerBridge() { ++ if (mNativeExtensionWindowControllerBridge != 0) { ++ ExtensionWindowControllerBridgeImplJni.get() ++ .destroy(mNativeExtensionWindowControllerBridge); ++ } ++ } ++ + @CalledByNative + private void clearNativePtr() { + mNativeExtensionWindowControllerBridge = 0; diff --git a/chrome/browser/ui/android/toolbar/BUILD.gn b/chrome/browser/ui/android/toolbar/BUILD.gn --- a/chrome/browser/ui/android/toolbar/BUILD.gn +++ b/chrome/browser/ui/android/toolbar/BUILD.gn diff --git a/build/patches/Enable-extension-in-incognito.patch b/build/patches/Enable-extension-in-incognito.patch index 53e6754a..e8cc367a 100644 --- a/build/patches/Enable-extension-in-incognito.patch +++ b/build/patches/Enable-extension-in-incognito.patch @@ -12,22 +12,25 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html .../BaseCustomTabRootUiCoordinator.java | 4 +- .../CustomTabIntentDataProvider.java | 3 + .../tabbed_mode/TabbedRootUiCoordinator.java | 3 +- + .../browser/tabmodel/TabModelJniBridge.java | 4 +- .../tabmodel/TabModelSelectorBase.java | 7 ++ .../browser/toolbar/ToolbarManager.java | 4 +- .../chrome/browser/ui/RootUiCoordinator.java | 6 +- + .../developer_private_functions_shared.cc | 4 +- .../browser/extensions/extension_tab_util.cc | 2 +- - .../tabmodel/IncognitoTabModelImpl.java | 5 + + .../tabmodel/IncognitoTabModelImpl.java | 10 +- .../tabmodel/IncognitoTabModelObserver.java | 2 + .../extensions/extension_actions_bridge.cc | 12 +++ .../extensions/extension_actions_bridge.h | 1 + .../ui/extensions/ExtensionActionsBridge.java | 6 ++ + .../android/tab_model/tab_model_jni_bridge.cc | 4 + .../ExtensionActionListCoordinator.java | 4 +- .../ExtensionActionListMediator.java | 16 ++-- .../ExtensionToolbarCoordinator.java | 7 +- .../ExtensionToolbarCoordinatorImpl.java | 5 +- .../ChromeAndroidTaskTrackerImpl.java | 93 ++++++++++++++----- .../ChromeAndroidTaskTracker.java | 6 +- - 21 files changed, 201 insertions(+), 51 deletions(-) + 24 files changed, 213 insertions(+), 56 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 @@ -245,6 +248,22 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/Tab @NonNull ActivityLifecycleDispatcher activityLifecycleDispatcher, @NonNull ObservableSupplier 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 +@@ -129,10 +129,10 @@ public abstract class TabModelJniBridge implements TabModelInternal { + @Override + public void associateWithBrowserWindow(long nativeAndroidBrowserWindow) { + // Ensure this isn't set multiple times. +- assert mNativeAndroidBrowserWindow == 0; ++ if (nativeAndroidBrowserWindow != 0) assert mNativeAndroidBrowserWindow == 0; + mNativeAndroidBrowserWindow = nativeAndroidBrowserWindow; + +- assert nativeAndroidBrowserWindow != 0; ++ // assert nativeAndroidBrowserWindow != 0; + TabModelJniBridgeJni.get() + .associateWithBrowserWindow(mNativeTabModelJniBridge, nativeAndroidBrowserWindow); + } 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 @@ -327,6 +346,20 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordi @NonNull ActivityLifecycleDispatcher activityLifecycleDispatcher, @NonNull ObservableSupplier layoutManagerSupplier, @NonNull MenuOrKeyboardActionController menuOrKeyboardActionController, +diff --git a/chrome/browser/extensions/api/developer_private/developer_private_functions_shared.cc b/chrome/browser/extensions/api/developer_private/developer_private_functions_shared.cc +--- a/chrome/browser/extensions/api/developer_private/developer_private_functions_shared.cc ++++ b/chrome/browser/extensions/api/developer_private/developer_private_functions_shared.cc +@@ -1676,8 +1676,8 @@ DeveloperPrivateDismissSafetyHubExtensionsMenuNotificationFunction::Run() { + } + + Profile* profile = Profile::FromBrowserContext(browser_context()); +- SafetyHubMenuNotificationServiceFactory::GetForProfile(profile) +- ->DismissActiveNotificationOfModule( ++ 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 @@ -342,18 +375,31 @@ diff --git a/chrome/browser/extensions/extension_tab_util.cc b/chrome/browser/ex 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 -@@ -151,6 +151,11 @@ class IncognitoTabModelImpl implements IncognitoTabModelInternal { - mDelegateModel.destroy(); - mCurrentTabSupplier.set(null); - mTabCountSupplier.set(0); +@@ -140,8 +140,12 @@ class IncognitoTabModelImpl implements IncognitoTabModelInternal { + return; + } + ++ // Disassociate ++ mDelegateModel.associateWithBrowserWindow(/*nativeAndroidBrowserWindow=*/ 0); + mNativeAndroidBrowserWindow = 0; + -+ for (IncognitoTabModelObserver observer : mIncognitoObservers) { + for (IncognitoTabModelObserver observer : mIncognitoObservers) { +- observer.didBecomeEmpty(); + observer.didDestroyed(); -+ } + } + mDelegateModel +@@ -152,6 +156,10 @@ class IncognitoTabModelImpl implements IncognitoTabModelInternal { + mCurrentTabSupplier.set(null); + mTabCountSupplier.set(0); + ++ for (IncognitoTabModelObserver observer : mIncognitoObservers) { ++ observer.didBecomeEmpty(); ++ } ++ mDelegateModel = EmptyTabModel.getInstance(true); for (Callback delegateModelObserver : mDelegateModelObservers) { + delegateModelObserver.onResult(mDelegateModel); 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 @@ -427,6 +473,20 @@ 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/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 +@@ -116,6 +116,10 @@ void TabModelJniBridge::AssociateWithBrowserWindow( + // BrowserWindowInterface is available on desktop Android, but not other Android + // builds. For non-desktop Android, this function should be a no-op. + #if BUILDFLAG(IS_DESKTOP_ANDROID_CROMITE) ++ if (native_android_browser_window == 0) { ++ scoped_unowned_user_data_.reset(); ++ return; ++ } + BrowserWindowInterface* android_browser_window = + reinterpret_cast(native_android_browser_window); + CHECK(android_browser_window != nullptr); 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 diff --git a/build/patches/Experimental-support-for-extensions-on-Android.patch b/build/patches/Experimental-support-for-extensions-on-Android.patch index 4aaefe49..d58da44b 100644 --- a/build/patches/Experimental-support-for-extensions-on-Android.patch +++ b/build/patches/Experimental-support-for-extensions-on-Android.patch @@ -81,12 +81,13 @@ License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html chrome/browser/startup_data.h | 6 +- .../common/task_manager_features.cc | 2 +- chrome/browser/ui/BUILD.gn | 6 +- - .../browser/ui/android/context_menu_helper.cc | 6 +- + .../browser/ui/android/context_menu_helper.cc | 12 +++- .../browser/ui/android/context_menu_helper.h | 4 +- chrome/browser/ui/android/extensions/BUILD.gn | 4 +- .../extensions/extension_actions_bridge.cc | 23 ++++++ .../extensions/extension_actions_bridge.h | 1 + - .../res/layout/extensions_menu_footer.xml | 3 +- + .../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 +- @@ -123,6 +124,8 @@ License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html chrome/common/extensions/api/api_sources.gni | 7 ++ chrome/common/webui_url_constants.cc | 2 +- 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/version.gni | 4 +- .../core/browser/host_content_settings_map.cc | 6 ++ @@ -183,7 +186,7 @@ License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html ui/webui/resources/cr_elements/BUILD.gn | 2 +- .../cr_elements/cr_toolbar/cr_toolbar.css | 6 ++ ui/webui/resources/css/BUILD.gn | 2 +- - 171 files changed, 561 insertions(+), 288 deletions(-) + 174 files changed, 572 insertions(+), 289 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 @@ -1671,6 +1674,24 @@ diff --git a/chrome/browser/ui/android/context_menu_helper.cc b/chrome/browser/u // Reset any previous menu model, in case a new menu is shown // before the old one was gracefully closed. extension_menu_model_.reset(); +@@ -82,11 +82,17 @@ void ContextMenuHelper::ShowContextMenu( + } + + void ContextMenuHelper::DismissContextMenu() { ++#if BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS_CROMITE) ++ extension_menu_model_.reset(); ++#endif // BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS) + JNIEnv* env = base::android::AttachCurrentThread(); + Java_ContextMenuHelper_dismissContextMenu(env, java_obj_); + } + + void ContextMenuHelper::OnContextMenuClosed(JNIEnv* env) { ++#if BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS_CROMITE) ++ extension_menu_model_.reset(); ++#endif // BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS) + GetWebContents().NotifyContextMenuClosed(context_menu_params_.link_followed, + context_menu_params_.impression); + } diff --git a/chrome/browser/ui/android/context_menu_helper.h b/chrome/browser/ui/android/context_menu_helper.h --- a/chrome/browser/ui/android/context_menu_helper.h +++ b/chrome/browser/ui/android/context_menu_helper.h @@ -1762,6 +1783,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/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 +@@ -49,6 +49,7 @@ found in the LICENSE file. + + @@ -2512,6 +2552,37 @@ diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_const inline constexpr char kChromeUIDiscardsHost[] = "discards"; inline constexpr char kChromeUIDiscardsURL[] = "chrome://discards/"; #endif +diff --git a/chrome/renderer/sandbox_status_extension_android.cc b/chrome/renderer/sandbox_status_extension_android.cc +--- a/chrome/renderer/sandbox_status_extension_android.cc ++++ b/chrome/renderer/sandbox_status_extension_android.cc +@@ -34,7 +34,7 @@ SandboxStatusExtension::SandboxStatusExtension(content::RenderFrame* frame) + frame->GetAssociatedInterfaceRegistry() + ->AddInterface(base::BindRepeating( + &SandboxStatusExtension::OnSandboxStatusExtensionRequest, +- base::RetainedRef(this))); ++ weak_ptr_factory_.GetWeakPtr())); + } + + SandboxStatusExtension::~SandboxStatusExtension() = default; +@@ -46,6 +46,7 @@ void SandboxStatusExtension::Create(content::RenderFrame* frame) { + } + + void SandboxStatusExtension::OnDestruct() { ++ weak_ptr_factory_.InvalidateWeakPtrs(); + // This object is ref-counted, since a callback could still be in-flight. + Release(); + } +diff --git a/chrome/renderer/sandbox_status_extension_android.h b/chrome/renderer/sandbox_status_extension_android.h +--- a/chrome/renderer/sandbox_status_extension_android.h ++++ b/chrome/renderer/sandbox_status_extension_android.h +@@ -73,6 +73,7 @@ class SandboxStatusExtension + + mojo::AssociatedReceiver receiver_{ + this}; ++ base::WeakPtrFactory weak_ptr_factory_{this}; + }; + + #endif // CHROME_RENDERER_SANDBOX_STATUS_EXTENSION_ANDROID_H_ diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn