b2b82985创建于 2023年1月5日历史提交
diff --git chrome/browser/ui/browser_command_controller.cc chrome/browser/ui/browser_command_controller.cc
index 92f10fac6b017..cc53da3a0b32e 100644
--- chrome/browser/ui/browser_command_controller.cc
+++ chrome/browser/ui/browser_command_controller.cc
@@ -368,8 +368,10 @@ bool BrowserCommandController::ExecuteCommandWithDisposition(
   // CommandUpdaterDelegate and CommandUpdater declare this function so we
   // choose to not implement CommandUpdaterDelegate inside this class and
   // therefore command_updater_ doesn't have the delegate set).
-  if (!SupportsCommand(id) || !IsCommandEnabled(id))
+  if (!SupportsCommand(id) || !IsCommandEnabled(id)) {
+    LOG(WARNING) << "Invalid/disabled command " << id;
     return false;
+  }
 
   // No commands are enabled if there is not yet any selected tab.
   // TODO(pkasting): It seems like we should not need this, because either
@@ -979,11 +981,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();
 }
 
 void BrowserCommandController::InitCommandState() {
diff --git chrome/browser/ui/views/frame/browser_frame.cc chrome/browser/ui/views/frame/browser_frame.cc
index 6264562165ced..d20f970ba1254 100644
--- chrome/browser/ui/views/frame/browser_frame.cc
+++ chrome/browser/ui/views/frame/browser_frame.cc
@@ -73,15 +73,23 @@ bool IsUsingGtkTheme(Profile* profile) {
 ////////////////////////////////////////////////////////////////////////////////
 // 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() {}
@@ -141,6 +149,12 @@ gfx::Rect BrowserFrame::GetBoundsForTabStripRegion(
 }
 
 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);
 }
 
@@ -175,15 +189,21 @@ void BrowserFrame::GetWindowPlacement(gfx::Rect* bounds,
 
 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();
 }
 
@@ -244,6 +264,8 @@ const ui::ThemeProvider* BrowserFrame::GetThemeProvider() const {
 
 ui::ColorProviderManager::InitializerSupplier* BrowserFrame::GetCustomTheme()
     const {
+  if (!browser_view_)
+    return nullptr;
   Browser* browser = browser_view_->browser();
   auto* app_controller = browser->app_controller();
   // Ignore GTK+ for web apps with window-controls-overlay as the
@@ -369,7 +391,8 @@ void BrowserFrame::SelectNativeTheme() {
   // Select between regular, dark and GTK theme.
   ui::NativeTheme* native_theme = ui::NativeTheme::GetInstanceForNativeUi();
 
-  if (browser_view_->browser()->profile()->IsIncognitoProfile()) {
+  if (browser_view_ &&
+      browser_view_->browser()->profile()->IsIncognitoProfile()) {
     // If the flag is enabled, then no matter if we are using the default theme
     // or not we always use the dark ui instance.
     if (base::FeatureList::IsEnabled(
diff --git chrome/browser/ui/views/frame/browser_frame.h chrome/browser/ui/views/frame/browser_frame.h
index 6a1e9abbc66aa..aa9e3ebe2599c 100644
--- chrome/browser/ui/views/frame/browser_frame.h
+++ chrome/browser/ui/views/frame/browser_frame.h
@@ -53,7 +53,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;
diff --git chrome/browser/ui/views/frame/browser_view.cc chrome/browser/ui/views/frame/browser_view.cc
index 8138e50a55072..e01b2274119b8 100644
--- chrome/browser/ui/views/frame/browser_view.cc
+++ chrome/browser/ui/views/frame/browser_view.cc
@@ -291,11 +291,10 @@ using content::WebContents;
 using views::ColumnSet;
 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.
@@ -683,11 +682,22 @@ class BrowserView::SidePanelButtonHighlighter : public views::ViewObserver {
 ///////////////////////////////////////////////////////////////////////////////
 // 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);
+
+  immersive_mode_controller_ = chrome::CreateImmersiveModeController();
+
   SetShowIcon(::ShouldShowWindowIcon(browser_.get()));
 
   // In forced app mode, all size controls are always disabled. Otherwise, use
@@ -701,7 +711,6 @@ BrowserView::BrowserView(std::unique_ptr<Browser> browser)
   }
 
   browser_->tab_strip_model()->AddObserver(this);
-  immersive_mode_controller_ = chrome::CreateImmersiveModeController();
 
   // Top container holds tab strip region and toolbar and lives at the front of
   // the view hierarchy.
@@ -749,8 +758,15 @@ BrowserView::BrowserView(std::unique_ptr<Browser> browser)
   contents_container->SetLayoutManager(std::make_unique<ContentsLayoutManager>(
       devtools_web_view_, contents_web_view_));
 
-  toolbar_ = top_container_->AddChildView(
-      std::make_unique<ToolbarView>(browser_.get(), this));
+  toolbar_ = OverrideCreateToolbar(browser_.get(), this);
+  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>());
@@ -1587,6 +1603,8 @@ bool BrowserView::ShouldHideUIForFullscreen() const {
   if (immersive_mode_controller_->IsEnabled())
     return false;
 
+  if (!frame_->GetFrameView())
+    return false;
   return frame_->GetFrameView()->ShouldHideTopUIForFullscreen();
 }
 
@@ -2731,7 +2749,8 @@ BrowserView::GetNativeViewHostsForTopControlsSlide() const {
 }
 
 void BrowserView::ReparentTopContainerForEndOfImmersive() {
-  overlay_view_->SetVisible(false);
+  if (overlay_view_)
+    overlay_view_->SetVisible(false);
   top_container()->DestroyLayer();
   AddChildViewAt(top_container(), 0);
   EnsureFocusOrder();
@@ -3220,8 +3239,10 @@ void BrowserView::Layout() {
 
   // 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.
@@ -3284,6 +3305,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): Manage this either inside SidePanel or the corresponding button
@@ -3336,13 +3362,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();
@@ -3761,7 +3783,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 {
@@ -4052,6 +4075,8 @@ Profile* BrowserView::GetProfile() {
 }
 
 void BrowserView::UpdateUIForTabFullscreen() {
+  if (!frame_->GetFrameView())
+    return;
   frame()->GetFrameView()->UpdateFullscreenTopUI();
 }
 
@@ -4074,6 +4099,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 02d9793dd5c8d..fe8b0cef88375 100644
--- chrome/browser/ui/views/frame/browser_view.h
+++ chrome/browser/ui/views/frame/browser_view.h
@@ -125,11 +125,16 @@ class BrowserView : public BrowserWindow,
                     public webapps::AppBannerManager::Observer {
  public:
   METADATA_HEADER(BrowserView);
+  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; }
   BrowserFrame* frame() const { return frame_; }
 
@@ -705,6 +710,12 @@ class BrowserView : public BrowserWindow,
       const std::map<std::string, std::string>& extra_data) override;
 #endif
 
+ protected:
+  virtual ToolbarView* OverrideCreateToolbar(Browser* browser,
+                                             BrowserView* browser_view) {
+    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 1d22e4b057c6c..d73b547f09e0b 100644
--- chrome/browser/ui/views/frame/browser_view_layout.cc
+++ chrome/browser/ui/views/frame/browser_view_layout.cc
@@ -40,6 +40,10 @@
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/client_view.h"
 
+#if BUILDFLAG(ENABLE_CEF)
+#include "cef/libcef/browser/chrome/views/chrome_views_util.h"
+#endif
+
 using views::View;
 using web_modal::WebContentsModalDialogHost;
 using web_modal::ModalDialogHostObserver;
@@ -458,6 +462,11 @@ int BrowserViewLayout::LayoutWebUITabStrip(int top) {
 
 int BrowserViewLayout::LayoutToolbar(int top) {
   TRACE_EVENT0("ui", "BrowserViewLayout::LayoutToolbar");
+  if (cef::IsCefView(toolbar_)) {
+    // CEF may take ownership of the toolbar. Early exit to avoid the DCHECK
+    // in LayoutManager::SetViewVisibility().
+    return top;
+  }
   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/tabs/browser_tab_strip_controller.cc chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
index b5706099ce923..07cebc2f8b65f 100644
--- chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
+++ chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -559,37 +559,53 @@ 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::ShouldPaintAsActiveFrame() const {
+  if (!GetFrameView())
+    return false;
   return GetFrameView()->ShouldPaintAsActive();
 }
 
 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);
 }
 
 SkColor BrowserTabStripController::GetToolbarTopSeparatorColor() const {
+  if (!GetFrameView())
+    return SK_ColorWHITE;
   return GetFrameView()->GetToolbarTopSeparatorColor();
 }
 
 absl::optional<int> BrowserTabStripController::GetCustomBackgroundId(
     BrowserFrameActiveState active_state) const {
+  if (!GetFrameView())
+    return absl::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 b5098154b2f7e..4a3121cedf083 100644
--- chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -168,12 +168,13 @@ auto& GetViewCommandMap() {
 ////////////////////////////////////////////////////////////////////////////////
 // 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);
 
   UpgradeDetector::GetInstance()->AddObserver(this);
@@ -208,7 +209,7 @@ void ToolbarView::Init() {
 #endif
   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);
 
diff --git chrome/browser/ui/views/toolbar/toolbar_view.h chrome/browser/ui/views/toolbar/toolbar_view.h
index 79efc97f711f1..6915479340275 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;