Chromium Code Reviews| Index: headless/lib/browser/headless_devtools_client_impl.cc |
| diff --git a/headless/lib/browser/headless_devtools_client_impl.cc b/headless/lib/browser/headless_devtools_client_impl.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..9a14430183915647e3519bee394892a7019673d7 |
| --- /dev/null |
| +++ b/headless/lib/browser/headless_devtools_client_impl.cc |
| @@ -0,0 +1,293 @@ |
| +// 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_devtools_client_impl.h" |
| + |
| +#include <memory> |
| + |
| +#include "base/json/json_reader.h" |
| +#include "base/json/json_writer.h" |
| +#include "base/memory/ptr_util.h" |
| +#include "base/values.h" |
| +#include "content/public/browser/devtools_agent_host.h" |
| + |
| +namespace headless { |
| + |
| +// static |
| +std::unique_ptr<HeadlessDevToolsClient> HeadlessDevToolsClient::Create() { |
| + return base::WrapUnique(new HeadlessDevToolsClientImpl()); |
| +} |
| + |
| +// static |
| +HeadlessDevToolsClientImpl* HeadlessDevToolsClientImpl::From( |
| + HeadlessDevToolsClient* client) { |
| + // This downcast is safe because there is only one implementation of |
| + // HeadlessDevToolsClient. |
| + return static_cast<HeadlessDevToolsClientImpl*>(client); |
| +} |
| + |
| +HeadlessDevToolsClientImpl::HeadlessDevToolsClientImpl() |
| + : agent_host_(nullptr), |
| + next_message_id_(0), |
| + accessibility_domain_(this), |
| + animation_domain_(this), |
| + application_cache_domain_(this), |
| + cache_storage_domain_(this), |
| + console_domain_(this), |
| + css_domain_(this), |
| + database_domain_(this), |
| + debugger_domain_(this), |
| + device_orientation_domain_(this), |
| + dom_debugger_domain_(this), |
| + dom_domain_(this), |
| + dom_storage_domain_(this), |
| + emulation_domain_(this), |
| + heap_profiler_domain_(this), |
| + indexeddb_domain_(this), |
| + input_domain_(this), |
| + inspector_domain_(this), |
| + io_domain_(this), |
| + layer_tree_domain_(this), |
| + memory_domain_(this), |
| + network_domain_(this), |
| + page_domain_(this), |
| + profiler_domain_(this), |
| + rendering_domain_(this), |
| + runtime_domain_(this), |
| + security_domain_(this), |
| + service_worker_domain_(this), |
| + tracing_domain_(this), |
| + worker_domain_(this) {} |
| + |
| +HeadlessDevToolsClientImpl::~HeadlessDevToolsClientImpl() {} |
| + |
| +void HeadlessDevToolsClientImpl::AttachToHost( |
| + content::DevToolsAgentHost* agent_host) { |
| + DCHECK(!agent_host_); |
| + agent_host_ = agent_host; |
| + agent_host_->AttachClient(this); |
| +} |
| + |
| +void HeadlessDevToolsClientImpl::DetachFromHost( |
| + content::DevToolsAgentHost* agent_host) { |
| + DCHECK_EQ(agent_host_, agent_host); |
| + agent_host_->DetachClient(); |
| + agent_host_ = nullptr; |
| + pending_messages_.clear(); |
| +} |
| + |
| +void HeadlessDevToolsClientImpl::DispatchProtocolMessage( |
| + content::DevToolsAgentHost* agent_host, |
| + const std::string& json_message) { |
| + DCHECK_EQ(agent_host_, agent_host); |
| + std::unique_ptr<base::Value> message = |
| + base::JSONReader::Read(json_message, base::JSON_PARSE_RFC); |
| + base::DictionaryValue* message_dict; |
| + if (!message || !message->GetAsDictionary(&message_dict)) { |
| + NOTREACHED() << "Badly formed reply"; |
| + return; |
| + } |
| + int id = 0; |
| + DCHECK(message_dict->GetInteger("id", &id)); |
| + auto it = pending_messages_.find(id); |
| + if (it == pending_messages_.end()) { |
| + NOTREACHED() << "Unexpected reply"; |
| + return; |
| + } |
| + base::DictionaryValue* result_dict; |
| + if (message_dict->GetDictionary("result", &result_dict)) { |
| + it->second.callback_with_result.Run(*result_dict); |
| + } else { |
| + it->second.callback.Run(); |
| + } |
| + pending_messages_.erase(it); |
| +} |
| + |
| +void HeadlessDevToolsClientImpl::AgentHostClosed( |
| + content::DevToolsAgentHost* agent_host, |
| + bool replaced_with_another_client) { |
| + DCHECK_EQ(agent_host_, agent_host); |
| + agent_host = nullptr; |
| + pending_messages_.clear(); |
| +} |
| + |
| +accessibility::Domain* HeadlessDevToolsClientImpl::GetAccessibility() { |
| + return &accessibility_domain_; |
| +} |
| + |
| +animation::Domain* HeadlessDevToolsClientImpl::GetAnimation() { |
| + return &animation_domain_; |
| +} |
| + |
| +application_cache::Domain* HeadlessDevToolsClientImpl::GetApplicationCache() { |
| + return &application_cache_domain_; |
| +} |
| + |
| +cache_storage::Domain* HeadlessDevToolsClientImpl::GetCacheStorage() { |
| + return &cache_storage_domain_; |
| +} |
| + |
| +console::Domain* HeadlessDevToolsClientImpl::GetConsole() { |
| + return &console_domain_; |
| +} |
| + |
| +css::Domain* HeadlessDevToolsClientImpl::GetCSS() { |
| + return &css_domain_; |
| +} |
| + |
| +database::Domain* HeadlessDevToolsClientImpl::GetDatabase() { |
| + return &database_domain_; |
| +} |
| + |
| +debugger::Domain* HeadlessDevToolsClientImpl::GetDebugger() { |
| + return &debugger_domain_; |
| +} |
| + |
| +device_orientation::Domain* HeadlessDevToolsClientImpl::GetDeviceOrientation() { |
| + return &device_orientation_domain_; |
| +} |
| + |
| +dom_debugger::Domain* HeadlessDevToolsClientImpl::GetDOMDebugger() { |
| + return &dom_debugger_domain_; |
| +} |
| + |
| +dom::Domain* HeadlessDevToolsClientImpl::GetDOM() { |
| + return &dom_domain_; |
| +} |
| + |
| +dom_storage::Domain* HeadlessDevToolsClientImpl::GetDOMStorage() { |
| + return &dom_storage_domain_; |
| +} |
| + |
| +emulation::Domain* HeadlessDevToolsClientImpl::GetEmulation() { |
| + return &emulation_domain_; |
| +} |
| + |
| +heap_profiler::Domain* HeadlessDevToolsClientImpl::GetHeapProfiler() { |
| + return &heap_profiler_domain_; |
| +} |
| + |
| +indexeddb::Domain* HeadlessDevToolsClientImpl::GetIndexedDB() { |
| + return &indexeddb_domain_; |
| +} |
| + |
| +input::Domain* HeadlessDevToolsClientImpl::GetInput() { |
| + return &input_domain_; |
| +} |
| + |
| +inspector::Domain* HeadlessDevToolsClientImpl::GetInspector() { |
| + return &inspector_domain_; |
| +} |
| + |
| +io::Domain* HeadlessDevToolsClientImpl::GetIO() { |
| + return &io_domain_; |
| +} |
| + |
| +layer_tree::Domain* HeadlessDevToolsClientImpl::GetLayerTree() { |
| + return &layer_tree_domain_; |
| +} |
| + |
| +memory::Domain* HeadlessDevToolsClientImpl::GetMemory() { |
| + return &memory_domain_; |
| +} |
| + |
| +network::Domain* HeadlessDevToolsClientImpl::GetNetwork() { |
| + return &network_domain_; |
| +} |
| + |
| +page::Domain* HeadlessDevToolsClientImpl::GetPage() { |
| + return &page_domain_; |
| +} |
| + |
| +profiler::Domain* HeadlessDevToolsClientImpl::GetProfiler() { |
| + return &profiler_domain_; |
| +} |
| + |
| +rendering::Domain* HeadlessDevToolsClientImpl::GetRendering() { |
| + return &rendering_domain_; |
| +} |
| + |
| +runtime::Domain* HeadlessDevToolsClientImpl::GetRuntime() { |
| + return &runtime_domain_; |
| +} |
| + |
| +security::Domain* HeadlessDevToolsClientImpl::GetSecurity() { |
| + return &security_domain_; |
| +} |
| + |
| +service_worker::Domain* HeadlessDevToolsClientImpl::GetServiceWorker() { |
| + return &service_worker_domain_; |
| +} |
| + |
| +tracing::Domain* HeadlessDevToolsClientImpl::GetTracing() { |
| + return &tracing_domain_; |
| +} |
| + |
| +worker::Domain* HeadlessDevToolsClientImpl::GetWorker() { |
| + return &worker_domain_; |
| +} |
| + |
| +void HeadlessDevToolsClientImpl::SendMessage( |
| + const char* method, |
| + std::unique_ptr<base::Value> params, |
| + base::Callback<void(const base::Value&)> callback) { |
| + base::DictionaryValue message; |
| + message.SetString("method", method); |
| + message.Set("params", std::move(params)); |
| + int id = FinalizeAndSendMessage(&message); |
| + pending_messages_[id] = PendingMessage(callback); |
| +} |
| + |
| +void HeadlessDevToolsClientImpl::SendMessage( |
| + const char* method, |
| + std::unique_ptr<base::Value> params, |
| + base::Callback<void()> callback) { |
| + base::DictionaryValue message; |
| + message.SetString("method", method); |
| + message.Set("params", std::move(params)); |
| + int id = FinalizeAndSendMessage(&message); |
| + pending_messages_[id] = PendingMessage(callback); |
| +} |
| + |
| +void HeadlessDevToolsClientImpl::SendMessage( |
| + const char* method, |
| + base::Callback<void(const base::Value&)> callback) { |
| + base::DictionaryValue message; |
| + message.SetString("method", method); |
| + int id = FinalizeAndSendMessage(&message); |
| + pending_messages_[id] = PendingMessage(callback); |
| +} |
| + |
| +void HeadlessDevToolsClientImpl::SendMessage(const char* method, |
|
altimin
2016/04/14 12:54:12
Looks like these three methods have a lot in commo
Sami
2016/04/15 14:43:44
Refactored.
|
| + base::Callback<void()> callback) { |
| + base::DictionaryValue message; |
| + message.SetString("method", method); |
| + int id = FinalizeAndSendMessage(&message); |
| + pending_messages_[id] = PendingMessage(callback); |
| +} |
| + |
| +int HeadlessDevToolsClientImpl::FinalizeAndSendMessage( |
| + base::DictionaryValue* message) { |
| + DCHECK(agent_host_); |
| + int id = next_message_id_++; |
| + message->SetInteger("id", id); |
| + std::string json_message; |
| + base::JSONWriter::Write(*message, &json_message); |
| + agent_host_->DispatchProtocolMessage(json_message); |
|
dgozman
2016/04/14 18:01:54
This could synchronously call |DispatchProtocolMes
Sami
2016/04/15 14:43:44
Well spotted, thanks.
|
| + return id; |
| +} |
| + |
| +HeadlessDevToolsClientImpl::PendingMessage::PendingMessage() {} |
| + |
| +HeadlessDevToolsClientImpl::PendingMessage::PendingMessage( |
| + base::Callback<void()> callback) |
| + : callback(callback) {} |
| + |
| +HeadlessDevToolsClientImpl::PendingMessage::PendingMessage( |
| + base::Callback<void(const base::Value&)> callback) |
| + : callback_with_result(callback) {} |
| + |
| +HeadlessDevToolsClientImpl::PendingMessage::~PendingMessage() {} |
| + |
| +} // namespace headless |