Chromium
Table of contents
Version notes
- 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
# 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.
Download source code with a specific tag on a desktop.
Checkout a working branch with a meaningful name.
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.
git fetch origin refs/tags/new_commits_tag
git rebase –onto fetch_head branch_name
gclient sync –with_branch_heads –with_tags
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
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
Create browser window
ui/startup/startup -| browser_naviagator --> Browser::Create --> browser/ui/browser --createBrowserWindow--> BrowserView->BrowserFrame->RootView
Browser Window hierarchy
chrome/browser/ui/views/frame/browser_window_fatory --> BrowserView(implement:BrowserWindow:BAseWindow)
Programming basics
Get native HWND
Views::HWNDForNativeView (Browser->window()->BrowserWindow->GetNativeWindow())
Profile and Signin
- 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. 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()
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]
Profile Avatar
Source root path: chrome/browser
- Show toolbar avatar button
> /ui/views/frame/browser_view.cc::MaybeShowProfileSwitchIPH
- 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
- 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
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
- 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
- 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()) ... }
- 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:
- browser/new_tab_page
- browser/ui/webui/new_tab_page
- 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:
- mojo handler
- DataSource
- web_ui()->RegisterMessageCallback
And methods to update page content:
- webui::SetupWebUIDataSource
[Reference]
- https://chromium.googlesource.com/chromium/src/+/lkgr/docs/webui_explainer.md
Metrics
Security model
Hacks
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; }
disable copy to outside: modify ui/base/clipboard/clipboard_win.cc
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/';