贡献者指南¶
目录¶
GeckoView 贡献者快速入门指南¶
本指南面向希望为 GeckoView 项目做出贡献的开发者。如果您想开始在您的应用程序中使用 GeckoView,则应参考wiki。
背景¶
GeckoView 是一个公共 API,它将核心 Gecko 功能暴露给 GeckoView 使用者。多个 Mozilla 产品使用 GeckoView 作为它们进入 Gecko 的核心入口点。例如,Android Components 将 GeckoView 作为依赖项,并使用它与 Gecko 通信。Fenix、Focus 和 Reference Browser 将 Android Components 作为依赖项,并在该框架之上构建浏览器。
总体架构如下所示:
Gecko <-> GeckoView <-> Android Components <-> Fenix 或 Focus 或 Reference Browser
**Gecko** 是其他组件构建的基础平台。它是一个多层面的强大平台,符合与浏览器机制相关的标准。
**GeckoView** 公开 Gecko 的关键部分,供 API 使用者在 Android 系统中使用。通过这种方式公开了一部分关键的 Gecko 功能。它是一个公共 API,因此公共 API 的更改设计为始终不会破坏现有功能,并遵循弃用流程。
**Android Components** 链接到 GeckoView 以支持 Gecko 浏览器。它与 Gecko 和 GeckoView 平台无关。例如,可以使用其他浏览器引擎代替 Gecko。它还提供其他可重用的浏览器构建组件。
**Fenix 或 Focus 或 Reference Browser** 是最终的应用程序产品。它们包含主要的视图层,并将所有内容连接在一起以形成最终产品。
在解决 Bug 时,请牢记这种架构。识别解决 Bug 的正确层是任何 Bug 的重要第一步。
执行 Bug 修复¶
第一步,您需要设置 mozilla-central 和 Bootstrap 并构建项目。
一旦您让 GeckoView 构建并运行,您就可以开始贡献了。有一个针对 Git 开发者的 执行 Bug 修复的通用指南 供您参考。要专门为 GeckoView 贡献代码,您需要以下其他信息。
调试代码¶
由于 GeckoView 位于多个层级上,因此最佳调试工具通常取决于 Bug 所在的层级。对于 Java 或 Kotlin 代码,使用 Android Studio IDE 是连接调试器和设置断点的一种简单方法。在设置原生调试后,它也可以与 C++ 代码一起使用。请参阅有关 原生调试 的本指南。
对于 JavaScript 代码,可以使用 Firefox 桌面版 Nightly 的 about:debugging 部分连接调试器。设备必须设置为支持 USB 连接,并且设备可能需要启用开发者模式。
有时,留下日志以帮助首先跟踪 Bug 究竟位于哪一层更容易,在各个层级上执行此操作:
**Java** -
Log.i("Any Tag", "Any string " + variable.toString())
可用于在 GeckoView 中进行永久性日志记录,但应遵循现有的日志记录实践。需要导入。
请注意,Android Components 具有不同的永久性日志记录实践。
**JavaScript** -
dump("Any string " + variable)
可能不用于永久性日志记录。
可能需要使用
JSON.stringify(variable)
在 JavaScript 中反序列化对象。
**JavaScript** -
debug`Any String ${variable}`
可用于永久性日志记录,但应遵循现有的日志记录实践。需要导入。
建议在早期调试阶段使用
dump
。
**JavaScript** -
console.log("Any String " + variable)
可以使用桌面版上的
about:debugging
连接到连接的设备,然后连接到内容进程来查看。
**C++** -
MOZ_LOG
尚未在 logcat 中正确显示。添加此行
CreateOrGetModule("modulename")->SetLevel(LogLevel::Verbose);
到代码的此部分 作为查看MOZ_LOG
日志的临时解决方案。
**C++** -
printf_stderr("Any String")
或__android_log_write(ANDROID_LOG_INFO, "Any Tag", "Any string");
或__android_log_print(ANDROID_LOG_INFO, "Any Tag", "Any string");
这些都不应用于永久性日志记录,仅用于调试。对于永久性日志记录,请使用
MOZ_LOG
。变量日志记录需要转换为 C 字符串或其他支持的日志记录字符串。
GeckoView C++ 文件的永久性日志记录可以类似于以下方式设置:
#define GVS_LOG(...) MOZ_LOG(sGVSupportLog, LogLevel::Info, (__VA_ARGS__)) static mozilla::LazyLogModule sGVSupportLog("Any Tag"); GVS_LOG("Any string");
请确保在请求合并之前删除任何非永久性调试日志。
要在 Android 上查看日志,请连接设备并运行 adb logcat -v color
以获取彩色日志,或者使用 Android Studio 日志框架。
在本地运行测试和 linter¶
为了确保您的补丁不会破坏 GeckoView 中的现有功能,您可以使用以下命令运行 junit 测试套件:
./mach geckoview-junit
此命令还允许您运行单个测试或测试类,例如:
./mach geckoview-junit org.mozilla.geckoview.test.NavigationDelegateTest
./mach geckoview-junit org.mozilla.geckoview.test.NavigationDelegateTest#loadUnknownHost
要查看其他选项的信息,只需运行 ./mach geckoview-junit --help
;对于处理间歇性测试失败特别需要注意的是 --repeat N
和 --run-until-failure
,它们都完全按照您的预期执行。如果测试间歇性失败,请参考 调试间歇性测试失败 以获取其他提示。
其他测试(例如 mochitests)可以使用以下命令运行:
./mach test <path-or-dir-to-test>
核心 GeckoView lints 为:
# Will perform general Android specific formatting and linting.
./mach lint -l android-format
# Will determine if GeckoView API changes happened, find more info at API documentation below, if changes occurred.
./mach lint --linter android-api-lint
# Will perform static analysis and report required changes.
./mach lint --warnings --outgoing
对于以下 linter,请在命令中添加 --fix
以使 linter 自动修复问题。请注意,使用 --fix
会进行更改。大多数命令也接受特定的文件或目录以加快 linting 速度。
如果您的补丁创建了 GeckoView JavaScript 模块,则应运行 ESLint:
./mach lint -l eslint mobile/android/modules/geckoview/
如果您的补丁对 C++ 文件进行了更改,则应运行 C++ linter 格式化程序:
./mach clang-format -p <path/to/file.cpp>
如果您的补丁对 Python 文件进行了更改:
./mach lint --linter flake8
./mach lint --linter black
此外,有时 lints 可以自动检测并在某些文件上修复,例如:
# Will attempt to detect the linter and fix any issues.
# Note, using ``--fix`` will make code changes.
./mach lint --fix <path-to-file>
更新变更日志和 API 文档¶
如果您要提交的补丁更改了 GeckoView 的公共 API,则必须确保 API 文档保持最新。
GeckoView 遵循弃用策略,您可以在此 设计文档 中了解更多信息。要弃用 API,请添加弃用标志,并使用弃用通知的标识符,以便所有具有相同标识符的通知将在同一时间删除(请参见下面的示例)。版本是在我们期望删除附加到注释的已弃用成员的主版本。GeckoView 团队制定了一项弃用策略,要求每个向后不兼容的更改保留旧代码 3 个版本,从而允许下游使用者(如 Fenix)有时间异步迁移到新代码而不会破坏构建。
@Deprecated
@DeprecationSchedule(id = "<interface_or_class_of_method>-<method_name>", version = <Current Nightly + 3>)
由于这是一个公共 API,因此必须更新变更日志。请确保遵循变更日志条目的正确格式。在下一个发布版本的标题下,为对 API 进行的更改添加新条目,以及任何相关文件的链接和 Bug 编号。
格式应如下所示:
- Summary of changes that should mention the method name, along with the respective class /
interface name, the major version and the index, and the bug ID, along with the
bugzilla link
[<major_version>.<index>]: {{javadoc_uri}}/<url_path>
目前,只需使用对 API 所做的更改摘要更新变更日志(示例中的第一行)。要确定索引,请取 [<major_version>.<index>]
列表中的下一个索引。如果没有列表,则从 index = 1
开始。
添加方法的示例
- Added [`GeckoRuntimeSettings.Builder#aboutConfigEnabled`][71.12] to control whether or
not `about:config` should be available.
([bug 1540065]({{bugzilla}}1540065))
[71.12]: {{javadoc_uri}}/GeckoRuntimeSettings.Builder.html#aboutConfigEnabled(boolean)
弃用方法的示例
- ⚠️ Deprecated [`GeckoSession.ContentDelegate.onProductUrl`][128.5], will now be removed in v131.
([bug 1898055]({{bugzilla}}1898055))
[128.5]: {{javadoc_uri}}/GeckoSession.ContentDelegate.html#onProductUrl(org.mozilla.geckoview.GeckoSession)
要检查您的补丁是否更改了 API,请运行以下命令:
./mach lint --linter android-api-lint
此命令的输出将通知您您所做的任何更改是否破坏了现有的 API。命令的第一次运行将告诉您是否存在 API 更改。如果存在更改并且预期更改,请查看更改并按照其提供的说明操作。
./mach gradle geckoview:apiLintWithGeckoBinariesDebug
运行上述命令应该会导致构建失败,并且输出应该包含一个 API 密钥,该密钥应该用于更新变更日志中的 [api-version]
字段。接下来,再次运行该命令:
./mach gradle geckoview:apiLintWithGeckoBinariesDebug
这次构建应该通过,并且将为更改生成一个 api.txt 文件。接下来,按照下一个命令再次检查所做的更改是否不会破坏现有的 API:
./mach lint --linter android-api-lint
如果弃用了 API,请提交后续 Bug 或通过添加关键字 leave-open 保持 Bug 打开以删除和清理其将在哪个版本中删除的已弃用 API。此外,请确保运行前两个命令已将已弃用方法的 javadoc 更改为指示该方法已计划弃用。如果不是,请手动执行此操作。
特殊情况是,更改 API 的补丁可能需要提升到 mozilla-central 的早期分支,例如 beta 频道。为此,请按照通常的提升步骤操作,并为提升创建补丁版本,该版本映射到新的目标分支并重新运行 API linter 命令。
接下来,我们将创建本地 JavaDoc:
在本地创建 JavaDoc¶
注意
确保更改日志中已更新 API 版本,并且更改日志中对 API 所做更改的摘要已正确填写。否则,此步骤将无法正常工作。
GeckoView 是一个公共 API,因此维护良好的 javadoc 是一种重要的实践。要在本地创建 javadoc,我们使用以下命令
./mach gradle geckoview:javadocWithGeckoBinariesDebug
要在本地查看 javadoc,可以选择以下两个选项之一
导航到
<mozilla-central root>/<build architecture>/gradle/build/mobile/android/geckoview/docs/javadoc/withGeckoBinaries-debug
在您的
mozilla-unified
目录中,输入以下命令find . -name withGeckoBinaries-debug
这将返回本地 javadoc 的相对路径。
例如,输出可能是这样
mozilla-unified/objdir-frontend/gradle/build/mobile/android/geckoview/docs/javadoc/withGeckoBinaries-debug
然后,使用以下命令进入本地 javadoc 的目录
cd path_of_javadoc_from_above
现在,我们想要启动一个本地 Web 服务器。要本地启动,可以使用任何 Web 服务器,例如
python3 -m http.server 8000
在此示例中,通过 https://127.0.0.1:8000/org/mozilla/geckoview/
导航到 Web 文档。
注意
如果您收到 404 错误,请确保您已导航到正确的目录,然后尝试重新启动 Web 服务器。
然后,在网页上显示的列表中查找已更改的方法,并单击它。
在更改日志中,主要版本摘要列表下方,应该有一个已更改方法的 URL 列表。为下一个索引添加一个新条目(保持主要版本不变)。然后,在本地 Web 服务器中,复制 .../org/mozilla/geckoview/
后面的所有内容。通过执行 {{javadoc_uri}}/<paste_the_copied_text>
填写条目。请参阅上面的示例以供参考。
提交到 try
服务器¶
建议在提交补丁之前运行您的测试。您可以使用 Mozilla 的 try
服务器来执行此操作。要将 GeckoView 补丁提交到 try
(在提交审查之前),请键入
./mach try --preset android-geckoview
这将自动运行来自 GeckoView 测试套件的关键测试。如果您的补丁在 try
上通过,则可以(相当)确信它在审查后会成功落地。
try
上的失败将以橙色突出显示的测试名称显示。选择测试以了解更多信息。由于测试工具的问题,偶尔会出现间歇性故障。重新触发测试是确认它是间歇性故障而不是由补丁引起的的好方法。通常,对于已记录的间歇性故障,还将有一个错误号以及一部分堆栈跟踪。有关更多信息,请参阅 间歇性测试故障。
要调试 try 上的故障,始终建议检查 logcat。为此,选择单个测试,选择“工件和调试”,然后从“logcat-emulator-5554.log”打开日志。
标记审阅者¶
将补丁提交到 Phabricator 时,如果您知道您希望谁来审查您的补丁,请将其 Phabricator 句柄放在 reviewers
字段中。
如果您不知道在 Phabricator 提交消息中标记谁进行审查,请将该字段留空,并在提交后,按照 Phabricator 中补丁的链接,然后滚动到屏幕底部,直到看到评论框。
选择
Add Action
下拉菜单,然后选择Change Reviewers
选项。在显示的框中,添加
geckoview-reviewers
。选择此组作为审阅者将通知 GeckoView 团队的所有成员有一个补丁需要审查。单击
Submit
提交审阅者更改请求。
GeckoView、Android 组件、Fenix、Focus 和参考浏览器依赖项替换¶
在 mozilla-central 上的完整构建中,内部产品依赖项替换会自动处理。构建时,替换到这些其他产品的操作将在运行 ./mach build 后自动发生。但是,在工件构建中,Gecko 或 GeckoView 中的更改不会始终如一地反映出来。如果要对 Gecko 或 GeckoView 进行更改,则**强烈**建议仅使用完整构建,因为在使用工件构建时,Gecko 或 GeckoView 中的更改可能不会反映出来。
包含 GeckoView 作为依赖项¶
如果要将 GeckoView 的开发版本作为依赖项包含在另一个应用程序中,则必须链接到本地副本。实现此目标的方法有多种,但首选方法是使用 Gradle 的依赖项替换机制,该机制在 mozilla-central
中具有第一类支持,并且在 Mozilla 的 GeckoView 使用生态系统中具有模式。
好消息是 mach build
生成了您需要的所有内容,因此在进行以下配置后,您应该会发现以下命令会重建您的本地 GeckoView,然后在下游项目中使用您的本地版本。
cd /path/to/mozilla-central && ./mach build
cd /path/to/project && ./gradlew assembleDebug
**请确保您的 ``mozconfig`` 为您的目标设备指定了正确的 ``–target`` 参数。**许多项目使用“ABI 分割”仅将目标设备的本机代码库包含在部署到设备的 APK 中。在 x86-64 和 aarch64 设备上,这可能导致 GeckoView 无法找到任何库,因为有效的 x86 和 ARM 库未包含在已部署的 APK 中。通过将 --target
设置为您的设备支持的确切 ABI 来避免这种情况。
将您的本地 GeckoView 依赖项替换到非 Mozilla 项目中¶
在尚未对依赖项替换提供一流支持的项目中,您可以自己执行替换。请参阅 substitue-local-geckoview.gradle 中的文档,但大致如下:在每个使用 GeckoView 的 Gradle 项目中,即在每个包含 dependencies { ... 'org.mozilla.geckoview:geckoview-...' }
块的 build.gradle
中,包含以下行
ext.topsrcdir = "/path/to/mozilla-central"
ext.topobjdir = "/path/to/object-directory" // Optional.
apply from: "${topsrcdir}/substitute-local-geckoview.gradle"
当您想返回使用已发布的 GeckoView 构建时,请记住从所有 ``build.gradle`` 文件中删除这些行!
后续步骤¶
开始使用 Android 本机调试