魔改chromium源码——自定义浏览器启动参数
在进行以下操作之前,请确保已完成之前文章中提到的 源码拉取及编译 部分。
如果已顺利完成相关配置,即可继续执行后续操作。
为什么需要自定义传参?
在讨论这个问题之前,我们需要引入一个重要的背景概念:环境持久化 和运行环境一致性 。这是许多现代浏览器应用场景中不可忽视的关键点。
众所周知,当浏览器启动时,其内部参数(如指纹、用户代理、硬件信息等)会被初始化并固定下来。例如,假设你登录了某个网站(比如A网站),第一次启动浏览器时,系统计算出的设备指纹是1111。但当你关闭浏览器后再次打开时,由于浏览器内部可能默认启用了指纹随机化机制 ,指纹可能会变成2222。对于A网站的风控系统来说,这种指纹的变化会被视为异常行为,进而将你的运行环境标记为可疑,甚至可能导致账户被限制或封禁。 因此,在实际应用中,为了实现更灵活且可控的浏览器行为,我们需要解决以下几个核心问题:
- 明确随机化的控制点 :我们需要知道哪些参数是可以被随机化的,以及如何修改它们。
- 实现随机值的持久化:随机生成的值需要能够在多次启动之间保持一致,避免因频繁变化而触发风控。
- 支持外部干预:通过外部手段动态调整内部参数,以满足不同场景的需求。
在这种情况下,自定义传参 就显得尤为重要。通过在浏览器启动时传递不同的参数,我们可以为每一个浏览器实例设置独立的配置,从而实现多样化的运行效果。例如:
- 数据隔离 :浏览器自带的--user-data-dir参数可以指定不同的用户数据目录,确保每个实例的数据完全隔离。
- 指纹定制 :通过传参,我们可以为每个浏览器实例分配固定的指纹值,避免因随机化导致的风控问题。
- 灵活扩展 :自定义传参不仅限于指纹,还可以用于调整其他关键参数(如分辨率、语言、时区等),从而更好地模拟真实用户环境。
综上所述,自定义传参是实现环境持久化和运行环境一致性的基础工具之一。它不仅能够帮助我们规避风控系统的误判,还能为复杂的应用场景提供更高的灵活性和可控性。这正是我们在设计和使用浏览器自动化方案时需要重点关注的核心能力
以下为实现步骤以及验证方式:
验证方式我们会用到 新增自定义变量到windows属性 这篇文章中的方法,将传参接收的值挂载到 window 全局变量。然后在devtool中输出,验证我们传值是否符合预期。
步骤 1:定义新的命令行开关
修改位置:
src\chrome\common\chrome_switches.h
在 namespace switches 中新增变量
extern const char kMyCustomFlag[]; // 新增
修改位置:
src\chrome\common\chrome_switches.cc
在 namespace switches 中新增变量,my-custom-flag 就是我们要传的链接参数
const char kMyCustomFlag[] = "my-custom-flag"; // 新增
步骤 2:创建 JavaScript 绑定,用于测试验证
在 src\content\renderer\ 中新增文件 my_custom_flag.h
#ifndef CONTENT_RENDERER_MY_CODE_BINDING_H_
#define CONTENT_RENDERER_MY_CODE_BINDING_H_
#include "v8/include/v8.h"
namespace content {
class myCustomFlagBinding {
public:
static void Install(v8::Local<v8::Context> context);
};
}
#endif
在 src\content\renderer\ 中新增文件 my_custom_flag.cc
#include "content/renderer/my_custom_flag.h"
#include "base/logging.h" // NEW: For LOG(INFO)
#include "v8/include/v8.h"
#include "base/command_line.h"
#include "chrome/common/chrome_switches.h"
namespace content {
void myCustomFlagBinding::Install(v8::Local<v8::Context> context) {
v8::Isolate* isolate = context->GetIsolate();
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Object> global = context->Global();
std::string value;
auto* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kMyCustomFlag)) {
value = command_line->GetSwitchValueASCII(switches::kMyCustomFlag);
LOG(INFO) << "Custom flag detected in renderer: --my-custom-flag=" << value; // NEW: Enable logging
} else {
LOG(INFO) << "No --my-custom-flag found in renderer"; // NEW: Log when switch is missing
}
// commandFlag 就是新增的全局变量,访问方式就是 window.commandFlag
global->Set(
context,
v8::String::NewFromUtf8(isolate, "commandFlag").ToLocalChecked(),
v8::String::NewFromUtf8(isolate, value.c_str()).ToLocalChecked())
.Check();
}
} // namespace content
将新增的这2个文件,添加到 BUILD.gn 的 target(link_target_type, "renderer") 下的 sources 列表中
步骤 3:绑定到 RenderFrameImpl,用于测试验证
修改位置:
src\content\renderer\render_frame_impl.cc
新增头文件
#include "content/renderer/my_custom_flag.h"
新增内容
if (world_id == 0) {
myCustomFlagBinding::Install(context);
}
步骤 4:确保开关传播到渲染进程
修改位置:
src\content\browser\renderer_host\render_process_host_impl.cc
新增头文件
#include "chrome/common/chrome_switches.h"
在void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer中新增
switches::kMyCustomFlag,
最后,在src目录下,执行 gn gen out/Default ,重新生成构建文件
构建成功之后运行一下命令进行编译
autoninja -C out/Default chrome
使用以下方式启动编译好的chrome.exe