Skip to content

Commit

Permalink
Mandoline DevTools service - part 1
Browse files Browse the repository at this point in the history
This CL:
- adds DevToolsCoordinatorImpl to handle DevToolsCoordinator interface calls and start HTTP server.
- adds command-line flag remote-debugging-port.

This CL doesn't make the DevTools service handle HTTP/WebSocket messages, which will be in follow-up CLs.

BUG=478249

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

Cr-Commit-Position: refs/heads/master@{#331380}
  • Loading branch information
yzshen authored and Commit bot committed May 26, 2015
1 parent d47fb84 commit b51b266
Show file tree
Hide file tree
Showing 11 changed files with 364 additions and 9 deletions.
5 changes: 5 additions & 0 deletions components/devtools_service/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import("//third_party/mojo/src/mojo/public/mojo_application.gni")

source_set("lib") {
sources = [
"devtools_coordinator_impl.cc",
"devtools_coordinator_impl.h",
"devtools_service_delegate.cc",
"devtools_service_delegate.h",
]
Expand All @@ -14,7 +16,10 @@ source_set("lib") {
"//base",
"//components/devtools_service/public/interfaces",
"//mojo/application/public/cpp",
"//mojo/common",
"//mojo/services/network/public/interfaces",
"//third_party/mojo/src/mojo/public/cpp/bindings",
"//url",
]
}

Expand Down
1 change: 1 addition & 0 deletions components/devtools_service/DEPS
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
include_rules = [
"+mojo/application",
"+mojo/common",
"+mojo/services/network/public",
"+third_party/mojo/src/mojo/public",
]
177 changes: 177 additions & 0 deletions components/devtools_service/devtools_coordinator_impl.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
// 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_coordinator_impl.h"

#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "mojo/application/public/cpp/application_impl.h"
#include "mojo/services/network/public/interfaces/http_message.mojom.h"
#include "mojo/services/network/public/interfaces/net_address.mojom.h"
#include "mojo/services/network/public/interfaces/network_service.mojom.h"

namespace devtools_service {

class DevToolsCoordinatorImpl::HttpConnectionDelegateImpl
: public mojo::HttpConnectionDelegate,
public mojo::ErrorHandler {
public:
HttpConnectionDelegateImpl(
DevToolsCoordinatorImpl* owner,
mojo::HttpConnectionPtr connection,
mojo::InterfaceRequest<HttpConnectionDelegate> delegate_request)
: owner_(owner),
connection_(connection.Pass()),
binding_(this, delegate_request.Pass()) {
DCHECK(owner_);
DCHECK(connection_);
DCHECK(binding_.is_bound());

connection_.set_error_handler(this);
binding_.set_error_handler(this);
}

mojo::HttpConnection* connection() { return connection_.get(); }

private:
// mojo::HttpConnectionDelegate implementation:
void OnReceivedRequest(mojo::HttpRequestPtr request,
const OnReceivedRequestCallback& callback) override {
owner_->OnReceivedRequest(this, request.Pass(), callback);
}

void OnReceivedWebSocketRequest(
mojo::HttpRequestPtr request,
const OnReceivedWebSocketRequestCallback& callback) override {
owner_->OnReceivedWebSocketRequest(this, request.Pass(), callback);
}

// mojo::ErrorHandler implementation.
void OnConnectionError() override { owner_->OnConnectionClosed(this); }

DevToolsCoordinatorImpl* const owner_;
mojo::HttpConnectionPtr connection_;
mojo::Binding<HttpConnectionDelegate> binding_;

DISALLOW_COPY_AND_ASSIGN(HttpConnectionDelegateImpl);
};

DevToolsCoordinatorImpl::DevToolsCoordinatorImpl(
mojo::ApplicationImpl* application)
: application_(application) {
DCHECK(application_);
}

DevToolsCoordinatorImpl::~DevToolsCoordinatorImpl() {
STLDeleteElements(&connections_);
}

void DevToolsCoordinatorImpl::CreateAgentClient(
mojo::InterfaceRequest<DevToolsAgentClient> request) {
if (!IsInitialized()) {
// Ignore the request if remote debugging is not needed.
return;
}

// TODO(yzshen): Implement it.
NOTIMPLEMENTED();
}

void DevToolsCoordinatorImpl::BindToCoordinatorRequest(
mojo::InterfaceRequest<DevToolsCoordinator> request) {
coordinator_bindings_.AddBinding(this, request.Pass());
}

void DevToolsCoordinatorImpl::Initialize(uint16_t remote_debugging_port) {
if (IsInitialized()) {
LOG(WARNING) << "DevTools service receives a "
<< "DevToolsCoordinator.Initialize() call while it has "
<< "already been initialized.";
return;
}

VLOG(1) << "Remote debugging HTTP server is started on port "
<< remote_debugging_port << ".";
mojo::NetworkServicePtr network_service;
mojo::URLRequestPtr request(mojo::URLRequest::New());
request->url = "mojo:network_service";
application_->ConnectToService(request.Pass(), &network_service);

mojo::NetAddressPtr local_address(mojo::NetAddress::New());
local_address->family = mojo::NET_ADDRESS_FAMILY_IPV4;
local_address->ipv4 = mojo::NetAddressIPv4::New();
local_address->ipv4->port = remote_debugging_port;
local_address->ipv4->addr.resize(4);
local_address->ipv4->addr[0] = 127;
local_address->ipv4->addr[1] = 0;
local_address->ipv4->addr[2] = 0;
local_address->ipv4->addr[3] = 1;

mojo::HttpServerDelegatePtr http_server_delegate;
http_server_delegate_binding_.reset(
new mojo::Binding<mojo::HttpServerDelegate>(this, &http_server_delegate));
network_service->CreateHttpServer(
local_address.Pass(), http_server_delegate.Pass(),
mojo::NetworkService::CreateHttpServerCallback());
}

void DevToolsCoordinatorImpl::OnConnected(
mojo::HttpConnectionPtr connection,
mojo::InterfaceRequest<mojo::HttpConnectionDelegate> delegate) {
connections_.insert(
new HttpConnectionDelegateImpl(this, connection.Pass(), delegate.Pass()));
}

void DevToolsCoordinatorImpl::OnReceivedRequest(
HttpConnectionDelegateImpl* connection,
mojo::HttpRequestPtr request,
const OnReceivedRequestCallback& callback) {
DCHECK(connections_.find(connection) != connections_.end());

// TODO(yzshen): Implement it.
static const char kNotImplemented[] = "Not implemented yet!";
mojo::HttpResponsePtr response(mojo::HttpResponse::New());
response->headers.resize(2);
response->headers[0] = mojo::HttpHeader::New();
response->headers[0]->name = "Content-Length";
response->headers[0]->value = base::StringPrintf(
"%lu", static_cast<unsigned long>(sizeof(kNotImplemented)));
response->headers[1] = mojo::HttpHeader::New();
response->headers[1]->name = "Content-Type";
response->headers[1]->value = "text/html";

uint32_t num_bytes = sizeof(kNotImplemented);
MojoCreateDataPipeOptions options;
options.struct_size = sizeof(MojoCreateDataPipeOptions);
options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
options.element_num_bytes = 1;
options.capacity_num_bytes = num_bytes;
mojo::DataPipe data_pipe(options);
response->body = data_pipe.consumer_handle.Pass();
WriteDataRaw(data_pipe.producer_handle.get(), kNotImplemented, &num_bytes,
MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);

callback.Run(response.Pass());
}

void DevToolsCoordinatorImpl::OnReceivedWebSocketRequest(
HttpConnectionDelegateImpl* connection,
mojo::HttpRequestPtr request,
const OnReceivedWebSocketRequestCallback& callback) {
DCHECK(connections_.find(connection) != connections_.end());

// TODO(yzshen): Implement it.
NOTIMPLEMENTED();
}

void DevToolsCoordinatorImpl::OnConnectionClosed(
HttpConnectionDelegateImpl* connection) {
DCHECK(connections_.find(connection) != connections_.end());

delete connection;
connections_.erase(connection);
}

} // namespace devtools_service
82 changes: 82 additions & 0 deletions components/devtools_service/devtools_coordinator_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// 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_COORDINATOR_IMPL_H_
#define COMPONENTS_DEVTOOLS_SERVICE_DEVTOOLS_COORDINATOR_IMPL_H_

#include <set>

#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "components/devtools_service/public/interfaces/devtools_service.mojom.h"
#include "mojo/common/weak_binding_set.h"
#include "mojo/services/network/public/interfaces/http_connection.mojom.h"
#include "mojo/services/network/public/interfaces/http_server.mojom.h"

namespace mojo {
class ApplicationImpl;
}

namespace devtools_service {

// DevToolsCoordinatorImpl is the central control of the DevTools service. It
// manages the communication with DevTools agents (e.g., Web page renderers). It
// also starts an HTTP server to speak the Chrome remote debugging protocol.
class DevToolsCoordinatorImpl : public DevToolsCoordinator,
public mojo::HttpServerDelegate {
public:
// Doesn't take ownership of |application|, which must outlive this object.
explicit DevToolsCoordinatorImpl(mojo::ApplicationImpl* application);
~DevToolsCoordinatorImpl() override;

void CreateAgentClient(mojo::InterfaceRequest<DevToolsAgentClient> request);
void BindToCoordinatorRequest(
mojo::InterfaceRequest<DevToolsCoordinator> request);

private:
class HttpConnectionDelegateImpl;

// DevToolsCoordinator implementation.
void Initialize(uint16_t remote_debugging_port) override;

// mojo::HttpServerDelegate implementation.
void OnConnected(
mojo::HttpConnectionPtr connection,
mojo::InterfaceRequest<mojo::HttpConnectionDelegate> delegate) override;

bool IsInitialized() const { return !!http_server_delegate_binding_; }

// The following methods are called by HttpConnectionDelegateImpl.
using OnReceivedRequestCallback =
mojo::HttpConnectionDelegate::OnReceivedRequestCallback;
void OnReceivedRequest(HttpConnectionDelegateImpl* connection,
mojo::HttpRequestPtr request,
const OnReceivedRequestCallback& callback);

using OnReceivedWebSocketRequestCallback =
mojo::HttpConnectionDelegate::OnReceivedWebSocketRequestCallback;
void OnReceivedWebSocketRequest(
HttpConnectionDelegateImpl* connection,
mojo::HttpRequestPtr request,
const OnReceivedWebSocketRequestCallback& callback);

void OnConnectionClosed(HttpConnectionDelegateImpl* connection);

// Not owned by this object.
mojo::ApplicationImpl* const application_;

mojo::WeakBindingSet<DevToolsCoordinator> coordinator_bindings_;

scoped_ptr<mojo::Binding<mojo::HttpServerDelegate>>
http_server_delegate_binding_;

// Owns the elements.
std::set<HttpConnectionDelegateImpl*> connections_;

DISALLOW_COPY_AND_ASSIGN(DevToolsCoordinatorImpl);
};

} // namespace devtools_service

#endif // COMPONENTS_DEVTOOLS_SERVICE_DEVTOOLS_COORDINATOR_IMPL_H_
44 changes: 38 additions & 6 deletions components/devtools_service/devtools_service_delegate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,59 @@
#include "components/devtools_service/devtools_service_delegate.h"

#include "base/logging.h"
#include "components/devtools_service/devtools_coordinator_impl.h"
#include "mojo/application/public/cpp/application_connection.h"
#include "mojo/application/public/cpp/application_impl.h"
#include "mojo/common/url_type_converters.h"
#include "url/gurl.h"

namespace devtools_service {

DevToolsServiceDelegate::DevToolsServiceDelegate() {}
namespace {

DevToolsServiceDelegate::~DevToolsServiceDelegate() {}
bool IsShell(const GURL& requestor_url) {
// TODO(yzshen): http://crbug.com/491656 "mojo://shell/" has to be used
// instead of "mojo:shell" because "mojo" is not treated as a standard scheme.
return requestor_url == GURL("mojo://shell/");
}

} // namespace

DevToolsServiceDelegate::DevToolsServiceDelegate() {
}

DevToolsServiceDelegate::~DevToolsServiceDelegate() {
}

void DevToolsServiceDelegate::Initialize(mojo::ApplicationImpl* app) {
NOTIMPLEMENTED();
coordinator_.reset(new DevToolsCoordinatorImpl(app));
}

bool DevToolsServiceDelegate::ConfigureIncomingConnection(
mojo::ApplicationConnection* connection) {
NOTIMPLEMENTED();
return false;
connection->AddService<DevToolsAgentClient>(this);

// DevToolsCoordinator is a privileged interface and only allowed for the
// shell.
if (IsShell(GURL(connection->GetRemoteApplicationURL())))
connection->AddService<DevToolsCoordinator>(this);
return true;
}

void DevToolsServiceDelegate::Quit() {
NOTIMPLEMENTED();
coordinator_.reset();
}

void DevToolsServiceDelegate::Create(
mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<DevToolsAgentClient> request) {
coordinator_->CreateAgentClient(request.Pass());
}

void DevToolsServiceDelegate::Create(
mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<DevToolsCoordinator> request) {
coordinator_->BindToCoordinatorRequest(request.Pass());
}

} // namespace devtools_service
21 changes: 19 additions & 2 deletions components/devtools_service/devtools_service_delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,40 @@
#define COMPONENTS_DEVTOOLS_SERVICE_DEVTOOLS_SERVICE_DELEGATE_H_

#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "components/devtools_service/public/interfaces/devtools_service.mojom.h"
#include "mojo/application/public/cpp/application_delegate.h"
#include "mojo/application/public/cpp/interface_factory.h"

namespace devtools_service {

class DevToolsServiceDelegate : public mojo::ApplicationDelegate {
class DevToolsCoordinatorImpl;

class DevToolsServiceDelegate
: public mojo::ApplicationDelegate,
public mojo::InterfaceFactory<DevToolsAgentClient>,
public mojo::InterfaceFactory<DevToolsCoordinator> {
public:
DevToolsServiceDelegate();
~DevToolsServiceDelegate() override;

private:
// ApplicationDelegate implementation.
// mojo::ApplicationDelegate implementation.
void Initialize(mojo::ApplicationImpl* app) override;
bool ConfigureIncomingConnection(
mojo::ApplicationConnection* connection) override;
void Quit() override;

// mojo::InterfaceFactory<DevToolsAgentClient> implementation.
void Create(mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<DevToolsAgentClient> request) override;

// mojo::InterfaceFactory<DevToolsCoordinator> implementation.
void Create(mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<DevToolsCoordinator> request) override;

scoped_ptr<DevToolsCoordinatorImpl> coordinator_;

DISALLOW_COPY_AND_ASSIGN(DevToolsServiceDelegate);
};

Expand Down
Loading

0 comments on commit b51b266

Please sign in to comment.