Chromium Code Reviews| Index: sky/services/inspector/server.cc |
| diff --git a/sky/services/inspector/server.cc b/sky/services/inspector/server.cc |
| index d052cc257b01185058697692dd63ab94c2dfa6b9..574c30367c552867ecf173a9fea872c495d3c5e8 100644 |
| --- a/sky/services/inspector/server.cc |
| +++ b/sky/services/inspector/server.cc |
| @@ -2,36 +2,197 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| +#include "base/lazy_instance.h" |
|
abarth-chromium
2014/11/11 02:53:57
Is this needed?
|
| #include "mojo/application/application_runner_chromium.h" |
| #include "mojo/public/c/system/main.h" |
| #include "mojo/public/cpp/application/application_delegate.h" |
| #include "mojo/public/cpp/application/application_impl.h" |
| +#include "net/server/http_server.h" |
| +#include "net/socket/tcp_server_socket.h" |
| #include "sky/services/inspector/inspector_frontend_impl.h" |
| namespace sky { |
| namespace inspector { |
| -class Server : public mojo::ApplicationDelegate { |
| +// TODO(eseidel): None of this Impl nonsense is necessary: crbug.com/431963 |
| +class ServerImpl : public mojo::InterfaceImpl<InspectorServer> { |
|
abarth-chromium
2014/11/11 02:53:57
Should we move this into server.h and create anoth
Aaron Boodman
2014/11/11 16:12:50
As I said in other class, I think the opposite.
|
| +public: |
| + class Delegate { |
| + public: |
| + virtual void Register(ServerImpl* impl) = 0; |
| + virtual void Unregister(ServerImpl* impl) = 0; |
| + virtual void Listen(int32_t port) = 0; |
| + }; |
| + ServerImpl(Delegate* delegate) : delegate_(delegate) { |
|
abarth-chromium
2014/11/11 02:53:57
explicit
|
| + delegate_->Register(this); |
| + } |
| + virtual ~ServerImpl() { |
| + delegate_->Unregister(this); |
| + } |
| + |
| + // InspectorServer: |
| + void Listen(int32_t port, const mojo::Callback<void()>& callback) override; |
| + |
| + void OnShutdown() { |
| + delete this; |
| + } |
| + |
| +private: |
| + // InterfaceImpl: |
| + void OnConnectionError() override { |
| + delete this; |
| + } |
| + |
| + Delegate* delegate_; |
| +}; |
| + |
| +namespace { |
| +const int kNotConnected = -1; |
| +} |
| + |
| +class Server : public mojo::ApplicationDelegate, |
| + public InspectorFrontendImpl::Delegate, |
| + public ServerImpl::Delegate, |
| + public mojo::InterfaceFactory<InspectorFrontend>, |
| + public mojo::InterfaceFactory<InspectorServer>, |
| + public net::HttpServer::Delegate { |
| public: |
| - Server() {} |
| - virtual ~Server() {} |
| + Server() : connection_id_(kNotConnected) {} |
| + virtual ~Server(); |
| private: |
| - // Overridden from mojo::ApplicationDelegate: |
| - virtual void Initialize(mojo::ApplicationImpl* app) override { |
| + // mojo::ApplicationDelegate: |
| + void Initialize(mojo::ApplicationImpl* app) override { |
| } |
| - |
| - virtual bool ConfigureIncomingConnection( |
| + bool ConfigureIncomingConnection( |
| mojo::ApplicationConnection* connection) override { |
| - connection->AddService(&frontend_factory_); |
| + connection->AddService<InspectorFrontend>(this); |
| + connection->AddService<InspectorServer>(this); |
| return true; |
| } |
| - InspectorFrontendFactory frontend_factory_; |
| + // InterfaceFactory<InspectorFrontend>: |
| + void Create(mojo::ApplicationConnection* connection, |
| + mojo::InterfaceRequest<InspectorFrontend> request) override { |
| + WeakBindToRequest(new InspectorFrontendImpl(this), &request); |
| + } |
| + |
| + // InterfaceFactory<InspectorServer>: |
| + void Create(mojo::ApplicationConnection* connection, |
| + mojo::InterfaceRequest<InspectorServer> request) override { |
| + WeakBindToRequest(new ServerImpl(this), &request); |
| + } |
| + |
| + // ServerImpl::Delegate: |
| + void Register(ServerImpl*) override; |
| + void Unregister(ServerImpl*) override; |
| + void Listen(int32_t port) override; |
| + |
| + // InspectorFrontendImpl::Delegate: |
| + void Register(InspectorFrontendImpl*) override; |
| + void Unregister(InspectorFrontendImpl*) override; |
| + void SendMessage(const mojo::String& message) override; |
| + |
| + // net::HttpServer::Delegate: |
| + void OnConnect(int connection_id) override; |
| + void OnHttpRequest( |
| + int connection_id, const net::HttpServerRequestInfo& info) override; |
| + void OnWebSocketRequest( |
| + int connection_id, const net::HttpServerRequestInfo& info) override; |
| + void OnWebSocketMessage( |
| + int connection_id, const std::string& data) override; |
| + void OnClose(int connection_id) override; |
| + |
| + void CloseAllAgentConnections(); |
| + |
| + int connection_id_; |
| + scoped_ptr<net::HttpServer> web_server_; |
| + ObserverList<InspectorFrontendImpl> agents_; |
| + ObserverList<ServerImpl> clients_; |
| DISALLOW_COPY_AND_ASSIGN(Server); |
| }; |
| +Server::~Server() |
| +{ |
|
abarth-chromium
2014/11/11 02:53:57
These lines should be merged in Chromium style.
|
| + FOR_EACH_OBSERVER(ServerImpl, clients_, OnShutdown()); |
| + CloseAllAgentConnections(); |
| +} |
| + |
| +void Server::CloseAllAgentConnections() { |
| + FOR_EACH_OBSERVER(InspectorFrontendImpl, agents_, OnShutdown()); |
| +} |
| + |
| +void Server::OnConnect(int connection_id) { |
| +} |
| + |
| +void Server::OnHttpRequest( |
| + int connection_id, const net::HttpServerRequestInfo& info) { |
| + web_server_->Send500(connection_id, "websockets protocol only"); |
| +} |
| + |
| +void Server::OnWebSocketRequest( |
| + int connection_id, const net::HttpServerRequestInfo& info) { |
| + if (connection_id_ != kNotConnected) { |
| + web_server_->Close(connection_id); |
| + return; |
| + } |
| + web_server_->AcceptWebSocket(connection_id, info); |
| + connection_id_ = connection_id; |
| + FOR_EACH_OBSERVER(InspectorFrontendImpl, agents_, client()->OnConnect()); |
| +} |
| + |
| +void Server::OnWebSocketMessage( |
| + int connection_id, const std::string& data) { |
| + DCHECK_EQ(connection_id, connection_id_); |
| + FOR_EACH_OBSERVER(InspectorFrontendImpl, agents_, client()->OnMessage(data)); |
| +} |
| + |
| +void Server::OnClose(int connection_id) { |
| + if (connection_id != connection_id_) |
| + return; |
| + connection_id_ = kNotConnected; |
| + FOR_EACH_OBSERVER(InspectorFrontendImpl, agents_, client()->OnDisconnect()); |
| +} |
| + |
| +void Server::Register(ServerImpl* client) { |
| + clients_.AddObserver(client); |
| +} |
| + |
| +void Server::Unregister(ServerImpl* client) { |
| + clients_.RemoveObserver(client); |
| +} |
| + |
| +void Server::Register(InspectorFrontendImpl* agent) { |
| + agents_.AddObserver(agent); |
| +} |
| + |
| +void Server::Unregister(InspectorFrontendImpl* agent) { |
| + agents_.RemoveObserver(agent); |
| +} |
| + |
| +void ServerImpl::Listen(int32_t port, const mojo::Callback<void()>& callback) { |
| + delegate_->Listen(port); |
| + callback.Run(); |
| +} |
| + |
| +void Server::Listen(int32_t port) { |
| + CloseAllAgentConnections(); // Assume caller represents a new app. |
| + |
| + // TODO(eseidel): Early-out here if we're already bound to the right port. |
|
abarth-chromium
2014/11/11 02:53:57
Is this comment still accurate? The network seman
|
| + web_server_.reset(); |
| + scoped_ptr<net::ServerSocket> server_socket( |
| + new net::TCPServerSocket(NULL, net::NetLog::Source())); |
| + server_socket->ListenWithAddressAndPort("0.0.0.0", port, 1); |
| + web_server_.reset(new net::HttpServer(server_socket.Pass(), this)); |
| +} |
| + |
| +void Server::SendMessage(const mojo::String& message) { |
| + if (connection_id_ == kNotConnected) |
| + return; |
| + web_server_->SendOverWebSocket(connection_id_, message); |
| +} |
| + |
| } // namespace inspector |
| } // namespace sky |