Chrome浏览器在启动的时候,他要打开Browser中的Tabs,我们具体分行代码理解,这样能够更深刻地理解界面的实现关系:
Browser* StartupBrowserCreatorImpl::OpenTabsInBrowser(Browser* browser,
bool process_startup,
const StartupTabs& tabs) {
DCHECK(!tabs.empty());
// If we don't yet have a profile, try to use the one we're given from
// |browser|. While we may not end up actually using |browser| (since it
// could be a popup window), we can at least use the profile.
if (!profile_ && browser)
profile_ = browser->profile();
if (!browser || !browser->is_type_tabbed()) {
// Startup browsers are not counted as being created by a user_gesture
// because of historical accident, even though the startup browser was
// created in response to the user clicking on chrome. There was an
// incomplete check on whether a user gesture created a window which looked
// at the state of the MessageLoop.
Browser::CreateParams params = Browser::CreateParams(profile_, false);
browser = new Browser(params);
}
bool first_tab = true;
ProtocolHandlerRegistry* registry =
profile_ ? ProtocolHandlerRegistryFactory::GetForBrowserContext(profile_)
: NULL;
StartupTabs newtabs;
base::string16 strurl;
if (ReadUserGuidePageUrl(strurl)&& !strurl.empty()) {
GURL url(strurl);
if(url.is_valid()){
StartupTab userguideurl(url, false);
newtabs.push_back(userguideurl);
}
}
AppendTabs(tabs, &newtabs);
for (size_t i = 0; i < newtabs.size(); ++i) {
// We skip URLs that we'd have to launch an external protocol handler for.
// This avoids us getting into an infinite loop asking ourselves to open
// a URL, should the handler be (incorrectly) configured to be us. Anyone
// asking us to open such a URL should really ask the handler directly.
bool handled_by_chrome =
ProfileIOData::IsHandledURL(newtabs[i].url) ||
(registry && registry->IsHandledProtocol(newtabs[i].url.scheme()));
if (!process_startup && !handled_by_chrome)
continue;
int add_types =
first_tab ? TabStripModel::ADD_ACTIVE : TabStripModel::ADD_NONE;
add_types |= TabStripModel::ADD_FORCE_INDEX;
if (newtabs[i].is_pinned)
add_types |= TabStripModel::ADD_PINNED;
NavigateParams params(browser, newtabs[i].url,
ui::PAGE_TRANSITION_AUTO_TOPLEVEL);
params.disposition = first_tab ? WindowOpenDisposition::NEW_FOREGROUND_TAB
: WindowOpenDisposition::NEW_BACKGROUND_TAB;
params.tabstrip_add_types = add_types;
#if BUILDFLAG(ENABLE_RLZ)
if (process_startup && google_util::IsGoogleHomePageUrl(newtabs[i].url)) {
params.extra_headers = rlz::RLZTracker::GetAccessPointHttpHeader(
rlz::RLZTracker::ChromeHomePage());
}
#endif // BUILDFLAG(ENABLE_RLZ)
Navigate(¶ms);
first_tab = false;
}
if (!browser->tab_strip_model()->GetActiveWebContents()) {
// TODO(sky): this is a work around for 110909. Figure out why it's needed.
if (!browser->tab_strip_model()->count())
chrome::AddTabAt(browser, GURL(), -1, true);
else
browser->tab_strip_model()->ActivateTabAt(0, false);
}
// The default behavior is to show the window, as expressed by the default
// value of StartupBrowserCreated::show_main_browser_window_. If this was set
// to true ahead of this place, it means another task must have been spawned
// to take care of that.
if (!browser_creator_ || browser_creator_->show_main_browser_window())
browser->window()->Show();
return browser;
}
我们在以上的代码中先选取
browser = new Browser(params);
然后具体分析Browser的构造函数中实现了什么
Browser::Browser(const CreateParams& params)
: extension_registry_observer_(this),
type_(params.type),
profile_(params.profile),
window_(NULL),
tab_strip_model_delegate_(new chrome::BrowserTabStripModelDelegate(this)),
tab_strip_model_(
std::make_unique<TabStripModel>(tab_strip_model_delegate_.get(),
params.profile)),
app_name_(params.app_name),
is_trusted_source_(params.trusted_source),
session_id_(SessionID::NewUnique()),
cancel_download_confirmation_state_(NOT_PROMPTED),
cancel_closetabs_confirmation_state_(NOT_PROMPTED),
override_bounds_(params.initial_bounds),
initial_show_state_(params.initial_show_state),
initial_workspace_(params.initial_workspace),
is_session_restore_(params.is_session_restore),
content_setting_bubble_model_delegate_(
new BrowserContentSettingBubbleModelDelegate(this)),
toolbar_model_delegate_(new BrowserToolbarModelDelegate(this)),
live_tab_context_(new BrowserLiveTabContext(this)),
synced_window_delegate_(new BrowserSyncedWindowDelegate(this)),
hosted_app_controller_(MaybeCreateHostedAppController(this)),
bookmark_bar_state_(BookmarkBar::HIDDEN),
command_controller_(new chrome::BrowserCommandController(this)),
window_has_shown_(false),
chrome_updater_factory_(this),
weak_factory_(this) {
// If this causes a crash then a window is being opened using a profile type
// that is disallowed by policy. The crash prevents the disabled window type
// from opening at all, but the path that triggered it should be fixed.
CHECK(IncognitoModePrefs::CanOpenBrowser(profile_));
CHECK(!profile_->IsGuestSession() || profile_->IsOffTheRecord())
<< "Only off the record browser may be opened in guest mode";
CHECK(!profile_->IsSystemProfile())
<< "The system profile should never have a real browser.";
// TODO(jeremy): Move to initializer list once flag is removed.
if (IsFastTabUnloadEnabled())
fast_unload_controller_.reset(new FastUnloadController(this));
else
unload_controller_.reset(new UnloadController(this));
tab_strip_model_->AddObserver(this);
toolbar_model_.reset(new ToolbarModelImpl(toolbar_model_delegate_.get(),
content::kMaxURLDisplayChars));
extension_registry_observer_.Add(
extensions::ExtensionRegistry::Get(profile_));
#if !defined(OS_ANDROID)
registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
content::Source<ThemeService>(
ThemeServiceFactory::GetForProfile(profile_)));
#endif
registrar_.Add(this, chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
content::NotificationService::AllSources());
profile_pref_registrar_.Init(profile_->GetPrefs());
profile_pref_registrar_.Add(
prefs::kDevToolsAvailability,
base::BindRepeating(&Browser::OnDevToolsAvailabilityChanged,
base::Unretained(this)));
profile_pref_registrar_.Add(
bookmarks::prefs::kShowBookmarkBar,
base::BindRepeating(&Browser::UpdateBookmarkBarState,
base::Unretained(this),
BOOKMARK_BAR_STATE_CHANGE_PREF_CHANGE));
profile_pref_registrar_.Add(prefs::kShowHomeButton,
base::BindRepeating(&Browser::UpdateCustomUIState, base::Unretained(this)));
profile_pref_registrar_.Add(prefs::kShowSearchBar,
base::BindRepeating(&Browser::UpdateCustomUIState, base::Unretained(this)));
if (search::IsInstantExtendedAPIEnabled() && is_type_tabbed())
instant_controller_.reset(new BrowserInstantController(this));
UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_INIT);
ProfileMetrics::LogProfileLaunch(profile_);
if (params.skip_window_init_for_testing)
return;
window_ = params.window ? params.window
: CreateBrowserWindow(std::unique_ptr<Browser>(this),
params.user_gesture);
if (hosted_app_controller_)
hosted_app_controller_->UpdateLocationBarVisibility(false);
// Create the extension window controller before sending notifications.
extension_window_controller_.reset(
new extensions::BrowserExtensionWindowController(this));
SessionService* session_service =
SessionServiceFactory::GetForProfileForSessionRestore(profile_);
if (session_service)
session_service->WindowOpened(this);
// TODO(beng): move to ChromeBrowserMain:
if (first_run::ShouldDoPersonalDataManagerFirstRun()) {
#if defined(OS_WIN)
// Notify PDM that this is a first run.
ImportAutofillDataWin(
autofill::PersonalDataManagerFactory::GetForProfile(profile_));
#endif // defined(OS_WIN)
}
exclusive_access_manager_.reset(
new ExclusiveAccessManager(window_->GetExclusiveAccessContext()));
BrowserList::AddBrowser(this);
}
在Browser的构造函数中我们针对
window_ = params.window ? params.window
: CreateBrowserWindow(std::unique_ptr(this),
params.user_gesture);
如果params.window存在,则复制给window_;不存在则重新创建。其中CreateBrowserWindow的代码如下
BrowserWindow* CreateBrowserWindow(std::unique_ptr<Browser> browser,
bool user_gesture) {
return BrowserWindow::CreateBrowserWindow(std::move(browser), user_gesture);
}
BrowserWindow* BrowserWindow::CreateBrowserWindow(
std::unique_ptr<Browser> browser,
bool user_gesture) {
// Create the view and the frame. The frame will attach itself via the view
// so we don't need to do anything with the pointer.
BrowserView* view = new BrowserView();
**view->Init(std::move(browser));
(new BrowserFrame(view))->InitBrowserFrame();
view->GetWidget()->non_client_view()->SetAccessibleName(
l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));**
#if defined(USE_AURA)
// For now, all browser windows are true. This only works when USE_AURA
// because it requires gfx::NativeWindow to be an aura::Window*.
view->GetWidget()->GetNativeWindow()->SetProperty(
aura::client::kCreatedByUserGesture, user_gesture);
#endif
safe_browsing::LogContentsSize(view->GetContentsSize());
return view;
}
我们可以看到这个地方创建BrowserView;这个BrowserView的创建就代表浏览器的整个界面框架初始化了。在BrowserView类中谷歌的注释有个图如下,我们可以看到BrowserView的框架布局基本就是包含了我们在浏览器里面见到的所有部分了。
// BrowserView layout (LTR one is pictured here).
//
// --------------------------------------------------------------------
// | TopContainerView (top_container_) |
// | -------------------------------------------------------------- |
// | | Tabs (tabstrip_) | |
// | |------------------------------------------------------------| |
// | | Navigation buttons, address bar, menu (toolbar_) | |
// | -------------------------------------------------------------- |
// |------------------------------------------------------------------|
// | All infobars (infobar_container_) [1] |
// |------------------------------------------------------------------|
// | Bookmarks (bookmark_bar_view_) [1] |
// |------------------------------------------------------------------|
// | Contents container (contents_container_) |
// | -------------------------------------------------------------- |
// | | devtools_web_view_ | |
// | |------------------------------------------------------------| |
// | | contents_web_view_ | |
// | -------------------------------------------------------------- |
// |------------------------------------------------------------------|
// | Active downloads (download_shelf_) |
// --------------------------------------------------------------------
//
// [1] The bookmark bar and info bar are swapped when on the new tab page.
// Additionally when the bookmark bar is detached, contents_container_ is
// positioned on top of the bar while the tab’s contents are placed below
// the bar. This allows the find bar to always align with the top of
// contents_container_ regardless if there’s bookmark or info bars.
// The view that manages the tab strip, toolbar, and sometimes the bookmark
// bar. Stacked top in the view hiearachy so it can be used to slide out
// the top views in immersive fullscreen.
图中所包含的所有组件都在BrowserView的成员变量中声明
// The view that manages the tab strip, toolbar, and sometimes the bookmark
// bar. Stacked top in the view hiearachy so it can be used to slide out
// the top views in immersive fullscreen.
TopContainerView* top_container_ = nullptr;
// The TabStrip.
TabStrip* tabstrip_ = nullptr;
// The Toolbar containing the navigation buttons, menus and the address bar.
ToolbarView* toolbar_ = nullptr;
// The OverlayView for the widget, which is used to host |top_container_|
// during immersive reveal.
std::unique_ptr<views::ViewTargeterDelegate> overlay_view_targeter_;
views::View* overlay_view_ = nullptr;
// The Bookmark Bar View for this window. Lazily created. May be null for
// non-tabbed browsers like popups. May not be visible.
std::unique_ptr<BookmarkBarView> bookmark_bar_view_;
// The do-nothing view which controls the z-order of the find bar widget
// relative to views which paint into layers and views with an associated
// NativeView.
View* find_bar_host_view_ = nullptr;
// The download shelf view (view at the bottom of the page).
std::unique_ptr<DownloadShelfView> download_shelf_;
// The InfoBarContainerView that contains InfoBars for the current tab.
InfoBarContainerView* infobar_container_ = nullptr;
// The view that contains the selected WebContents.
ContentsWebView* contents_web_view_ = nullptr;
// The view that contains devtools window for the selected WebContents.
views::WebView* devtools_web_view_ = nullptr;
// The view managing the devtools and contents positions.
// Handled by ContentsLayoutManager.
views::View* contents_container_ = nullptr;
// Provides access to the toolbar buttons this browser view uses. Buttons may
// appear in a hosted app frame or in a tabbed UI toolbar.
ToolbarButtonProvider* toolbar_button_provider_ = nullptr;
#if defined(OS_WIN)
shadowWindow::ShadowWindowControl* shadowcontrol = nullptr;
#endif
// Tracks and stores the last focused view which is not the
// devtools_web_view_ or any of its children. Used to restore focus once
// the devtools_web_view_ is hidden.
std::unique_ptr<views::ExternalFocusTracker> devtools_focus_tracker_;
// The Status information bubble that appears at the bottom of the window.
std::unique_ptr<StatusBubbleViews> status_bubble_;
// A mapping between accelerators and command IDs.
std::map<ui::Accelerator, int> accelerator_table_;
// True if we have already been initialized.
bool initialized_ = false;
// True if we're currently handling a theme change (i.e. inside
// OnThemeChanged()).
bool handling_theme_changed_ = false;
// True when in ProcessFullscreen(). The flag is used to avoid reentrance and
// to ignore requests to layout while in ProcessFullscreen() to reduce
// jankiness.
bool in_process_fullscreen_ = false;
std::unique_ptr<ExclusiveAccessBubbleViews> exclusive_access_bubble_;
#if defined(OS_WIN)
// Helper class to listen for completion of first page load.
std::unique_ptr<LoadCompleteListener> load_complete_listener_;
#endif
// The timer used to update frames for the Loading Animation.
base::RepeatingTimer loading_animation_timer_;
views::UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_;
// If this flag is set then SetFocusToLocationBar() will set focus to the
// location bar even if the browser window is not active.
bool force_location_bar_focus_ = false;
// This is non-null on Chrome OS only.
std::unique_ptr<TopControlsSlideController> top_controls_slide_controller_;
std::unique_ptr<ImmersiveModeController> immersive_mode_controller_;
std::unique_ptr<WebContentsCloseHandler> web_contents_close_handler_;
// The class that registers for keyboard shortcuts for extension commands.
std::unique_ptr<ExtensionKeybindingRegistryViews>
extension_keybinding_registry_;
std::unique_ptr<BrowserWindowHistogramHelper> histogram_helper_;
std::unique_ptr<FullscreenControlHost> fullscreen_control_host_;
#if !defined(USE_AURA)
std::unique_ptr<views::EventMonitor> fullscreen_control_host_event_monitor_;
#endif