Chrome UI学习—主界面以及组件分布2

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(&params);

    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

版权声明:本文为weixin_37972910原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。