Files
cef/patch/patches/chrome_runtime_views.patch
Marshall Greenblatt a26ddfd279 Update to Chromium version 156.0.8078.0
win: dxil.dll is no longer distributed
mac: Xcode 27 (macOS 26.6+) is now required
2026-10-07 12:25:37 -04:00

1250 lines
51 KiB
Diff

diff --git chrome/browser/ui/browser_command_controller.cc chrome/browser/ui/browser_command_controller.cc
index 921461b9e9bd0423d6d180762d0a06d0a3cd9c94..06c7fb432c8da0ccf3b70806b568c776e222a90e 100644
--- chrome/browser/ui/browser_command_controller.cc
+++ chrome/browser/ui/browser_command_controller.cc
@@ -198,6 +198,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;
@@ -554,6 +558,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)
@@ -641,6 +651,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;
}
@@ -667,6 +678,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) {
@@ -1712,12 +1730,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 faaded8ad5427c95787fde91961ae6d543902336..292beca4fb2c1ccfb4804acc9cc5151a68d62ad2 100644
--- chrome/browser/ui/toolbar/app_menu_model.cc
+++ chrome/browser/ui/toolbar/app_menu_model.cc
@@ -190,6 +190,10 @@
#include "content/public/browser/gpu_data_manager.h"
#endif
+#if BUILDFLAG(ENABLE_CEF)
+#include "cef/libcef/browser/chrome/browser_delegate.h"
+#endif
+
using base::UserMetricsAction;
using content::WebContents;
@@ -778,18 +782,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 {
@@ -932,6 +938,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
////////////////////////////////////////////////////////////////////////////////
@@ -2019,7 +2076,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);
@@ -2037,6 +2094,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) {
@@ -2277,8 +2358,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(
@@ -2431,6 +2514,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 7fd1446d69240e26e347487b69998da389b33d7b..59ee3acdf8870bddf7b1c6981fcc618540efde36 100644
--- chrome/browser/ui/toolbar/app_menu_model.h
+++ chrome/browser/ui/toolbar/app_menu_model.h
@@ -310,6 +310,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;
@@ -349,6 +350,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 b68f089aebf83b82499611404433d430e9971f14..6123e7fe79ad94eac0b7c248d4907a588995b4c0 100644
--- chrome/browser/ui/views/frame/browser_view.cc
+++ chrome/browser/ui/views/frame/browser_view.cc
@@ -419,6 +419,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;
@@ -890,11 +894,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();
}
@@ -921,7 +935,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);
@@ -945,8 +960,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());
@@ -1108,6 +1131,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);
@@ -1122,7 +1149,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.
@@ -1221,7 +1250,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());
@@ -1243,6 +1272,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.
@@ -1967,6 +2006,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();
}
@@ -3174,6 +3234,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();
@@ -4095,7 +4158,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) {
@@ -4272,9 +4338,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(
@@ -4532,12 +4611,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()) {
gfx::Point point_in_browser_view_coords(location);
views::View::ConvertPointToTarget(GetWidget()->GetRootView(), this,
&point_in_browser_view_coords);
@@ -4550,9 +4656,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_browser_view_coords);
}
@@ -4888,7 +4993,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()) {
@@ -5176,6 +5283,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 6c4807bbaaf0a8e12e1a2df8545b4b55f491c297..9cc40ae854a363a98f1c8f3b7be44d0ab366957d 100644
--- chrome/browser/ui/views/frame/browser_view.h
+++ chrome/browser/ui/views/frame/browser_view.h
@@ -151,7 +151,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;
@@ -823,10 +825,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.
@@ -1093,11 +1101,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 6a221594b09f0b8fa10e4b8bbca05a0e52e52a58..e1037567bb95ec02defe4c08890439a22a1fbcda 100644
--- chrome/browser/ui/views/frame/browser_widget.cc
+++ chrome/browser/ui/views/frame/browser_widget.cc
@@ -100,16 +100,29 @@ 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);
+ }
views::WidgetStationarityMonitor::GetInstance().TrackWidget(*this);
}
+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() {
set_widget_closed();
@@ -128,7 +141,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() {
@@ -253,6 +270,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;
}
}
@@ -385,6 +404,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());
@@ -553,6 +575,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:
@@ -567,17 +596,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();
}
@@ -616,6 +651,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 c84c47a1190f9acd9602e6cc06badcbf81cf00a2..a2bb1d25ea23b8eb2b3c6763739d0f65a9f4d130 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 ac03bc00a00a9e127479f9da46b8bfb68da5fe98..b695949269ea20fee3c421ab72e0ca0d81f33831 100644
--- chrome/browser/ui/views/frame/layout/browser_view_layout_delegate.h
+++ chrome/browser/ui/views/frame/layout/browser_view_layout_delegate.h
@@ -46,6 +46,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 162cb0487882a40ed6324115d5e58eb3cca97186..fdf3895be6aa8d4444849c45e1266eed1cf36cfb 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
@@ -35,19 +35,23 @@
#include "chrome/browser/ui/window_feature_controller/window_feature_controller.h"
#endif
+#if BUILDFLAG(ENABLE_CEF)
+#include "cef/libcef/browser/chrome/browser_delegate.h"
+#endif
+
BrowserViewLayoutDelegateImpl::BrowserViewLayoutDelegateImpl(
BrowserView& browser_view)
: browser_view_(browser_view) {
- PrefService* prefs = browser_view_->GetProfile()->GetPrefs();
- tab_search_pinned_to_tab_strip_ =
- prefs->GetBoolean(prefs::kTabSearchPinnedToTabstrip);
-
- pref_registrar_.Init(prefs);
- pref_registrar_.Add(
- prefs::kTabSearchPinnedToTabstrip,
- base::BindRepeating(
- &BrowserViewLayoutDelegateImpl::OnTabSearchPinnedStateChanged,
- base::Unretained(this)));
+ PrefService* prefs = browser_view_->GetProfile()->GetPrefs();
+ tab_search_pinned_to_tab_strip_ =
+ prefs->GetBoolean(prefs::kTabSearchPinnedToTabstrip);
+
+ pref_registrar_.Init(prefs);
+ pref_registrar_.Add(
+ prefs::kTabSearchPinnedToTabstrip,
+ base::BindRepeating(
+ &BrowserViewLayoutDelegateImpl::OnTabSearchPinnedStateChanged,
+ base::Unretained(this)));
}
BrowserViewLayoutDelegateImpl::~BrowserViewLayoutDelegateImpl() = default;
@@ -144,6 +148,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 df5a04fcd0006b93ce966079c65eff6fe5684d65..b726f843b05aff31ad75e3f085ea2853febd38ec 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
@@ -30,6 +30,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 59bdfa1e118091ea37ba235fb47b05797fdb16ed..69a4e327752488204cf046ac62b25b84be782ccb 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"
@@ -75,6 +76,11 @@
#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
#include "extensions/common/constants.h"
#endif // BUILDFLAG(ENABLE_EXTENSIONS_CORE)
+
+#if BUILDFLAG(ENABLE_CEF)
+#include "ui/views/controls/webview/webview.h"
+#endif
+
namespace {
constexpr int kWindowIconImageSize = 16;
@@ -346,6 +352,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() {
@@ -452,18 +464,42 @@ 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()->GetActiveContentsWebView(),
+ &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(
@@ -528,7 +564,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_) {
@@ -1004,7 +1041,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 bac174d0b227aa593d369b6e2e7f7b58179f2c16..cbc4b2936dddd2745b236f44a86c84b23f09ae44 100644
--- chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -171,6 +171,10 @@
#include "chrome/browser/web_applications/web_app_tab_helper.h"
#endif
+#if BUILDFLAG(ENABLE_CEF)
+#include "cef/libcef/browser/chrome/browser_util.h"
+#endif
+
namespace {
int IncrementalMinimumWidth(const views::View* view) {
@@ -197,6 +201,14 @@ bool CanHostWebUIOmnibox(BrowserWindowInterface* browser, bool is_popup_mode) {
if (!browser) {
return true;
}
+#if BUILDFLAG(ENABLE_CEF)
+ if (browser->cef_delegate() && browser->cef_delegate()->IsViewsHosted() &&
+ !cef::BrowserForBWI(browser)->toolbar_overridden()) {
+ // CEF initializes a fallback toolbar even when none is configured.
+ // Only create WebUI popups for a configured Chrome toolbar.
+ return false;
+ }
+#endif
return !web_app::AppBrowserController::IsWebApp(browser) &&
browser->GetType() != BrowserWindowInterface::Type::TYPE_DEVTOOLS;
}
@@ -396,7 +408,7 @@ void LocationBarView::Init() {
}
}
- // Default to the legacy popup view for web apps, devtools, and popup windows.
+ // Default to the legacy popup view when WebUI popups are not supported.
// When the legacy `OmniboxPopupViewViews` is deprecated we will need to
// ensure that a null `omnibox_popup_view_` doesn't cause any issues (or aim
// for a cleaner solution).
@@ -479,6 +491,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 f3468b8df860303d49052587004ca1e0f501d4fd..44c59704cad310c5f577470eb3b0e2c431cb9a6c 100644
--- chrome/browser/ui/views/omnibox/omnibox_popup_closer.cc
+++ chrome/browser/ui/views/omnibox/omnibox_popup_closer.cc
@@ -59,7 +59,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 136f1c7c87a446ff5192a58f87f874800f09375d..3177568b2663a824f308a94d6874585fec0ecc26 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"
@@ -182,6 +183,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;
@@ -269,12 +274,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(),
@@ -314,6 +320,8 @@ ToolbarView::~ToolbarView() {
for (const auto& view_and_command : GetViewCommandMap()) {
chrome::RemoveCommandObserver(browser_, view_and_command.second, this);
}
+
+ browser_view_->WillDestroyToolbar();
}
// Forwards the early teardown request to both the embedded and detached WebUI
@@ -328,6 +336,19 @@ void ToolbarView::DestroyWebUIToolbarWebContents() {
}
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
@@ -348,7 +369,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.
@@ -421,7 +443,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()));
@@ -556,7 +578,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_));
}
@@ -613,7 +636,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 50e546251e9f8021683a6929593205daefbb0596..57c9e8d4659ddab00fc3cd30be8af5f3bbfbb8b1 100644
--- chrome/browser/ui/views/toolbar/toolbar_view.h
+++ chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -113,7 +113,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;