diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-12-10 16:19:40 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-12-10 16:01:50 +0000 |
commit | 51f6c2793adab2d864b3d2b360000ef8db1d3e92 (patch) | |
tree | 835b3b4446b012c75e80177cef9fbe6972cc7dbe /chromium/headless | |
parent | 6036726eb981b6c4b42047513b9d3f4ac865daac (diff) | |
download | qtwebengine-chromium-51f6c2793adab2d864b3d2b360000ef8db1d3e92.tar.gz |
BASELINE: Update Chromium to 71.0.3578.93
Change-Id: I6a32086c33670e1b033f8b10e6bf1fd4da1d105d
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/headless')
43 files changed, 860 insertions, 854 deletions
diff --git a/chromium/headless/BUILD.gn b/chromium/headless/BUILD.gn index f295efb4166..a3b300a0df8 100644 --- a/chromium/headless/BUILD.gn +++ b/chromium/headless/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/jumbo.gni") import("//build/config/chrome_build.gni") import("//build/util/lastchange.gni") import("//build/util/process_version.gni") @@ -271,8 +272,6 @@ inspector_protocol_generate("protocol_sources") { "lib/browser/protocol/dp_browser.h", "lib/browser/protocol/dp_headless_experimental.cc", "lib/browser/protocol/dp_headless_experimental.h", - "lib/browser/protocol/dp_network.cc", - "lib/browser/protocol/dp_network.h", "lib/browser/protocol/dp_page.cc", "lib/browser/protocol/dp_page.h", "lib/browser/protocol/dp_target.cc", @@ -282,7 +281,7 @@ inspector_protocol_generate("protocol_sources") { ] } -component("headless") { +jumbo_component("headless") { sources = [ "app/headless_shell_switches.cc", "app/headless_shell_switches.h", @@ -303,20 +302,18 @@ component("headless") { "lib/browser/headless_devtools_client_impl.cc", "lib/browser/headless_devtools_manager_delegate.cc", "lib/browser/headless_devtools_manager_delegate.h", - "lib/browser/headless_network_conditions.cc", - "lib/browser/headless_network_conditions.h", "lib/browser/headless_permission_manager.cc", "lib/browser/headless_permission_manager.h", "lib/browser/headless_platform_event_source.cc", "lib/browser/headless_platform_event_source.h", "lib/browser/headless_quota_permission_context.cc", "lib/browser/headless_quota_permission_context.h", + "lib/browser/headless_request_context_manager.cc", + "lib/browser/headless_request_context_manager.h", "lib/browser/headless_resource_dispatcher_host_delegate.cc", "lib/browser/headless_resource_dispatcher_host_delegate.h", "lib/browser/headless_shell_application_mac.h", "lib/browser/headless_shell_application_mac.mm", - "lib/browser/headless_url_request_context_getter.cc", - "lib/browser/headless_url_request_context_getter.h", "lib/browser/headless_window_tree_host.h", "lib/browser/protocol/browser_handler.cc", "lib/browser/protocol/browser_handler.h", @@ -326,8 +323,6 @@ component("headless") { "lib/browser/protocol/headless_devtools_session.h", "lib/browser/protocol/headless_handler.cc", "lib/browser/protocol/headless_handler.h", - "lib/browser/protocol/network_handler.cc", - "lib/browser/protocol/network_handler.h", "lib/browser/protocol/page_handler.cc", "lib/browser/protocol/page_handler.h", "lib/browser/protocol/protocol_string.cc", @@ -382,8 +377,6 @@ component("headless") { sources += [ "lib/browser/headless_print_manager.cc", "lib/browser/headless_print_manager.h", - "lib/renderer/headless_print_render_frame_helper_delegate.cc", - "lib/renderer/headless_print_render_frame_helper_delegate.h", ] } @@ -420,6 +413,10 @@ component("headless") { deps += [ "//components/os_crypt" ] } + if (enable_basic_printing) { + deps += [ "//components/printing/browser" ] + } + if (is_component_build) { sources += [ "lib/browser/headless_content_browser_client.cc", @@ -435,6 +432,13 @@ component("headless") { "lib/utility/headless_content_utility_client.h", ] + if (enable_basic_printing) { + sources += [ + "lib/renderer/headless_print_render_frame_helper_delegate.cc", + "lib/renderer/headless_print_render_frame_helper_delegate.h", + ] + } + deps += [ "//components/crash/core/common:crash_key", "//components/security_state/content", @@ -518,6 +522,13 @@ if (!is_component_build) { "lib/renderer/headless_content_renderer_client.h", ] + if (enable_basic_printing) { + sources += [ + "lib/renderer/headless_print_render_frame_helper_delegate.cc", + "lib/renderer/headless_print_render_frame_helper_delegate.h", + ] + } + deps = [ ":headless", "//components/crash/core/common:crash_key", @@ -804,8 +815,6 @@ if (is_win) { sources = [ "app/headless_shell.cc", "app/headless_shell.h", - "app/headless_shell_switches.cc", - "app/headless_shell_switches.h", "app/headless_shell_win.cc", "public/headless_shell.h", ] @@ -839,19 +848,22 @@ if (is_win) { # Headless library with all included dependencies. Use this library unless you # have browser/child dependencies restrictions. -static_library("headless_shell_lib") { +jumbo_static_library("headless_shell_lib") { sources = [ "app/headless_shell.cc", "app/headless_shell.h", - "app/headless_shell_switches.cc", - "app/headless_shell_switches.h", - "lib/browser/headless_content_browser_client.cc", - "lib/browser/headless_content_browser_client.h", "lib/utility/headless_content_utility_client.cc", "lib/utility/headless_content_utility_client.h", "public/headless_shell.h", ] + if (!is_component_build) { + sources += [ + "lib/browser/headless_content_browser_client.cc", + "lib/browser/headless_content_browser_client.h", + ] + } + deps = [ ":headless_renderer", "//components/security_state/content", @@ -893,6 +905,7 @@ if (is_fuchsia) { fuchsia_package("headless_shell_pkg") { binary = ":headless_shell" package_name_override = "headless_shell" + sandbox_policy = "//build/config/fuchsia/testing_sandbox_policy" } fuchsia_package_runner("headless_shell_fuchsia") { diff --git a/chromium/headless/app/headless_shell.cc b/chromium/headless/app/headless_shell.cc index 244636b6a99..f0e0c9d3e1f 100644 --- a/chromium/headless/app/headless_shell.cc +++ b/chromium/headless/app/headless_shell.cc @@ -409,7 +409,15 @@ void HeadlessShell::InputExpression() { std::stringstream expression; while (true) { int c = fgetc(stdin); - if (c == EOF || c == '\n') { + if (c == '\n') + break; + if (c == EOF) { + // If there's no expression, then quit. + if (expression.str().size() == 0) { + printf("\n"); + Shutdown(); + return; + } break; } expression << static_cast<char>(c); @@ -713,11 +721,6 @@ int HeadlessShellMain(int argc, const char** argv) { builder.SetProxyConfig(std::move(proxy_config)); } - if (command_line.HasSwitch(::network::switches::kHostResolverRules)) { - builder.SetHostResolverRules(command_line.GetSwitchValueASCII( - ::network::switches::kHostResolverRules)); - } - if (command_line.HasSwitch(switches::kUseGL)) { builder.SetGLImplementation( command_line.GetSwitchValueASCII(switches::kUseGL)); diff --git a/chromium/headless/app/headless_shell_switches.h b/chromium/headless/app/headless_shell_switches.h index 32166fd0fe0..e00256b2f3a 100644 --- a/chromium/headless/app/headless_shell_switches.h +++ b/chromium/headless/app/headless_shell_switches.h @@ -6,35 +6,36 @@ #define HEADLESS_APP_HEADLESS_SHELL_SWITCHES_H_ #include "content/public/common/content_switches.h" +#include "headless/public/headless_export.h" namespace headless { namespace switches { -extern const char kCrashDumpsDir[]; -extern const char kDefaultBackgroundColor[]; -extern const char kDeterministicMode[]; -extern const char kDisableCrashReporter[]; -extern const char kDumpDom[]; -extern const char kEnableBeginFrameControl[]; -extern const char kEnableCrashReporter[]; -extern const char kHideScrollbars[]; -extern const char kPasswordStore[]; -extern const char kPrintToPDF[]; -extern const char kProxyBypassList[]; -extern const char kProxyServer[]; -extern const char kRemoteDebuggingAddress[]; -extern const char kRepl[]; -extern const char kScreenshot[]; -extern const char kSSLKeyLogFile[]; -extern const char kTimeout[]; -extern const char kUseGL[]; -extern const char kUserAgent[]; -extern const char kUserDataDir[]; -extern const char kVirtualTimeBudget[]; -extern const char kWindowSize[]; -extern const char kAuthServerWhitelist[]; -extern const char kFontRenderHinting[]; -extern const char kBlockNewWebContents[]; +HEADLESS_EXPORT extern const char kCrashDumpsDir[]; +HEADLESS_EXPORT extern const char kDefaultBackgroundColor[]; +HEADLESS_EXPORT extern const char kDeterministicMode[]; +HEADLESS_EXPORT extern const char kDisableCrashReporter[]; +HEADLESS_EXPORT extern const char kDumpDom[]; +HEADLESS_EXPORT extern const char kEnableBeginFrameControl[]; +HEADLESS_EXPORT extern const char kEnableCrashReporter[]; +HEADLESS_EXPORT extern const char kHideScrollbars[]; +HEADLESS_EXPORT extern const char kPasswordStore[]; +HEADLESS_EXPORT extern const char kPrintToPDF[]; +HEADLESS_EXPORT extern const char kProxyBypassList[]; +HEADLESS_EXPORT extern const char kProxyServer[]; +HEADLESS_EXPORT extern const char kRemoteDebuggingAddress[]; +HEADLESS_EXPORT extern const char kRepl[]; +HEADLESS_EXPORT extern const char kScreenshot[]; +HEADLESS_EXPORT extern const char kSSLKeyLogFile[]; +HEADLESS_EXPORT extern const char kTimeout[]; +HEADLESS_EXPORT extern const char kUseGL[]; +HEADLESS_EXPORT extern const char kUserAgent[]; +HEADLESS_EXPORT extern const char kUserDataDir[]; +HEADLESS_EXPORT extern const char kVirtualTimeBudget[]; +HEADLESS_EXPORT extern const char kWindowSize[]; +HEADLESS_EXPORT extern const char kAuthServerWhitelist[]; +HEADLESS_EXPORT extern const char kFontRenderHinting[]; +HEADLESS_EXPORT extern const char kBlockNewWebContents[]; // Switches which are replicated from content. using ::switches::kRemoteDebuggingPort; diff --git a/chromium/headless/lib/browser/DEPS b/chromium/headless/lib/browser/DEPS index f20dffe78f0..a8066900276 100644 --- a/chromium/headless/lib/browser/DEPS +++ b/chromium/headless/lib/browser/DEPS @@ -5,6 +5,7 @@ include_rules = [ "+components/security_state", "+components/viz", "+printing", + "+services/network", "+storage/browser/quota", "+storage/common/quota", "+third_party/skia/include", diff --git a/chromium/headless/lib/browser/devtools_api/domain_type_conversions_h.template b/chromium/headless/lib/browser/devtools_api/domain_type_conversions_h.template index 913854048f0..5c02c6fee5f 100644 --- a/chromium/headless/lib/browser/devtools_api/domain_type_conversions_h.template +++ b/chromium/headless/lib/browser/devtools_api/domain_type_conversions_h.template @@ -34,8 +34,8 @@ struct FromValue<{{namespace}}::{{type.id}}> { } }; -template <typename T> -std::unique_ptr<base::Value> ToValueImpl(const {{namespace}}::{{type.id}}& value, T*) { +template <> +inline std::unique_ptr<base::Value> ToValue(const {{namespace}}::{{type.id}}& value) { switch (value) { {% for literal in type.enum %} case {{namespace}}::{{type.id}}::{{literal | sanitize_literal | dash_to_camelcase | camelcase_to_hacker_style | upper }}: @@ -56,8 +56,8 @@ struct FromValue<{{namespace}}::{{type.id}}> { } }; -template <typename T> -std::unique_ptr<base::Value> ToValueImpl(const {{namespace}}::{{type.id}}& value, T*) { +template <> +inline std::unique_ptr<base::Value> ToValue(const {{namespace}}::{{type.id}}& value) { return value.Serialize(); } diff --git a/chromium/headless/lib/browser/devtools_api/domain_types_cc.template b/chromium/headless/lib/browser/devtools_api/domain_types_cc.template index be125aeb835..e87e338d376 100644 --- a/chromium/headless/lib/browser/devtools_api/domain_types_cc.template +++ b/chromium/headless/lib/browser/devtools_api/domain_types_cc.template @@ -15,15 +15,6 @@ namespace headless { -namespace internal { - -template <typename T> -std::unique_ptr<base::Value> ToValue(const T& value) { - return ToValueImpl(value, static_cast<T*>(nullptr)); -} - -} // namespace internal - namespace {{domain.domain | camelcase_to_hacker_style}} { {% for type in domain.types %} {% if not (type.type == "object") or not ("properties" in type) %}{% continue %}{% endif %} diff --git a/chromium/headless/lib/browser/headless_browser_context_impl.cc b/chromium/headless/lib/browser/headless_browser_context_impl.cc index 0e59b9c8cc2..6ded70eb106 100644 --- a/chromium/headless/lib/browser/headless_browser_context_impl.cc +++ b/chromium/headless/lib/browser/headless_browser_context_impl.cc @@ -11,74 +11,35 @@ #include "base/guid.h" #include "base/path_service.h" +#include "base/task/post_task.h" +#include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/resource_context.h" #include "content/public/browser/storage_partition.h" #include "headless/grit/headless_lib_resources.h" #include "headless/lib/browser/headless_browser_context_options.h" #include "headless/lib/browser/headless_browser_impl.h" #include "headless/lib/browser/headless_browser_main_parts.h" #include "headless/lib/browser/headless_permission_manager.h" -#include "headless/lib/browser/headless_url_request_context_getter.h" -#include "net/log/net_log.h" +#include "headless/lib/browser/headless_web_contents_impl.h" #include "net/url_request/url_request_context.h" #include "ui/base/resource/resource_bundle.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::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); - } - - net::URLRequestContextGetter* url_request_context_getter() { - return url_request_context_getter_.get(); - } - - 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::URLRequestContext* HeadlessResourceContext::GetRequestContext() { - CHECK(url_request_context_getter_); - return url_request_context_getter_->GetURLRequestContext(); -} - HeadlessBrowserContextImpl::HeadlessBrowserContextImpl( HeadlessBrowserImpl* browser, std::unique_ptr<HeadlessBrowserContextOptions> context_options) : browser_(browser), context_options_(std::move(context_options)), - resource_context_(std::make_unique<HeadlessResourceContext>()), permission_controller_delegate_( - std::make_unique<HeadlessPermissionManager>(this)), - net_log_(new net::NetLog()) { + std::make_unique<HeadlessPermissionManager>(this)) { InitWhileIOAllowed(); + base::FilePath user_data_path = + IsOffTheRecord() || context_options_->user_data_dir().empty() + ? base::FilePath() + : path_; + request_context_manager_ = std::make_unique<HeadlessRequestContextManager>( + context_options_.get(), user_data_path); } HeadlessBrowserContextImpl::~HeadlessBrowserContextImpl() { @@ -88,22 +49,12 @@ HeadlessBrowserContextImpl::~HeadlessBrowserContextImpl() { // Destroy all web contents before shutting down storage partitions. web_contents_map_.clear(); - if (resource_context_) { + if (request_context_manager_) { content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE, - resource_context_.release()); + request_context_manager_.release()); } - content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE, - net_log_.release()); ShutdownStoragePartitions(); - - if (url_request_getter_) { - content::BrowserThread::PostTask( - content::BrowserThread::IO, FROM_HERE, - base::BindOnce( - &HeadlessURLRequestContextGetter::NotifyContextShuttingDown, - url_request_getter_)); - } } // static @@ -222,7 +173,7 @@ bool HeadlessBrowserContextImpl::IsOffTheRecord() const { } content::ResourceContext* HeadlessBrowserContextImpl::GetResourceContext() { - return resource_context_.get(); + return request_context_manager_->GetResourceContext(); } content::DownloadManagerDelegate* @@ -274,14 +225,8 @@ HeadlessBrowserContextImpl::GetBrowsingDataRemoverDelegate() { net::URLRequestContextGetter* HeadlessBrowserContextImpl::CreateRequestContext( content::ProtocolHandlerMap* protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors) { - url_request_getter_ = base::MakeRefCounted<HeadlessURLRequestContextGetter>( - content::BrowserThread::GetTaskRunnerForThread( - content::BrowserThread::IO), - protocol_handlers, context_options_->TakeProtocolHandlers(), - std::move(request_interceptors), context_options_.get(), net_log_.get(), - this); - resource_context_->set_url_request_context_getter(url_request_getter_); - return url_request_getter_.get(); + return request_context_manager_->CreateRequestContext( + protocol_handlers, std::move(request_interceptors)); } net::URLRequestContextGetter* @@ -295,7 +240,7 @@ HeadlessBrowserContextImpl::CreateRequestContextForStoragePartition( net::URLRequestContextGetter* HeadlessBrowserContextImpl::CreateMediaRequestContext() { - return resource_context_->url_request_context_getter(); + return request_context_manager_->url_request_context_getter(); } net::URLRequestContextGetter* @@ -359,13 +304,12 @@ const std::string& HeadlessBrowserContextImpl::Id() const { return UniqueId(); } -void HeadlessBrowserContextImpl::SetNetworkConditions( - HeadlessNetworkConditions conditions) { - network_conditions_ = conditions; -} - -HeadlessNetworkConditions HeadlessBrowserContextImpl::GetNetworkConditions() { - return network_conditions_; +::network::mojom::NetworkContextPtr +HeadlessBrowserContextImpl::CreateNetworkContext( + bool in_memory, + const base::FilePath& relative_partition_path) { + return request_context_manager_->CreateNetworkContext( + in_memory, relative_partition_path); } HeadlessBrowserContext::Builder::Builder(HeadlessBrowserImpl* browser) @@ -410,13 +354,6 @@ HeadlessBrowserContext::Builder::SetProxyConfig( return *this; } -HeadlessBrowserContext::Builder& -HeadlessBrowserContext::Builder::SetHostResolverRules( - const std::string& host_resolver_rules) { - options_->host_resolver_rules_ = host_resolver_rules; - return *this; -} - HeadlessBrowserContext::Builder& HeadlessBrowserContext::Builder::SetWindowSize( const gfx::Size& window_size) { options_->window_size_ = window_size; diff --git a/chromium/headless/lib/browser/headless_browser_context_impl.h b/chromium/headless/lib/browser/headless_browser_context_impl.h index d192b101783..35deb9a904d 100644 --- a/chromium/headless/lib/browser/headless_browser_context_impl.h +++ b/chromium/headless/lib/browser/headless_browser_context_impl.h @@ -16,19 +16,13 @@ #include "content/public/browser/global_routing_id.h" #include "content/public/browser/resource_context.h" #include "headless/lib/browser/headless_browser_context_options.h" -#include "headless/lib/browser/headless_network_conditions.h" -#include "headless/lib/browser/headless_url_request_context_getter.h" +#include "headless/lib/browser/headless_request_context_manager.h" #include "headless/public/headless_browser.h" #include "headless/public/headless_browser_context.h" #include "headless/public/headless_export.h" -namespace net { -class NetLog; -} - namespace headless { class HeadlessBrowserImpl; -class HeadlessResourceContext; class HeadlessWebContentsImpl; class HEADLESS_EXPORT HeadlessBrowserContextImpl final @@ -71,7 +65,7 @@ class HEADLESS_EXPORT HeadlessBrowserContextImpl final content::ResourceContext* GetResourceContext() override; content::DownloadManagerDelegate* GetDownloadManagerDelegate() override; content::BrowserPluginGuestManager* GetGuestManager() override; - storage::SpecialStoragePolicy* GetSpecialStoragePolicy() override; + ::storage::SpecialStoragePolicy* GetSpecialStoragePolicy() override; content::PushMessagingService* GetPushMessagingService() override; content::SSLHostStateDelegate* GetSSLHostStateDelegate() override; content::PermissionControllerDelegate* GetPermissionControllerDelegate() @@ -114,8 +108,9 @@ class HEADLESS_EXPORT HeadlessBrowserContextImpl final const base::UnguessableToken* GetDevToolsFrameTokenForFrameTreeNodeId( int frame_tree_node_id) const; - void SetNetworkConditions(HeadlessNetworkConditions conditions); - HeadlessNetworkConditions GetNetworkConditions() override; + ::network::mojom::NetworkContextPtr CreateNetworkContext( + bool in_memory, + const base::FilePath& relative_partition_path); private: HeadlessBrowserContextImpl( @@ -128,8 +123,6 @@ class HEADLESS_EXPORT HeadlessBrowserContextImpl final HeadlessBrowserImpl* browser_; // Not owned. std::unique_ptr<HeadlessBrowserContextOptions> context_options_; - std::unique_ptr<HeadlessResourceContext> resource_context_; - scoped_refptr<HeadlessURLRequestContextGetter> url_request_getter_; base::FilePath path_; std::unordered_map<std::string, std::unique_ptr<HeadlessWebContents>> @@ -147,9 +140,8 @@ class HEADLESS_EXPORT HeadlessBrowserContextImpl final std::unique_ptr<content::PermissionControllerDelegate> permission_controller_delegate_; - std::unique_ptr<net::NetLog> net_log_; - HeadlessNetworkConditions network_conditions_; + std::unique_ptr<HeadlessRequestContextManager> request_context_manager_; DISALLOW_COPY_AND_ASSIGN(HeadlessBrowserContextImpl); }; diff --git a/chromium/headless/lib/browser/headless_browser_context_options.cc b/chromium/headless/lib/browser/headless_browser_context_options.cc index aedbb0ac501..e3ab688858b 100644 --- a/chromium/headless/lib/browser/headless_browser_context_options.cc +++ b/chromium/headless/lib/browser/headless_browser_context_options.cc @@ -52,11 +52,6 @@ const net::ProxyConfig* HeadlessBrowserContextOptions::proxy_config() const { return browser_options_->proxy_config.get(); } -const std::string& HeadlessBrowserContextOptions::host_resolver_rules() const { - return ReturnOverriddenValue(host_resolver_rules_, - browser_options_->host_resolver_rules); -} - const gfx::Size& HeadlessBrowserContextOptions::window_size() const { return ReturnOverriddenValue(window_size_, browser_options_->window_size); } diff --git a/chromium/headless/lib/browser/headless_browser_context_options.h b/chromium/headless/lib/browser/headless_browser_context_options.h index a8f3b098903..441f884ba9f 100644 --- a/chromium/headless/lib/browser/headless_browser_context_options.h +++ b/chromium/headless/lib/browser/headless_browser_context_options.h @@ -34,9 +34,6 @@ class HeadlessBrowserContextOptions { // See HeadlessBrowser::Options::proxy_config. const net::ProxyConfig* proxy_config() const; - // See HeadlessBrowser::Options::host_resolver_rules. - const std::string& host_resolver_rules() const; - const gfx::Size& window_size() const; // See HeadlessBrowser::Options::user_data_dir. diff --git a/chromium/headless/lib/browser/headless_browser_impl.cc b/chromium/headless/lib/browser/headless_browser_impl.cc index c4e508b9ecc..93956145520 100644 --- a/chromium/headless/lib/browser/headless_browser_impl.cc +++ b/chromium/headless/lib/browser/headless_browser_impl.cc @@ -12,11 +12,12 @@ #include "base/command_line.h" #include "base/memory/ptr_util.h" #include "base/run_loop.h" +#include "base/task/post_task.h" #include "base/threading/thread_task_runner_handle.h" #include "content/public/app/content_main.h" +#include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/devtools_agent_host.h" -#include "content/public/browser/web_contents.h" #include "content/public/common/content_switches.h" #include "headless/app/headless_shell_switches.h" #include "headless/lib/browser/headless_browser_context_impl.h" @@ -24,23 +25,14 @@ #include "headless/lib/browser/headless_devtools_agent_host_client.h" #include "headless/lib/browser/headless_web_contents_impl.h" #include "headless/lib/headless_content_main_delegate.h" -#include "headless/public/internal/headless_devtools_client_impl.h" #include "net/http/http_util.h" #include "services/network/public/cpp/network_switches.h" -#include "ui/aura/client/focus_client.h" -#include "ui/aura/env.h" -#include "ui/aura/window.h" #include "ui/events/devices/device_data_manager.h" -#include "ui/gfx/geometry/size.h" #if defined(USE_NSS_CERTS) #include "net/cert_net/nss_ocsp.h" #endif -namespace content { -class DevToolsAgentHost; -} - namespace headless { namespace { @@ -93,17 +85,20 @@ HeadlessBrowserImpl::CreateBrowserContextBuilder() { scoped_refptr<base::SingleThreadTaskRunner> HeadlessBrowserImpl::BrowserMainThread() const { - return content::BrowserThread::GetTaskRunnerForThread( - content::BrowserThread::UI); + return base::CreateSingleThreadTaskRunnerWithTraits( + {content::BrowserThread::UI}); } void HeadlessBrowserImpl::Shutdown() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); weak_ptr_factory_.InvalidateWeakPtrs(); - browser_contexts_.clear(); - + if (system_request_context_manager_) { + content::BrowserThread::DeleteSoon( + content::BrowserThread::IO, FROM_HERE, + system_request_context_manager_.release()); + } browser_main_parts_->QuitMainMessageLoop(); } @@ -172,7 +167,14 @@ void HeadlessBrowserImpl::SetDefaultBrowserContext( HeadlessBrowserContext* browser_context) { DCHECK(!browser_context || this == HeadlessBrowserContextImpl::From(browser_context)->browser()); + default_browser_context_ = browser_context; + + if (default_browser_context_ && !system_request_context_manager_) { + system_request_context_manager_ = + HeadlessRequestContextManager::CreateSystemContext( + HeadlessBrowserContextImpl::From(browser_context)->options()); + } } HeadlessBrowserContext* HeadlessBrowserImpl::GetDefaultBrowserContext() { diff --git a/chromium/headless/lib/browser/headless_browser_impl.h b/chromium/headless/lib/browser/headless_browser_impl.h index 1d2468470e5..7203861025f 100644 --- a/chromium/headless/lib/browser/headless_browser_impl.h +++ b/chromium/headless/lib/browser/headless_browser_impl.h @@ -14,19 +14,24 @@ #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" -#include "content/public/browser/web_contents.h" #include "headless/lib/browser/headless_devtools_manager_delegate.h" -#include "headless/lib/browser/headless_web_contents_impl.h" +#include "headless/public/headless_devtools_target.h" #include "headless/public/headless_export.h" namespace ui { class Compositor; } // namespace ui +namespace gfx { +class Rect; +} // namespace gfx + namespace headless { class HeadlessBrowserContextImpl; class HeadlessBrowserMainParts; +class HeadlessRequestContextManager; +class HeadlessWebContentsImpl; extern const base::FilePath::CharType kDefaultProfileName[]; @@ -99,7 +104,8 @@ class HEADLESS_EXPORT HeadlessBrowserImpl : public HeadlessBrowser, HeadlessBrowserContext* default_browser_context_; // Not owned. scoped_refptr<content::DevToolsAgentHost> agent_host_; - + std::unique_ptr<HeadlessRequestContextManager> + system_request_context_manager_; base::WeakPtrFactory<HeadlessBrowserImpl> weak_ptr_factory_; private: diff --git a/chromium/headless/lib/browser/headless_browser_impl_aura.cc b/chromium/headless/lib/browser/headless_browser_impl_aura.cc index 56d8d51f6b0..58617e00a22 100644 --- a/chromium/headless/lib/browser/headless_browser_impl_aura.cc +++ b/chromium/headless/lib/browser/headless_browser_impl_aura.cc @@ -10,6 +10,8 @@ #include "content/public/browser/web_contents.h" #include "headless/lib/browser/headless_clipboard.h" #include "headless/lib/browser/headless_screen.h" +#include "headless/lib/browser/headless_web_contents_impl.h" +#include "headless/lib/browser/headless_window_tree_host.h" #include "ui/aura/env.h" #include "ui/aura/window.h" #include "ui/base/clipboard/clipboard.h" diff --git a/chromium/headless/lib/browser/headless_browser_impl_mac.mm b/chromium/headless/lib/browser/headless_browser_impl_mac.mm index beb30b8a61e..fef6a41c526 100644 --- a/chromium/headless/lib/browser/headless_browser_impl_mac.mm +++ b/chromium/headless/lib/browser/headless_browser_impl_mac.mm @@ -6,6 +6,7 @@ #import "base/mac/scoped_objc_class_swizzler.h" #include "content/public/browser/web_contents.h" +#include "headless/lib/browser/headless_web_contents_impl.h" #import "ui/base/cocoa/base_view.h" #import "ui/gfx/mac/coordinate_conversion.h" diff --git a/chromium/headless/lib/browser/headless_content_browser_client.cc b/chromium/headless/lib/browser/headless_content_browser_client.cc index e67fed7c969..3912d8430dc 100644 --- a/chromium/headless/lib/browser/headless_content_browser_client.cc +++ b/chromium/headless/lib/browser/headless_content_browser_client.cc @@ -200,8 +200,8 @@ HeadlessContentBrowserClient::CreateQuotaPermissionContext() { void HeadlessContentBrowserClient::GetQuotaSettings( content::BrowserContext* context, content::StoragePartition* partition, - storage::OptionalQuotaSettingsCallback callback) { - storage::GetNominalDynamicSettings( + ::storage::OptionalQuotaSettingsCallback callback) { + ::storage::GetNominalDynamicSettings( partition->GetPath(), context->IsOffTheRecord(), std::move(callback)); } @@ -338,4 +338,13 @@ bool HeadlessContentBrowserClient::ShouldEnableStrictSiteIsolation() { return false; } +::network::mojom::NetworkContextPtr +HeadlessContentBrowserClient::CreateNetworkContext( + content::BrowserContext* context, + bool in_memory, + const base::FilePath& relative_partition_path) { + return HeadlessBrowserContextImpl::From(context)->CreateNetworkContext( + in_memory, relative_partition_path); +} + } // namespace headless diff --git a/chromium/headless/lib/browser/headless_content_browser_client.h b/chromium/headless/lib/browser/headless_content_browser_client.h index 1393f43719a..f8f18b39b74 100644 --- a/chromium/headless/lib/browser/headless_content_browser_client.h +++ b/chromium/headless/lib/browser/headless_content_browser_client.h @@ -31,7 +31,7 @@ class HeadlessContentBrowserClient : public content::ContentBrowserClient { void GetQuotaSettings( content::BrowserContext* context, content::StoragePartition* partition, - storage::OptionalQuotaSettingsCallback callback) override; + ::storage::OptionalQuotaSettingsCallback callback) override; #if defined(OS_POSIX) && !defined(OS_MACOSX) void GetAdditionalMappedFilesForChildProcess( const base::CommandLine& command_line, @@ -61,6 +61,11 @@ class HeadlessContentBrowserClient : public content::ContentBrowserClient { const GURL& effective_site_url) override; bool ShouldEnableStrictSiteIsolation() override; + ::network::mojom::NetworkContextPtr CreateNetworkContext( + content::BrowserContext* context, + bool in_memory, + const base::FilePath& relative_partition_path) override; + private: std::unique_ptr<base::Value> GetBrowserServiceManifestOverlay(); std::unique_ptr<base::Value> GetRendererServiceManifestOverlay(); diff --git a/chromium/headless/lib/browser/headless_devtools_client_impl.cc b/chromium/headless/lib/browser/headless_devtools_client_impl.cc index 2a77fc5ad8f..065a42d9d49 100644 --- a/chromium/headless/lib/browser/headless_devtools_client_impl.cc +++ b/chromium/headless/lib/browser/headless_devtools_client_impl.cc @@ -10,7 +10,9 @@ #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/memory/ptr_util.h" +#include "base/task/post_task.h" #include "base/values.h" +#include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "headless/public/headless_devtools_target.h" @@ -84,8 +86,8 @@ void HeadlessDevToolsClientImpl::AttachToExternalHost( } void HeadlessDevToolsClientImpl::InitBrowserMainThread() { - browser_main_thread_ = content::BrowserThread::GetTaskRunnerForThread( - content::BrowserThread::UI); + browser_main_thread_ = base::CreateSingleThreadTaskRunnerWithTraits( + {content::BrowserThread::UI}); } void HeadlessDevToolsClientImpl::ChannelClosed() { diff --git a/chromium/headless/lib/browser/headless_network_conditions.cc b/chromium/headless/lib/browser/headless_network_conditions.cc deleted file mode 100644 index 208208c9020..00000000000 --- a/chromium/headless/lib/browser/headless_network_conditions.cc +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2017 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_network_conditions.h" - -namespace headless { - -HeadlessNetworkConditions::HeadlessNetworkConditions() - : HeadlessNetworkConditions(false) {} - -HeadlessNetworkConditions::HeadlessNetworkConditions(bool offline) - : HeadlessNetworkConditions(offline, 0, 0, 0) {} - -HeadlessNetworkConditions::HeadlessNetworkConditions(bool offline, - double latency, - double download_throughput, - double upload_throughput) - : offline(offline), - latency(latency), - download_throughput(download_throughput), - upload_throughput(upload_throughput) {} - -HeadlessNetworkConditions::~HeadlessNetworkConditions() = default; - -} // namespace headless diff --git a/chromium/headless/lib/browser/headless_network_conditions.h b/chromium/headless/lib/browser/headless_network_conditions.h deleted file mode 100644 index 041847d5064..00000000000 --- a/chromium/headless/lib/browser/headless_network_conditions.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2017 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_NETWORK_CONDITIONS_H_ -#define HEADLESS_LIB_BROWSER_HEADLESS_NETWORK_CONDITIONS_H_ - -#include <string> -#include <vector> - -#include "base/macros.h" - -#include "headless/public/headless_export.h" - -namespace headless { - -// HeadlessNetworkConditions holds information about desired network conditions. -struct HEADLESS_EXPORT HeadlessNetworkConditions { - HeadlessNetworkConditions(); - ~HeadlessNetworkConditions(); - - explicit HeadlessNetworkConditions(bool offline); - HeadlessNetworkConditions(bool offline, - double latency, - double download_throughput, - double upload_throughput); - - bool offline; - double latency; - double download_throughput; - double upload_throughput; -}; - -} // namespace headless - -#endif // HEADLESS_LIB_BROWSER_HEADLESS_NETWORK_CONDITIONS_H_ diff --git a/chromium/headless/lib/browser/headless_print_manager.cc b/chromium/headless/lib/browser/headless_print_manager.cc index 876da578449..4c55230f18b 100644 --- a/chromium/headless/lib/browser/headless_print_manager.cc +++ b/chromium/headless/lib/browser/headless_print_manager.cc @@ -282,18 +282,16 @@ void HeadlessPrintManager::OnPrintingFailed(int cookie) { void HeadlessPrintManager::OnDidPrintDocument( const PrintHostMsg_DidPrintDocument_Params& params) { auto& content = params.content; - if (!base::SharedMemory::IsHandleValid(content.metafile_data_handle)) { + if (!content.metafile_data_region.IsValid()) { ReleaseJob(INVALID_MEMORY_HANDLE); return; } - auto shared_buf = - std::make_unique<base::SharedMemory>(content.metafile_data_handle, true); - if (!shared_buf->Map(content.data_size)) { + base::ReadOnlySharedMemoryMapping map = content.metafile_data_region.Map(); + if (!map.IsValid()) { ReleaseJob(METAFILE_MAP_ERROR); return; } - data_ = std::string(static_cast<const char*>(shared_buf->memory()), - content.data_size); + data_ = std::string(static_cast<const char*>(map.memory()), map.size()); ReleaseJob(PRINT_SUCCESS); } diff --git a/chromium/headless/lib/browser/headless_request_context_manager.cc b/chromium/headless/lib/browser/headless_request_context_manager.cc new file mode 100644 index 00000000000..f8dcb0ae4ed --- /dev/null +++ b/chromium/headless/lib/browser/headless_request_context_manager.cc @@ -0,0 +1,410 @@ +// Copyright 2018 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_request_context_manager.h" + +#include "base/task/post_task.h" +#include "base/threading/thread_task_runner_handle.h" +#include "build/build_config.h" +#include "components/cookie_config/cookie_store_util.h" +#include "components/os_crypt/key_storage_config_linux.h" +#include "components/os_crypt/os_crypt.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/cookie_store_factory.h" +#include "content/public/browser/devtools_network_transaction_factory.h" +#include "content/public/browser/network_service_instance.h" +#include "content/public/browser/resource_context.h" +#include "headless/app/headless_shell_switches.h" +#include "headless/lib/browser/headless_browser_context_options.h" +#include "net/base/network_delegate_impl.h" +#include "net/cookies/cookie_store.h" +#include "net/http/http_auth_handler_factory.h" +#include "net/http/http_auth_scheme.h" +#include "net/http/http_transaction_factory.h" +#include "net/ssl/channel_id_service.h" +#include "net/ssl/default_channel_id_store.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_context_builder.h" +#include "net/url_request/url_request_context_getter.h" +#include "services/network/network_service.h" +#include "services/network/public/cpp/features.h" +#include "services/network/url_request_context_builder_mojo.h" + +namespace headless { + +namespace { + +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) +static char kProductName[] = "HeadlessChrome"; +#endif + +class DelegateImpl : public net::NetworkDelegateImpl { + public: + DelegateImpl() = default; + ~DelegateImpl() override = default; + + private: + // net::NetworkDelegateImpl implementation. + bool OnCanAccessFile(const net::URLRequest& request, + const base::FilePath& original_path, + const base::FilePath& absolute_path) const override { + return true; + } + + DISALLOW_COPY_AND_ASSIGN(DelegateImpl); +}; + +net::NetworkTrafficAnnotationTag GetProxyConfigTrafficAnnotationTag() { + static net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation("proxy_config_headless", R"( + semantics { + sender: "Proxy Config" + description: + "Creates a proxy based on configuration received from headless " + "command prompt." + trigger: + "User starts headless with proxy config." + data: + "Proxy configurations." + destination: OTHER + destination_other: + "The proxy server specified in the configuration." + } + policy { + cookies_allowed: NO + setting: + "This config is only used for headless mode and provided by user." + policy_exception_justification: + "This config is only used for headless mode and provided by user." + })"); + return traffic_annotation; +} + +} // namespace + +// 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() = default; + ~HeadlessResourceContext() override { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + } + + // ResourceContext implementation: + net::URLRequestContext* GetRequestContext() override { + CHECK(url_request_context_getter_); + return url_request_context_getter_->GetURLRequestContext(); + } + + // 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. + 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); +}; + +class HeadlessURLRequestContextGetter : public net::URLRequestContextGetter { + public: + explicit HeadlessURLRequestContextGetter( + scoped_refptr<base::SingleThreadTaskRunner> task_runner) + : context_(nullptr), task_runner_(task_runner) {} + + net::URLRequestContext* GetURLRequestContext() override { return context_; } + + scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() + const override { + return task_runner_; + } + + void SetURLRequestContext(net::URLRequestContext* context) { + DCHECK(!context_ && !context_owner_); + DCHECK(!base::FeatureList::IsEnabled(::network::features::kNetworkService)); + + context_ = context; + } + + void SetURLRequestContext(std::unique_ptr<net::URLRequestContext> context) { + DCHECK(!context_ && !context_owner_); + DCHECK(base::FeatureList::IsEnabled(::network::features::kNetworkService)); + + context_owner_ = std::move(context); + context_ = context_owner_.get(); + } + + void Shutdown() { + context_ = nullptr; + NotifyContextShuttingDown(); + if (context_owner_) + task_runner_->DeleteSoon(FROM_HERE, context_owner_.release()); + } + + private: + ~HeadlessURLRequestContextGetter() override { DCHECK(!context_); } + + net::URLRequestContext* context_; + std::unique_ptr<net::URLRequestContext> context_owner_; + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; +}; + +// Tracks the ProxyConfig to use, and passes any updates to a NetworkContext's +// ProxyConfigClient. +class HeadlessProxyConfigMonitor + : public net::ProxyConfigService::Observer, + public ::network::mojom::ProxyConfigPollerClient { + public: + static void DeleteSoon(std::unique_ptr<HeadlessProxyConfigMonitor> instance) { + instance->task_runner_->DeleteSoon(FROM_HERE, instance.release()); + } + + explicit HeadlessProxyConfigMonitor( + scoped_refptr<base::SingleThreadTaskRunner> task_runner) + : task_runner_(task_runner), poller_binding_(this) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + // We must create the proxy config service on the UI loop on Linux because + // it must synchronously run on the glib message loop. + proxy_config_service_ = + net::ProxyResolutionService::CreateSystemProxyConfigService( + task_runner_); + task_runner_->PostTask( + FROM_HERE, base::BindOnce(&net::ProxyConfigService::AddObserver, + base::Unretained(proxy_config_service_.get()), + base::Unretained(this))); + } + + ~HeadlessProxyConfigMonitor() override { + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + proxy_config_service_->RemoveObserver(this); + } + + // Populates proxy-related fields of |network_context_params|. Updated + // ProxyConfigs will be sent to a NetworkContext created with those params + // whenever the configuration changes. Can be called more than once to inform + // multiple NetworkContexts of proxy changes. + void AddToNetworkContextParams( + ::network::mojom::NetworkContextParams* network_context_params) { + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + DCHECK(!proxy_config_client_); + network_context_params->proxy_config_client_request = + mojo::MakeRequest(&proxy_config_client_); + poller_binding_.Bind( + mojo::MakeRequest(&network_context_params->proxy_config_poller_client)); + net::ProxyConfigWithAnnotation proxy_config; + net::ProxyConfigService::ConfigAvailability availability = + proxy_config_service_->GetLatestProxyConfig(&proxy_config); + if (availability != net::ProxyConfigService::CONFIG_PENDING) + network_context_params->initial_proxy_config = proxy_config; + } + + private: + // net::ProxyConfigService::Observer implementation: + void OnProxyConfigChanged( + const net::ProxyConfigWithAnnotation& config, + net::ProxyConfigService::ConfigAvailability availability) override { + if (!proxy_config_client_) + return; + switch (availability) { + case net::ProxyConfigService::CONFIG_VALID: + proxy_config_client_->OnProxyConfigUpdated(config); + break; + case net::ProxyConfigService::CONFIG_UNSET: + proxy_config_client_->OnProxyConfigUpdated( + net::ProxyConfigWithAnnotation::CreateDirect()); + break; + case net::ProxyConfigService::CONFIG_PENDING: + NOTREACHED(); + break; + } + } + + // network::mojom::ProxyConfigPollerClient implementation: + void OnLazyProxyConfigPoll() override { proxy_config_service_->OnLazyPoll(); } + + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + std::unique_ptr<net::ProxyConfigService> proxy_config_service_; + mojo::Binding<::network::mojom::ProxyConfigPollerClient> poller_binding_; + ::network::mojom::ProxyConfigClientPtr proxy_config_client_; + + DISALLOW_COPY_AND_ASSIGN(HeadlessProxyConfigMonitor); +}; + +// static +std::unique_ptr<HeadlessRequestContextManager> +HeadlessRequestContextManager::CreateSystemContext( + const HeadlessBrowserContextOptions* options) { + auto manager = std::make_unique<HeadlessRequestContextManager>( + options, base::FilePath()); + manager->is_system_context_ = true; + auto* network_service = content::GetNetworkService(); + + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + auto auth_params = ::network::mojom::HttpAuthDynamicParams::New(); + auth_params->server_whitelist = + command_line->GetSwitchValueASCII(switches::kAuthServerWhitelist); + network_service->ConfigureHttpAuthPrefs(std::move(auth_params)); + +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) + if (manager->user_data_path_.empty()) { + ::network::mojom::CryptConfigPtr config = + ::network::mojom::CryptConfig::New(); + config->store = command_line->GetSwitchValueASCII(switches::kPasswordStore); + config->product_name = kProductName; + config->should_use_preference = false; + config->user_data_path = manager->user_data_path_; + network_service->SetCryptConfig(std::move(config)); + } +#endif + + if (!manager->network_service_enabled_) { + manager->Initialize(); + return manager; + } + network_service->CreateNetworkContext(MakeRequest(&manager->network_context_), + manager->CreateNetworkContextParams()); + + return manager; +} + +HeadlessRequestContextManager::HeadlessRequestContextManager( + const HeadlessBrowserContextOptions* options, + base::FilePath user_data_path) + : network_service_enabled_( + base::FeatureList::IsEnabled(::network::features::kNetworkService)), + io_task_runner_(base::CreateSingleThreadTaskRunnerWithTraits( + {content::BrowserThread::IO})), + user_data_path_(std::move(user_data_path)), + accept_language_(options->accept_language()), + user_agent_(options->user_agent()), + proxy_config_( + options->proxy_config() + ? std::make_unique<net::ProxyConfig>(*options->proxy_config()) + : nullptr), + is_system_context_(false), + resource_context_(std::make_unique<HeadlessResourceContext>()) { + if (!proxy_config_) { + auto proxy_monitor_task_runner = network_service_enabled_ + ? base::ThreadTaskRunnerHandle::Get() + : io_task_runner_; + proxy_config_monitor_ = + std::make_unique<HeadlessProxyConfigMonitor>(proxy_monitor_task_runner); + } +} + +HeadlessRequestContextManager::~HeadlessRequestContextManager() { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (url_request_context_getter_) + url_request_context_getter_->Shutdown(); + if (proxy_config_monitor_) + HeadlessProxyConfigMonitor::DeleteSoon(std::move(proxy_config_monitor_)); +} + +net::URLRequestContextGetter* +HeadlessRequestContextManager::CreateRequestContext( + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors) { + request_interceptors_ = std::move(request_interceptors); + protocol_handlers_.swap(*protocol_handlers); + Initialize(); + return url_request_context_getter_.get(); +} + +::network::mojom::NetworkContextPtr +HeadlessRequestContextManager::CreateNetworkContext( + bool in_memory, + const base::FilePath& relative_partition_path) { + if (!network_service_enabled_) { + if (!network_context_) { + DCHECK(!network_context_request_); + network_context_request_ = mojo::MakeRequest(&network_context_); + } + return std::move(network_context_); + } + content::GetNetworkService()->CreateNetworkContext( + MakeRequest(&network_context_), CreateNetworkContextParams()); + return std::move(network_context_); +} + +content::ResourceContext* HeadlessRequestContextManager::GetResourceContext() { + return resource_context_.get(); +} + +net::URLRequestContextGetter* +HeadlessRequestContextManager::url_request_context_getter() { + return url_request_context_getter_.get(); +} + +void HeadlessRequestContextManager::Initialize() { + url_request_context_getter_ = + base::MakeRefCounted<HeadlessURLRequestContextGetter>(io_task_runner_); + resource_context_->set_url_request_context_getter( + url_request_context_getter_); + if (!network_context_) { + DCHECK(!network_context_request_); + network_context_request_ = mojo::MakeRequest(&network_context_); + } + io_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&HeadlessRequestContextManager::InitializeOnIO, + base::Unretained(this))); +} + +void HeadlessRequestContextManager::InitializeOnIO() { + if (!network_service_enabled_) { + DCHECK(network_context_request_); + + auto builder = std::make_unique<::network::URLRequestContextBuilderMojo>(); + builder->set_network_delegate(std::make_unique<DelegateImpl>()); + builder->SetCreateHttpTransactionFactoryCallback( + base::BindOnce(&content::CreateDevToolsNetworkTransactionFactory)); + builder->SetInterceptors(std::move(request_interceptors_)); + + net::URLRequestContext* url_request_context = nullptr; + network_context_owner_ = + content::GetNetworkServiceImpl()->CreateNetworkContextWithBuilder( + std::move(network_context_request_), CreateNetworkContextParams(), + std::move(builder), &url_request_context); + + url_request_context_getter_->SetURLRequestContext(url_request_context); + return; + } + + net::URLRequestContextBuilder builder; + builder.set_proxy_resolution_service( + net::ProxyResolutionService::CreateDirect()); + url_request_context_getter_->SetURLRequestContext(builder.Build()); +} + +::network::mojom::NetworkContextParamsPtr +HeadlessRequestContextManager::CreateNetworkContextParams() { + auto context_params = ::network::mojom::NetworkContextParams::New(); + + context_params->user_agent = user_agent_; + context_params->accept_language = accept_language_; + context_params->enable_encrypted_cookies = false; + // TODO(skyostil): Make these configurable. + context_params->enable_data_url_support = true; + context_params->enable_file_url_support = true; + context_params->primary_network_context = is_system_context_; + + if (!user_data_path_.empty()) { + context_params->cookie_path = + user_data_path_.Append(FILE_PATH_LITERAL("Cookies")); + } + if (proxy_config_) { + context_params->initial_proxy_config = net::ProxyConfigWithAnnotation( + *proxy_config_, GetProxyConfigTrafficAnnotationTag()); + } else { + proxy_config_monitor_->AddToNetworkContextParams(context_params.get()); + } + return context_params; +} + +} // namespace headless diff --git a/chromium/headless/lib/browser/headless_request_context_manager.h b/chromium/headless/lib/browser/headless_request_context_manager.h new file mode 100644 index 00000000000..232cc6d9bdc --- /dev/null +++ b/chromium/headless/lib/browser/headless_request_context_manager.h @@ -0,0 +1,84 @@ +// Copyright 2018 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_REQUEST_CONTEXT_MANAGER_H_ +#define HEADLESS_LIB_BROWSER_HEADLESS_REQUEST_CONTEXT_MANAGER_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 "services/network/public/mojom/network_context.mojom.h" + +#include <string> + +namespace content { +class ResourceContext; +} + +namespace net { +class URLRequestContextGetter; +} // namespace net + +namespace headless { + +class HeadlessBrowserContextOptions; +class HeadlessProxyConfigMonitor; +class HeadlessResourceContext; +class HeadlessURLRequestContextGetter; + +class HeadlessRequestContextManager { + public: + static std::unique_ptr<HeadlessRequestContextManager> CreateSystemContext( + const HeadlessBrowserContextOptions* options); + + explicit HeadlessRequestContextManager( + const HeadlessBrowserContextOptions* options, + base::FilePath user_data_path); + ~HeadlessRequestContextManager(); + + net::URLRequestContextGetter* CreateRequestContext( + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors); + + ::network::mojom::NetworkContextPtr CreateNetworkContext( + bool in_memory, + const base::FilePath& relative_partition_path); + + content::ResourceContext* GetResourceContext(); + net::URLRequestContextGetter* url_request_context_getter(); + + private: + void Initialize(); + void InitializeOnIO(); + + ::network::mojom::NetworkContextParamsPtr CreateNetworkContextParams(); + + const bool network_service_enabled_; + + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; + + base::FilePath user_data_path_; + std::string accept_language_; + std::string user_agent_; + std::unique_ptr<net::ProxyConfig> proxy_config_; + std::unique_ptr<HeadlessProxyConfigMonitor> proxy_config_monitor_; + bool is_system_context_; + + ::network::mojom::NetworkContextPtr network_context_; + ::network::mojom::NetworkContextRequest network_context_request_; + + content::ProtocolHandlerMap protocol_handlers_; + content::URLRequestInterceptorScopedVector request_interceptors_; + + std::unique_ptr<::network::mojom::NetworkContext> network_context_owner_; + scoped_refptr<HeadlessURLRequestContextGetter> url_request_context_getter_; + std::unique_ptr<HeadlessResourceContext> resource_context_; + + DISALLOW_COPY_AND_ASSIGN(HeadlessRequestContextManager); +}; + +} // namespace headless + +#endif // HEADLESS_LIB_BROWSER_HEADLESS_REQUEST_CONTEXT_MANAGER_H_ diff --git a/chromium/headless/lib/browser/headless_shell_application_mac.mm b/chromium/headless/lib/browser/headless_shell_application_mac.mm index d1ac00051bf..fddf2bf5c68 100644 --- a/chromium/headless/lib/browser/headless_shell_application_mac.mm +++ b/chromium/headless/lib/browser/headless_shell_application_mac.mm @@ -5,6 +5,15 @@ #include "headless/lib/browser/headless_shell_application_mac.h" #include "base/auto_reset.h" +#include "base/observer_list.h" +#include "content/public/browser/native_event_processor_mac.h" +#include "content/public/browser/native_event_processor_observer_mac.h" + +@interface HeadlessShellCrApplication ()<NativeEventProcessor> { + base::ObserverList<content::NativeEventProcessorObserver>::Unchecked + observers_; +} +@end @implementation HeadlessShellCrApplication @@ -17,4 +26,20 @@ - (void)setHandlingSendEvent:(BOOL)handlingSendEvent { } +- (void)sendEvent:(NSEvent*)event { + content::ScopedNotifyNativeEventProcessorObserver scopedObserverNotifier( + &observers_, event); + [super sendEvent:event]; +} + +- (void)addNativeEventProcessorObserver: + (content::NativeEventProcessorObserver*)observer { + observers_.AddObserver(observer); +} + +- (void)removeNativeEventProcessorObserver: + (content::NativeEventProcessorObserver*)observer { + observers_.RemoveObserver(observer); +} + @end diff --git a/chromium/headless/lib/browser/headless_url_request_context_getter.cc b/chromium/headless/lib/browser/headless_url_request_context_getter.cc deleted file mode 100644 index 06502b46f8c..00000000000 --- a/chromium/headless/lib/browser/headless_url_request_context_getter.cc +++ /dev/null @@ -1,246 +0,0 @@ -// 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 <utility> -#include <vector> - -#include "base/task/post_task.h" -#include "build/build_config.h" -#include "components/cookie_config/cookie_store_util.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/cookie_store_factory.h" -#include "content/public/browser/devtools_network_transaction_factory.h" -#include "headless/app/headless_shell_switches.h" -#include "headless/lib/browser/headless_browser_context_impl.h" -#include "headless/lib/browser/headless_browser_context_options.h" -#include "net/base/network_delegate_impl.h" -#include "net/cookies/cookie_store.h" -#include "net/dns/mapped_host_resolver.h" -#include "net/http/http_auth_handler_factory.h" -#include "net/http/http_auth_scheme.h" -#include "net/http/http_transaction_factory.h" -#include "net/http/http_util.h" -#include "net/proxy_resolution/proxy_resolution_service.h" -#include "net/ssl/channel_id_service.h" -#include "net/ssl/default_channel_id_store.h" -#include "net/traffic_annotation/network_traffic_annotation.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_context_builder.h" - -#if defined(OS_LINUX) && !defined(OS_CHROMEOS) -#include "base/command_line.h" -#include "components/os_crypt/key_storage_config_linux.h" -#include "components/os_crypt/os_crypt.h" -#endif - -namespace headless { - -namespace { - -class DelegateImpl : public net::NetworkDelegateImpl { - public: - DelegateImpl() = default; - ~DelegateImpl() override = default; - - private: - // net::NetworkDelegateImpl implementation. - bool OnCanAccessFile(const net::URLRequest& request, - const base::FilePath& original_path, - const base::FilePath& absolute_path) const override { - return true; - } - - DISALLOW_COPY_AND_ASSIGN(DelegateImpl); -}; - -} // namespace - -HeadlessURLRequestContextGetter::HeadlessURLRequestContextGetter( - scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, - content::ProtocolHandlerMap* protocol_handlers, - content::ProtocolHandlerMap context_protocol_handlers, - content::URLRequestInterceptorScopedVector request_interceptors, - HeadlessBrowserContextOptions* options, - net::NetLog* net_log, - HeadlessBrowserContextImpl* headless_browser_context) - : io_task_runner_(std::move(io_task_runner)), - accept_language_(options->accept_language()), - user_agent_(options->user_agent()), - host_resolver_rules_(options->host_resolver_rules()), - proxy_config_(options->proxy_config()), - request_interceptors_(std::move(request_interceptors)), - net_log_(net_log) { - // Must first be created on the UI thread. - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - std::swap(protocol_handlers_, *protocol_handlers); - for (auto& pair : context_protocol_handlers) { - protocol_handlers_[pair.first] = std::move(pair.second); - } - - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - prefs_.SetServerWhitelist( - command_line->GetSwitchValueASCII(switches::kAuthServerWhitelist)); - - // 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 (!proxy_config_) { - proxy_config_service_ = - net::ProxyResolutionService::CreateSystemProxyConfigService( - io_task_runner_); - } - if (!headless_browser_context->IsOffTheRecord() && - !headless_browser_context->options()->user_data_dir().empty()) { - user_data_path_ = headless_browser_context->GetPath(); - } -} - -HeadlessURLRequestContextGetter::~HeadlessURLRequestContextGetter() = default; - -net::URLRequestContext* -HeadlessURLRequestContextGetter::GetURLRequestContext() { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - if (shut_down_) - return nullptr; - - if (url_request_context_) - return url_request_context_.get(); - - net::URLRequestContextBuilder builder; - - // Don't store cookies in incognito mode or if no user-data-dir was - // specified - // TODO: Enable this always once saving/restoring sessions is implemented - // (https://crbug.com/617931) - if (!user_data_path_.empty()) { -#if defined(OS_LINUX) && !defined(OS_CHROMEOS) - std::unique_ptr<os_crypt::Config> config(new os_crypt::Config()); - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - config->store = command_line->GetSwitchValueASCII(switches::kPasswordStore); - config->product_name = "HeadlessChrome"; - // OSCrypt may target keyring, which requires calls from the main - // thread. - config->main_thread_runner = content::BrowserThread::GetTaskRunnerForThread( - content::BrowserThread::UI); - config->should_use_preference = false; - config->user_data_path = user_data_path_; - OSCrypt::SetConfig(std::move(config)); -#endif - - content::CookieStoreConfig cookie_config( - user_data_path_.Append(FILE_PATH_LITERAL("Cookies")), false, true, - NULL); - cookie_config.crypto_delegate = cookie_config::GetCookieCryptoDelegate(); - // TODO(crbug.com/801910): Hook up logging by passing in a non-null netlog. - std::unique_ptr<net::CookieStore> cookie_store = - CreateCookieStore(cookie_config, nullptr /* netlog*/); - std::unique_ptr<net::ChannelIDService> channel_id_service = - std::make_unique<net::ChannelIDService>( - new net::DefaultChannelIDStore(nullptr)); - - cookie_store->SetChannelIDServiceID(channel_id_service->GetUniqueID()); - builder.SetCookieAndChannelIdStores(std::move(cookie_store), - std::move(channel_id_service)); - } - - builder.set_accept_language( - net::HttpUtil::GenerateAcceptLanguageHeader(accept_language_)); - builder.set_user_agent(user_agent_); - // TODO(skyostil): Make these configurable. - builder.set_data_enabled(true); - builder.set_file_enabled(true); - if (proxy_config_) { - net::NetworkTrafficAnnotationTag traffic_annotation = - net::DefineNetworkTrafficAnnotation("proxy_config_headless", R"( - semantics { - sender: "Proxy Config" - description: - "Creates a proxy based on configuration received from headless " - "command prompt." - trigger: - "User starts headless with proxy config." - data: - "Proxy configurations." - destination: OTHER - destination_other: - "The proxy server specified in the configuration." - } - policy { - cookies_allowed: NO - setting: - "This config is only used for headless mode and provided by user." - policy_exception_justification: - "This config is only used for headless mode and provided by user." - })"); - - builder.set_proxy_resolution_service( - net::ProxyResolutionService::CreateFixed(net::ProxyConfigWithAnnotation( - *proxy_config_, traffic_annotation))); - } else { - builder.set_proxy_config_service(std::move(proxy_config_service_)); - } - - builder.set_network_delegate(std::make_unique<DelegateImpl>()); - std::unique_ptr<net::HostResolver> host_resolver( - net::HostResolver::CreateDefaultResolver(net_log_)); - - if (!host_resolver_rules_.empty()) { - std::unique_ptr<net::MappedHostResolver> mapped_host_resolver( - new net::MappedHostResolver(std::move(host_resolver))); - mapped_host_resolver->SetRulesFromString(host_resolver_rules_); - host_resolver = std::move(mapped_host_resolver); - } - - std::unique_ptr<net::HttpAuthHandlerRegistryFactory> factory = - net::HttpAuthHandlerRegistryFactory::CreateDefault(host_resolver.get()); - factory->SetHttpAuthPreferences(net::kNegotiateAuthScheme, &prefs_); - builder.SetHttpAuthHandlerFactory(std::move(factory)); - builder.set_host_resolver(std::move(host_resolver)); - - // Extra headers are required for network emulation and are removed in - // DevToolsNetworkTransaction. If a protocol handler is set for http or - // https, then it is likely that the HttpTransactionFactoryCallback will - // not be called and DevToolsNetworkTransaction would not remove the header. - bool has_http_handler = false; - for (auto& pair : protocol_handlers_) { - builder.SetProtocolHandler(pair.first, std::move(pair.second)); - if (pair.first == url::kHttpScheme || pair.first == url::kHttpsScheme) - has_http_handler = true; - } - protocol_handlers_.clear(); - builder.SetInterceptors(std::move(request_interceptors_)); - - if (!has_http_handler) { - builder.SetCreateHttpTransactionFactoryCallback( - base::BindOnce(&content::CreateDevToolsNetworkTransactionFactory)); - } - - url_request_context_ = builder.Build(); - url_request_context_->set_net_log(net_log_); - - return url_request_context_.get(); -} - -scoped_refptr<base::SingleThreadTaskRunner> -HeadlessURLRequestContextGetter::GetNetworkTaskRunner() const { - return io_task_runner_; -} - -net::HostResolver* HeadlessURLRequestContextGetter::host_resolver() const { - return url_request_context_->host_resolver(); -} - -void HeadlessURLRequestContextGetter::NotifyContextShuttingDown() { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - shut_down_ = true; - net::URLRequestContextGetter::NotifyContextShuttingDown(); - url_request_context_ = nullptr; // deletes it -} - -} // 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 deleted file mode 100644 index 027fae59e64..00000000000 --- a/chromium/headless/lib/browser/headless_url_request_context_getter.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef HEADLESS_LIB_BROWSER_HEADLESS_URL_REQUEST_CONTEXT_GETTER_H_ -#define HEADLESS_LIB_BROWSER_HEADLESS_URL_REQUEST_CONTEXT_GETTER_H_ - -#include <memory> -#include <string> - -#include "base/compiler_specific.h" -#include "base/files/file_path.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "content/public/browser/browser_context.h" -#include "headless/public/headless_browser.h" -#include "net/http/http_auth_preferences.h" -#include "net/proxy_resolution/proxy_config.h" -#include "net/proxy_resolution/proxy_config_service.h" -#include "net/url_request/url_request_context_getter.h" -#include "net/url_request/url_request_job_factory.h" - -namespace net { -class HostResolver; -class ProxyConfigService; -} - -namespace headless { -class HeadlessBrowserContextOptions; -class HeadlessBrowserContextImpl; - -class HeadlessURLRequestContextGetter : public net::URLRequestContextGetter { - public: - HeadlessURLRequestContextGetter( - scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, - content::ProtocolHandlerMap* protocol_handlers, - ProtocolHandlerMap context_protocol_handlers, - content::URLRequestInterceptorScopedVector request_interceptors, - HeadlessBrowserContextOptions* options, - net::NetLog* net_log, - HeadlessBrowserContextImpl* headless_browser_context); - - // net::URLRequestContextGetter implementation: - net::URLRequestContext* GetURLRequestContext() override; - scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() - const override; - - net::HostResolver* host_resolver() const; - - void NotifyContextShuttingDown(); - - protected: - ~HeadlessURLRequestContextGetter() override; - - private: - scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; - - // The |options| object given to the constructor is not guaranteed to outlive - // this class, so we make copies of the parts we need to access on the IO - // thread. - std::string accept_language_; - std::string user_agent_; - std::string host_resolver_rules_; - const net::ProxyConfig* proxy_config_; // Not owned. - - std::unique_ptr<net::ProxyConfigService> proxy_config_service_; - std::unique_ptr<net::URLRequestContext> url_request_context_; - content::ProtocolHandlerMap protocol_handlers_; - content::URLRequestInterceptorScopedVector request_interceptors_; - net::NetLog* net_log_; // Not owned - net::HttpAuthPreferences prefs_; - base::FilePath user_data_path_; - bool shut_down_ = false; - - DISALLOW_COPY_AND_ASSIGN(HeadlessURLRequestContextGetter); -}; - -} // namespace headless - -#endif // HEADLESS_LIB_BROWSER_HEADLESS_URL_REQUEST_CONTEXT_GETTER_H_ diff --git a/chromium/headless/lib/browser/protocol/browser_handler.cc b/chromium/headless/lib/browser/protocol/browser_handler.cc index 97ec5f5892c..06719795c5d 100644 --- a/chromium/headless/lib/browser/protocol/browser_handler.cc +++ b/chromium/headless/lib/browser/protocol/browser_handler.cc @@ -4,8 +4,12 @@ #include "headless/lib/browser/protocol/browser_handler.h" +#include "base/task/post_task.h" +#include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/web_contents.h" #include "headless/lib/browser/headless_browser_impl.h" +#include "headless/lib/browser/headless_web_contents_impl.h" namespace headless { namespace protocol { @@ -62,8 +66,8 @@ Response BrowserHandler::GetWindowBounds( } Response BrowserHandler::Close() { - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, + base::PostTaskWithTraits( + FROM_HERE, {content::BrowserThread::UI}, base::BindOnce(&HeadlessBrowserImpl::Shutdown, browser())); return Response::OK(); } diff --git a/chromium/headless/lib/browser/protocol/headless_devtools_session.cc b/chromium/headless/lib/browser/protocol/headless_devtools_session.cc index d7cc307449f..7eb37595ceb 100644 --- a/chromium/headless/lib/browser/protocol/headless_devtools_session.cc +++ b/chromium/headless/lib/browser/protocol/headless_devtools_session.cc @@ -8,7 +8,6 @@ #include "content/public/browser/devtools_agent_host_client.h" #include "headless/lib/browser/protocol/browser_handler.h" #include "headless/lib/browser/protocol/headless_handler.h" -#include "headless/lib/browser/protocol/network_handler.h" #include "headless/lib/browser/protocol/page_handler.h" #include "headless/lib/browser/protocol/target_handler.h" @@ -32,7 +31,6 @@ HeadlessDevToolsSession::HeadlessDevToolsSession( } if (agent_host->GetType() == content::DevToolsAgentHost::kTypeBrowser) AddHandler(std::make_unique<BrowserHandler>(browser_)); - AddHandler(std::make_unique<NetworkHandler>(browser_)); AddHandler(std::make_unique<TargetHandler>(browser_)); } diff --git a/chromium/headless/lib/browser/protocol/network_handler.cc b/chromium/headless/lib/browser/protocol/network_handler.cc deleted file mode 100644 index ff8a1bd8153..00000000000 --- a/chromium/headless/lib/browser/protocol/network_handler.cc +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2014 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/protocol/network_handler.h" - -#include "headless/lib/browser/headless_browser_context_impl.h" -#include "headless/lib/browser/headless_browser_impl.h" - -namespace headless { -namespace protocol { - -NetworkHandler::NetworkHandler(base::WeakPtr<HeadlessBrowserImpl> browser) - : DomainHandler(Network::Metainfo::domainName, browser) {} - -NetworkHandler::~NetworkHandler() = default; - -void NetworkHandler::Wire(UberDispatcher* dispatcher) { - Network::Dispatcher::wire(dispatcher, this); -} - -Response NetworkHandler::EmulateNetworkConditions( - bool offline, - double latency, - double download_throughput, - double upload_throughput, - Maybe<Network::ConnectionType>) { - // Associate NetworkConditions to context - std::vector<HeadlessBrowserContext*> browser_contexts = - browser()->GetAllBrowserContexts(); - HeadlessNetworkConditions conditions(HeadlessNetworkConditions( - offline, std::max(latency, 0.0), std::max(download_throughput, 0.0), - std::max(upload_throughput, 0.0))); - SetNetworkConditions(browser_contexts, conditions); - return Response::FallThrough(); -} - -Response NetworkHandler::Disable() { - // Can be a part of the shutdown cycle. - if (!browser()) - return Response::OK(); - std::vector<HeadlessBrowserContext*> browser_contexts = - browser()->GetAllBrowserContexts(); - SetNetworkConditions(browser_contexts, HeadlessNetworkConditions()); - return Response::FallThrough(); -} - -void NetworkHandler::SetNetworkConditions( - std::vector<HeadlessBrowserContext*> browser_contexts, - HeadlessNetworkConditions conditions) { - for (std::vector<HeadlessBrowserContext*>::iterator it = - browser_contexts.begin(); - it != browser_contexts.end(); ++it) { - HeadlessBrowserContextImpl* context = - static_cast<HeadlessBrowserContextImpl*>(*it); - context->SetNetworkConditions(conditions); - } -} - -} // namespace protocol -} // namespace headless diff --git a/chromium/headless/lib/browser/protocol/network_handler.h b/chromium/headless/lib/browser/protocol/network_handler.h deleted file mode 100644 index b9c3e30d4ee..00000000000 --- a/chromium/headless/lib/browser/protocol/network_handler.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2014 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_PROTOCOL_NETWORK_HANDLER_H_ -#define HEADLESS_LIB_BROWSER_PROTOCOL_NETWORK_HANDLER_H_ - -#include "headless/lib/browser/headless_network_conditions.h" -#include "headless/lib/browser/protocol/domain_handler.h" -#include "headless/lib/browser/protocol/dp_network.h" - -namespace headless { - -class HeadlessBrowserContext; - -namespace protocol { - -class NetworkHandler : public DomainHandler, public Network::Backend { - public: - explicit NetworkHandler(base::WeakPtr<HeadlessBrowserImpl> browser); - ~NetworkHandler() override; - - void Wire(UberDispatcher* dispatcher) override; - - // Network::Backend implementation - Response EmulateNetworkConditions( - bool offline, - double latency, - double download_throughput, - double upload_throughput, - Maybe<Network::ConnectionType> connection_type) override; - Response Disable() override; - - private: - void SetNetworkConditions( - std::vector<HeadlessBrowserContext*> browser_contexts, - HeadlessNetworkConditions conditions); - DISALLOW_COPY_AND_ASSIGN(NetworkHandler); -}; - -} // namespace protocol -} // namespace headless - -#endif // HEADLESS_LIB_BROWSER_PROTOCOL_NETWORK_HANDLER_H_ diff --git a/chromium/headless/lib/browser/protocol/target_handler.cc b/chromium/headless/lib/browser/protocol/target_handler.cc index b1865d56726..15da7d7edb7 100644 --- a/chromium/headless/lib/browser/protocol/target_handler.cc +++ b/chromium/headless/lib/browser/protocol/target_handler.cc @@ -7,6 +7,7 @@ #include "build/build_config.h" #include "headless/lib/browser/headless_browser_context_impl.h" #include "headless/lib/browser/headless_browser_impl.h" +#include "headless/lib/browser/headless_web_contents_impl.h" #include "ui/gfx/geometry/size.h" namespace headless { diff --git a/chromium/headless/lib/dom_tree_extraction_expected_nodes.txt b/chromium/headless/lib/dom_tree_extraction_expected_nodes.txt index fe074127e7c..22008d96306 100644 --- a/chromium/headless/lib/dom_tree_extraction_expected_nodes.txt +++ b/chromium/headless/lib/dom_tree_extraction_expected_nodes.txt @@ -14,7 +14,9 @@ "layoutNodeIndex": 0, "nodeName": "#document", "nodeType": 9, - "nodeValue": "" + "nodeValue": "", + "scrollOffsetX": 0.0, + "scrollOffsetY": 0.0 } { "backendNodeId": "?", @@ -120,7 +122,7 @@ } ], "backendNodeId": "?", "boundingBox": { - "height": 354.0, + "height": 353.4375, "width": 784.0, "x": 8.0, "y": 8.0 @@ -201,10 +203,10 @@ } ], "backendNodeId": "?", "boundingBox": { - "height": 205.0, + "height": 204.0, "width": 404.0, "x": 8.0, - "y": 61.0 + "y": 61.4375 }, "contentDocumentIndex": 18, "frameId": "?", @@ -230,7 +232,9 @@ "layoutNodeIndex": 7, "nodeName": "#document", "nodeType": 9, - "nodeValue": "" + "nodeValue": "", + "scrollOffsetX": 0.0, + "scrollOffsetY": 0.0 } { "backendNodeId": "?", @@ -257,7 +261,7 @@ { "backendNodeId": "?", "boundingBox": { - "height": 171.0, + "height": 170.5625, "width": 384.0, "x": 8.0, "y": 8.0 @@ -301,7 +305,7 @@ "backendNodeId": "?", "boundingBox": { "height": 36.0, - "width": 308.0, + "width": 307.734375, "x": 8.0, "y": 8.0 }, @@ -350,10 +354,10 @@ } ], "backendNodeId": "?", "boundingBox": { - "height": 97.0, + "height": 96.0, "width": 784.0, "x": 8.0, - "y": 265.0 + "y": 265.4375 }, "childNodeIndexes": [ 28, 29, 48 ], "layoutNodeIndex": 13, @@ -375,10 +379,10 @@ } ], "backendNodeId": "?", "boundingBox": { - "height": 97.0, + "height": 96.0, "width": 784.0, "x": 8.0, - "y": 265.0 + "y": 265.4375 }, "childNodeIndexes": [ 30, 31, 47 ], "layoutNodeIndex": 14, @@ -400,10 +404,10 @@ } ], "backendNodeId": "?", "boundingBox": { - "height": 97.0, + "height": 96.0, "width": 784.0, "x": 8.0, - "y": 265.0 + "y": 265.4375 }, "childNodeIndexes": [ 32, 33, 35, 36, 38, 39, 40, 41, 46 ], "layoutNodeIndex": 15, @@ -425,10 +429,10 @@ } ], "backendNodeId": "?", "boundingBox": { - "height": 17.0, + "height": 16.0, "width": 112.0, "x": 8.0, - "y": 265.0 + "y": 265.4375 }, "childNodeIndexes": [ 34 ], "isClickable": true, @@ -441,10 +445,10 @@ { "backendNodeId": "?", "boundingBox": { - "height": 17.0, + "height": 16.0, "width": 112.0, "x": 8.0, - "y": 265.0 + "y": 265.4375 }, "inlineTextNodes": [ { "boundingBox": { @@ -481,10 +485,10 @@ { "backendNodeId": "?", "boundingBox": { - "height": 17.0, + "height": 16.0, "width": 784.0, "x": 8.0, - "y": 297.0 + "y": 297.4375 }, "childNodeIndexes": [ 37 ], "layoutNodeIndex": 19, @@ -496,10 +500,10 @@ { "backendNodeId": "?", "boundingBox": { - "height": 17.0, + "height": 16.0, "width": 192.0, "x": 8.0, - "y": 297.0 + "y": 297.4375 }, "inlineTextNodes": [ { "boundingBox": { @@ -527,10 +531,10 @@ { "backendNodeId": "?", "boundingBox": { - "height": 17.0, + "height": 16.0, "width": 0.0, "x": 8.0, - "y": 329.0 + "y": 329.4375 }, "inlineTextNodes": [ { "boundingBox": { @@ -562,10 +566,10 @@ } ], "backendNodeId": "?", "boundingBox": { - "height": 17.0, + "height": 16.0, "width": 784.0, "x": 8.0, - "y": 345.0 + "y": 345.4375 }, "childNodeIndexes": [ 42, 43, 45 ], "layoutNodeIndex": 22, @@ -577,10 +581,10 @@ { "backendNodeId": "?", "boundingBox": { - "height": 17.0, + "height": 16.0, "width": 80.0, "x": 8.0, - "y": 345.0 + "y": 345.4375 }, "inlineTextNodes": [ { "boundingBox": { @@ -602,10 +606,10 @@ { "backendNodeId": "?", "boundingBox": { - "height": 17.0, + "height": 16.0, "width": 80.0, "x": 88.0, - "y": 345.0 + "y": 345.4375 }, "childNodeIndexes": [ 44 ], "layoutNodeIndex": 24, @@ -617,10 +621,10 @@ { "backendNodeId": "?", "boundingBox": { - "height": 17.0, + "height": 16.0, "width": 80.0, "x": 88.0, - "y": 345.0 + "y": 345.4375 }, "inlineTextNodes": [ { "boundingBox": { @@ -642,10 +646,10 @@ { "backendNodeId": "?", "boundingBox": { - "height": 17.0, + "height": 16.0, "width": 128.0, "x": 168.0, - "y": 345.0 + "y": 345.4375 }, "inlineTextNodes": [ { "boundingBox": { diff --git a/chromium/headless/lib/headless_browser_browsertest.cc b/chromium/headless/lib/headless_browser_browsertest.cc index dba6e9f17bb..4cd0459f832 100644 --- a/chromium/headless/lib/headless_browser_browsertest.cc +++ b/chromium/headless/lib/headless_browser_browsertest.cc @@ -11,8 +11,11 @@ #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_restrictions.h" #include "build/build_config.h" +#include "content/public/browser/navigation_controller.h" +#include "content/public/browser/navigation_entry.h" #include "content/public/browser/permission_controller_delegate.h" #include "content/public/browser/permission_type.h" +#include "content/public/browser/ssl_status.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_switches.h" #include "content/public/common/url_constants.h" @@ -29,11 +32,8 @@ #include "headless/public/headless_devtools_target.h" #include "headless/public/headless_web_contents.h" #include "headless/test/headless_browser_test.h" -#include "net/base/registry_controlled_domains/registry_controlled_domain.h" -#include "net/cookies/cookie_store.h" -#include "net/http/http_util.h" +#include "net/cert/cert_status_flags.h" #include "net/test/spawned_test_server/spawned_test_server.h" -#include "net/url_request/url_request_context.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/clipboard/clipboard.h" @@ -231,30 +231,6 @@ IN_PROC_BROWSER_TEST_F(HeadlessBrowserTestWithProxy, SetProxyConfig) { EXPECT_TRUE(browser_context->GetAllWebContents().empty()); } -IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, SetHostResolverRules) { - EXPECT_TRUE(embedded_test_server()->Start()); - - std::string host_resolver_rules = - base::StringPrintf("MAP not-an-actual-domain.tld 127.0.0.1:%d", - embedded_test_server()->host_port_pair().port()); - - HeadlessBrowserContext* browser_context = - browser() - ->CreateBrowserContextBuilder() - .SetHostResolverRules(host_resolver_rules) - .Build(); - - // Load a page which doesn't actually exist, but which is turned into a valid - // address by our host resolver rules. - HeadlessWebContents* web_contents = - browser_context->CreateWebContentsBuilder() - .SetInitialURL(GURL("http://not-an-actual-domain.tld/hello.html")) - .Build(); - EXPECT_TRUE(web_contents); - - EXPECT_TRUE(WaitForLoad(web_contents)); -} - IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, WebGLSupported) { HeadlessBrowserContext* browser_context = browser()->CreateBrowserContextBuilder().Build(); @@ -661,8 +637,16 @@ class HeadlessBrowserTestAppendCommandLineFlags : public HeadlessBrowserTest { bool callback_was_run_ = false; }; +#if defined(OS_WIN) +// Flaky on Win ASAN. See https://crbug.com/884095. +#define MAYBE_AppendChildProcessCommandLineFlags \ + DISABLED_AppendChildProcessCommandLineFlags +#else +#define MAYBE_AppendChildProcessCommandLineFlags \ + AppendChildProcessCommandLineFlags +#endif IN_PROC_BROWSER_TEST_F(HeadlessBrowserTestAppendCommandLineFlags, - AppendChildProcessCommandLineFlags) { + MAYBE_AppendChildProcessCommandLineFlags) { // Create a new renderer process, and verify that callback was executed. HeadlessBrowserContext* browser_context = browser()->CreateBrowserContextBuilder().Build(); @@ -696,4 +680,29 @@ IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, ServerWantsClientCertificate) { EXPECT_TRUE(WaitForLoad(web_contents)); } +IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, AIAFetching) { + net::SpawnedTestServer::SSLOptions ssl_options( + net::SpawnedTestServer::SSLOptions::CERT_AUTO_AIA_INTERMEDIATE); + net::SpawnedTestServer server( + net::SpawnedTestServer::TYPE_HTTPS, ssl_options, + base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + ASSERT_TRUE(server.Start()); + + HeadlessBrowserContext* browser_context = + browser()->CreateBrowserContextBuilder().Build(); + browser()->SetDefaultBrowserContext(browser_context); + + GURL url = server.GetURL("/defaultresponse"); + HeadlessWebContents* web_contents = + browser_context->CreateWebContentsBuilder().SetInitialURL(url).Build(); + EXPECT_TRUE(WaitForLoad(web_contents)); + content::NavigationEntry* last_entry = + HeadlessWebContentsImpl::From(web_contents) + ->web_contents() + ->GetController() + .GetLastCommittedEntry(); + EXPECT_FALSE(net::IsCertStatusError(last_entry->GetSSL().cert_status)); + EXPECT_EQ(url, last_entry->GetURL()); +} + } // namespace headless diff --git a/chromium/headless/lib/headless_content_main_delegate.cc b/chromium/headless/lib/headless_content_main_delegate.cc index dc18c05d427..1446bb3190f 100644 --- a/chromium/headless/lib/headless_content_main_delegate.cc +++ b/chromium/headless/lib/headless_content_main_delegate.cc @@ -90,30 +90,30 @@ bool HeadlessContentMainDelegate::BasicStartupComplete(int* exit_code) { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); // Make sure all processes know that we're in headless mode. - if (!command_line->HasSwitch(switches::kHeadless)) - command_line->AppendSwitch(switches::kHeadless); + if (!command_line->HasSwitch(::switches::kHeadless)) + command_line->AppendSwitch(::switches::kHeadless); if (browser_->options()->single_process_mode) - command_line->AppendSwitch(switches::kSingleProcess); + command_line->AppendSwitch(::switches::kSingleProcess); if (browser_->options()->disable_sandbox) command_line->AppendSwitch(service_manager::switches::kNoSandbox); if (!browser_->options()->enable_resource_scheduler) - command_line->AppendSwitch(switches::kDisableResourceScheduler); + command_line->AppendSwitch(::switches::kDisableResourceScheduler); #if defined(USE_OZONE) // The headless backend is automatically chosen for a headless build, but also // adding it here allows us to run in a non-headless build too. - command_line->AppendSwitchASCII(switches::kOzonePlatform, "headless"); + command_line->AppendSwitchASCII(::switches::kOzonePlatform, "headless"); #endif - if (!command_line->HasSwitch(switches::kUseGL)) { + if (!command_line->HasSwitch(::switches::kUseGL)) { if (!browser_->options()->gl_implementation.empty()) { - command_line->AppendSwitchASCII(switches::kUseGL, + command_line->AppendSwitchASCII(::switches::kUseGL, browser_->options()->gl_implementation); } else { - command_line->AppendSwitch(switches::kDisableGpu); + command_line->AppendSwitch(::switches::kDisableGpu); } } @@ -121,7 +121,7 @@ bool HeadlessContentMainDelegate::BasicStartupComplete(int* exit_code) { // software compositing anyway, but only after attempting and failing to // initialize GPU compositing. We disable GPU compositing here explicitly to // preempt this attempt. - command_line->AppendSwitch(switches::kDisableGpuCompositing); + command_line->AppendSwitch(::switches::kDisableGpuCompositing); SetContentClient(&content_client_); return false; @@ -130,9 +130,9 @@ bool HeadlessContentMainDelegate::BasicStartupComplete(int* exit_code) { void HeadlessContentMainDelegate::InitLogging( const base::CommandLine& command_line) { const std::string process_type = - command_line.GetSwitchValueASCII(switches::kProcessType); + command_line.GetSwitchValueASCII(::switches::kProcessType); #if !defined(OS_WIN) - if (!command_line.HasSwitch(switches::kEnableLogging)) + if (!command_line.HasSwitch(::switches::kEnableLogging)) return; #else // Child processes in Windows are not able to initialize logging. @@ -142,11 +142,12 @@ void HeadlessContentMainDelegate::InitLogging( logging::LoggingDestination log_mode; base::FilePath log_filename(FILE_PATH_LITERAL("chrome_debug.log")); - if (command_line.GetSwitchValueASCII(switches::kEnableLogging) == "stderr") { + if (command_line.GetSwitchValueASCII(::switches::kEnableLogging) == + "stderr") { log_mode = logging::LOG_TO_SYSTEM_DEBUG_LOG; } else { base::FilePath custom_filename( - command_line.GetSwitchValuePath(switches::kEnableLogging)); + command_line.GetSwitchValuePath(::switches::kEnableLogging)); if (custom_filename.empty()) { log_mode = logging::LOG_TO_ALL; } else { @@ -155,10 +156,10 @@ void HeadlessContentMainDelegate::InitLogging( } } - if (command_line.HasSwitch(switches::kLoggingLevel) && + if (command_line.HasSwitch(::switches::kLoggingLevel) && logging::GetMinLogLevel() >= 0) { std::string log_level = - command_line.GetSwitchValueASCII(switches::kLoggingLevel); + command_line.GetSwitchValueASCII(::switches::kLoggingLevel); int level = 0; if (base::StringToInt(log_level, &level) && level >= 0 && level < logging::LOG_NUM_SEVERITIES) { @@ -216,7 +217,7 @@ void HeadlessContentMainDelegate::InitCrashReporter( NOTIMPLEMENTED(); #else const std::string process_type = - command_line.GetSwitchValueASCII(switches::kProcessType); + command_line.GetSwitchValueASCII(::switches::kProcessType); crash_reporter::SetCrashReporterClient(g_headless_crash_client.Pointer()); g_headless_crash_client.Pointer()->set_crash_dumps_dir( browser_->options()->crash_dumps_dir); @@ -251,7 +252,7 @@ void HeadlessContentMainDelegate::PreSandboxStartup() { // crash. InitLogging(command_line); #else - if (command_line.HasSwitch(switches::kEnableLogging)) + if (command_line.HasSwitch(::switches::kEnableLogging)) InitLogging(command_line); #endif // defined(OS_WIN) @@ -281,8 +282,8 @@ int HeadlessContentMainDelegate::RunProcess( browser_->RunOnStartCallback(); browser_runner->Run(); - browser_.reset(); browser_runner->Shutdown(); + browser_.reset(); // Return value >=0 here to disable calling content::BrowserMain. return 0; @@ -294,7 +295,7 @@ void HeadlessContentMainDelegate::ZygoteForked() { const base::CommandLine& command_line( *base::CommandLine::ForCurrentProcess()); const std::string process_type = - command_line.GetSwitchValueASCII(switches::kProcessType); + command_line.GetSwitchValueASCII(::switches::kProcessType); // Unconditionally try to turn on crash reporting since we do not have access // to the latest browser options at this point when testing. Breakpad will // bail out gracefully if the browser process hasn't enabled crash reporting. @@ -312,7 +313,8 @@ HeadlessContentMainDelegate* HeadlessContentMainDelegate::GetInstance() { // static void HeadlessContentMainDelegate::InitializeResourceBundle() { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - const std::string locale = command_line->GetSwitchValueASCII(switches::kLang); + const std::string locale = + command_line->GetSwitchValueASCII(::switches::kLang); ui::ResourceBundle::InitSharedInstanceWithLocale( locale, nullptr, ui::ResourceBundle::DO_NOT_LOAD_COMMON_RESOURCES); diff --git a/chromium/headless/lib/headless_content_main_delegate_mac.mm b/chromium/headless/lib/headless_content_main_delegate_mac.mm index 39211500af0..e524048e0b0 100644 --- a/chromium/headless/lib/headless_content_main_delegate_mac.mm +++ b/chromium/headless/lib/headless_content_main_delegate_mac.mm @@ -11,6 +11,12 @@ namespace headless { void HeadlessContentMainDelegate::PreCreateMainMessageLoop() { // Force the NSApplication subclass to be used. [HeadlessShellCrApplication sharedApplication]; + + // If there was an invocation to NSApp prior to this method, then the NSApp + // will not be a HeadlessShellCrApplication, but will instead be an + // NSApplication. This is undesirable and we must enforce that this doesn't + // happen. + CHECK([NSApp isKindOfClass:[HeadlessShellCrApplication class]]); } } // namespace headless diff --git a/chromium/headless/lib/headless_crash_reporter_client.cc b/chromium/headless/lib/headless_crash_reporter_client.cc index bda0c5d64d5..b1afe73ec7c 100644 --- a/chromium/headless/lib/headless_crash_reporter_client.cc +++ b/chromium/headless/lib/headless_crash_reporter_client.cc @@ -55,10 +55,10 @@ bool HeadlessCrashReporterClient::GetCrashDumpLocation( bool HeadlessCrashReporterClient::EnableBreakpadForProcess( const std::string& process_type) { - return process_type == switches::kRendererProcess || - process_type == switches::kPpapiPluginProcess || + return process_type == ::switches::kRendererProcess || + process_type == ::switches::kPpapiPluginProcess || process_type == service_manager::switches::kZygoteProcess || - process_type == switches::kGpuProcess; + process_type == ::switches::kGpuProcess; } } // namespace content diff --git a/chromium/headless/lib/headless_web_contents_browsertest.cc b/chromium/headless/lib/headless_web_contents_browsertest.cc index bd68c7732f7..1bbff18f19a 100644 --- a/chromium/headless/lib/headless_web_contents_browsertest.cc +++ b/chromium/headless/lib/headless_web_contents_browsertest.cc @@ -641,44 +641,34 @@ class HeadlessWebContentsBeginFrameControlBasicTest } void OnNeedsBeginFrame() override { - // Try to capture a screenshot in first frame. This should fail because the - // surface doesn't exist yet. BeginFrame(true); } void OnFrameFinished(std::unique_ptr<headless_experimental::BeginFrameResult> result) override { if (num_begin_frames_ == 1) { - // First BeginFrame should have caused damage. + // First BeginFrame should have caused damage and have a screenshot. EXPECT_TRUE(result->GetHasDamage()); - // But the screenshot should have failed (see above). - EXPECT_FALSE(result->HasScreenshotData()); - } else if (num_begin_frames_ == 2) { - // Expect a valid screenshot in second BeginFrame. - EXPECT_TRUE(result->GetHasDamage()); - EXPECT_TRUE(result->HasScreenshotData()); - if (result->HasScreenshotData()) { - std::string base64 = result->GetScreenshotData(); - EXPECT_LT(0u, base64.length()); - SkBitmap result_bitmap; - EXPECT_TRUE(DecodePNG(base64, &result_bitmap)); - - EXPECT_EQ(200, result_bitmap.width()); - EXPECT_EQ(200, result_bitmap.height()); - SkColor expected_color = SkColorSetRGB(0x00, 0x00, 0xff); - SkColor actual_color = result_bitmap.getColor(100, 100); - EXPECT_EQ(expected_color, actual_color); - } + ASSERT_TRUE(result->HasScreenshotData()); + std::string base64 = result->GetScreenshotData(); + EXPECT_LT(0u, base64.length()); + SkBitmap result_bitmap; + EXPECT_TRUE(DecodePNG(base64, &result_bitmap)); + EXPECT_EQ(200, result_bitmap.width()); + EXPECT_EQ(200, result_bitmap.height()); + SkColor expected_color = SkColorSetRGB(0x00, 0x00, 0xff); + SkColor actual_color = result_bitmap.getColor(100, 100); + EXPECT_EQ(expected_color, actual_color); } else { - DCHECK_EQ(3, num_begin_frames_); - // Can't guarantee that the last BeginFrame didn't have damage, but it + DCHECK_EQ(2, num_begin_frames_); + // Can't guarantee that the second BeginFrame didn't have damage, but it // should not have a screenshot. EXPECT_FALSE(result->HasScreenshotData()); } - if (num_begin_frames_ < 3) { - // Capture a screenshot in second but not third BeginFrame. - BeginFrame(num_begin_frames_ == 1); + if (num_begin_frames_ < 2) { + // Don't capture a screenshot in the second BeginFrame. + BeginFrame(false); } else { // Post completion to avoid deleting the WebContents on the same callstack // as frame finished callback. diff --git a/chromium/headless/lib/utility/headless_content_utility_client.cc b/chromium/headless/lib/utility/headless_content_utility_client.cc index 6ef75df789a..d3911cd0f0c 100644 --- a/chromium/headless/lib/utility/headless_content_utility_client.cc +++ b/chromium/headless/lib/utility/headless_content_utility_client.cc @@ -4,6 +4,7 @@ #include "headless/lib/utility/headless_content_utility_client.h" +#include "base/lazy_instance.h" #include "printing/buildflags/buildflags.h" #if BUILDFLAG(ENABLE_PRINTING) @@ -13,6 +14,18 @@ namespace headless { +namespace { +base::LazyInstance< + HeadlessContentUtilityClient::NetworkBinderCreationCallback>::Leaky + g_network_binder_creation_callback = LAZY_INSTANCE_INITIALIZER; +}; + +// static +void HeadlessContentUtilityClient::SetNetworkBinderCreationCallbackForTests( + NetworkBinderCreationCallback callback) { + g_network_binder_creation_callback.Get() = std::move(callback); +} + HeadlessContentUtilityClient::HeadlessContentUtilityClient( const std::string& user_agent) : user_agent_(user_agent) {} @@ -29,4 +42,10 @@ void HeadlessContentUtilityClient::RegisterServices( #endif } +void HeadlessContentUtilityClient::RegisterNetworkBinders( + service_manager::BinderRegistry* registry) { + if (g_network_binder_creation_callback.Get()) + g_network_binder_creation_callback.Get().Run(registry); +} + } // namespace headless diff --git a/chromium/headless/lib/utility/headless_content_utility_client.h b/chromium/headless/lib/utility/headless_content_utility_client.h index f577dc2c7c6..5e2e642fa0f 100644 --- a/chromium/headless/lib/utility/headless_content_utility_client.h +++ b/chromium/headless/lib/utility/headless_content_utility_client.h @@ -7,17 +7,28 @@ #include <string> +#include "base/callback.h" #include "content/public/utility/content_utility_client.h" +#include "headless/public/headless_export.h" namespace headless { -class HeadlessContentUtilityClient : public content::ContentUtilityClient { +class HEADLESS_EXPORT HeadlessContentUtilityClient + : public content::ContentUtilityClient { public: + using NetworkBinderCreationCallback = + base::RepeatingCallback<void(service_manager::BinderRegistry*)>; + + static void SetNetworkBinderCreationCallbackForTests( + NetworkBinderCreationCallback callback); + explicit HeadlessContentUtilityClient(const std::string& user_agent); ~HeadlessContentUtilityClient() override; // content::ContentUtilityClient: void RegisterServices(StaticServiceMap* services) override; + void RegisterNetworkBinders( + service_manager::BinderRegistry* registry) override; private: const std::string user_agent_; diff --git a/chromium/headless/protocol_config.json b/chromium/headless/protocol_config.json index 80fc13a2c4e..78bba001ffb 100644 --- a/chromium/headless/protocol_config.json +++ b/chromium/headless/protocol_config.json @@ -25,11 +25,6 @@ "async": ["beginFrame"] }, { - "domain": "Network", - "include": ["emulateNetworkConditions", "disable"], - "include_events": [] - }, - { "domain": "Page", "include": ["printToPDF"], "async": ["printToPDF"], diff --git a/chromium/headless/public/headless_browser.cc b/chromium/headless/public/headless_browser.cc index 22d2dc9504f..2f66f1f3dfd 100644 --- a/chromium/headless/public/headless_browser.cc +++ b/chromium/headless/public/headless_browser.cc @@ -20,14 +20,14 @@ namespace headless { namespace { // Product name for building the default user agent string. -const char kProductName[] = "HeadlessChrome"; +const char kHeadlessProductName[] = "HeadlessChrome"; constexpr gfx::Size kDefaultWindowSize(800, 600); constexpr gfx::FontRenderParams::Hinting kDefaultFontRenderHinting = gfx::FontRenderParams::Hinting::HINTING_FULL; std::string GetProductNameAndVersion() { - return std::string(kProductName) + "/" + PRODUCT_VERSION; + return std::string(kHeadlessProductName) + "/" + PRODUCT_VERSION; } } // namespace @@ -99,11 +99,6 @@ Builder& Builder::SetProxyConfig( return *this; } -Builder& Builder::SetHostResolverRules(const std::string& host_resolver_rules) { - options_.host_resolver_rules = host_resolver_rules; - return *this; -} - Builder& Builder::SetSingleProcessMode(bool single_process_mode) { options_.single_process_mode = single_process_mode; return *this; diff --git a/chromium/headless/public/headless_browser.h b/chromium/headless/public/headless_browser.h index 7b0e30cf118..130c2ee8b0d 100644 --- a/chromium/headless/public/headless_browser.h +++ b/chromium/headless/public/headless_browser.h @@ -161,10 +161,6 @@ struct HEADLESS_EXPORT HeadlessBrowser::Options { // The ProxyConfig to use. The system proxy settings are used by default. std::unique_ptr<net::ProxyConfig> proxy_config = nullptr; - // Comma-separated list of rules that control how hostnames are mapped. See - // chrome::switches::kHostRules for a description for the format. - std::string host_resolver_rules; - // Default window size. This is also used to create the window tree host and // as initial screen size. Defaults to 800x600. gfx::Size window_size; @@ -257,7 +253,6 @@ class HEADLESS_EXPORT HeadlessBrowser::Options::Builder { Builder& SetEnableBeginFrameControl(bool enable_begin_frame_control); Builder& SetUserAgent(const std::string& user_agent); Builder& SetProxyConfig(std::unique_ptr<net::ProxyConfig> proxy_config); - Builder& SetHostResolverRules(const std::string& host_resolver_rules); Builder& SetWindowSize(const gfx::Size& window_size); Builder& SetUserDataDir(const base::FilePath& user_data_dir); Builder& SetIncognitoMode(bool incognito_mode); diff --git a/chromium/headless/public/headless_browser_context.h b/chromium/headless/public/headless_browser_context.h index fd7207b3cca..886e2bbb246 100644 --- a/chromium/headless/public/headless_browser_context.h +++ b/chromium/headless/public/headless_browser_context.h @@ -14,9 +14,7 @@ #include "base/callback.h" #include "base/optional.h" #include "content/public/browser/browser_context.h" -#include "content/public/browser/resource_request_info.h" #include "content/public/common/web_preferences.h" -#include "headless/lib/browser/headless_network_conditions.h" #include "headless/public/headless_export.h" #include "headless/public/headless_web_contents.h" #include "net/proxy_resolution/proxy_resolution_service.h" @@ -34,7 +32,6 @@ class HeadlessBrowserContextOptions; // Builder::SetOverrideWebPreferencesCallback(). using content::WebPreferences; -using DevToolsStatus = content::ResourceRequestInfo::DevToolsStatus; using content::ProtocolHandlerMap; // Represents an isolated session with a unique cache, cookies, and other @@ -67,8 +64,6 @@ class HEADLESS_EXPORT HeadlessBrowserContext { // GUID for this browser context. virtual const std::string& Id() const = 0; - virtual HeadlessNetworkConditions GetNetworkConditions() = 0; - // TODO(skyostil): Allow saving and restoring contexts (crbug.com/617931). protected: @@ -107,7 +102,6 @@ class HEADLESS_EXPORT HeadlessBrowserContext::Builder { Builder& SetAcceptLanguage(const std::string& accept_language); Builder& SetUserAgent(const std::string& user_agent); Builder& SetProxyConfig(std::unique_ptr<net::ProxyConfig> proxy_config); - Builder& SetHostResolverRules(const std::string& host_resolver_rules); Builder& SetWindowSize(const gfx::Size& window_size); Builder& SetUserDataDir(const base::FilePath& user_data_dir); Builder& SetIncognitoMode(bool incognito_mode); diff --git a/chromium/headless/public/internal/value_conversions.h b/chromium/headless/public/internal/value_conversions.h index c9685d08fbe..fb82d9a964f 100644 --- a/chromium/headless/public/internal/value_conversions.h +++ b/chromium/headless/public/internal/value_conversions.h @@ -12,8 +12,8 @@ namespace headless { namespace internal { -// Generic conversion from a type to a base::Value. Implemented in -// types_DOMAIN.cc after all type-specific ToValueImpls have been defined. +// Generic conversion from a type to a base::Value. Implemented below +// (for composite and low level types) and and in types_DOMAIN.cc. template <typename T> std::unique_ptr<base::Value> ToValue(const T& value); @@ -26,49 +26,52 @@ struct FromValue { ErrorReporter* errors); }; -// ToValueImpl is a helper used by the ToValue template for dispatching into -// type-specific serializers. It uses a dummy |T*| argument as a way to -// partially specialize vector types. -template <typename T> -std::unique_ptr<base::Value> ToValueImpl(int value, T*) { +template <> +inline std::unique_ptr<base::Value> ToValue(const int& value) { return std::make_unique<base::Value>(value); } -template <typename T> -std::unique_ptr<base::Value> ToValueImpl(double value, T*) { +template <> +inline std::unique_ptr<base::Value> ToValue(const double& value) { return std::make_unique<base::Value>(value); } -template <typename T> -std::unique_ptr<base::Value> ToValueImpl(bool value, T*) { +template <> +inline std::unique_ptr<base::Value> ToValue(const bool& value) { return std::make_unique<base::Value>(value); } -template <typename T> -std::unique_ptr<base::Value> ToValueImpl(const std::string& value, T*) { +template <> +inline std::unique_ptr<base::Value> ToValue(const std::string& value) { return std::make_unique<base::Value>(value); } -template <typename T> -std::unique_ptr<base::Value> ToValueImpl(const base::Value& value, T*) { +template <> +inline std::unique_ptr<base::Value> ToValue(const base::Value& value) { return value.CreateDeepCopy(); } -template <typename T> -std::unique_ptr<base::Value> ToValueImpl(const std::vector<T>& vector, - const std::vector<T>*) { - std::unique_ptr<base::ListValue> result(new base::ListValue()); - for (const auto& it : vector) - result->Append(ToValue(it)); - return std::move(result); +template <> +inline std::unique_ptr<base::Value> ToValue( + const base::DictionaryValue& value) { + return ToValue(static_cast<const base::Value&>(value)); } +// Note: Order of the two templates below is important to handle +// vectors of unique_ptr. template <typename T> -std::unique_ptr<base::Value> ToValueImpl(const std::unique_ptr<T>& value, - std::unique_ptr<T>*) { +std::unique_ptr<base::Value> ToValue(const std::unique_ptr<T>& value) { return ToValue(*value); } +template <typename T> +std::unique_ptr<base::Value> ToValue(const std::vector<T>& vector_of_values) { + std::unique_ptr<base::ListValue> result(new base::ListValue()); + for (const T& value : vector_of_values) + result->Append(ToValue(value)); + return std::move(result); +} + // FromValue specializations for basic types. template <> struct FromValue<bool> { |