cef/patch/patches/chrome_runtime_views.patch
Marshall Greenblatt dca0435d2f chrome: Add support for Alloy style browsers and windows (see #3681)
Split the Alloy runtime into bootstrap and style components. Support
creation of Alloy style browsers and windows with the Chrome runtime.
Chrome runtime (`--enable-chrome-runtime`) + Alloy style
(`--use-alloy-style`) supports Views (`--use-views`), native parent
(`--use-native`) and windowless rendering
(`--off-screen-rendering-enabled`).

Print preview is supported in all cases except with windowless rendering
on all platforms and native parent on MacOS. It is disabled by default
with Alloy style for legacy compatibility. Where supported it can be
enabled or disabled globally using `--[enable|disable]-print-preview` or
configured on a per-RequestContext basis using the
`printing.print_preview_disabled` preference. It also behaves as
expected when triggered via the PDF viewer print button.

Chrome runtime + Alloy style behavior differs from Alloy runtime in the
following significant ways:

- Supports Chrome error pages by default.
- DevTools popups are Chrome style only (cannot be windowless).
- The Alloy extension API will not supported.

Chrome runtime + Alloy style passes all expected Alloy ceftests except
the following:

- `DisplayTest.AutoResize` (Alloy extension API not supported)
- `DownloadTest.*` (Download API not yet supported)
- `ExtensionTest.*` (Alloy extension API not supported)

This change also adds Chrome runtime support for
CefContextMenuHandler::RunContextMenu (see #3293).

This change also explicitly blocks (and doesn't retry) FrameAttached
requests from PDF viewer and print preview excluded frames (see #3664).

Known issues specific to Chrome runtime + Alloy style:
- DevTools popup with windowless rendering doesn't load successfully.
  Use windowed rendering or remote debugging as a workaround.
- Chrome style Window with Alloy style BrowserView (`--use-alloy-style
  --use-chrome-style-window`) does not show Chrome theme changes.

To test:
- Run `ceftests --enable-chrome-runtime --use-alloy-style
       [--use-chrome-style-window] [--use-views|--use-native]
       --gtest_filter=...`
- Run `cefclient --enable-chrome-runtime --use-alloy-style
       [--use-chrome-style-window]
       [--use-views|--use-native|--off-screen-rendering-enabled]`
- Run `cefsimple --enable-chrome-runtime --use-alloy-style [--use-views]`
2024-04-22 14:57:37 -04:00

1174 lines
45 KiB
Diff

diff --git chrome/browser/ui/browser_command_controller.cc chrome/browser/ui/browser_command_controller.cc
index 3bf48f1897c93..a9b219500beac 100644
--- chrome/browser/ui/browser_command_controller.cc
+++ chrome/browser/ui/browser_command_controller.cc
@@ -400,6 +400,7 @@ bool BrowserCommandController::ExecuteCommandWithDisposition(
// choose to not implement CommandUpdaterDelegate inside this class and
// therefore command_updater_ doesn't have the delegate set).
if (!SupportsCommand(id) || !IsCommandEnabled(id)) {
+ LOG(WARNING) << "Invalid/disabled command " << id;
return false;
}
@@ -416,6 +417,13 @@ bool BrowserCommandController::ExecuteCommandWithDisposition(
DCHECK(command_updater_.IsCommandEnabled(id))
<< "Invalid/disabled command " << id;
+#if BUILDFLAG(ENABLE_CEF)
+ if (browser_->cef_delegate() &&
+ browser_->cef_delegate()->HandleCommand(id, disposition)) {
+ return true;
+ }
+#endif
+
// The order of commands in this switch statement must match the function
// declaration order in browser.h!
switch (id) {
@@ -1169,11 +1177,13 @@ void BrowserCommandController::TabRestoreServiceLoaded(
// BrowserCommandController, private:
bool BrowserCommandController::IsShowingMainUI() {
- return browser_->SupportsWindowFeature(Browser::FEATURE_TABSTRIP);
+ return browser_->SupportsWindowFeature(Browser::FEATURE_TABSTRIP) ||
+ browser_->toolbar_overridden();
}
bool BrowserCommandController::IsShowingLocationBar() {
- return browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR);
+ return browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR) ||
+ browser_->toolbar_overridden();
}
bool BrowserCommandController::IsWebAppOrCustomTab() const {
diff --git chrome/browser/ui/toolbar/app_menu_model.cc chrome/browser/ui/toolbar/app_menu_model.cc
index 8cdbf6a389727..715078e9d0a2c 100644
--- chrome/browser/ui/toolbar/app_menu_model.cc
+++ chrome/browser/ui/toolbar/app_menu_model.cc
@@ -709,6 +709,57 @@ SaveAndShareSubMenuModel::SaveAndShareSubMenuModel(
}
}
+#if BUILDFLAG(ENABLE_CEF)
+using IsVisibleCallback = base::RepeatingCallback<bool(int)>;
+
+void FilterMenuModel(ui::SimpleMenuModel* model,
+ const IsVisibleCallback& is_visible) {
+ absl::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 = absl::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
////////////////////////////////////////////////////////////////////////////////
@@ -1571,7 +1622,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_->profile())
->GetGlobalErrorByMenuItemCommandID(command_id);
@@ -1586,6 +1637,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) {
@@ -1753,11 +1828,15 @@ void AppMenuModel::Build() {
kDefaultIconSize));
}
- AddSeparator(features::IsChromeRefresh2023() ? ui::NORMAL_SEPARATOR
- : ui::LOWER_SEPARATOR);
- CreateZoomMenu();
- AddSeparator(features::IsChromeRefresh2023() ? ui::NORMAL_SEPARATOR
- : ui::UPPER_SEPARATOR);
+ if (IsCommandIdVisible(IDC_ZOOM_MENU)) {
+ AddSeparator(features::IsChromeRefresh2023() ? ui::NORMAL_SEPARATOR
+ : ui::LOWER_SEPARATOR);
+ CreateZoomMenu();
+ AddSeparator(features::IsChromeRefresh2023() ? ui::NORMAL_SEPARATOR
+ : ui::UPPER_SEPARATOR);
+ } else {
+ AddSeparator(ui::NORMAL_SEPARATOR);
+ }
AddItemWithStringId(IDC_PRINT, IDS_PRINT);
@@ -1870,9 +1949,13 @@ void AppMenuModel::Build() {
kMoreToolsMenuItem);
if (!features::IsChromeRefresh2023()) {
- AddSeparator(ui::LOWER_SEPARATOR);
- CreateCutCopyPasteMenu();
- AddSeparator(ui::UPPER_SEPARATOR);
+ if (IsCommandIdVisible(IDC_EDIT_MENU)) {
+ AddSeparator(ui::LOWER_SEPARATOR);
+ CreateCutCopyPasteMenu();
+ AddSeparator(ui::UPPER_SEPARATOR);
+ } else {
+ AddSeparator(ui::NORMAL_SEPARATOR);
+ }
}
if (!features::IsChromeRefresh2023()) {
@@ -1961,6 +2044,11 @@ void AppMenuModel::Build() {
SetCommandIcon(this, IDC_EXIT, kExitMenuIcon);
}
+#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 e9d46ee3b2250..0b1b19140c42e 100644
--- chrome/browser/ui/toolbar/app_menu_model.h
+++ chrome/browser/ui/toolbar/app_menu_model.h
@@ -218,6 +218,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 IsElementIdAlerted(ui::ElementIdentifier element_id) const override;
bool GetAcceleratorForCommandId(int command_id,
@@ -259,6 +260,8 @@ class AppMenuModel : public ui::SimpleMenuModel,
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/find_bar_host.cc chrome/browser/ui/views/find_bar_host.cc
index 0ccfe39eb5696..c9424316b6d14 100644
--- chrome/browser/ui/views/find_bar_host.cc
+++ chrome/browser/ui/views/find_bar_host.cc
@@ -581,6 +581,14 @@ gfx::Rect FindBarHost::GetDialogPosition(gfx::Rect avoid_overlapping_rect) {
// The BrowserView does Layout for the components that we care about
// positioning relative to, so we ask it to tell us where we should go.
gfx::Rect find_bar_bounds = browser_view_->GetFindBarBoundingBox();
+
+#if BUILDFLAG(ENABLE_CEF)
+ if (browser_view_->browser() && browser_view_->browser()->cef_delegate()) {
+ browser_view_->browser()->cef_delegate()->UpdateFindBarBoundingBox(
+ &find_bar_bounds);
+ }
+#endif
+
if (find_bar_bounds.IsEmpty()) {
return gfx::Rect();
}
diff --git chrome/browser/ui/views/frame/browser_frame.cc chrome/browser/ui/views/frame/browser_frame.cc
index cce1835d35be3..75f8aae063ada 100644
--- chrome/browser/ui/views/frame/browser_frame.cc
+++ chrome/browser/ui/views/frame/browser_frame.cc
@@ -114,15 +114,23 @@ ui::ColorProviderKey::SchemeVariant GetSchemeVariant(
////////////////////////////////////////////////////////////////////////////////
// BrowserFrame, public:
+BrowserFrame::BrowserFrame() : BrowserFrame(nullptr) {}
+
BrowserFrame::BrowserFrame(BrowserView* browser_view)
: native_browser_frame_(nullptr),
root_view_(nullptr),
browser_frame_view_(nullptr),
- browser_view_(browser_view) {
- browser_view_->set_frame(this);
+ browser_view_(nullptr) {
set_is_secondary_widget(false);
// Don't focus anything on creation, selecting a tab will set the focus.
set_focus_on_creation(false);
+ if (browser_view)
+ InitBrowserView(browser_view);
+}
+
+void BrowserFrame::InitBrowserView(BrowserView* browser_view) {
+ browser_view_ = browser_view;
+ browser_view_->set_frame(this);
}
BrowserFrame::~BrowserFrame() {}
@@ -228,10 +236,20 @@ void BrowserFrame::LayoutWebAppWindowTitle(
}
int BrowserFrame::GetTopInset() const {
+ if (!browser_frame_view_) {
+ // With CEF the browser may already be part of a larger Views layout. Zero
+ // out the adjustment in BrowserView::GetTopInsetInBrowserView() so that
+ // the browser isn't shifted to the top of the window.
+ return browser_view_->y();
+ }
return browser_frame_view_->GetTopInset(false);
}
void BrowserFrame::UpdateThrobber(bool running) {
+ if (!browser_frame_view_) {
+ // Not supported with CEF Views-hosted DevTools windows.
+ return;
+ }
browser_frame_view_->UpdateThrobber(running);
}
@@ -240,6 +258,8 @@ BrowserNonClientFrameView* BrowserFrame::GetFrameView() const {
}
bool BrowserFrame::UseCustomFrame() const {
+ if (!native_browser_frame_)
+ return true;
return native_browser_frame_->UseCustomFrame();
}
@@ -253,20 +273,30 @@ bool BrowserFrame::ShouldDrawFrameHeader() const {
void BrowserFrame::GetWindowPlacement(gfx::Rect* bounds,
ui::WindowShowState* show_state) const {
+ if (!native_browser_frame_) {
+ *show_state = ui::SHOW_STATE_DEFAULT;
+ return;
+ }
return native_browser_frame_->GetWindowPlacement(bounds, show_state);
}
content::KeyboardEventProcessingResult BrowserFrame::PreHandleKeyboardEvent(
const content::NativeWebKeyboardEvent& event) {
+ if (!native_browser_frame_)
+ return content::KeyboardEventProcessingResult::NOT_HANDLED;
return native_browser_frame_->PreHandleKeyboardEvent(event);
}
bool BrowserFrame::HandleKeyboardEvent(
const content::NativeWebKeyboardEvent& event) {
+ if (!native_browser_frame_)
+ return false;
return native_browser_frame_->HandleKeyboardEvent(event);
}
void BrowserFrame::OnBrowserViewInitViewsComplete() {
+ if (!browser_frame_view_)
+ return;
browser_frame_view_->OnBrowserViewInitViewsComplete();
}
@@ -367,6 +397,8 @@ ui::ColorProviderKey::ThemeInitializerSupplier* BrowserFrame::GetCustomTheme()
}
void BrowserFrame::OnNativeWidgetWorkspaceChanged() {
+ if (!browser_view_)
+ return;
chrome::SaveWindowWorkspace(browser_view_->browser(), GetWorkspace());
chrome::SaveWindowVisibleOnAllWorkspaces(browser_view_->browser(),
IsVisibleOnAllWorkspaces());
@@ -483,6 +515,8 @@ void BrowserFrame::OnNativeThemeUpdated(ui::NativeTheme* observed_theme) {
ui::ColorProviderKey BrowserFrame::GetColorProviderKey() const {
auto key = Widget::GetColorProviderKey();
+ if (!browser_view_)
+ return key;
key.app_controller = browser_view_->browser()->app_controller();
@@ -572,6 +606,13 @@ void BrowserFrame::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:
@@ -637,5 +678,8 @@ bool BrowserFrame::RegenerateFrameOnThemeChange(
}
bool BrowserFrame::IsIncognitoBrowser() const {
+ if (!browser_view_) {
+ return true;
+ }
return browser_view_->browser()->profile()->IsIncognitoProfile();
}
diff --git chrome/browser/ui/views/frame/browser_frame.h chrome/browser/ui/views/frame/browser_frame.h
index 2e973c9e279b0..8662f9cf14b17 100644
--- chrome/browser/ui/views/frame/browser_frame.h
+++ chrome/browser/ui/views/frame/browser_frame.h
@@ -58,7 +58,9 @@ enum class TabDragKind {
// This is a virtual interface that allows system specific browser frames.
class BrowserFrame : public views::Widget, public views::ContextMenuController {
public:
+ BrowserFrame();
explicit BrowserFrame(BrowserView* browser_view);
+ void InitBrowserView(BrowserView* browser_view);
BrowserFrame(const BrowserFrame&) = delete;
BrowserFrame& operator=(const BrowserFrame&) = delete;
@@ -137,7 +139,7 @@ class BrowserFrame : public views::Widget, public views::ContextMenuController {
// 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;
@@ -175,17 +177,17 @@ class BrowserFrame : public views::Widget, public views::ContextMenuController {
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:
void OnTouchUiChanged();
// 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/browser_view.cc chrome/browser/ui/views/frame/browser_view.cc
index f764d5edc704c..b7d5ee188736e 100644
--- chrome/browser/ui/views/frame/browser_view.cc
+++ chrome/browser/ui/views/frame/browser_view.cc
@@ -351,11 +351,10 @@ using content::NativeWebKeyboardEvent;
using content::WebContents;
using web_modal::WebContentsModalDialogHost;
-namespace {
+// static
+const char BrowserView::kBrowserViewKey[] = "__BROWSER_VIEW__";
-// The name of a key to store on the window handle so that other code can
-// locate this object using just the handle.
-const char* const kBrowserViewKey = "__BROWSER_VIEW__";
+namespace {
#if BUILDFLAG(IS_CHROMEOS_ASH)
// UMA histograms that record animation smoothness for tab loading animation.
@@ -688,6 +687,14 @@ class BrowserViewLayoutDelegateImpl : public BrowserViewLayoutDelegate {
return browser_view_->frame()->GetTopInset() - browser_view_->y();
}
+ void UpdateDialogTopInsetInBrowserView(int* dialog_top_y) const override {
+#if BUILDFLAG(ENABLE_CEF)
+ if (auto cef_delegate = browser_view_->browser_->cef_delegate()) {
+ cef_delegate->UpdateDialogTopInset(dialog_top_y);
+ }
+#endif
+ }
+
bool IsToolbarVisible() const override {
return browser_view_->IsToolbarVisible();
}
@@ -839,11 +846,21 @@ class BrowserView::AccessibilityModeObserver : public ui::AXModeObserver {
///////////////////////////////////////////////////////////////////////////////
// BrowserView, public:
+BrowserView::BrowserView() : BrowserView(nullptr) {}
+
BrowserView::BrowserView(std::unique_ptr<Browser> browser)
: views::ClientView(nullptr, nullptr),
- browser_(std::move(browser)),
accessibility_mode_observer_(
std::make_unique<AccessibilityModeObserver>(this)) {
+ if (browser) {
+ InitBrowser(std::move(browser));
+ }
+}
+
+void BrowserView::InitBrowser(std::unique_ptr<Browser> browser) {
+ DCHECK(!browser_);
+ browser_ = std::move(browser);
+
// Store the actions so that the access is available for other classes.
if (features::IsSidePanelPinningEnabled()) {
browser_->SetUserData(BrowserActions::UserDataKey(),
@@ -944,8 +961,15 @@ BrowserView::BrowserView(std::unique_ptr<Browser> browser)
contents_container->SetLayoutManager(std::make_unique<ContentsLayoutManager>(
devtools_web_view_, contents_web_view_, watermark_view_));
- toolbar_ = top_container_->AddChildView(
- std::make_unique<ToolbarView>(browser_.get(), this));
+ toolbar_ = OverrideCreateToolbar();
+ if (!toolbar_) {
+ toolbar_ = new ToolbarView(browser_.get(), this, absl::nullopt);
+ } else {
+ browser_->set_toolbar_overridden(true);
+ // Update state that depends on the above flag.
+ browser_->command_controller()->FullscreenStateChanged();
+ }
+ top_container_->AddChildView(base::WrapUnique(toolbar_.get()));
contents_separator_ =
top_container_->AddChildView(std::make_unique<ContentsSeparator>());
@@ -1022,7 +1046,9 @@ BrowserView::~BrowserView() {
// All the tabs should have been destroyed already. If we were closed by the
// OS with some tabs than the NativeBrowserFrame should have destroyed them.
+ if (browser_) {
DCHECK_EQ(0, browser_->tab_strip_model()->count());
+ }
// Stop the animation timer explicitly here to avoid running it in a nested
// message loop, which may run by Browser destructor.
@@ -1036,12 +1062,14 @@ BrowserView::~BrowserView() {
// child views and it is an observer for avatar toolbar button if any.
autofill_bubble_handler_.reset();
+ if (browser_) {
auto* global_registry =
extensions::ExtensionCommandsGlobalRegistry::Get(browser_->profile());
if (global_registry->registry_for_active_window() ==
extension_keybinding_registry_.get()) {
global_registry->set_registry_for_active_window(nullptr);
}
+ }
// The TabStrip attaches a listener to the model. Make sure we shut down the
// TabStrip first so that it can cleanly remove the listener.
@@ -1065,7 +1093,9 @@ BrowserView::~BrowserView() {
// `SidePanelUI::RemoveSidePanelUIForBrowser()` deletes the
// SidePanelCoordinator.
+ if (browser()) {
SidePanelUI::RemoveSidePanelUIForBrowser(browser());
+ }
}
// static
@@ -2039,9 +2069,14 @@ void BrowserView::OnExclusiveAccessUserInput() {
bool BrowserView::ShouldHideUIForFullscreen() const {
// Immersive mode needs UI for the slide-down top panel.
- if (immersive_mode_controller_->IsEnabled())
+ // Avoid callback into |immersive_mode_controller_| during construction.
+ // See CEF issue #3527.
+ if (immersive_mode_controller_ &&
+ immersive_mode_controller_->IsEnabled())
return false;
+ if (!frame_->GetFrameView())
+ return false;
return frame_->GetFrameView()->ShouldHideTopUIForFullscreen();
}
@@ -3172,7 +3207,8 @@ DownloadShelf* BrowserView::GetDownloadShelf() {
}
DownloadBubbleUIController* BrowserView::GetDownloadBubbleUIController() {
- DCHECK(toolbar_button_provider_);
+ if (!toolbar_button_provider_)
+ return nullptr;
if (auto* download_button = toolbar_button_provider_->GetDownloadButton())
return download_button->bubble_controller();
return nullptr;
@@ -3727,7 +3763,8 @@ void BrowserView::ReparentTopContainerForEndOfImmersive() {
if (top_container()->parent() == this)
return;
- overlay_view_->SetVisible(false);
+ if (overlay_view_)
+ overlay_view_->SetVisible(false);
top_container()->DestroyLayer();
AddChildViewAt(top_container(), 0);
EnsureFocusOrder();
@@ -4209,11 +4246,38 @@ 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() &&
+ !browser_->SupportsWindowFeature(Browser::FEATURE_TITLEBAR);
+ if (frameless_pip) {
+ if (auto frame_view = frame()->GetFrameView()) {
+ int result = frame_view->NonClientHitTest(location);
+ if (result == HTTOP || result == HTTOPLEFT || result == HTTOPRIGHT) {
+ // Allow resize from the top of a frameless window.
+ return false;
+ }
+ }
+ }
+#endif
+
+ absl::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 = browser()->app_controller();
- 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(),
@@ -4222,7 +4286,7 @@ 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(
+ 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);
@@ -4333,8 +4397,10 @@ void BrowserView::Layout(PassKey) {
// TODO(jamescook): Why was this in the middle of layout code?
toolbar_->location_bar()->omnibox_view()->SetFocusBehavior(
- IsToolbarVisible() ? FocusBehavior::ALWAYS : FocusBehavior::NEVER);
- frame()->GetFrameView()->UpdateMinimumSize();
+ (IsToolbarVisible() || browser_->toolbar_overridden()) ?
+ FocusBehavior::ALWAYS : FocusBehavior::NEVER);
+ if (frame()->GetFrameView())
+ frame()->GetFrameView()->UpdateMinimumSize();
// Some of the situations when the BrowserView is laid out are:
// - Enter/exit immersive fullscreen mode.
@@ -4400,6 +4466,11 @@ void BrowserView::AddedToWidget() {
SetThemeProfileForWindow(GetNativeWindow(), browser_->profile());
#endif
+ // This browser view may already have a custom button provider set (e.g the
+ // hosted app frame).
+ if (!toolbar_button_provider_)
+ SetToolbarButtonProvider(toolbar_);
+
toolbar_->Init();
// TODO(pbos): Investigate whether the side panels should be creatable when
@@ -4448,13 +4519,9 @@ void BrowserView::AddedToWidget() {
EnsureFocusOrder();
- // This browser view may already have a custom button provider set (e.g the
- // hosted app frame).
- if (!toolbar_button_provider_)
- SetToolbarButtonProvider(toolbar_);
-
frame_->OnBrowserViewInitViewsComplete();
- frame_->GetFrameView()->UpdateMinimumSize();
+ if (frame_->GetFrameView())
+ frame_->GetFrameView()->UpdateMinimumSize();
using_native_frame_ = frame_->ShouldUseNativeFrame();
MaybeInitializeWebUITabStrip();
@@ -4885,7 +4952,8 @@ void BrowserView::ProcessFullscreen(bool fullscreen,
// Undo our anti-jankiness hacks and force a re-layout.
in_process_fullscreen_ = false;
ToolbarSizeChanged(false);
- frame_->GetFrameView()->OnFullscreenStateChanged();
+ if (frame_->GetFrameView())
+ frame_->GetFrameView()->OnFullscreenStateChanged();
}
bool BrowserView::ShouldUseImmersiveFullscreenForUrl(const GURL& url) const {
@@ -5307,6 +5375,8 @@ Profile* BrowserView::GetProfile() {
}
void BrowserView::UpdateUIForTabFullscreen() {
+ if (!frame_->GetFrameView())
+ return;
frame()->GetFrameView()->UpdateFullscreenTopUI();
}
@@ -5329,6 +5399,8 @@ void BrowserView::HideDownloadShelf() {
}
bool BrowserView::CanUserExitFullscreen() const {
+ if (!frame_->GetFrameView())
+ return true;
return frame_->GetFrameView()->CanUserExitFullscreen();
}
diff --git chrome/browser/ui/views/frame/browser_view.h chrome/browser/ui/views/frame/browser_view.h
index 836b5aa549183..a336aca64101d 100644
--- chrome/browser/ui/views/frame/browser_view.h
+++ chrome/browser/ui/views/frame/browser_view.h
@@ -137,11 +137,16 @@ class BrowserView : public BrowserWindow,
METADATA_HEADER(BrowserView, views::ClientView)
public:
+ BrowserView();
explicit BrowserView(std::unique_ptr<Browser> browser);
+ void InitBrowser(std::unique_ptr<Browser> browser);
BrowserView(const BrowserView&) = delete;
BrowserView& operator=(const BrowserView&) = delete;
~BrowserView() override;
+ // Key used to bind BrowserView to the Widget with which it is associated.
+ static const char kBrowserViewKey[];
+
void set_frame(BrowserFrame* frame) {
frame_ = frame;
paint_as_active_subscription_ =
@@ -863,6 +868,9 @@ class BrowserView : public BrowserWindow,
const gfx::Rect& contents_webview_bounds,
const gfx::Rect& local_webview_container_bounds);
+ protected:
+ virtual ToolbarView* OverrideCreateToolbar() { return nullptr; }
+
private:
// Do not friend BrowserViewLayout. Use the BrowserViewLayoutDelegate
// interface to keep these two classes decoupled and testable.
diff --git chrome/browser/ui/views/frame/browser_view_layout.cc chrome/browser/ui/views/frame/browser_view_layout.cc
index 0991a57cccfe8..3ed3d43497460 100644
--- chrome/browser/ui/views/frame/browser_view_layout.cc
+++ chrome/browser/ui/views/frame/browser_view_layout.cc
@@ -48,6 +48,10 @@
#include "ui/views/window/client_view.h"
#include "ui/views/window/hit_test_utils.h"
+#if BUILDFLAG(ENABLE_CEF)
+#include "cef/libcef/browser/chrome/views/chrome_views_util.h"
+#endif
+
using views::View;
using web_modal::ModalDialogHostObserver;
using web_modal::WebContentsModalDialogHost;
@@ -92,6 +96,10 @@ class BrowserViewLayout::WebContentsModalDialogHostViews
observer.OnHostDestroying();
}
+ bool HasObservers() const {
+ return !observer_list_.empty();
+ }
+
void NotifyPositionRequiresUpdate() {
for (ModalDialogHostObserver& observer : observer_list_)
observer.OnPositionRequiresUpdate();
@@ -102,7 +110,7 @@ class BrowserViewLayout::WebContentsModalDialogHostViews
views::View* view = browser_view_layout_->contents_container_;
gfx::Rect rect = view->ConvertRectToWidget(view->GetLocalBounds());
const int middle_x = rect.x() + rect.width() / 2;
- const int top = browser_view_layout_->dialog_top_y_;
+ const int top = GetDialogTopY();
return gfx::Point(middle_x - size.width() / 2, top);
}
@@ -117,7 +125,7 @@ class BrowserViewLayout::WebContentsModalDialogHostViews
gfx::Size GetMaximumDialogSize() override {
views::View* view = browser_view_layout_->contents_container_;
gfx::Rect content_area = view->ConvertRectToWidget(view->GetLocalBounds());
- const int top = browser_view_layout_->dialog_top_y_;
+ const int top = GetDialogTopY();
return gfx::Size(content_area.width(), content_area.bottom() - top);
}
@@ -131,6 +139,13 @@ class BrowserViewLayout::WebContentsModalDialogHostViews
return GetHostWidget()->GetNativeView();
}
+ int GetDialogTopY() const {
+ int dialog_top_y = browser_view_layout_->dialog_top_y_;
+ browser_view_layout_->delegate_->UpdateDialogTopInsetInBrowserView(
+ &dialog_top_y);
+ return dialog_top_y;
+ }
+
// Add/remove observer.
void AddObserver(ModalDialogHostObserver* observer) override {
observer_list_.AddObserver(observer);
@@ -441,6 +456,8 @@ void BrowserViewLayout::Layout(views::View* browser_view) {
if (exclusive_access_bubble)
exclusive_access_bubble->RepositionIfVisible();
+ // 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());
@@ -454,6 +471,7 @@ void BrowserViewLayout::Layout(views::View* browser_view) {
latest_dialog_bounds_in_screen_ = dialog_bounds_in_screen;
dialog_host_->NotifyPositionRequiresUpdate();
}
+ }
}
// Return the preferred size which is the size required to give each
@@ -583,6 +601,13 @@ int BrowserViewLayout::LayoutWebUITabStrip(int top) {
int BrowserViewLayout::LayoutToolbar(int top) {
TRACE_EVENT0("ui", "BrowserViewLayout::LayoutToolbar");
+#if BUILDFLAG(ENABLE_CEF)
+ if (cef::IsCefView(toolbar_)) {
+ // CEF may take ownership of the toolbar. Early exit to avoid the DCHECK
+ // in LayoutManager::SetViewVisibility().
+ return top;
+ }
+#endif
int browser_view_width = vertical_layout_rect_.width();
bool toolbar_visible = delegate_->IsToolbarVisible();
int height = toolbar_visible ? toolbar_->GetPreferredSize().height() : 0;
diff --git chrome/browser/ui/views/frame/browser_view_layout_delegate.h chrome/browser/ui/views/frame/browser_view_layout_delegate.h
index 29ad5517bd3c9..b0fe093467abc 100644
--- chrome/browser/ui/views/frame/browser_view_layout_delegate.h
+++ chrome/browser/ui/views/frame/browser_view_layout_delegate.h
@@ -28,6 +28,7 @@ class BrowserViewLayoutDelegate {
const gfx::Rect& available_space,
views::Label& window_title_label) const = 0;
virtual int GetTopInsetInBrowserView() const = 0;
+ virtual void UpdateDialogTopInsetInBrowserView(int* dialog_top_y) const = 0;
virtual bool IsToolbarVisible() const = 0;
virtual bool IsBookmarkBarVisible() const = 0;
virtual bool IsContentsSeparatorEnabled() const = 0;
diff --git chrome/browser/ui/views/frame/contents_web_view.cc chrome/browser/ui/views/frame/contents_web_view.cc
index 71445bfab1824..c77750ea2a820 100644
--- chrome/browser/ui/views/frame/contents_web_view.cc
+++ chrome/browser/ui/views/frame/contents_web_view.cc
@@ -28,6 +28,12 @@ ContentsWebView::ContentsWebView(content::BrowserContext* browser_context)
: views::WebView(browser_context),
status_bubble_(nullptr) {
SetProperty(views::kElementIdentifierKey, kContentsWebViewElementId);
+
+ // Mouse events on draggable regions will not be handled by the WebView.
+ // Avoid the resulting DCHECK in NativeViewHost::OnMousePressed by
+ // configuring the NativeViewHost not to process events via the view
+ // hierarchy.
+ holder()->SetCanProcessEventsWithinSubtree(false);
}
ContentsWebView::~ContentsWebView() {
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 ee9e4cf7d4d92..e6c53660a4407 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
@@ -610,6 +610,11 @@ PictureInPictureBrowserFrameView::PictureInPictureBrowserFrameView(
frame->GetNativeWindow()->SetEventTargeter(
std::make_unique<chromeos::InteriorResizeHandleTargeter>());
#endif
+
+ if (!browser_view->browser()->SupportsWindowFeature(
+ Browser::FEATURE_TITLEBAR)) {
+ top_bar_container_view_->SetVisible(false);
+ }
}
PictureInPictureBrowserFrameView::~PictureInPictureBrowserFrameView() {
@@ -737,18 +742,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 =
+ browser_view()->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(),
+ browser_view()->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(
@@ -817,7 +846,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_) {
@@ -1309,7 +1339,8 @@ gfx::Insets PictureInPictureBrowserFrameView::ResizeBorderInsets() 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/omnibox/omnibox_popup_closer.cc chrome/browser/ui/views/omnibox/omnibox_popup_closer.cc
index b862ceac7225d..9575440a77d67 100644
--- chrome/browser/ui/views/omnibox/omnibox_popup_closer.cc
+++ chrome/browser/ui/views/omnibox/omnibox_popup_closer.cc
@@ -27,7 +27,8 @@ OmniboxPopupCloser::OmniboxPopupCloser(BrowserView* browser_view)
OmniboxPopupCloser::~OmniboxPopupCloser() = default;
void OmniboxPopupCloser::OnMouseEvent(ui::MouseEvent* event) {
- if (!browser_view_->browser()->is_delete_scheduled() &&
+ if (browser_view_->browser() &&
+ !browser_view_->browser()->is_delete_scheduled() &&
event->type() == ui::ET_MOUSE_PRESSED) {
LocationBarView* location_bar_view = browser_view_->GetLocationBarView();
CHECK(location_bar_view);
diff --git chrome/browser/ui/views/page_action/page_action_icon_controller.cc chrome/browser/ui/views/page_action/page_action_icon_controller.cc
index 55d99c5f53e92..172ac465b6f21 100644
--- chrome/browser/ui/views/page_action/page_action_icon_controller.cc
+++ chrome/browser/ui/views/page_action/page_action_icon_controller.cc
@@ -97,6 +97,12 @@ void PageActionIconController::Init(const PageActionIconParams& params,
};
for (PageActionIconType type : params.types_enabled) {
+#if BUILDFLAG(ENABLE_CEF)
+ if (params.browser && params.browser->cef_delegate() &&
+ !params.browser->cef_delegate()->IsPageActionIconVisible(type)) {
+ continue;
+ }
+#endif
switch (type) {
case PageActionIconType::kPaymentsOfferNotification:
add_page_action_icon(
diff --git chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
index a8fc1df0e8fae..cc496ba91716e 100644
--- chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
+++ chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -554,29 +554,41 @@ gfx::Range BrowserTabStripController::ListTabsInGroup(
}
bool BrowserTabStripController::IsFrameCondensed() const {
+ if (!GetFrameView())
+ return false;
return GetFrameView()->IsFrameCondensed();
}
bool BrowserTabStripController::HasVisibleBackgroundTabShapes() const {
+ if (!GetFrameView())
+ return false;
return GetFrameView()->HasVisibleBackgroundTabShapes(
BrowserFrameActiveState::kUseCurrent);
}
bool BrowserTabStripController::EverHasVisibleBackgroundTabShapes() const {
+ if (!GetFrameView())
+ return false;
return GetFrameView()->EverHasVisibleBackgroundTabShapes();
}
bool BrowserTabStripController::CanDrawStrokes() const {
+ if (!GetFrameView())
+ return false;
return GetFrameView()->CanDrawStrokes();
}
SkColor BrowserTabStripController::GetFrameColor(
BrowserFrameActiveState active_state) const {
+ if (!GetFrameView())
+ return SK_ColorWHITE;
return GetFrameView()->GetFrameColor(active_state);
}
std::optional<int> BrowserTabStripController::GetCustomBackgroundId(
BrowserFrameActiveState active_state) const {
+ if (!GetFrameView())
+ return std::nullopt;
return GetFrameView()->GetCustomBackgroundId(active_state);
}
diff --git chrome/browser/ui/views/toolbar/toolbar_view.cc chrome/browser/ui/views/toolbar/toolbar_view.cc
index d65dc839c20e7..cf4caa7301108 100644
--- chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -191,7 +191,7 @@ class TabstripLikeBackground : public views::Background {
void Paint(gfx::Canvas* canvas, views::View* view) const override {
bool painted = TopContainerBackground::PaintThemeCustomImage(canvas, view,
browser_view_);
- if (!painted) {
+ if (!painted && browser_view_->frame()->GetFrameView()) {
SkColor frame_color =
browser_view_->frame()->GetFrameView()->GetFrameColor(
BrowserFrameActiveState::kUseCurrent);
@@ -221,12 +221,13 @@ END_METADATA
////////////////////////////////////////////////////////////////////////////////
// ToolbarView, public:
-ToolbarView::ToolbarView(Browser* browser, BrowserView* browser_view)
+ToolbarView::ToolbarView(Browser* browser, BrowserView* browser_view,
+ absl::optional<DisplayMode> display_mode)
: AnimationDelegateViews(this),
browser_(browser),
browser_view_(browser_view),
app_menu_icon_controller_(browser->profile(), this),
- display_mode_(GetDisplayMode(browser)) {
+ display_mode_(display_mode ? *display_mode : GetDisplayMode(browser)) {
SetID(VIEW_ID_TOOLBAR);
container_view_ = AddChildView(std::make_unique<ContainerView>());
@@ -251,6 +252,19 @@ ToolbarView::~ToolbarView() {
}
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
@@ -275,12 +289,12 @@ void ToolbarView::Init() {
auto location_bar = std::make_unique<LocationBarView>(
browser_, browser_->profile(), browser_->command_controller(), this,
- display_mode_ != DisplayMode::NORMAL);
+ display_mode_ != DisplayMode::NORMAL && !browser_->toolbar_overridden());
// Make sure the toolbar shows by default.
size_animation_.Reset(1);
std::unique_ptr<DownloadToolbarButtonView> download_button;
- if (download::IsDownloadBubbleEnabled()) {
+ if (download::IsDownloadBubbleEnabled() && BUTTON_VISIBLE(kDownload)) {
download_button =
std::make_unique<DownloadToolbarButtonView>(browser_view_);
}
@@ -362,8 +376,10 @@ void ToolbarView::Init() {
}
}
std::unique_ptr<media_router::CastToolbarButton> cast;
- if (media_router::MediaRouterEnabled(browser_->profile()))
+ if (media_router::MediaRouterEnabled(browser_->profile()) &&
+ BUTTON_VISIBLE(kCast)) {
cast = media_router::CastToolbarButton::Create(browser_);
+ }
std::unique_ptr<MediaToolbarButtonView> media_button;
if (base::FeatureList::IsEnabled(media::kGlobalMediaControls)) {
@@ -373,7 +389,8 @@ void ToolbarView::Init() {
std::unique_ptr<send_tab_to_self::SendTabToSelfToolbarIconView>
send_tab_to_self_button;
- if (!browser_->profile()->IsOffTheRecord()) {
+ if (!browser_->profile()->IsOffTheRecord() &&
+ BUTTON_VISIBLE(kSendTabToSelf)) {
send_tab_to_self_button =
std::make_unique<send_tab_to_self::SendTabToSelfToolbarIconView>(
browser_view_);
@@ -452,7 +469,7 @@ void ToolbarView::Init() {
send_tab_to_self_button_ =
container_view_->AddChildView(std::move(send_tab_to_self_button));
- if (!features::IsSidePanelPinningEnabled()) {
+ if (!features::IsSidePanelPinningEnabled() && BUTTON_VISIBLE(kSidePanel)) {
if (companion::IsCompanionFeatureEnabled()) {
side_panel_container_ = container_view_->AddChildView(
std::make_unique<SidePanelToolbarContainer>(browser_view_));
@@ -811,7 +828,7 @@ void ToolbarView::Layout(PassKey) {
if (display_mode_ == DisplayMode::NORMAL) {
LayoutCommon();
- if (features::IsChromeRefresh2023()) {
+ if (features::IsChromeRefresh2023() && !browser_->toolbar_overridden()) {
UpdateClipPath();
}
}
diff --git chrome/browser/ui/views/toolbar/toolbar_view.h chrome/browser/ui/views/toolbar/toolbar_view.h
index 325b73a399d3f..9242aed24ef35 100644
--- chrome/browser/ui/views/toolbar/toolbar_view.h
+++ chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -93,7 +93,8 @@ class ToolbarView : public views::AccessiblePaneView,
// needs to be displayed.
};
- ToolbarView(Browser* browser, BrowserView* browser_view);
+ ToolbarView(Browser* browser, BrowserView* browser_view,
+ absl::optional<DisplayMode> display_mode);
ToolbarView(const ToolbarView&) = delete;
ToolbarView& operator=(const ToolbarView&) = delete;
~ToolbarView() override;
diff --git chrome/browser/ui/web_applications/draggable_region_host_impl.cc chrome/browser/ui/web_applications/draggable_region_host_impl.cc
index 8980b03f2c945..831f6dd681cb9 100644
--- chrome/browser/ui/web_applications/draggable_region_host_impl.cc
+++ chrome/browser/ui/web_applications/draggable_region_host_impl.cc
@@ -11,6 +11,28 @@
#include "chrome/common/chrome_features.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+namespace {
+
+bool IsSupported(Browser* browser) {
+ // May be nullptr when running with Alloy style.
+ if (!browser)
+ return false;
+
+ if (web_app::AppBrowserController::IsWebApp(browser))
+ return true;
+
+#if BUILDFLAG(ENABLE_CEF)
+ if (browser->cef_delegate() &&
+ browser->cef_delegate()->SupportsDraggableRegion()) {
+ return true;
+ }
+#endif
+
+ return false;
+}
+
+} // namespace
+
DraggableRegionsHostImpl::DraggableRegionsHostImpl(
content::RenderFrameHost& render_frame_host,
mojo::PendingReceiver<chrome::mojom::DraggableRegions> receiver)
@@ -28,7 +50,7 @@ void DraggableRegionsHostImpl::CreateIfAllowed(
auto* browser = chrome::FindBrowserWithTab(web_contents);
// We only want to bind the receiver for PWAs.
- if (!web_app::AppBrowserController::IsWebApp(browser))
+ if (!IsSupported(browser))
return;
// The object is bound to the lifetime of |render_frame_host| and the mojo
@@ -43,7 +65,7 @@ void DraggableRegionsHostImpl::UpdateDraggableRegions(
auto* browser = chrome::FindBrowserWithTab(web_contents);
// When a WebApp browser's WebContents is reparented to a tabbed browser, a
// draggable regions update may race with the reparenting logic.
- if (!web_app::AppBrowserController::IsWebApp(browser))
+ if (!IsSupported(browser))
return;
SkRegion sk_region;
@@ -56,5 +78,12 @@ void DraggableRegionsHostImpl::UpdateDraggableRegions(
}
auto* app_browser_controller = browser->app_controller();
- app_browser_controller->UpdateDraggableRegion(sk_region);
+ if (app_browser_controller) {
+ app_browser_controller->UpdateDraggableRegion(sk_region);
+ }
+#if BUILDFLAG(ENABLE_CEF)
+ else {
+ browser->cef_delegate()->UpdateDraggableRegion(sk_region);
+ }
+#endif
}