Я пытаюсь внедрить браузер Headless Chromium в свое приложение C ++. Для этого у меня есть класс, написанный как
class HeadlessExample :
public headless::HeadlessWebContents::Observer,
public headless::page::Observer,
{
public:
HeadlessExample(headless::HeadlessBrowser* browser,
headless::HeadlessWebContents* web_contents);
~HeadlessExample() override;
// headless::HeadlessWebContents::Observer implementation:
void DevToolsTargetReady() override;
// headless::page::Observer implementation:
void OnLoadEventFired(
const headless::page::LoadEventFiredParams& params) override;
private:
// The headless browser instance. Owned by the headless library. See main().
headless::HeadlessBrowser* browser_;
// Our tab. Owned by |browser_|.
headless::HeadlessWebContents* web_contents_;
// The DevTools client used to control the tab.
std::unique_ptr<headless::HeadlessDevToolsClient> devtools_client_;
// A helper for creating weak pointers to this class.
base::WeakPtrFactory<HeadlessExample> weak_factory_;
}
Для запуска безголового браузера есть главное, написанное как
int main(int argc, const char** argv) {
#if !defined(OS_WIN)
// This function must be the first thing we call to make sure child processes
// such as the renderer are started properly. The headless library starts
// child processes by forking and exec'ing the main application.
headless::RunChildProcessIfNeeded(argc, argv);
#endif
// Create a headless browser instance. There can be one of these per process
// and it can only be initialized once.
headless::HeadlessBrowser::Options::Builder builder(0, nullptr);
#if defined(OS_WIN)
// In windows, you must initialize and set the sandbox, or pass it along
// if it has already been initialized.
sandbox::SandboxInterfaceInfo sandbox_info = { 0 };
content::InitializeSandboxInfo(&sandbox_info);
builder.SetSandboxInfo(&sandbox_info);
#endif
// Here you can customize browser options. As an example we set the window
// size.
builder.SetWindowSize(gfx::Size(800, 600));
builder.SetUserAgent("Mozilla/5.0 (Windows NT 10.0; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0");
builder.SetAcceptLanguage("en-US,en;q=0.5");
// Pass control to the headless library. It will bring up the browser and
// invoke the given callback on the browser UI thread. Note: if you need to
// pass more parameters to the callback, you can add them to the Bind() call
// below.
// HeadlessExample example;
// example.StartDevToolsTarget();
headless::HeadlessBrowserMain(builder.Build(),
base::Bind(&OnHeadlessBrowserStarted));
}
Когда браузер инициализируется, эта функция работает. Здесь я загружаю HTML-страницу setcookie.html локально.
void OnHeadlessBrowserStarted(headless::HeadlessBrowser* browser) {
// In order to open tabs, we first need a browser context. It corresponds to a
// user profile and contains things like the user's cookies, local storage,
// cache, etc.
headless::HeadlessBrowserContext::Builder context_builder =
browser->CreateBrowserContextBuilder();
// Here we can set options for the browser context. As an example we enable
// incognito mode, which makes sure profile data is not written to disk.
context_builder.SetIncognitoMode(true);
// Construct the context and set it as the default. The default browser
// context is used by the Target.createTarget() DevTools command when no other
// context is given.
headless::HeadlessBrowserContext* browser_context = context_builder.Build();
browser->SetDefaultBrowserContext(browser_context);
// Get the URL from the command line.
base::CommandLine::StringVector args =
base::CommandLine::ForCurrentProcess()->GetArgs();
args.clear();
std::string url = "file:///C:/setcookie.html";
std::wstring wurl(url.begin(), url.end());
args.push_back(wurl);
if (args.empty()) {
LOG(ERROR) << "No URL to load";
browser->Shutdown();
return;
}
GURL url(args[0]);
// Open a tab (i.e., HeadlessWebContents) in the newly created browser
// context.
headless::HeadlessWebContents::Builder tab_builder(
browser_context->CreateWebContentsBuilder());
// We can set options for the opened tab here. In this example we are just
// setting the initial URL to navigate to.
tab_builder.SetInitialURL(url);
// Create an instance of the example app, which will wait for the page to load
// and print its DOM.
headless::HeadlessWebContents* web_contents = tab_builder.Build();
g_example = new HeadlessExample(browser, web_contents);
}
Содержимое файла setcookie.html
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<p id="demo1">A Paragraph1.</p>
<p id="demo2">A Paragraph2.</p>
<p id="demo3">A Paragraph3.</p>
<script>
document.getElementById("demo1").innerHTML = document.body.getElementsByTagName("script")[0].innerHTML;
</script>
<script>
document.getElementById("demo2").innerHTML = document.body.getElementsByTagName("script")[1].innerHTML;
</script>
<script>
document.getElementById("demo3").innerHTML = document.body.getElementsByTagName("script")[2].innerHTML;
</script>
</body>
</html>
В основном, часть тела этой страницы содержит три сценария. Когда я загружаю эту страницу с помощью браузера, все эти три сценария запускаются автоматически при загрузке страницы, поскольку сценарии находятся внутри узла body.
Когда страница загружается в моем примере приложения (HeadlessExample), вызывается функция OnLoadEventFire
void HeadlessExample::OnLoadEventFired(
const headless::page::LoadEventFiredParams& params) {
}
Я правильно вхожу в эту функцию. Я хочу запустить все записи внутри тега body при загрузке страницы. Пожалуйста, кто-нибудь расскажет о механизмах запуска всех скриптов в теге body html-страницы при загрузке страницы.
Задача ещё не решена.
Других решений пока нет …