前言

最近某个项目需要轻度定制的 Chromium ,记录一下编译和修改的过程。

这篇文章主要记录以下内容:

  • 如何拉取 Chromium for android 的代码
  • 如何编译 Chromium for android
  • 一些对 Chromium for android 的小定制与修改
  • 看 Chromium 源码时的经验小记

谷歌官方的编译方式可以在这里找到:
https://chromium.googlesource.com/chromium/src/+/HEAD/docs/android_build_instructions.md
本文会在官方说明的基础上进行进一步的解释与补充。

工作环境

编译 Chromium for android 需要 Linux 环境,并且只能使用 Linux 环境。
本文所使用的编译环境时 Arch Linux。
编译机配置,推荐 16GB 内存(跑的时候峰值需求能到 9GB 多),100GB 磁盘空间(拉取完整源码并编译 98 版本,最后实际消耗 78GB )。

首先的首先,创建一个文件夹,用来存放相关内容。
mkdir ~/work
cd ~/work

编译需要一些软件包的支持,由于此处的编译环境是 Arch Linux ,官方并没有为其提供一键安装软件包的脚本,因此基本上是报错缺啥装啥。
当然, base-devel 可以先装好。

源码的拉取

源码本体就在这里。
https://chromium.googlesource.com/chromium/src/

但是,由于编译源码需要一些额外的树外工具和 hooks ,而这些东西并不包含在主代码中,因此我们仍然需要使用谷歌的官方工具进行源码拉取。

获取源码管理工具

下载工具。
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git

将工具增加到环境变量。
export PATH="${PATH}:${HOME}/work/depot_tools"

拉取源码

mkdir chromium && cd chromium
fetch --nohooks android

此处拉取的完整代码,为的是稍后切换版本时方便,我想没有人会想把非常不稳定的主线版本拿来日用吧。
--nohooks代表暂时先不安装 hooks ,而只是拉取代码,hooks 我们稍后安装,按部就班的来。

这一步可能需要非常久的时间,而且建议开启代理,源码大小在 50GB 左右。

选择版本

在上一步完成后,工作目录下会多出一个 src 文件夹。
进入此文件夹。
cd src

从仓库刷新所有的 Tags。
git fetch origin --tags

查看 Tags。
git tag

选择一个心仪的 Tag 检出代码,比如:
git checkout 97.0.4692.93

安装 hooks 和 树外依赖

(ubuntu专用)安装依赖软件包
./build/install-build-deps-android.sh
Arch Linux 并不支持这个脚本,因此需要手动的“缺啥补啥”。
某些软件包甚至 Arch 官方仓库里没有,需要从 AUR 安装,比如
ncurses5-compat-libs

再次刷新源码并安装 树外依赖 和 hooks 。
gclient sync
这一步也需要下载不少的东西,请确保网络畅通。

编译

配置编译

指定编译配置文件。
gn args out/Default
其中,out/Default 是编译输出目录。

这一步操作后会打开一个文本编辑器,在其中写入编译配置:

# 目标操作系统
target_os = "android"
# 目标架构
target_cpu = "arm64"
# 不把警告作为错误,否则有一定可能性遭遇警告转来的编译错误
treat_warnings_as_errors = false
# 编译“正式版”,而非“开发人员内部版本”,启动正式版具有的性能优化
is_official_build = true
# 编译 ffmpeg 相关模块以提供 H.264 视频解码功能
ffmpeg_branding = "Chrome"
proprietary_codecs = true

开始编译

autoninja -C out/Default chrome_public_apk

然后编译就开始了,记得依赖缺啥补啥。

编译完成后,可以在 out/Default/apks 下找到安装包。

刷新代码

也许有一天,你会想要更新本地代码,拉取新代码编译新版 Chromium,此时需要做的是:

  • 配置环境变量
  • 进入 src 文件夹
  • 获取新代码:git fetch origin --tags
  • 检出新代码:git checkout <新的版本>
  • 更新 Hooks 和 树外工具:gclient sync
  • 编译!autoninja -C out/Default chrome_public_apk

搞定!

魔改

干掉 StrictMode

自编译 Chromium 在打开时会在屏幕边缘短暂绘制一个红框,在主线程执行长时间操作时也会绘制,可以通过干掉 StrictMode 解决。

diff --git a/components/strictmode/android/java/src/org/chromium/components/strictmode/ReflectiveThreadStrictModeInterceptor.java b/components/strictmode/android/java/src/org/chromium/components/strictmode/ReflectiveThreadStrictModeInterceptor.java
index 1c9e868c8fdab..2fc3cebba6f2f 100644
--- a/components/strictmode/android/java/src/org/chromium/components/strictmode/ReflectiveThreadStrictModeInterceptor.java
+++ b/components/strictmode/android/java/src/org/chromium/components/strictmode/ReflectiveThreadStrictModeInterceptor.java
@@ -68,7 +68,7 @@ final class ReflectiveThreadStrictModeInterceptor implements ThreadStrictModeInt
         // trace with stack frames prior to android.os.Handler calls stripped out.
 
         interceptWithReflection();
-        StrictMode.setThreadPolicy(new ThreadPolicy.Builder(detectors).penaltyLog().build());
+        //StrictMode.setThreadPolicy(new ThreadPolicy.Builder(detectors).penaltyLog().build());
     }
 
     private void interceptWithReflection() {

修改默认搜索引擎

diff --git a/components/search_engines/template_url_prepopulate_data.cc b/components/search_engines/template_url_prepopulate_data.cc
index c9c393401e513..33a502ed3e06f 100644
--- a/components/search_engines/template_url_prepopulate_data.cc
+++ b/components/search_engines/template_url_prepopulate_data.cc
@@ -201,10 +201,9 @@ const PrepopulatedEngine* const engines_CL[] = {
 
 // China
 const PrepopulatedEngine* const engines_CN[] = {
-    &sogou,
-    &baidu,
     &bing,
-    &google,
+    &baidu,
+    &sogou,
     &so_360,
 };

注意:只要搜索引擎列表里有谷歌,默认搜索引擎永远是谷歌,把谷歌删了后,默认搜索引擎是第一个。

默认关闭登录谷歌引导

diff --git a/components/signin/internal/identity_manager/primary_account_manager.cc b/components/signin/internal/identity_manager/primary_account_manager.cc
index 51ca2abc2b158..160c45365126a 100644
--- a/components/signin/internal/identity_manager/primary_account_manager.cc
+++ b/components/signin/internal/identity_manager/primary_account_manager.cc
@@ -55,7 +55,7 @@ void PrimaryAccountManager::RegisterProfilePrefs(PrefRegistrySimple* registry) {
   registry->RegisterBooleanPref(prefs::kGoogleServicesConsentedToSync, false);
   registry->RegisterBooleanPref(prefs::kAutologinEnabled, true);
   registry->RegisterListPref(prefs::kReverseAutologinRejectedEmailList);
-  registry->RegisterBooleanPref(prefs::kSigninAllowed, true);
+  registry->RegisterBooleanPref(prefs::kSigninAllowed, false);
   registry->RegisterBooleanPref(prefs::kSignedInWithCredentialProvider, false);
 }

Chromium 中的默认偏好都是在 Native 层中使用如上方式注册的,因此在搜索某个设置时可以使用:
grep -rn "Register.*Pref" --exclude-dir=out --exclude-dir=.git | grep -i <你的关键词>
来快速定位一个设置。

移除不想要的启动引导页面

diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
index 78c793c0e7c46..2f0d6da51dd21 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
@@ -139,7 +139,7 @@ public class FirstRunActivity extends FirstRunActivityBase implements FirstRunPa
     private void createFirstPage() {
         FREMobileIdentityConsistencyFieldTrial.createFirstRunTrial();
         BooleanSupplier showWelcomePage = () -> !FirstRunStatus.shouldSkipWelcomePage();
-        if (FREMobileIdentityConsistencyFieldTrial.isEnabled()) {
+        if (false) {
             mPages.add(new FirstRunPage<>(SigninFirstRunFragment.class, showWelcomePage));
         } else {
             // TODO(crbug.com/1111490): Revisit during post-MVP.
@@ -178,44 +178,6 @@ public class FirstRunActivity extends FirstRunActivityBase implements FirstRunPa
         assert areNativeAndPoliciesInitialized();
         mFirstRunFlowSequencer.updateFirstRunProperties(mFreProperties);
 
-        BooleanSupplier showDataReductionPromo =
-                () -> mFreProperties.getBoolean(SHOW_DATA_REDUCTION_PAGE);
-        BooleanSupplier showSearchEnginePromo =
-                () -> mFreProperties.getBoolean(SHOW_SEARCH_ENGINE_PAGE);
-        BooleanSupplier showSyncConsent = () -> mFreProperties.getBoolean(SHOW_SYNC_CONSENT_PAGE);
-
-        // An optional Data Saver page.
-        if (!FREMobileIdentityConsistencyFieldTrial.isEnabled()
-                && showDataReductionPromo.getAsBoolean()) {
-            mPages.add(new FirstRunPage<>(
-                    DDAjrXkGz1p2FHQMfZ6QaedHZbxtzt1TCb.class, showDataReductionPromo));
-            mFreProgressStates.add(MobileFreProgress.DATA_SAVER_SHOWN);
-        }
-
-        // An optional page to select a default search engine.
-        if (showSearchEnginePromo.getAsBoolean()) {
-            mPages.add(new FirstRunPage<>(
-                    DefaultSearchEngineFirstRunFragment.class, showSearchEnginePromo));
-            mFreProgressStates.add(MobileFreProgress.DEFAULT_SEARCH_ENGINE_SHOWN);
-        }
-
-        // An optional sync consent page, the visibility of this page will be decided on the fly
-        // according to the situation.
-        mPages.add(new FirstRunPage<>(SyncConsentFirstRunFragment.class, showSyncConsent));
-        mFreProgressStates.add(MobileFreProgress.SYNC_CONSENT_SHOWN);
-
-        // An optional Data Saver page, this page will be hidden if users click the |Settings|
-        // link on the sync consent page.
-        if (FREMobileIdentityConsistencyFieldTrial.isEnabled()
-                && showDataReductionPromo.getAsBoolean()) {
-            mPages.add(new FirstRunPage<>(
-                    DDAjrXkGz1p2FHQMfZ6QaedHZbxtzt1TCb.class, showDataReductionPromo));
-            mFreProgressStates.add(MobileFreProgress.DATA_SAVER_SHOWN);
-        }
-
-        if (mPagerAdapter != null) {
-            mPagerAdapter.notifyDataSetChanged();
-        }
         mPostNativeAndPolicyPagesCreated = true;
 
         if (sObserver != null) {

这里把所有可选的引导页面都删完了,只留了个欢迎屏幕,同时也禁用了欢迎屏幕在 GMS 可用时显示登录选项的功能。

移除不想要的设置选项

diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java
index 39f3c5c3aa135..b465a174147e5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java
@@ -255,9 +255,9 @@ public class MainSettings extends PreferenceFragmentCompat
             removePreferenceIfPresent(PREF_DEVELOPER);
         }
 
-        ChromeBasePreference dataReduction =
-                (ChromeBasePreference) findPreference(PREF_DATA_REDUCTION);
-        dataReduction.setSummary(DataReductionPreferenceFragment.generateSummary(getResources()));
+        removePreferenceIfPresent(PREF_ACCOUNT_AND_GOOGLE_SERVICES_SECTION);
+        removePreferenceIfPresent(PREF_GOOGLE_SERVICES);
+        removePreferenceIfPresent(PREF_DATA_REDUCTION);
     }

不显示开发者选项

diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/DeveloperSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/DeveloperSettings.java
index 1f9156c7fb11d..9608cdfecfec0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/DeveloperSettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/DeveloperSettings.java
@@ -33,7 +33,6 @@ public class DeveloperSettings extends PreferenceFragmentCompat {
         // Chrome version in Settings>About multiple times.
         if (sIsEnabledForTests != null) return sIsEnabledForTests;
 
-        if (VersionConstants.CHANNEL <= Channel.DEV) return true;
         return SharedPreferencesManager.getInstance().readBoolean(
                 ChromePreferenceKeys.SETTINGS_DEVELOPER_ENABLED, false);
     }

禁用主页上的“探索”

diff --git a/components/feed/core/shared_prefs/pref_names.cc b/components/feed/core/shared_prefs/pref_names.cc
index 57a65895fbded..511f7a2b500e1 100644
--- a/components/feed/core/shared_prefs/pref_names.cc
+++ b/components/feed/core/shared_prefs/pref_names.cc
@@ -20,8 +20,8 @@ const char kArticlesListVisible[] = "ntp_snippets.list_visible";
 const char kVideoPreviewsType[] = "ntp_snippets.video_previews_type";
 
 void RegisterFeedSharedProfilePrefs(PrefRegistrySimple* registry) {
-  registry->RegisterBooleanPref(kEnableSnippets, true);
-  registry->RegisterBooleanPref(kArticlesListVisible, true);
+  registry->RegisterBooleanPref(kEnableSnippets, false);
+  registry->RegisterBooleanPref(kArticlesListVisible, false);
   registry->RegisterIntegerPref(kVideoPreviewsType, 1);
 }