summaryrefslogtreecommitdiff
path: root/chromium/headless/lib/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/headless/lib/browser')
-rw-r--r--chromium/headless/lib/browser/devtools_api/domain_cc.template4
-rw-r--r--chromium/headless/lib/browser/devtools_api/domain_type_conversions_h.template5
-rw-r--r--chromium/headless/lib/browser/devtools_api/domain_types_cc.template7
-rw-r--r--chromium/headless/lib/browser/headless_browser_context_impl.cc19
-rw-r--r--chromium/headless/lib/browser/headless_browser_context_impl.h3
-rw-r--r--chromium/headless/lib/browser/headless_browser_context_options.cc4
-rw-r--r--chromium/headless/lib/browser/headless_browser_context_options.h3
-rw-r--r--chromium/headless/lib/browser/headless_browser_impl.cc24
-rw-r--r--chromium/headless/lib/browser/headless_browser_impl.h10
-rw-r--r--chromium/headless/lib/browser/headless_browser_main_parts.cc2
-rw-r--r--chromium/headless/lib/browser/headless_clipboard.cc4
-rw-r--r--chromium/headless/lib/browser/headless_content_browser_client.cc68
-rw-r--r--chromium/headless/lib/browser/headless_content_browser_client.h20
-rw-r--r--chromium/headless/lib/browser/headless_devtools_client_impl.cc36
-rw-r--r--chromium/headless/lib/browser/headless_devtools_manager_delegate.cc272
-rw-r--r--chromium/headless/lib/browser/headless_devtools_manager_delegate.h6
-rw-r--r--chromium/headless/lib/browser/headless_focus_client.cc2
-rw-r--r--chromium/headless/lib/browser/headless_network_conditions.cc2
-rw-r--r--chromium/headless/lib/browser/headless_network_delegate.cc6
-rw-r--r--chromium/headless/lib/browser/headless_network_delegate.h2
-rw-r--r--chromium/headless/lib/browser/headless_permission_manager.cc16
-rw-r--r--chromium/headless/lib/browser/headless_permission_manager.h8
-rw-r--r--chromium/headless/lib/browser/headless_platform_event_source.cc4
-rw-r--r--chromium/headless/lib/browser/headless_print_manager.cc2
-rw-r--r--chromium/headless/lib/browser/headless_quota_permission_context.cc4
-rw-r--r--chromium/headless/lib/browser/headless_resource_dispatcher_host_delegate.cc12
-rw-r--r--chromium/headless/lib/browser/headless_resource_dispatcher_host_delegate.h7
-rw-r--r--chromium/headless/lib/browser/headless_screen.cc2
-rw-r--r--chromium/headless/lib/browser/headless_tab_socket_impl.cc4
-rw-r--r--chromium/headless/lib/browser/headless_url_request_context_getter.cc58
-rw-r--r--chromium/headless/lib/browser/headless_url_request_context_getter.h1
-rw-r--r--chromium/headless/lib/browser/headless_web_contents_impl.cc20
-rw-r--r--chromium/headless/lib/browser/headless_web_contents_impl.h6
33 files changed, 462 insertions, 181 deletions
diff --git a/chromium/headless/lib/browser/devtools_api/domain_cc.template b/chromium/headless/lib/browser/devtools_api/domain_cc.template
index de9425c33c8..ac16d62dd52 100644
--- a/chromium/headless/lib/browser/devtools_api/domain_cc.template
+++ b/chromium/headless/lib/browser/devtools_api/domain_cc.template
@@ -110,7 +110,7 @@ void Domain::Handle{{method_name}}Response(base::Callback<void(std::unique_ptr<{
}
ErrorReporter errors;
std::unique_ptr<{{method_name}}Result> result = {{method_name}}Result::Parse(response, &errors);
- DCHECK(!errors.HasErrors());
+ DCHECK(!errors.HasErrors()) << errors.ToString();
callback.Run(std::move(result));
}
{% endfor %}
@@ -121,7 +121,7 @@ void Domain::Handle{{method_name}}Response(base::Callback<void(std::unique_ptr<{
void Domain::Dispatch{{event.name | to_title_case}}Event(const base::Value& params) {
ErrorReporter errors;
std::unique_ptr<{{event.name | to_title_case}}Params> parsed_params({{event.name | to_title_case}}Params::Parse(params, &errors));
- DCHECK(!errors.HasErrors());
+ DCHECK(!errors.HasErrors()) << errors.ToString();
for (ExperimentalObserver& observer : observers_) {
observer.On{{event.name | to_title_case}}(*parsed_params);
}
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 15796eb756d..eb8297050ce 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
@@ -20,14 +20,13 @@ template <>
struct FromValue<{{namespace}}::{{type.id}}> {
static {{namespace}}::{{type.id}} Parse(const base::Value& value, ErrorReporter* errors) {
{% set default = namespace + '::' + type.id + '::' + type.enum[0] | sanitize_literal | dash_to_camelcase | camelcase_to_hacker_style | upper %}
- std::string string_value;
- if (!value.GetAsString(&string_value)) {
+ if (!value.is_string()) {
errors->AddError("string enum value expected");
{# Return an arbitrary enum member -- the caller will just ignore it. #}
return {{default}};
}
{% for literal in type.enum %}
- if (string_value == "{{literal}}")
+ if (value.GetString() == "{{literal}}")
return {{namespace}}::{{type.id}}::{{literal | sanitize_literal | dash_to_camelcase | camelcase_to_hacker_style | upper }};
{% endfor %}
errors->AddError("invalid enum value");
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 bd1c2773dd4..be125aeb835 100644
--- a/chromium/headless/lib/browser/devtools_api/domain_types_cc.template
+++ b/chromium/headless/lib/browser/devtools_api/domain_types_cc.template
@@ -31,8 +31,7 @@ namespace {{domain.domain | camelcase_to_hacker_style}} {
std::unique_ptr<{{type.id}}> {{type.id}}::Parse(const base::Value& value, ErrorReporter* errors) {
errors->Push();
errors->SetName("{{type.id}}");
- const base::DictionaryValue* object;
- if (!value.GetAsDictionary(&object)) {
+ if (!value.is_dict()) {
errors->AddError("object expected");
errors->Pop();
return nullptr;
@@ -43,8 +42,8 @@ std::unique_ptr<{{type.id}}> {{type.id}}::Parse(const base::Value& value, ErrorR
errors->SetName("{{type.id}}");
{% for property in type.properties %}
{% set value_name = property.name | camelcase_to_hacker_style + "_value" %}
- const base::Value* {{value_name}};
- if (object->Get("{{property.name}}", &{{value_name}})) {
+ const base::Value* {{value_name}} = value.FindKey("{{property.name}}");
+ if ({{value_name}}) {
errors->SetName("{{property.name}}");
{% if property.optional %}
result->{{property.name | camelcase_to_hacker_style}}_ = internal::FromValue<{{resolve_type(property).raw_type}}>::Parse(*{{value_name}}, errors);
diff --git a/chromium/headless/lib/browser/headless_browser_context_impl.cc b/chromium/headless/lib/browser/headless_browser_context_impl.cc
index 781c0abe9e3..17849e27819 100644
--- a/chromium/headless/lib/browser/headless_browser_context_impl.cc
+++ b/chromium/headless/lib/browser/headless_browser_context_impl.cc
@@ -83,9 +83,9 @@ HeadlessBrowserContextImpl::HeadlessBrowserContextImpl(
std::unique_ptr<HeadlessBrowserContextOptions> context_options)
: browser_(browser),
context_options_(std::move(context_options)),
- resource_context_(new HeadlessResourceContext),
+ resource_context_(std::make_unique<HeadlessResourceContext>()),
should_remove_headers_(true),
- permission_manager_(new HeadlessPermissionManager()),
+ permission_manager_(std::make_unique<HeadlessPermissionManager>(this)),
id_(base::GenerateGUID()) {
InitWhileIOAllowed();
}
@@ -201,7 +201,8 @@ void HeadlessBrowserContextImpl::Close() {
void HeadlessBrowserContextImpl::InitWhileIOAllowed() {
if (!context_options_->user_data_dir().empty()) {
- path_ = context_options_->user_data_dir();
+ path_ =
+ context_options_->user_data_dir().Append(FILE_PATH_LITERAL("Default"));
} else {
PathService::Get(base::DIR_EXE, &path_);
}
@@ -253,8 +254,6 @@ HeadlessBrowserContextImpl::GetSSLHostStateDelegate() {
}
content::PermissionManager* HeadlessBrowserContextImpl::GetPermissionManager() {
- if (!permission_manager_.get())
- permission_manager_.reset(new HeadlessPermissionManager());
return permission_manager_.get();
}
@@ -476,6 +475,12 @@ HeadlessBrowserContext::Builder::SetIncognitoMode(bool incognito_mode) {
}
HeadlessBrowserContext::Builder&
+HeadlessBrowserContext::Builder::SetAllowCookies(bool allow_cookies) {
+ options_->allow_cookies_ = allow_cookies;
+ return *this;
+}
+
+HeadlessBrowserContext::Builder&
HeadlessBrowserContext::Builder::AddTabSocketMojoBindings() {
std::string js_bindings =
ui::ResourceBundle::GetSharedInstance()
@@ -514,13 +519,13 @@ HeadlessBrowserContext* HeadlessBrowserContext::Builder::Build() {
return browser_->CreateBrowserContext(this);
}
-HeadlessBrowserContext::Builder::MojoBindings::MojoBindings() {}
+HeadlessBrowserContext::Builder::MojoBindings::MojoBindings() = default;
HeadlessBrowserContext::Builder::MojoBindings::MojoBindings(
const std::string& mojom_name,
const std::string& js_bindings)
: mojom_name(mojom_name), js_bindings(js_bindings) {}
-HeadlessBrowserContext::Builder::MojoBindings::~MojoBindings() {}
+HeadlessBrowserContext::Builder::MojoBindings::~MojoBindings() = default;
} // namespace headless
diff --git a/chromium/headless/lib/browser/headless_browser_context_impl.h b/chromium/headless/lib/browser/headless_browser_context_impl.h
index 580b8b0e15f..d84727c1a5d 100644
--- a/chromium/headless/lib/browser/headless_browser_context_impl.h
+++ b/chromium/headless/lib/browser/headless_browser_context_impl.h
@@ -13,7 +13,6 @@
#include "base/files/file_path.h"
#include "base/unguessable_token.h"
#include "content/public/browser/browser_context.h"
-#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/resource_context.h"
#include "headless/lib/browser/headless_browser_context_options.h"
#include "headless/lib/browser/headless_network_conditions.h"
@@ -120,7 +119,7 @@ class HeadlessBrowserContextImpl : public HeadlessBrowserContext,
bool canceled_by_devtools);
void SetNetworkConditions(HeadlessNetworkConditions conditions);
- HeadlessNetworkConditions GetNetworkConditions();
+ HeadlessNetworkConditions GetNetworkConditions() override;
private:
HeadlessBrowserContextImpl(
diff --git a/chromium/headless/lib/browser/headless_browser_context_options.cc b/chromium/headless/lib/browser/headless_browser_context_options.cc
index 5898576830a..93e078083b7 100644
--- a/chromium/headless/lib/browser/headless_browser_context_options.cc
+++ b/chromium/headless/lib/browser/headless_browser_context_options.cc
@@ -74,6 +74,10 @@ bool HeadlessBrowserContextOptions::incognito_mode() const {
browser_options_->incognito_mode);
}
+bool HeadlessBrowserContextOptions::allow_cookies() const {
+ return ReturnOverriddenValue(allow_cookies_, browser_options_->allow_cookies);
+}
+
const base::Callback<void(WebPreferences*)>&
HeadlessBrowserContextOptions::override_web_preferences_callback() const {
return ReturnOverriddenValue(
diff --git a/chromium/headless/lib/browser/headless_browser_context_options.h b/chromium/headless/lib/browser/headless_browser_context_options.h
index 23a4f6251a7..00e1295f751 100644
--- a/chromium/headless/lib/browser/headless_browser_context_options.h
+++ b/chromium/headless/lib/browser/headless_browser_context_options.h
@@ -44,6 +44,8 @@ class HeadlessBrowserContextOptions {
// Set HeadlessBrowser::Options::incognito_mode.
bool incognito_mode() const;
+ bool allow_cookies() const;
+
// Custom network protocol handlers. These can be used to override URL
// fetching for different network schemes.
const ProtocolHandlerMap& protocol_handlers() const;
@@ -70,6 +72,7 @@ class HeadlessBrowserContextOptions {
base::Optional<gfx::Size> window_size_;
base::Optional<base::FilePath> user_data_dir_;
base::Optional<bool> incognito_mode_;
+ base::Optional<bool> allow_cookies_;
base::Optional<base::Callback<void(WebPreferences*)>>
override_web_preferences_callback_;
diff --git a/chromium/headless/lib/browser/headless_browser_impl.cc b/chromium/headless/lib/browser/headless_browser_impl.cc
index bbd231c1bb3..88bede99b53 100644
--- a/chromium/headless/lib/browser/headless_browser_impl.cc
+++ b/chromium/headless/lib/browser/headless_browser_impl.cc
@@ -77,7 +77,7 @@ HeadlessBrowserImpl::HeadlessBrowserImpl(
agent_host_(nullptr),
weak_ptr_factory_(this) {}
-HeadlessBrowserImpl::~HeadlessBrowserImpl() {}
+HeadlessBrowserImpl::~HeadlessBrowserImpl() = default;
HeadlessBrowserContext::Builder
HeadlessBrowserImpl::CreateBrowserContextBuilder() {
@@ -103,7 +103,10 @@ void HeadlessBrowserImpl::Shutdown() {
weak_ptr_factory_.InvalidateWeakPtrs();
// Destroy all browser contexts.
- browser_contexts_.clear();
+ {
+ base::AutoLock lock(browser_contexts_lock_);
+ browser_contexts_.clear();
+ }
BrowserMainThread()->PostTask(FROM_HERE,
base::MessageLoop::QuitWhenIdleClosure());
@@ -112,6 +115,7 @@ void HeadlessBrowserImpl::Shutdown() {
std::vector<HeadlessBrowserContext*>
HeadlessBrowserImpl::GetAllBrowserContexts() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ base::AutoLock lock(browser_contexts_lock_);
std::vector<HeadlessBrowserContext*> result;
result.reserve(browser_contexts_.size());
@@ -162,6 +166,7 @@ HeadlessBrowserContext* HeadlessBrowserImpl::CreateBrowserContext(
HeadlessBrowserContext* result = browser_context.get();
+ base::AutoLock lock(browser_contexts_lock_);
browser_contexts_[browser_context->Id()] = std::move(browser_context);
return result;
@@ -169,6 +174,7 @@ HeadlessBrowserContext* HeadlessBrowserImpl::CreateBrowserContext(
void HeadlessBrowserImpl::DestroyBrowserContext(
HeadlessBrowserContextImpl* browser_context) {
+ base::AutoLock lock(browser_contexts_lock_);
auto it = browser_contexts_.find(browser_context->Id());
DCHECK(it != browser_contexts_.end());
browser_contexts_.erase(it);
@@ -218,12 +224,26 @@ HeadlessWebContentsImpl* HeadlessBrowserImpl::GetWebContentsForWindowId(
HeadlessBrowserContext* HeadlessBrowserImpl::GetBrowserContextForId(
const std::string& id) {
+ base::AutoLock lock(browser_contexts_lock_);
auto find_it = browser_contexts_.find(id);
if (find_it == browser_contexts_.end())
return nullptr;
return find_it->second.get();
}
+LockedPtr<HeadlessBrowserContextImpl>
+HeadlessBrowserImpl::GetBrowserContextForRenderFrame(
+ int render_process_id,
+ int render_frame_id) const {
+ MoveableAutoLock lock(browser_contexts_lock_);
+ for (const auto& pair : browser_contexts_) {
+ if (pair.second->GetDevToolsFrameToken(render_process_id, render_frame_id))
+ return LockedPtr<HeadlessBrowserContextImpl>(std::move(lock),
+ pair.second.get());
+ }
+ return LockedPtr<HeadlessBrowserContextImpl>(std::move(lock), nullptr);
+}
+
HeadlessDevToolsTarget* HeadlessBrowserImpl::GetDevToolsTarget() {
return agent_host_ ? this : nullptr;
}
diff --git a/chromium/headless/lib/browser/headless_browser_impl.h b/chromium/headless/lib/browser/headless_browser_impl.h
index 591e50a0532..7f4ec64dc20 100644
--- a/chromium/headless/lib/browser/headless_browser_impl.h
+++ b/chromium/headless/lib/browser/headless_browser_impl.h
@@ -18,6 +18,7 @@
#include "headless/lib/browser/headless_devtools_manager_delegate.h"
#include "headless/lib/browser/headless_web_contents_impl.h"
#include "headless/public/headless_export.h"
+#include "headless/public/util/moveable_auto_lock.h"
namespace ui {
class Compositor;
@@ -78,6 +79,12 @@ class HEADLESS_EXPORT HeadlessBrowserImpl : public HeadlessBrowser,
base::WeakPtr<HeadlessBrowserImpl> GetWeakPtr();
+ // Returns the corresponding HeadlessBrowserContextImpl or null if one can't
+ // be found. Can be called on any thread.
+ LockedPtr<HeadlessBrowserContextImpl> GetBrowserContextForRenderFrame(
+ int render_process_id,
+ int render_frame_id) const;
+
// All the methods that begin with Platform need to be implemented by the
// platform specific headless implementation.
// Helper for one time initialization of application
@@ -93,7 +100,8 @@ class HEADLESS_EXPORT HeadlessBrowserImpl : public HeadlessBrowser,
HeadlessBrowser::Options options_;
HeadlessBrowserMainParts* browser_main_parts_; // Not owned.
- std::unordered_map<std::string, std::unique_ptr<HeadlessBrowserContextImpl>>
+ mutable base::Lock browser_contexts_lock_; // Protects |browser_contexts_|
+ base::flat_map<std::string, std::unique_ptr<HeadlessBrowserContextImpl>>
browser_contexts_;
HeadlessBrowserContext* default_browser_context_; // Not owned.
diff --git a/chromium/headless/lib/browser/headless_browser_main_parts.cc b/chromium/headless/lib/browser/headless_browser_main_parts.cc
index 64e9018f5e3..da66fb7f75d 100644
--- a/chromium/headless/lib/browser/headless_browser_main_parts.cc
+++ b/chromium/headless/lib/browser/headless_browser_main_parts.cc
@@ -18,7 +18,7 @@ HeadlessBrowserMainParts::HeadlessBrowserMainParts(HeadlessBrowserImpl* browser)
: browser_(browser)
, devtools_http_handler_started_(false) {}
-HeadlessBrowserMainParts::~HeadlessBrowserMainParts() {}
+HeadlessBrowserMainParts::~HeadlessBrowserMainParts() = default;
void HeadlessBrowserMainParts::PreMainMessageLoopRun() {
const base::CommandLine* command_line =
diff --git a/chromium/headless/lib/browser/headless_clipboard.cc b/chromium/headless/lib/browser/headless_clipboard.cc
index dcadd4c36c1..9b9fd069746 100644
--- a/chromium/headless/lib/browser/headless_clipboard.cc
+++ b/chromium/headless/lib/browser/headless_clipboard.cc
@@ -13,7 +13,7 @@ namespace headless {
HeadlessClipboard::HeadlessClipboard()
: default_store_type_(ui::CLIPBOARD_TYPE_COPY_PASTE) {}
-HeadlessClipboard::~HeadlessClipboard() {}
+HeadlessClipboard::~HeadlessClipboard() = default;
void HeadlessClipboard::OnPreShutdown() {}
@@ -182,7 +182,7 @@ HeadlessClipboard::DataStore::DataStore() : sequence_number(0) {}
HeadlessClipboard::DataStore::DataStore(const DataStore& other) = default;
-HeadlessClipboard::DataStore::~DataStore() {}
+HeadlessClipboard::DataStore::~DataStore() = default;
void HeadlessClipboard::DataStore::Clear() {
data.clear();
diff --git a/chromium/headless/lib/browser/headless_content_browser_client.cc b/chromium/headless/lib/browser/headless_content_browser_client.cc
index d96b9886839..98434626717 100644
--- a/chromium/headless/lib/browser/headless_content_browser_client.cc
+++ b/chromium/headless/lib/browser/headless_content_browser_client.cc
@@ -14,6 +14,7 @@
#include "base/memory/ptr_util.h"
#include "base/path_service.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/resource_dispatcher_host.h"
@@ -114,9 +115,11 @@ int GetCrashSignalFD(const base::CommandLine& command_line,
HeadlessContentBrowserClient::HeadlessContentBrowserClient(
HeadlessBrowserImpl* browser)
- : browser_(browser) {}
+ : browser_(browser),
+ append_command_line_flags_callback_(
+ browser_->options()->append_command_line_flags_callback) {}
-HeadlessContentBrowserClient::~HeadlessContentBrowserClient() {}
+HeadlessContentBrowserClient::~HeadlessContentBrowserClient() = default;
content::BrowserMainParts* HeadlessContentBrowserClient::CreateBrowserMainParts(
const content::MainFunctionParams&) {
@@ -230,6 +233,9 @@ void HeadlessContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
void HeadlessContentBrowserClient::AppendExtraCommandLineSwitches(
base::CommandLine* command_line,
int child_process_id) {
+ // NOTE: We may be called on the UI or IO thread. If called on the IO thread,
+ // |browser_| may have already been destroyed.
+
command_line->AppendSwitch(::switches::kHeadless);
const base::CommandLine& old_command_line(
*base::CommandLine::ForCurrentProcess());
@@ -245,8 +251,10 @@ void HeadlessContentBrowserClient::AppendExtraCommandLineSwitches(
#endif // defined(HEADLESS_USE_BREAKPAD)
// If we're spawning a renderer, then override the language switch.
- if (command_line->GetSwitchValueASCII(::switches::kProcessType) ==
- ::switches::kRendererProcess) {
+ std::string process_type =
+ command_line->GetSwitchValueASCII(::switches::kProcessType);
+ if (process_type == ::switches::kRendererProcess) {
+ // Renderer processes are initialized on the UI thread, so this is safe.
content::RenderProcessHost* render_process_host =
content::RenderProcessHost::FromID(child_process_id);
if (render_process_host) {
@@ -262,6 +270,22 @@ void HeadlessContentBrowserClient::AppendExtraCommandLineSwitches(
}
}
}
+
+ if (append_command_line_flags_callback_) {
+ HeadlessBrowserContextImpl* headless_browser_context_impl = nullptr;
+ if (process_type == ::switches::kRendererProcess) {
+ // Renderer processes are initialized on the UI thread, so this is safe.
+ content::RenderProcessHost* render_process_host =
+ content::RenderProcessHost::FromID(child_process_id);
+ if (render_process_host) {
+ headless_browser_context_impl = HeadlessBrowserContextImpl::From(
+ render_process_host->GetBrowserContext());
+ }
+ }
+ append_command_line_flags_callback_.Run(command_line,
+ headless_browser_context_impl,
+ process_type, child_process_id);
+ }
}
void HeadlessContentBrowserClient::AllowCertificateError(
@@ -290,8 +314,7 @@ void HeadlessContentBrowserClient::AllowCertificateError(
void HeadlessContentBrowserClient::ResourceDispatcherHostCreated() {
resource_dispatcher_host_delegate_.reset(
- new HeadlessResourceDispatcherHostDelegate(
- browser_->options()->enable_resource_scheduler));
+ new HeadlessResourceDispatcherHostDelegate);
content::ResourceDispatcherHost::Get()->SetDelegate(
resource_dispatcher_host_delegate_.get());
}
@@ -300,4 +323,37 @@ net::NetLog* HeadlessContentBrowserClient::GetNetLog() {
return browser_->browser_main_parts()->net_log();
}
+bool HeadlessContentBrowserClient::AllowGetCookie(
+ const GURL& url,
+ const GURL& first_party,
+ const net::CookieList& cookie_list,
+ content::ResourceContext* context,
+ int render_process_id,
+ int render_frame_id) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ LockedPtr<HeadlessBrowserContextImpl> browser_context =
+ browser_->GetBrowserContextForRenderFrame(render_process_id,
+ render_frame_id);
+ if (!browser_context)
+ return false;
+ return browser_context->options()->allow_cookies();
+}
+
+bool HeadlessContentBrowserClient::AllowSetCookie(
+ const GURL& url,
+ const GURL& first_party,
+ const net::CanonicalCookie& cookie,
+ content::ResourceContext* context,
+ int render_process_id,
+ int render_frame_id,
+ const net::CookieOptions& options) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ LockedPtr<HeadlessBrowserContextImpl> browser_context =
+ browser_->GetBrowserContextForRenderFrame(render_process_id,
+ render_frame_id);
+ if (!browser_context)
+ return false;
+ return browser_context->options()->allow_cookies();
+}
+
} // 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 929bc9f346b..6a7daae9ad8 100644
--- a/chromium/headless/lib/browser/headless_content_browser_client.h
+++ b/chromium/headless/lib/browser/headless_content_browser_client.h
@@ -7,6 +7,7 @@
#include "content/public/browser/content_browser_client.h"
#include "headless/lib/browser/headless_resource_dispatcher_host_delegate.h"
+#include "headless/public/headless_browser.h"
namespace headless {
@@ -55,6 +56,21 @@ class HeadlessContentBrowserClient : public content::ContentBrowserClient {
net::NetLog* GetNetLog() override;
+ bool AllowGetCookie(const GURL& url,
+ const GURL& first_party,
+ const net::CookieList& cookie_list,
+ content::ResourceContext* context,
+ int render_process_id,
+ int render_frame_id) override;
+
+ bool AllowSetCookie(const GURL& url,
+ const GURL& first_party,
+ const net::CanonicalCookie& cookie,
+ content::ResourceContext* context,
+ int render_process_id,
+ int render_frame_id,
+ const net::CookieOptions& options) override;
+
private:
std::unique_ptr<base::Value> GetBrowserServiceManifestOverlay();
std::unique_ptr<base::Value> GetRendererServiceManifestOverlay();
@@ -62,6 +78,10 @@ class HeadlessContentBrowserClient : public content::ContentBrowserClient {
HeadlessBrowserImpl* browser_; // Not owned.
+ // We store the callback here because we may call it from the I/O thread.
+ HeadlessBrowser::Options::AppendCommandLineFlagsCallback
+ append_command_line_flags_callback_;
+
std::unique_ptr<HeadlessResourceDispatcherHostDelegate>
resource_dispatcher_host_delegate_;
diff --git a/chromium/headless/lib/browser/headless_devtools_client_impl.cc b/chromium/headless/lib/browser/headless_devtools_client_impl.cc
index 8cf1e5e5274..9763565c59b 100644
--- a/chromium/headless/lib/browser/headless_devtools_client_impl.cc
+++ b/chromium/headless/lib/browser/headless_devtools_client_impl.cc
@@ -61,6 +61,7 @@ HeadlessDevToolsClientImpl::HeadlessDevToolsClientImpl()
memory_domain_(this),
network_domain_(this),
page_domain_(this),
+ performance_domain_(this),
profiler_domain_(this),
runtime_domain_(this),
security_domain_(this),
@@ -71,7 +72,7 @@ HeadlessDevToolsClientImpl::HeadlessDevToolsClientImpl()
content::BrowserThread::UI)),
weak_ptr_factory_(this) {}
-HeadlessDevToolsClientImpl::~HeadlessDevToolsClientImpl() {}
+HeadlessDevToolsClientImpl::~HeadlessDevToolsClientImpl() = default;
bool HeadlessDevToolsClientImpl::AttachToHost(
content::DevToolsAgentHost* agent_host) {
@@ -115,14 +116,13 @@ void HeadlessDevToolsClientImpl::SendRawDevToolsMessage(
#ifndef NDEBUG
std::unique_ptr<base::Value> message =
base::JSONReader::Read(json_message, base::JSON_PARSE_RFC);
- const base::DictionaryValue* message_dict;
- int id = 0;
- if (!message || !message->GetAsDictionary(&message_dict) ||
- !message_dict->GetInteger("id", &id)) {
- NOTREACHED() << "Badly formed message";
+ const base::Value* id_value = message->FindKey("id");
+ if (!id_value) {
+ NOTREACHED() << "Badly formed message " << json_message;
return;
}
- DCHECK_EQ((id % 2), 1) << "Raw devtools messages must have an odd ID.";
+ DCHECK_EQ((id_value->GetInt() % 2), 1)
+ << "Raw devtools messages must have an odd ID.";
#endif
agent_host_->DispatchProtocolMessage(this, json_message);
@@ -162,10 +162,10 @@ void HeadlessDevToolsClientImpl::DispatchProtocolMessage(
bool HeadlessDevToolsClientImpl::DispatchMessageReply(
const base::DictionaryValue& message_dict) {
- int id = 0;
- if (!message_dict.GetInteger("id", &id))
+ const base::Value* id_value = message_dict.FindKey("id");
+ if (!id_value)
return false;
- auto it = pending_messages_.find(id);
+ auto it = pending_messages_.find(id_value->GetInt());
if (it == pending_messages_.end()) {
NOTREACHED() << "Unexpected reply";
return false;
@@ -193,9 +193,10 @@ bool HeadlessDevToolsClientImpl::DispatchMessageReply(
bool HeadlessDevToolsClientImpl::DispatchEvent(
std::unique_ptr<base::Value> owning_message,
const base::DictionaryValue& message_dict) {
- std::string method;
- if (!message_dict.GetString("method", &method))
+ const base::Value* method_value = message_dict.FindKey("method");
+ if (!method_value)
return false;
+ const std::string& method = method_value->GetString();
if (method == "Inspector.targetCrashed")
renderer_crashed_ = true;
EventHandlerMap::const_iterator it = event_handlers_.find(method);
@@ -228,8 +229,7 @@ void HeadlessDevToolsClientImpl::DispatchEventTask(
}
void HeadlessDevToolsClientImpl::AgentHostClosed(
- content::DevToolsAgentHost* agent_host,
- bool replaced_with_another_client) {
+ content::DevToolsAgentHost* agent_host) {
DCHECK_EQ(agent_host_, agent_host);
agent_host = nullptr;
pending_messages_.clear();
@@ -340,6 +340,10 @@ page::Domain* HeadlessDevToolsClientImpl::GetPage() {
return &page_domain_;
}
+performance::Domain* HeadlessDevToolsClientImpl::GetPerformance() {
+ return &performance_domain_;
+}
+
profiler::Domain* HeadlessDevToolsClientImpl::GetProfiler() {
return &profiler_domain_;
}
@@ -412,7 +416,7 @@ void HeadlessDevToolsClientImpl::RegisterEventHandler(
event_handlers_[method] = callback;
}
-HeadlessDevToolsClientImpl::Callback::Callback() {}
+HeadlessDevToolsClientImpl::Callback::Callback() = default;
HeadlessDevToolsClientImpl::Callback::Callback(Callback&& other) = default;
@@ -423,7 +427,7 @@ HeadlessDevToolsClientImpl::Callback::Callback(
base::Callback<void(const base::Value&)> callback)
: callback_with_result(callback) {}
-HeadlessDevToolsClientImpl::Callback::~Callback() {}
+HeadlessDevToolsClientImpl::Callback::~Callback() = default;
HeadlessDevToolsClientImpl::Callback& HeadlessDevToolsClientImpl::Callback::
operator=(Callback&& other) = default;
diff --git a/chromium/headless/lib/browser/headless_devtools_manager_delegate.cc b/chromium/headless/lib/browser/headless_devtools_manager_delegate.cc
index 498aafcf51f..553d7159b51 100644
--- a/chromium/headless/lib/browser/headless_devtools_manager_delegate.cc
+++ b/chromium/headless/lib/browser/headless_devtools_manager_delegate.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/base64.h"
+#include "base/command_line.h"
#include "base/json/json_writer.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
@@ -20,7 +21,6 @@
#include "headless/grit/headless_lib_resources.h"
#include "headless/lib/browser/headless_browser_context_impl.h"
#include "headless/lib/browser/headless_browser_impl.h"
-#include "headless/lib/browser/headless_network_conditions.h"
#include "headless/lib/browser/headless_web_contents_impl.h"
#include "headless/public/devtools/domains/target.h"
#include "printing/units.h"
@@ -155,9 +155,11 @@ void OnBeginFrameFinished(
ImageEncoding encoding,
int quality,
bool has_damage,
+ bool main_frame_content_updated,
std::unique_ptr<SkBitmap> bitmap) {
auto result = base::MakeUnique<base::DictionaryValue>();
result->SetBoolean("hasDamage", has_damage);
+ result->SetBoolean("mainFrameContentUpdated", main_frame_content_updated);
if (bitmap && !bitmap->drawsNothing()) {
result->SetString("screenshotData",
@@ -182,21 +184,42 @@ std::unique_ptr<base::DictionaryValue> ParsePrintSettings(
HeadlessPrintSettings* settings) {
// We can safely ignore the return values of the following Get methods since
// the defaults are already set in |settings|.
- params->GetBoolean("landscape", &settings->landscape);
- params->GetBoolean("displayHeaderFooter", &settings->display_header_footer);
- params->GetBoolean("printBackground", &settings->should_print_backgrounds);
- params->GetDouble("scale", &settings->scale);
+ if (const base::Value* landscape_value = params->FindKey("landscape"))
+ settings->landscape = landscape_value->GetBool();
+
+ if (const base::Value* display_header_footer_value =
+ params->FindKey("displayHeaderFooter")) {
+ settings->display_header_footer = display_header_footer_value->GetBool();
+ }
+
+ if (const base::Value* should_print_backgrounds_value =
+ params->FindKey("printBackground")) {
+ settings->should_print_backgrounds =
+ should_print_backgrounds_value->GetBool();
+ }
+ if (const base::Value* scale_value = params->FindKey("scale"))
+ settings->scale = scale_value->GetDouble();
if (settings->scale > kScaleMaxVal / 100 ||
settings->scale < kScaleMinVal / 100)
return CreateInvalidParamResponse(command_id, "scale");
- params->GetString("pageRanges", &settings->page_ranges);
- params->GetBoolean("ignoreInvalidPageRanges",
- &settings->ignore_invalid_page_ranges);
+ if (const base::Value* page_ranges_value = params->FindKey("pageRanges"))
+ settings->page_ranges = page_ranges_value->GetString();
+
+ if (const base::Value* ignore_invalid_page_ranges_value =
+ params->FindKey("ignoreInvalidPageRanges")) {
+ settings->ignore_invalid_page_ranges =
+ ignore_invalid_page_ranges_value->GetBool();
+ }
double paper_width_in_inch = printing::kLetterWidthInch;
+
+ if (const base::Value* paper_width_value = params->FindKey("paperWidth"))
+ paper_width_in_inch = paper_width_value->GetDouble();
+
double paper_height_in_inch = printing::kLetterHeightInch;
- params->GetDouble("paperWidth", &paper_width_in_inch);
- params->GetDouble("paperHeight", &paper_height_in_inch);
+
+ if (const base::Value* paper_height_value = params->FindKey("paperHeight"))
+ paper_height_in_inch = paper_height_value->GetDouble();
if (paper_width_in_inch <= 0)
return CreateInvalidParamResponse(command_id, "paperWidth");
if (paper_height_in_inch <= 0)
@@ -211,10 +234,19 @@ std::unique_ptr<base::DictionaryValue> ParsePrintSettings(
double margin_bottom_in_inch = default_margin_in_inch;
double margin_left_in_inch = default_margin_in_inch;
double margin_right_in_inch = default_margin_in_inch;
- params->GetDouble("marginTop", &margin_top_in_inch);
- params->GetDouble("marginBottom", &margin_bottom_in_inch);
- params->GetDouble("marginLeft", &margin_left_in_inch);
- params->GetDouble("marginRight", &margin_right_in_inch);
+
+ if (const base::Value* margin_top_value = params->FindKey("marginTop"))
+ margin_top_in_inch = margin_top_value->GetDouble();
+
+ if (const base::Value* margin_bottom_value = params->FindKey("marginBottom"))
+ margin_bottom_in_inch = margin_bottom_value->GetDouble();
+
+ if (const base::Value* margin_left_value = params->FindKey("marginLeft"))
+ margin_left_in_inch = margin_left_value->GetDouble();
+
+ if (const base::Value* margin_right_value = params->FindKey("marginRight"))
+ margin_right_in_inch = margin_right_value->GetDouble();
+
if (margin_top_in_inch < 0)
return CreateInvalidParamResponse(command_id, "marginTop");
if (margin_bottom_in_inch < 0)
@@ -281,7 +313,7 @@ HeadlessDevToolsManagerDelegate::HeadlessDevToolsManagerDelegate(
&HeadlessDevToolsManagerDelegate::BeginFrame, base::Unretained(this));
}
-HeadlessDevToolsManagerDelegate::~HeadlessDevToolsManagerDelegate() {}
+HeadlessDevToolsManagerDelegate::~HeadlessDevToolsManagerDelegate() = default;
bool HeadlessDevToolsManagerDelegate::HandleCommand(
content::DevToolsAgentHost* agent_host,
@@ -292,21 +324,22 @@ bool HeadlessDevToolsManagerDelegate::HandleCommand(
if (!browser_)
return false;
- int id;
- std::string method;
- if (!command->GetInteger("id", &id) || !command->GetString("method", &method))
+ const base::Value* id_value = command->FindKey("id");
+ const base::Value* method_value = command->FindKey("method");
+ if (!id_value || !method_value)
return false;
const base::DictionaryValue* params = nullptr;
command->GetDictionary("params", &params);
+ const std::string& method = method_value->GetString();
auto find_it = command_map_.find(method);
if (find_it == command_map_.end()) {
// Check for any commands that are actioned then passed on to devtools to
// handle.
find_it = unhandled_command_map_.find(method);
if (find_it != unhandled_command_map_.end())
- find_it->second.Run(agent_host, session_id, id, params);
+ find_it->second.Run(agent_host, session_id, id_value->GetInt(), params);
return false;
}
@@ -315,7 +348,8 @@ bool HeadlessDevToolsManagerDelegate::HandleCommand(
agent_host->GetType() != content::DevToolsAgentHost::kTypeBrowser)
return false;
- auto cmd_result = find_it->second.Run(agent_host, session_id, id, params);
+ auto cmd_result =
+ find_it->second.Run(agent_host, session_id, id_value->GetInt(), params);
if (!cmd_result)
return false;
agent_host->SendProtocolMessageToClient(session_id,
@@ -333,18 +367,19 @@ bool HeadlessDevToolsManagerDelegate::HandleAsyncCommand(
if (!browser_)
return false;
- int id;
- std::string method;
- if (!command->GetInteger("id", &id) || !command->GetString("method", &method))
+ const base::Value* id_value = command->FindKey("id");
+ const base::Value* method_value = command->FindKey("method");
+ if (!id_value || !method_value)
return false;
- auto find_it = async_command_map_.find(method);
+ auto find_it = async_command_map_.find(method_value->GetString());
if (find_it == async_command_map_.end())
return false;
const base::DictionaryValue* params = nullptr;
command->GetDictionary("params", &params);
- find_it->second.Run(agent_host, session_id, id, params, callback);
+ find_it->second.Run(agent_host, session_id, id_value->GetInt(), params,
+ callback);
return true;
}
@@ -432,16 +467,32 @@ HeadlessDevToolsManagerDelegate::CreateTarget(
int command_id,
const base::DictionaryValue* params) {
std::string url;
+
+ if (const base::Value* url_value = params->FindKey("url")) {
+ url = url_value->GetString();
+ } else {
+ return CreateInvalidParamResponse(command_id, "url");
+ }
+
std::string browser_context_id;
+ if (const base::Value* browser_context_id_value =
+ params->FindKey("browserContextId")) {
+ browser_context_id = browser_context_id_value->GetString();
+ }
+
int width = browser_->options()->window_size.width();
+ if (const base::Value* width_value = params->FindKey("width"))
+ width = width_value->GetInt();
+
int height = browser_->options()->window_size.height();
- if (!params || !params->GetString("url", &url))
- return CreateInvalidParamResponse(command_id, "url");
+ if (const base::Value* height_value = params->FindKey("height"))
+ height = height_value->GetInt();
+
bool enable_begin_frame_control = false;
- params->GetString("browserContextId", &browser_context_id);
- params->GetInteger("width", &width);
- params->GetInteger("height", &height);
- params->GetBoolean("enableBeginFrameControl", &enable_begin_frame_control);
+ if (const base::Value* enable_begin_frame_control_value =
+ params->FindKey("enableBeginFrameControl")) {
+ enable_begin_frame_control = enable_begin_frame_control_value->GetBool();
+ }
#if defined(OS_MACOSX)
if (enable_begin_frame_control) {
@@ -488,11 +539,12 @@ HeadlessDevToolsManagerDelegate::CloseTarget(
int session_id,
int command_id,
const base::DictionaryValue* params) {
- std::string target_id;
- if (!params || !params->GetString("targetId", &target_id))
+ const base::Value* target_id_value = params->FindKey("targetId");
+ if (!target_id_value)
return CreateInvalidParamResponse(command_id, "targetId");
HeadlessWebContents* web_contents =
- browser_->GetWebContentsForDevToolsAgentHostId(target_id);
+ browser_->GetWebContentsForDevToolsAgentHostId(
+ target_id_value->GetString());
bool success = false;
if (web_contents) {
web_contents->Close();
@@ -528,11 +580,13 @@ HeadlessDevToolsManagerDelegate::DisposeBrowserContext(
int session_id,
int command_id,
const base::DictionaryValue* params) {
- std::string browser_context_id;
- if (!params || !params->GetString("browserContextId", &browser_context_id))
+ const base::Value* browser_context_id_value =
+ params->FindKey("browserContextId");
+ if (!browser_context_id_value)
return CreateInvalidParamResponse(command_id, "browserContextId");
+
HeadlessBrowserContext* context =
- browser_->GetBrowserContextForId(browser_context_id);
+ browser_->GetBrowserContextForId(browser_context_id_value->GetString());
bool success = false;
if (context && context != browser_->GetDefaultBrowserContext() &&
@@ -555,12 +609,13 @@ HeadlessDevToolsManagerDelegate::GetWindowForTarget(
int session_id,
int command_id,
const base::DictionaryValue* params) {
- std::string target_id;
- if (!params->GetString("targetId", &target_id))
+ const base::Value* target_id_value = params->FindKey("targetId");
+ if (!target_id_value)
return CreateInvalidParamResponse(command_id, "targetId");
HeadlessWebContentsImpl* web_contents = HeadlessWebContentsImpl::From(
- browser_->GetWebContentsForDevToolsAgentHostId(target_id));
+ browser_->GetWebContentsForDevToolsAgentHostId(
+ target_id_value->GetString()));
if (!web_contents) {
return CreateErrorResponse(command_id, kErrorServerError,
"No web contents for the given target id");
@@ -590,11 +645,11 @@ HeadlessDevToolsManagerDelegate::GetWindowBounds(
int session_id,
int command_id,
const base::DictionaryValue* params) {
- int window_id;
- if (!params->GetInteger("windowId", &window_id))
+ HeadlessWebContentsImpl* web_contents;
+ const base::Value* window_id_value = params->FindKey("windowId");
+ if (!window_id_value || !window_id_value->is_int())
return CreateInvalidParamResponse(command_id, "windowId");
- HeadlessWebContentsImpl* web_contents =
- browser_->GetWebContentsForWindowId(window_id);
+ web_contents = browser_->GetWebContentsForWindowId(window_id_value->GetInt());
if (!web_contents) {
return CreateErrorResponse(command_id, kErrorServerError,
"Browser window not found");
@@ -611,48 +666,56 @@ HeadlessDevToolsManagerDelegate::SetWindowBounds(
int session_id,
int command_id,
const base::DictionaryValue* params) {
- int window_id;
- if (!params->GetInteger("windowId", &window_id))
+ HeadlessWebContentsImpl* web_contents;
+ const base::Value* window_id_value = params->FindKey("windowId");
+ if (!window_id_value || !window_id_value->is_int())
return CreateInvalidParamResponse(command_id, "windowId");
- HeadlessWebContentsImpl* web_contents =
- browser_->GetWebContentsForWindowId(window_id);
+ web_contents = browser_->GetWebContentsForWindowId(window_id_value->GetInt());
+
if (!web_contents) {
return CreateErrorResponse(command_id, kErrorServerError,
"Browser window not found");
}
- const base::Value* value = nullptr;
- const base::DictionaryValue* bounds_dict = nullptr;
- if (!params->Get("bounds", &value) || !value->GetAsDictionary(&bounds_dict))
+ const base::Value* bounds_value = params->FindKey("bounds");
+ if (!bounds_value || !bounds_value->is_dict())
return CreateInvalidParamResponse(command_id, "bounds");
std::string window_state;
- if (!bounds_dict->GetString("windowState", &window_state)) {
+ if (const base::Value* window_state_value =
+ bounds_value->FindKey("windowState")) {
+ window_state = window_state_value->GetString();
+ if (window_state != "normal" && window_state != "minimized" &&
+ window_state != "maximized" && window_state != "fullscreen") {
+ return CreateInvalidParamResponse(command_id, "windowState");
+ }
+ } else {
window_state = "normal";
- } else if (window_state != "normal" && window_state != "minimized" &&
- window_state != "maximized" && window_state != "fullscreen") {
- return CreateInvalidParamResponse(command_id, "windowState");
}
// Compute updated bounds when window state is normal.
bool set_bounds = false;
gfx::Rect bounds = web_contents->web_contents()->GetContainerBounds();
- int left, top, width, height;
- if (bounds_dict->GetInteger("left", &left)) {
- bounds.set_x(left);
+ if (const base::Value* left_value = bounds_value->FindKey("left")) {
+ bounds.set_x(left_value->GetInt());
set_bounds = true;
}
- if (bounds_dict->GetInteger("top", &top)) {
- bounds.set_y(top);
+
+ if (const base::Value* top_value = bounds_value->FindKey("top")) {
+ bounds.set_y(top_value->GetInt());
set_bounds = true;
}
- if (bounds_dict->GetInteger("width", &width)) {
+
+ if (const base::Value* width_value = bounds_value->FindKey("width")) {
+ int width = width_value->GetInt();
if (width < 0)
return CreateInvalidParamResponse(command_id, "width");
bounds.set_width(width);
set_bounds = true;
}
- if (bounds_dict->GetInteger("height", &height)) {
+
+ if (const base::Value* height_value = bounds_value->FindKey("height")) {
+ int height = height_value->GetInt();
if (height < 0)
return CreateInvalidParamResponse(command_id, "height");
bounds.set_height(height);
@@ -685,19 +748,26 @@ HeadlessDevToolsManagerDelegate::EmulateNetworkConditions(
int command_id,
const base::DictionaryValue* params) {
// Associate NetworkConditions to context
- HeadlessBrowserContextImpl* browser_context =
- static_cast<HeadlessBrowserContextImpl*>(
- browser_->GetDefaultBrowserContext());
- bool offline = false;
- double latency = 0, download_throughput = 0, upload_throughput = 0;
- params->GetBoolean("offline", &offline);
- params->GetDouble("latency", &latency);
- params->GetDouble("downloadThroughput", &download_throughput);
- params->GetDouble("uploadThroughput", &upload_throughput);
+ std::vector<HeadlessBrowserContext*> browser_contexts =
+ browser_->GetAllBrowserContexts();
+ if (browser_contexts.empty())
+ return CreateSuccessResponse(command_id, nullptr);
+ const base::Value* offline_value = params->FindKey("offline");
+ const base::Value* latency_value = params->FindKey("latency");
+ const base::Value* download_throughput_value =
+ params->FindKey("downloadThroughput");
+ const base::Value* upload_throughput_value =
+ params->FindKey("uploadThroughput");
HeadlessNetworkConditions conditions(HeadlessNetworkConditions(
- offline, std::max(latency, 0.0), std::max(download_throughput, 0.0),
- std::max(upload_throughput, 0.0)));
- browser_context->SetNetworkConditions(conditions);
+ offline_value ? offline_value->GetBool() : false,
+ latency_value ? std::max(latency_value->GetDouble(), 0.0) : 0,
+ download_throughput_value
+ ? std::max(download_throughput_value->GetDouble(), 0.0)
+ : 0,
+ upload_throughput_value
+ ? std::max(upload_throughput_value->GetDouble(), 0.0)
+ : 0));
+ SetNetworkConditions(browser_contexts, conditions);
return CreateSuccessResponse(command_id, nullptr);
}
@@ -707,13 +777,26 @@ HeadlessDevToolsManagerDelegate::NetworkDisable(
int session_id,
int command_id,
const base::DictionaryValue* params) {
- HeadlessBrowserContextImpl* browser_context =
- static_cast<HeadlessBrowserContextImpl*>(
- browser_->GetDefaultBrowserContext());
- browser_context->SetNetworkConditions(HeadlessNetworkConditions());
+ std::vector<HeadlessBrowserContext*> browser_contexts =
+ browser_->GetAllBrowserContexts();
+ if (browser_contexts.empty())
+ return CreateSuccessResponse(command_id, nullptr);
+ SetNetworkConditions(browser_contexts, HeadlessNetworkConditions());
return CreateSuccessResponse(command_id, nullptr);
}
+void HeadlessDevToolsManagerDelegate::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);
+ }
+}
+
std::unique_ptr<base::DictionaryValue>
HeadlessDevToolsManagerDelegate::EnableHeadlessExperimental(
content::DevToolsAgentHost* agent_host,
@@ -774,24 +857,21 @@ void HeadlessDevToolsManagerDelegate::BeginFrame(
return;
}
- double frame_time_double = 0;
- double deadline_double = 0;
- double interval_double = 0;
-
base::Time frame_time;
base::TimeTicks frame_timeticks;
base::TimeTicks deadline;
base::TimeDelta interval;
- if (params->GetDouble("frameTime", &frame_time_double)) {
- frame_time = base::Time::FromDoubleT(frame_time_double);
+ if (const base::Value* frame_time_value = params->FindKey("frameTime")) {
+ frame_time = base::Time::FromJsTime(frame_time_value->GetDouble());
base::TimeDelta delta = frame_time - base::Time::UnixEpoch();
frame_timeticks = base::TimeTicks::UnixEpoch() + delta;
} else {
frame_timeticks = base::TimeTicks::Now();
}
- if (params->GetDouble("interval", &interval_double)) {
+ if (const base::Value* interval_value = params->FindKey("interval")) {
+ double interval_double = interval_value->GetDouble();
if (interval_double <= 0) {
callback.Run(CreateErrorResponse(command_id, kErrorInvalidParam,
"interval has to be greater than 0"));
@@ -802,9 +882,9 @@ void HeadlessDevToolsManagerDelegate::BeginFrame(
interval = viz::BeginFrameArgs::DefaultInterval();
}
- if (params->GetDouble("deadline", &deadline_double)) {
+ if (const base::Value* deadline_value = params->FindKey("deadline")) {
base::TimeDelta delta =
- base::Time::FromDoubleT(deadline_double) - frame_time;
+ base::Time::FromDoubleT(deadline_value->GetDouble()) - frame_time;
if (delta <= base::TimeDelta()) {
callback.Run(CreateErrorResponse(command_id, kErrorInvalidParam,
"deadline has to be after frameTime"));
@@ -829,8 +909,8 @@ void HeadlessDevToolsManagerDelegate::BeginFrame(
capture_screenshot = true;
- std::string format;
- if (screenshot_dict->GetString("format", &format)) {
+ if (const base::Value* format_value = screenshot_dict->FindKey("format")) {
+ const std::string& format = format_value->GetString();
if (format == kPng) {
encoding = ImageEncoding::kPng;
} else if (format == kJpeg) {
@@ -842,12 +922,14 @@ void HeadlessDevToolsManagerDelegate::BeginFrame(
}
}
- if (screenshot_dict->GetInteger("quality", &quality) &&
- (quality < 0 || quality > 100)) {
- callback.Run(
- CreateErrorResponse(command_id, kErrorInvalidParam,
- "screenshot.quality has to be in range 0..100"));
- return;
+ if (const base::Value* quality_value = screenshot_dict->FindKey("quality")) {
+ quality = quality_value->GetInt();
+ if (quality < 0 || quality > 100) {
+ callback.Run(CreateErrorResponse(
+ command_id, kErrorInvalidParam,
+ "screenshot.quality has to be in range 0..100"));
+ return;
+ }
}
}
diff --git a/chromium/headless/lib/browser/headless_devtools_manager_delegate.h b/chromium/headless/lib/browser/headless_devtools_manager_delegate.h
index 9ad18ba1a07..b8fb8a81110 100644
--- a/chromium/headless/lib/browser/headless_devtools_manager_delegate.h
+++ b/chromium/headless/lib/browser/headless_devtools_manager_delegate.h
@@ -13,6 +13,8 @@
#include "base/memory/weak_ptr.h"
#include "base/values.h"
#include "content/public/browser/devtools_manager_delegate.h"
+#include "headless/lib/browser/headless_network_conditions.h"
+#include "headless/public/headless_browser_context.h"
#include "printing/features/features.h"
#if BUILDFLAG(ENABLE_BASIC_PRINTING)
@@ -116,6 +118,10 @@ class HeadlessDevToolsManagerDelegate
int command_id,
const base::DictionaryValue* params);
+ void SetNetworkConditions(
+ std::vector<HeadlessBrowserContext*> browser_contexts,
+ HeadlessNetworkConditions conditions);
+
void PrintToPDF(content::DevToolsAgentHost* agent_host,
int session_id,
int command_id,
diff --git a/chromium/headless/lib/browser/headless_focus_client.cc b/chromium/headless/lib/browser/headless_focus_client.cc
index 9a4e806e86c..c406c703861 100644
--- a/chromium/headless/lib/browser/headless_focus_client.cc
+++ b/chromium/headless/lib/browser/headless_focus_client.cc
@@ -12,7 +12,7 @@ namespace headless {
HeadlessFocusClient::HeadlessFocusClient()
: focused_window_(NULL), observer_manager_(this) {}
-HeadlessFocusClient::~HeadlessFocusClient() {}
+HeadlessFocusClient::~HeadlessFocusClient() = default;
void HeadlessFocusClient::AddObserver(
aura::client::FocusChangeObserver* observer) {
diff --git a/chromium/headless/lib/browser/headless_network_conditions.cc b/chromium/headless/lib/browser/headless_network_conditions.cc
index 3b7c643569e..208208c9020 100644
--- a/chromium/headless/lib/browser/headless_network_conditions.cc
+++ b/chromium/headless/lib/browser/headless_network_conditions.cc
@@ -21,6 +21,6 @@ HeadlessNetworkConditions::HeadlessNetworkConditions(bool offline,
download_throughput(download_throughput),
upload_throughput(upload_throughput) {}
-HeadlessNetworkConditions::~HeadlessNetworkConditions() {}
+HeadlessNetworkConditions::~HeadlessNetworkConditions() = default;
} // namespace headless
diff --git a/chromium/headless/lib/browser/headless_network_delegate.cc b/chromium/headless/lib/browser/headless_network_delegate.cc
index 28859f5f686..51e39600211 100644
--- a/chromium/headless/lib/browser/headless_network_delegate.cc
+++ b/chromium/headless/lib/browser/headless_network_delegate.cc
@@ -40,7 +40,9 @@ int HeadlessNetworkDelegate::OnBeforeURLRequest(
net::URLRequest* request,
const net::CompletionCallback& callback,
GURL* new_url) {
- if (headless_browser_context_->ShouldRemoveHeaders()) {
+ base::AutoLock lock(lock_);
+ if (headless_browser_context_ &&
+ headless_browser_context_->ShouldRemoveHeaders()) {
request->RemoveRequestHeaderByName(
kDevToolsEmulateNetworkConditionsClientId);
}
@@ -112,7 +114,7 @@ bool HeadlessNetworkDelegate::OnCanGetCookies(
}
bool HeadlessNetworkDelegate::OnCanSetCookie(const net::URLRequest& request,
- const std::string& cookie_line,
+ const net::CanonicalCookie& cookie,
net::CookieOptions* options) {
return true;
}
diff --git a/chromium/headless/lib/browser/headless_network_delegate.h b/chromium/headless/lib/browser/headless_network_delegate.h
index ccfb5f63976..66ed81528fc 100644
--- a/chromium/headless/lib/browser/headless_network_delegate.h
+++ b/chromium/headless/lib/browser/headless_network_delegate.h
@@ -66,7 +66,7 @@ class HeadlessNetworkDelegate : public net::NetworkDelegateImpl,
const net::CookieList& cookie_list) override;
bool OnCanSetCookie(const net::URLRequest& request,
- const std::string& cookie_line,
+ const net::CanonicalCookie& cookie,
net::CookieOptions* options) override;
bool OnCanAccessFile(const net::URLRequest& request,
diff --git a/chromium/headless/lib/browser/headless_permission_manager.cc b/chromium/headless/lib/browser/headless_permission_manager.cc
index a75ee4c3481..8f0fc66e483 100644
--- a/chromium/headless/lib/browser/headless_permission_manager.cc
+++ b/chromium/headless/lib/browser/headless_permission_manager.cc
@@ -5,13 +5,16 @@
#include "headless/lib/browser/headless_permission_manager.h"
#include "base/callback.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/permission_type.h"
namespace headless {
-HeadlessPermissionManager::HeadlessPermissionManager() : PermissionManager() {}
+HeadlessPermissionManager::HeadlessPermissionManager(
+ content::BrowserContext* browser_context)
+ : browser_context_(browser_context) {}
-HeadlessPermissionManager::~HeadlessPermissionManager() {}
+HeadlessPermissionManager::~HeadlessPermissionManager() = default;
int HeadlessPermissionManager::RequestPermission(
content::PermissionType permission,
@@ -20,7 +23,14 @@ int HeadlessPermissionManager::RequestPermission(
bool user_gesture,
const base::Callback<void(blink::mojom::PermissionStatus)>& callback) {
// In headless mode we just pretent the user "closes" any permission prompt,
- // without accepting or denying.
+ // without accepting or denying. Notifications are the exception to this,
+ // which are explicitly disabled in Incognito mode.
+ if (browser_context_->IsOffTheRecord() &&
+ permission == content::PermissionType::NOTIFICATIONS) {
+ callback.Run(blink::mojom::PermissionStatus::DENIED);
+ return kNoPendingOperation;
+ }
+
callback.Run(blink::mojom::PermissionStatus::ASK);
return kNoPendingOperation;
}
diff --git a/chromium/headless/lib/browser/headless_permission_manager.h b/chromium/headless/lib/browser/headless_permission_manager.h
index 5eb31859cc3..f9a12522333 100644
--- a/chromium/headless/lib/browser/headless_permission_manager.h
+++ b/chromium/headless/lib/browser/headless_permission_manager.h
@@ -9,11 +9,15 @@
#include "base/macros.h"
#include "content/public/browser/permission_manager.h"
+namespace content {
+class BrowserContext;
+}
+
namespace headless {
class HeadlessPermissionManager : public content::PermissionManager {
public:
- HeadlessPermissionManager();
+ explicit HeadlessPermissionManager(content::BrowserContext* browser_context);
~HeadlessPermissionManager() override;
// PermissionManager implementation.
@@ -49,6 +53,8 @@ class HeadlessPermissionManager : public content::PermissionManager {
void UnsubscribePermissionStatusChange(int subscription_id) override;
private:
+ content::BrowserContext* browser_context_;
+
DISALLOW_COPY_AND_ASSIGN(HeadlessPermissionManager);
};
diff --git a/chromium/headless/lib/browser/headless_platform_event_source.cc b/chromium/headless/lib/browser/headless_platform_event_source.cc
index 7c3100ee4f2..598ec80d1cb 100644
--- a/chromium/headless/lib/browser/headless_platform_event_source.cc
+++ b/chromium/headless/lib/browser/headless_platform_event_source.cc
@@ -6,8 +6,8 @@
namespace headless {
-HeadlessPlatformEventSource::HeadlessPlatformEventSource() {}
+HeadlessPlatformEventSource::HeadlessPlatformEventSource() = default;
-HeadlessPlatformEventSource::~HeadlessPlatformEventSource() {}
+HeadlessPlatformEventSource::~HeadlessPlatformEventSource() = default;
} // namespace headless
diff --git a/chromium/headless/lib/browser/headless_print_manager.cc b/chromium/headless/lib/browser/headless_print_manager.cc
index 2213796df0c..e7a816dcb45 100644
--- a/chromium/headless/lib/browser/headless_print_manager.cc
+++ b/chromium/headless/lib/browser/headless_print_manager.cc
@@ -51,7 +51,7 @@ HeadlessPrintManager::HeadlessPrintManager(content::WebContents* web_contents)
Reset();
}
-HeadlessPrintManager::~HeadlessPrintManager() {}
+HeadlessPrintManager::~HeadlessPrintManager() = default;
// static
std::string HeadlessPrintManager::PrintResultToString(PrintResult result) {
diff --git a/chromium/headless/lib/browser/headless_quota_permission_context.cc b/chromium/headless/lib/browser/headless_quota_permission_context.cc
index 618cbe5c978..b75f01bcf42 100644
--- a/chromium/headless/lib/browser/headless_quota_permission_context.cc
+++ b/chromium/headless/lib/browser/headless_quota_permission_context.cc
@@ -8,7 +8,7 @@
namespace headless {
-HeadlessQuotaPermissionContext::HeadlessQuotaPermissionContext() {}
+HeadlessQuotaPermissionContext::HeadlessQuotaPermissionContext() = default;
void HeadlessQuotaPermissionContext::RequestQuotaPermission(
const content::StorageQuotaParams& params,
@@ -24,6 +24,6 @@ void HeadlessQuotaPermissionContext::RequestQuotaPermission(
callback.Run(QUOTA_PERMISSION_RESPONSE_ALLOW);
}
-HeadlessQuotaPermissionContext::~HeadlessQuotaPermissionContext() {}
+HeadlessQuotaPermissionContext::~HeadlessQuotaPermissionContext() = default;
} // namespace headless
diff --git a/chromium/headless/lib/browser/headless_resource_dispatcher_host_delegate.cc b/chromium/headless/lib/browser/headless_resource_dispatcher_host_delegate.cc
index b8feeb5a386..d7b4888c527 100644
--- a/chromium/headless/lib/browser/headless_resource_dispatcher_host_delegate.cc
+++ b/chromium/headless/lib/browser/headless_resource_dispatcher_host_delegate.cc
@@ -6,16 +6,10 @@
namespace headless {
-HeadlessResourceDispatcherHostDelegate::HeadlessResourceDispatcherHostDelegate(
- bool enable_resource_scheduler)
- : enable_resource_scheduler_(enable_resource_scheduler) {}
-
HeadlessResourceDispatcherHostDelegate::
- ~HeadlessResourceDispatcherHostDelegate() {}
+ HeadlessResourceDispatcherHostDelegate() = default;
-bool HeadlessResourceDispatcherHostDelegate::ShouldUseResourceScheduler()
- const {
- return enable_resource_scheduler_;
-}
+HeadlessResourceDispatcherHostDelegate::
+ ~HeadlessResourceDispatcherHostDelegate() = default;
} // namespace headless
diff --git a/chromium/headless/lib/browser/headless_resource_dispatcher_host_delegate.h b/chromium/headless/lib/browser/headless_resource_dispatcher_host_delegate.h
index 8e276489478..7600c9bfe05 100644
--- a/chromium/headless/lib/browser/headless_resource_dispatcher_host_delegate.h
+++ b/chromium/headless/lib/browser/headless_resource_dispatcher_host_delegate.h
@@ -12,15 +12,10 @@ namespace headless {
class HeadlessResourceDispatcherHostDelegate
: public content::ResourceDispatcherHostDelegate {
public:
- explicit HeadlessResourceDispatcherHostDelegate(
- bool enable_resource_scheduler);
+ HeadlessResourceDispatcherHostDelegate();
~HeadlessResourceDispatcherHostDelegate() override;
- bool ShouldUseResourceScheduler() const override;
-
private:
- const bool enable_resource_scheduler_;
-
DISALLOW_COPY_AND_ASSIGN(HeadlessResourceDispatcherHostDelegate);
};
diff --git a/chromium/headless/lib/browser/headless_screen.cc b/chromium/headless/lib/browser/headless_screen.cc
index 1ee6b64a754..7ce5366b3fa 100644
--- a/chromium/headless/lib/browser/headless_screen.cc
+++ b/chromium/headless/lib/browser/headless_screen.cc
@@ -21,7 +21,7 @@ HeadlessScreen* HeadlessScreen::Create(const gfx::Size& size) {
return new HeadlessScreen(gfx::Rect(size));
}
-HeadlessScreen::~HeadlessScreen() {}
+HeadlessScreen::~HeadlessScreen() = default;
gfx::Point HeadlessScreen::GetCursorScreenPoint() {
return aura::Env::GetInstance()->last_mouse_location();
diff --git a/chromium/headless/lib/browser/headless_tab_socket_impl.cc b/chromium/headless/lib/browser/headless_tab_socket_impl.cc
index 05e562c4099..cbdb7dc5d79 100644
--- a/chromium/headless/lib/browser/headless_tab_socket_impl.cc
+++ b/chromium/headless/lib/browser/headless_tab_socket_impl.cc
@@ -19,7 +19,7 @@ HeadlessTabSocketImpl::HeadlessTabSocketImpl(content::WebContents* web_contents)
listener_(nullptr),
weak_ptr_factory_(this) {}
-HeadlessTabSocketImpl::~HeadlessTabSocketImpl() {}
+HeadlessTabSocketImpl::~HeadlessTabSocketImpl() = default;
// Wrangles the async responses to
// HeadlessRenderFrameControllerImpl::InstallTabSocket for which at most one
@@ -68,7 +68,7 @@ class TabSocketInstallationController
bool success_;
friend class base::RefCounted<TabSocketInstallationController>;
- ~TabSocketInstallationController() {}
+ ~TabSocketInstallationController() = default;
};
void HeadlessTabSocketImpl::InstallHeadlessTabSocketBindings(
diff --git a/chromium/headless/lib/browser/headless_url_request_context_getter.cc b/chromium/headless/lib/browser/headless_url_request_context_getter.cc
index d2eaffad364..9df02187acc 100644
--- a/chromium/headless/lib/browser/headless_url_request_context_getter.cc
+++ b/chromium/headless/lib/browser/headless_url_request_context_getter.cc
@@ -10,18 +10,31 @@
#include "base/memory/ptr_util.h"
#include "base/task_scheduler/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 "headless/lib/browser/headless_network_delegate.h"
+#include "net/cookies/cookie_store.h"
#include "net/dns/mapped_host_resolver.h"
#include "net/http/http_transaction_factory.h"
#include "net/http/http_util.h"
#include "net/proxy/proxy_service.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"
+#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 {
HeadlessURLRequestContextGetter::HeadlessURLRequestContextGetter(
@@ -74,6 +87,51 @@ HeadlessURLRequestContextGetter::GetURLRequestContext() {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
if (!url_request_context_) {
net::URLRequestContextBuilder builder;
+
+ {
+ base::AutoLock lock(lock_);
+ // 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 (headless_browser_context_ &&
+ !headless_browser_context_->IsOffTheRecord() &&
+ !headless_browser_context_->options()->user_data_dir().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 = headless_browser_context_->GetPath();
+ OSCrypt::SetConfig(std::move(config));
+#endif
+
+ content::CookieStoreConfig cookie_config(
+ headless_browser_context_->GetPath().Append(
+ FILE_PATH_LITERAL("Cookies")),
+ content::CookieStoreConfig::PERSISTANT_SESSION_COOKIES, NULL);
+ cookie_config.crypto_delegate =
+ cookie_config::GetCookieCryptoDelegate();
+ std::unique_ptr<net::CookieStore> cookie_store =
+ CreateCookieStore(cookie_config);
+ std::unique_ptr<net::ChannelIDService> channel_id_service =
+ base::MakeUnique<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_);
diff --git a/chromium/headless/lib/browser/headless_url_request_context_getter.h b/chromium/headless/lib/browser/headless_url_request_context_getter.h
index 92341b3b497..1fb71c9f48a 100644
--- a/chromium/headless/lib/browser/headless_url_request_context_getter.h
+++ b/chromium/headless/lib/browser/headless_url_request_context_getter.h
@@ -14,7 +14,6 @@
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
#include "content/public/browser/browser_context.h"
-#include "content/public/browser/content_browser_client.h"
#include "headless/public/headless_browser.h"
#include "net/proxy/proxy_config.h"
#include "net/proxy/proxy_config_service.h"
diff --git a/chromium/headless/lib/browser/headless_web_contents_impl.cc b/chromium/headless/lib/browser/headless_web_contents_impl.cc
index a3d53b70e4d..cc0c7509625 100644
--- a/chromium/headless/lib/browser/headless_web_contents_impl.cc
+++ b/chromium/headless/lib/browser/headless_web_contents_impl.cc
@@ -207,13 +207,13 @@ void CreateTabSocketMojoServiceForContents(
struct HeadlessWebContentsImpl::PendingFrame {
public:
- PendingFrame() {}
- ~PendingFrame() {}
+ PendingFrame() = default;
+ ~PendingFrame() = default;
bool MaybeRunCallback() {
if (wait_for_copy_result || !display_did_finish_frame)
return false;
- callback.Run(has_damage, std::move(bitmap));
+ callback.Run(has_damage, main_frame_content_updated, std::move(bitmap));
return true;
}
@@ -221,6 +221,7 @@ struct HeadlessWebContentsImpl::PendingFrame {
bool wait_for_copy_result = false;
bool display_did_finish_frame = false;
bool has_damage = false;
+ bool main_frame_content_updated = false;
std::unique_ptr<SkBitmap> bitmap;
FrameFinishedCallback callback;
@@ -321,6 +322,7 @@ HeadlessWebContentsImpl::HeadlessWebContentsImpl(
weak_ptr_factory_(this) {
#if BUILDFLAG(ENABLE_BASIC_PRINTING) && !defined(CHROME_MULTIPLE_DLL_CHILD)
HeadlessPrintManager::CreateForWebContents(web_contents);
+// TODO(weili): Add support for printing OOPIFs.
#endif
web_contents->GetMutableRendererPrefs()->accept_languages =
browser_context->options()->accept_language();
@@ -595,6 +597,14 @@ void HeadlessWebContentsImpl::DidReceiveCompositorFrame() {
for (int session_id : begin_frame_events_enabled_sessions_)
agent_host_->SendProtocolMessageToClient(session_id, json_result);
}
+
+ // Set main_frame_content_updated on pending frames that the display hasn't
+ // completed yet. Pending frames that it did complete won't incorporate this
+ // CompositorFrame. In practice, this should only be a single PendingFrame.
+ for (const std::unique_ptr<PendingFrame>& pending_frame : pending_frames_) {
+ if (!pending_frame->display_did_finish_frame)
+ pending_frame->main_frame_content_updated = true;
+ }
}
void HeadlessWebContentsImpl::PendingFrameReadbackComplete(
@@ -699,7 +709,7 @@ HeadlessWebContents* HeadlessWebContents::Builder::Build() {
return browser_context_->CreateWebContents(this);
}
-HeadlessWebContents::Builder::MojoService::MojoService() {}
+HeadlessWebContents::Builder::MojoService::MojoService() = default;
HeadlessWebContents::Builder::MojoService::MojoService(
const MojoService& other) = default;
@@ -709,6 +719,6 @@ HeadlessWebContents::Builder::MojoService::MojoService(
const ServiceFactoryCallback& service_factory)
: service_name(service_name), service_factory(service_factory) {}
-HeadlessWebContents::Builder::MojoService::~MojoService() {}
+HeadlessWebContents::Builder::MojoService::~MojoService() = default;
} // namespace headless
diff --git a/chromium/headless/lib/browser/headless_web_contents_impl.h b/chromium/headless/lib/browser/headless_web_contents_impl.h
index a2095d73f56..a4e06e025ae 100644
--- a/chromium/headless/lib/browser/headless_web_contents_impl.h
+++ b/chromium/headless/lib/browser/headless_web_contents_impl.h
@@ -143,7 +143,9 @@ class HEADLESS_EXPORT HeadlessWebContentsImpl
void SetBeginFrameEventsEnabled(int session_id, bool enabled);
using FrameFinishedCallback =
- base::Callback<void(bool /*has_damage*/, std::unique_ptr<SkBitmap>)>;
+ base::Callback<void(bool /* has_damage */,
+ bool /* main_frame_content_updated */,
+ std::unique_ptr<SkBitmap>)>;
void BeginFrame(const base::TimeTicks& frame_timeticks,
const base::TimeTicks& deadline,
const base::TimeDelta& interval,
@@ -170,7 +172,7 @@ class HEADLESS_EXPORT HeadlessWebContentsImpl
const SkBitmap& bitmap,
content::ReadbackResponse response);
- uint32_t begin_frame_source_id_ = viz::BeginFrameArgs::kManualSourceId;
+ uint64_t begin_frame_source_id_ = viz::BeginFrameArgs::kManualSourceId;
uint64_t begin_frame_sequence_number_ =
viz::BeginFrameArgs::kStartingFrameNumber;
bool begin_frame_control_enabled_ = false;