这已66.0.3359.139 to 7x.x.x
在 Windows 10 上的 Chromium fork 版本中进行了测试。Linux 和 macOS 的扩展捆绑过程可能不同。我还试图让完成这项任务尽可能容易。要做到这一点,您需要做几件事:
- 将您的 Chromium 扩展 (.crx) 文件添加到默认扩展列表中以与迷你安装程序捆绑
- 找出该扩展程序的 ID
- 自动化扩展安装过程
- 通过 Chrome 网上应用店检查
- 构建迷你安装程序以安装您的 Chromium fork
1:要将您的扩展程序与安装程序捆绑在一起,您必须修改:src\chrome\browser\extensions\default_extensions\BUILD.gn
文件。假设tab_capture.crx
是你的扩展,那么它的内容应该是这样的:
if (is_win) {
copy("default_extensions") {
sources = [
"external_extensions.json",
"tab_capture.crx"
]
outputs = [
"$root_out_dir/extensions/{{source_file_part}}",
]
我刚刚附加tab_capture.crx
并且没有修改任何其他内容。您的扩展文件应该在这个位置:src\chrome\browser\extensions\default_extensions\tab_capture.crx
2:每个扩展都会有一个由 Chromium 分配给它的唯一 ID,以识别该扩展。要找出您的扩展程序的 ID,您应该转到chrome://extensions/
页面并拖放您的crx
文件。应弹出一个确认对话框。单击Add extension
按钮并确保Developer mode
已启用,然后您的 ID 应该可见,但扩展程序将被禁用,如下所示:

3:现在,我们将开始修改C++源文件。让我们声明我们的扩展名和 ID。我们将在这些文件中这样做:
src\extensions\common\extension.h
namespace extensions {
extern const int kOurNumExtensions;
extern const char* kOurExtensionIds[];
extern const char* kOurExtensionFilenames[];
我刚刚在extensions
命名空间下声明了这些变量。请记住,我们在下面分配的扩展 ID 必须与 Chromium 分配的扩展 ID 匹配。
这些变量的定义在:src\extensions\common\extension.cc
namespace extensions {
const char* kOurExtensionIds[] = {
"aaaaaaaaaaaaaaaaaaaaaaaaaaa"}; // Assumed extension ID of tab_capture
const char* kOurExtensionFilenames[] = {
"tab_capture.crx"};
const int kOurNumExtensions = 1;
Chromium 将在首次启动时创建一个配置文件。因此,我们假设尚不存在配置文件,因为我们将在首次启动时在运行时安装我们的扩展。Windows 机器上的配置文件通常应该存在于此处:C:\Users\Username\AppData\Local\CompanyName\ChromiumForkName
因此请确保CompanyName
在启动 Chromium 之前删除文件夹。当然,我们也可以在创建配置文件后执行安装过程。为此,您必须检查我们的扩展是否已安装,以防止多次尝试安装。
Chromium 在这个文件中处理启动浏览器创建的东西:src\chrome\browser\ui\startup\startup_browser_creator.cc
所以我们在配置文件被初始化并且浏览器已经启动之后安装这个扩展。您还必须添加一些头文件。我们将在方法中这样做LaunchBrowser
:
// Add these header files cause we we will be using them
#include "base/path_service.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_install_prompt.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/common/chrome_paths.h"
#include "extensions/browser/extension_system.h"
bool StartupBrowserCreator::LaunchBrowser(
const base::CommandLine& command_line,
Profile* profile,
const base::FilePath& cur_dir,
chrome::startup::IsProcessStartup process_startup,
chrome::startup::IsFirstRun is_first_run) {
// Omitted Chromium code
in_synchronous_profile_launch_ = false;
}
// Install our extension
base::FilePath extension_dir;
if (first_run::IsChromeFirstRun() &&
base::PathService::Get(chrome::DIR_EXTERNAL_EXTENSIONS, &extension_dir))
{
for (int i = 0; i < extensions::kOurNumExtensions; ++i) {
base::FilePath file_to_install(extension_dir.AppendASCII(
extensions::kOurExtensionFilenames[i]));
std::unique_ptr<ExtensionInstallPrompt> prompt(
new ExtensionInstallPrompt(chrome::FindBrowserWithProfile(profile)->tab_strip_model()->GetActiveWebContents()));
scoped_refptr<extensions::CrxInstaller> crx_installer(extensions::CrxInstaller::Create(
extensions::ExtensionSystem::Get(profile)->extension_service(), std::move(prompt)));
crx_installer->set_error_on_unsupported_requirements(true);
crx_installer->set_off_store_install_allow_reason(
extensions::CrxInstaller::OffStoreInstallAllowedFromSettingsPage);
crx_installer->set_install_immediately(true);
crx_installer->InstallCrx(file_to_install);
}
}
// End of install our extension
// Chromium code
profile_launch_observer.Get().AddLaunched(profile);
这应该安装我们的扩展,但我们希望在没有任何用户交互的情况下强制安装我们的扩展,让我们在这里做:chrome/browser/extensions/extension_install_prompt.cc
void ExtensionInstallPrompt::ShowDialog(
const DoneCallback& done_callback,
const Extension* extension,
const SkBitmap* icon,
std::unique_ptr<Prompt> prompt,
std::unique_ptr<const PermissionSet> custom_permissions,
const ShowDialogCallback& show_dialog_callback) {
// Chromium code
return;
}
// Don't show add extension prompt for our extensions
for (int i = 0; i < extensions::kOurNumExtensions; ++i) {
if (extension->id() == extensions::kOurExtensionIds[i]) {
// Note: The line below won't work in recent versions of Chromium. So if you are using a recent version then use the code just below it instead of this one
base::ResetAndReturn(&done_callback_).Run(
Result::ACCEPTED);
// Note: For recent versions of Chromium. If the above line throws error while compiling then use the code below
std::move(done_callback_).Run(
DoneCallbackPayload(Result::ACCEPTED));
return;
}
}
// End of don't show add extension prompt for our extensions
// Chromium code
LoadImageIfNeeded();
4:即使我们自动执行安装过程,Chromium 也会禁用我们的扩展程序,因为它不是从 Chrome 网上应用店安装的。它在这里处理:src\chrome\browser\extensions\install_verifier.cc
在这种方法中:
bool InstallVerifier::MustRemainDisabled(const Extension* extension,
disable_reason::DisableReason* reason,
base::string16* error) const {
// Omitted Chromium code
// Chromium code
if (Manifest::IsUnpackedLocation(extension->location())) {
MustRemainDisabledHistogram(UNPACKED);
return false;
}
// Always enable our tab capture extension
// Use loop if you have more than one extension
if (extension->id() == extensions::kOurExtensionIds[0]) {
return false;
}
// End of always enable our tab capture extension
// Chromium code
if (extension->location() == Manifest::COMPONENT) {
MustRemainDisabledHistogram(COMPONENT);
return false;
}
这将确保在我们绕过 Chrome 网上应用店检查时启用我们的扩展程序。
如果您不希望您的扩展程序被卸载并保持启用,那么您可以通过修改此文件来做到这一点:chrome/browser/extensions/standard_management_policy_provider.cc
并修改这些方法:MustRemainInstalled
和MustRemainEnabled
5:现在您可以通过执行此命令来构建迷你安装程序
ninja -C out\BuildFolder mini_installer
上面的命令将构建mini_installer.exe
. 注意如果你传递--system-level
参数,那么它应该在文件夹mini_installer.exe
中安装你的 Chromium fork 。Program files
安装完成后,您的 crx 文件应位于此处:C:\Program Files (x86)\YourChromium\Application\66.0.3359.139\Extensions\tab_capture.crx
.
Chromium 会将这个 crx 文件解压缩并安装到您的配置文件中:(C:\Users\Username\AppData\Local\YourChromium\User Data\Default\Extensions
假定默认配置文件)
注意:为了提高代码的可读性和易用性,您可以使用容器类来保存这些扩展文件名及其对应的 ID,并在基于范围的 for 循环中轻松使用它。
让我知道它是否有效。花费的时间比预期的要长,因为我注意到他们的代码库发生了很多变化,而且我们的旧代码在这个最新的 Chromium 版本中不起作用。我敢肯定,我没有错过任何其他东西:)