Commit 4f1226d3 authored by yzshen's avatar yzshen Committed by Commit bot

Mandoline DevTools service: remote debugging protocol over HTTP/WebSocket.

This CL:
- adds service-side DevTools agent representation (DevToolsAgentHost) and registration for DevTools agents.
- supports requesting the list of available agents using HTTP request and communicating with them using WebSocket.

BUG=478249
TEST=None

Review URL: https://codereview.chromium.org/1164383002

Cr-Commit-Position: refs/heads/master@{#333804}
parent eb2fad48
...@@ -6,6 +6,8 @@ import("//mojo/public/mojo_application.gni") ...@@ -6,6 +6,8 @@ import("//mojo/public/mojo_application.gni")
source_set("lib") { source_set("lib") {
sources = [ sources = [
"devtools_agent_host.cc",
"devtools_agent_host.h",
"devtools_http_server.cc", "devtools_http_server.cc",
"devtools_http_server.h", "devtools_http_server.h",
"devtools_registry_impl.cc", "devtools_registry_impl.cc",
...@@ -21,6 +23,7 @@ source_set("lib") { ...@@ -21,6 +23,7 @@ source_set("lib") {
"//components/devtools_service/public/interfaces", "//components/devtools_service/public/interfaces",
"//mojo/application/public/cpp", "//mojo/application/public/cpp",
"//mojo/common", "//mojo/common",
"//mojo/services/network/public/cpp",
"//mojo/services/network/public/interfaces", "//mojo/services/network/public/interfaces",
"//third_party/mojo/src/mojo/public/cpp/bindings", "//third_party/mojo/src/mojo/public/cpp/bindings",
"//url", "//url",
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/devtools_service/devtools_agent_host.h"
#include "base/guid.h"
#include "base/logging.h"
namespace devtools_service {
DevToolsAgentHost::DevToolsAgentHost(DevToolsAgentPtr agent)
: id_(base::GenerateGUID()),
agent_(agent.Pass()),
binding_(this),
delegate_(nullptr) {
agent_.set_error_handler(this);
}
DevToolsAgentHost::~DevToolsAgentHost() {
if (delegate_)
delegate_->OnAgentHostClosed(this);
}
void DevToolsAgentHost::SetDelegate(Delegate* delegate) {
delegate_ = delegate;
if (delegate_) {
if (binding_.is_bound())
return;
DevToolsAgentClientPtr client;
binding_.Bind(&client);
agent_->SetClient(client.Pass(), id_);
} else {
if (!binding_.is_bound())
return;
binding_.Close();
}
}
void DevToolsAgentHost::SendProtocolMessageToAgent(const std::string& message) {
agent_->DispatchProtocolMessage(message);
}
void DevToolsAgentHost::DispatchProtocolMessage(const mojo::String& message) {
delegate_->DispatchProtocolMessage(this, message);
}
void DevToolsAgentHost::OnConnectionError() {
agent_connection_error_handler_.Run();
}
} // namespace devtools_service
// 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 COMPONENTS_DEVTOOLS_SERVICE_DEVTOOLS_AGENT_HOST_H_
#define COMPONENTS_DEVTOOLS_SERVICE_DEVTOOLS_AGENT_HOST_H_
#include <string>
#include "base/macros.h"
#include "components/devtools_service/public/interfaces/devtools_service.mojom.h"
#include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h"
#include "third_party/mojo/src/mojo/public/cpp/bindings/callback.h"
#include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h"
namespace devtools_service {
// DevToolsAgentHost represents a DevTools agent at the service side.
class DevToolsAgentHost : public DevToolsAgentClient,
public mojo::ErrorHandler {
public:
class Delegate {
public:
virtual ~Delegate() {}
virtual void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
const std::string& message) = 0;
// Notifies the delegate that |agent_host| is going away.
virtual void OnAgentHostClosed(DevToolsAgentHost* agent_host) = 0;
};
explicit DevToolsAgentHost(DevToolsAgentPtr agent);
~DevToolsAgentHost() override;
void set_agent_connection_error_handler(const mojo::Closure& handler) {
agent_connection_error_handler_ = handler;
}
std::string id() const { return id_; }
// Doesn't take ownership of |delegate|. If |delegate| dies before this
// object, a new delegate or nullptr must be set so that this object doesn't
// hold an invalid pointer.
void SetDelegate(Delegate* delegate);
bool IsAttached() const { return !!delegate_; }
void SendProtocolMessageToAgent(const std::string& message);
private:
// DevToolsAgentClient implementation.
void DispatchProtocolMessage(const mojo::String& message) override;
// mojo::ErrorHandler implementation.
void OnConnectionError() override;
const std::string id_;
DevToolsAgentPtr agent_;
mojo::Closure agent_connection_error_handler_;
mojo::Binding<DevToolsAgentClient> binding_;
Delegate* delegate_;
DISALLOW_COPY_AND_ASSIGN(DevToolsAgentHost);
};
} // namespace devtools_service
#endif // COMPONENTS_DEVTOOLS_SERVICE_DEVTOOLS_AGENT_HOST_H_
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "mojo/services/network/public/interfaces/http_connection.mojom.h" #include "mojo/services/network/public/interfaces/http_connection.mojom.h"
#include "mojo/services/network/public/interfaces/http_message.mojom.h"
#include "mojo/services/network/public/interfaces/http_server.mojom.h" #include "mojo/services/network/public/interfaces/http_server.mojom.h"
namespace devtools_service { namespace devtools_service {
...@@ -30,25 +31,27 @@ class DevToolsHttpServer : public mojo::HttpServerDelegate { ...@@ -30,25 +31,27 @@ class DevToolsHttpServer : public mojo::HttpServerDelegate {
mojo::HttpConnectionPtr connection, mojo::HttpConnectionPtr connection,
mojo::InterfaceRequest<mojo::HttpConnectionDelegate> delegate) override; mojo::InterfaceRequest<mojo::HttpConnectionDelegate> delegate) override;
// The following methods are called by HttpConnectionDelegateImpl. // The following three methods are called by HttpConnectionDelegateImpl.
using OnReceivedRequestCallback = using OnReceivedRequestCallback =
mojo::HttpConnectionDelegate::OnReceivedRequestCallback; mojo::HttpConnectionDelegate::OnReceivedRequestCallback;
void OnReceivedRequest(HttpConnectionDelegateImpl* connection, void OnReceivedRequest(HttpConnectionDelegateImpl* connection,
mojo::HttpRequestPtr request, mojo::HttpRequestPtr request,
const OnReceivedRequestCallback& callback); const OnReceivedRequestCallback& callback);
using OnReceivedWebSocketRequestCallback = using OnReceivedWebSocketRequestCallback =
mojo::HttpConnectionDelegate::OnReceivedWebSocketRequestCallback; mojo::HttpConnectionDelegate::OnReceivedWebSocketRequestCallback;
void OnReceivedWebSocketRequest( void OnReceivedWebSocketRequest(
HttpConnectionDelegateImpl* connection, HttpConnectionDelegateImpl* connection,
mojo::HttpRequestPtr request, mojo::HttpRequestPtr request,
const OnReceivedWebSocketRequestCallback& callback); const OnReceivedWebSocketRequestCallback& callback);
void OnConnectionClosed(HttpConnectionDelegateImpl* connection); void OnConnectionClosed(HttpConnectionDelegateImpl* connection);
mojo::HttpResponsePtr ProcessJsonRequest(mojo::HttpRequestPtr request);
// Not owned by this object. // Not owned by this object.
DevToolsService* const service_; DevToolsService* const service_;
const uint16_t remote_debugging_port_;
scoped_ptr<mojo::Binding<mojo::HttpServerDelegate>> scoped_ptr<mojo::Binding<mojo::HttpServerDelegate>>
http_server_delegate_binding_; http_server_delegate_binding_;
......
...@@ -5,9 +5,17 @@ ...@@ -5,9 +5,17 @@
#include "components/devtools_service/devtools_registry_impl.h" #include "components/devtools_service/devtools_registry_impl.h"
#include "base/logging.h" #include "base/logging.h"
#include "components/devtools_service/devtools_agent_host.h"
namespace devtools_service { namespace devtools_service {
DevToolsRegistryImpl::Iterator::Iterator(DevToolsRegistryImpl* registry)
: registry_(registry), iter_(registry->agents_.begin()) {
}
DevToolsRegistryImpl::Iterator::~Iterator() {
}
DevToolsRegistryImpl::DevToolsRegistryImpl(DevToolsService* service) DevToolsRegistryImpl::DevToolsRegistryImpl(DevToolsService* service)
: service_(service) { : service_(service) {
} }
...@@ -20,9 +28,26 @@ void DevToolsRegistryImpl::BindToRegistryRequest( ...@@ -20,9 +28,26 @@ void DevToolsRegistryImpl::BindToRegistryRequest(
bindings_.AddBinding(this, request.Pass()); bindings_.AddBinding(this, request.Pass());
} }
DevToolsAgentHost* DevToolsRegistryImpl::GetAgentById(const std::string& id) {
auto iter = agents_.find(id);
if (iter == agents_.end())
return nullptr;
return iter->second.get();
}
void DevToolsRegistryImpl::RegisterAgent(DevToolsAgentPtr agent) { void DevToolsRegistryImpl::RegisterAgent(DevToolsAgentPtr agent) {
// TODO(yzshen): Implement it. linked_ptr<DevToolsAgentHost> agent_host(new DevToolsAgentHost(agent.Pass()));
NOTIMPLEMENTED(); std::string id = agent_host->id();
agent_host->set_agent_connection_error_handler(
[this, id]() { OnAgentConnectionError(id); });
agents_[agent_host->id()] = agent_host;
}
void DevToolsRegistryImpl::OnAgentConnectionError(const std::string& id) {
DCHECK(agents_.find(id) != agents_.end());
agents_.erase(id);
} }
} // namespace devtools_service } // namespace devtools_service
...@@ -5,30 +5,57 @@ ...@@ -5,30 +5,57 @@
#ifndef COMPONENTS_DEVTOOLS_SERVICE_DEVTOOLS_REGISTRY_IMPL_H_ #ifndef COMPONENTS_DEVTOOLS_SERVICE_DEVTOOLS_REGISTRY_IMPL_H_
#define COMPONENTS_DEVTOOLS_SERVICE_DEVTOOLS_REGISTRY_IMPL_H_ #define COMPONENTS_DEVTOOLS_SERVICE_DEVTOOLS_REGISTRY_IMPL_H_
#include <map>
#include <string>
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/linked_ptr.h"
#include "components/devtools_service/public/interfaces/devtools_service.mojom.h" #include "components/devtools_service/public/interfaces/devtools_service.mojom.h"
#include "mojo/common/weak_binding_set.h" #include "mojo/common/weak_binding_set.h"
namespace devtools_service { namespace devtools_service {
class DevToolsAgentHost;
class DevToolsService; class DevToolsService;
class DevToolsRegistryImpl : public DevToolsRegistry { class DevToolsRegistryImpl : public DevToolsRegistry {
public: public:
class Iterator {
public:
// |registry| must outlive this object.
explicit Iterator(DevToolsRegistryImpl* registry);
~Iterator();
bool IsAtEnd() const { return iter_ == registry_->agents_.end(); }
void Advance() { ++iter_; }
DevToolsAgentHost* value() { return iter_->second.get(); }
private:
DevToolsRegistryImpl* const registry_;
std::map<std::string, linked_ptr<DevToolsAgentHost>>::const_iterator iter_;
};
// |service| must outlive this object. // |service| must outlive this object.
explicit DevToolsRegistryImpl(DevToolsService* service); explicit DevToolsRegistryImpl(DevToolsService* service);
~DevToolsRegistryImpl() override; ~DevToolsRegistryImpl() override;
void BindToRegistryRequest(mojo::InterfaceRequest<DevToolsRegistry> request); void BindToRegistryRequest(mojo::InterfaceRequest<DevToolsRegistry> request);
DevToolsAgentHost* GetAgentById(const std::string& id);
private: private:
// DevToolsRegistry implementation. // DevToolsRegistry implementation.
void RegisterAgent(DevToolsAgentPtr agent) override; void RegisterAgent(DevToolsAgentPtr agent) override;
void OnAgentConnectionError(const std::string& id);
DevToolsService* const service_; DevToolsService* const service_;
mojo::WeakBindingSet<DevToolsRegistry> bindings_; mojo::WeakBindingSet<DevToolsRegistry> bindings_;
std::map<std::string, linked_ptr<DevToolsAgentHost>> agents_;
DISALLOW_COPY_AND_ASSIGN(DevToolsRegistryImpl); DISALLOW_COPY_AND_ASSIGN(DevToolsRegistryImpl);
}; };
......
...@@ -30,7 +30,7 @@ interface DevToolsAgent { ...@@ -30,7 +30,7 @@ interface DevToolsAgent {
// DispatchProtocolMessage() calls. If a client doesn't want to receive // DispatchProtocolMessage() calls. If a client doesn't want to receive
// messages anymore, it could simply close the underlying message pipe of // messages anymore, it could simply close the underlying message pipe of
// |client|. // |client|.
SetClient(DevToolsAgentClient client); SetClient(DevToolsAgentClient client, string client_id);
// Sends a command (in remote debugging protocol JSON format) to the agent. // Sends a command (in remote debugging protocol JSON format) to the agent.
DispatchProtocolMessage(string message); DispatchProtocolMessage(string message);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment