Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(535)

Side by Side Diff: headless/app/headless_example.cc

Issue 2677033003: headless: Add a small C++ example application (Closed)
Patch Set: outerHTML instead of innerHTML Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « headless/README.md ('k') | headless/app/headless_shell.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // A small example application showing the use of the C++ Headless Chrome
6 // library. It navigates to a web site given on the command line, waits for it
7 // to load and prints out the DOM.
8 //
9 // Tip: start reading from the main() function below.
10
11 #include "base/bind.h"
12 #include "base/command_line.h"
13 #include "base/memory/weak_ptr.h"
14 #include "headless/public/devtools/domains/page.h"
15 #include "headless/public/devtools/domains/runtime.h"
16 #include "headless/public/headless_browser.h"
17 #include "headless/public/headless_devtools_client.h"
18 #include "headless/public/headless_devtools_target.h"
19 #include "headless/public/headless_web_contents.h"
20 #include "ui/gfx/geometry/size.h"
21
22 // This class contains the main application logic, i.e., waiting for a page to
23 // load and printing its DOM. Note that browser initialization happens outside
24 // this class.
25 class HeadlessExample : public headless::HeadlessWebContents::Observer,
alex clarke (OOO till 29th) 2017/02/10 14:46:47 This should probably extend inspector::Experimenta
Sami 2017/02/10 16:25:26 Hmm, this is supposed to be a really simple exampl
26 public headless::page::Observer {
27 public:
28 HeadlessExample(headless::HeadlessBrowser* browser,
29 headless::HeadlessWebContents* web_contents);
30 ~HeadlessExample() override;
31
32 // headless::HeadlessWebContents::Observer implementation:
33 void DevToolsTargetReady() override;
34
35 // headless::page::Observer implementation:
36 void OnLoadEventFired(
37 const headless::page::LoadEventFiredParams& params) override;
38
39 void OnDomFetched(std::unique_ptr<headless::runtime::EvaluateResult> result);
40
41 private:
42 // The headless browser instance. See main().
43 headless::HeadlessBrowser* browser_;
altimin 2017/02/10 14:39:43 UNOWNED?
Sami 2017/02/10 16:25:26 I'm thinking in the age of unique_ptr and friends,
44 // Our tab.
45 headless::HeadlessWebContents* web_contents_;
altimin 2017/02/10 14:39:43 UNOWNED?
Sami 2017/02/10 16:25:26 Done.
46 // The DevTools client used to control the tab.
47 std::unique_ptr<headless::HeadlessDevToolsClient> devtools_client_;
48 // A helper for creating weak pointers to this class.
49 base::WeakPtrFactory<HeadlessExample> weak_factory_;
50 };
51
52 namespace {
53 std::unique_ptr<HeadlessExample> g_example;
altimin 2017/02/10 14:39:43 I'm slightly terrified about the idea that Headles
Sami 2017/02/10 16:25:26 Good point, let's make this a raw ptr.
54 }
55
56 HeadlessExample::HeadlessExample(headless::HeadlessBrowser* browser,
57 headless::HeadlessWebContents* web_contents)
58 : browser_(browser),
59 web_contents_(web_contents),
60 devtools_client_(headless::HeadlessDevToolsClient::Create()),
61 weak_factory_(this) {
62 web_contents_->AddObserver(this);
63 }
64
65 HeadlessExample::~HeadlessExample() {
66 // Note that we shut down the browser last, because it owns objects such as
67 // the web contents which can no longer be accessed after the browser is gone.
68 web_contents_->GetDevToolsTarget()->DetachClient(devtools_client_.get());
altimin 2017/02/10 14:39:43 We should also add removing observer from Page dom
Sami 2017/02/10 16:25:26 Oops, done.
69 web_contents_->RemoveObserver(this);
70 browser_->Shutdown();
71 }
72
73 // This method is called when the tab is ready for DevTools inspection.
74 void HeadlessExample::DevToolsTargetReady() {
75 // Attach our DevTools client to the tab so that we can send commands to it
76 // and observe events.
77 web_contents_->GetDevToolsTarget()->AttachClient(devtools_client_.get());
78
79 // Start observing events from DevTools's page domain. This lets us get
80 // notified when the page has finished loading. Note that it is possible
81 // the page has already finished loading by now. See
82 // HeadlessShell::DevToolTargetReady for how to handle that case correctly.
83 devtools_client_->GetPage()->AddObserver(this);
84 devtools_client_->GetPage()->Enable();
85 }
86
87 void HeadlessExample::OnLoadEventFired(
88 const headless::page::LoadEventFiredParams& params) {
89 // The page has now finished loading. Let's grab a snapshot of the DOM by
90 // evaluating the outerHTML property on the body element.
91 devtools_client_->GetRuntime()->Evaluate(
92 "document.body.outerHTML",
93 base::Bind(&HeadlessExample::OnDomFetched, weak_factory_.GetWeakPtr()));
94 }
95
96 void HeadlessExample::OnDomFetched(
97 std::unique_ptr<headless::runtime::EvaluateResult> result) {
98 std::string dom;
altimin 2017/02/10 14:39:43 Check that we got a valid result here?
Sami 2017/02/10 16:25:26 Done.
99 if (result->GetResult()->GetValue()->GetAsString(&dom))
100 printf("%s\n", dom.c_str());
101
102 // Shut down the browser (see ~HeadlessExample).
103 g_example.reset();
104 }
105
106 // This function is called by the headless library after the browser has been
107 // initialized. It runs on the UI thread.
108 void OnHeadlessBrowserStarted(headless::HeadlessBrowser* browser) {
109 // In order to open tabs, we first need a browser context. It corresponds to a
110 // user profile and contains things like the user's cookies, local storage,
111 // cache, etc.
112 headless::HeadlessBrowserContext::Builder context_builder =
113 browser->CreateBrowserContextBuilder();
114
115 // Here we can set options for the browser context. As an example we enable
116 // incognito mode, which makes sure profile data is not written to disk.
117 context_builder.SetIncognitoMode(true);
118
119 // Construct the context and set it as the default. The default browser
120 // context is used by the Target.createTarget() DevTools command when no other
121 // context is given.
122 headless::HeadlessBrowserContext* browser_context = context_builder.Build();
123 browser->SetDefaultBrowserContext(browser_context);
124
125 // Get the URL from the command line.
126 base::CommandLine::StringVector args =
127 base::CommandLine::ForCurrentProcess()->GetArgs();
128 if (args.empty()) {
129 LOG(ERROR) << "No URL to load";
130 browser->Shutdown();
131 return;
132 }
133 GURL url(args[0]);
134
135 // Open a tab (i.e., HeadlessWebContents) in the newly created browser
136 // context.
137 headless::HeadlessWebContents::Builder tab_builder(
138 browser_context->CreateWebContentsBuilder());
139
140 // We can set options for the opened tab here. In this example we are just
141 // setting the initial URL to navigate to.
142 tab_builder.SetInitialURL(url);
143
144 // Create an instance of the example app, which will wait for the page to load
145 // and print its DOM.
146 headless::HeadlessWebContents* web_contents = tab_builder.Build();
147 g_example.reset(new HeadlessExample(browser, web_contents));
148 }
149
150 int main(int argc, const char** argv) {
151 // This function must be the first thing we call to make sure child processes
152 // such as the renderer are started properly. The headless library starts
153 // child processes by forking and exec'ing the main application.
154 headless::RunChildProcessIfNeeded(argc, argv);
155
156 // Create a headless browser instance. There can be one of these per process
157 // and it can only be initialized once.
158 headless::HeadlessBrowser::Options::Builder builder(argc, argv);
159
160 // Here you can customize browser options. As an example we set the window
161 // size.
162 builder.SetWindowSize(gfx::Size(800, 600));
163
164 // Pass control to the headless library. It will bring up the browser and
165 // invoke the given callback on the browser UI thread. Note: if you need to
166 // pass more parameters to the callback, you can add them to the Bind() call
167 // below.
168 return headless::HeadlessBrowserMain(builder.Build(),
169 base::Bind(&OnHeadlessBrowserStarted));
170 }
OLDNEW
« no previous file with comments | « headless/README.md ('k') | headless/app/headless_shell.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698