Files
cef/patch/patches/chrome_runtime_views.patch
T
Marshall Greenblatt 33624e6bc2 Update to Chromium version 154.0.8037.0
- Windows SDK 10.0.28000.2270 is now required
- CefRegisterExtension is deprecated due to https://crbug.com/40347662
2026-09-06 13:10:22 -04:00

1150 lines
48 KiB
Diff

diff --git chrome/browser/ui/browser_command_controller.cc chrome/browser/ui/browser_command_controller.cc
index e366925102783c4ec00f5ef2366b694b30b9eee9..64d398146853a6d0337a872b7dc0684165d1f85d 100644
--- chrome/browser/ui/browser_command_controller.cc
+++ chrome/browser/ui/browser_command_controller.cc
@@ -188,6 +188,10 @@
#include "chrome/browser/ui/shortcuts/desktop_shortcuts_utils.h"
#endif // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN)
+#if BUILDFLAG(ENABLE_CEF)
+#include "cef/libcef/browser/chrome/browser_util.h"
+#endif
+
static_assert(BUILDFLAG(ENABLE_EXTENSIONS));
using Extension = extensions::Extension;
@@ -543,6 +547,12 @@ void BrowserCommandController::ContentRestrictionsChanged() {
void BrowserCommandController::FullscreenStateChanged() {
UpdateCommandsForFullscreenMode();
+
+#if BUILDFLAG(ENABLE_CEF)
+ if (browser_->cef_delegate()) {
+ browser_->cef_delegate()->WindowFullscreenStateChanged();
+ }
+#endif
}
#if BUILDFLAG(IS_CHROMEOS)
@@ -634,6 +644,7 @@ bool BrowserCommandController::ExecuteCommandWithDispositionAndContext(
std::optional<actions::ActionInvocationContext> context,
base::TimeTicks time_stamp) {
if (!SupportsCommand(id) || !IsCommandEnabled(id)) {
+ LOG(WARNING) << "Invalid/disabled command " << id;
return false;
}
@@ -660,6 +671,13 @@ void BrowserCommandController::HandleCommandWithDisposition(
base::TimeTicks time_stamp) {
DCHECK(IsCommandEnabled(id)) << "Invalid/disabled command " << id;
+#if BUILDFLAG(ENABLE_CEF)
+ if (browser_->cef_delegate() &&
+ browser_->cef_delegate()->HandleCommand(id, disposition)) {
+ return;
+ }
+#endif
+
// The order of commands in this switch statement must match the function
// declaration order in browser.h!
switch (id) {
@@ -1702,12 +1720,14 @@ void BrowserCommandController::TabRestoreServiceLoaded(
bool BrowserCommandController::IsShowingMainUI() {
return WindowFeatureController::From(browser_)->SupportsWindowFeature(
- WindowFeatureController::WindowFeature::kFeatureTabStrip);
+ WindowFeatureController::WindowFeature::kFeatureTabStrip) ||
+ cef::BrowserForBWI(browser_)->toolbar_overridden();
}
bool BrowserCommandController::IsShowingLocationBar() {
return WindowFeatureController::From(browser_)->SupportsWindowFeature(
- WindowFeatureController::WindowFeature::kFeatureLocationBar);
+ WindowFeatureController::WindowFeature::kFeatureLocationBar) ||
+ cef::BrowserForBWI(browser_)->toolbar_overridden();
}
void BrowserCommandController::InitCommandState() {
diff --git chrome/browser/ui/toolbar/app_menu_model.cc chrome/browser/ui/toolbar/app_menu_model.cc
index 45cd05f34337285d387d617a160c84bc32904fd1..2a5b8dfd7036a568503b588e27801d8d21ded256 100644
--- chrome/browser/ui/toolbar/app_menu_model.cc
+++ chrome/browser/ui/toolbar/app_menu_model.cc
@@ -934,18 +934,20 @@ FindAndEditSubMenuModel::FindAndEditSubMenuModel(
AddItemWithStringIdAndVectorIcon(
this, IDC_FIND, IDS_FIND,
features::IsRoundedIconsEnabled() ? kFindInPageIcon : kSearchMenuOldIcon);
- AddSeparator(ui::NORMAL_SEPARATOR);
- AddItemWithStringIdAndVectorIcon(
- this, IDC_CUT, IDS_CUT,
- features::IsRoundedIconsEnabled() ? kContentCutIcon : kCutMenuOldIcon);
- AddItemWithStringIdAndVectorIcon(this, IDC_COPY, IDS_COPY,
- features::IsRoundedIconsEnabled()
- ? vector_icons::kContentCopyIcon
- : kCopyMenuOldIcon);
- AddItemWithStringIdAndVectorIcon(this, IDC_PASTE, IDS_PASTE,
- features::IsRoundedIconsEnabled()
- ? kContentPasteIcon
- : kPasteMenuOldIcon);
+ if (delegate->IsCommandIdVisible(AppMenuModel::kEditMenuPlaceholder)) {
+ AddSeparator(ui::NORMAL_SEPARATOR);
+ AddItemWithStringIdAndVectorIcon(
+ this, IDC_CUT, IDS_CUT,
+ features::IsRoundedIconsEnabled() ? kContentCutIcon : kCutMenuOldIcon);
+ AddItemWithStringIdAndVectorIcon(this, IDC_COPY, IDS_COPY,
+ features::IsRoundedIconsEnabled()
+ ? vector_icons::kContentCopyIcon
+ : kCopyMenuOldIcon);
+ AddItemWithStringIdAndVectorIcon(this, IDC_PASTE, IDS_PASTE,
+ features::IsRoundedIconsEnabled()
+ ? kContentPasteIcon
+ : kPasteMenuOldIcon);
+ }
}
class SaveAndShareSubMenuModel : public ui::SimpleMenuModel {
@@ -1087,6 +1089,57 @@ bool ArePromotionsEnabled() {
return local_state && local_state->GetBoolean(prefs::kPromotionsEnabled);
}
+#if BUILDFLAG(ENABLE_CEF)
+using IsVisibleCallback = base::RepeatingCallback<bool(int)>;
+
+void FilterMenuModel(ui::SimpleMenuModel* model,
+ const IsVisibleCallback& is_visible) {
+ std::optional<size_t> last_separator;
+ size_t visible_ct = 0;
+ for (size_t i = 0; i < model->GetItemCount(); ++i) {
+ const auto type = model->GetTypeAt(i);
+ if (type == ui::MenuModel::TYPE_SEPARATOR) {
+ if (last_separator) {
+ // Remove multiple separators in a row. Prefer to remove a NORMAL
+ // separator if possible (as compared to zoom/edit controls which use
+ // UPPER/LOWER separators).
+ if (model->GetSeparatorTypeAt(*last_separator) ==
+ ui::NORMAL_SEPARATOR) {
+ model->RemoveItemAt(*last_separator);
+ i--;
+ last_separator = i;
+ } else {
+ model->RemoveItemAt(i);
+ i--;
+ }
+ } else if (visible_ct == 0) {
+ // Remove leading separator.
+ model->RemoveItemAt(i);
+ i--;
+ } else {
+ last_separator = i;
+ }
+ visible_ct = 0;
+ } else if (is_visible.Run(model->GetCommandIdAt(i))) {
+ last_separator = std::nullopt;
+ visible_ct++;
+
+ if (type == ui::MenuModel::TYPE_SUBMENU) {
+ // Filter sub-menu.
+ auto sub_model =
+ static_cast<ui::SimpleMenuModel*>(model->GetSubmenuModelAt(i));
+ FilterMenuModel(sub_model, is_visible);
+ }
+ }
+ }
+
+ if (last_separator) {
+ // Remove trailing separator.
+ model->RemoveItemAt(*last_separator);
+ }
+}
+#endif // BUILDFLAG(ENABLE_CEF)
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -2132,7 +2185,7 @@ bool AppMenuModel::IsCommandIdChecked(int command_id) const {
return false;
}
-bool AppMenuModel::IsCommandIdEnabled(int command_id) const {
+bool AppMenuModel::IsCommandIdEnabledInternal(int command_id) const {
GlobalError* error =
GlobalErrorServiceFactory::GetForProfile(browser_->GetProfile())
->GetGlobalErrorByMenuItemCommandID(command_id);
@@ -2148,6 +2201,30 @@ bool AppMenuModel::IsCommandIdEnabled(int command_id) const {
}
}
+bool AppMenuModel::IsCommandIdEnabled(int command_id) const {
+ if (!IsCommandIdEnabledInternal(command_id)) {
+ return false;
+ }
+
+#if BUILDFLAG(ENABLE_CEF)
+ if (browser_->cef_delegate()) {
+ return browser_->cef_delegate()->IsAppMenuItemEnabled(command_id);
+ }
+#endif
+
+ return true;
+}
+
+bool AppMenuModel::IsCommandIdVisible(int command_id) const {
+#if BUILDFLAG(ENABLE_CEF)
+ if (browser_->cef_delegate()) {
+ return browser_->cef_delegate()->IsAppMenuItemVisible(command_id);
+ }
+#endif
+
+ return true;
+}
+
bool AppMenuModel::IsCommandIdAlerted(int command_id) const {
if (command_id == IDC_VIEW_PASSWORDS ||
command_id == IDC_SHOW_PASSWORD_MANAGER) {
@@ -2373,8 +2450,10 @@ void AppMenuModel::Build() {
SetElementIdentifierAt(GetIndexOfCommandId(IDC_CLEAR_BROWSING_DATA).value(),
kClearBrowsingDataMenuItem);
- AddSeparator(ui::NORMAL_SEPARATOR);
- CreateZoomMenu();
+ if (IsCommandIdVisible(AppMenuModel::kZoomMenuPlaceholder)) {
+ AddSeparator(ui::NORMAL_SEPARATOR);
+ CreateZoomMenu();
+ }
AddSeparator(ui::NORMAL_SEPARATOR);
AddItemWithStringIdAndVectorIcon(
@@ -2512,6 +2591,11 @@ void AppMenuModel::Build() {
}
#endif // !BUILDFLAG(IS_CHROMEOS)
+#if BUILDFLAG(ENABLE_CEF)
+ FilterMenuModel(this, base::BindRepeating(&AppMenuModel::IsCommandIdVisible,
+ base::Unretained(this)));
+#endif
+
uma_action_recorded_ = false;
}
diff --git chrome/browser/ui/toolbar/app_menu_model.h chrome/browser/ui/toolbar/app_menu_model.h
index ed3f1fa50b5887ae407c928715bf3ff68d1a156c..30a9d221bfe22b71b239da72ee576e55c1707b76 100644
--- chrome/browser/ui/toolbar/app_menu_model.h
+++ chrome/browser/ui/toolbar/app_menu_model.h
@@ -283,6 +283,7 @@ class AppMenuModel : public ui::SimpleMenuModel,
void ExecuteCommand(int command_id, int event_flags) override;
bool IsCommandIdChecked(int command_id) const override;
bool IsCommandIdEnabled(int command_id) const override;
+ bool IsCommandIdVisible(int command_id) const override;
bool IsCommandIdAlerted(int command_id) const override;
bool GetAcceleratorForCommandId(int command_id,
ui::Accelerator* accelerator) const override;
@@ -322,6 +323,8 @@ class AppMenuModel : public ui::SimpleMenuModel,
void LogSafetyHubInteractionMetrics(safety_hub::SafetyHubModuleType sh_module,
int event_flags);
+ bool IsCommandIdEnabledInternal(int command_id) const;
+
private:
// Adds actionable global error menu items to the menu.
// Examples: Extension permissions and sign in errors.
diff --git chrome/browser/ui/views/frame/browser_view.cc chrome/browser/ui/views/frame/browser_view.cc
index 24eca1ab9a2ab4b2cbf533e59bf290d8309ba898..4f405cfa2f2fd33ac6797801c6f81af311e19523 100644
--- chrome/browser/ui/views/frame/browser_view.cc
+++ chrome/browser/ui/views/frame/browser_view.cc
@@ -411,6 +411,10 @@
#undef LoadAccelerators
#endif
+#if BUILDFLAG(ENABLE_CEF)
+#include "cef/libcef/browser/chrome/browser_util.h"
+#endif
+
using base::UserMetricsAction;
using content::WebContents;
using input::NativeWebKeyboardEvent;
@@ -882,11 +886,21 @@ class BrowserView::PipExclusionObserverImpl
///////////////////////////////////////////////////////////////////////////////
// BrowserView, public:
+BrowserView::BrowserView() : BrowserView(nullptr) {}
+
BrowserView::BrowserView(BrowserWindowInterface* browser)
: views::ClientView(nullptr, nullptr),
exclusive_access_context_(
- std::make_unique<ExclusiveAccessContextImpl>(*this)),
- browser_(browser) {
+ std::make_unique<ExclusiveAccessContextImpl>(*this)) {
+ if (browser) {
+ InitBrowser(browser);
+ }
+}
+
+void BrowserView::InitBrowser(BrowserWindowInterface* browser) {
+ DCHECK(!browser_);
+ browser_ = browser;
+
if (auto* manager = InitialWebUIWindowMetricsManager::From(browser_.get())) {
manager->OnBrowserWindowCreated();
}
@@ -905,7 +919,8 @@ BrowserView::BrowserView(BrowserWindowInterface* browser)
SetCanMinimize(false);
SetCanMaximize(false);
SetCanFullscreen(false);
- SetCanResize(true);
+ SetCanResize(
+ BrowserInitState::From(&*browser_)->create_params().can_resize);
} else {
SetCanResize(
BrowserInitState::From(&*browser_)->create_params().can_resize);
@@ -929,8 +944,16 @@ BrowserView::BrowserView(BrowserWindowInterface* browser)
top_container_ = AddChildView(std::make_unique<TopContainerView>(this));
top_container_insertion_index_ = GetIndexOf(top_container_.get());
- toolbar_ = top_container_->AddChildView(
- std::make_unique<ToolbarView>(browser_.get(), this));
+ toolbar_ = OverrideCreateToolbar();
+ if (!toolbar_) {
+ toolbar_ = new ToolbarView(browser_.get(), this, std::nullopt);
+ } else {
+ cef::BrowserForBWI(browser_.get())->set_toolbar_overridden(true);
+ // Update state that depends on the above flag.
+ chrome::BrowserCommandController::From(browser_.get())
+ ->FullscreenStateChanged();
+ }
+ top_container_->AddChildView(base::WrapUnique(toolbar_.get()));
top_container_separator_ = top_container_->AddChildView(
ContentsSeparator::CreateContentsSeparator());
@@ -1093,6 +1116,10 @@ BrowserView::BrowserView(BrowserWindowInterface* browser)
}
BrowserView::~BrowserView() {
+ // If the Toolbar is not overloaded it will be destroyed via
+ // RemoveAllChildViews().
+ WillDestroyToolbar();
+
// Remove the layout manager to avoid dangling. This needs to be earlier than
// other cleanups that destroy views referenced in the layout manager.
SetLayoutManager(nullptr);
@@ -1105,7 +1132,9 @@ BrowserView::~BrowserView() {
// All the tabs should have been destroyed already. If we were closed by the
// OS with some tabs than the BrowserNativeWidget should have destroyed them.
- DCHECK_EQ(0, browser_->GetTabStripModel()->count());
+ if (browser_) {
+ DCHECK_EQ(0, browser_->GetTabStripModel()->count());
+ }
// Stop the animation timer explicitly here to avoid running it in a nested
// message loop, which may run by Browser destructor.
@@ -1204,7 +1233,7 @@ void BrowserView::SetDisableRevealerDelayForTesting(bool disable) {
g_disable_revealer_delay_for_testing = disable;
}
-gfx::Rect BrowserView::GetFindBarBoundingBox() const {
+gfx::Rect BrowserView::GetFindBarBoundingBoxImpl() const {
gfx::Rect contents_bounds = multi_contents_view_->ConvertRectToWidget(
multi_contents_view_->GetLocalBounds());
@@ -1226,6 +1255,16 @@ gfx::Rect BrowserView::GetFindBarBoundingBox() const {
return multi_contents_view_->GetMirroredRect(contents_bounds);
}
+gfx::Rect BrowserView::GetFindBarBoundingBox() const {
+ auto bounds = GetFindBarBoundingBoxImpl();
+#if BUILDFLAG(ENABLE_CEF)
+ if (browser() && browser()->cef_delegate()) {
+ browser()->cef_delegate()->UpdateFindBarBoundingBox(&bounds);
+ }
+#endif
+ return bounds;
+}
+
ClientFrameElementInfo BrowserView::GetFrameElementInfo() const {
// We want to return tabstrip_->height(), but we might be called in the midst
// of layout, when that hasn't yet been updated to reflect the current state.
@@ -1955,6 +1994,27 @@ gfx::Point BrowserView::GetThemeOffsetFromBrowserView() const {
ThemeProperties::kFrameHeightAboveTabs - browser_view_origin.y());
}
+void BrowserView::WillDestroyToolbar() {
+ // Reset autofill bubble handler to make sure it does not out-live toolbar,
+ // since it is responsible for showing autofill related bubbles from toolbar's
+ // child views and it is an observer for avatar toolbar button if any.
+ autofill_bubble_handler_.reset();
+
+ if (GetBrowserViewLayout()) {
+ GetBrowserViewLayout()->reset_toolbar();
+ }
+
+ if (toolbar_ && toolbar_->parent()) {
+ // Remove now instead of waiting for RemoveAllChildViews(), as there is
+ // otherwise no guarantee that the Toolbar will be removed before the
+ // BrowserView is removed (and destroyed).
+ toolbar_->parent()->RemoveChildView(toolbar_);
+ toolbar_.ClearAndDelete();
+ } else {
+ toolbar_ = nullptr;
+ }
+}
+
bool BrowserView::IsLoadingAnimationRunning() const {
return !loading_animation_start_.is_null();
}
@@ -3154,6 +3214,9 @@ ShowTranslateBubbleResult BrowserView::ShowTranslateBubble(
DownloadBubbleUIController* BrowserView::GetDownloadBubbleUIController() {
#if !BUILDFLAG(IS_CHROMEOS)
+ if (!browser_) {
+ return nullptr;
+ }
if (auto* download_controller =
DownloadToolbarUIController::From(browser_.get())) {
return download_controller->bubble_controller();
@@ -4072,7 +4135,10 @@ bool BrowserView::GetSavedWindowPlacement(
}
views::View* BrowserView::GetContentsView() {
- return multi_contents_view_->GetActiveContentsView();
+ if (multi_contents_view_) {
+ return multi_contents_view_->GetActiveContentsView();
+ }
+ return nullptr;
}
views::ClientView* BrowserView::CreateClientView(views::Widget* widget) {
@@ -4238,9 +4304,22 @@ void BrowserView::DeleteBrowserWindow() {
// before the frame is destroyed to mitigate UAF risk.
browser_widget_->SaveWindowPlacementIfNeeded();
- browser_widget_.reset();
- // BrowserWidget owns BrowserView in its views::View hierarchy and `this` will
- // not be valid after this returns.
+ const bool views_hosted =
+#if BUILDFLAG(ENABLE_CEF)
+ browser() && browser()->cef_delegate() &&
+ browser()->cef_delegate()->IsViewsHosted();
+#else
+ false;
+#endif
+
+ if (views_hosted) {
+ // The BrowserWidget is owned by CefWindowWidgetDelegate.
+ browser_widget_.release();
+ } else {
+ browser_widget_.reset();
+ // BrowserWidget owns BrowserView in its views::View hierarchy and `this`
+ // will not be valid after this returns.
+ }
}
void BrowserView::SetForceShowBookmarkBarFlag(
@@ -4501,12 +4580,39 @@ void BrowserView::GetAccessiblePanes(std::vector<views::View*>* panes) {
bool BrowserView::ShouldDescendIntoChildForEventHandling(
gfx::NativeView child,
const gfx::Point& location) {
+#if BUILDFLAG(ENABLE_CEF)
+ const bool frameless_pip =
+ GetIsPictureInPictureType() &&
+ !WindowFeatureController::From(browser_.get())
+ ->SupportsWindowFeature(
+ WindowFeatureController::WindowFeature::kFeatureTitleBar);
+ if (frameless_pip) {
+ int result = GetFrameView()->NonClientHitTest(location);
+ if (result == HTTOP || result == HTTOPLEFT || result == HTTOPRIGHT) {
+ // Allow resize from the top of a frameless window.
+ return false;
+ }
+ }
+#endif
+
+ std::optional<SkRegion> draggable_region;
+
// Window for PWAs with window-controls-overlay display override should claim
// mouse events that fall within the draggable region.
web_app::AppBrowserController* controller =
web_app::AppBrowserController::From(browser());
- if (AreDraggableRegionsEnabled() && controller &&
- controller->draggable_region().has_value()) {
+ if (AreDraggableRegionsEnabled() && controller) {
+ draggable_region = controller->draggable_region();
+ }
+
+#if BUILDFLAG(ENABLE_CEF)
+ // Match logic in PictureInPictureBrowserFrameView::NonClientHitTest.
+ if (!draggable_region.has_value() && frameless_pip) {
+ draggable_region = browser_->cef_delegate()->GetDraggableRegion();
+ }
+#endif
+
+ if (draggable_region.has_value()) {
// Draggable regions are defined relative to the web contents.
gfx::Point point_in_contents_web_view_coords(location);
views::View::ConvertPointToTarget(GetWidget()->GetRootView(),
@@ -4515,9 +4621,8 @@ bool BrowserView::ShouldDescendIntoChildForEventHandling(
// Draggable regions should be ignored for clicks into any browser view's
// owned widgets, for example alerts, permission prompts or find bar.
- return !controller->draggable_region()->contains(
- point_in_contents_web_view_coords.x(),
- point_in_contents_web_view_coords.y()) ||
+ return !draggable_region->contains(point_in_contents_web_view_coords.x(),
+ point_in_contents_web_view_coords.y()) ||
WidgetOwnedByAnchorContainsPoint(point_in_contents_web_view_coords);
}
@@ -4838,7 +4943,9 @@ void BrowserView::Layout(PassKey) {
LayoutSuperclass<views::View>(this);
// TODO(jamescook): Why was this in the middle of layout code?
- toolbar_->location_bar()->UpdateFocusBehavior(IsToolbarVisible());
+ toolbar_->location_bar()->UpdateFocusBehavior(
+ IsToolbarVisible() ||
+ cef::BrowserForBWI(browser_.get())->toolbar_overridden());
GetFrameView()->UpdateMinimumSize();
if (omnibox::IsWebUIOmniboxInBrowserViewEnabled()) {
@@ -5127,6 +5234,16 @@ void BrowserView::AddedToWidget() {
fallback_popup_anchor_ = std::make_unique<views::ViewSubregionAnchor>(
kFallbackPopupAnchorElementId, *this);
+ if (browser_->GetWindow()) {
+ // Initialize the browser features that rely on the browser window now that
+ // it is initialized. This will instead be called from the Browser
+ // constructor for default Chrome UI windows.
+ // TODO(cef): Remove BrowserForBWI cast once InitPostWindowConstruction
+ // takes BrowserWindowInterface* (upstream change pending).
+ browser_->GetFeatures().InitPostWindowConstruction(
+ cef::BrowserForBWI(browser_.get()));
+ }
+
initialized_ = true;
}
diff --git chrome/browser/ui/views/frame/browser_view.h chrome/browser/ui/views/frame/browser_view.h
index 38dae976bf310759751a0a42880317717acdcfcf..919aa21dc0e68a7cfcb7b16be4cc76e7b1002c4e 100644
--- chrome/browser/ui/views/frame/browser_view.h
+++ chrome/browser/ui/views/frame/browser_view.h
@@ -145,7 +145,9 @@ class BrowserView : public BrowserWindow,
// locate this object using just the handle.
static constexpr char kBrowserViewKey[] = "__BROWSER_VIEW__";
+ BrowserView();
explicit BrowserView(BrowserWindowInterface* browser);
+ void InitBrowser(BrowserWindowInterface* browser);
BrowserView(const BrowserView&) = delete;
BrowserView& operator=(const BrowserView&) = delete;
~BrowserView() override;
@@ -802,10 +804,16 @@ class BrowserView : public BrowserWindow,
bool IsLockedFullscreen() const;
#endif
- protected:
+ // Called during Toolbar destruction to remove dependent objects that have
+ // dangling references.
+ virtual void WillDestroyToolbar();
+
// BrowserWindow:
void DeleteBrowserWindow() final;
+ protected:
+ virtual ToolbarView* OverrideCreateToolbar() { return nullptr; }
+
private:
// Do not friend BrowserViewLayout. Use the BrowserViewLayoutDelegate
// interface to keep these two classes decoupled and testable.
@@ -1074,11 +1082,13 @@ class BrowserView : public BrowserWindow,
class ExclusiveAccessContextImpl;
std::unique_ptr<ExclusiveAccessContextImpl> exclusive_access_context_;
+ gfx::Rect GetFindBarBoundingBoxImpl() const;
+
// The BrowserWidget that owns this view.
std::unique_ptr<BrowserWidget> browser_widget_;
// The owning BrowserWindowInterface object. `browser_` will outlive this.
- const raw_ptr<BrowserWindowInterface> browser_;
+ raw_ptr<BrowserWindowInterface> browser_;
base::CallbackListSubscription chip_visibility_subscription_;
diff --git chrome/browser/ui/views/frame/browser_widget.cc chrome/browser/ui/views/frame/browser_widget.cc
index 7482e34aa43f98206b44355957b32e76104ffa51..86f8a09a68bcbcfc1584c1b46b3fb10d2b367f3a 100644
--- chrome/browser/ui/views/frame/browser_widget.cc
+++ chrome/browser/ui/views/frame/browser_widget.cc
@@ -99,13 +99,26 @@ bool IsUsingLinuxSystemTheme(Profile* profile) {
////////////////////////////////////////////////////////////////////////////////
// BrowserWidget, public:
+BrowserWidget::BrowserWidget() : BrowserWidget(nullptr) {}
+
BrowserWidget::BrowserWidget(BrowserView* browser_view)
: browser_native_widget_(nullptr),
root_view_(nullptr),
browser_frame_view_(nullptr),
- browser_view_(browser_view) {
+ browser_view_(nullptr) {
// Don't focus anything on creation, selecting a tab will set the focus.
set_focus_on_creation(false);
+ if (browser_view) {
+ SetBrowserView(browser_view);
+ }
+}
+
+void BrowserWidget::SetBrowserFrameView(BrowserFrameView* browser_frame_view) {
+ browser_frame_view_ = browser_frame_view;
+}
+
+void BrowserWidget::SetBrowserView(BrowserView* browser_view) {
+ browser_view_ = browser_view;
}
BrowserWidget::~BrowserWidget() {
@@ -126,7 +139,11 @@ BrowserWidget::~BrowserWidget() {
// Do this here and not in ~BrowserView() as BrowserWindowFeatures may attempt
// to read state on the BrowserWidget as they undergo destruction, and
// BrowserWidget state is destroyed at the end of this scope.
- browser_view_->browser()->GetFeatures().TearDownPreBrowserWindowDestruction();
+ if (browser_view_ && browser_view_->browser()) {
+ browser_view_->browser()
+ ->GetFeatures()
+ .TearDownPreBrowserWindowDestruction();
+ }
}
void BrowserWidget::InitBrowserWidget() {
@@ -251,6 +268,8 @@ void BrowserWidget::GetWindowPlacement(
ui::mojom::WindowShowState* show_state) const {
if (browser_native_widget_) {
browser_native_widget_->GetWindowPlacement(bounds, show_state);
+ } else {
+ *show_state = ui::mojom::WindowShowState::kDefault;
}
}
@@ -383,6 +402,9 @@ ui::ColorProviderKey::ThemeInitializerSupplier* BrowserWidget::GetCustomTheme()
}
void BrowserWidget::OnNativeWidgetWorkspaceChanged() {
+ if (!browser_view_) {
+ return;
+ }
chrome::SaveWindowWorkspace(browser_view_->browser(), GetWorkspace());
chrome::SaveWindowVisibleOnAllWorkspaces(browser_view_->browser(),
IsVisibleOnAllWorkspaces());
@@ -548,6 +570,13 @@ void BrowserWidget::SelectNativeTheme() {
return;
}
+ // Always use the NativeTheme for forced color modes.
+ if (ui::NativeTheme::IsForcedDarkMode() ||
+ ui::NativeTheme::IsForcedLightMode()) {
+ SetNativeTheme(native_theme);
+ return;
+ }
+
// Ignore the system theme for web apps with window-controls-overlay as the
// display_override so the web contents can blend with the overlay by using
// the developer-provided theme color for a better experience. Context:
@@ -562,17 +591,23 @@ void BrowserWidget::SelectNativeTheme() {
}
void BrowserWidget::OnTouchUiChanged() {
- client_view()->InvalidateLayout();
-
- // For standard browser frame, if we do not invalidate the FrameView
- // the client window bounds will not be properly updated which could cause
- // visual artifacts. See crbug.com/40112464 for details.
- if (non_client_view()->frame_view()) {
- // Note that invalidating a view invalidates all of its ancestors, so it is
- // not necessary to also invalidate the NonClientView or RootView here.
- non_client_view()->frame_view()->InvalidateLayout();
- } else {
- non_client_view()->InvalidateLayout();
+ // client_view() is null when there is no NonClientView (e.g. CEF Chrome-style
+ // browsers with a native parent use TYPE_CONTROL). See CEF issue #3941.
+ if (client_view()) {
+ client_view()->InvalidateLayout();
+ }
+
+ if (non_client_view()) {
+ // For standard browser frame, if we do not invalidate the FrameView
+ // the client window bounds will not be properly updated which could cause
+ // visual artifacts. See crbug.com/40112464 for details.
+ if (non_client_view()->frame_view()) {
+ // Note that invalidating a view invalidates all of its ancestors, so it
+ // is not necessary to also invalidate the NonClientView or RootView here.
+ non_client_view()->frame_view()->InvalidateLayout();
+ } else {
+ non_client_view()->InvalidateLayout();
+ }
}
GetRootView()->InvalidateLayout();
}
@@ -611,6 +646,9 @@ bool BrowserWidget::RegenerateFrameOnThemeChange(
}
bool BrowserWidget::IsIncognitoBrowser() const {
+ if (!browser_view_) {
+ return true;
+ }
return browser_view_->browser()->GetProfile()->IsIncognitoProfile();
}
diff --git chrome/browser/ui/views/frame/browser_widget.h chrome/browser/ui/views/frame/browser_widget.h
index d384a2c99a1c1d8f160de20ea8518a6a4cc5ab71..39937dca7434763b3baa82600c7c9e73a6c01573 100644
--- chrome/browser/ui/views/frame/browser_widget.h
+++ chrome/browser/ui/views/frame/browser_widget.h
@@ -58,6 +58,7 @@ enum class TabDragKind {
class BrowserWidget : public views::Widget,
public views::ContextMenuController {
public:
+ BrowserWidget();
explicit BrowserWidget(BrowserView* browser_view);
BrowserWidget(const BrowserWidget&) = delete;
@@ -98,7 +99,7 @@ class BrowserWidget : public views::Widget,
// ThemeService calls this when a user has changed their theme, indicating
// that it's time to redraw everything.
- void UserChangedTheme(BrowserThemeChangeType theme_change_type);
+ virtual void UserChangedTheme(BrowserThemeChangeType theme_change_type);
// views::Widget:
views::internal::RootView* CreateRootView() override;
@@ -132,11 +133,21 @@ class BrowserWidget : public views::Widget,
void SetTabDragKind(TabDragKind tab_drag_kind);
TabDragKind tab_drag_kind() const { return tab_drag_kind_; }
+ BrowserView* browser_view() const { return browser_view_.get(); }
+
protected:
+ void SetBrowserFrameView(BrowserFrameView* browser_frame_view);
+ void SetBrowserView(BrowserView* browser_view);
+
// views::Widget:
void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override;
ui::ColorProviderKey GetColorProviderKey() const override;
+ // Select a native theme that is appropriate for the current context. This is
+ // currently only needed for Linux to switch between the regular NativeTheme
+ // and the GTK NativeTheme instance.
+ void SelectNativeTheme();
+
private:
const ui::ThemeProvider* GetBaseThemeProvider() const;
@@ -146,11 +157,6 @@ class BrowserWidget : public views::Widget,
// Callback for MenuRunner.
void OnMenuClosed();
- // Select a native theme that is appropriate for the current context. This is
- // currently only needed for Linux to switch between the regular NativeTheme
- // and the GTK NativeTheme instance.
- void SelectNativeTheme();
-
// Regenerate the frame on theme change if necessary. Returns true if
// regenerated.
bool RegenerateFrameOnThemeChange(BrowserThemeChangeType theme_change_type);
diff --git chrome/browser/ui/views/frame/layout/browser_view_layout.cc chrome/browser/ui/views/frame/layout/browser_view_layout.cc
index 778997a0f1aec1982a2421bb18faf5918347af51..9f7f99605e186c11220b9f6d6787e1818b173379 100644
--- chrome/browser/ui/views/frame/layout/browser_view_layout.cc
+++ chrome/browser/ui/views/frame/layout/browser_view_layout.cc
@@ -24,6 +24,10 @@
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
+#if BUILDFLAG(ENABLE_CEF)
+#include "cef/libcef/browser/chrome/views/chrome_views_util.h"
+#endif
+
using web_modal::ModalDialogHostObserver;
using web_modal::WebContentsModalDialogHost;
@@ -66,6 +70,8 @@ class BrowserViewLayout::BrowserModalDialogHostViews
observer_list_.Notify(&ModalDialogHostObserver::OnHostDestroying);
}
+ bool HasObservers() const { return !observer_list_.empty(); }
+
void NotifyPositionRequiresUpdate() override {
observer_list_.Notify(&ModalDialogHostObserver::OnPositionRequiresUpdate);
}
@@ -221,18 +227,21 @@ void BrowserViewLayout::UpdateBubbles() {
exclusive_access_bubble->RepositionIfVisible();
}
- // Adjust any hosted dialogs if the browser's dialog hosting bounds changed.
- const gfx::Rect dialog_bounds(dialog_host_->GetDialogPosition(gfx::Size()),
- dialog_host_->GetMaximumDialogSize());
- const gfx::Rect host_widget_bounds =
- dialog_host_->GetHostWidget()
- ? dialog_host_->GetHostWidget()->GetClientAreaBoundsInScreen()
- : gfx::Rect();
- const gfx::Rect dialog_bounds_in_screen =
- dialog_bounds + host_widget_bounds.OffsetFromOrigin();
- if (latest_dialog_bounds_in_screen_ != dialog_bounds_in_screen) {
- latest_dialog_bounds_in_screen_ = dialog_bounds_in_screen;
- dialog_host_->NotifyPositionRequiresUpdate();
+ // Avoid unnecessary calls to UpdateDialogTopInsetInBrowserView().
+ if (dialog_host_->HasObservers()) {
+ // Adjust any hosted dialogs if the browser's dialog hosting bounds changed.
+ const gfx::Rect dialog_bounds(dialog_host_->GetDialogPosition(gfx::Size()),
+ dialog_host_->GetMaximumDialogSize());
+ const gfx::Rect host_widget_bounds =
+ dialog_host_->GetHostWidget()
+ ? dialog_host_->GetHostWidget()->GetClientAreaBoundsInScreen()
+ : gfx::Rect();
+ const gfx::Rect dialog_bounds_in_screen =
+ dialog_bounds + host_widget_bounds.OffsetFromOrigin();
+ if (latest_dialog_bounds_in_screen_ != dialog_bounds_in_screen) {
+ latest_dialog_bounds_in_screen_ = dialog_bounds_in_screen;
+ dialog_host_->NotifyPositionRequiresUpdate();
+ }
}
}
diff --git chrome/browser/ui/views/frame/layout/browser_view_layout.h chrome/browser/ui/views/frame/layout/browser_view_layout.h
index 04ce33b996df2279123d26d474a371c6de735ca3..8d6b958120ca7a6391901d4002356fd7ed8b1341 100644
--- chrome/browser/ui/views/frame/layout/browser_view_layout.h
+++ chrome/browser/ui/views/frame/layout/browser_view_layout.h
@@ -136,6 +136,8 @@ class BrowserViewLayout : public views::LayoutManager {
return views_.side_panel_animation_content;
}
+ void reset_toolbar() { views_.toolbar = nullptr; }
+
// views::LayoutManager overrides:
gfx::Size GetPreferredSize(
const views::View* host,
diff --git chrome/browser/ui/views/frame/layout/browser_view_layout_delegate.h chrome/browser/ui/views/frame/layout/browser_view_layout_delegate.h
index 1ee5f63dd6806e2701002c550e423f90a071f422..68969c512a8b4be6e14fb0f6c7d3ce9929132618 100644
--- chrome/browser/ui/views/frame/layout/browser_view_layout_delegate.h
+++ chrome/browser/ui/views/frame/layout/browser_view_layout_delegate.h
@@ -43,6 +43,7 @@ class BrowserViewLayoutDelegate {
bool use_browser_bounds) const = 0;
virtual WindowState GetBrowserWindowState() const = 0;
virtual views::LayoutAlignment GetWindowTitleAlignment() const = 0;
+ virtual void UpdateDialogTopInsetInBrowserView(int* dialog_top_y) const = 0;
virtual bool IsToolbarVisible() const = 0;
virtual bool IsBookmarkBarVisible() const = 0;
virtual bool IsInfobarVisible() const = 0;
diff --git chrome/browser/ui/views/frame/layout/browser_view_layout_delegate_impl.cc chrome/browser/ui/views/frame/layout/browser_view_layout_delegate_impl.cc
index e51647c429151fd07b32102fa5e9423967cdec16..6eb5bfa261907cec3077ac18e87fde69bf817981 100644
--- chrome/browser/ui/views/frame/layout/browser_view_layout_delegate_impl.cc
+++ chrome/browser/ui/views/frame/layout/browser_view_layout_delegate_impl.cc
@@ -131,6 +131,15 @@ views::LayoutAlignment BrowserViewLayoutDelegateImpl::GetWindowTitleAlignment()
return GetFrameView()->GetWindowTitleAlignment();
}
+void BrowserViewLayoutDelegateImpl::UpdateDialogTopInsetInBrowserView(
+ int* dialog_top_y) const {
+#if BUILDFLAG(ENABLE_CEF)
+ if (auto cef_delegate = browser_view_->browser()->cef_delegate()) {
+ cef_delegate->UpdateDialogTopInset(dialog_top_y);
+ }
+#endif
+}
+
bool BrowserViewLayoutDelegateImpl::IsToolbarVisible() const {
return browser_view_->IsToolbarVisible();
}
diff --git chrome/browser/ui/views/frame/layout/browser_view_layout_delegate_impl.h chrome/browser/ui/views/frame/layout/browser_view_layout_delegate_impl.h
index 0340813d5e0834af5b1ae1af4f02ab04dea77d64..a1a9fb235433e553bffbd4ac31cef271149bd2ee 100644
--- chrome/browser/ui/views/frame/layout/browser_view_layout_delegate_impl.h
+++ chrome/browser/ui/views/frame/layout/browser_view_layout_delegate_impl.h
@@ -31,6 +31,7 @@ class BrowserViewLayoutDelegateImpl : public BrowserViewLayoutDelegate {
bool use_browser_bounds) const override;
WindowState GetBrowserWindowState() const override;
views::LayoutAlignment GetWindowTitleAlignment() const override;
+ void UpdateDialogTopInsetInBrowserView(int* dialog_top_y) const override;
bool IsToolbarVisible() const override;
bool IsBookmarkBarVisible() const override;
bool IsInfobarVisible() const override;
diff --git chrome/browser/ui/views/frame/layout/browser_view_layout_impl.cc chrome/browser/ui/views/frame/layout/browser_view_layout_impl.cc
index 32dc2739b9e326625d5dbcb7d18623c147e8209e..b0a5644023cf8d2cf2d9ccba1130417ea49d2d29 100644
--- chrome/browser/ui/views/frame/layout/browser_view_layout_impl.cc
+++ chrome/browser/ui/views/frame/layout/browser_view_layout_impl.cc
@@ -221,7 +221,16 @@ void BrowserViewLayoutImpl::Layout(views::View* host) {
auto params = delegate().GetBrowserLayoutParams(/*use_browser_bounds=*/true);
if (params.IsEmpty()) {
- return;
+ // Layout params are empty during early initialization (before the frame
+ // view has been laid out). Fall back to using the host's local bounds
+ // as the visual client area to allow layout to proceed with valid bounds.
+ // This prevents View::Layout's for-loop from triggering child layouts
+ // with 0x0 bounds.
+ params.visual_client_area = host->GetLocalBounds();
+ if (params.IsEmpty()) {
+ // Host also has no bounds yet, can't perform layout.
+ return;
+ }
}
DoPreLayoutComputations(params);
@@ -353,11 +362,13 @@ void BrowserViewLayoutImpl::OnGlassModeChanged() {}
int BrowserViewLayoutImpl::GetDialogTop(const ProposedLayout& layout) const {
const int kConstrainedWindowOverlap = 3;
const auto* const browser_view = views().browser_view.get();
+ int dialog_top_y = kConstrainedWindowOverlap;
if (const auto toolbar_rect =
layout.GetBoundsFor(views().toolbar, browser_view)) {
- return toolbar_rect->bottom() - kConstrainedWindowOverlap;
+ dialog_top_y = toolbar_rect->bottom() - kConstrainedWindowOverlap;
}
- return kConstrainedWindowOverlap;
+ delegate().UpdateDialogTopInsetInBrowserView(&dialog_top_y);
+ return dialog_top_y;
}
int BrowserViewLayoutImpl::GetDialogBottom(const ProposedLayout& layout) const {
diff --git chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc
index 2ed2551ecd268e624bd7b32769b46b8f90342662..89355560f1b21440adb9b6c5e0c0e9bcdd67a48a 100644
--- chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc
+++ chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc
@@ -29,6 +29,7 @@
#include "chrome/browser/ui/views/picture_in_picture/picture_in_picture_bounds_change_animation.h"
#include "chrome/browser/ui/views/picture_in_picture/picture_in_picture_tucker.h"
#include "chrome/browser/ui/views/picture_in_picture/pip_top_bar_animation_controller.h"
+#include "chrome/browser/ui/window_feature_controller/window_feature_controller.h"
#include "chrome/grit/generated_resources.h"
#include "components/omnibox/browser/location_bar_model_impl.h"
#include "components/vector_icons/vector_icons.h"
@@ -345,6 +346,12 @@ PictureInPictureBrowserFrameView::PictureInPictureBrowserFrameView(
IsOverlayViewVisible()) {
PictureInPictureWindowManager::GetInstance()->ClearCachedBounds();
}
+
+ if (!WindowFeatureController::From(browser_view->browser())
+ ->SupportsWindowFeature(
+ WindowFeatureController::WindowFeature::kFeatureTitleBar)) {
+ top_bar_container_view_->SetVisible(false);
+ }
}
PictureInPictureBrowserFrameView::~PictureInPictureBrowserFrameView() {
@@ -451,18 +458,41 @@ gfx::Rect PictureInPictureBrowserFrameView::GetWindowBoundsForClientBounds(
int PictureInPictureBrowserFrameView::NonClientHitTest(
const gfx::Point& point) {
- // Allow interacting with the buttons.
- if (GetLocationIconViewBounds().Contains(point) ||
- GetBackToTabControlsBounds().Contains(point) ||
- GetCloseControlsBounds().Contains(point)) {
- return HTCLIENT;
+ const bool frameless = !top_bar_container_view_->GetVisible();
+ if (!frameless) {
+ // Allow interacting with the buttons.
+ if (GetLocationIconViewBounds().Contains(point) ||
+ GetBackToTabControlsBounds().Contains(point) ||
+ GetCloseControlsBounds().Contains(point)) {
+ return HTCLIENT;
+ }
+
+ for (size_t i = 0; i < content_setting_views_.size(); i++) {
+ if (GetContentSettingViewBounds(i).Contains(point)) {
+ return HTCLIENT;
+ }
+ }
}
- for (size_t i = 0; i < content_setting_views_.size(); i++) {
- if (GetContentSettingViewBounds(i).Contains(point)) {
- return HTCLIENT;
+#if BUILDFLAG(ENABLE_CEF)
+ if (frameless) {
+ // Match logic in BrowserView::ShouldDescendIntoChildForEventHandling.
+ const auto draggable_region =
+ GetBrowserView()->browser()->cef_delegate()->GetDraggableRegion();
+ if (draggable_region.has_value()) {
+ // Draggable regions are defined relative to the web contents.
+ gfx::Point point_in_contents_web_view_coords(point);
+ views::View::ConvertPointToTarget(GetWidget()->GetRootView(),
+ GetBrowserView()->contents_web_view(),
+ &point_in_contents_web_view_coords);
+
+ if (draggable_region->contains(point_in_contents_web_view_coords.x(),
+ point_in_contents_web_view_coords.y())) {
+ return HTCAPTION;
+ }
}
}
+#endif // BUILDFLAG(ENABLE_CEF)
// Allow dragging and resizing the window.
int window_component = GetHTComponentForFrame(
@@ -527,7 +557,8 @@ void PictureInPictureBrowserFrameView::Layout(PassKey) {
gfx::Rect content_area = GetLocalBounds();
content_area.Inset(FrameBorderInsets());
gfx::Rect top_bar = content_area;
- top_bar.set_height(kTopControlsHeight);
+ top_bar.set_height(top_bar_container_view_->GetVisible() ? kTopControlsHeight
+ : 0);
top_bar_container_view_->SetBoundsRect(top_bar);
#if !BUILDFLAG(IS_ANDROID)
if (auto_pip_setting_overlay_) {
@@ -1003,7 +1034,8 @@ gfx::Insets PictureInPictureBrowserFrameView::FrameBorderInsets() const {
}
int PictureInPictureBrowserFrameView::GetTopAreaHeight() const {
- return FrameBorderInsets().top() + kTopControlsHeight;
+ return FrameBorderInsets().top() +
+ (top_bar_container_view_->GetVisible() ? kTopControlsHeight : 0);
}
gfx::Size PictureInPictureBrowserFrameView::GetNonClientViewAreaSize() const {
diff --git chrome/browser/ui/views/location_bar/location_bar_view.cc chrome/browser/ui/views/location_bar/location_bar_view.cc
index f97b92504ba812fd6e5dc25f1974fc86b3bc1d52..c01b995d733b825bdb19e4cb1ac38a029e141065 100644
--- chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -449,6 +449,18 @@ void LocationBarView::Init() {
page_action_items = page_actions::GetActivePageActionItems(*browser_);
}
+#if BUILDFLAG(ENABLE_CEF)
+ if (browser_ && browser_->cef_delegate()) {
+ const auto& properties_provider =
+ page_actions::PageActionPropertiesProvider();
+ std::erase_if(page_action_items, [&](actions::ActionItem* item) {
+ const auto& props =
+ properties_provider.GetProperties(item->GetActionId().value());
+ return !browser_->cef_delegate()->IsPageActionIconVisible(props.type);
+ });
+ }
+#endif
+
static constexpr int kBetweenIconSpacing = 8;
const page_actions::PageActionViewParams page_action_params{
.icon_size =
diff --git chrome/browser/ui/views/omnibox/omnibox_popup_closer.cc chrome/browser/ui/views/omnibox/omnibox_popup_closer.cc
index 57d2e49e599ffb409d566a27a29ef9431557fea0..c8aaf3fd1d78d803de138e8c7936e5d01bc18ad5 100644
--- chrome/browser/ui/views/omnibox/omnibox_popup_closer.cc
+++ chrome/browser/ui/views/omnibox/omnibox_popup_closer.cc
@@ -60,7 +60,8 @@ OmniboxPopupCloser::~OmniboxPopupCloser() = default;
void OmniboxPopupCloser::OnMouseEvent(ui::MouseEvent* event) {
// Close the omnibox popup if the click is outside the omnibox view.
- if (!browser_view_->browser()->IsDeleteScheduled()) {
+ if (browser_view_->browser() &&
+ !browser_view_->browser()->IsDeleteScheduled()) {
LocationBar* location_bar = browser_view_->GetLocationBar();
CHECK(location_bar);
if (location_bar->ShouldCloseOmniboxPopup(event)) {
diff --git chrome/browser/ui/views/toolbar/toolbar_view.cc chrome/browser/ui/views/toolbar/toolbar_view.cc
index 58334f610569244b55dcfee3db5bc337b7e3c357..ad0528de81dd7a936faa9acdc1a8d649270ed66c 100644
--- chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -43,6 +43,7 @@
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/ui/actions/chrome_action_id.h"
#include "chrome/browser/ui/ai_overlay_dialog/ai_overlay_dialog_controller.h"
+#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_actions.h"
#include "chrome/browser/ui/browser_command_controller.h"
#include "chrome/browser/ui/browser_commands.h"
@@ -174,6 +175,10 @@
#include "ui/aura/window_occlusion_tracker.h"
#endif
+#if BUILDFLAG(ENABLE_CEF)
+#include "cef/libcef/browser/chrome/browser_util.h"
+#endif
+
using base::UserMetricsAction;
using content::WebContents;
@@ -261,12 +266,13 @@ void SetRefreshMargins(views::View* button, bool expanded) {
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(ToolbarView, kToolbarElementId);
ToolbarView::ToolbarView(BrowserWindowInterface* browser,
- BrowserView* browser_view)
+ BrowserView* browser_view,
+ std::optional<DisplayMode> display_mode)
: AnimationDelegateViews(this),
browser_(browser),
browser_view_(browser_view),
app_menu_icon_controller_(browser->GetProfile(), this),
- display_mode_(GetDisplayMode(browser)) {
+ display_mode_(display_mode ? *display_mode : GetDisplayMode(browser)) {
// WebApp type-browsers set their own ToolbarButtonProvider.
if (!web_app::AppBrowserController::IsWebApp(browser)) {
scoped_unowned_user_data_.emplace(browser_->GetUnownedUserDataHost(),
@@ -306,9 +312,24 @@ ToolbarView::~ToolbarView() {
for (const auto& view_and_command : GetViewCommandMap()) {
chrome::RemoveCommandObserver(browser_, view_and_command.second, this);
}
+
+ browser_view_->WillDestroyToolbar();
}
void ToolbarView::Init() {
+#if BUILDFLAG(ENABLE_CEF)
+ using ToolbarButtonType = cef::BrowserDelegate::ToolbarButtonType;
+ auto button_visible = [this](ToolbarButtonType type) {
+ if (this->browser_->cef_delegate()) {
+ return this->browser_->cef_delegate()->IsToolbarButtonVisible(type);
+ }
+ return true;
+ };
+#define BUTTON_VISIBLE(type) button_visible(ToolbarButtonType::type)
+#else
+#define BUTTON_VISIBLE(type) true
+#endif
+
#if defined(USE_AURA)
// Avoid generating too many occlusion tracking calculation events before this
// function returns. The occlusion status will be computed only once once this
@@ -329,7 +350,8 @@ void ToolbarView::Init() {
location_bar_view = std::make_unique<LocationBarView>(
browser_, browser_->GetProfile(),
chrome::BrowserCommandController::From(browser_), this,
- display_mode_ != DisplayMode::kNormal);
+ display_mode_ != DisplayMode::kNormal &&
+ !cef::BrowserForBWI(browser_)->toolbar_overridden());
}
// Make sure the toolbar shows by default.
@@ -402,7 +424,7 @@ void ToolbarView::Init() {
std::unique_ptr<MediaToolbarButtonView> media_button;
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
- if (!features::IsWebUIMediaButtonEnabled()) {
+ if (!features::IsWebUIMediaButtonEnabled() && BUTTON_VISIBLE(kMedia)) {
media_button = std::make_unique<MediaToolbarButtonView>(
browser_view_, std::make_unique<MediaToolbarButtonContextualMenu>(
browser_->GetProfile()));
@@ -529,7 +551,8 @@ void ToolbarView::Init() {
// Only show the Battery Saver button when it is not controlled by the OS. On
// ChromeOS the battery icon in the shelf shows the same information.
if (!performance_manager::user_tuning::IsBatterySaverModeManagedByOS() &&
- !features::IsWebUIBatterySaverButtonEnabled()) {
+ !features::IsWebUIBatterySaverButtonEnabled() &&
+ BUTTON_VISIBLE(kBatterySaver)) {
battery_saver_button_ =
AddChildView(std::make_unique<BatterySaverButton>(browser_));
}
@@ -581,7 +604,7 @@ void ToolbarView::Init() {
avatar_ = AddChildView(std::make_unique<AvatarToolbarButton>(browser_));
bool show_avatar_toolbar_button =
AvatarToolbarButtonInterface::CanShowForProfile(browser_->GetProfile());
- avatar_->SetVisible(show_avatar_toolbar_button);
+ avatar_->SetVisible(show_avatar_toolbar_button && BUTTON_VISIBLE(kAvatar));
}
// Only manage the overflow button when there are at least some views
diff --git chrome/browser/ui/views/toolbar/toolbar_view.h chrome/browser/ui/views/toolbar/toolbar_view.h
index daed2c76ac524c4d7caf8764d432a0d07e5047c8..a6fba0c6ebd35e6c6a1e23fd71186a25e231786e 100644
--- chrome/browser/ui/views/toolbar/toolbar_view.h
+++ chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -111,7 +111,9 @@ class ToolbarView : public views::AccessiblePaneView,
DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kToolbarElementId);
- ToolbarView(BrowserWindowInterface* browser, BrowserView* browser_view);
+ ToolbarView(BrowserWindowInterface* browser,
+ BrowserView* browser_view,
+ std::optional<DisplayMode> display_mode);
ToolbarView(const ToolbarView&) = delete;
ToolbarView& operator=(const ToolbarView&) = delete;
~ToolbarView() override;