将Chrome扩展程序内置到Chromium中的标准方法 [英] Standard way to build a Chrome extension into Chromium

查看:318
本文介绍了将Chrome扩展程序内置到Chromium中的标准方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经构建了一个我已经使用Selenium安装到Chrome的Chrome扩展程序。



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



我发现了几个论坛,有人建议他们尝试一下,但是没有一个看起来像是成功的。



我发现了一些有关系统管理员如何为其网络中的用户强制将扩展安装到Chrome中的提示:



3:现在,我们将开始修改C ++源文件。让我们声明扩展程序的名称和ID。我们将在以下文件中这样做:
src\extensions\common\extension.h

 命名空间扩展{

extern const int kOurNumExtensions;
extern const char * kOurExtensionIds [];
extern const char * kOurExtensionFilenames [];

我刚刚在扩展名以下声明了这些变量命名空间。请记住,我们在下面分配的扩展名ID必须与Chromium分配的扩展名ID匹配。



这些变量的定义位于: src\extensions \common\extension.cc

 命名空间扩展{

const char * kOurExtensionIds [] = {
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}; //假定为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 方法中这样做:

  //添加这些标头文件,因为我们将使用它们
#include base / path_service.h
#include chrome / browser / extensions / crx_installer.h
#include chrome / browser / extensions /extension_install_prompt.h
#include chrome /浏览器/扩展名/extension_service.h
#include chrome / common / chrome_paths.h
#include扩展名/浏览器/ 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){
//省略的铬代码
in_synchronous_profile_launch_ = false;
}

//安装扩展名
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>提示(
new ExtensionInstallPrompt(chrome :: FindBrowserWithProfile(profile)-> tab_strip_model()-> GetActiveWebContents()));
scoped_refptr< extensions :: CrxInstaller> crx_installer(扩展名:: 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);
}
}
//扩展程序的安装结束

//铬代码
profile_launch_observer.Get()。AddLaunched(profile);

这应该安装我们的扩展程序,但是由于我们希望在没有任何用户交互的情况下强制安装我们的扩展程序,在这里执行: chrome /浏览器/扩展程序/extension_install_prompt.cc

  void ExtensionInstallPrompt :: ShowDialog(
const DoneCallback& done_callback,
const Extension *扩展名,
const SkBitmap *图标,
std :: unique_ptr< Prompt>提示符,
std :: unique_ptr< const PermissionSet> custom_permissions,
const ShowDialogCallback& show_dialog_callback){
//铬代码
return;
}

//不显示扩展名的添加扩展提示
for(int i = 0; i< extensions :: kOurNumExtensions; ++ i){
if(extension-> id()== extensions :: kOurExtensionIds [i]){
base :: ResetAndReturn(& done_callback _)。Run(Result :: ACCEPTED);
的回报;
}
}
//不显示结尾为扩展名添加扩展提示

//铬代码
LoadImageIfNeeded();

4:即使我们自动执行安装过程,Chromium也会禁用扩展程序的原因,因为它不是从Chrome Web Store安装的。在这里处理: src\chrome\浏览器扩展名install_verifier.cc 用这种方法:

  bool InstallVerifier :: MustRemainDisabled(const Extension *扩展名,
disable_reason :: DisableReason *原因,
base :: string16 *错误)const {
/ /省略的Chromium代码

// Chromium代码
if(Manifest :: IsUnpackedLocation(extension-> location())){
MustRemainDisabledHistogram(UNPACKED);
返回false;
}

//始终启用标签页捕获扩展名
//如果您有多个扩展名
if(extension-> id()= = extensions :: kOurExtensionIds [0]){
返回false;
}
//始终启用标签捕获扩展

//铬代码
if(extension-> location()== Manifest :: COMPONENT ){
MustRemainDisabledHistogram(COMPONENT);
返回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 ,则它将在<$ c中安装Chromium分支$ c>程序文件文件夹。安装完成后,您的crx文件应位于以下位置: C:\Program Files(x86)\YourChromium\Application\66.0.3359.139\Extensions\tab_capture.crx



Chromium将解压缩此crx文件并将其安装到您的个人资料中: C:\Users\Username\AppData\Local\YourChromium \用户数据\默认\扩展名(假定默认配置文件)



注意:提高代码的可读性并且易于使用,您可以使用容器类来保存这些扩展名及其对应的ID,并在基于for循环的范围内轻松使用它。



让我知道是否有用。我花了比预期更长的时间,因为我注意到他们的代码库中有很多更改,而我们的旧代码在最新的Chromium版本中无法正常工作。我敢肯定,我没有错过任何其他东西:)


I have built a Chrome extension that I have been installing into Chrome using Selenium.

Now I would like to build my own Chromium from source so that my extension is pre-bundled into the built distributed package so that I don't have to worry about needing Selenium to install the CRX file for my use case.

I have found several forums where people suggested they were going to try this, but none of them ended up seeming like they were successful.

I found some tips on how a system administrator can force install extensions into chromium for users in their network: https://support.google.com/chrome/a/answer/6306504?hl=en But that is for chrome enterprise, probably not going to be useful for me.

Here is another post which talks about how to offline install chrome extensions. I might be able to use some of this to make what I want happen.

Has anyone had success actually building into chromium a CRX so that the CRX is just installed automatically?

Quick update:

I just want to note: I'm installing my custom version of chrome with an InnoSetup installer. So I do have the chance to, after my chromium fork is installed, do some custom execution steps post install. And my extensions are hosted on the chrome web store and approved.

So if there is some way to programmatically install chrome extensions into a Chromium installation from the web store, I would could easily use that.

解决方案

This has been tested in our Chromium fork version 66.0.3359.139 on Windows 10. The extension bundling process might be different for Linux and OS X. I have also tried to make it as easy as possible to accomplish this task. There are a couple of things you will have to do to accomplish this:

  1. Add your Chromium extension (.crx) file to a list of default extensions to bundle with mini installer
  2. Find out the ID of that extension
  3. Automate plugin installation process
  4. By pass Chrome Web Store check
  5. Build mini installer to install your Chromium fork

1: To bundle your extension with the installer, you will have to modify: src\chrome\browser\extensions\default_extensions\BUILD.gn file. Suppose tab_capture.crx is your extension then it's contents should look something like this:

if (is_win) {
copy("default_extensions") {
sources = [
  "external_extensions.json",
  "tab_capture.crx"
]
outputs = [
  "$root_out_dir/extensions/{{source_file_part}}",
]

I have just appended tab_capture.crx and have not modified anything else. Your extension file should be in this location: src\chrome\browser\extensions\default_extensions\tab_capture.crx

2: Each extension will have a unique ID assigned to it by Chromium to identify that extension. To find out the ID of your extension you should go to chrome://extensions/ page and drag and drop your crx file. A confirmation dialog box should popup. Click Add extension button and make sure Developer mode is enabled then your ID should be visible but the extension will be disabled as shown below:

3: Now, we will start modifying C++ source files. Let's declare our extension's name and ID. We will do so in these files: src\extensions\common\extension.h

namespace extensions {

extern const int kOurNumExtensions;
extern const char* kOurExtensionIds[];
extern const char* kOurExtensionFilenames[];

I have just declared those variables below extensions namespace. Remember, extension ID that we are assigning below must match with the extension ID assigned by Chromium.

Those variables' definition in: 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 will create a profile when it's first launched. So we assume no profile exists yet because we will install our extension at run time when it's first launched. A profile on a Windows machine should typically exists here: C:\Users\Username\AppData\Local\CompanyName\ChromiumForkName so make sure to delete CompanyName folder before launching Chromium. Of course, we can do the installation process after a profile has been created too. For that you will have to check if our extension has been installed or not to prevent multiple attempts of installation.

Chromium handles startup browser creation stuff in this file: src\chrome\browser\ui\startup\startup_browser_creator.cc so we install this plugin after a profile has been initialized and browser has been launched. You will have to add some header files too. We will do so in LaunchBrowser method:

// 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);

That should install our extension but as we want our extension to be forcefully installed without any user interaction, let's do it here: 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]) {
        base::ResetAndReturn(&done_callback_).Run(Result::ACCEPTED);
        return;
    }
}
// End of don't show add extension prompt for our extensions

// Chromium code
LoadImageIfNeeded();

4: Even if we automate the installation process, Chromium will disable our extension cause it was not installed from Chrome Web Store. It's handled here: src\chrome\browser\extensions\install_verifier.cc in this method:

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;
}

This will ensure that our extension will be enabled as we are bypassing Chrome Web Store check.

If you don't want your extension to be uninstalled and remain enabled then you can do so by modifying this file: chrome/browser/extensions/standard_management_policy_provider.cc and modify these methods: MustRemainInstalled and MustRemainEnabled

5: Now you can build mini installer by executing this command ninja -C out\BuildFolder mini_installer to build mini_installer.exe. If you pass --system-level argument to mini_installer.exe then it should install your Chromium fork in Program files folder. After the installation is complete your crx file should be located here: C:\Program Files (x86)\YourChromium\Application\66.0.3359.139\Extensions\tab_capture.crx.

Chromium will unpack and install this crx file to your profile: C:\Users\Username\AppData\Local\YourChromium\User Data\Default\Extensions (Assumed default profile)

Note: To improve code readability and ease of use, you could use container classes to hold those extension file names and their corresponding IDs and use it easily in a range based for loop.

Let me know if it works. Took longer than expected cause I noticed lots of changes in their code base and our old code was not working in this latest Chromium build. I am sure, I have not missed anything else :)

这篇关于将Chrome扩展程序内置到Chromium中的标准方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆