[Android] Initial integration of Brave adaptive buttons (#31303)

* [Android] Initial integration of Brave adaptive buttons

The Bookmarks button is the first in the list; the rest of the buttons will be added in separate PRs.

Important notes:
- override via `chromium_src` doesn't work for `patches/chrome-browser-ui-android-toolbar-adaptive_toolbar_enums.h.patch` since this file is parsed by `java_cpp_enum.py` to convert it to java enum
- patch to `java_cpp_enum.py` was added to be able to do 1 line patch, since upsteam parses each value as a separate line
- in `patches/chrome-browser-ui-android-toolbar-adaptive_toolbar_enums.h.patch` were added values for all planned Brave buttons to avoid additional patching for each consecutive PR

* Python patch optimisations

* Presubmit fixes

* Remove python patch in favour of multiline header patch
This commit is contained in:
samartnik
2025-09-22 10:33:12 -04:00
committed by GitHub
parent 63f401f757
commit a15ed443a5
21 changed files with 577 additions and 11 deletions
+35
View File
@@ -1030,3 +1030,38 @@
-keep class org.chromium.chrome.browser.download.home.search.BraveSearchBarCoordinator {
<init>(...);
}
-keep class org.chromium.chrome.browser.ui.AdaptiveToolbarUiCoordinator {
<init>(...);
}
-keep class org.chromium.chrome.browser.ui.BraveAdaptiveToolbarUiCoordinator {
<init>(...);
}
-keep class org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarStatePredictor {
*** isValidSegment(...);
}
-keep class org.chromium.chrome.browser.toolbar.adaptive.settings.RadioButtonGroupAdaptiveToolbarPreference {
*** mIsBound;
*** mAutoButton;
*** mNewTabButton;
*** mShareButton;
}
-keep class org.chromium.chrome.browser.ui.AdaptiveToolbarUiCoordinator {
*** mContext;
*** mActivityTabProvider;
*** mModalDialogManagerSupplier;
*** mProfileSupplier;
*** mAdaptiveToolbarButtonController;
}
-keep class org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarStatePredictor {
public <init>(...);
}
-keep class org.chromium.chrome.browser.toolbar.adaptive.BraveAdaptiveToolbarStatePredictor {
public <init>(...);
}
@@ -22,6 +22,7 @@ import org.chromium.chrome.browser.ActivityTabProvider;
import org.chromium.chrome.browser.app.BraveActivity;
import org.chromium.chrome.browser.back_press.BackPressManager;
import org.chromium.chrome.browser.bookmarks.BookmarkManagerOpener;
import org.chromium.chrome.browser.bookmarks.BookmarkManagerOpenerImpl;
import org.chromium.chrome.browser.bookmarks.BookmarkModel;
import org.chromium.chrome.browser.bookmarks.TabBookmarker;
import org.chromium.chrome.browser.compositor.CompositorViewHolder;
@@ -44,6 +45,7 @@ import org.chromium.chrome.browser.tab_ui.TabSwitcher;
import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.toolbar.ToolbarIntentMetadata;
import org.chromium.chrome.browser.ui.BraveAdaptiveToolbarUiCoordinator;
import org.chromium.chrome.browser.ui.appmenu.AppMenuBlocker;
import org.chromium.chrome.browser.ui.appmenu.AppMenuDelegate;
import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeController;
@@ -206,4 +208,16 @@ public class BraveTabbedRootUiCoordinator extends TabbedRootUiCoordinator {
hubManager.setStatusIndicatorHeight(bottomToolbarHeight);
});
}
@Override
protected void initializeToolbar() {
super.initializeToolbar();
assert mAdaptiveToolbarUiCoordinator instanceof BraveAdaptiveToolbarUiCoordinator
: "Bytecode change was not applied!";
if (mAdaptiveToolbarUiCoordinator
instanceof BraveAdaptiveToolbarUiCoordinator braveCoordinator) {
braveCoordinator.initializeBrave(new BookmarkManagerOpenerImpl());
}
}
}
@@ -0,0 +1,74 @@
/* Copyright (c) 2025 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.toolbar.adaptive;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.view.View;
import org.chromium.base.supplier.ObservableSupplier;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ActivityTabProvider;
import org.chromium.chrome.browser.bookmarks.BookmarkManagerOpener;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.toolbar.optional_button.BaseButtonDataProvider;
import org.chromium.ui.modaldialog.ModalDialogManager;
/** Handles displaying bookmarks button on toolbar. */
@NullMarked
public class BraveBookmarksButtonController extends BaseButtonDataProvider {
private final Context mContext;
private final ObservableSupplier<Profile> mProfileSupplier;
private final BookmarkManagerOpener mBookmarkManagerOpener;
public BraveBookmarksButtonController(
Context context,
Drawable buttonDrawable,
ActivityTabProvider tabProvider,
ObservableSupplier<Profile> profileSupplier,
ModalDialogManager modalDialogManager,
BookmarkManagerOpener bookmarkManagerOpener) {
super(
tabProvider,
modalDialogManager,
buttonDrawable,
context.getString(R.string.menu_bookmarks),
/* actionChipLabelResId= */ Resources.ID_NULL,
/* supportsTinting= */ true,
/* iphCommandBuilder= */ null,
AdaptiveToolbarButtonVariant.BOOKMARKS,
/* tooltipTextResId= */ R.string.menu_bookmarks);
mContext = context;
mProfileSupplier = profileSupplier;
mBookmarkManagerOpener = bookmarkManagerOpener;
}
@Override
public void onClick(View view) {
Profile profile = mProfileSupplier.get();
if (profile == null) return;
assert mContext instanceof Activity : "Context is not an Activity";
if (!(mContext instanceof Activity)) return;
mBookmarkManagerOpener.showBookmarkManager(
(Activity) mContext, mActiveTabSupplier.get(), profile, /* folderId= */ null);
}
@Override
protected boolean shouldShowButton(@Nullable Tab tab) {
if (!super.shouldShowButton(tab)) return false;
// Show the `Bookmarks` button for all tabs
return true;
}
}
@@ -0,0 +1,79 @@
/* Copyright (c) 2025 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.ui;
import android.content.Context;
import androidx.annotation.Nullable;
import androidx.appcompat.content.res.AppCompatResources;
import org.chromium.base.supplier.ObservableSupplier;
import org.chromium.base.supplier.Supplier;
import org.chromium.build.annotations.NullMarked;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ActivityTabProvider;
import org.chromium.chrome.browser.bookmarks.BookmarkManagerOpener;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonController;
import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonVariant;
import org.chromium.chrome.browser.toolbar.adaptive.BraveBookmarksButtonController;
import org.chromium.ui.modaldialog.ModalDialogManager;
/**
* Brave-specific coordinator for adaptive toolbar UI components. Extends the base
* AdaptiveToolbarUiCoordinator with Brave-specific functionality.
*/
@NullMarked
public class BraveAdaptiveToolbarUiCoordinator extends AdaptiveToolbarUiCoordinator {
// Variables below will be removed in bytecode, variables from the parent class will be used
// instead.
@Nullable private Context mContext;
@Nullable private ActivityTabProvider mActivityTabProvider;
@Nullable private Supplier<ModalDialogManager> mModalDialogManagerSupplier;
@Nullable private ObservableSupplier<Profile> mProfileSupplier;
@Nullable private AdaptiveToolbarButtonController mAdaptiveToolbarButtonController;
public BraveAdaptiveToolbarUiCoordinator(
Context context,
ActivityTabProvider activityTabProvider,
Supplier<ModalDialogManager> modalDialogManagerSupplier) {
super(context, activityTabProvider, modalDialogManagerSupplier);
}
/**
* Initialize Brave-specific adaptive toolbar components.
*
* @param bookmarkManagerOpener The bookmark manager opener for the `Bookmarks` button.
*/
public void initializeBrave(BookmarkManagerOpener bookmarkManagerOpener) {
assert mContext != null
&& mActivityTabProvider != null
&& mModalDialogManagerSupplier != null
&& mProfileSupplier != null
: "Bytecode changes were not applied!";
if (mContext == null
|| mActivityTabProvider == null
|| mModalDialogManagerSupplier == null
|| mProfileSupplier == null) {
return;
}
assert mAdaptiveToolbarButtonController != null
: "initializeBrave must be called after initialize!";
if (mAdaptiveToolbarButtonController == null) {
return;
}
var bookmarksButtonController =
new BraveBookmarksButtonController(
mContext,
AppCompatResources.getDrawable(mContext, R.drawable.brave_menu_bookmarks),
mActivityTabProvider,
mProfileSupplier,
mModalDialogManagerSupplier.get(),
bookmarkManagerOpener);
mAdaptiveToolbarButtonController.addButtonVariant(
AdaptiveToolbarButtonVariant.BOOKMARKS, bookmarksButtonController);
}
}