diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2016-05-09 14:22:11 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2016-05-09 15:11:45 +0000 |
commit | 2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c (patch) | |
tree | e75f511546c5fd1a173e87c1f9fb11d7ac8d1af3 /chromium/headless/lib/browser | |
parent | a4f3d46271c57e8155ba912df46a05559d14726e (diff) | |
download | qtwebengine-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')
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_ |