Skip to main content Link Search Menu Expand Document (external link) Copy Copied

Chromium

Table of contents

  1. Version notes
  2. Build from source
    1. Typic gclient workflow
    2. Checkout specific branch
  3. Our way to manage local branches
  4. Go through the source code
    1. Application startup
      1. Programming basics
    2. Profile and Signin
    3. Profile Avatar
      1. Programming basics
    4. Enterprise Managed
    5. New Tab Page
    6. Safe browsing
    7. WebUI
    8. Metrics
    9. Security model
  5. Hacks

Version notes

Chrome data, all in one place

  • 110 the first version require Windows 10 or higher.
  • 109 the last version supported Windows 7/8. (ref/tags/109.0.5414.143)

Build from source

#download source
$mkdir chromium & cd chromium
$gclient config --name "src" --unmanged https://chromium.googlesource.com/chromium/src.git
$gclient sync --with_branch_heads --with_tags --revision src@109.0.5414.143

–unmanaged means this gclient config is not under other version control

–revision specify a version. Without it, gclient checkout the latest main branch

Typic gclient workflow

gclient brief

# config git entry
gclient config git@gitlab.gz.cvte.cn:CrOS/src.git --unmanaged # <1s

# checkout code
gclinet sync --revision src@c/master --nohooks # >10m,不需要水管
gclient runhooks # >10m,需要水管
...... # 编译
......  # 修改代码
...... # 使用 git  进行代码提交

# update:
cd src
git pull # <10s
gclient sync # <30s

Checkout specific branch

This is probably the fastest way to fetch Chromium’s source code. Suppose 59.0.3071.115 is the version of Chromium, you wish to build. You run this command:

git fetch https://chromium.googlesource.com/chromium/src.git +refs/tags/59.0.3071.115:chromium_59.0.3071.115

If you don’t want the history to be fetched (faster fetching of Chromium source code):

git fetch https://chromium.googlesource.com/chromium/src.git +refs/tags/59.0.3071.115:chromium_59.0.3071.115 --depth 1

Now from your Chromium repo, use the following command to show a list of tags available

git tag -l

or

git ls-remote --tags

You have to checkout that tag by running

git checkout tags/59.0.3071.115

Then run these commands in the order listed below to pull all the third-party dependencies:

// make sure under "src"
gclient sync --with_branch_heads --with_tags

Our way to manage local branches

Setup a git server locally, for a working branch. Typically we pick a major version as our working branch.

  1. Download source code with a specific tag on a desktop.

  2. Checkout a working branch with a meaningful name.

  3. On the local git server, initialize a bare repo, then push the local branch to it.

Update the branch, when there are new commits upstream.

  1. git fetch origin refs/tags/new_commits_tag

  2. git rebase –onto fetch_head branch_name

  3. gclient sync –with_branch_heads –with_tags

  4. git push

Go through the source code

There is good start page to Get Around The Chromium Source Code Directory Structure, though some descriptions are out of date.

Application startup

  1. Startup

     chrome/app/main.cc::wWinMain -[load dll]-> chrome/app/chrome_main
     |    |-[delegate]-> Content/app/ContentMain -> BrowserMain -> runner
     |                                                              |
     |                                                              v
     |-[create]-> chrome_main_delegate -[createContentClient]-> SetContentClient
    

    Initial mechanism

     > Content::ContentMain
     > ChromeBrowserMainParts: public content::BrowserMainParts
     > ChromeBrowserMainExtraParts
    
  2. Create browser window

     ui/startup/startup -|
     browser_naviagator --> Browser::Create --> browser/ui/browser
     --createBrowserWindow--> BrowserView->BrowserFrame->RootView
    
  3. Browser Window hierarchy

     chrome/browser/ui/views/frame/browser_window_fatory -->
     BrowserView(implement:BrowserWindow:BAseWindow)
    

Programming basics

  1. Get native HWND

     Views::HWNDForNativeView (Browser->window()->BrowserWindow->GetNativeWindow())
    

Profile and Signin

  1. Initialize Profile and show profile picker
     > /chrome_browser_main.cc::ChromeBrowserMainParts::PreMainMessageLoopRunImpl
     > /chrome_browser_main.cc::CreateInitialProfile
     > /ui/startup/startup_browser_creator.cc::GetFallbackStartupProfile //create profile picker info
     > /ui/startup/startup_browser_creator.cc::StartupBrowserCreator::Start
     >> ProcessCmdLineImpl
     >> LaunchBrowserForLastProfiles
     > /ui/views/profiles/profile_picker_view.cc::ProfilePicker::Show
    

    It is source code pattern, refer to /ui/README.md:
    ProfilePicker::Show declared in /ui/profile_picker.h, but defined in /ui/views/profiles/profile_picker_view.cc.

  2. Continue with profile picker flow controller

    flow controller class:

     classDiagram
         profile_management_flow_controller <|-- profile_management_flow_controller_impl
         profile_management_flow_controller_impl <|-- first_run_flow_controller_dice
         first_run_flow_controller_dice <|-- profile_picker_flow_controller
    
     > chrome/browser/ui/views/profiles/profile_picker_view.cc::Init(Profile* picker_profile)
     >> flow_controller_ = CreateFlowController
     >> if entry_point() == kFirstRun
     >>> FirstRunFlowControllerDice
     >> else
     >>> ProfilePickerFlowController
     >> flow_controller_->Init()
    
  3. Signin Webui interactions

     flowchart TD
         A["resources::signin"]
         B["webui::profile_picker_handler.cc"]
         C["Profile_picker_view.cc"]
         D["callback resources::signin"]
         E["authenticator.js"]
         A --> B --> C --> D --> E
    
     > resources/signin/navigation_mixin.ts navigateTo
     >> ./policy_helper.js::isForceSigninenabled
     >>> loadTimeData.getBoolean('signInProfileCreationFlowSupported')
     <-(set)- signin/signin_util.cc::IsForceSigninEnabled <-(prefs::kForceBrowserSignin)
    
     > JS callback into ui/webui/signin/profile-picker-handler.cc handlers
     >> ui/views/profiles/profile_picker_view.cc::ProfilePicker::SwitchToDiceSignIn
     >> ui/views/profiles/profile_picker_view.cc::ProfilePickerView::SwitchToForcedSignIn
    

    After profile created, call back into signin webui:

    ui/webui/signin/inline_login_handler.cc <————> rescources/inline_login

     > ui/views/profiles/profile_picker_view.cc::OnProfileDiceForcedSigninCreated
     > ShowForceSigninDialog
     >> ProfilePicker::ShowDialog(profile, "chrome://chrome-signin/")
     >>> resources/inline_login
    
     //web bridge from web to handler
     <<< inline_login_browser_proxy.ts:: initialize()
    
     >>> ui/webui/signin/inline_login_handler.cc FireWebUIListener("load-auth-extension", params)
    
     >>> chrome/resources/gaia_auth_host/authenticator.js:load()
    

    GaiaUrl defined in google_apis/gaia/gaia_urls.h. The Url in authenticator.js not works!

[Reference]

  1. Mutilple profiles

Profile Avatar

Source root path: chrome/browser

  1. Show toolbar avatar button
     > /ui/views/frame/browser_view.cc::MaybeShowProfileSwitchIPH
    
  2. Click avatar button and show profile menu bubble
     > /ui/views/profiles/avatar_toolbar_button.cc::AvatarToolbarButton::ButtonPressed
     > /ui/views/frame/browser_view.cc::ShowAvatarBubbleFromAvatarButton
     > /ui/views/profiles/profile_menu_coordinator.cc::Show
         > create bubble IncognitoMenuView or ProfileMenuView
         > bubble/bubble_dialog_delegate_view.cc::CreateBubble
    
  3. profiles/profile_menu_view_base.cc providers the UI for different menus that ar created by user clicking the avatar button
     > /ui/views/profile/profile_menu_view.cc::BuildMenu
    
  4. Account signin

    Source root path: /chrome/browser/signin

     > /signin/signin_ui_util.cc::EnableSyncFromMultiAccountPromo
     > /signin/signin_ui_delegate_impl_dice.cc::SigninUiDelegateImplDice::ShowSigninUI
     > /signin/signin_ui_delegate_impl_dice.cc::ShowDiceTab
     > /ui/signin_view_controller.cc::ShowDiceAddAccountTab
         > active_contents->OpenURL
         or
         > ShowTabOverwritingNTP
    

    SigninViewController responsible for showing and hiding all sign-in related UIs

  5. Handle signin response
     > chrome_content_browser_client.cc::CreateURLLoaderThrottles
         > register signin_throttle with <signin::HeaderModificationDelegateImpl>(profile)
    

    any response in

     > signin/header_modification_delegate_impl.cc::HeaderModificationDelegateImpl::ProcessResponse
     > signin/chrome_signin_helper.cc::ProcessAccountConsistencyResponseHeaders
    
     > signin/dice_response_handler.cc::ProcessDiceHeader
     > signin/dice_response_handler.cc::DiceTokenFetcher::OnClientOAuthSuccess
     > signin/dice_response_handler.cc::OnTokenExchangeSuccess
    
     > process_dice_header_delegate_impl.cc::HandleTokenExchangeSuccess
     > signin/dice_web_signin_interceptor.cc::MaybeInterceptWebSignin
    

Programming basics

  1. Get profile manager
     ProfileManager* profile_manager = g_browser_process->profile_manager()
     const std::vector<Profile*> loaded_profiles = profile_manager->GetLoadedProfiles();
     for (Profile* profile : loaded_profiles) {
         ProfileAttributesEntry* entry = profile_manager->GetProfileAttributesStorage().GetProfileAttributesWithPath(profile->GetPath());
         if (entry && entry->IsSigninRequired())
             ...
     }
    
  2. Build WebContents with profile
     std::unique_ptr<content::WebContentsf> contents_ = content::WebContents::Create(
         content::WebContents::CreateParams(Profile*)
     )
     contents_->SetDelegate(this)
    
    

Enterprise Managed

New Tab Page

The related source files:

  1. browser/new_tab_page
  2. browser/ui/webui/new_tab_page
  3. browser/resources/new_tab_page

Safe browsing

WebUI

Define WebUI contants in: /chrome/common/webui_url_constants.cc

Define localization resource in: /chrome/browser/resources/*_resources.grd

Implement content::WebUIController class

Implement WebUIMessaegHandler class, it also has multiple sub-classes, such as WebUIMessageHandler.
And called WebUI::AddMessageHandler

Instantize WebUI browser/ui/webui/chrome_web_ui_controller_factory.cc::GetWebUIFactoryFunction

WebUI has several methods to communicate with browser:

  1. mojo handler
  2. DataSource
  3. web_ui()->RegisterMessageCallback

And methods to update page content:

  1. webui::SetupWebUIDataSource

[Reference]

  1. https://chromium.googlesource.com/chromium/src/+/lkgr/docs/webui_explainer.md

Metrics

Security model

Hacks

  1. disable srceen capture: modify chrome/browser/ui/views/frame/browser_window_factory.cc

     // diff
     + #include "ui/aura/window_tree_host.h"
    
     BrowserWindow* BrowserWindow::CreateBrowserWindow(
     ...
    
     + HWND hwnd = view->GetNativeWindow()->GetHost()->GetAcceleratedWidget();
     + SetWindowDisplayAffinity(hwnd, 0x00000011);
    
     return view;
     }
    
  2. disable copy to outside: modify ui/base/clipboard/clipboard_win.cc

  3. customize profile picker flow to force signin

    Start with profile picker always:

     chrome/browser/chrome_browser_main.cc:
     StartupProfileInfo CreateInitialProfile(
    
         ProfileMnanger::GetPrimaryUserProfile();
     #endif // BUILDFLAG(IS_CHROMEOS_LACROS)
    
     - profile_info = GetStartupProfile(cur_dir, parsed_command_line);
     + profile_info = {.profile = nullptr, .mode = StarupProfileMode::kProfilePicker};
    
         if (profile_info.mode == StartupProfileMode::kError ...
    

    Force to signin:

     chrome/browser/signin/signin_util.cc:
     bool IsForceSigninEnables() {
     - SetForceSigninPolicy(prefs->GetBoolean(prefs::kForeceBrowserSignin));
     + SetForeceSigninPolicy(true)
     }
    

    Start signin:

     chrome/browser/resources/gaia_auth_host/authenticator.js
     - const IDP_ORIGIN = 'https://accounts.google.com/';
     + const IDP_ORIGIN = 'https://accounts.own_server.com/';