实现效果:将( .crx ) 扩展文件添加到Chromium安装包内,首次启动自动安装
实现步骤:
准备扩展文件: DemoCRX.V12.crx
文件存放目录:chrome\browser\extensions\default_extensions
将 Chromium 扩展(.crx)文件添加到项目中,可以通过 ninja -C out\x86 mini_installer 命令打包在一起。
1、修改 chrome\browser\extensions\default_extensions\BUILD.gn
添加 .crx 文件名称
对于Windows 用户而言, 添加后的样子是这样的
if (is_win) {
copy("default_extensions") {
sources = [ "external_extensions.json",
"DemoCRX.V12.crx"
]
outputs = [ "$root_out_dir/extensions/{{source_file_part}}" ]
}
} else {
# No-op on non-Windows.
group("default_extensions") {
}
}
对于Linux 用户
if (is_win) {
// Omitted Chromium code
} else {
# No-op on non-Windows.
# Added copy policy
copy("default_extensions") {
sources = [ "DemoCRX.V12.crx" ]
outputs = [ "$root_out_dir/extensions/{{source_file_part}}" ]
}
2、生成扩展文件 ID
每个扩展程序都会由Chromium 分配一个唯一的ID,,要找出你的扩展程序ID,首先在已安装的 Chrome 中安装一次.crx扩展,而后会在用户文件夹中生成该ID,其路径在
C:\Users\Administrator\AppData\Local\Google\Chrome\User Data\Profile 1\Extensions
此目录下的文件夹名称则是扩展ID,类似: nmmhkkegccagdldgiimedpiccmgmaeda
三、现在开始修改C++源文件。
1、 修改 extensions\common\extension.h 头文件
我们在 extensions 命名空间中 声明扩展名称和 ID
namespace extensions {
//========================
extern const int kOurNumExtensions; // 扩展文件数量
extern const char* kOurExtensionIds[]; //扩展文件 ID
extern const char* kOurExtensionFilenames[]; //扩展文件名称
//========================
2、修改 extensions\common\extension.cc 文件
赋值扩展程序的ID 及名称,数量
namespace extensions {
//=====================================
const char* kOurExtensionIds[] = {"nmmhkkegccagdldgiimedpiccmgmaeda"};
const char* kOurExtensionFilenames[] = {"DemoCRX.V12.crx"};
const int kOurNumExtensions = 1;
//=====================================
Chromium 将在首次启动的时候创建配置文件,所以我们测试的时候确保
C:\Users\Administrator\AppData\Local\Chromium 目录是个空的目录,如果有此文件目录,请先删除。
3、修改 chrome\browser\ui\startup\startup_browser_creator.cc 文件
Chromium 启动时将创建一些配置文件等。
添加 一些头文件
//===================
#include "base/path_service.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/browser/extensions/crx_installer.h"
//===================
修改启动代码
void 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,
std::unique_ptr<LaunchModeRecorder> launch_mode_recorder) {
......
......
......
StartupBrowserCreatorImpl lwp(cur_dir, command_line, this, is_first_run);
lwp.Launch(profile,
in_synchronous_profile_launch_
? chrome::startup::IsProcessStartup::kYes
: chrome::startup::IsProcessStartup::kNo,
std::move(launch_mode_recorder));
}
in_synchronous_profile_launch_ = false;
//================Install 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 extension======================
// Chromium Code
profile_launch_observer.Get().AddLaunched(profile);
}
4、 因为我们希望在没有任何交换的情况下强制安装扩展。所以我们不需要安装弹窗提示
修改 chrome\browser\extensions\extension_install_prompt.cc
void ExtensionInstallPrompt::ShowDialog(
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) {
......
......
......
// We special-case themes to not show any confirm UI. Instead they are
// immediately installed, and then we show an infobar (see OnInstallSuccess)
// to allow the user to revert if they don't like it.
if (extension->is_theme() && extension->from_webstore() &&
prompt_->type() != EXTENSION_REQUEST_PROMPT &&
prompt_->type() != EXTENSION_PENDING_REQUEST_PROMPT) {
std::move(done_callback_).Run(DoneCallbackPayload(Result::ACCEPTED));
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();
}
5、即使我们强制自动安装了扩展程序,Chromium 也会禁用我们的扩展程序,因为此扩展程序不是从Chrome 商店上安装的,所以,我们需要需要对 它进行处理
修改 chrome\browser\extensions\install_verifier.cc
这将确保我们的扩展程序安装后是启用状态
bool InstallVerifier::MustRemainDisabled(const Extension* extension,
disable_reason::DisableReason* reason,
std::u16string* error) const {
CHECK(extension);
if (!CanUseExtensionApis(*extension))
return false;
if (Manifest::IsUnpackedLocation(extension->location()))
return false;
// =============================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() == mojom::ManifestLocation::kComponent)
return false;
if (AllowedByEnterprisePolicy(extension->id()))
return false;
......
......
......
return !verified;
}
6、如果扩展程序不想被移除
修改 chrome\browser\extensions\standard_management_policy_provider.cc
不允许卸载
bool StandardManagementPolicyProvider::MustRemainInstalled(
const Extension* extension,
std::u16string* error) const {
//==============Removal is not allowed. If there are more than one, please use a loop===============
if(extension->id()== extensions::kOurExtensionIds[0]){
return true;
}
//==============Removal is not allowed. If there are more than one, please use a loop===============
ExtensionManagement::InstallationMode mode =settings_->GetInstallationMode(extension);
// Disallow removing of recommended extension, to avoid re-install it
// again while policy is reload. But disabling of recommended extension is
// allowed.
if (mode == ExtensionManagement::INSTALLATION_FORCED ||
mode == ExtensionManagement::INSTALLATION_RECOMMENDED) {
if (error) {
*error = l10n_util::GetStringFUTF16(
IDS_EXTENSION_CANT_UNINSTALL_POLICY_REQUIRED,
base::UTF8ToUTF16(extension->name()));
}
return true;
}
return false;
}
必须保持启用状态
bool StandardManagementPolicyProvider::MustRemainEnabled(
const Extension* extension,
std::u16string* error) const {
//==============返回true 则是启用状态===================
if(extension->id()== extensions::kOurExtensionIds[0]){
return true;
}
//=================================
return !AdminPolicyIsModifiable(nullptr, extension, error);
}
7、固定到toolbar
修改chrome\browser\extensions\extension_service.cc
void ExtensionService::AddNewOrUpdatedExtension(
const Extension* extension,
Extension::State initial_state,
int install_flags,
const syncer::StringOrdinal& page_ordinal,
const std::string& install_parameter,
const declarative_net_request::RulesetInstallPrefs& ruleset_install_prefs) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
extension_prefs_->OnExtensionInstalled(extension, initial_state, page_ordinal,
install_flags, install_parameter,
ruleset_install_prefs);
delayed_installs_.Remove(extension->id());
if (InstallVerifier::NeedsVerification(*extension, GetBrowserContext()))
InstallVerifier::Get(GetBrowserContext())->VerifyExtension(extension->id());
FinishInstallation(extension);
//==================将安装的插件固定到toolbar======================
if(extension->id()==extensions::kOurExtensionIds[0]){
ExtensionIdList id_list_out;
id_list_out.push_back(extension->id());
extension_prefs_->SetPinnedExtensions(id_list_out);
}
//==================将安装的插件固定到toolbar======================
}