c++ - 在 Chromium 中构建 Chrome 扩展的标准方法

标签 c++ google-chrome-extension chromium

我已经构建了一个 Chrome 扩展,我已经使用 Selenium 将它安装到 Chrome 中。

现在我想从源代码构建我自己的 Chromium,这样我的扩展就被预先捆绑到构建的分布式包中,这样我就不必担心需要 Selenium 为我的用例安装 CRX 文件。

我找到了几个论坛,人们建议他们尝试这个,但没有一个最终看起来像是成功的。

我发现了一些关于系统管理员如何为网络中的用户强制安装扩展到 Chrome 的提示:https://support.google.com/chrome/a/answer/6306504?hl=en
但那是针对 chrome 企业的,可能对我没有用。

Here is another post which talks about how to offline install chrome extensions .我也许可以使用其中的一些来实现我想要的。

有没有人成功地将 CRX 嵌入到 Chromium 中,以便 CRX 自动安装?

快速更新:

我只想注意:我正在使用 InnoSetup 安装程序安装我的自定义版本的 chrome。所以我确实有机会在安装我的 Chromium fork 后,在安装后执行一些自定义执行步骤。我的扩展程序托管在 chrome 网上商店并获得批准。

因此,如果有某种方法可以以编程方式将 chrome 扩展程序从网上商店安装到 Chromium 安装中,我会很容易地使用它。

最佳答案

这已经在我们的 Chromium fork 版本中进行了测试 66.0.3359.139 to 7x.x.x在 Windows 10 上。 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 应该可见,但扩展程序将被禁用,如下所示:
    enter image description here
    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并修改这些方法:MustRemainInstalledMustRemainEnabled 5:现在您可以通过执行此命令来构建迷你安装程序
    ninja -C out\BuildFolder mini_installer
    
    上面的命令将构建 mini_installer.exe . 备注 如果您通过 --system-level论据 mini_installer.exe那么它应该在 Program files 中安装你的 Chromium fork文件夹。安装完成后,您的 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 版本中不起作用。我敢肯定,我没有错过任何其他东西:)

    关于c++ - 在 Chromium 中构建 Chrome 扩展的标准方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50125821/

    相关文章:

    c++ - 复制构造函数何时开始工作?

    c++ - SACSegmentation检测奇平面模型

    javascript - Google chrome - 扩展程序 chrome 空闲时不起作用

    javascript - Chrome 扩展上下文菜单不存在

    html - 关于基于 Chromium 的桌面应用程序的想法?

    c++ - 使用 fscanf 从文件中读取字符

    c++ - 如何在 C++ 中计算 A、B、C <= 10^18 的 (A*B)%C?

    c++ - Berkelium 编译错误

    javascript - 我正在访问的网站可以访问由 Chrome 扩展程序添加的全局变量吗?

    javascript - css:在打印的 PDF 页面的 HTML 页脚中呈现页码(Chromium)