[Android] Shows Brave Wallet UI based on policy. (#33630)

* [Android] Shows Brave Wallet UI based on policy.

Resolves: https://github.com/brave/brave-browser/issues/52496
This commit is contained in:
Serg
2026-02-04 10:08:30 -05:00
committed by GitHub
parent bc36878601
commit 461d66e02c
19 changed files with 286 additions and 109 deletions
+1
View File
@@ -98,6 +98,7 @@ brave_java_sources = [
"../../brave/android/java/org/chromium/chrome/browser/crash/BravePureJavaExceptionReporter.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/AssetRatioServiceFactory.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/BlockchainRegistryFactory.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/BraveWalletPolicy.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/BraveWalletProviderDelegateImplHelper.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/BraveWalletServiceFactory.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/SwapServiceFactory.java",
+1
View File
@@ -351,6 +351,7 @@
}
-keep class org.chromium.chrome.browser.site_settings.ChromeSiteSettingsDelegate {
*** mProfile;
public <init>(...);
}
@@ -130,6 +130,7 @@ import org.chromium.chrome.browser.browsing_data.TimePeriod;
import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChrome;
import org.chromium.chrome.browser.crypto_wallet.AssetRatioServiceFactory;
import org.chromium.chrome.browser.crypto_wallet.BlockchainRegistryFactory;
import org.chromium.chrome.browser.crypto_wallet.BraveWalletPolicy;
import org.chromium.chrome.browser.crypto_wallet.BraveWalletServiceFactory;
import org.chromium.chrome.browser.crypto_wallet.SwapServiceFactory;
import org.chromium.chrome.browser.crypto_wallet.activities.AddAccountActivity;
@@ -770,13 +771,16 @@ public abstract class BraveActivity extends ChromeActivity
public void showWalletPanel(
final boolean showPendingTransactions, final boolean ignoreWeb3NotificationPreference) {
// Don't show wallet panel if disabled by policy or services not initialized
if (mKeyringService == null) {
return;
}
final BraveToolbarLayoutImpl layout = getBraveToolbarLayout();
layout.showWalletIcon(true);
if (!ignoreWeb3NotificationPreference
&& !BraveWalletPreferences.getPrefWeb3NotificationsEnabled()) {
return;
}
assert mKeyringService != null;
mKeyringService.isLocked(
locked -> {
if (locked) {
@@ -2052,6 +2056,10 @@ public abstract class BraveActivity extends ChromeActivity
}
public void setupWalletModel() {
// Don't setup wallet model if disabled by policy
if (BraveWalletPolicy.isDisabledByPolicy(mTabModelProfileSupplier.get())) {
return;
}
PostTask.postTask(
TaskTraits.UI_DEFAULT,
() -> {
@@ -2088,93 +2096,145 @@ public abstract class BraveActivity extends ChromeActivity
@MainThread
private void setupObservers() {
ThreadUtils.assertOnUiThread();
if (mWalletModel == null) {
return;
}
clearObservers();
mWalletModel.getCryptoModel().getPendingTxHelper().mSelectedPendingRequest.observe(
this, transactionInfo -> {
if (transactionInfo == null) {
return;
}
// don't show dapps panel if the wallet is locked and requests are being
// processed by the approve dialog already
mKeyringService.isLocked(locked -> {
if (locked) {
return;
}
mWalletModel
.getCryptoModel()
.getPendingTxHelper()
.mSelectedPendingRequest
.observe(
this,
transactionInfo -> {
if (transactionInfo == null) {
return;
}
// don't show dapps panel if the wallet is locked and requests are being
// processed by the approve dialog already
mKeyringService.isLocked(
locked -> {
if (locked) {
return;
}
if (!mIsProcessingPendingDappsTxRequest) {
mIsProcessingPendingDappsTxRequest = true;
openBraveWalletDAppsActivity(
BraveWalletDAppsActivity.ActivityType.CONFIRM_TRANSACTION);
}
if (!mIsProcessingPendingDappsTxRequest) {
mIsProcessingPendingDappsTxRequest = true;
openBraveWalletDAppsActivity(
BraveWalletDAppsActivity.ActivityType
.CONFIRM_TRANSACTION);
}
// update badge if there's a pending tx
updateWalletBadgeVisibility();
});
});
// update badge if there's a pending tx
updateWalletBadgeVisibility();
});
});
mWalletModel.getDappsModel().mWalletIconNotificationVisible.observe(
this, this::setWalletBadgeVisibility);
mWalletModel
.getDappsModel()
.mWalletIconNotificationVisible
.observe(this, this::setWalletBadgeVisibility);
mWalletModel.getDappsModel().mPendingWalletAccountCreationRequest.observe(this, request -> {
if (request == null) return;
mWalletModel.getKeyringModel().isWalletLocked(isLocked -> {
if (!BraveWalletPreferences.getPrefWeb3NotificationsEnabled()) return;
if (isLocked) {
Tab tab = getActivityTab();
if (tab != null) {
walletInteractionDetected(tab.getWebContents());
}
showWalletPanel(false);
return;
}
for (CryptoAccountTypeInfo info :
mWalletModel.getCryptoModel().getSupportedCryptoAccountTypes()) {
if (info.getCoinType() == request.getCoinType()) {
Intent intent = AddAccountActivity.createIntentToAddAccount(
this, info.getCoinType());
startActivity(intent);
mWalletModel.getDappsModel().removeProcessedAccountCreationRequest(request);
break;
}
}
});
});
mWalletModel.getCryptoModel().getNetworkModel().mNeedToCreateAccountForNetwork.observe(
this, networkInfo -> {
if (networkInfo == null) return;
MaterialAlertDialogBuilder builder =
new MaterialAlertDialogBuilder(
this, R.style.BraveWalletAlertDialogTheme)
.setMessage(getString(
R.string.brave_wallet_create_account_description,
networkInfo.symbolName))
.setPositiveButton(R.string.brave_action_yes,
(dialog, which) -> {
mWalletModel.createAccountAndSetDefaultNetwork(
networkInfo);
})
.setNegativeButton(
R.string.brave_action_no, (dialog, which) -> {
mWalletModel.getCryptoModel()
.getNetworkModel()
.clearCreateAccountState();
dialog.dismiss();
mWalletModel
.getDappsModel()
.mPendingWalletAccountCreationRequest
.observe(
this,
request -> {
if (request == null) return;
mWalletModel
.getKeyringModel()
.isWalletLocked(
isLocked -> {
if (!BraveWalletPreferences
.getPrefWeb3NotificationsEnabled()) {
return;
}
if (isLocked) {
Tab tab = getActivityTab();
if (tab != null) {
walletInteractionDetected(
tab.getWebContents());
}
showWalletPanel(false);
return;
}
for (CryptoAccountTypeInfo info :
mWalletModel
.getCryptoModel()
.getSupportedCryptoAccountTypes()) {
if (info.getCoinType()
== request.getCoinType()) {
Intent intent =
AddAccountActivity
.createIntentToAddAccount(
this,
info.getCoinType());
startActivity(intent);
mWalletModel
.getDappsModel()
.removeProcessedAccountCreationRequest( // presubmit: ignore-long-line
request);
break;
}
}
});
builder.show();
});
});
mWalletModel
.getCryptoModel()
.getNetworkModel()
.mNeedToCreateAccountForNetwork
.observe(
this,
networkInfo -> {
if (networkInfo == null) return;
MaterialAlertDialogBuilder builder =
new MaterialAlertDialogBuilder(
this, R.style.BraveWalletAlertDialogTheme)
.setMessage(
getString(
R.string
.brave_wallet_create_account_description, // presubmit: ignore-long-line
networkInfo.symbolName))
.setPositiveButton(
R.string.brave_action_yes,
(dialog, which) -> {
mWalletModel
.createAccountAndSetDefaultNetwork(
networkInfo);
})
.setNegativeButton(
R.string.brave_action_no,
(dialog, which) -> {
mWalletModel
.getCryptoModel()
.getNetworkModel()
.clearCreateAccountState();
dialog.dismiss();
});
builder.show();
});
}
@MainThread
private void clearObservers() {
ThreadUtils.assertOnUiThread();
mWalletModel.getCryptoModel().getPendingTxHelper().mSelectedPendingRequest.removeObservers(
this);
if (mWalletModel == null) {
return;
}
mWalletModel
.getCryptoModel()
.getPendingTxHelper()
.mSelectedPendingRequest
.removeObservers(this);
mWalletModel.getDappsModel().mWalletIconNotificationVisible.removeObservers(this);
mWalletModel.getCryptoModel()
mWalletModel
.getCryptoModel()
.getNetworkModel()
.mNeedToCreateAccountForNetwork.removeObservers(this);
.mNeedToCreateAccountForNetwork
.removeObservers(this);
}
private void showBraveRateDialog() {
@@ -2483,6 +2543,10 @@ public abstract class BraveActivity extends ChromeActivity
}
private void initWalletNativeServices() {
// Don't initialize wallet services if disabled by policy
if (BraveWalletPolicy.isDisabledByPolicy(mTabModelProfileSupplier.get())) {
return;
}
initBlockchainRegistry();
initTxService();
initEthTxManagerProxy();
@@ -0,0 +1,27 @@
/* Copyright (c) 2026 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
package org.chromium.chrome.browser.crypto_wallet;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
import org.chromium.chrome.browser.preferences.BravePref;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.components.prefs.PrefService;
import org.chromium.components.user_prefs.UserPrefs;
/** Provides policy state for Brave Wallet. */
@NullMarked
public class BraveWalletPolicy {
/** Returns true if Wallet is disabled by policy for the given profile. */
public static boolean isDisabledByPolicy(@Nullable Profile profile) {
if (profile == null) {
return false;
}
PrefService prefService = UserPrefs.get(profile);
return prefService.isManagedPreference(BravePref.BRAVE_WALLET_DISABLED_BY_POLICY)
&& prefService.getBoolean(BravePref.BRAVE_WALLET_DISABLED_BY_POLICY);
}
}
@@ -26,6 +26,7 @@ import org.chromium.chrome.browser.BraveFeatureUtil;
import org.chromium.chrome.browser.BraveLocalState;
import org.chromium.chrome.browser.BraveRelaunchUtils;
import org.chromium.chrome.browser.browsing_data.BraveClearBrowsingDataFragment;
import org.chromium.chrome.browser.crypto_wallet.BraveWalletPolicy;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.metrics.ChangeMetricsReportingStateCalledFrom;
import org.chromium.chrome.browser.metrics.UmaSessionStats;
@@ -473,6 +474,13 @@ public class BravePrivacySettings extends PrivacySettings {
removePreferenceIfPresent(PREF_PRIVACY_GUIDE);
removePreferenceIfPresent(PREF_PASSWORD_LEAK_DETECTION);
// Hide decentralized DNS settings when wallet is disabled by policy
if (BraveWalletPolicy.isDisabledByPolicy(getProfile())) {
removePreferenceIfPresent(PREF_UNSTOPPABLE_DOMAINS);
removePreferenceIfPresent(PREF_ENS);
removePreferenceIfPresent(PREF_SNS);
}
if (!ChromeFeatureList.isEnabled(BraveFeatureList.BRAVE_ANDROID_SAFE_BROWSING)) {
removePreferenceIfPresent(PREF_SAFE_BROWSING);
} else {
@@ -28,6 +28,7 @@ import org.chromium.chrome.browser.brave_leo.BraveLeoPrefUtils;
import org.chromium.chrome.browser.brave_news.BraveNewsPolicy;
import org.chromium.chrome.browser.brave_origin.BraveOriginPlansActivity;
import org.chromium.chrome.browser.brave_origin.BraveOriginSubscriptionPrefs;
import org.chromium.chrome.browser.crypto_wallet.BraveWalletPolicy;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.homepage.settings.BraveHomepageSettings;
import org.chromium.chrome.browser.notifications.BraveNotificationWarningDialog;
@@ -149,6 +150,7 @@ public abstract class BraveMainPreferencesBase extends BravePreferenceFragment
checkLeoPolicyAndUpdatePreference();
checkNewsPolicyAndUpdatePreference();
checkVpnPolicyAndUpdatePreference();
checkWalletPolicyAndUpdatePreference();
if (mNotificationClicked
&& BraveNotificationWarningDialog.shouldShowNotificationWarningDialog(getActivity())
@@ -630,4 +632,11 @@ public abstract class BraveMainPreferencesBase extends BravePreferenceFragment
removePreferenceIfPresent(PREF_BRAVE_VPN_CALLOUT);
}
}
/** Checks if Brave Wallet is disabled by policy and removes the preference if so. */
private void checkWalletPolicyAndUpdatePreference() {
if (BraveWalletPolicy.isDisabledByPolicy(getProfile())) {
removePreferenceIfPresent(PREF_BRAVE_WALLET);
}
}
}
@@ -9,15 +9,30 @@ import android.content.Context;
import android.graphics.drawable.Drawable;
import org.chromium.base.Callback;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
import org.chromium.chrome.browser.crypto_wallet.BraveWalletPolicy;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.components.browser_ui.site_settings.BraveWalletSiteSettingsDelegate;
import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory;
import org.chromium.url.GURL;
public class BraveSiteSettingsDelegate extends ChromeSiteSettingsDelegate {
@NullMarked
public class BraveSiteSettingsDelegate extends ChromeSiteSettingsDelegate
implements BraveWalletSiteSettingsDelegate {
// Will be deleted in bytecode, value from the parent class will be used instead.
@Nullable private Profile mProfile;
public BraveSiteSettingsDelegate(Context context, Profile profile) {
super(context, profile);
}
@Override
public boolean isWalletDisabledByPolicy() {
return BraveWalletPolicy.isDisabledByPolicy(mProfile);
}
@SuppressWarnings("NullAway")
@Override
public void getFaviconImageForURL(GURL faviconUrl, Callback<Drawable> callback) {
if (!faviconUrl.isValid()) {
@@ -38,6 +38,7 @@ import org.chromium.chrome.browser.app.appmenu.AppMenuIconRowFooter;
import org.chromium.chrome.browser.bookmarks.BookmarkModel;
import org.chromium.chrome.browser.brave_leo.BraveLeoPrefUtils;
import org.chromium.chrome.browser.brave_news.BraveNewsPolicy;
import org.chromium.chrome.browser.crypto_wallet.BraveWalletPolicy;
import org.chromium.chrome.browser.feed.webfeed.WebFeedSnackbarController;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.homepage.HomepageManager;
@@ -136,6 +137,16 @@ public class BraveTabbedAppMenuPropertiesDelegate extends TabbedAppMenuPropertie
*/
private List<PolicyControlledMenuItem> getPolicyControlledMenuItems() {
return Arrays.asList(
new PolicyControlledMenuItem(
R.id.brave_wallet_id,
this::buildBraveWalletItem,
() -> ChromeFeatureList.isEnabled(BraveFeatureList.NATIVE_BRAVE_WALLET),
() -> {
Tab tab = mActivityTabProvider.get();
return tab != null
&& BraveWalletPolicy.isDisabledByPolicy(tab.getProfile());
},
Arrays.asList(R.id.brave_leo_id, R.id.all_bookmarks_menu_id)),
new PolicyControlledMenuItem(
R.id.brave_leo_id,
this::buildBraveLeoItem,
@@ -636,10 +647,7 @@ public class BraveTabbedAppMenuPropertiesDelegate extends TabbedAppMenuPropertie
buildModelForStandardMenuItem(
R.id.recent_tabs_menu_id, R.string.menu_recent_tabs, 0)));
// Add Brave specific items.
if (ChromeFeatureList.isEnabled(BraveFeatureList.NATIVE_BRAVE_WALLET)) {
modelList.add(buildBraveWalletItem());
}
// Add Brave specific items (Wallet is handled by policy-controlled mechanism).
if (ChromeFeatureList.isEnabled(BraveFeatureList.BRAVE_PLAYLIST)) {
modelList.add(buildBravePlaylistItem());
modelList.add(buildBraveAddToPlaylistItem());
@@ -903,11 +911,7 @@ public class BraveTabbedAppMenuPropertiesDelegate extends TabbedAppMenuPropertie
}
}
// Add Brave specific items.
if (ChromeFeatureList.isEnabled(BraveFeatureList.NATIVE_BRAVE_WALLET)) {
addMenuItemAfter(
modelList, buildBraveWalletItem(), Arrays.asList(R.id.all_bookmarks_menu_id));
}
// Add Brave specific items (Wallet is handled by policy-controlled mechanism).
if (ChromeFeatureList.isEnabled(BraveFeatureList.BRAVE_PLAYLIST)
&& ChromeSharedPreferences.getInstance()
.readBoolean(BravePreferenceKeys.PREF_ENABLE_PLAYLIST, true)) {
@@ -58,6 +58,7 @@ import org.chromium.chrome.browser.BraveRewardsObserver;
import org.chromium.chrome.browser.BraveRewardsPolicy;
import org.chromium.chrome.browser.app.BraveActivity;
import org.chromium.chrome.browser.brave_stats.BraveStatsUtil;
import org.chromium.chrome.browser.crypto_wallet.BraveWalletPolicy;
import org.chromium.chrome.browser.crypto_wallet.controller.DAppsWalletController;
import org.chromium.chrome.browser.custom_layout.popup_window_tooltip.PopupWindowTooltip;
import org.chromium.chrome.browser.customtabs.FullScreenCustomTabActivity;
@@ -1125,7 +1126,7 @@ public abstract class BraveToolbarLayoutImpl extends ToolbarLayout
return;
}
}
if (show) {
if (show && !BraveWalletPolicy.isDisabledByPolicy(currentTab.getProfile())) {
mWalletLayout.setVisibility(View.VISIBLE);
mTabsWithWalletIcon.add(currentTab.getId());
} else {
@@ -2439,6 +2439,10 @@ public class BytecodeTest {
"mSite",
true,
Website.class));
Assert.assertTrue(
fieldExists(
"org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate",
"mProfile"));
Assert.assertTrue(
fieldExists(
"org/chromium/components/variations/firstrun/VariationsSeedFetcher",
@@ -411,6 +411,10 @@ public class BraveTabbedAppMenuPropertiesDelegateUnitTest {
when(mPrefService.isManagedPreference(BravePref.MANAGED_BRAVE_VPN_DISABLED))
.thenReturn(true);
when(mPrefService.getBoolean(BravePref.MANAGED_BRAVE_VPN_DISABLED)).thenReturn(true);
// Wallet: BRAVE_WALLET_DISABLED_BY_POLICY = true means disabled
when(mPrefService.isManagedPreference(BravePref.BRAVE_WALLET_DISABLED_BY_POLICY))
.thenReturn(true);
when(mPrefService.getBoolean(BravePref.BRAVE_WALLET_DISABLED_BY_POLICY)).thenReturn(true);
assertEquals(MenuGroup.PAGE_MENU, mTabbedAppMenuPropertiesDelegate.getMenuGroup());
MVCListAdapter.ModelList modelList = mTabbedAppMenuPropertiesDelegate.getMenuItems();
@@ -424,7 +428,7 @@ public class BraveTabbedAppMenuPropertiesDelegateUnitTest {
R.id.open_history_menu_id,
R.id.downloads_menu_id,
R.id.all_bookmarks_menu_id,
R.id.brave_wallet_id,
// R.id.brave_wallet_id is NOT included - disabled by policy
// R.id.brave_leo_id is NOT included - disabled by policy
// R.id.brave_rewards_id is NOT included - disabled by policy
R.id.recent_tabs_menu_id,
+1
View File
@@ -43,6 +43,7 @@ java_cpp_strings("java_pref_names_srcjar") {
"//brave/components/brave_rewards/core/pref_names.h",
"//brave/components/brave_shields/core/common/pref_names.h",
"//brave/components/brave_vpn/common/pref_names.h",
"//brave/components/brave_wallet/browser/pref_names.h",
"//brave/components/constants/pref_names.h",
"//brave/components/de_amp/common/pref_names.cc",
"//brave/components/de_amp/common/pref_names.h",
@@ -471,16 +471,18 @@ TEST_F(DecentralizedDnsNetworkDelegateHelperTest,
int result = OnBeforeURLRequest_DecentralizedDnsPreRedirectWork(
base::DoNothing(), brave_request_info);
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
// On desktop platforms, policy is enforced, so wallet is disabled
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \
BUILDFLAG(IS_ANDROID)
// On desktop and Android platforms, policy is enforced, so wallet is disabled
// Should return OK immediately (not pending) because wallet is disabled
EXPECT_EQ(net::OK, result);
EXPECT_TRUE(brave_request_info->new_url_spec.empty());
#else
// On mobile platforms, policy is not enforced, so wallet is always enabled
// On other platforms, policy is not enforced, so wallet is always enabled
// Should return ERR_IO_PENDING because it will try to resolve the domain
EXPECT_EQ(net::ERR_IO_PENDING, result);
#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) ||
// BUILDFLAG(IS_ANDROID)
}
// Test that decentralized DNS works when BraveWalletDisabled policy is false
@@ -9,12 +9,18 @@ import org.objectweb.asm.ClassVisitor;
public class BraveSiteSettingsDelegateClassAdapter extends BraveClassVisitor {
static String sChromeSiteSettingsDelegateClassName = "org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate";
static String sBraveSiteSettingsDelegateClassName = "org/chromium/chrome/browser/site_settings/BraveSiteSettingsDelegate";
static String sChromeSiteSettingsDelegateClassName =
"org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate";
static String sBraveSiteSettingsDelegateClassName =
"org/chromium/chrome/browser/site_settings/BraveSiteSettingsDelegate";
public BraveSiteSettingsDelegateClassAdapter(ClassVisitor visitor) {
super(visitor);
redirectConstructor(sChromeSiteSettingsDelegateClassName, sBraveSiteSettingsDelegateClassName);
redirectConstructor(
sChromeSiteSettingsDelegateClassName, sBraveSiteSettingsDelegateClassName);
deleteField(sBraveSiteSettingsDelegateClassName, "mProfile");
makeProtectedField(sChromeSiteSettingsDelegateClassName, "mProfile");
}
}
@@ -49,13 +49,9 @@ namespace {
constexpr size_t kCardanoScriptHashSize = 28u;
bool IsDisabledByPolicy(PrefService* prefs) {
#if BUILDFLAG(IS_ANDROID)
return false;
#else
DCHECK(prefs);
return prefs->IsManagedPreference(kBraveWalletDisabledByPolicy) &&
prefs->GetBoolean(kBraveWalletDisabledByPolicy);
#endif
}
constexpr const char kEnsRegistryContractAddress[] =
@@ -1016,13 +1016,8 @@ TEST_F(BraveWalletPolicyTest, PolicyDisablesWallet) {
// Test that the policy preference is set correctly
EXPECT_TRUE(prefs_.GetBoolean(kBraveWalletDisabledByPolicy));
#if BUILDFLAG(IS_ANDROID)
// On android the policy is not enforced
EXPECT_TRUE(IsAllowed(&prefs_));
#else
// On other platforms, policy should be enforced
// Policy should be enforced
EXPECT_FALSE(IsAllowed(&prefs_));
#endif // BUILDFLAG(IS_ANDROID)
}
TEST_F(BraveWalletPolicyTest, PolicyEnablesWallet) {
@@ -12,6 +12,7 @@ android_library("java") {
"java/src/org/chromium/components/browser_ui/site_settings/BraveSingleWebsiteSettings.java",
"java/src/org/chromium/components/browser_ui/site_settings/BraveSiteSettingsCategory.java",
"java/src/org/chromium/components/browser_ui/site_settings/BraveSiteSettingsPreferencesBase.java",
"java/src/org/chromium/components/browser_ui/site_settings/BraveWalletSiteSettingsDelegate.java",
"java/src/org/chromium/components/browser_ui/site_settings/BraveWebsite.java",
"java/src/org/chromium/components/browser_ui/site_settings/BraveWebsitePermissionsFetcher.java",
]
@@ -19,6 +19,7 @@ public class BraveSiteSettingsPreferencesBase extends BaseSiteSettingsFragment {
private static final String IDLE_DETECTION = "idle_detection";
private static final String DIVIDER_KEY = "divider";
private static final String PERMISSION_AUTOREVOCATION_KEY = "permission_autorevocation";
private static final String ETHEREUM_CONNECTED_SITES_KEY = "ethereum_connected_sites";
private static final String SOLANA_CONNECTED_SITES_KEY = "solana_connected_sites";
private final HashMap<String, Preference> mRemovedPreferences = new HashMap<>();
@@ -67,6 +68,12 @@ public class BraveSiteSettingsPreferencesBase extends BaseSiteSettingsFragment {
removePreferenceIfPresent(ADS_KEY);
removePreferenceIfPresent(BACKGROUND_SYNC_KEY);
// Hide Ethereum and Solana connected sites when wallet is disabled by policy.
if (isWalletDisabledByPolicy()) {
removePreferenceIfPresent(ETHEREUM_CONNECTED_SITES_KEY);
removePreferenceIfPresent(SOLANA_CONNECTED_SITES_KEY);
}
// We want to place these Settings at the bottom.
// See https://github.com/brave/brave-browser/issues/46547
// for the context
@@ -78,11 +85,23 @@ public class BraveSiteSettingsPreferencesBase extends BaseSiteSettingsFragment {
if (prefDivider != null && prefPermissionAutorevocation != null) {
Preference prefSolanaConnectedSites =
getPreferenceScreen().findPreference(SOLANA_CONNECTED_SITES_KEY);
assert prefSolanaConnectedSites != null
: "Adjust if needed for the last pref in the site settings screen";
int solanaConnectedSitesOrder = prefSolanaConnectedSites.getOrder();
prefDivider.setOrder(solanaConnectedSitesOrder + 1);
prefPermissionAutorevocation.setOrder(solanaConnectedSitesOrder + 2);
// Solana preference may be removed if wallet is disabled by policy.
if (prefSolanaConnectedSites != null) {
int solanaConnectedSitesOrder = prefSolanaConnectedSites.getOrder();
prefDivider.setOrder(solanaConnectedSitesOrder + 1);
prefPermissionAutorevocation.setOrder(solanaConnectedSitesOrder + 2);
}
}
}
private boolean isWalletDisabledByPolicy() {
if (!hasSiteSettingsDelegate()) {
return false;
}
SiteSettingsDelegate delegate = getSiteSettingsDelegate();
if (delegate instanceof BraveWalletSiteSettingsDelegate) {
return ((BraveWalletSiteSettingsDelegate) delegate).isWalletDisabledByPolicy();
}
return false;
}
}
@@ -0,0 +1,19 @@
/* Copyright (c) 2026 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
package org.chromium.components.browser_ui.site_settings;
import org.chromium.build.annotations.NullMarked;
/**
* Interface for wallet-related site settings delegate methods. Implemented by
* BraveSiteSettingsDelegate to provide wallet policy information to components-level code without
* creating layering violations.
*/
@NullMarked
public interface BraveWalletSiteSettingsDelegate {
/** Returns true if Brave Wallet is disabled by enterprise policy. */
boolean isWalletDisabledByPolicy();
}