summaryrefslogtreecommitdiff
path: root/chromium/headless/lib/browser
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2016-05-09 14:22:11 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2016-05-09 15:11:45 +0000
commit2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c (patch)
treee75f511546c5fd1a173e87c1f9fb11d7ac8d1af3 /chromium/headless/lib/browser
parenta4f3d46271c57e8155ba912df46a05559d14726e (diff)
downloadqtwebengine-chromium-2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c.tar.gz
BASELINE: Update Chromium to 51.0.2704.41
Also adds in all smaller components by reversing logic for exclusion. Change-Id: Ibf90b506e7da088ea2f65dcf23f2b0992c504422 Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
Diffstat (limited to 'chromium/headless/lib/browser')
-rw-r--r--chromium/headless/lib/browser/DEPS3
-rw-r--r--chromium/headless/lib/browser/headless_browser_context.cc185
-rw-r--r--chromium/headless/lib/browser/headless_browser_context.h71
-rw-r--r--chromium/headless/lib/browser/headless_browser_impl.cc108
-rw-r--r--chromium/headless/lib/browser/headless_browser_impl.h65
-rw-r--r--chromium/headless/lib/browser/headless_browser_main_parts.cc54
-rw-r--r--chromium/headless/lib/browser/headless_browser_main_parts.h44
-rw-r--r--chromium/headless/lib/browser/headless_content_browser_client.cc30
-rw-r--r--chromium/headless/lib/browser/headless_content_browser_client.h32
-rw-r--r--chromium/headless/lib/browser/headless_devtools.cc105
-rw-r--r--chromium/headless/lib/browser/headless_devtools.h24
-rw-r--r--chromium/headless/lib/browser/headless_screen.cc174
-rw-r--r--chromium/headless/lib/browser/headless_screen.h76
-rw-r--r--chromium/headless/lib/browser/headless_url_request_context_getter.cc226
-rw-r--r--chromium/headless/lib/browser/headless_url_request_context_getter.h83
-rw-r--r--chromium/headless/lib/browser/headless_web_contents_impl.cc114
-rw-r--r--chromium/headless/lib/browser/headless_web_contents_impl.h58
17 files changed, 1452 insertions, 0 deletions
diff --git a/chromium/headless/lib/browser/DEPS b/chromium/headless/lib/browser/DEPS
new file mode 100644
index 00000000000..75ab3c75a98
--- /dev/null
+++ b/chromium/headless/lib/browser/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+ui/aura"
+]
diff --git a/chromium/headless/lib/browser/headless_browser_context.cc b/chromium/headless/lib/browser/headless_browser_context.cc
new file mode 100644
index 00000000000..b48f09012e2
--- /dev/null
+++ b/chromium/headless/lib/browser/headless_browser_context.cc
@@ -0,0 +1,185 @@
+// 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/browser/headless_browser_context.h"
+
+#include <memory>
+
+#include "base/path_service.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/resource_context.h"
+#include "content/public/browser/storage_partition.h"
+#include "headless/lib/browser/headless_url_request_context_getter.h"
+#include "net/url_request/url_request_context.h"
+
+namespace headless {
+
+// Contains net::URLRequestContextGetter required for resource loading.
+// Must be destructed on the IO thread as per content::ResourceContext
+// requirements.
+class HeadlessResourceContext : public content::ResourceContext {
+ public:
+ HeadlessResourceContext();
+ ~HeadlessResourceContext() override;
+
+ // ResourceContext implementation:
+ net::HostResolver* GetHostResolver() override;
+ net::URLRequestContext* GetRequestContext() override;
+
+ // Configure the URL request context getter to be used for resource fetching.
+ // Must be called before any of the other methods of this class are used. Must
+ // be called on the browser UI thread.
+ void set_url_request_context_getter(
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ url_request_context_getter_ = std::move(url_request_context_getter);
+ }
+
+ private:
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
+
+ DISALLOW_COPY_AND_ASSIGN(HeadlessResourceContext);
+};
+
+HeadlessResourceContext::HeadlessResourceContext() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+}
+
+HeadlessResourceContext::~HeadlessResourceContext() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+}
+
+net::HostResolver* HeadlessResourceContext::GetHostResolver() {
+ CHECK(url_request_context_getter_);
+ return url_request_context_getter_->GetURLRequestContext()->host_resolver();
+}
+
+net::URLRequestContext* HeadlessResourceContext::GetRequestContext() {
+ CHECK(url_request_context_getter_);
+ return url_request_context_getter_->GetURLRequestContext();
+}
+
+HeadlessBrowserContext::HeadlessBrowserContext(
+ const HeadlessBrowser::Options& options)
+ : resource_context_(new HeadlessResourceContext), options_(options) {
+ InitWhileIOAllowed();
+}
+
+HeadlessBrowserContext::~HeadlessBrowserContext() {
+ if (resource_context_) {
+ content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE,
+ resource_context_.release());
+ }
+}
+
+void HeadlessBrowserContext::InitWhileIOAllowed() {
+ // TODO(skyostil): Allow the embedder to override this.
+ PathService::Get(base::DIR_EXE, &path_);
+ BrowserContext::Initialize(this, path_);
+}
+
+std::unique_ptr<content::ZoomLevelDelegate>
+HeadlessBrowserContext::CreateZoomLevelDelegate(
+ const base::FilePath& partition_path) {
+ return std::unique_ptr<content::ZoomLevelDelegate>();
+}
+
+base::FilePath HeadlessBrowserContext::GetPath() const {
+ return path_;
+}
+
+bool HeadlessBrowserContext::IsOffTheRecord() const {
+ return false;
+}
+
+net::URLRequestContextGetter* HeadlessBrowserContext::GetRequestContext() {
+ return GetDefaultStoragePartition(this)->GetURLRequestContext();
+}
+
+net::URLRequestContextGetter* HeadlessBrowserContext::GetMediaRequestContext() {
+ return GetRequestContext();
+}
+
+net::URLRequestContextGetter*
+HeadlessBrowserContext::GetMediaRequestContextForRenderProcess(
+ int renderer_child_id) {
+ return GetRequestContext();
+}
+
+net::URLRequestContextGetter*
+HeadlessBrowserContext::GetMediaRequestContextForStoragePartition(
+ const base::FilePath& partition_path,
+ bool in_memory) {
+ return GetRequestContext();
+}
+
+content::ResourceContext* HeadlessBrowserContext::GetResourceContext() {
+ return resource_context_.get();
+}
+
+content::DownloadManagerDelegate*
+HeadlessBrowserContext::GetDownloadManagerDelegate() {
+ return nullptr;
+}
+
+content::BrowserPluginGuestManager* HeadlessBrowserContext::GetGuestManager() {
+ // TODO(altimin): Should be non-null? (is null in content/shell).
+ return nullptr;
+}
+
+storage::SpecialStoragePolicy*
+HeadlessBrowserContext::GetSpecialStoragePolicy() {
+ return nullptr;
+}
+
+content::PushMessagingService*
+HeadlessBrowserContext::GetPushMessagingService() {
+ return nullptr;
+}
+
+content::SSLHostStateDelegate*
+HeadlessBrowserContext::GetSSLHostStateDelegate() {
+ return nullptr;
+}
+
+content::PermissionManager* HeadlessBrowserContext::GetPermissionManager() {
+ return nullptr;
+}
+
+content::BackgroundSyncController*
+HeadlessBrowserContext::GetBackgroundSyncController() {
+ return nullptr;
+}
+
+net::URLRequestContextGetter* HeadlessBrowserContext::CreateRequestContext(
+ content::ProtocolHandlerMap* protocol_handlers,
+ content::URLRequestInterceptorScopedVector request_interceptors) {
+ scoped_refptr<HeadlessURLRequestContextGetter> url_request_context_getter(
+ new HeadlessURLRequestContextGetter(
+ false /* ignore_certificate_errors */, GetPath(),
+ content::BrowserThread::GetMessageLoopProxyForThread(
+ content::BrowserThread::IO),
+ content::BrowserThread::GetMessageLoopProxyForThread(
+ content::BrowserThread::FILE),
+ protocol_handlers, std::move(request_interceptors),
+ nullptr /* net_log */, options()));
+ resource_context_->set_url_request_context_getter(url_request_context_getter);
+ return url_request_context_getter.get();
+}
+
+net::URLRequestContextGetter*
+HeadlessBrowserContext::CreateRequestContextForStoragePartition(
+ const base::FilePath& partition_path,
+ bool in_memory,
+ content::ProtocolHandlerMap* protocol_handlers,
+ content::URLRequestInterceptorScopedVector request_interceptors) {
+ return nullptr;
+}
+
+void HeadlessBrowserContext::SetOptionsForTesting(
+ const HeadlessBrowser::Options& options) {
+ options_ = options;
+}
+
+} // namespace headless
diff --git a/chromium/headless/lib/browser/headless_browser_context.h b/chromium/headless/lib/browser/headless_browser_context.h
new file mode 100644
index 00000000000..6fd6676de16
--- /dev/null
+++ b/chromium/headless/lib/browser/headless_browser_context.h
@@ -0,0 +1,71 @@
+// 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_BROWSER_HEADLESS_BROWSER_CONTEXT_H_
+#define HEADLESS_LIB_BROWSER_HEADLESS_BROWSER_CONTEXT_H_
+
+#include <memory>
+
+#include "base/files/file_path.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/resource_context.h"
+#include "headless/lib/browser/headless_url_request_context_getter.h"
+#include "headless/public/headless_browser.h"
+
+namespace headless {
+class HeadlessResourceContext;
+
+class HeadlessBrowserContext : public content::BrowserContext {
+ public:
+ explicit HeadlessBrowserContext(const HeadlessBrowser::Options& options);
+ ~HeadlessBrowserContext() override;
+
+ // BrowserContext implementation:
+ std::unique_ptr<content::ZoomLevelDelegate> CreateZoomLevelDelegate(
+ const base::FilePath& partition_path) override;
+ base::FilePath GetPath() const override;
+ bool IsOffTheRecord() const override;
+ net::URLRequestContextGetter* GetRequestContext() override;
+ net::URLRequestContextGetter* GetMediaRequestContext() override;
+ net::URLRequestContextGetter* GetMediaRequestContextForRenderProcess(
+ int renderer_child_id) override;
+ net::URLRequestContextGetter* GetMediaRequestContextForStoragePartition(
+ const base::FilePath& partition_path,
+ bool in_memory) override;
+ content::ResourceContext* GetResourceContext() override;
+ content::DownloadManagerDelegate* GetDownloadManagerDelegate() override;
+ content::BrowserPluginGuestManager* GetGuestManager() override;
+ storage::SpecialStoragePolicy* GetSpecialStoragePolicy() override;
+ content::PushMessagingService* GetPushMessagingService() override;
+ content::SSLHostStateDelegate* GetSSLHostStateDelegate() override;
+ content::PermissionManager* GetPermissionManager() override;
+ content::BackgroundSyncController* GetBackgroundSyncController() override;
+ net::URLRequestContextGetter* CreateRequestContext(
+ content::ProtocolHandlerMap* protocol_handlers,
+ content::URLRequestInterceptorScopedVector request_interceptors) override;
+ net::URLRequestContextGetter* CreateRequestContextForStoragePartition(
+ const base::FilePath& partition_path,
+ bool in_memory,
+ content::ProtocolHandlerMap* protocol_handlers,
+ content::URLRequestInterceptorScopedVector request_interceptors) override;
+
+ const HeadlessBrowser::Options& options() const { return options_; }
+ void SetOptionsForTesting(const HeadlessBrowser::Options& options);
+
+ private:
+ // Performs initialization of the HeadlessBrowserContext while IO is still
+ // allowed on the current thread.
+ void InitWhileIOAllowed();
+
+ base::FilePath path_;
+ std::unique_ptr<HeadlessResourceContext> resource_context_;
+ HeadlessBrowser::Options options_;
+
+ DISALLOW_COPY_AND_ASSIGN(HeadlessBrowserContext);
+};
+
+} // namespace headless
+
+#endif // HEADLESS_LIB_BROWSER_HEADLESS_BROWSER_CONTEXT_H_
diff --git a/chromium/headless/lib/browser/headless_browser_impl.cc b/chromium/headless/lib/browser/headless_browser_impl.cc
new file mode 100644
index 00000000000..57564d7ddc8
--- /dev/null
+++ b/chromium/headless/lib/browser/headless_browser_impl.cc
@@ -0,0 +1,108 @@
+// 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/browser/headless_browser_impl.h"
+
+#include "base/memory/ptr_util.h"
+#include "base/thread_task_runner_handle.h"
+#include "content/public/app/content_main.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
+#include "headless/lib/browser/headless_browser_context.h"
+#include "headless/lib/browser/headless_browser_main_parts.h"
+#include "headless/lib/browser/headless_web_contents_impl.h"
+#include "headless/lib/headless_content_main_delegate.h"
+#include "ui/aura/env.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace headless {
+
+HeadlessBrowserImpl::HeadlessBrowserImpl(
+ const base::Callback<void(HeadlessBrowser*)>& on_start_callback,
+ const HeadlessBrowser::Options& options)
+ : on_start_callback_(on_start_callback),
+ options_(options),
+ browser_main_parts_(nullptr) {
+ DCHECK(!on_start_callback_.is_null());
+}
+
+HeadlessBrowserImpl::~HeadlessBrowserImpl() {}
+
+std::unique_ptr<HeadlessWebContents> HeadlessBrowserImpl::CreateWebContents(
+ const GURL& initial_url,
+ const gfx::Size& size) {
+ DCHECK(BrowserMainThread()->BelongsToCurrentThread());
+ std::unique_ptr<HeadlessWebContentsImpl> web_contents =
+ base::WrapUnique(new HeadlessWebContentsImpl(
+ browser_context(), window_tree_host_->window(), size));
+ // We require the user to pass in an initial URL to ensure that the renderer
+ // gets initialized and eventually becomes ready to be inspected. See
+ // HeadlessWebContents::Observer::WebContentsReady.
+ if (!web_contents->OpenURL(initial_url))
+ return nullptr;
+ return std::move(web_contents);
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+HeadlessBrowserImpl::BrowserMainThread() const {
+ return content::BrowserThread::GetMessageLoopProxyForThread(
+ content::BrowserThread::UI);
+}
+
+void HeadlessBrowserImpl::Shutdown() {
+ DCHECK(BrowserMainThread()->BelongsToCurrentThread());
+ BrowserMainThread()->PostTask(FROM_HERE,
+ base::MessageLoop::QuitWhenIdleClosure());
+}
+
+HeadlessBrowserContext* HeadlessBrowserImpl::browser_context() const {
+ DCHECK(BrowserMainThread()->BelongsToCurrentThread());
+ DCHECK(browser_main_parts());
+ return browser_main_parts()->browser_context();
+}
+
+HeadlessBrowserMainParts* HeadlessBrowserImpl::browser_main_parts() const {
+ DCHECK(BrowserMainThread()->BelongsToCurrentThread());
+ return browser_main_parts_;
+}
+
+void HeadlessBrowserImpl::set_browser_main_parts(
+ HeadlessBrowserMainParts* browser_main_parts) {
+ DCHECK(!browser_main_parts_);
+ browser_main_parts_ = browser_main_parts;
+}
+
+void HeadlessBrowserImpl::RunOnStartCallback() {
+ DCHECK(aura::Env::GetInstance());
+ window_tree_host_.reset(aura::WindowTreeHost::Create(gfx::Rect()));
+ window_tree_host_->InitHost();
+
+ on_start_callback_.Run(this);
+ on_start_callback_ = base::Callback<void(HeadlessBrowser*)>();
+}
+
+void HeadlessBrowserImpl::SetOptionsForTesting(
+ const HeadlessBrowser::Options& options) {
+ options_ = options;
+ browser_context()->SetOptionsForTesting(options);
+}
+
+int HeadlessBrowserMain(
+ const HeadlessBrowser::Options& options,
+ const base::Callback<void(HeadlessBrowser*)>& on_browser_start_callback) {
+ std::unique_ptr<HeadlessBrowserImpl> browser(
+ new HeadlessBrowserImpl(on_browser_start_callback, options));
+
+ // TODO(skyostil): Implement custom message pumps.
+ DCHECK(!options.message_pump);
+
+ headless::HeadlessContentMainDelegate delegate(std::move(browser));
+ content::ContentMainParams params(&delegate);
+ params.argc = options.argc;
+ params.argv = options.argv;
+ return content::ContentMain(params);
+}
+
+} // namespace headless
diff --git a/chromium/headless/lib/browser/headless_browser_impl.h b/chromium/headless/lib/browser/headless_browser_impl.h
new file mode 100644
index 00000000000..eadeb56b64d
--- /dev/null
+++ b/chromium/headless/lib/browser/headless_browser_impl.h
@@ -0,0 +1,65 @@
+// 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_BROWSER_HEADLESS_BROWSER_IMPL_H_
+#define HEADLESS_LIB_BROWSER_HEADLESS_BROWSER_IMPL_H_
+
+#include "headless/public/headless_browser.h"
+
+#include <memory>
+
+#include "base/synchronization/lock.h"
+#include "headless/lib/browser/headless_web_contents_impl.h"
+
+namespace aura {
+class WindowTreeHost;
+}
+
+namespace headless {
+
+class HeadlessBrowserContext;
+class HeadlessBrowserMainParts;
+
+class HeadlessBrowserImpl : public HeadlessBrowser {
+ public:
+ HeadlessBrowserImpl(
+ const base::Callback<void(HeadlessBrowser*)>& on_start_callback,
+ const HeadlessBrowser::Options& options);
+ ~HeadlessBrowserImpl() override;
+
+ // HeadlessBrowser implementation:
+ std::unique_ptr<HeadlessWebContents> CreateWebContents(
+ const GURL& initial_url,
+ const gfx::Size& size) override;
+ scoped_refptr<base::SingleThreadTaskRunner> BrowserMainThread()
+ const override;
+
+ void Shutdown() override;
+
+ void set_browser_main_parts(HeadlessBrowserMainParts* browser_main_parts);
+ HeadlessBrowserMainParts* browser_main_parts() const;
+
+ HeadlessBrowserContext* browser_context() const;
+
+ void RunOnStartCallback();
+
+ const HeadlessBrowser::Options& options() const { return options_; }
+
+ // Customize the options used by this headless browser instance. Note that
+ // options which take effect before the message loop has been started (e.g.,
+ // custom message pumps) cannot be set via this method.
+ void SetOptionsForTesting(const HeadlessBrowser::Options& options);
+
+ protected:
+ base::Callback<void(HeadlessBrowser*)> on_start_callback_;
+ HeadlessBrowser::Options options_;
+ HeadlessBrowserMainParts* browser_main_parts_; // Not owned.
+ std::unique_ptr<aura::WindowTreeHost> window_tree_host_;
+
+ DISALLOW_COPY_AND_ASSIGN(HeadlessBrowserImpl);
+};
+
+} // namespace headless
+
+#endif // HEADLESS_LIB_BROWSER_HEADLESS_BROWSER_IMPL_H_
diff --git a/chromium/headless/lib/browser/headless_browser_main_parts.cc b/chromium/headless/lib/browser/headless_browser_main_parts.cc
new file mode 100644
index 00000000000..c85ba353244
--- /dev/null
+++ b/chromium/headless/lib/browser/headless_browser_main_parts.cc
@@ -0,0 +1,54 @@
+// 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/browser/headless_browser_main_parts.h"
+
+#include "components/devtools_http_handler/devtools_http_handler.h"
+#include "headless/lib/browser/headless_browser_context.h"
+#include "headless/lib/browser/headless_browser_impl.h"
+#include "headless/lib/browser/headless_devtools.h"
+#include "headless/lib/browser/headless_screen.h"
+#include "ui/aura/env.h"
+#include "ui/gfx/screen.h"
+
+namespace headless {
+
+namespace {
+
+void PlatformInitialize() {
+ HeadlessScreen* screen = HeadlessScreen::Create(gfx::Size());
+ gfx::Screen::SetScreenInstance(screen);
+}
+
+void PlatformExit() {
+ aura::Env::DeleteInstance();
+}
+
+} // namespace
+
+HeadlessBrowserMainParts::HeadlessBrowserMainParts(HeadlessBrowserImpl* browser)
+ : browser_(browser) {}
+
+HeadlessBrowserMainParts::~HeadlessBrowserMainParts() {}
+
+void HeadlessBrowserMainParts::PreMainMessageLoopRun() {
+ browser_context_.reset(new HeadlessBrowserContext(browser_->options()));
+ if (browser_->options().devtools_endpoint.address().IsValid()) {
+ devtools_http_handler_ =
+ CreateLocalDevToolsHttpHandler(browser_context_.get());
+ }
+ PlatformInitialize();
+}
+
+void HeadlessBrowserMainParts::PostMainMessageLoopRun() {
+ browser_context_.reset();
+ devtools_http_handler_.reset();
+ PlatformExit();
+}
+
+HeadlessBrowserContext* HeadlessBrowserMainParts::browser_context() const {
+ return browser_context_.get();
+}
+
+} // namespace headless
diff --git a/chromium/headless/lib/browser/headless_browser_main_parts.h b/chromium/headless/lib/browser/headless_browser_main_parts.h
new file mode 100644
index 00000000000..3b7453ecf9a
--- /dev/null
+++ b/chromium/headless/lib/browser/headless_browser_main_parts.h
@@ -0,0 +1,44 @@
+// 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_BROWSER_HEADLESS_BROWSER_MAIN_PARTS_H_
+#define HEADLESS_LIB_BROWSER_HEADLESS_BROWSER_MAIN_PARTS_H_
+
+#include <memory>
+
+#include "content/public/browser/browser_main_parts.h"
+#include "headless/public/headless_browser.h"
+
+namespace devtools_http_handler {
+class DevToolsHttpHandler;
+}
+
+namespace headless {
+
+class HeadlessBrowserContext;
+class HeadlessBrowserImpl;
+
+class HeadlessBrowserMainParts : public content::BrowserMainParts {
+ public:
+ explicit HeadlessBrowserMainParts(HeadlessBrowserImpl* browser);
+ ~HeadlessBrowserMainParts() override;
+
+ // content::BrowserMainParts implementation:
+ void PreMainMessageLoopRun() override;
+ void PostMainMessageLoopRun() override;
+
+ HeadlessBrowserContext* browser_context() const;
+
+ private:
+ HeadlessBrowserImpl* browser_; // Not owned.
+ std::unique_ptr<HeadlessBrowserContext> browser_context_;
+ std::unique_ptr<devtools_http_handler::DevToolsHttpHandler>
+ devtools_http_handler_;
+
+ DISALLOW_COPY_AND_ASSIGN(HeadlessBrowserMainParts);
+};
+
+} // namespace headless
+
+#endif // HEADLESS_LIB_BROWSER_HEADLESS_BROWSER_MAIN_PARTS_H_
diff --git a/chromium/headless/lib/browser/headless_content_browser_client.cc b/chromium/headless/lib/browser/headless_content_browser_client.cc
new file mode 100644
index 00000000000..a56a1fef4d9
--- /dev/null
+++ b/chromium/headless/lib/browser/headless_content_browser_client.cc
@@ -0,0 +1,30 @@
+// 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/browser/headless_content_browser_client.h"
+
+#include <memory>
+
+#include "base/memory/ptr_util.h"
+#include "content/public/browser/browser_thread.h"
+#include "headless/lib/browser/headless_browser_impl.h"
+#include "headless/lib/browser/headless_browser_main_parts.h"
+
+namespace headless {
+
+HeadlessContentBrowserClient::HeadlessContentBrowserClient(
+ HeadlessBrowserImpl* browser)
+ : browser_(browser) {}
+
+HeadlessContentBrowserClient::~HeadlessContentBrowserClient() {}
+
+content::BrowserMainParts* HeadlessContentBrowserClient::CreateBrowserMainParts(
+ const content::MainFunctionParams&) {
+ std::unique_ptr<HeadlessBrowserMainParts> browser_main_parts =
+ base::WrapUnique(new HeadlessBrowserMainParts(browser_));
+ browser_->set_browser_main_parts(browser_main_parts.get());
+ return browser_main_parts.release();
+}
+
+} // namespace headless
diff --git a/chromium/headless/lib/browser/headless_content_browser_client.h b/chromium/headless/lib/browser/headless_content_browser_client.h
new file mode 100644
index 00000000000..16d9ef300ae
--- /dev/null
+++ b/chromium/headless/lib/browser/headless_content_browser_client.h
@@ -0,0 +1,32 @@
+// 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_BROWSER_HEADLESS_CONTENT_BROWSER_CLIENT_H_
+#define HEADLESS_LIB_BROWSER_HEADLESS_CONTENT_BROWSER_CLIENT_H_
+
+#include "content/public/browser/content_browser_client.h"
+
+namespace headless {
+
+class HeadlessBrowserImpl;
+class HeadlessBrowserMainParts;
+
+class HeadlessContentBrowserClient : public content::ContentBrowserClient {
+ public:
+ explicit HeadlessContentBrowserClient(HeadlessBrowserImpl* browser);
+ ~HeadlessContentBrowserClient() override;
+
+ // content::ContentBrowserClient implementation:
+ content::BrowserMainParts* CreateBrowserMainParts(
+ const content::MainFunctionParams&) override;
+
+ private:
+ HeadlessBrowserImpl* browser_; // Not owned.
+
+ DISALLOW_COPY_AND_ASSIGN(HeadlessContentBrowserClient);
+};
+
+} // namespace headless
+
+#endif // HEADLESS_LIB_BROWSER_HEADLESS_CONTENT_BROWSER_CLIENT_H_
diff --git a/chromium/headless/lib/browser/headless_devtools.cc b/chromium/headless/lib/browser/headless_devtools.cc
new file mode 100644
index 00000000000..5945e3dd4dc
--- /dev/null
+++ b/chromium/headless/lib/browser/headless_devtools.cc
@@ -0,0 +1,105 @@
+// 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/browser/headless_devtools.h"
+
+#include "base/files/file_path.h"
+#include "base/memory/ptr_util.h"
+#include "components/devtools_http_handler/devtools_http_handler.h"
+#include "components/devtools_http_handler/devtools_http_handler_delegate.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/devtools_frontend_host.h"
+#include "content/public/browser/navigation_entry.h"
+#include "headless/grit/headless_lib_resources.h"
+#include "headless/lib/browser/headless_browser_context.h"
+#include "net/base/net_errors.h"
+#include "net/socket/tcp_server_socket.h"
+#include "ui/base/resource/resource_bundle.h"
+
+using devtools_http_handler::DevToolsHttpHandler;
+
+namespace headless {
+
+namespace {
+
+const int kBackLog = 10;
+
+class TCPServerSocketFactory : public DevToolsHttpHandler::ServerSocketFactory {
+ public:
+ TCPServerSocketFactory(const net::IPEndPoint& endpoint)
+ : endpoint_(endpoint) {
+ DCHECK(endpoint_.address().IsValid());
+ }
+
+ private:
+ // DevToolsHttpHandler::ServerSocketFactory implementation:
+ std::unique_ptr<net::ServerSocket> CreateForHttpServer() override {
+ std::unique_ptr<net::ServerSocket> socket(
+ new net::TCPServerSocket(nullptr, net::NetLog::Source()));
+ if (socket->Listen(endpoint_, kBackLog) != net::OK)
+ return std::unique_ptr<net::ServerSocket>();
+
+ return socket;
+ }
+
+ net::IPEndPoint endpoint_;
+
+ DISALLOW_COPY_AND_ASSIGN(TCPServerSocketFactory);
+};
+
+class HeadlessDevToolsDelegate
+ : public devtools_http_handler::DevToolsHttpHandlerDelegate {
+ public:
+ HeadlessDevToolsDelegate();
+ ~HeadlessDevToolsDelegate() override;
+
+ // devtools_http_handler::DevToolsHttpHandlerDelegate implementation:
+ std::string GetDiscoveryPageHTML() override;
+ std::string GetFrontendResource(const std::string& path) override;
+ std::string GetPageThumbnailData(const GURL& url) override;
+ content::DevToolsExternalAgentProxyDelegate* HandleWebSocketConnection(
+ const std::string& path) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HeadlessDevToolsDelegate);
+};
+
+HeadlessDevToolsDelegate::HeadlessDevToolsDelegate() {}
+
+HeadlessDevToolsDelegate::~HeadlessDevToolsDelegate() {}
+
+std::string HeadlessDevToolsDelegate::GetDiscoveryPageHTML() {
+ return ResourceBundle::GetSharedInstance().GetRawDataResource(
+ IDR_HEADLESS_LIB_DEVTOOLS_DISCOVERY_PAGE).as_string();
+}
+
+std::string HeadlessDevToolsDelegate::GetFrontendResource(
+ const std::string& path) {
+ return content::DevToolsFrontendHost::GetFrontendResource(path).as_string();
+}
+
+std::string HeadlessDevToolsDelegate::GetPageThumbnailData(const GURL& url) {
+ return std::string();
+}
+
+content::DevToolsExternalAgentProxyDelegate*
+HeadlessDevToolsDelegate::HandleWebSocketConnection(const std::string& path) {
+ return nullptr;
+}
+
+} // namespace
+
+std::unique_ptr<DevToolsHttpHandler> CreateLocalDevToolsHttpHandler(
+ HeadlessBrowserContext* browser_context) {
+ const net::IPEndPoint& endpoint =
+ browser_context->options().devtools_endpoint;
+ std::unique_ptr<DevToolsHttpHandler::ServerSocketFactory> socket_factory(
+ new TCPServerSocketFactory(endpoint));
+ return base::WrapUnique(new DevToolsHttpHandler(
+ std::move(socket_factory), std::string(), new HeadlessDevToolsDelegate(),
+ browser_context->GetPath(), base::FilePath(), std::string(),
+ browser_context->options().user_agent));
+}
+
+} // namespace headless
diff --git a/chromium/headless/lib/browser/headless_devtools.h b/chromium/headless/lib/browser/headless_devtools.h
new file mode 100644
index 00000000000..f4f303a4650
--- /dev/null
+++ b/chromium/headless/lib/browser/headless_devtools.h
@@ -0,0 +1,24 @@
+// 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_BROWSER_HEADLESS_DEVTOOLS_H_
+#define HEADLESS_LIB_BROWSER_HEADLESS_DEVTOOLS_H_
+
+#include <memory>
+
+namespace devtools_http_handler {
+class DevToolsHttpHandler;
+}
+
+namespace headless {
+class HeadlessBrowserContext;
+
+// Starts a DevTools HTTP handler on the loopback interface on the port
+// configured by HeadlessBrowser::Options.
+std::unique_ptr<devtools_http_handler::DevToolsHttpHandler>
+CreateLocalDevToolsHttpHandler(HeadlessBrowserContext* browser_context);
+
+} // namespace content
+
+#endif // HEADLESS_LIB_BROWSER_HEADLESS_DEVTOOLS_H_
diff --git a/chromium/headless/lib/browser/headless_screen.cc b/chromium/headless/lib/browser/headless_screen.cc
new file mode 100644
index 00000000000..6d6f6074c73
--- /dev/null
+++ b/chromium/headless/lib/browser/headless_screen.cc
@@ -0,0 +1,174 @@
+// 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_screen.h"
+
+#include <stdint.h>
+
+#include "base/logging.h"
+#include "ui/aura/env.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/base/ime/input_method.h"
+#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/geometry/size_conversions.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/screen.h"
+
+namespace headless {
+
+namespace {
+
+bool IsRotationPortrait(gfx::Display::Rotation rotation) {
+ return rotation == gfx::Display::ROTATE_90 ||
+ rotation == gfx::Display::ROTATE_270;
+}
+
+} // namespace
+
+// static
+HeadlessScreen* HeadlessScreen::Create(const gfx::Size& size) {
+ const gfx::Size kDefaultSize(800, 600);
+ return new HeadlessScreen(gfx::Rect(size.IsEmpty() ? kDefaultSize : size));
+}
+
+HeadlessScreen::~HeadlessScreen() {}
+
+aura::WindowTreeHost* HeadlessScreen::CreateHostForPrimaryDisplay() {
+ DCHECK(!host_);
+ host_ = aura::WindowTreeHost::Create(gfx::Rect(display_.GetSizeInPixel()));
+ // Some tests don't correctly manage window focus/activation states.
+ // Makes sure InputMethod is default focused so that IME basics can work.
+ host_->GetInputMethod()->OnFocus();
+ host_->window()->AddObserver(this);
+ host_->InitHost();
+ return host_;
+}
+
+void HeadlessScreen::SetDeviceScaleFactor(float device_scale_factor) {
+ gfx::Rect bounds_in_pixel(display_.GetSizeInPixel());
+ display_.SetScaleAndBounds(device_scale_factor, bounds_in_pixel);
+}
+
+void HeadlessScreen::SetDisplayRotation(gfx::Display::Rotation rotation) {
+ gfx::Rect bounds_in_pixel(display_.GetSizeInPixel());
+ gfx::Rect new_bounds(bounds_in_pixel);
+ if (IsRotationPortrait(rotation) != IsRotationPortrait(display_.rotation())) {
+ new_bounds.set_width(bounds_in_pixel.height());
+ new_bounds.set_height(bounds_in_pixel.width());
+ }
+ display_.set_rotation(rotation);
+ display_.SetScaleAndBounds(display_.device_scale_factor(), new_bounds);
+ host_->SetRootTransform(GetRotationTransform() * GetUIScaleTransform());
+}
+
+void HeadlessScreen::SetUIScale(float ui_scale) {
+ ui_scale_ = ui_scale;
+ gfx::Rect bounds_in_pixel(display_.GetSizeInPixel());
+ gfx::Rect new_bounds = gfx::ToNearestRect(
+ gfx::ScaleRect(gfx::RectF(bounds_in_pixel), 1.0f / ui_scale));
+ display_.SetScaleAndBounds(display_.device_scale_factor(), new_bounds);
+ host_->SetRootTransform(GetRotationTransform() * GetUIScaleTransform());
+}
+
+void HeadlessScreen::SetWorkAreaInsets(const gfx::Insets& insets) {
+ display_.UpdateWorkAreaFromInsets(insets);
+}
+
+gfx::Transform HeadlessScreen::GetRotationTransform() const {
+ gfx::Transform rotate;
+ switch (display_.rotation()) {
+ case gfx::Display::ROTATE_0:
+ break;
+ case gfx::Display::ROTATE_90:
+ rotate.Translate(display_.bounds().height(), 0);
+ rotate.Rotate(90);
+ break;
+ case gfx::Display::ROTATE_270:
+ rotate.Translate(0, display_.bounds().width());
+ rotate.Rotate(270);
+ break;
+ case gfx::Display::ROTATE_180:
+ rotate.Translate(display_.bounds().width(), display_.bounds().height());
+ rotate.Rotate(180);
+ break;
+ }
+
+ return rotate;
+}
+
+gfx::Transform HeadlessScreen::GetUIScaleTransform() const {
+ gfx::Transform ui_scale;
+ ui_scale.Scale(1.0f / ui_scale_, 1.0f / ui_scale_);
+ return ui_scale;
+}
+
+void HeadlessScreen::OnWindowBoundsChanged(aura::Window* window,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) {
+ DCHECK_EQ(host_->window(), window);
+ display_.SetSize(gfx::ScaleToFlooredSize(new_bounds.size(),
+ display_.device_scale_factor()));
+}
+
+void HeadlessScreen::OnWindowDestroying(aura::Window* window) {
+ if (host_->window() == window)
+ host_ = NULL;
+}
+
+gfx::Point HeadlessScreen::GetCursorScreenPoint() {
+ return aura::Env::GetInstance()->last_mouse_location();
+}
+
+gfx::NativeWindow HeadlessScreen::GetWindowUnderCursor() {
+ return GetWindowAtScreenPoint(GetCursorScreenPoint());
+}
+
+gfx::NativeWindow HeadlessScreen::GetWindowAtScreenPoint(
+ const gfx::Point& point) {
+ if (!host_ || !host_->window())
+ return nullptr;
+ return host_->window()->GetTopWindowContainingPoint(point);
+}
+
+int HeadlessScreen::GetNumDisplays() const {
+ return 1;
+}
+
+std::vector<gfx::Display> HeadlessScreen::GetAllDisplays() const {
+ return std::vector<gfx::Display>(1, display_);
+}
+
+gfx::Display HeadlessScreen::GetDisplayNearestWindow(
+ gfx::NativeWindow window) const {
+ return display_;
+}
+
+gfx::Display HeadlessScreen::GetDisplayNearestPoint(
+ const gfx::Point& point) const {
+ return display_;
+}
+
+gfx::Display HeadlessScreen::GetDisplayMatching(
+ const gfx::Rect& match_rect) const {
+ return display_;
+}
+
+gfx::Display HeadlessScreen::GetPrimaryDisplay() const {
+ return display_;
+}
+
+void HeadlessScreen::AddObserver(gfx::DisplayObserver* observer) {}
+
+void HeadlessScreen::RemoveObserver(gfx::DisplayObserver* observer) {}
+
+HeadlessScreen::HeadlessScreen(const gfx::Rect& screen_bounds)
+ : host_(NULL), ui_scale_(1.0f) {
+ static int64_t synthesized_display_id = 2000;
+ display_.set_id(synthesized_display_id++);
+ display_.SetScaleAndBounds(1.0f, screen_bounds);
+}
+
+} // namespace headless
diff --git a/chromium/headless/lib/browser/headless_screen.h b/chromium/headless/lib/browser/headless_screen.h
new file mode 100644
index 00000000000..c6b6b3be01b
--- /dev/null
+++ b/chromium/headless/lib/browser/headless_screen.h
@@ -0,0 +1,76 @@
+// 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_SCREEN_H_
+#define HEADLESS_LIB_BROWSER_HEADLESS_SCREEN_H_
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "ui/aura/window_observer.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/screen.h"
+
+namespace gfx {
+class Insets;
+class Rect;
+class Transform;
+}
+
+namespace aura {
+class Window;
+class WindowTreeHost;
+}
+
+namespace headless {
+
+class HeadlessScreen : public gfx::Screen, public aura::WindowObserver {
+ public:
+ // Creates a gfx::Screen of the specified size. If no size is specified, then
+ // creates a 800x600 screen. |size| is in physical pixels.
+ static HeadlessScreen* Create(const gfx::Size& size);
+ ~HeadlessScreen() override;
+
+ aura::WindowTreeHost* CreateHostForPrimaryDisplay();
+
+ void SetDeviceScaleFactor(float device_scale_fator);
+ void SetDisplayRotation(gfx::Display::Rotation rotation);
+ void SetUIScale(float ui_scale);
+ void SetWorkAreaInsets(const gfx::Insets& insets);
+
+ protected:
+ gfx::Transform GetRotationTransform() const;
+ gfx::Transform GetUIScaleTransform() const;
+
+ // WindowObserver overrides:
+ void OnWindowBoundsChanged(aura::Window* window,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) override;
+ void OnWindowDestroying(aura::Window* window) override;
+
+ // gfx::Screen overrides:
+ gfx::Point GetCursorScreenPoint() override;
+ gfx::NativeWindow GetWindowUnderCursor() override;
+ gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) override;
+ int GetNumDisplays() const override;
+ std::vector<gfx::Display> GetAllDisplays() const override;
+ gfx::Display GetDisplayNearestWindow(gfx::NativeView view) const override;
+ gfx::Display GetDisplayNearestPoint(const gfx::Point& point) const override;
+ gfx::Display GetDisplayMatching(const gfx::Rect& match_rect) const override;
+ gfx::Display GetPrimaryDisplay() const override;
+ void AddObserver(gfx::DisplayObserver* observer) override;
+ void RemoveObserver(gfx::DisplayObserver* observer) override;
+
+ private:
+ explicit HeadlessScreen(const gfx::Rect& screen_bounds);
+
+ aura::WindowTreeHost* host_;
+ gfx::Display display_;
+ float ui_scale_;
+
+ DISALLOW_COPY_AND_ASSIGN(HeadlessScreen);
+};
+
+} // namespace headless
+
+#endif // HEADLESS_LIB_BROWSER_HEADLESS_SCREEN_H_
diff --git a/chromium/headless/lib/browser/headless_url_request_context_getter.cc b/chromium/headless/lib/browser/headless_url_request_context_getter.cc
new file mode 100644
index 00000000000..1a46e1064a1
--- /dev/null
+++ b/chromium/headless/lib/browser/headless_url_request_context_getter.cc
@@ -0,0 +1,226 @@
+// 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_url_request_context_getter.h"
+
+#include <memory>
+
+#include "base/command_line.h"
+#include "base/memory/ptr_util.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/worker_pool.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/cookie_store_factory.h"
+#include "content/public/common/content_switches.h"
+#include "net/cert/cert_verifier.h"
+#include "net/cookies/cookie_store.h"
+#include "net/dns/host_resolver.h"
+#include "net/dns/mapped_host_resolver.h"
+#include "net/http/http_auth_handler_factory.h"
+#include "net/http/http_cache.h"
+#include "net/http/http_network_session.h"
+#include "net/http/http_server_properties_impl.h"
+#include "net/http/transport_security_state.h"
+#include "net/proxy/proxy_service.h"
+#include "net/ssl/channel_id_service.h"
+#include "net/ssl/default_channel_id_store.h"
+#include "net/ssl/ssl_config_service_defaults.h"
+#include "net/url_request/data_protocol_handler.h"
+#include "net/url_request/file_protocol_handler.h"
+#include "net/url_request/static_http_user_agent_settings.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_storage.h"
+#include "net/url_request/url_request_intercepting_job_factory.h"
+#include "net/url_request/url_request_job_factory_impl.h"
+
+namespace headless {
+
+namespace {
+
+void InstallProtocolHandlers(net::URLRequestJobFactoryImpl* job_factory,
+ content::ProtocolHandlerMap* protocol_handlers) {
+ for (content::ProtocolHandlerMap::iterator it = protocol_handlers->begin();
+ it != protocol_handlers->end(); ++it) {
+ bool set_protocol = job_factory->SetProtocolHandler(
+ it->first, base::WrapUnique(it->second.release()));
+ DCHECK(set_protocol);
+ }
+ protocol_handlers->clear();
+}
+
+} // namespace
+
+HeadlessURLRequestContextGetter::HeadlessURLRequestContextGetter(
+ bool ignore_certificate_errors,
+ const base::FilePath& base_path,
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> file_task_runner,
+ content::ProtocolHandlerMap* protocol_handlers,
+ content::URLRequestInterceptorScopedVector request_interceptors,
+ net::NetLog* net_log,
+ const HeadlessBrowser::Options& options)
+ : ignore_certificate_errors_(ignore_certificate_errors),
+ base_path_(base_path),
+ io_task_runner_(std::move(io_task_runner)),
+ file_task_runner_(std::move(file_task_runner)),
+ net_log_(net_log),
+ options_(options),
+ request_interceptors_(std::move(request_interceptors)) {
+ // Must first be created on the UI thread.
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ std::swap(protocol_handlers_, *protocol_handlers);
+
+ // We must create the proxy config service on the UI loop on Linux because it
+ // must synchronously run on the glib message loop. This will be passed to
+ // the URLRequestContextStorage on the IO thread in GetURLRequestContext().
+ if (options_.proxy_server.IsEmpty())
+ proxy_config_service_ = GetProxyConfigService();
+}
+
+HeadlessURLRequestContextGetter::~HeadlessURLRequestContextGetter() {}
+
+std::unique_ptr<net::NetworkDelegate>
+HeadlessURLRequestContextGetter::CreateNetworkDelegate() {
+ return nullptr;
+}
+
+std::unique_ptr<net::ProxyConfigService>
+HeadlessURLRequestContextGetter::GetProxyConfigService() {
+ return net::ProxyService::CreateSystemProxyConfigService(io_task_runner_,
+ file_task_runner_);
+}
+
+std::unique_ptr<net::ProxyService>
+HeadlessURLRequestContextGetter::GetProxyService() {
+ if (!options_.proxy_server.IsEmpty())
+ return net::ProxyService::CreateFixed(options_.proxy_server.ToString());
+ return net::ProxyService::CreateUsingSystemProxyResolver(
+ std::move(proxy_config_service_), 0, url_request_context_->net_log());
+}
+
+net::URLRequestContext*
+HeadlessURLRequestContextGetter::GetURLRequestContext() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+ if (!url_request_context_) {
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+
+ url_request_context_.reset(new net::URLRequestContext());
+ url_request_context_->set_net_log(net_log_);
+ network_delegate_ = CreateNetworkDelegate();
+ url_request_context_->set_network_delegate(network_delegate_.get());
+ storage_.reset(
+ new net::URLRequestContextStorage(url_request_context_.get()));
+ storage_->set_cookie_store(
+ content::CreateCookieStore(content::CookieStoreConfig()));
+ storage_->set_channel_id_service(base::WrapUnique(
+ new net::ChannelIDService(new net::DefaultChannelIDStore(nullptr),
+ base::WorkerPool::GetTaskRunner(true))));
+ // TODO(skyostil): Make language settings configurable.
+ storage_->set_http_user_agent_settings(base::WrapUnique(
+ new net::StaticHttpUserAgentSettings("en-us,en", options_.user_agent)));
+
+ std::unique_ptr<net::HostResolver> host_resolver(
+ net::HostResolver::CreateDefaultResolver(
+ url_request_context_->net_log()));
+
+ storage_->set_cert_verifier(net::CertVerifier::CreateDefault());
+ storage_->set_transport_security_state(
+ base::WrapUnique(new net::TransportSecurityState));
+ storage_->set_proxy_service(GetProxyService());
+ storage_->set_ssl_config_service(new net::SSLConfigServiceDefaults);
+ storage_->set_http_auth_handler_factory(
+ net::HttpAuthHandlerFactory::CreateDefault(host_resolver.get()));
+ storage_->set_http_server_properties(
+ base::WrapUnique(new net::HttpServerPropertiesImpl()));
+
+ base::FilePath cache_path = base_path_.Append(FILE_PATH_LITERAL("Cache"));
+ std::unique_ptr<net::HttpCache::DefaultBackend> main_backend(
+ new net::HttpCache::DefaultBackend(
+ net::DISK_CACHE, net::CACHE_BACKEND_DEFAULT, cache_path, 0,
+ content::BrowserThread::GetMessageLoopProxyForThread(
+ content::BrowserThread::CACHE)));
+
+ net::HttpNetworkSession::Params network_session_params;
+ network_session_params.cert_verifier =
+ url_request_context_->cert_verifier();
+ network_session_params.transport_security_state =
+ url_request_context_->transport_security_state();
+ network_session_params.channel_id_service =
+ url_request_context_->channel_id_service();
+ network_session_params.proxy_service =
+ url_request_context_->proxy_service();
+ network_session_params.ssl_config_service =
+ url_request_context_->ssl_config_service();
+ network_session_params.http_auth_handler_factory =
+ url_request_context_->http_auth_handler_factory();
+ network_session_params.http_server_properties =
+ url_request_context_->http_server_properties();
+ network_session_params.net_log = url_request_context_->net_log();
+ network_session_params.ignore_certificate_errors =
+ ignore_certificate_errors_;
+ if (command_line.HasSwitch(switches::kHostResolverRules)) {
+ std::unique_ptr<net::MappedHostResolver> mapped_host_resolver(
+ new net::MappedHostResolver(std::move(host_resolver)));
+ mapped_host_resolver->SetRulesFromString(
+ command_line.GetSwitchValueASCII(switches::kHostResolverRules));
+ host_resolver = std::move(mapped_host_resolver);
+ }
+
+ // Give |storage_| ownership at the end in case it's |mapped_host_resolver|.
+ storage_->set_host_resolver(std::move(host_resolver));
+ network_session_params.host_resolver =
+ url_request_context_->host_resolver();
+
+ storage_->set_http_network_session(
+ base::WrapUnique(new net::HttpNetworkSession(network_session_params)));
+ storage_->set_http_transaction_factory(base::WrapUnique(new net::HttpCache(
+ storage_->http_network_session(), std::move(main_backend),
+ true /* set_up_quic_server_info */)));
+
+ std::unique_ptr<net::URLRequestJobFactoryImpl> job_factory(
+ new net::URLRequestJobFactoryImpl());
+
+ InstallProtocolHandlers(job_factory.get(), &protocol_handlers_);
+ bool set_protocol = job_factory->SetProtocolHandler(
+ url::kDataScheme, base::WrapUnique(new net::DataProtocolHandler));
+ DCHECK(set_protocol);
+ set_protocol = job_factory->SetProtocolHandler(
+ url::kFileScheme,
+ base::WrapUnique(new net::FileProtocolHandler(
+ content::BrowserThread::GetBlockingPool()
+ ->GetTaskRunnerWithShutdownBehavior(
+ base::SequencedWorkerPool::SKIP_ON_SHUTDOWN))));
+ DCHECK(set_protocol);
+
+ // Set up interceptors in the reverse order so that the last inceptor is at
+ // the end of the linked list of job factories.
+ std::unique_ptr<net::URLRequestJobFactory> top_job_factory =
+ std::move(job_factory);
+ for (auto i = request_interceptors_.rbegin();
+ i != request_interceptors_.rend(); ++i) {
+ top_job_factory.reset(new net::URLRequestInterceptingJobFactory(
+ std::move(top_job_factory), base::WrapUnique(*i)));
+ }
+ request_interceptors_.weak_clear();
+ // Save the head of the job factory list at storage_.
+ storage_->set_job_factory(std::move(top_job_factory));
+ }
+
+ return url_request_context_.get();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+HeadlessURLRequestContextGetter::GetNetworkTaskRunner() const {
+ return content::BrowserThread::GetMessageLoopProxyForThread(
+ content::BrowserThread::IO);
+}
+
+net::HostResolver* HeadlessURLRequestContextGetter::host_resolver() const {
+ return url_request_context_->host_resolver();
+}
+
+} // namespace headless
diff --git a/chromium/headless/lib/browser/headless_url_request_context_getter.h b/chromium/headless/lib/browser/headless_url_request_context_getter.h
new file mode 100644
index 00000000000..99340a6cc3c
--- /dev/null
+++ b/chromium/headless/lib/browser/headless_url_request_context_getter.h
@@ -0,0 +1,83 @@
+// 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_BROWSER_HEADLESS_URL_REQUEST_CONTEXT_GETTER_H_
+#define HEADLESS_LIB_BROWSER_HEADLESS_URL_REQUEST_CONTEXT_GETTER_H_
+
+#include <memory>
+
+#include "base/compiler_specific.h"
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/content_browser_client.h"
+#include "headless/public/headless_browser.h"
+#include "net/proxy/proxy_config_service.h"
+#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 {
+
+class HeadlessURLRequestContextGetter : public net::URLRequestContextGetter {
+ public:
+ HeadlessURLRequestContextGetter(
+ bool ignore_certificate_errors,
+ const base::FilePath& base_path,
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> file_task_runner,
+ content::ProtocolHandlerMap* protocol_handlers,
+ content::URLRequestInterceptorScopedVector request_interceptors,
+ net::NetLog* net_log,
+ const HeadlessBrowser::Options& options);
+
+ // net::URLRequestContextGetter implementation:
+ net::URLRequestContext* GetURLRequestContext() override;
+ scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner()
+ const override;
+
+ net::HostResolver* host_resolver() const;
+
+ protected:
+ ~HeadlessURLRequestContextGetter() override;
+
+ std::unique_ptr<net::NetworkDelegate> CreateNetworkDelegate();
+ std::unique_ptr<net::ProxyConfigService> GetProxyConfigService();
+ std::unique_ptr<net::ProxyService> GetProxyService();
+
+ private:
+ bool ignore_certificate_errors_;
+ base::FilePath base_path_;
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
+ net::NetLog* net_log_;
+ HeadlessBrowser::Options options_;
+
+ std::unique_ptr<net::ProxyConfigService> proxy_config_service_;
+ std::unique_ptr<net::NetworkDelegate> network_delegate_;
+ std::unique_ptr<net::URLRequestContextStorage> storage_;
+ std::unique_ptr<net::URLRequestContext> url_request_context_;
+ content::ProtocolHandlerMap protocol_handlers_;
+ content::URLRequestInterceptorScopedVector request_interceptors_;
+
+ DISALLOW_COPY_AND_ASSIGN(HeadlessURLRequestContextGetter);
+};
+
+} // namespace headless
+
+#endif // HEADLESS_LIB_BROWSER_HEADLESS_URL_REQUEST_CONTEXT_GETTER_H_
diff --git a/chromium/headless/lib/browser/headless_web_contents_impl.cc b/chromium/headless/lib/browser/headless_web_contents_impl.cc
new file mode 100644
index 00000000000..f58dfe0671c
--- /dev/null
+++ b/chromium/headless/lib/browser/headless_web_contents_impl.cc
@@ -0,0 +1,114 @@
+// 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/browser/headless_web_contents_impl.h"
+
+#include "base/bind.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/weak_ptr.h"
+#include "base/trace_event/trace_event.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/common/bindings_policy.h"
+#include "content/public/common/service_registry.h"
+#include "content/public/renderer/render_frame.h"
+#include "ui/aura/window.h"
+
+namespace headless {
+
+class WebContentsObserverAdapter : public content::WebContentsObserver {
+ public:
+ WebContentsObserverAdapter(content::WebContents* web_contents,
+ HeadlessWebContents::Observer* observer)
+ : content::WebContentsObserver(web_contents), observer_(observer) {}
+
+ ~WebContentsObserverAdapter() override {}
+
+ void RenderViewReady() override { observer_->WebContentsReady(); }
+
+ void DocumentOnLoadCompletedInMainFrame() override {
+ observer_->DocumentOnLoadCompletedInMainFrame();
+ }
+
+ void DidFinishNavigation(
+ content::NavigationHandle* navigation_handle) override {
+ observer_->DidFinishNavigation(navigation_handle->HasCommitted() &&
+ !navigation_handle->IsErrorPage());
+ }
+
+ private:
+ HeadlessWebContents::Observer* observer_; // Not owned.
+
+ DISALLOW_COPY_AND_ASSIGN(WebContentsObserverAdapter);
+};
+
+class HeadlessWebContentsImpl::Delegate : public content::WebContentsDelegate {
+ public:
+ Delegate() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Delegate);
+};
+
+HeadlessWebContentsImpl::HeadlessWebContentsImpl(
+ content::BrowserContext* browser_context,
+ aura::Window* parent_window,
+ const gfx::Size& initial_size)
+ : web_contents_delegate_(new HeadlessWebContentsImpl::Delegate()) {
+ content::WebContents::CreateParams create_params(browser_context, nullptr);
+ create_params.initial_size = initial_size;
+
+ web_contents_.reset(content::WebContents::Create(create_params));
+ web_contents_->SetDelegate(web_contents_delegate_.get());
+
+ aura::Window* contents = web_contents_->GetNativeView();
+ DCHECK(!parent_window->Contains(contents));
+ parent_window->AddChild(contents);
+ contents->Show();
+
+ contents->SetBounds(gfx::Rect(initial_size));
+ content::RenderWidgetHostView* host_view =
+ web_contents_->GetRenderWidgetHostView();
+ if (host_view)
+ host_view->SetSize(initial_size);
+}
+
+HeadlessWebContentsImpl::~HeadlessWebContentsImpl() {
+ web_contents_->Close();
+}
+
+bool HeadlessWebContentsImpl::OpenURL(const GURL& url) {
+ if (!url.is_valid())
+ return false;
+ content::NavigationController::LoadURLParams params(url);
+ params.transition_type = ui::PageTransitionFromInt(
+ ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
+ web_contents_->GetController().LoadURLWithParams(params);
+ web_contents_->Focus();
+ return true;
+}
+
+void HeadlessWebContentsImpl::AddObserver(Observer* observer) {
+ DCHECK(observer_map_.find(observer) == observer_map_.end());
+ observer_map_[observer] = base::WrapUnique(
+ new WebContentsObserverAdapter(web_contents_.get(), observer));
+}
+
+void HeadlessWebContentsImpl::RemoveObserver(Observer* observer) {
+ ObserverMap::iterator it = observer_map_.find(observer);
+ DCHECK(it != observer_map_.end());
+ observer_map_.erase(it);
+}
+
+content::WebContents* HeadlessWebContentsImpl::web_contents() const {
+ return web_contents_.get();
+}
+
+} // namespace headless
diff --git a/chromium/headless/lib/browser/headless_web_contents_impl.h b/chromium/headless/lib/browser/headless_web_contents_impl.h
new file mode 100644
index 00000000000..e1cdc2d1615
--- /dev/null
+++ b/chromium/headless/lib/browser/headless_web_contents_impl.h
@@ -0,0 +1,58 @@
+// 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_BROWSER_HEADLESS_WEB_CONTENTS_IMPL_H_
+#define HEADLESS_LIB_BROWSER_HEADLESS_WEB_CONTENTS_IMPL_H_
+
+#include "headless/public/headless_web_contents.h"
+
+#include <memory>
+#include <unordered_map>
+
+namespace aura {
+class Window;
+}
+
+namespace content {
+class WebContents;
+class BrowserContext;
+}
+
+namespace gfx {
+class Size;
+}
+
+namespace headless {
+class WebContentsObserverAdapter;
+
+class HeadlessWebContentsImpl : public HeadlessWebContents {
+ public:
+ HeadlessWebContentsImpl(content::BrowserContext* context,
+ aura::Window* parent_window,
+ const gfx::Size& initial_size);
+ ~HeadlessWebContentsImpl() override;
+
+ // HeadlessWebContents implementation:
+ void AddObserver(Observer* observer) override;
+ void RemoveObserver(Observer* observer) override;
+
+ content::WebContents* web_contents() const;
+ bool OpenURL(const GURL& url);
+
+ private:
+ class Delegate;
+ std::unique_ptr<Delegate> web_contents_delegate_;
+ std::unique_ptr<content::WebContents> web_contents_;
+
+ using ObserverMap =
+ std::unordered_map<HeadlessWebContents::Observer*,
+ std::unique_ptr<WebContentsObserverAdapter>>;
+ ObserverMap observer_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(HeadlessWebContentsImpl);
+};
+
+} // namespace headless
+
+#endif // HEADLESS_LIB_BROWSER_HEADLESS_WEB_CONTENTS_IMPL_H_