summaryrefslogtreecommitdiff
path: root/chromium/headless
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-04-05 14:08:31 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-04-11 07:46:53 +0000
commit6a4cabb866f66d4128a97cdc6d9d08ce074f1247 (patch)
treeab00f70a5e89278d6a0d16ff0c42578dc4d84a2d /chromium/headless
parente733310db58160074f574c429d48f8308c0afe17 (diff)
downloadqtwebengine-chromium-6a4cabb866f66d4128a97cdc6d9d08ce074f1247.tar.gz
BASELINE: Update Chromium to 57.0.2987.144
Change-Id: I29db402ff696c71a04c4dbaec822c2e53efe0267 Reviewed-by: Peter Varga <pvarga@inf.u-szeged.hu>
Diffstat (limited to 'chromium/headless')
-rw-r--r--chromium/headless/BUILD.gn30
-rw-r--r--chromium/headless/DEPS7
-rw-r--r--chromium/headless/OWNERS1
-rw-r--r--chromium/headless/README.md50
-rw-r--r--chromium/headless/app/headless_shell.cc154
-rw-r--r--chromium/headless/app/headless_shell_switches.cc6
-rw-r--r--chromium/headless/app/headless_shell_switches.h1
-rw-r--r--chromium/headless/lib/DEPS6
-rw-r--r--chromium/headless/lib/browser/devtools_api/client_api_generator.py4
-rw-r--r--chromium/headless/lib/browser/devtools_api/domain_cc.template5
-rw-r--r--chromium/headless/lib/browser/devtools_api/domain_types_forward_declarations_h.template (renamed from chromium/headless/lib/browser/devtools_api/domain_types_forward_declaration_h.template)6
-rw-r--r--chromium/headless/lib/browser/devtools_api/domain_types_h.template2
-rw-r--r--chromium/headless/lib/browser/headless_browser_impl.cc23
-rw-r--r--chromium/headless/lib/browser/headless_browser_impl.h4
-rw-r--r--chromium/headless/lib/browser/headless_browser_main_parts.h1
-rw-r--r--chromium/headless/lib/browser/headless_content_browser_client.cc2
-rw-r--r--chromium/headless/lib/browser/headless_content_browser_client.h4
-rw-r--r--chromium/headless/lib/browser/headless_devtools_client_impl.cc33
-rw-r--r--chromium/headless/lib/browser/headless_devtools_client_impl.h5
-rw-r--r--chromium/headless/lib/browser/headless_devtools_manager_delegate.cc158
-rw-r--r--chromium/headless/lib/browser/headless_devtools_manager_delegate.h22
-rw-r--r--chromium/headless/lib/browser/headless_platform_event_source.cc13
-rw-r--r--chromium/headless/lib/browser/headless_platform_event_source.h26
-rw-r--r--chromium/headless/lib/browser/headless_screen.cc1
-rw-r--r--chromium/headless/lib/browser/headless_screen.h1
-rw-r--r--chromium/headless/lib/browser/headless_url_request_context_getter.cc9
-rw-r--r--chromium/headless/lib/browser/headless_url_request_context_getter.h9
-rw-r--r--chromium/headless/lib/browser/headless_web_contents_impl.cc41
-rw-r--r--chromium/headless/lib/browser/headless_web_contents_impl.h17
-rw-r--r--chromium/headless/lib/browser/headless_window_tree_host.cc75
-rw-r--r--chromium/headless/lib/browser/headless_window_tree_host.h48
-rw-r--r--chromium/headless/lib/embedder_mojo_browsertest.cc20
-rw-r--r--chromium/headless/lib/headless_content_main_delegate.cc42
-rw-r--r--chromium/headless/lib/headless_content_main_delegate.h12
-rw-r--r--chromium/headless/lib/headless_devtools_client_browsertest.cc129
-rw-r--r--chromium/headless/lib/headless_web_contents_browsertest.cc60
-rw-r--r--chromium/headless/lib/renderer/headless_content_renderer_client.cc16
-rw-r--r--chromium/headless/lib/renderer/headless_content_renderer_client.h22
-rw-r--r--chromium/headless/lib/utility/headless_content_utility_client.cc13
-rw-r--r--chromium/headless/lib/utility/headless_content_utility_client.h22
-rw-r--r--chromium/headless/public/domains/types_unittest.cc31
-rw-r--r--chromium/headless/public/headless_browser.h6
-rw-r--r--chromium/headless/public/headless_devtools_target.h15
-rw-r--r--chromium/headless/public/headless_web_contents.h11
-rw-r--r--chromium/headless/public/internal/value_conversions.h2
-rw-r--r--chromium/headless/public/util/deterministic_http_protocol_handler.h1
-rw-r--r--chromium/headless/public/util/dom_tree_extractor_browsertest.cc348
-rw-r--r--chromium/headless/public/util/http_url_fetcher.h1
-rw-r--r--chromium/headless/public/util/in_memory_request_job.h5
-rw-r--r--chromium/headless/public/util/testing/generic_url_request_mocks.cc1
-rw-r--r--chromium/headless/public/util/testing/generic_url_request_mocks.h8
51 files changed, 1079 insertions, 450 deletions
diff --git a/chromium/headless/BUILD.gn b/chromium/headless/BUILD.gn
index 9c9d392f436..d6cd10639cd 100644
--- a/chromium/headless/BUILD.gn
+++ b/chromium/headless/BUILD.gn
@@ -43,7 +43,7 @@ repack("pak") {
}
deps = [
- ":headless_lib_resources_grit",
+ ":resources",
"//components/strings",
"//content:resources",
"//content/app/resources",
@@ -60,7 +60,7 @@ repack("pak") {
output = "$root_out_dir/headless_lib.pak"
}
-grit("headless_lib_resources_grit") {
+grit("resources") {
source = "lib/resources/headless_lib_resources.grd"
outputs = [
"grit/headless_lib_resources.h",
@@ -137,7 +137,7 @@ action("gen_devtools_client_api") {
"lib/browser/devtools_api/domain_h.template",
"lib/browser/devtools_api/domain_type_conversions_h.template",
"lib/browser/devtools_api/domain_types_cc.template",
- "lib/browser/devtools_api/domain_types_forward_declaration_h.template",
+ "lib/browser/devtools_api/domain_types_forward_declarations_h.template",
"lib/browser/devtools_api/domain_types_h.template",
]
@@ -167,6 +167,8 @@ static_library("headless_lib") {
"lib/browser/headless_devtools_client_impl.h",
"lib/browser/headless_devtools_manager_delegate.cc",
"lib/browser/headless_devtools_manager_delegate.h",
+ "lib/browser/headless_platform_event_source.cc",
+ "lib/browser/headless_platform_event_source.h",
"lib/browser/headless_screen.cc",
"lib/browser/headless_screen.h",
"lib/browser/headless_url_request_context_getter.cc",
@@ -175,14 +177,12 @@ static_library("headless_lib") {
"lib/browser/headless_web_contents_impl.h",
"lib/browser/headless_window_parenting_client.cc",
"lib/browser/headless_window_parenting_client.h",
+ "lib/browser/headless_window_tree_host.cc",
+ "lib/browser/headless_window_tree_host.h",
"lib/headless_content_client.cc",
"lib/headless_content_client.h",
"lib/headless_content_main_delegate.cc",
"lib/headless_content_main_delegate.h",
- "lib/renderer/headless_content_renderer_client.cc",
- "lib/renderer/headless_content_renderer_client.h",
- "lib/utility/headless_content_utility_client.cc",
- "lib/utility/headless_content_utility_client.h",
"public/headless_browser.cc",
"public/headless_browser.h",
"public/headless_browser_context.h",
@@ -232,11 +232,8 @@ static_library("headless_lib") {
"//components/security_state/core",
"//content/public/app:both",
"//content/public/browser",
- "//content/public/child",
"//content/public/common",
"//content/public/common:service_names",
- "//content/public/renderer",
- "//content/public/utility",
"//net",
"//services/service_manager/public/cpp",
"//third_party/mesa:osmesa",
@@ -244,10 +241,14 @@ static_library("headless_lib") {
"//ui/base",
"//ui/compositor",
"//ui/display",
- "//ui/ozone",
+ "//ui/events/devices",
"//url",
]
+ if (use_ozone) {
+ deps += [ "//ui/ozone" ]
+ }
+
configs += [ ":headless_implementation" ]
}
@@ -331,6 +332,13 @@ test("headless_browsertests") {
data = [
"$root_out_dir/headless_browser_tests.pak",
+ "$root_out_dir/headless_lib.pak",
+ "//net/tools/testserver/",
+ "//third_party/pyftpdlib/",
+ "//third_party/pywebsocket/",
+ "//third_party/skia/",
+ "//third_party/tlslite/",
+ "test/data/",
]
defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
diff --git a/chromium/headless/DEPS b/chromium/headless/DEPS
index 500e0224908..edf61b6ede4 100644
--- a/chromium/headless/DEPS
+++ b/chromium/headless/DEPS
@@ -1,10 +1,15 @@
include_rules = [
- "+content/public",
+ "+content/public/app",
+ "+content/public/browser",
+ "+content/public/common",
+ "+content/public/test",
"+mojo/public",
"+net",
"+ui/base",
"+ui/base/resource",
"+ui/display",
+ "+ui/events/devices",
+ "+ui/events/platform",
"+ui/gfx",
"+ui/gfx/geometry",
"+ui/gl",
diff --git a/chromium/headless/OWNERS b/chromium/headless/OWNERS
index f845aaa8881..c87978e7381 100644
--- a/chromium/headless/OWNERS
+++ b/chromium/headless/OWNERS
@@ -1,2 +1,3 @@
skyostil@chromium.org
alexclarke@chromium.org
+altimin@chromium.org
diff --git a/chromium/headless/README.md b/chromium/headless/README.md
index 06128d79b66..bf4d30149cf 100644
--- a/chromium/headless/README.md
+++ b/chromium/headless/README.md
@@ -1,17 +1,37 @@
# Headless Chromium
-Headless Chromium is a library for running Chromium in a headless/server
-environment. Expected use cases include loading web pages, extracting metadata
-(e.g., the DOM) and generating bitmaps from page contents -- using all the
-modern web platform features provided by Chromium and Blink.
+Headless Chromium allows running Chromium in a headless/server environment.
+Expected use cases include loading web pages, extracting metadata (e.g., the
+DOM) and generating bitmaps from page contents -- using all the modern web
+platform features provided by Chromium and Blink.
-See the [architecture design doc](https://docs.google.com/document/d/11zIkKkLBocofGgoTeeyibB2TZ_k7nR78v7kNelCatUE)
-for more information.
+There are two ways to use Headless Chromium:
-## Headless shell
+## Usage via the DevTools remote debugging protocol
-The headless shell is a sample application which demonstrates the use of the
-headless API. To run it, first initialize a headless build configuration:
+1. Start a normal Chrome binary with the `--headless` command line flag
+(Linux-only for now):
+
+```
+$ chrome --headless --remote-debugging-port=9222 https://chromium.org
+```
+
+Currently you'll also need to use `--disable-gpu` to avoid an error from a
+missing Mesa library.
+
+2. Navigate to `http://localhost:9222` in another browser to open the
+[DevTools](https://developer.chrome.com/devtools) interface or use a tool such
+as [Selenium](http://www.seleniumhq.org/) to drive the headless browser.
+
+## Usage as a C++ library
+
+Headless Chromium can be built as a library for embedding into a C++
+application. This approach is otherwise similar to controlling the browser over
+a DevTools connection, but it provides more customization points, e.g., for
+networking and [mojo services](https://docs.google.com/document/d/1Fr6_DJH6OK9rG3-ibMvRPTNnHsAXPk0VzxxiuJDSK3M/edit#heading=h.qh0udvlk963d).
+
+Headless Shell is a sample application which demonstrates the use of the
+headless C++ API. To run it, first initialize a headless build configuration:
```
$ mkdir -p out/Debug
@@ -25,8 +45,7 @@ Then build the shell:
$ ninja -C out/Debug headless_shell
```
-After the build completes, the headless shell can be run with the following
-command:
+After the build completes, Headless Shell can be run with the following command:
```
$ out/Debug/headless_shell https://www.google.com
@@ -39,7 +58,7 @@ shell, start it with an argument specifying the debugging port:
$ out/Debug/headless_shell --remote-debugging-port=9222 https://youtube.com
```
-Then navigate to `http://127.0.0.1:9222` with your browser.
+Then navigate to `http://localhost:9222` with your browser.
## Embedder API
@@ -67,8 +86,12 @@ web pages. Its main classes are:
See the [client API documentation](https://docs.google.com/document/d/1rlqcp8nk-ZQvldNJWdbaMbwfDbJoOXvahPCDoPGOwhQ/edit#)
for more information.
-## Documentation
+## Resources and Documentation
+
+Mailing list: [headless-dev@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/headless-dev)
+Bug tracker: [Proj=Headless](https://bugs.chromium.org/p/chromium/issues/list?can=2&q=Proj%3DHeadless)
+* [Runtime headless mode for Chrome](https://docs.google.com/document/d/1aIJUzQr3eougZQp90bp4mqGr5gY6hdUice8UPa-Ys90/edit#)
* [Virtual Time in Blink](https://docs.google.com/document/d/1y9kdt_zezt7pbey6uzvt1dgklwc1ob_vy4nzo1zbqmo/edit#heading=h.tn3gd1y9ifml)
* [Headless Chrome architecture](https://docs.google.com/document/d/11zIkKkLBocofGgoTeeyibB2TZ_k7nR78v7kNelCatUE/edit)
* [Headless Chrome C++ DevTools API](https://docs.google.com/document/d/1rlqcp8nk-ZQvldNJWdbaMbwfDbJoOXvahPCDoPGOwhQ/edit#heading=h.ng2bxb15li9a)
@@ -77,3 +100,4 @@ web pages. Its main classes are:
* [Controlling BeginFrame through DevTools](https://docs.google.com/document/d/1LVMYDkfjrrX9PNkrD8pJH5-Np_XUTQHIuJ8IEOirQH4/edit?ts=57d96dbd#heading=h.ndv831lc9uf0)
* [Viewport bounds and scale for screenshots](https://docs.google.com/document/d/1VTcYz4q_x0f1O5IVrvRX4u1DVd_K34IVUl1VULLTCWw/edit#heading=h.ndv831lc9uf0)
* [BlinkOn 6 presentation slides](https://docs.google.com/presentation/d/1gqK9F4lGAY3TZudAtdcxzMQNEE7PcuQrGu83No3l0lw/edit#slide=id.p)
+* [Architecture design doc](https://docs.google.com/document/d/11zIkKkLBocofGgoTeeyibB2TZ_k7nR78v7kNelCatUE)
diff --git a/chromium/headless/app/headless_shell.cc b/chromium/headless/app/headless_shell.cc
index b57fc5f9070..047f408a0f4 100644
--- a/chromium/headless/app/headless_shell.cc
+++ b/chromium/headless/app/headless_shell.cc
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <iostream>
#include <memory>
+#include <sstream>
#include <string>
#include "base/base64.h"
@@ -13,12 +13,15 @@
#include "base/files/file_path.h"
#include "base/json/json_writer.h"
#include "base/location.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_number_conversions.h"
#include "content/public/common/content_switches.h"
#include "headless/app/headless_shell_switches.h"
#include "headless/public/devtools/domains/emulation.h"
+#include "headless/public/devtools/domains/inspector.h"
#include "headless/public/devtools/domains/page.h"
#include "headless/public/devtools/domains/runtime.h"
#include "headless/public/headless_browser.h"
@@ -42,7 +45,7 @@ const char kDefaultScreenshotFileName[] = "screenshot.png";
bool ParseWindowSize(std::string window_size, gfx::Size* parsed_window_size) {
int width, height = 0;
- if (sscanf(window_size.c_str(), "%dx%d", &width, &height) >= 2 &&
+ if (sscanf(window_size.c_str(), "%d%*[x,]%d", &width, &height) >= 2 &&
width >= 0 && height >= 0) {
parsed_window_size->set_width(width);
parsed_window_size->set_height(height);
@@ -55,6 +58,7 @@ bool ParseWindowSize(std::string window_size, gfx::Size* parsed_window_size) {
// An application which implements a simple headless browser.
class HeadlessShell : public HeadlessWebContents::Observer,
emulation::ExperimentalObserver,
+ inspector::ExperimentalObserver,
page::Observer {
public:
HeadlessShell()
@@ -62,7 +66,8 @@ class HeadlessShell : public HeadlessWebContents::Observer,
devtools_client_(HeadlessDevToolsClient::Create()),
web_contents_(nullptr),
processed_page_ready_(false),
- browser_context_(nullptr) {}
+ browser_context_(nullptr),
+ weak_factory_(this) {}
~HeadlessShell() override {}
void OnStart(HeadlessBrowser* browser) {
@@ -70,6 +75,8 @@ class HeadlessShell : public HeadlessWebContents::Observer,
HeadlessBrowserContext::Builder context_builder =
browser_->CreateBrowserContextBuilder();
+ // TODO(eseckler): These switches should also affect BrowserContexts that
+ // are created via DevTools later.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDeterministicFetch)) {
deterministic_dispatcher_.reset(
@@ -93,6 +100,7 @@ class HeadlessShell : public HeadlessWebContents::Observer,
}));
}
browser_context_ = context_builder.Build();
+ browser_->SetDefaultBrowserContext(browser_context_);
HeadlessWebContents::Builder builder(
browser_context_->CreateWebContentsBuilder());
@@ -101,16 +109,23 @@ class HeadlessShell : public HeadlessWebContents::Observer,
// TODO(alexclarke): Should we navigate to about:blank first if using
// virtual time?
- if (!args.empty() && !args[0].empty())
- builder.SetInitialURL(GURL(args[0]));
-
- web_contents_ = builder.Build();
- if (!web_contents_) {
- LOG(ERROR) << "Navigation failed";
- browser_->Shutdown();
- return;
+ if (args.empty())
+ args.push_back("about:blank");
+ for (auto it = args.rbegin(); it != args.rend(); ++it) {
+ GURL url(*it);
+ HeadlessWebContents* web_contents = builder.SetInitialURL(url).Build();
+ if (!web_contents) {
+ LOG(ERROR) << "Navigation to " << url << " failed";
+ browser_->Shutdown();
+ return;
+ }
+ if (!web_contents_ && !RemoteDebuggingEnabled()) {
+ // TODO(jzfeng): Support observing multiple targets.
+ url_ = url;
+ web_contents_ = web_contents;
+ web_contents_->AddObserver(this);
+ }
}
- web_contents_->AddObserver(this);
}
void Shutdown() {
@@ -118,8 +133,12 @@ class HeadlessShell : public HeadlessWebContents::Observer,
return;
if (!RemoteDebuggingEnabled()) {
devtools_client_->GetEmulation()->GetExperimental()->RemoveObserver(this);
+ devtools_client_->GetInspector()->GetExperimental()->RemoveObserver(this);
devtools_client_->GetPage()->RemoveObserver(this);
- web_contents_->GetDevToolsTarget()->DetachClient(devtools_client_.get());
+ if (web_contents_->GetDevToolsTarget()) {
+ web_contents_->GetDevToolsTarget()->DetachClient(
+ devtools_client_.get());
+ }
}
web_contents_->RemoveObserver(this);
web_contents_ = nullptr;
@@ -129,9 +148,8 @@ class HeadlessShell : public HeadlessWebContents::Observer,
// HeadlessWebContents::Observer implementation:
void DevToolsTargetReady() override {
- if (RemoteDebuggingEnabled())
- return;
web_contents_->GetDevToolsTarget()->AttachClient(devtools_client_.get());
+ devtools_client_->GetInspector()->GetExperimental()->AddObserver(this);
devtools_client_->GetPage()->AddObserver(this);
devtools_client_->GetPage()->Enable();
// Check if the document had already finished loading by the time we
@@ -156,15 +174,41 @@ class HeadlessShell : public HeadlessWebContents::Observer,
} else {
PollReadyState();
}
+
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kTimeout)) {
+ std::string timeout_ms_ascii =
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kTimeout);
+ int timeout_ms;
+ CHECK(base::StringToInt(timeout_ms_ascii, &timeout_ms))
+ << "Expected an integer value for --timeout=";
+ browser_->BrowserMainThread()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&HeadlessShell::FetchTimeout, weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(timeout_ms));
+ }
+
// TODO(skyostil): Implement more features to demonstrate the devtools API.
}
+ void FetchTimeout() {
+ LOG(INFO) << "Timeout.";
+ devtools_client_->GetPage()->GetExperimental()->StopLoading(
+ page::StopLoadingParams::Builder().Build());
+ }
+
+ void OnTargetCrashed(const inspector::TargetCrashedParams& params) override {
+ LOG(ERROR) << "Abnormal renderer termination.";
+ // NB this never gets called if remote debugging is enabled.
+ Shutdown();
+ }
+
void PollReadyState() {
// We need to check the current location in addition to the ready state to
// be sure the expected page is ready.
devtools_client_->GetRuntime()->Evaluate(
"document.readyState + ' ' + document.location.href",
- base::Bind(&HeadlessShell::OnReadyState, base::Unretained(this)));
+ base::Bind(&HeadlessShell::OnReadyState, weak_factory_.GetWeakPtr()));
}
void OnReadyState(std::unique_ptr<runtime::EvaluateResult> result) {
@@ -208,9 +252,8 @@ class HeadlessShell : public HeadlessWebContents::Observer,
FetchDom();
} else if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kRepl)) {
- std::cout
- << "Type a Javascript expression to evaluate or \"quit\" to exit."
- << std::endl;
+ LOG(INFO)
+ << "Type a Javascript expression to evaluate or \"quit\" to exit.";
InputExpression();
} else if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kScreenshot)) {
@@ -223,7 +266,7 @@ class HeadlessShell : public HeadlessWebContents::Observer,
void FetchDom() {
devtools_client_->GetRuntime()->Evaluate(
"document.body.innerHTML",
- base::Bind(&HeadlessShell::OnDomFetched, base::Unretained(this)));
+ base::Bind(&HeadlessShell::OnDomFetched, weak_factory_.GetWeakPtr()));
}
void OnDomFetched(std::unique_ptr<runtime::EvaluateResult> result) {
@@ -233,7 +276,7 @@ class HeadlessShell : public HeadlessWebContents::Observer,
} else {
std::string dom;
if (result->GetResult()->GetValue()->GetAsString(&dom)) {
- std::cout << dom << std::endl;
+ printf("%s\n", dom.c_str());
}
}
Shutdown();
@@ -242,23 +285,29 @@ class HeadlessShell : public HeadlessWebContents::Observer,
void InputExpression() {
// Note that a real system should read user input asynchronously, because
// otherwise all other browser activity is suspended (e.g., page loading).
- std::string expression;
- std::cout << ">>> ";
- std::getline(std::cin, expression);
- if (std::cin.bad() || std::cin.eof() || expression == "quit") {
+ printf(">>> ");
+ std::stringstream expression;
+ while (true) {
+ int c = fgetc(stdin);
+ if (c == EOF || c == '\n') {
+ break;
+ }
+ expression << c;
+ }
+ if (expression.str() == "quit") {
Shutdown();
return;
}
devtools_client_->GetRuntime()->Evaluate(
- expression,
- base::Bind(&HeadlessShell::OnExpressionResult, base::Unretained(this)));
+ expression.str(), base::Bind(&HeadlessShell::OnExpressionResult,
+ weak_factory_.GetWeakPtr()));
}
void OnExpressionResult(std::unique_ptr<runtime::EvaluateResult> result) {
std::unique_ptr<base::Value> value = result->Serialize();
std::string result_json;
base::JSONWriter::Write(*value, &result_json);
- std::cout << result_json << std::endl;
+ printf("%s\n", result_json.c_str());
InputExpression();
}
@@ -266,7 +315,7 @@ class HeadlessShell : public HeadlessWebContents::Observer,
devtools_client_->GetPage()->GetExperimental()->CaptureScreenshot(
page::CaptureScreenshotParams::Builder().Build(),
base::Bind(&HeadlessShell::OnScreenshotCaptured,
- base::Unretained(this)));
+ weak_factory_.GetWeakPtr()));
}
void OnScreenshotCaptured(
@@ -284,7 +333,7 @@ class HeadlessShell : public HeadlessWebContents::Observer,
file_name, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
base::File::FLAG_ASYNC,
base::Bind(&HeadlessShell::OnScreenshotFileOpened,
- base::Unretained(this), base::Passed(std::move(result)),
+ weak_factory_.GetWeakPtr(), base::Passed(std::move(result)),
file_name));
if (open_result != net::ERR_IO_PENDING) {
// Operation could not be started.
@@ -311,7 +360,7 @@ class HeadlessShell : public HeadlessWebContents::Observer,
const int write_result = screenshot_file_stream_->Write(
buf.get(), buf->size(),
base::Bind(&HeadlessShell::OnScreenshotFileWritten,
- base::Unretained(this), file_name, buf->size()));
+ weak_factory_.GetWeakPtr(), file_name, buf->size()));
if (write_result != net::ERR_IO_PENDING) {
// Operation may have completed successfully or failed.
OnScreenshotFileWritten(file_name, buf->size(), write_result);
@@ -326,11 +375,11 @@ class HeadlessShell : public HeadlessWebContents::Observer,
LOG(ERROR) << "Writing screenshot to file " << file_name.value()
<< " was unsuccessful: " << net::ErrorToString(write_result);
} else {
- std::cout << "Screenshot written to file " << file_name.value() << "."
+ LOG(INFO) << "Screenshot written to file " << file_name.value() << "."
<< std::endl;
}
int close_result = screenshot_file_stream_->Close(base::Bind(
- &HeadlessShell::OnScreenshotFileClosed, base::Unretained(this)));
+ &HeadlessShell::OnScreenshotFileClosed, weak_factory_.GetWeakPtr()));
if (close_result != net::ERR_IO_PENDING) {
// Operation could not be started.
OnScreenshotFileClosed(close_result);
@@ -354,10 +403,46 @@ class HeadlessShell : public HeadlessWebContents::Observer,
std::unique_ptr<net::FileStream> screenshot_file_stream_;
HeadlessBrowserContext* browser_context_;
std::unique_ptr<DeterministicDispatcher> deterministic_dispatcher_;
+ base::WeakPtrFactory<HeadlessShell> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(HeadlessShell);
};
+bool ValidateCommandLine(const base::CommandLine& command_line) {
+ if (!command_line.HasSwitch(::switches::kRemoteDebuggingPort)) {
+ if (command_line.GetArgs().size() <= 1)
+ return true;
+ LOG(ERROR) << "Open multiple tabs is only supported when the "
+ << "remote debug port is set.";
+ return false;
+ }
+ if (command_line.HasSwitch(switches::kDumpDom)) {
+ LOG(ERROR) << "Dump DOM is disabled when remote debugging is enabled.";
+ return false;
+ }
+ if (command_line.HasSwitch(switches::kRepl)) {
+ LOG(ERROR) << "Evaluate Javascript is disabled "
+ << "when remote debugging is enabled.";
+ return false;
+ }
+ if (command_line.HasSwitch(switches::kScreenshot)) {
+ LOG(ERROR) << "Capture screenshot is disabled "
+ << "when remote debugging is enabled.";
+ return false;
+ }
+ if (command_line.HasSwitch(switches::kTimeout)) {
+ LOG(ERROR) << "Navigation timeout is disabled "
+ << "when remote debugging is enabled.";
+ return false;
+ }
+ if (command_line.HasSwitch(switches::kVirtualTimeBudget)) {
+ LOG(ERROR) << "Virtual time budget is disabled "
+ << "when remote debugging is enabled.";
+ return false;
+ }
+ return true;
+}
+
int HeadlessShellMain(int argc, const char** argv) {
RunChildProcessIfNeeded(argc, argv);
HeadlessShell shell;
@@ -365,6 +450,9 @@ int HeadlessShellMain(int argc, const char** argv) {
// Enable devtools if requested.
base::CommandLine command_line(argc, argv);
+ if (!ValidateCommandLine(command_line))
+ return EXIT_FAILURE;
+
if (command_line.HasSwitch(::switches::kRemoteDebuggingPort)) {
std::string address = kDevToolsHttpServerAddress;
if (command_line.HasSwitch(switches::kRemoteDebuggingAddress)) {
diff --git a/chromium/headless/app/headless_shell_switches.cc b/chromium/headless/app/headless_shell_switches.cc
index 18cf95d3e1b..06750596296 100644
--- a/chromium/headless/app/headless_shell_switches.cc
+++ b/chromium/headless/app/headless_shell_switches.cc
@@ -35,6 +35,10 @@ const char kRepl[] = "repl";
// Save a screenshot of the loaded page.
const char kScreenshot[] = "screenshot";
+// Issues a stop after the specified number of milliseconds. This cancels all
+// navigation and causes the DOMContentLoaded event to fire.
+const char kTimeout[] = "timeout";
+
// Sets the GL implementation to use. Use a blank string to disable GL
// rendering.
const char kUseGL[] = "use-gl";
@@ -50,7 +54,7 @@ const char kUserDataDir[] = "user-data-dir";
// specified virtual time budget is exhausted.
const char kVirtualTimeBudget[] = "virtual-time-budget";
-// Sets the initial window size. Provided as string in the format "800x600".
+// Sets the initial window size. Provided as string in the format "800,600".
const char kWindowSize[] = "window-size";
} // namespace switches
diff --git a/chromium/headless/app/headless_shell_switches.h b/chromium/headless/app/headless_shell_switches.h
index 3806b43232d..9d0a348e6e7 100644
--- a/chromium/headless/app/headless_shell_switches.h
+++ b/chromium/headless/app/headless_shell_switches.h
@@ -14,6 +14,7 @@ extern const char kProxyServer[];
extern const char kRemoteDebuggingAddress[];
extern const char kRepl[];
extern const char kScreenshot[];
+extern const char kTimeout[];
extern const char kUseGL[];
extern const char kUserDataDir[];
extern const char kVirtualTimeBudget[];
diff --git a/chromium/headless/lib/DEPS b/chromium/headless/lib/DEPS
new file mode 100644
index 00000000000..54e541c3580
--- /dev/null
+++ b/chromium/headless/lib/DEPS
@@ -0,0 +1,6 @@
+specific_include_rules = {
+ "headless_web_contents_browsertest.cc": [
+ "+third_party/skia/include",
+ ]
+}
+
diff --git a/chromium/headless/lib/browser/devtools_api/client_api_generator.py b/chromium/headless/lib/browser/devtools_api/client_api_generator.py
index ce96de211b4..435358af73d 100644
--- a/chromium/headless/lib/browser/devtools_api/client_api_generator.py
+++ b/chromium/headless/lib/browser/devtools_api/client_api_generator.py
@@ -494,8 +494,8 @@ def GenerateTypes(jinja_env, output_dirname, json_api):
# Generate forward declarations for types.
GeneratePerDomain(
jinja_env, os.path.join(output_dirname, 'devtools', 'internal'),
- json_api, 'domain_types_forward_declaration', ['h'],
- lambda domain_name: 'types_forward_declaration_%s' % (domain_name, ))
+ json_api, 'domain_types_forward_declarations', ['h'],
+ lambda domain_name: 'types_forward_declarations_%s' % (domain_name, ))
# Generate types on per-domain basis.
GeneratePerDomain(
jinja_env, os.path.join(output_dirname, 'devtools', 'domains'),
diff --git a/chromium/headless/lib/browser/devtools_api/domain_cc.template b/chromium/headless/lib/browser/devtools_api/domain_cc.template
index 88f28b1f56a..dc04d6e9d7b 100644
--- a/chromium/headless/lib/browser/devtools_api/domain_cc.template
+++ b/chromium/headless/lib/browser/devtools_api/domain_cc.template
@@ -102,6 +102,11 @@ void {{class_name}}::{{method_name}}(std::unique_ptr<{{method_name}}Params> para
void Domain::Handle{{method_name}}Response(base::Callback<void(std::unique_ptr<{{method_name}}Result>)> callback, const base::Value& response) {
if (callback.is_null())
return;
+ // This is an error response.
+ if (response.IsType(base::Value::Type::NONE)) {
+ callback.Run(nullptr);
+ return;
+ }
ErrorReporter errors;
std::unique_ptr<{{method_name}}Result> result = {{method_name}}Result::Parse(response, &errors);
DCHECK(!errors.HasErrors());
diff --git a/chromium/headless/lib/browser/devtools_api/domain_types_forward_declaration_h.template b/chromium/headless/lib/browser/devtools_api/domain_types_forward_declarations_h.template
index 4bb223b04ab..b321a17bc56 100644
--- a/chromium/headless/lib/browser/devtools_api/domain_types_forward_declaration_h.template
+++ b/chromium/headless/lib/browser/devtools_api/domain_types_forward_declarations_h.template
@@ -4,8 +4,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef HEADLESS_PUBLIC_DEVTOOLS_INTERNAL_TYPES_FORWARD_DECLARATION_{{domain.domain | camelcase_to_hacker_style | upper}}_H_
-#define HEADLESS_PUBLIC_DEVTOOLS_INTERNAL_TYPES_FORWARD_DECLARATION_{{domain.domain | camelcase_to_hacker_style | upper}}_H_
+#ifndef HEADLESS_PUBLIC_DEVTOOLS_INTERNAL_TYPES_FORWARD_DECLARATIONS_{{domain.domain | camelcase_to_hacker_style | upper}}_H_
+#define HEADLESS_PUBLIC_DEVTOOLS_INTERNAL_TYPES_FORWARD_DECLARATIONS_{{domain.domain | camelcase_to_hacker_style | upper}}_H_
#include "base/optional.h"
#include "base/values.h"
@@ -41,4 +41,4 @@ enum class {{type.id}} {
} // namespace headless
-#endif // HEADLESS_PUBLIC_DEVTOOLS_INTERNAL_TYPES_FORWARD_DECLARATION_{{domain.domain | camelcase_to_hacker_style | upper}}_H_
+#endif // HEADLESS_PUBLIC_DEVTOOLS_INTERNAL_TYPES_FORWARD_DECLARATIONS_{{domain.domain | camelcase_to_hacker_style | upper}}_H_
diff --git a/chromium/headless/lib/browser/devtools_api/domain_types_h.template b/chromium/headless/lib/browser/devtools_api/domain_types_h.template
index f53f8ae1a52..b2e695ef6b9 100644
--- a/chromium/headless/lib/browser/devtools_api/domain_types_h.template
+++ b/chromium/headless/lib/browser/devtools_api/domain_types_h.template
@@ -10,7 +10,7 @@
#include "base/optional.h"
#include "base/values.h"
{% for domain_name in domain.dependencies %}
-#include "headless/public/devtools/internal/types_forward_declaration_{{domain_name | camelcase_to_hacker_style}}.h"
+#include "headless/public/devtools/internal/types_forward_declarations_{{domain_name | camelcase_to_hacker_style}}.h"
{% endfor %}
#include "headless/public/headless_export.h"
#include "headless/public/util/error_reporter.h"
diff --git a/chromium/headless/lib/browser/headless_browser_impl.cc b/chromium/headless/lib/browser/headless_browser_impl.cc
index c1647257fd3..93d6918a76c 100644
--- a/chromium/headless/lib/browser/headless_browser_impl.cc
+++ b/chromium/headless/lib/browser/headless_browser_impl.cc
@@ -19,9 +19,11 @@
#include "headless/lib/browser/headless_browser_main_parts.h"
#include "headless/lib/browser/headless_web_contents_impl.h"
#include "headless/lib/browser/headless_window_parenting_client.h"
+#include "headless/lib/browser/headless_window_tree_host.h"
#include "headless/lib/headless_content_main_delegate.h"
#include "ui/aura/env.h"
-#include "ui/aura/window_tree_host.h"
+#include "ui/aura/window.h"
+#include "ui/events/devices/device_data_manager.h"
#include "ui/gfx/geometry/size.h"
namespace headless {
@@ -52,6 +54,7 @@ HeadlessBrowserImpl::HeadlessBrowserImpl(
: on_start_callback_(on_start_callback),
options_(std::move(options)),
browser_main_parts_(nullptr),
+ default_browser_context_(nullptr),
weak_ptr_factory_(this) {}
HeadlessBrowserImpl::~HeadlessBrowserImpl() {}
@@ -119,9 +122,12 @@ void HeadlessBrowserImpl::set_browser_main_parts(
void HeadlessBrowserImpl::RunOnStartCallback() {
DCHECK(aura::Env::GetInstance());
+ ui::DeviceDataManager::CreateInstance();
+
window_tree_host_.reset(
- aura::WindowTreeHost::Create(gfx::Rect(options()->window_size)));
+ new HeadlessWindowTreeHost(gfx::Rect(options()->window_size)));
window_tree_host_->InitHost();
+ window_tree_host_->window()->Show();
window_parenting_client_.reset(
new HeadlessWindowParentingClient(window_tree_host_->window()));
@@ -153,6 +159,19 @@ void HeadlessBrowserImpl::DestroyBrowserContext(
auto it = browser_contexts_.find(browser_context->Id());
DCHECK(it != browser_contexts_.end());
browser_contexts_.erase(it);
+ if (default_browser_context_ == browser_context)
+ SetDefaultBrowserContext(nullptr);
+}
+
+void HeadlessBrowserImpl::SetDefaultBrowserContext(
+ HeadlessBrowserContext* browser_context) {
+ DCHECK(!browser_context ||
+ this == HeadlessBrowserContextImpl::From(browser_context)->browser());
+ default_browser_context_ = browser_context;
+}
+
+HeadlessBrowserContext* HeadlessBrowserImpl::GetDefaultBrowserContext() {
+ return default_browser_context_;
}
base::WeakPtr<HeadlessBrowserImpl> HeadlessBrowserImpl::GetWeakPtr() {
diff --git a/chromium/headless/lib/browser/headless_browser_impl.h b/chromium/headless/lib/browser/headless_browser_impl.h
index 74a4b6c29cf..f37dff1dbc4 100644
--- a/chromium/headless/lib/browser/headless_browser_impl.h
+++ b/chromium/headless/lib/browser/headless_browser_impl.h
@@ -51,6 +51,9 @@ class HeadlessBrowserImpl : public HeadlessBrowser {
const std::string& devtools_agent_host_id) override;
HeadlessBrowserContext* GetBrowserContextForId(
const std::string& id) override;
+ void SetDefaultBrowserContext(
+ HeadlessBrowserContext* browser_context) override;
+ HeadlessBrowserContext* GetDefaultBrowserContext() override;
void set_browser_main_parts(HeadlessBrowserMainParts* browser_main_parts);
HeadlessBrowserMainParts* browser_main_parts() const;
@@ -82,6 +85,7 @@ class HeadlessBrowserImpl : public HeadlessBrowser {
std::unordered_map<std::string, std::unique_ptr<HeadlessBrowserContextImpl>>
browser_contexts_;
+ HeadlessBrowserContext* default_browser_context_; // Not owned.
base::WeakPtrFactory<HeadlessBrowserImpl> weak_ptr_factory_;
diff --git a/chromium/headless/lib/browser/headless_browser_main_parts.h b/chromium/headless/lib/browser/headless_browser_main_parts.h
index 97bc9e9e912..e29b92abed3 100644
--- a/chromium/headless/lib/browser/headless_browser_main_parts.h
+++ b/chromium/headless/lib/browser/headless_browser_main_parts.h
@@ -12,7 +12,6 @@
namespace headless {
-class HeadlessBrowserContextImpl;
class HeadlessBrowserImpl;
class HeadlessBrowserMainParts : public content::BrowserMainParts {
diff --git a/chromium/headless/lib/browser/headless_content_browser_client.cc b/chromium/headless/lib/browser/headless_content_browser_client.cc
index 1bfe88ff8cb..8ba656c082c 100644
--- a/chromium/headless/lib/browser/headless_content_browser_client.cc
+++ b/chromium/headless/lib/browser/headless_content_browser_client.cc
@@ -61,7 +61,7 @@ HeadlessContentBrowserClient::GetDevToolsManagerDelegate() {
std::unique_ptr<base::Value>
HeadlessContentBrowserClient::GetServiceManifestOverlay(
- const std::string& name) {
+ base::StringPiece name) {
if (name != content::mojom::kBrowserServiceName ||
browser_->options()->mojo_service_names.empty())
return nullptr;
diff --git a/chromium/headless/lib/browser/headless_content_browser_client.h b/chromium/headless/lib/browser/headless_content_browser_client.h
index 8e9651e9d21..3f443819867 100644
--- a/chromium/headless/lib/browser/headless_content_browser_client.h
+++ b/chromium/headless/lib/browser/headless_content_browser_client.h
@@ -10,8 +10,6 @@
namespace headless {
class HeadlessBrowserImpl;
-class HeadlessBrowserMainParts;
-class HeadlessDevToolsManagerDelegate;
class HeadlessContentBrowserClient : public content::ContentBrowserClient {
public:
@@ -25,7 +23,7 @@ class HeadlessContentBrowserClient : public content::ContentBrowserClient {
content::WebPreferences* prefs) override;
content::DevToolsManagerDelegate* GetDevToolsManagerDelegate() override;
std::unique_ptr<base::Value> GetServiceManifestOverlay(
- const std::string& name) override;
+ base::StringPiece name) override;
private:
HeadlessBrowserImpl* browser_; // Not owned.
diff --git a/chromium/headless/lib/browser/headless_devtools_client_impl.cc b/chromium/headless/lib/browser/headless_devtools_client_impl.cc
index 833b9dc49af..b6e2905a405 100644
--- a/chromium/headless/lib/browser/headless_devtools_client_impl.cc
+++ b/chromium/headless/lib/browser/headless_devtools_client_impl.cc
@@ -32,6 +32,7 @@ HeadlessDevToolsClientImpl* HeadlessDevToolsClientImpl::From(
HeadlessDevToolsClientImpl::HeadlessDevToolsClientImpl()
: agent_host_(nullptr),
next_message_id_(0),
+ renderer_crashed_(false),
accessibility_domain_(this),
animation_domain_(this),
application_cache_domain_(this),
@@ -68,17 +69,28 @@ HeadlessDevToolsClientImpl::HeadlessDevToolsClientImpl()
HeadlessDevToolsClientImpl::~HeadlessDevToolsClientImpl() {}
-void HeadlessDevToolsClientImpl::AttachToHost(
+bool HeadlessDevToolsClientImpl::AttachToHost(
+ content::DevToolsAgentHost* agent_host) {
+ DCHECK(!agent_host_);
+ if (agent_host->AttachClient(this)) {
+ agent_host_ = agent_host;
+ return true;
+ }
+ return false;
+}
+
+void HeadlessDevToolsClientImpl::ForceAttachToHost(
content::DevToolsAgentHost* agent_host) {
DCHECK(!agent_host_);
agent_host_ = agent_host;
- agent_host_->AttachClient(this);
+ agent_host_->ForceAttachClient(this);
}
void HeadlessDevToolsClientImpl::DetachFromHost(
content::DevToolsAgentHost* agent_host) {
DCHECK_EQ(agent_host_, agent_host);
- agent_host_->DetachClient(this);
+ if (!renderer_crashed_)
+ agent_host_->DetachClient(this);
agent_host_ = nullptr;
pending_messages_.clear();
}
@@ -114,11 +126,16 @@ bool HeadlessDevToolsClientImpl::DispatchMessageReply(
pending_messages_.erase(it);
if (!callback.callback_with_result.is_null()) {
const base::DictionaryValue* result_dict;
- if (!message_dict.GetDictionary("result", &result_dict)) {
- NOTREACHED() << "Badly formed reply result";
+ if (message_dict.GetDictionary("result", &result_dict)) {
+ callback.callback_with_result.Run(*result_dict);
+ } else if (message_dict.GetDictionary("error", &result_dict)) {
+ std::unique_ptr<base::Value> null_value = base::Value::CreateNullValue();
+ DLOG(ERROR) << "Error in method call result: " << *result_dict;
+ callback.callback_with_result.Run(*null_value);
+ } else {
+ NOTREACHED() << "Reply has neither result nor error";
return false;
}
- callback.callback_with_result.Run(*result_dict);
} else if (!callback.callback.is_null()) {
callback.callback.Run();
}
@@ -131,6 +148,8 @@ bool HeadlessDevToolsClientImpl::DispatchEvent(
std::string method;
if (!message_dict.GetString("method", &method))
return false;
+ if (method == "Inspector.targetCrashed")
+ renderer_crashed_ = true;
EventHandlerMap::const_iterator it = event_handlers_.find(method);
if (it == event_handlers_.end()) {
NOTREACHED() << "Unknown event: " << method;
@@ -292,6 +311,8 @@ template <typename CallbackType>
void HeadlessDevToolsClientImpl::FinalizeAndSendMessage(
base::DictionaryValue* message,
CallbackType callback) {
+ if (renderer_crashed_)
+ return;
DCHECK(agent_host_);
int id = next_message_id_++;
message->SetInteger("id", id);
diff --git a/chromium/headless/lib/browser/headless_devtools_client_impl.h b/chromium/headless/lib/browser/headless_devtools_client_impl.h
index 3ee800b13e8..a9e270a4b4f 100644
--- a/chromium/headless/lib/browser/headless_devtools_client_impl.h
+++ b/chromium/headless/lib/browser/headless_devtools_client_impl.h
@@ -115,7 +115,8 @@ class HeadlessDevToolsClientImpl : public HeadlessDevToolsClient,
const char* method,
base::Callback<void(const base::Value&)> callback) override;
- void AttachToHost(content::DevToolsAgentHost* agent_host);
+ bool AttachToHost(content::DevToolsAgentHost* agent_host);
+ void ForceAttachToHost(content::DevToolsAgentHost* agent_host);
void DetachFromHost(content::DevToolsAgentHost* agent_host);
private:
@@ -163,6 +164,8 @@ class HeadlessDevToolsClientImpl : public HeadlessDevToolsClient,
EventHandlerMap event_handlers_;
+ bool renderer_crashed_;
+
accessibility::ExperimentalDomain accessibility_domain_;
animation::ExperimentalDomain animation_domain_;
application_cache::ExperimentalDomain application_cache_domain_;
diff --git a/chromium/headless/lib/browser/headless_devtools_manager_delegate.cc b/chromium/headless/lib/browser/headless_devtools_manager_delegate.cc
index 0c82f334ab8..0842569beb3 100644
--- a/chromium/headless/lib/browser/headless_devtools_manager_delegate.cc
+++ b/chromium/headless/lib/browser/headless_devtools_manager_delegate.cc
@@ -20,9 +20,57 @@
namespace headless {
+namespace {
+const char kIdParam[] = "id";
+const char kResultParam[] = "result";
+const char kErrorParam[] = "error";
+const char kErrorCodeParam[] = "code";
+const char kErrorMessageParam[] = "message";
+
+// JSON RPC 2.0 spec: http://www.jsonrpc.org/specification#error_object
+enum Error {
+ kErrorInvalidParam = -32602,
+ kErrorServerError = -32000
+};
+
+std::unique_ptr<base::DictionaryValue> CreateSuccessResponse(
+ int command_id,
+ std::unique_ptr<base::Value> result) {
+ if (!result)
+ result.reset(new base::DictionaryValue());
+
+ std::unique_ptr<base::DictionaryValue> response(new base::DictionaryValue());
+ response->SetInteger(kIdParam, command_id);
+ response->Set(kResultParam, std::move(result));
+ return response;
+}
+
+std::unique_ptr<base::DictionaryValue> CreateErrorResponse(
+ int command_id,
+ int error_code,
+ const std::string& error_message) {
+ std::unique_ptr<base::DictionaryValue> error_object(
+ new base::DictionaryValue());
+ error_object->SetInteger(kErrorCodeParam, error_code);
+ error_object->SetString(kErrorMessageParam, error_message);
+
+ std::unique_ptr<base::DictionaryValue> response(new base::DictionaryValue());
+ response->Set(kErrorParam, std::move(error_object));
+ return response;
+}
+
+std::unique_ptr<base::DictionaryValue> CreateInvalidParamResponse(
+ int command_id,
+ const std::string& param) {
+ return CreateErrorResponse(
+ command_id, kErrorInvalidParam,
+ base::StringPrintf("Missing or invalid '%s' parameter", param.c_str()));
+}
+} // namespace
+
HeadlessDevToolsManagerDelegate::HeadlessDevToolsManagerDelegate(
base::WeakPtr<HeadlessBrowserImpl> browser)
- : browser_(std::move(browser)), default_browser_context_(nullptr) {
+ : browser_(std::move(browser)) {
command_map_["Target.createTarget"] =
&HeadlessDevToolsManagerDelegate::CreateTarget;
command_map_["Target.closeTarget"] =
@@ -45,29 +93,25 @@ base::DictionaryValue* HeadlessDevToolsManagerDelegate::HandleCommand(
int id;
std::string method;
- const base::DictionaryValue* params = nullptr;
if (!command->GetInteger("id", &id) ||
- !command->GetString("method", &method) ||
- !command->GetDictionary("params", &params)) {
+ !command->GetString("method", &method)) {
return nullptr;
}
auto find_it = command_map_.find(method);
if (find_it == command_map_.end())
return nullptr;
CommandMemberFnPtr command_fn_ptr = find_it->second;
- std::unique_ptr<base::Value> cmd_result(((this)->*command_fn_ptr)(params));
- if (!cmd_result)
- return nullptr;
-
- std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
- result->SetInteger("id", id);
- result->Set("result", std::move(cmd_result));
- return result.release();
+ const base::DictionaryValue* params = nullptr;
+ command->GetDictionary("params", &params);
+ std::unique_ptr<base::DictionaryValue> cmd_result(
+ ((this)->*command_fn_ptr)(id, params));
+ return cmd_result.release();
}
std::string HeadlessDevToolsManagerDelegate::GetDiscoveryPageHTML() {
- return ResourceBundle::GetSharedInstance().GetRawDataResource(
- IDR_HEADLESS_LIB_DEVTOOLS_DISCOVERY_PAGE).as_string();
+ return ResourceBundle::GetSharedInstance()
+ .GetRawDataResource(IDR_HEADLESS_LIB_DEVTOOLS_DISCOVERY_PAGE)
+ .as_string();
}
std::string HeadlessDevToolsManagerDelegate::GetFrontendResource(
@@ -75,26 +119,34 @@ std::string HeadlessDevToolsManagerDelegate::GetFrontendResource(
return content::DevToolsFrontendHost::GetFrontendResource(path).as_string();
}
-std::unique_ptr<base::Value> HeadlessDevToolsManagerDelegate::CreateTarget(
+std::unique_ptr<base::DictionaryValue>
+HeadlessDevToolsManagerDelegate::CreateTarget(
+ int command_id,
const base::DictionaryValue* params) {
std::string url;
std::string browser_context_id;
int width = browser_->options()->window_size.width();
int height = browser_->options()->window_size.height();
- params->GetString("url", &url);
+ if (!params || !params->GetString("url", &url))
+ return CreateInvalidParamResponse(command_id, "url");
params->GetString("browserContextId", &browser_context_id);
params->GetInteger("width", &width);
params->GetInteger("height", &height);
- // TODO(alexclarke): Should we fail when user passes incorrect id?
HeadlessBrowserContext* context =
browser_->GetBrowserContextForId(browser_context_id);
- if (!context) {
- if (!default_browser_context_) {
- default_browser_context_ =
- browser_->CreateBrowserContextBuilder().Build();
+ if (!browser_context_id.empty()) {
+ context = browser_->GetBrowserContextForId(browser_context_id);
+ if (!context)
+ return CreateInvalidParamResponse(command_id, "browserContextId");
+ } else {
+ context = browser_->GetDefaultBrowserContext();
+ if (!context) {
+ return CreateErrorResponse(command_id, kErrorServerError,
+ "You specified no |browserContextId|, but "
+ "there is no default browser context set on "
+ "HeadlessBrowser");
}
- context = default_browser_context_;
}
HeadlessWebContentsImpl* web_contents_impl =
@@ -103,18 +155,21 @@ std::unique_ptr<base::Value> HeadlessDevToolsManagerDelegate::CreateTarget(
.SetWindowSize(gfx::Size(width, height))
.Build());
- return target::CreateTargetResult::Builder()
- .SetTargetId(web_contents_impl->GetDevToolsAgentHostId())
- .Build()
- ->Serialize();
+ std::unique_ptr<base::Value> result(
+ target::CreateTargetResult::Builder()
+ .SetTargetId(web_contents_impl->GetDevToolsAgentHostId())
+ .Build()
+ ->Serialize());
+ return CreateSuccessResponse(command_id, std::move(result));
}
-std::unique_ptr<base::Value> HeadlessDevToolsManagerDelegate::CloseTarget(
+std::unique_ptr<base::DictionaryValue>
+HeadlessDevToolsManagerDelegate::CloseTarget(
+ int command_id,
const base::DictionaryValue* params) {
std::string target_id;
- if (!params->GetString("targetId", &target_id)) {
- return nullptr;
- }
+ if (!params || !params->GetString("targetId", &target_id))
+ return CreateInvalidParamResponse(command_id, "targetId");
HeadlessWebContents* web_contents =
browser_->GetWebContentsForDevToolsAgentHostId(target_id);
bool success = false;
@@ -122,46 +177,51 @@ std::unique_ptr<base::Value> HeadlessDevToolsManagerDelegate::CloseTarget(
web_contents->Close();
success = true;
}
- return target::CloseTargetResult::Builder()
- .SetSuccess(success)
- .Build()
- ->Serialize();
+ std::unique_ptr<base::Value> result(target::CloseTargetResult::Builder()
+ .SetSuccess(success)
+ .Build()
+ ->Serialize());
+ return CreateSuccessResponse(command_id, std::move(result));
}
-std::unique_ptr<base::Value>
+std::unique_ptr<base::DictionaryValue>
HeadlessDevToolsManagerDelegate::CreateBrowserContext(
+ int command_id,
const base::DictionaryValue* params) {
HeadlessBrowserContext* browser_context =
browser_->CreateBrowserContextBuilder().Build();
- std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
- return target::CreateBrowserContextResult::Builder()
- .SetBrowserContextId(browser_context->Id())
- .Build()
- ->Serialize();
+ std::unique_ptr<base::Value> result(
+ target::CreateBrowserContextResult::Builder()
+ .SetBrowserContextId(browser_context->Id())
+ .Build()
+ ->Serialize());
+ return CreateSuccessResponse(command_id, std::move(result));
}
-std::unique_ptr<base::Value>
+std::unique_ptr<base::DictionaryValue>
HeadlessDevToolsManagerDelegate::DisposeBrowserContext(
+ int command_id,
const base::DictionaryValue* params) {
std::string browser_context_id;
- if (!params->GetString("browserContextId", &browser_context_id)) {
- return nullptr;
- }
+ if (!params || !params->GetString("browserContextId", &browser_context_id))
+ return CreateInvalidParamResponse(command_id, "browserContextId");
HeadlessBrowserContext* context =
browser_->GetBrowserContextForId(browser_context_id);
bool success = false;
- if (context && context != default_browser_context_ &&
+ if (context && context != browser_->GetDefaultBrowserContext() &&
context->GetAllWebContents().empty()) {
success = true;
context->Close();
}
- return target::DisposeBrowserContextResult::Builder()
- .SetSuccess(success)
- .Build()
- ->Serialize();
+ std::unique_ptr<base::Value> result(
+ target::DisposeBrowserContextResult::Builder()
+ .SetSuccess(success)
+ .Build()
+ ->Serialize());
+ return CreateSuccessResponse(command_id, std::move(result));
}
} // namespace headless
diff --git a/chromium/headless/lib/browser/headless_devtools_manager_delegate.h b/chromium/headless/lib/browser/headless_devtools_manager_delegate.h
index 4d43fc76b79..c891e8246c6 100644
--- a/chromium/headless/lib/browser/headless_devtools_manager_delegate.h
+++ b/chromium/headless/lib/browser/headless_devtools_manager_delegate.h
@@ -16,8 +16,6 @@
namespace headless {
class HeadlessBrowserImpl;
-class HeadlessBrowserContext;
-class HeadlessWebContentsImpl;
class HeadlessDevToolsManagerDelegate
: public content::DevToolsManagerDelegate {
@@ -33,22 +31,26 @@ class HeadlessDevToolsManagerDelegate
std::string GetFrontendResource(const std::string& path) override;
private:
- std::unique_ptr<base::Value> CreateTarget(
+ std::unique_ptr<base::DictionaryValue> CreateTarget(
+ int command_id,
const base::DictionaryValue* params);
- std::unique_ptr<base::Value> CloseTarget(const base::DictionaryValue* params);
- std::unique_ptr<base::Value> CreateBrowserContext(
+ std::unique_ptr<base::DictionaryValue> CloseTarget(
+ int command_id,
const base::DictionaryValue* params);
- std::unique_ptr<base::Value> DisposeBrowserContext(
+ std::unique_ptr<base::DictionaryValue> CreateBrowserContext(
+ int command_id,
+ const base::DictionaryValue* params);
+ std::unique_ptr<base::DictionaryValue> DisposeBrowserContext(
+ int command_id,
const base::DictionaryValue* params);
base::WeakPtr<HeadlessBrowserImpl> browser_;
- using CommandMemberFnPtr = std::unique_ptr<base::Value> (
- HeadlessDevToolsManagerDelegate::*)(const base::DictionaryValue* params);
+ using CommandMemberFnPtr = std::unique_ptr<base::DictionaryValue> (
+ HeadlessDevToolsManagerDelegate::*)(int command_id,
+ const base::DictionaryValue* params);
std::map<std::string, CommandMemberFnPtr> command_map_;
-
- HeadlessBrowserContext* default_browser_context_;
};
} // namespace headless
diff --git a/chromium/headless/lib/browser/headless_platform_event_source.cc b/chromium/headless/lib/browser/headless_platform_event_source.cc
new file mode 100644
index 00000000000..7c3100ee4f2
--- /dev/null
+++ b/chromium/headless/lib/browser/headless_platform_event_source.cc
@@ -0,0 +1,13 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "headless/lib/browser/headless_platform_event_source.h"
+
+namespace headless {
+
+HeadlessPlatformEventSource::HeadlessPlatformEventSource() {}
+
+HeadlessPlatformEventSource::~HeadlessPlatformEventSource() {}
+
+} // namespace headless
diff --git a/chromium/headless/lib/browser/headless_platform_event_source.h b/chromium/headless/lib/browser/headless_platform_event_source.h
new file mode 100644
index 00000000000..ccd74632567
--- /dev/null
+++ b/chromium/headless/lib/browser/headless_platform_event_source.h
@@ -0,0 +1,26 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef HEADLESS_LIB_BROWSER_HEADLESS_PLATFORM_EVENT_SOURCE_H_
+#define HEADLESS_LIB_BROWSER_HEADLESS_PLATFORM_EVENT_SOURCE_H_
+
+#include "base/macros.h"
+#include "ui/events/platform/platform_event_source.h"
+
+namespace headless {
+
+// A stub event source whose main purpose is to prevent the default platform
+// event source from getting created.
+class HeadlessPlatformEventSource : public ui::PlatformEventSource {
+ public:
+ HeadlessPlatformEventSource();
+ ~HeadlessPlatformEventSource() override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HeadlessPlatformEventSource);
+};
+
+} // namespace headless
+
+#endif // HEADLESS_LIB_BROWSER_HEADLESS_PLATFORM_EVENT_SOURCE_H_
diff --git a/chromium/headless/lib/browser/headless_screen.cc b/chromium/headless/lib/browser/headless_screen.cc
index be86924d2e3..9cc1e4745a5 100644
--- a/chromium/headless/lib/browser/headless_screen.cc
+++ b/chromium/headless/lib/browser/headless_screen.cc
@@ -43,6 +43,7 @@ aura::WindowTreeHost* HeadlessScreen::CreateHostForPrimaryDisplay() {
host_->GetInputMethod()->OnFocus();
host_->window()->AddObserver(this);
host_->InitHost();
+ host_->window()->Show();
return host_;
}
diff --git a/chromium/headless/lib/browser/headless_screen.h b/chromium/headless/lib/browser/headless_screen.h
index ed9e388f079..8c5cb98c083 100644
--- a/chromium/headless/lib/browser/headless_screen.h
+++ b/chromium/headless/lib/browser/headless_screen.h
@@ -19,7 +19,6 @@ class Transform;
namespace aura {
class Window;
-class WindowParentingClient;
class WindowTreeHost;
}
diff --git a/chromium/headless/lib/browser/headless_url_request_context_getter.cc b/chromium/headless/lib/browser/headless_url_request_context_getter.cc
index 04a04d5c25a..0bb623df377 100644
--- a/chromium/headless/lib/browser/headless_url_request_context_getter.cc
+++ b/chromium/headless/lib/browser/headless_url_request_context_getter.cc
@@ -88,14 +88,7 @@ HeadlessURLRequestContextGetter::GetURLRequestContext() {
base::WrapUnique(pair.second.release()));
}
protocol_handlers_.clear();
-
- std::vector<std::unique_ptr<net::URLRequestInterceptor>>
- request_interceptors;
- for (auto it : request_interceptors_) {
- request_interceptors.push_back(base::WrapUnique(it));
- }
- request_interceptors_.weak_clear();
- builder.SetInterceptors(std::move(request_interceptors));
+ builder.SetInterceptors(std::move(request_interceptors_));
url_request_context_ = builder.Build();
}
diff --git a/chromium/headless/lib/browser/headless_url_request_context_getter.h b/chromium/headless/lib/browser/headless_url_request_context_getter.h
index 166f6a9cbe6..e1bee1ea43f 100644
--- a/chromium/headless/lib/browser/headless_url_request_context_getter.h
+++ b/chromium/headless/lib/browser/headless_url_request_context_getter.h
@@ -19,18 +19,9 @@
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_job_factory.h"
-namespace base {
-class MessageLoop;
-}
-
namespace net {
class HostResolver;
-class MappedHostResolver;
-class NetworkDelegate;
-class NetLog;
class ProxyConfigService;
-class ProxyService;
-class URLRequestContextStorage;
}
namespace headless {
diff --git a/chromium/headless/lib/browser/headless_web_contents_impl.cc b/chromium/headless/lib/browser/headless_web_contents_impl.cc
index dfdf31b30db..1516d964ff3 100644
--- a/chromium/headless/lib/browser/headless_web_contents_impl.cc
+++ b/chromium/headless/lib/browser/headless_web_contents_impl.cc
@@ -26,7 +26,6 @@
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/origin_util.h"
-#include "content/public/renderer/render_frame.h"
#include "headless/lib/browser/headless_browser_context_impl.h"
#include "headless/lib/browser/headless_browser_impl.h"
#include "headless/lib/browser/headless_browser_main_parts.h"
@@ -57,6 +56,8 @@ class WebContentsObserverAdapter : public content::WebContentsObserver {
observer_->DevToolsTargetReady();
}
+ HeadlessWebContents::Observer* observer() { return observer_; }
+
private:
HeadlessWebContents::Observer* observer_; // Not owned.
@@ -157,12 +158,16 @@ HeadlessWebContentsImpl::HeadlessWebContentsImpl(
new HeadlessWebContentsImpl::Delegate(browser_context)),
web_contents_(web_contents),
agent_host_(content::DevToolsAgentHost::GetOrCreateFor(web_contents)),
- browser_context_(browser_context) {
+ browser_context_(browser_context),
+ render_process_host_(web_contents->GetRenderProcessHost()) {
web_contents_->SetDelegate(web_contents_delegate_.get());
+ render_process_host_->AddObserver(this);
}
HeadlessWebContentsImpl::~HeadlessWebContentsImpl() {
web_contents_->Close();
+ if (render_process_host_)
+ render_process_host_->RemoveObserver(this);
}
void HeadlessWebContentsImpl::RenderFrameCreated(
@@ -214,12 +219,35 @@ void HeadlessWebContentsImpl::RemoveObserver(Observer* observer) {
observer_map_.erase(it);
}
+void HeadlessWebContentsImpl::RenderProcessExited(
+ content::RenderProcessHost* host,
+ base::TerminationStatus status,
+ int exit_code) {
+ DCHECK_EQ(render_process_host_, host);
+ for (const auto& pair : observer_map_) {
+ pair.second->observer()->RenderProcessExited(status, exit_code);
+ }
+}
+
+void HeadlessWebContentsImpl::RenderProcessHostDestroyed(
+ content::RenderProcessHost* host) {
+ DCHECK_EQ(render_process_host_, host);
+ render_process_host_ = nullptr;
+}
+
HeadlessDevToolsTarget* HeadlessWebContentsImpl::GetDevToolsTarget() {
return web_contents()->GetMainFrame()->IsRenderFrameLive() ? this : nullptr;
}
-void HeadlessWebContentsImpl::AttachClient(HeadlessDevToolsClient* client) {
- HeadlessDevToolsClientImpl::From(client)->AttachToHost(agent_host_.get());
+bool HeadlessWebContentsImpl::AttachClient(HeadlessDevToolsClient* client) {
+ return HeadlessDevToolsClientImpl::From(client)->AttachToHost(
+ agent_host_.get());
+}
+
+void HeadlessWebContentsImpl::ForceAttachClient(
+ HeadlessDevToolsClient* client) {
+ HeadlessDevToolsClientImpl::From(client)->ForceAttachToHost(
+ agent_host_.get());
}
void HeadlessWebContentsImpl::DetachClient(HeadlessDevToolsClient* client) {
@@ -227,6 +255,11 @@ void HeadlessWebContentsImpl::DetachClient(HeadlessDevToolsClient* client) {
HeadlessDevToolsClientImpl::From(client)->DetachFromHost(agent_host_.get());
}
+bool HeadlessWebContentsImpl::IsAttached() {
+ DCHECK(agent_host_);
+ return agent_host_->IsAttached();
+}
+
content::WebContents* HeadlessWebContentsImpl::web_contents() const {
return web_contents_.get();
}
diff --git a/chromium/headless/lib/browser/headless_web_contents_impl.h b/chromium/headless/lib/browser/headless_web_contents_impl.h
index 43293847b35..a18a46aa49d 100644
--- a/chromium/headless/lib/browser/headless_web_contents_impl.h
+++ b/chromium/headless/lib/browser/headless_web_contents_impl.h
@@ -10,6 +10,7 @@
#include <string>
#include <unordered_map>
+#include "content/public/browser/render_process_host_observer.h"
#include "content/public/browser/web_contents_observer.h"
#include "headless/public/headless_devtools_target.h"
#include "headless/public/headless_web_contents.h"
@@ -19,7 +20,6 @@ class Window;
}
namespace content {
-class BrowserContext;
class DevToolsAgentHost;
class WebContents;
}
@@ -29,12 +29,12 @@ class Size;
}
namespace headless {
-class HeadlessDevToolsHostImpl;
class HeadlessBrowserImpl;
class WebContentsObserverAdapter;
class HeadlessWebContentsImpl : public HeadlessWebContents,
public HeadlessDevToolsTarget,
+ public content::RenderProcessHostObserver,
public content::WebContentsObserver {
public:
~HeadlessWebContentsImpl() override;
@@ -56,8 +56,16 @@ class HeadlessWebContentsImpl : public HeadlessWebContents,
HeadlessDevToolsTarget* GetDevToolsTarget() override;
// HeadlessDevToolsTarget implementation:
- void AttachClient(HeadlessDevToolsClient* client) override;
+ bool AttachClient(HeadlessDevToolsClient* client) override;
+ void ForceAttachClient(HeadlessDevToolsClient* client) override;
void DetachClient(HeadlessDevToolsClient* client) override;
+ bool IsAttached() override;
+
+ // RenderProcessHostObserver implementation:
+ void RenderProcessExited(content::RenderProcessHost* host,
+ base::TerminationStatus status,
+ int exit_code) override;
+ void RenderProcessHostDestroyed(content::RenderProcessHost* host) override;
// content::WebContentsObserver implementation:
void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
@@ -88,7 +96,8 @@ class HeadlessWebContentsImpl : public HeadlessWebContents,
scoped_refptr<content::DevToolsAgentHost> agent_host_;
std::list<MojoService> mojo_services_;
- HeadlessBrowserContextImpl* browser_context_; // Not owned.
+ HeadlessBrowserContextImpl* browser_context_; // Not owned.
+ content::RenderProcessHost* render_process_host_; // Not owned.
using ObserverMap =
std::unordered_map<HeadlessWebContents::Observer*,
diff --git a/chromium/headless/lib/browser/headless_window_tree_host.cc b/chromium/headless/lib/browser/headless_window_tree_host.cc
new file mode 100644
index 00000000000..96cec1a96e6
--- /dev/null
+++ b/chromium/headless/lib/browser/headless_window_tree_host.cc
@@ -0,0 +1,75 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "headless/lib/browser/headless_window_tree_host.h"
+
+#include "ui/gfx/icc_profile.h"
+
+namespace headless {
+
+HeadlessWindowTreeHost::HeadlessWindowTreeHost(const gfx::Rect& bounds)
+ : bounds_(bounds) {
+ CreateCompositor();
+ OnAcceleratedWidgetAvailable();
+}
+
+HeadlessWindowTreeHost::~HeadlessWindowTreeHost() {
+ DestroyCompositor();
+ DestroyDispatcher();
+}
+
+bool HeadlessWindowTreeHost::CanDispatchEvent(const ui::PlatformEvent& event) {
+ return false;
+}
+
+uint32_t HeadlessWindowTreeHost::DispatchEvent(const ui::PlatformEvent& event) {
+ return 0;
+}
+
+ui::EventSource* HeadlessWindowTreeHost::GetEventSource() {
+ return this;
+}
+
+gfx::AcceleratedWidget HeadlessWindowTreeHost::GetAcceleratedWidget() {
+ return gfx::AcceleratedWidget();
+}
+
+gfx::Rect HeadlessWindowTreeHost::GetBoundsInPixels() const {
+ return bounds_;
+}
+
+void HeadlessWindowTreeHost::SetBoundsInPixels(const gfx::Rect& bounds) {
+ bool origin_changed = bounds_.origin() != bounds.origin();
+ bool size_changed = bounds_.size() != bounds.size();
+ bounds_ = bounds;
+ if (origin_changed)
+ OnHostMovedInPixels(bounds.origin());
+ if (size_changed)
+ OnHostResizedInPixels(bounds.size());
+}
+
+void HeadlessWindowTreeHost::ShowImpl() {}
+
+void HeadlessWindowTreeHost::HideImpl() {}
+
+gfx::Point HeadlessWindowTreeHost::GetLocationOnScreenInPixels() const {
+ return gfx::Point();
+}
+
+void HeadlessWindowTreeHost::SetCapture() {}
+
+void HeadlessWindowTreeHost::ReleaseCapture() {}
+
+void HeadlessWindowTreeHost::SetCursorNative(gfx::NativeCursor cursor_type) {}
+
+void HeadlessWindowTreeHost::MoveCursorToScreenLocationInPixels(
+ const gfx::Point& location) {}
+
+void HeadlessWindowTreeHost::OnCursorVisibilityChangedNative(bool show) {}
+
+gfx::ICCProfile HeadlessWindowTreeHost::GetICCProfileForCurrentDisplay() {
+ return gfx::ICCProfile();
+}
+
+} // namespace headless
diff --git a/chromium/headless/lib/browser/headless_window_tree_host.h b/chromium/headless/lib/browser/headless_window_tree_host.h
new file mode 100644
index 00000000000..c01545c9c35
--- /dev/null
+++ b/chromium/headless/lib/browser/headless_window_tree_host.h
@@ -0,0 +1,48 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef HEADLESS_LIB_BROWSER_HEADLESS_WINDOW_TREE_HOST_H_
+#define HEADLESS_LIB_BROWSER_HEADLESS_WINDOW_TREE_HOST_H_
+
+#include "base/macros.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/events/platform/platform_event_dispatcher.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace headless {
+
+class HeadlessWindowTreeHost : public aura::WindowTreeHost,
+ public ui::PlatformEventDispatcher {
+ public:
+ explicit HeadlessWindowTreeHost(const gfx::Rect& bounds);
+ ~HeadlessWindowTreeHost() override;
+
+ // ui::PlatformEventDispatcher:
+ bool CanDispatchEvent(const ui::PlatformEvent& event) override;
+ uint32_t DispatchEvent(const ui::PlatformEvent& event) override;
+
+ // WindowTreeHost:
+ ui::EventSource* GetEventSource() override;
+ gfx::AcceleratedWidget GetAcceleratedWidget() override;
+ void ShowImpl() override;
+ void HideImpl() override;
+ gfx::Rect GetBoundsInPixels() const override;
+ void SetBoundsInPixels(const gfx::Rect& bounds) override;
+ gfx::Point GetLocationOnScreenInPixels() const override;
+ void SetCapture() override;
+ void ReleaseCapture() override;
+ void SetCursorNative(gfx::NativeCursor cursor_type) override;
+ void MoveCursorToScreenLocationInPixels(const gfx::Point& location) override;
+ void OnCursorVisibilityChangedNative(bool show) override;
+ gfx::ICCProfile GetICCProfileForCurrentDisplay() override;
+
+ private:
+ gfx::Rect bounds_;
+
+ DISALLOW_COPY_AND_ASSIGN(HeadlessWindowTreeHost);
+};
+
+} // namespace headless
+
+#endif // HEADLESS_LIB_BROWSER_HEADLESS_WINDOW_TREE_HOST_H_
diff --git a/chromium/headless/lib/embedder_mojo_browsertest.cc b/chromium/headless/lib/embedder_mojo_browsertest.cc
index 3fb4ed1a5f5..92800f1acc3 100644
--- a/chromium/headless/lib/embedder_mojo_browsertest.cc
+++ b/chromium/headless/lib/embedder_mojo_browsertest.cc
@@ -152,16 +152,12 @@ class MojoBindingsTest : public EmbedderMojoTest {
"// fires after the requested modules have been loaded. \n"
"define([ \n"
" 'headless/lib/embedder_test.mojom', \n"
- " 'mojo/public/js/core', \n"
- " 'mojo/public/js/router', \n"
" 'content/public/renderer/frame_interfaces', \n"
- " ], function(embedderMojom, mojoCore, routerModule, \n"
- " frameInterfaces) { \n"
+ " ], function(embedderMojom, frameInterfaces) { \n"
" var testEmbedderService = \n"
- " new embedderMojom.TestEmbedderService.proxyClass( \n"
- " new routerModule.Router( \n"
- " frameInterfaces.getInterface( \n"
- " embedderMojom.TestEmbedderService.name))); \n"
+ " new embedderMojom.TestEmbedderServicePtr( \n"
+ " frameInterfaces.getInterface( \n"
+ " embedderMojom.TestEmbedderService.name)); \n"
" \n"
" // Send a message to the embedder! \n"
" testEmbedderService.returnTestResult('hello world'); \n"
@@ -238,7 +234,7 @@ class HttpDisabledByDefaultWhenMojoBindingsUsed : public EmbedderMojoTest,
}
void ReturnTestResult(const std::string& result) override {
- FinishAsynchronousTest();
+ DisableClientAndFinishAsynchronousTest();
FAIL() << "The HTTP page should not have been served and we should not have"
" recieved a mojo callback!";
}
@@ -246,6 +242,12 @@ class HttpDisabledByDefaultWhenMojoBindingsUsed : public EmbedderMojoTest,
void OnLoadingFailed(const network::LoadingFailedParams& params) override {
// The navigation should fail since HTTP requests are blackholed.
EXPECT_EQ(params.GetErrorText(), "net::ERR_FILE_NOT_FOUND");
+ DisableClientAndFinishAsynchronousTest();
+ }
+
+ void DisableClientAndFinishAsynchronousTest() {
+ devtools_client_->GetNetwork()->Disable();
+ devtools_client_->GetNetwork()->RemoveObserver(this);
FinishAsynchronousTest();
}
};
diff --git a/chromium/headless/lib/headless_content_main_delegate.cc b/chromium/headless/lib/headless_content_main_delegate.cc
index 193169ff8a0..4b7c1609035 100644
--- a/chromium/headless/lib/headless_content_main_delegate.cc
+++ b/chromium/headless/lib/headless_content_main_delegate.cc
@@ -5,6 +5,7 @@
#include "headless/lib/headless_content_main_delegate.h"
#include "base/command_line.h"
+#include "base/files/file_util.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/trace_event/trace_event.h"
@@ -12,9 +13,9 @@
#include "content/public/common/content_switches.h"
#include "headless/lib/browser/headless_browser_impl.h"
#include "headless/lib/browser/headless_content_browser_client.h"
-#include "headless/lib/renderer/headless_content_renderer_client.h"
-#include "headless/lib/utility/headless_content_utility_client.h"
#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/ui_base_switches.h"
+#include "ui/gfx/switches.h"
#include "ui/gl/gl_switches.h"
#include "ui/ozone/public/ozone_switches.h"
@@ -42,15 +43,21 @@ HeadlessContentMainDelegate::~HeadlessContentMainDelegate() {
bool HeadlessContentMainDelegate::BasicStartupComplete(int* exit_code) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ // Make sure all processes know that we're in headless mode.
+ if (!command_line->HasSwitch(switches::kHeadless))
+ command_line->AppendSwitch(switches::kHeadless);
+
if (browser_->options()->single_process_mode)
command_line->AppendSwitch(switches::kSingleProcess);
if (browser_->options()->disable_sandbox)
command_line->AppendSwitch(switches::kNoSandbox);
+#if defined(USE_OZONE)
// The headless backend is automatically chosen for a headless build, but also
// adding it here allows us to run in a non-headless build too.
command_line->AppendSwitchASCII(switches::kOzonePlatform, "headless");
+#endif
if (!browser_->options()->gl_implementation.empty()) {
command_line->AppendSwitchASCII(switches::kUseGL,
@@ -104,11 +111,24 @@ HeadlessContentMainDelegate* HeadlessContentMainDelegate::GetInstance() {
// static
void HeadlessContentMainDelegate::InitializeResourceBundle() {
+ base::FilePath dir_module;
base::FilePath pak_file;
- bool result = PathService::Get(base::DIR_MODULE, &pak_file);
+ bool result = PathService::Get(base::DIR_MODULE, &dir_module);
DCHECK(result);
- pak_file = pak_file.Append(FILE_PATH_LITERAL("headless_lib.pak"));
- ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file);
+
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ const std::string locale = command_line->GetSwitchValueASCII(switches::kLang);
+ ui::ResourceBundle::InitSharedInstanceWithLocale(
+ locale, nullptr, ui::ResourceBundle::DO_NOT_LOAD_COMMON_RESOURCES);
+
+ // Try loading the headless library pak file first. If it doesn't exist (i.e.,
+ // when we're running with the --headless switch), fall back to the browser's
+ // resource pak.
+ pak_file = dir_module.Append(FILE_PATH_LITERAL("headless_lib.pak"));
+ if (!base::PathExists(pak_file))
+ pak_file = dir_module.Append(FILE_PATH_LITERAL("resources.pak"));
+ ResourceBundle::GetSharedInstance().AddDataPackFromPath(
+ pak_file, ui::SCALE_FACTOR_NONE);
}
content::ContentBrowserClient*
@@ -117,16 +137,4 @@ HeadlessContentMainDelegate::CreateContentBrowserClient() {
return browser_client_.get();
}
-content::ContentRendererClient*
-HeadlessContentMainDelegate::CreateContentRendererClient() {
- renderer_client_.reset(new HeadlessContentRendererClient);
- return renderer_client_.get();
-}
-
-content::ContentUtilityClient*
-HeadlessContentMainDelegate::CreateContentUtilityClient() {
- utility_client_.reset(new HeadlessContentUtilityClient);
- return utility_client_.get();
-}
-
} // namespace headless
diff --git a/chromium/headless/lib/headless_content_main_delegate.h b/chromium/headless/lib/headless_content_main_delegate.h
index 00a20cf27dc..2e7aafe7973 100644
--- a/chromium/headless/lib/headless_content_main_delegate.h
+++ b/chromium/headless/lib/headless_content_main_delegate.h
@@ -10,18 +10,13 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "content/public/app/content_main_delegate.h"
+#include "headless/lib/browser/headless_platform_event_source.h"
#include "headless/lib/headless_content_client.h"
-namespace content {
-class BrowserContext;
-}
-
namespace headless {
class HeadlessBrowserImpl;
class HeadlessContentBrowserClient;
-class HeadlessContentUtilityClient;
-class HeadlessContentRendererClient;
class HeadlessContentMainDelegate : public content::ContentMainDelegate {
public:
@@ -37,8 +32,6 @@ class HeadlessContentMainDelegate : public content::ContentMainDelegate {
const content::MainFunctionParams& main_function_params) override;
void ZygoteForked() override;
content::ContentBrowserClient* CreateContentBrowserClient() override;
- content::ContentRendererClient* CreateContentRendererClient() override;
- content::ContentUtilityClient* CreateContentUtilityClient() override;
HeadlessBrowserImpl* browser() const { return browser_.get(); }
@@ -50,9 +43,8 @@ class HeadlessContentMainDelegate : public content::ContentMainDelegate {
static HeadlessContentMainDelegate* GetInstance();
std::unique_ptr<HeadlessContentBrowserClient> browser_client_;
- std::unique_ptr<HeadlessContentRendererClient> renderer_client_;
- std::unique_ptr<HeadlessContentUtilityClient> utility_client_;
HeadlessContentClient content_client_;
+ HeadlessPlatformEventSource platform_event_source_;
std::unique_ptr<HeadlessBrowserImpl> browser_;
diff --git a/chromium/headless/lib/headless_devtools_client_browsertest.cc b/chromium/headless/lib/headless_devtools_client_browsertest.cc
index 26252d8a7fd..6dbd79fad28 100644
--- a/chromium/headless/lib/headless_devtools_client_browsertest.cc
+++ b/chromium/headless/lib/headless_devtools_client_browsertest.cc
@@ -7,9 +7,12 @@
#include "base/json/json_reader.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test.h"
#include "headless/lib/browser/headless_web_contents_impl.h"
+#include "headless/public/devtools/domains/dom.h"
#include "headless/public/devtools/domains/emulation.h"
+#include "headless/public/devtools/domains/inspector.h"
#include "headless/public/devtools/domains/network.h"
#include "headless/public/devtools/domains/page.h"
#include "headless/public/devtools/domains/runtime.h"
@@ -62,6 +65,7 @@ class HeadlessDevToolsClientNavigationTest
}
void OnLoadEventFired(const page::LoadEventFiredParams& params) override {
+ devtools_client_->GetPage()->Disable();
devtools_client_->GetPage()->GetExperimental()->RemoveObserver(this);
FinishAsynchronousTest();
}
@@ -171,6 +175,7 @@ class HeadlessDevToolsClientObserverTest
&content_type));
EXPECT_EQ("text/html", content_type);
+ devtools_client_->GetNetwork()->Disable();
devtools_client_->GetNetwork()->RemoveObserver(this);
FinishAsynchronousTest();
}
@@ -205,6 +210,9 @@ class HeadlessDevToolsClientExperimentalTest
void OnFrameStoppedLoading(
const page::FrameStoppedLoadingParams& params) override {
+ devtools_client_->GetPage()->Disable();
+ devtools_client_->GetPage()->GetExperimental()->RemoveObserver(this);
+
// Check that a non-experimental command which has no return value can be
// called with a void() callback.
devtools_client_->GetPage()->Reload(
@@ -660,4 +668,125 @@ class HeadlessDevToolsNavigationControlTest
HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessDevToolsNavigationControlTest);
+class HeadlessCrashObserverTest : public HeadlessAsyncDevTooledBrowserTest,
+ inspector::ExperimentalObserver {
+ public:
+ void RunDevTooledTest() override {
+ devtools_client_->GetInspector()->GetExperimental()->AddObserver(this);
+ devtools_client_->GetInspector()->GetExperimental()->Enable(
+ headless::inspector::EnableParams::Builder().Build());
+ devtools_client_->GetPage()->Enable();
+ devtools_client_->GetPage()->Navigate(content::kChromeUICrashURL);
+ }
+
+ void OnTargetCrashed(const inspector::TargetCrashedParams& params) override {
+ FinishAsynchronousTest();
+ render_process_exited_ = true;
+ }
+
+ // Make sure we don't fail because the renderer crashed!
+ void RenderProcessExited(base::TerminationStatus status,
+ int exit_code) override {
+ EXPECT_EQ(base::TERMINATION_STATUS_ABNORMAL_TERMINATION, status);
+ }
+};
+
+HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessCrashObserverTest);
+
+class HeadlessDevToolsClientAttachTest
+ : public HeadlessAsyncDevTooledBrowserTest {
+ public:
+ void RunDevTooledTest() override {
+ other_devtools_client_ = HeadlessDevToolsClient::Create();
+ HeadlessDevToolsTarget* devtools_target =
+ web_contents_->GetDevToolsTarget();
+
+ // Try attaching: there's already a client attached.
+ EXPECT_FALSE(devtools_target->AttachClient(other_devtools_client_.get()));
+ EXPECT_TRUE(devtools_target->IsAttached());
+ // Detach the existing client, attach the other client.
+ devtools_target->DetachClient(devtools_client_.get());
+ EXPECT_FALSE(devtools_target->IsAttached());
+ EXPECT_TRUE(devtools_target->AttachClient(other_devtools_client_.get()));
+ EXPECT_TRUE(devtools_target->IsAttached());
+
+ // Now, let's make sure this devtools client works.
+ other_devtools_client_->GetRuntime()->Evaluate(
+ "24 * 7", base::Bind(&HeadlessDevToolsClientAttachTest::OnFirstResult,
+ base::Unretained(this)));
+ }
+
+ void OnFirstResult(std::unique_ptr<runtime::EvaluateResult> result) {
+ int value;
+ EXPECT_TRUE(result->GetResult()->HasValue());
+ EXPECT_TRUE(result->GetResult()->GetValue()->GetAsInteger(&value));
+ EXPECT_EQ(24 * 7, value);
+
+ HeadlessDevToolsTarget* devtools_target =
+ web_contents_->GetDevToolsTarget();
+
+ // Try attach, then force-attach the original client.
+ EXPECT_FALSE(devtools_target->AttachClient(devtools_client_.get()));
+ devtools_target->ForceAttachClient(devtools_client_.get());
+ EXPECT_TRUE(devtools_target->IsAttached());
+
+ devtools_client_->GetRuntime()->Evaluate(
+ "27 * 4", base::Bind(&HeadlessDevToolsClientAttachTest::OnSecondResult,
+ base::Unretained(this)));
+ }
+
+ void OnSecondResult(std::unique_ptr<runtime::EvaluateResult> result) {
+ int value;
+ EXPECT_TRUE(result->GetResult()->HasValue());
+ EXPECT_TRUE(result->GetResult()->GetValue()->GetAsInteger(&value));
+ EXPECT_EQ(27 * 4, value);
+
+ // If everything worked, this call will not crash, since it
+ // detaches devtools_client_.
+ FinishAsynchronousTest();
+ }
+
+ protected:
+ std::unique_ptr<HeadlessDevToolsClient> other_devtools_client_;
+};
+
+HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessDevToolsClientAttachTest);
+
+class HeadlessDevToolsMethodCallErrorTest
+ : public HeadlessAsyncDevTooledBrowserTest,
+ public page::Observer {
+ public:
+ void RunDevTooledTest() override {
+ EXPECT_TRUE(embedded_test_server()->Start());
+ devtools_client_->GetPage()->AddObserver(this);
+ devtools_client_->GetPage()->Enable();
+ devtools_client_->GetPage()->Navigate(
+ embedded_test_server()->GetURL("/hello.html").spec());
+ }
+
+ void OnLoadEventFired(const page::LoadEventFiredParams& params) override {
+ devtools_client_->GetPage()->GetExperimental()->RemoveObserver(this);
+ devtools_client_->GetDOM()->GetDocument(
+ base::Bind(&HeadlessDevToolsMethodCallErrorTest::OnGetDocument,
+ base::Unretained(this)));
+ }
+
+ void OnGetDocument(std::unique_ptr<dom::GetDocumentResult> result) {
+ devtools_client_->GetDOM()->QuerySelector(
+ dom::QuerySelectorParams::Builder()
+ .SetNodeId(result->GetRoot()->GetNodeId())
+ .SetSelector("<o_O>")
+ .Build(),
+ base::Bind(&HeadlessDevToolsMethodCallErrorTest::OnQuerySelector,
+ base::Unretained(this)));
+ }
+
+ void OnQuerySelector(std::unique_ptr<dom::QuerySelectorResult> result) {
+ EXPECT_EQ(nullptr, result);
+ FinishAsynchronousTest();
+ }
+};
+
+HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessDevToolsMethodCallErrorTest);
+
} // namespace headless
diff --git a/chromium/headless/lib/headless_web_contents_browsertest.cc b/chromium/headless/lib/headless_web_contents_browsertest.cc
index 51f519c9055..693e2dceeaa 100644
--- a/chromium/headless/lib/headless_web_contents_browsertest.cc
+++ b/chromium/headless/lib/headless_web_contents_browsertest.cc
@@ -6,8 +6,10 @@
#include <string>
#include <vector>
+#include "base/base64.h"
#include "content/public/test/browser_test.h"
#include "headless/public/devtools/domains/page.h"
+#include "headless/public/devtools/domains/runtime.h"
#include "headless/public/devtools/domains/security.h"
#include "headless/public/headless_browser.h"
#include "headless/public/headless_devtools_client.h"
@@ -15,6 +17,9 @@
#include "headless/test/headless_browser_test.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/geometry/size.h"
#include "url/gurl.h"
@@ -56,10 +61,41 @@ IN_PROC_BROWSER_TEST_F(HeadlessWebContentsTest, WindowOpen) {
browser_context->GetAllWebContents().size());
}
+namespace {
+bool DecodePNG(std::string base64_data, SkBitmap* bitmap) {
+ std::string png_data;
+ if (!base::Base64Decode(base64_data, &png_data))
+ return false;
+ return gfx::PNGCodec::Decode(
+ reinterpret_cast<unsigned const char*>(png_data.data()), png_data.size(),
+ bitmap);
+}
+} // namespace
+
+// Parameter specifies whether --disable-gpu should be used.
class HeadlessWebContentsScreenshotTest
- : public HeadlessAsyncDevTooledBrowserTest {
+ : public HeadlessAsyncDevTooledBrowserTest,
+ public ::testing::WithParamInterface<bool> {
public:
+ void SetUp() override {
+ EnablePixelOutput();
+ if (GetParam())
+ UseSoftwareCompositing();
+ HeadlessAsyncDevTooledBrowserTest::SetUp();
+ }
+
void RunDevTooledTest() override {
+ std::unique_ptr<runtime::EvaluateParams> params =
+ runtime::EvaluateParams::Builder()
+ .SetExpression("document.body.style.background = '#0000ff'")
+ .Build();
+ devtools_client_->GetRuntime()->Evaluate(
+ std::move(params),
+ base::Bind(&HeadlessWebContentsScreenshotTest::OnPageSetupCompleted,
+ base::Unretained(this)));
+ }
+
+ void OnPageSetupCompleted(std::unique_ptr<runtime::EvaluateResult> result) {
devtools_client_->GetPage()->GetExperimental()->CaptureScreenshot(
page::CaptureScreenshotParams::Builder().Build(),
base::Bind(&HeadlessWebContentsScreenshotTest::OnScreenshotCaptured,
@@ -68,12 +104,26 @@ class HeadlessWebContentsScreenshotTest
void OnScreenshotCaptured(
std::unique_ptr<page::CaptureScreenshotResult> result) {
- EXPECT_LT(0U, result->GetData().length());
+ std::string base64 = result->GetData();
+ EXPECT_LT(0U, base64.length());
+ SkBitmap result_bitmap;
+ EXPECT_TRUE(DecodePNG(base64, &result_bitmap));
+
+ EXPECT_EQ(800, result_bitmap.width());
+ EXPECT_EQ(600, result_bitmap.height());
+ SkColor actual_color = result_bitmap.getColor(400, 300);
+ SkColor expected_color = SkColorSetRGB(0x00, 0x00, 0xff);
+ EXPECT_EQ(expected_color, actual_color);
FinishAsynchronousTest();
}
};
-HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessWebContentsScreenshotTest);
+HEADLESS_ASYNC_DEVTOOLED_TEST_P(HeadlessWebContentsScreenshotTest);
+
+// Instantiate test case for both software and gpu compositing modes.
+INSTANTIATE_TEST_CASE_P(HeadlessWebContentsScreenshotTests,
+ HeadlessWebContentsScreenshotTest,
+ ::testing::Bool());
class HeadlessWebContentsSecurityTest
: public HeadlessAsyncDevTooledBrowserTest,
@@ -88,8 +138,10 @@ class HeadlessWebContentsSecurityTest
void OnSecurityStateChanged(
const security::SecurityStateChangedParams& params) override {
EXPECT_EQ(security::SecurityState::NEUTRAL, params.GetSecurityState());
- EXPECT_TRUE(params.HasExplanations());
+ devtools_client_->GetSecurity()->GetExperimental()->Disable(
+ security::DisableParams::Builder().Build());
+ devtools_client_->GetSecurity()->GetExperimental()->RemoveObserver(this);
FinishAsynchronousTest();
}
};
diff --git a/chromium/headless/lib/renderer/headless_content_renderer_client.cc b/chromium/headless/lib/renderer/headless_content_renderer_client.cc
deleted file mode 100644
index 82faf2165a5..00000000000
--- a/chromium/headless/lib/renderer/headless_content_renderer_client.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "headless/lib/renderer/headless_content_renderer_client.h"
-
-#include "base/strings/utf_string_conversions.h"
-#include "content/public/renderer/render_frame.h"
-
-namespace headless {
-
-HeadlessContentRendererClient::HeadlessContentRendererClient() {}
-
-HeadlessContentRendererClient::~HeadlessContentRendererClient() {}
-
-} // namespace headless
diff --git a/chromium/headless/lib/renderer/headless_content_renderer_client.h b/chromium/headless/lib/renderer/headless_content_renderer_client.h
deleted file mode 100644
index a10ff81752b..00000000000
--- a/chromium/headless/lib/renderer/headless_content_renderer_client.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef HEADLESS_LIB_RENDERER_HEADLESS_CONTENT_RENDERER_CLIENT_H_
-#define HEADLESS_LIB_RENDERER_HEADLESS_CONTENT_RENDERER_CLIENT_H_
-
-#include "content/public/renderer/content_renderer_client.h"
-
-namespace headless {
-
-class HeadlessContentRendererClient : public content::ContentRendererClient {
- public:
- HeadlessContentRendererClient();
- ~HeadlessContentRendererClient() override;
-
- DISALLOW_COPY_AND_ASSIGN(HeadlessContentRendererClient);
-};
-
-} // namespace headless
-
-#endif // HEADLESS_LIB_RENDERER_HEADLESS_CONTENT_RENDERER_CLIENT_H_
diff --git a/chromium/headless/lib/utility/headless_content_utility_client.cc b/chromium/headless/lib/utility/headless_content_utility_client.cc
deleted file mode 100644
index 952e7485ab6..00000000000
--- a/chromium/headless/lib/utility/headless_content_utility_client.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "headless/lib/utility/headless_content_utility_client.h"
-
-namespace headless {
-
-HeadlessContentUtilityClient::HeadlessContentUtilityClient() {}
-
-HeadlessContentUtilityClient::~HeadlessContentUtilityClient() {}
-
-} // namespace headless
diff --git a/chromium/headless/lib/utility/headless_content_utility_client.h b/chromium/headless/lib/utility/headless_content_utility_client.h
deleted file mode 100644
index 0a522f2c54b..00000000000
--- a/chromium/headless/lib/utility/headless_content_utility_client.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef HEADLESS_LIB_UTILITY_HEADLESS_CONTENT_UTILITY_CLIENT_H_
-#define HEADLESS_LIB_UTILITY_HEADLESS_CONTENT_UTILITY_CLIENT_H_
-
-#include "content/public/utility/content_utility_client.h"
-
-namespace headless {
-
-class HeadlessContentUtilityClient : public content::ContentUtilityClient {
- public:
- HeadlessContentUtilityClient();
- ~HeadlessContentUtilityClient() override;
-
- DISALLOW_COPY_AND_ASSIGN(HeadlessContentUtilityClient);
-};
-
-} // namespace headless
-
-#endif // HEADLESS_LIB_UTILITY_HEADLESS_CONTENT_UTILITY_CLIENT_H_
diff --git a/chromium/headless/public/domains/types_unittest.cc b/chromium/headless/public/domains/types_unittest.cc
index e5c0efa7e5a..db07df1a58d 100644
--- a/chromium/headless/public/domains/types_unittest.cc
+++ b/chromium/headless/public/domains/types_unittest.cc
@@ -3,7 +3,9 @@
// found in the LICENSE file.
#include "base/json/json_reader.h"
+#include "base/json/json_string_value_serializer.h"
#include "headless/public/devtools/domains/accessibility.h"
+#include "headless/public/devtools/domains/dom.h"
#include "headless/public/devtools/domains/memory.h"
#include "headless/public/devtools/domains/page.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -202,15 +204,40 @@ TEST(TypesTest, AnyProperty) {
.SetValue(std::move(value))
.Build());
EXPECT_TRUE(object);
- EXPECT_EQ(base::Value::TYPE_INTEGER, object->GetValue()->GetType());
+ EXPECT_EQ(base::Value::Type::INTEGER, object->GetValue()->GetType());
std::unique_ptr<accessibility::AXValue> clone(object->Clone());
EXPECT_TRUE(clone);
- EXPECT_EQ(base::Value::TYPE_INTEGER, clone->GetValue()->GetType());
+ EXPECT_EQ(base::Value::Type::INTEGER, clone->GetValue()->GetType());
int clone_value;
EXPECT_TRUE(clone->GetValue()->GetAsInteger(&clone_value));
EXPECT_EQ(123, clone_value);
}
+TEST(TypesTest, ComplexObjectClone) {
+ std::vector<std::unique_ptr<dom::Node>> child_nodes;
+ child_nodes.emplace_back(dom::Node::Builder()
+ .SetNodeId(1)
+ .SetBackendNodeId(2)
+ .SetNodeType(3)
+ .SetNodeName("-blink-blink")
+ .SetLocalName("-blink-blink")
+ .SetNodeValue("-blink-blink")
+ .Build());
+ std::unique_ptr<dom::SetChildNodesParams> params =
+ dom::SetChildNodesParams::Builder()
+ .SetParentId(123)
+ .SetNodes(std::move(child_nodes))
+ .Build();
+ std::unique_ptr<dom::SetChildNodesParams> clone = params->Clone();
+ ASSERT_NE(nullptr, clone);
+
+ std::string orig;
+ JSONStringValueSerializer(&orig).Serialize(*params->Serialize());
+ std::string clone_value;
+ JSONStringValueSerializer(&clone_value).Serialize(*clone->Serialize());
+ EXPECT_EQ(orig, clone_value);
+}
+
} // namespace headless
diff --git a/chromium/headless/public/headless_browser.h b/chromium/headless/public/headless_browser.h
index 021e91064fb..c3043f006ad 100644
--- a/chromium/headless/public/headless_browser.h
+++ b/chromium/headless/public/headless_browser.h
@@ -56,6 +56,12 @@ class HEADLESS_EXPORT HeadlessBrowser {
virtual HeadlessBrowserContext* GetBrowserContextForId(
const std::string& id) = 0;
+ // Allows setting and getting the browser context that DevTools will create
+ // new targets in by default.
+ virtual void SetDefaultBrowserContext(
+ HeadlessBrowserContext* browser_context) = 0;
+ virtual HeadlessBrowserContext* GetDefaultBrowserContext() = 0;
+
// Returns a task runner for submitting work to the browser file thread.
virtual scoped_refptr<base::SingleThreadTaskRunner> BrowserFileThread()
const = 0;
diff --git a/chromium/headless/public/headless_devtools_target.h b/chromium/headless/public/headless_devtools_target.h
index 941fe6f51e2..e8047f39b8f 100644
--- a/chromium/headless/public/headless_devtools_target.h
+++ b/chromium/headless/public/headless_devtools_target.h
@@ -20,14 +20,21 @@ class HEADLESS_EXPORT HeadlessDevToolsTarget {
// Attach or detach a client to this target. A client must be attached in
// order to send commands or receive notifications from the target.
//
- // A single client may be attached to at most one target at a time. Note that
- // currently also only one client may be attached to a single target at a
- // time.
+ // A single client may be attached to at most one target at a time. If
+ // the target already has a client attached, AttachClient will return false.
+ // ForceAttachClient will detach any existing connection before attaching
+ // |client|.
+ // Note that currently also only one client may be attached to a single target
+ // at a time.
//
// |client| must outlive this target.
- virtual void AttachClient(HeadlessDevToolsClient* client) = 0;
+ virtual bool AttachClient(HeadlessDevToolsClient* client) = 0;
+ virtual void ForceAttachClient(HeadlessDevToolsClient* client) = 0;
virtual void DetachClient(HeadlessDevToolsClient* client) = 0;
+ // Returns true if a devtools client is attached.
+ virtual bool IsAttached() = 0;
+
private:
DISALLOW_COPY_AND_ASSIGN(HeadlessDevToolsTarget);
};
diff --git a/chromium/headless/public/headless_web_contents.h b/chromium/headless/public/headless_web_contents.h
index 0ca6a588bb5..74dc4df9049 100644
--- a/chromium/headless/public/headless_web_contents.h
+++ b/chromium/headless/public/headless_web_contents.h
@@ -11,6 +11,7 @@
#include "base/callback.h"
#include "base/macros.h"
+#include "base/process/kill.h"
#include "headless/public/headless_export.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "ui/gfx/geometry/size.h"
@@ -39,6 +40,16 @@ class HEADLESS_EXPORT HeadlessWebContents {
// TODO(altimin): Support this event for pages that aren't created by us.
virtual void DevToolsTargetReady() {}
+ // This method is invoked when the process of the observed RenderProcessHost
+ // exits (either normally or with a crash). To determine if the process
+ // closed normally or crashed, examine the |status| parameter.
+ //
+ // If |status| is TERMINATION_STATUS_LAUNCH_FAILED then |exit_code| will
+ // contain a platform specific launch failure error code. Otherwise, it will
+ // contain the exit code for the process.
+ virtual void RenderProcessExited(base::TerminationStatus status,
+ int exit_code) {}
+
protected:
Observer() {}
virtual ~Observer() {}
diff --git a/chromium/headless/public/internal/value_conversions.h b/chromium/headless/public/internal/value_conversions.h
index 4a85a02a464..78ac41fc4cb 100644
--- a/chromium/headless/public/internal/value_conversions.h
+++ b/chromium/headless/public/internal/value_conversions.h
@@ -67,7 +67,7 @@ std::unique_ptr<base::Value> ToValueImpl(const std::vector<T>& vector,
template <typename T>
std::unique_ptr<base::Value> ToValueImpl(const std::unique_ptr<T>& value,
std::unique_ptr<T>*) {
- return ToValue(value.get());
+ return ToValue(*value);
}
// FromValue specializations for basic types.
diff --git a/chromium/headless/public/util/deterministic_http_protocol_handler.h b/chromium/headless/public/util/deterministic_http_protocol_handler.h
index da0a70d1e4b..89d76cbc692 100644
--- a/chromium/headless/public/util/deterministic_http_protocol_handler.h
+++ b/chromium/headless/public/util/deterministic_http_protocol_handler.h
@@ -17,7 +17,6 @@ class URLRequestJobFactory;
namespace headless {
class DeterministicDispatcher;
-class HeadlessBrowserContext;
// A deterministic protocol handler. Requests made to this protocol handler
// will return in order of creation, regardless of what order the network
diff --git a/chromium/headless/public/util/dom_tree_extractor_browsertest.cc b/chromium/headless/public/util/dom_tree_extractor_browsertest.cc
index 57b6a54869f..22b237960c5 100644
--- a/chromium/headless/public/util/dom_tree_extractor_browsertest.cc
+++ b/chromium/headless/public/util/dom_tree_extractor_browsertest.cc
@@ -49,13 +49,14 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
}
void OnLoadEventFired(const page::LoadEventFiredParams& params) override {
+ devtools_client_->GetPage()->Disable();
devtools_client_->GetPage()->RemoveObserver(this);
extractor_.reset(new DomTreeExtractor(devtools_client_.get()));
std::vector<std::string> css_whitelist = {
- "color", "display", "font-style", "margin-left",
- "margin-right", "margin-top", "margin-bottom"};
+ "color", "display", "font-style", "font-family",
+ "margin-left", "margin-right", "margin-top", "margin-bottom"};
extractor_->ExtractDomTree(
css_whitelist,
base::Bind(&DomTreeExtractorBrowserTest::OnDomTreeExtracted,
@@ -181,7 +182,7 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
"x": 0.0,
"y": 0.0
},
- "childIndices": [ 2, 5 ],
+ "childIndices": [ 2, 6 ],
"frameId": "?",
"localName": "html",
"nodeId": 2,
@@ -194,7 +195,7 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
R"raw_string({
"attributes": [ ],
"backendNodeId": 5,
- "childIndices": [ 3 ],
+ "childIndices": [ 3, 5 ],
"localName": "head",
"nodeId": 3,
"nodeName": "HEAD",
@@ -223,17 +224,29 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
})raw_string",
R"raw_string({
- "attributes": [ ],
+ "attributes": [ "href", "dom_tree_test.css", "rel", "stylesheet",
+ "type", "text/css" ],
"backendNodeId": 8,
+ "childIndices": [ ],
+ "localName": "link",
+ "nodeId": 6,
+ "nodeName": "LINK",
+ "nodeType": 1,
+ "nodeValue": ""
+ })raw_string",
+
+ R"raw_string({
+ "attributes": [ ],
+ "backendNodeId": 9,
"boundingBox": {
"height": 584.0,
"width": 784.0,
"x": 8.0,
"y": 8.0
},
- "childIndices": [ 6 ],
+ "childIndices": [ 7 ],
"localName": "body",
- "nodeId": 6,
+ "nodeId": 7,
"nodeName": "BODY",
"nodeType": 1,
"nodeValue": "",
@@ -242,16 +255,16 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
R"raw_string({
"attributes": [ "id", "id1" ],
- "backendNodeId": 9,
+ "backendNodeId": 10,
"boundingBox": {
- "height": 367.0,
+ "height": 354.0,
"width": 784.0,
"x": 8.0,
"y": 8.0
},
- "childIndices": [ 7, 9, 16 ],
+ "childIndices": [ 8, 10, 17 ],
"localName": "div",
- "nodeId": 7,
+ "nodeId": 8,
"nodeName": "DIV",
"nodeType": 1,
"nodeValue": "",
@@ -259,17 +272,17 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
})raw_string",
R"raw_string({
- "attributes": [ "style", "color: red" ],
- "backendNodeId": 10,
+ "attributes": [ "class", "red" ],
+ "backendNodeId": 11,
"boundingBox": {
- "height": 37.0,
+ "height": 32.0,
"width": 784.0,
"x": 8.0,
"y": 8.0
},
- "childIndices": [ 8 ],
+ "childIndices": [ 9 ],
"localName": "h1",
- "nodeId": 8,
+ "nodeId": 9,
"nodeName": "H1",
"nodeType": 1,
"nodeValue": "",
@@ -277,17 +290,17 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
})raw_string",
R"raw_string({
- "backendNodeId": 11,
+ "backendNodeId": 12,
"boundingBox": {
- "height": 36.0,
- "width": 143.0,
+ "height": 32.0,
+ "width": 320.0,
"x": 8.0,
"y": 8.0
},
"inlineTextNodes": [ {
"boundingBox": {
- "height": 36.0,
- "width": 142.171875,
+ "height": 32.0,
+ "width": 320.0,
"x": 8.0,
"y": 8.0
},
@@ -296,7 +309,7 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
} ],
"layoutText": "Some text.",
"localName": "",
- "nodeId": 9,
+ "nodeId": 10,
"nodeName": "#text",
"nodeType": 3,
"nodeValue": "Some text.",
@@ -304,33 +317,33 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
})raw_string",
R"raw_string({
- "attributes": [
- "src", "/iframe.html", "width", "400", "height", "200" ],
- "backendNodeId": 12,
+ "attributes": [ "src", "/iframe.html", "width", "400", "height",
+ "200" ],
+ "backendNodeId": 13,
"boundingBox": {
"height": 205.0,
"width": 404.0,
"x": 8.0,
- "y": 66.0
+ "y": 61.0
},
"childIndices": [ ],
- "contentDocumentIndex": 10,
+ "contentDocumentIndex": 11,
"frameId": "?",
"localName": "iframe",
- "nodeId": 10,
+ "nodeId": 11,
"nodeName": "IFRAME",
"nodeType": 1,
"nodeValue": "",
- "styleIndex": 4
+ "styleIndex": 6
})raw_string",
R"raw_string({
- "backendNodeId": 13,
+ "backendNodeId": 14,
"baseURL": "http://127.0.0.1/iframe.html",
- "childIndices": [ 11 ],
+ "childIndices": [ 12 ],
"documentURL": "http://127.0.0.1/iframe.html",
"localName": "",
- "nodeId": 11,
+ "nodeId": 12,
"nodeName": "#document",
"nodeType": 9,
"nodeValue": "",
@@ -339,29 +352,29 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
R"raw_string({
"attributes": [ ],
- "backendNodeId": 14,
+ "backendNodeId": 15,
"boundingBox": {
"height": 200.0,
"width": 400.0,
"x": 10.0,
- "y": 68.0
+ "y": 63.0
},
- "childIndices": [ 12, 13 ],
+ "childIndices": [ 13, 14 ],
"frameId": "?",
"localName": "html",
- "nodeId": 12,
+ "nodeId": 13,
"nodeName": "HTML",
"nodeType": 1,
"nodeValue": "",
- "styleIndex": 0
+ "styleIndex": 3
})raw_string",
R"raw_string({
"attributes": [ ],
- "backendNodeId": 15,
+ "backendNodeId": 16,
"childIndices": [ ],
"localName": "head",
- "nodeId": 13,
+ "nodeId": 14,
"nodeName": "HEAD",
"nodeType": 1,
"nodeValue": ""
@@ -369,42 +382,42 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
R"raw_string({
"attributes": [ ],
- "backendNodeId": 16,
+ "backendNodeId": 17,
"boundingBox": {
"height": 171.0,
"width": 384.0,
"x": 18.0,
- "y": 76.0
+ "y": 71.0
},
- "childIndices": [ 14 ],
+ "childIndices": [ 15 ],
"localName": "body",
- "nodeId": 14,
+ "nodeId": 15,
"nodeName": "BODY",
"nodeType": 1,
"nodeValue": "",
- "styleIndex": 1
+ "styleIndex": 4
})raw_string",
R"raw_string({
"attributes": [ ],
- "backendNodeId": 17,
+ "backendNodeId": 18,
"boundingBox": {
"height": 37.0,
"width": 384.0,
"x": 18.0,
- "y": 76.0
+ "y": 71.0
},
- "childIndices": [ 15 ],
+ "childIndices": [ 16 ],
"localName": "h1",
- "nodeId": 15,
+ "nodeId": 16,
"nodeName": "H1",
"nodeType": 1,
"nodeValue": "",
- "styleIndex": 3
+ "styleIndex": 5
})raw_string",
R"raw_string({
- "backendNodeId": 18,
+ "backendNodeId": 19,
"boundingBox": {
"height": 36.0,
"width": 308.0,
@@ -423,25 +436,25 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
} ],
"layoutText": "Hello from the iframe!",
"localName": "",
- "nodeId": 16,
+ "nodeId": 17,
"nodeName": "#text",
"nodeType": 3,
"nodeValue": "Hello from the iframe!",
- "styleIndex": 3
+ "styleIndex": 5
})raw_string",
R"raw_string({
"attributes": [ "id", "id2" ],
- "backendNodeId": 19,
+ "backendNodeId": 20,
"boundingBox": {
- "height": 105.0,
+ "height": 97.0,
"width": 784.0,
"x": 8.0,
- "y": 270.0
+ "y": 265.0
},
- "childIndices": [ 17 ],
+ "childIndices": [ 18 ],
"localName": "div",
- "nodeId": 17,
+ "nodeId": 18,
"nodeName": "DIV",
"nodeType": 1,
"nodeValue": "",
@@ -450,16 +463,16 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
R"raw_string({
"attributes": [ "id", "id3" ],
- "backendNodeId": 20,
+ "backendNodeId": 21,
"boundingBox": {
- "height": 105.0,
+ "height": 97.0,
"width": 784.0,
"x": 8.0,
- "y": 270.0
+ "y": 265.0
},
- "childIndices": [ 18 ],
+ "childIndices": [ 19 ],
"localName": "div",
- "nodeId": 18,
+ "nodeId": 19,
"nodeName": "DIV",
"nodeType": 1,
"nodeValue": "",
@@ -468,16 +481,16 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
R"raw_string({
"attributes": [ "id", "id4" ],
- "backendNodeId": 21,
+ "backendNodeId": 22,
"boundingBox": {
- "height": 105.0,
+ "height": 97.0,
"width": 784.0,
"x": 8.0,
- "y": 270.0
+ "y": 265.0
},
- "childIndices": [ 19, 21, 23, 24 ],
+ "childIndices": [ 20, 22, 24, 25 ],
"localName": "div",
- "nodeId": 19,
+ "nodeId": 20,
"nodeName": "DIV",
"nodeType": 1,
"nodeValue": "",
@@ -486,97 +499,97 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
R"raw_string({
"attributes": [ "href", "https://www.google.com" ],
- "backendNodeId": 22,
+ "backendNodeId": 23,
"boundingBox": {
- "height": 18.0,
- "width": 53.0,
+ "height": 17.0,
+ "width": 112.0,
"x": 8.0,
- "y": 270.0
+ "y": 265.0
},
- "childIndices": [ 20 ],
+ "childIndices": [ 21 ],
"localName": "a",
- "nodeId": 20,
+ "nodeId": 21,
"nodeName": "A",
"nodeType": 1,
"nodeValue": "",
- "styleIndex": 5
+ "styleIndex": 7
})raw_string",
R"raw_string({
- "backendNodeId": 23,
+ "backendNodeId": 24,
"boundingBox": {
- "height": 18.0,
- "width": 53.0,
+ "height": 17.0,
+ "width": 112.0,
"x": 8.0,
- "y": 270.0
+ "y": 265.0
},
"inlineTextNodes": [ {
"boundingBox": {
- "height": 17.0,
- "width": 52.421875,
+ "height": 16.0,
+ "width": 112.0,
"x": 8.0,
- "y": 270.4375
+ "y": 265.4375
},
"numCharacters": 7,
"startCharacterIndex": 0
} ],
"layoutText": "Google!",
"localName": "",
- "nodeId": 21,
+ "nodeId": 22,
"nodeName": "#text",
"nodeType": 3,
"nodeValue": "Google!",
- "styleIndex": 5
+ "styleIndex": 7
})raw_string",
R"raw_string({
"attributes": [ ],
- "backendNodeId": 24,
+ "backendNodeId": 25,
"boundingBox": {
- "height": 19.0,
+ "height": 17.0,
"width": 784.0,
"x": 8.0,
- "y": 304.0
+ "y": 297.0
},
- "childIndices": [ 22 ],
+ "childIndices": [ 23 ],
"localName": "p",
- "nodeId": 22,
+ "nodeId": 23,
"nodeName": "P",
"nodeType": 1,
"nodeValue": "",
- "styleIndex": 6
+ "styleIndex": 8
})raw_string",
R"raw_string({
- "backendNodeId": 25,
+ "backendNodeId": 26,
"boundingBox": {
- "height": 18.0,
- "width": 85.0,
+ "height": 17.0,
+ "width": 192.0,
"x": 8.0,
- "y": 304.0
+ "y": 297.0
},
"inlineTextNodes": [ {
"boundingBox": {
- "height": 17.0,
- "width": 84.84375,
+ "height": 16.0,
+ "width": 192.0,
"x": 8.0,
- "y": 304.4375
+ "y": 297.4375
},
"numCharacters": 12,
"startCharacterIndex": 0
} ],
"layoutText": "A paragraph!",
"localName": "",
- "nodeId": 23,
+ "nodeId": 24,
"nodeName": "#text",
"nodeType": 3,
"nodeValue": "A paragraph!",
- "styleIndex": 6
+ "styleIndex": 8
})raw_string",
R"raw_string({
"attributes": [ ],
- "backendNodeId": 26,
+ "backendNodeId": 27,
"boundingBox": {
"height": 0.0,
"width": 0.0,
@@ -586,138 +599,139 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
"childIndices": [ ],
"inlineTextNodes": [ {
"boundingBox": {
- "height": 17.0,
+ "height": 16.0,
"width": 0.0,
"x": 8.0,
- "y": 338.4375
+ "y": 329.4375
},
"numCharacters": 1,
"startCharacterIndex": 0
} ],
"layoutText": "\n",
"localName": "br",
- "nodeId": 24,
+ "nodeId": 25,
"nodeName": "BR",
"nodeType": 1,
"nodeValue": "",
- "styleIndex": 4
+ "styleIndex": 6
})raw_string",
R"raw_string({
- "attributes": [ "style", "color: green" ],
- "backendNodeId": 27,
+ "attributes": [ "class", "green" ],
+ "backendNodeId": 28,
"boundingBox": {
- "height": 19.0,
+ "height": 17.0,
"width": 784.0,
"x": 8.0,
- "y": 356.0
+ "y": 345.0
},
- "childIndices": [ 25, 26, 28 ],
+ "childIndices": [ 26, 27, 29 ],
"localName": "div",
- "nodeId": 25,
+ "nodeId": 26,
"nodeName": "DIV",
"nodeType": 1,
"nodeValue": "",
- "styleIndex": 7
- })raw_string",
+ "styleIndex": 9
+ }
+ )raw_string",
R"raw_string({
- "backendNodeId": 28,
+ "backendNodeId": 29,
"boundingBox": {
- "height": 18.0,
- "width": 41.0,
+ "height": 17.0,
+ "width": 80.0,
"x": 8.0,
- "y": 356.0
+ "y": 345.0
},
"inlineTextNodes": [ {
"boundingBox": {
- "height": 17.0,
- "width": 40.4375,
+ "height": 16.0,
+ "width": 80.0,
"x": 8.0,
- "y": 356.4375
+ "y": 345.4375
},
"numCharacters": 5,
"startCharacterIndex": 0
} ],
"layoutText": "Some ",
"localName": "",
- "nodeId": 26,
+ "nodeId": 27,
"nodeName": "#text",
"nodeType": 3,
"nodeValue": "Some ",
- "styleIndex": 7
+ "styleIndex": 9
})raw_string",
R"raw_string({
"attributes": [ ],
- "backendNodeId": 29,
+ "backendNodeId": 30,
"boundingBox": {
- "height": 18.0,
- "width": 37.0,
- "x": 48.0,
- "y": 356.0
+ "height": 17.0,
+ "width": 80.0,
+ "x": 88.0,
+ "y": 345.0
},
- "childIndices": [ 27 ],
+ "childIndices": [ 28 ],
"localName": "em",
- "nodeId": 27,
+ "nodeId": 28,
"nodeName": "EM",
"nodeType": 1,
"nodeValue": "",
- "styleIndex": 8
+ "styleIndex": 10
})raw_string",
R"raw_string({
- "backendNodeId": 30,
+ "backendNodeId": 31,
"boundingBox": {
- "height": 18.0,
- "width": 37.0,
- "x": 48.0,
- "y": 356.0
+ "height": 17.0,
+ "width": 80.0,
+ "x": 88.0,
+ "y": 345.0
},
"inlineTextNodes": [ {
"boundingBox": {
- "height": 17.0,
- "width": 35.828125,
- "x": 48.4375,
- "y": 356.4375
+ "height": 16.0,
+ "width": 80.0,
+ "x": 88.0,
+ "y": 345.4375
},
"numCharacters": 5,
"startCharacterIndex": 0
} ],
"layoutText": "green",
"localName": "",
- "nodeId": 28,
+ "nodeId": 29,
"nodeName": "#text",
"nodeType": 3,
"nodeValue": "green",
- "styleIndex": 8
+ "styleIndex": 10
})raw_string",
R"raw_string({
- "backendNodeId": 31,
+ "backendNodeId": 32,
"boundingBox": {
- "height": 18.0,
- "width": 41.0,
- "x": 84.0,
- "y": 356.0
+ "height": 17.0,
+ "width": 128.0,
+ "x": 168.0,
+ "y": 345.0
},
"inlineTextNodes": [ {
"boundingBox": {
- "height": 17.0,
- "width": 39.984375,
- "x": 84.265625,
- "y": 356.4375
+ "height": 16.0,
+ "width": 128.0,
+ "x": 168.0,
+ "y": 345.4375
},
"numCharacters": 8,
"startCharacterIndex": 0
} ],
"layoutText": " text...",
"localName": "",
- "nodeId": 29,
+ "nodeId": 30,
"nodeName": "#text",
"nodeType": 3,
"nodeValue": " text...",
- "styleIndex": 7
+ "styleIndex": 9
})raw_string"};
EXPECT_EQ(expected_dom_nodes.size(), dom_nodes.size());
@@ -736,6 +750,7 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
R"raw_string({
"color": "rgb(0, 0, 0)",
"display": "block",
+ "font-family": "ahem",
"font-style": "normal",
"margin-bottom": "0px",
"margin-left": "0px",
@@ -746,6 +761,7 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
R"raw_string({
"color": "rgb(0, 0, 0)",
"display": "block",
+ "font-family": "ahem",
"font-style": "normal",
"margin-bottom": "8px",
"margin-left": "8px",
@@ -756,6 +772,7 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
R"raw_string({
"color": "rgb(255, 0, 0)",
"display": "block",
+ "font-family": "ahem",
"font-style": "normal",
"margin-bottom": "21.44px",
"margin-left": "0px",
@@ -766,6 +783,29 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
R"raw_string({
"color": "rgb(0, 0, 0)",
"display": "block",
+ "font-family": "\"Times New Roman\"",
+ "font-style": "normal",
+ "margin-bottom": "0px",
+ "margin-left": "0px",
+ "margin-right": "0px",
+ "margin-top": "0px"
+ })raw_string",
+
+ R"raw_string({
+ "color": "rgb(0, 0, 0)",
+ "display": "block",
+ "font-family": "\"Times New Roman\"",
+ "font-style": "normal",
+ "margin-bottom": "8px",
+ "margin-left": "8px",
+ "margin-right": "8px",
+ "margin-top": "8px"
+ })raw_string",
+
+ R"raw_string({
+ "color": "rgb(0, 0, 0)",
+ "display": "block",
+ "font-family": "\"Times New Roman\"",
"font-style": "normal",
"margin-bottom": "21.44px",
"margin-left": "0px",
@@ -776,6 +816,7 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
R"raw_string({
"color": "rgb(0, 0, 0)",
"display": "inline",
+ "font-family": "ahem",
"font-style": "normal",
"margin-bottom": "0px",
"margin-left": "0px",
@@ -786,6 +827,7 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
R"raw_string({
"color": "rgb(0, 0, 238)",
"display": "inline",
+ "font-family": "ahem",
"font-style": "normal",
"margin-bottom": "0px",
"margin-left": "0px",
@@ -796,6 +838,7 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
R"raw_string({
"color": "rgb(0, 0, 0)",
"display": "block",
+ "font-family": "ahem",
"font-style": "normal",
"margin-bottom": "16px",
"margin-left": "0px",
@@ -806,6 +849,7 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
R"raw_string({
"color": "rgb(0, 128, 0)",
"display": "block",
+ "font-family": "ahem",
"font-style": "normal",
"margin-bottom": "0px",
"margin-left": "0px",
@@ -816,12 +860,14 @@ class DomTreeExtractorBrowserTest : public HeadlessAsyncDevTooledBrowserTest,
R"raw_string({
"color": "rgb(0, 128, 0)",
"display": "inline",
+ "font-family": "ahem",
"font-style": "italic",
"margin-bottom": "0px",
"margin-left": "0px",
"margin-right": "0px",
"margin-top": "0px"
- })raw_string"};
+ }
+ )raw_string"};
for (size_t i = 0; i < computed_styles.size(); i++) {
std::string result_json;
diff --git a/chromium/headless/public/util/http_url_fetcher.h b/chromium/headless/public/util/http_url_fetcher.h
index 2b17287d8fd..aa9cdb650f6 100644
--- a/chromium/headless/public/util/http_url_fetcher.h
+++ b/chromium/headless/public/util/http_url_fetcher.h
@@ -10,7 +10,6 @@
namespace net {
class URLRequestContext;
-class URLRequestJobFactory;
} // namespace
namespace headless {
diff --git a/chromium/headless/public/util/in_memory_request_job.h b/chromium/headless/public/util/in_memory_request_job.h
index 1526c9a470c..7810422b27f 100644
--- a/chromium/headless/public/util/in_memory_request_job.h
+++ b/chromium/headless/public/util/in_memory_request_job.h
@@ -9,11 +9,6 @@
#include "headless/public/util/in_memory_protocol_handler.h"
#include "net/url_request/url_request_job.h"
-namespace net {
-class StringIOBuffer;
-class DrainableIOBuffer;
-}
-
namespace headless {
class InMemoryRequestJob : public net::URLRequestJob {
public:
diff --git a/chromium/headless/public/util/testing/generic_url_request_mocks.cc b/chromium/headless/public/util/testing/generic_url_request_mocks.cc
index 08ff33d4b07..adcabbef839 100644
--- a/chromium/headless/public/util/testing/generic_url_request_mocks.cc
+++ b/chromium/headless/public/util/testing/generic_url_request_mocks.cc
@@ -5,6 +5,7 @@
#include "headless/public/util/testing/generic_url_request_mocks.h"
#include "base/logging.h"
+#include "base/threading/thread_task_runner_handle.h"
namespace net {
class URLRequestJob;
diff --git a/chromium/headless/public/util/testing/generic_url_request_mocks.h b/chromium/headless/public/util/testing/generic_url_request_mocks.h
index 7dc683fce64..fb8f0bef954 100644
--- a/chromium/headless/public/util/testing/generic_url_request_mocks.h
+++ b/chromium/headless/public/util/testing/generic_url_request_mocks.h
@@ -16,14 +16,6 @@
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_job_factory.h"
-namespace net {
-class URLRequestJob;
-} // namespace net
-
-namespace htmlrender_webkit_headless_proto {
-class Resource;
-} // htmlrender_webkit_headless_proto net
-
namespace headless {
class MockGenericURLRequestJobDelegate : public GenericURLRequestJob::Delegate {