Each browser window has the same structure, depicted below:
NativeWidget
.BrowserViewLayoutDelegate
.BrowserViewLayout
retrieves information about the layout. Implemented by BrowserView
; designed to be able to be mocked.┌─────────────────────────────────────┐ ┌───────────────────────┐ │ BrowserWidget │ ↔ │ BrowserNativeWidget + │ │ ┌─────────────────────────────────┐ │ │ NativeWidget │ │ │ RootView │ │ └───────────────────────┘ │ │ ┌─────────────────────────────┐ │ │ │ │ │ NonClientView │ │ │ │ │ │ ┌─────────────────────────┐ │ │ │ │ │ │ │ BrowserFrameView | │ │ │ │ │ │ │ ┌─────────────────────┐ │ │ │ │ │ │ │ │ │ BrowserView │ │ │ │ │ │ │ │ │ │ (ClientView) │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─────────────────────┘ │ │ │ │ │ │ │ └─────────────────────────┘ │ │ │ │ │ └─────────────────────────────┘ │ │ │ └─────────────────────────────────┘ │ └─────────────────────────────────────┘
If you're not sure where some piece of functionality goes:
Anything relating to the content of the browser window goes in BrowserView
.
BrowserViewLayout
.Anything relating to the frame and titlebar of the browser window goes in BrowserFrameView
, including but not limited to:
Any information or features of the whole window that are platform-specific go in BrowserNativeWidget
and are implemented in its platform-specific subclasses.
Any views::Widget
-specific stuff, like window event handling, goes in BrowserWidget
BrowserNativeWidget
.Cross-desktop-platform code should have access to BrowserView
, BrowserWidget
, BrowserFrameView
, and BrowserNativeWidget
. Therefore it is not necessary to pipe calls through another class if the class that actually has the method in question is available.
(The one exception is BrowserViewLayout
, which has access only to BrowserViewLayoutDelegate
, so calls must be piped through that class.)
Platform-specific logic should be behind a platform-agnostic API when possible, and if it actually applies to multiple platforms. If there is a logic path that only applies to one platform, try to encapsulate it in a platform-specific implementation; if it absolutely must be referenced outside of that implementation, place any required references in #if BUILDFLAG()
blocks.
For example, BrowserFrameView::CaptionButtonsOnLeadingEdge()
is a general question one might ask about any browser frame - “are the caption buttons on the leading (vs. trailing) edge of the window?” since caption buttons are present on every desktop platform, and it is used in cross-platform code. Therefore it goes in BrowserFrameView
, and should be called directly if that information is needed.
On the other hand, GetMinimizeButtonOffset()
lives in BrowserFrameViewWin
not because it‘s a question that could be asked about any browser, but is only ever actually used on Windows. It’s an implementation detail that doesn't need to be in the general interface.