diff --git a/framework/inspector/inspector.sky b/framework/inspector/inspector.sky index c4c8ec6866f390d003480c592859531cb09a5cf0..6e73f78f1903cb044707fa46e7c19dd0d1c5709c 100644 --- a/framework/inspector/inspector.sky +++ b/framework/inspector/inspector.sky @@ -93,5 +93,4 @@ window.frontendConnection = new connection.Connection( inspector.InspectorFrontend.proxyClass); window.frontend = frontendConnection.remote; -frontend.listen(9898); diff --git a/services/inspector/BUILD.gn b/services/inspector/BUILD.gn index e2b11f2a8676851d647e5480fc96ec5b3c7dfb50..eb52f0b00c09e05bb9a6dc901c063e365be43a82 100644 --- a/services/inspector/BUILD.gn +++ b/services/inspector/BUILD.gn @@ -5,8 +5,6 @@ import("//mojo/public/tools/bindings/mojom.gni") group("inspector") { - testonly = true - deps = [ ":sky_inspector_server", ] @@ -14,8 +12,6 @@ group("inspector") { shared_library("sky_inspector_server") { sources = [ - "inspector_frontend_impl.cc", - "inspector_frontend_impl.h", "server.cc", ] diff --git a/services/inspector/inspector.mojom b/services/inspector/inspector.mojom index 70a7503176119066a1e3ce739d042b645e685067..4d65b439716e5175f2a5fba66e8ec389f09e59dc 100644 --- a/services/inspector/inspector.mojom +++ b/services/inspector/inspector.mojom @@ -4,9 +4,12 @@ module sky; +interface InspectorServer { + Listen(int32 port) => (); +}; + [Client=InspectorBackend] interface InspectorFrontend { - Listen(int32 port); SendMessage(string message); }; diff --git a/services/inspector/inspector_frontend_impl.cc b/services/inspector/inspector_frontend_impl.cc deleted file mode 100644 index d88abd12dfab449a0f0a4e7b593c7ca8f9ebd115..0000000000000000000000000000000000000000 --- a/services/inspector/inspector_frontend_impl.cc +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2014 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 "sky/services/inspector/inspector_frontend_impl.h" - -#include "base/lazy_instance.h" -#include "net/server/http_server.h" -#include "net/socket/tcp_server_socket.h" - -namespace sky { -namespace inspector { -namespace { -const int kNotConnected = -1; -static base::LazyInstance> g_servers = - LAZY_INSTANCE_INITIALIZER; -} - -InspectorFrontendImpl::InspectorFrontendImpl() - : connection_id_(kNotConnected) { -} - -InspectorFrontendImpl::~InspectorFrontendImpl() { - StopListening(); -} - -void InspectorFrontendImpl::OnConnect(int connection_id) { -} - -void InspectorFrontendImpl::OnHttpRequest( - int connection_id, const net::HttpServerRequestInfo& info) { - web_server_->Send500(connection_id, "websockets protocol only"); -} - -void InspectorFrontendImpl::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; - client()->OnConnect(); -} - -void InspectorFrontendImpl::OnWebSocketMessage( - int connection_id, const std::string& data) { - DCHECK_EQ(connection_id, connection_id_); - client()->OnMessage(data); -} - -void InspectorFrontendImpl::OnClose(int connection_id) { - if (connection_id != connection_id_) - return; - connection_id_ = kNotConnected; - client()->OnDisconnect(); -} - -void InspectorFrontendImpl::Listen(int32_t port) { - Register(port); - scoped_ptr 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 InspectorFrontendImpl::StopListening() { - if (!web_server_) - return; - web_server_.reset(); - Unregister(); -} - -void InspectorFrontendImpl::Register(int port) { - auto& servers = g_servers.Get(); - auto iter = servers.find(port); - if (iter != servers.end()) - iter->second->StopListening(); - DCHECK(servers.find(port) == servers.end()); - servers[port] = this; - port_ = port; -} - -void InspectorFrontendImpl::Unregister() { - DCHECK(g_servers.Get().find(port_)->second == this); - g_servers.Get().erase(port_); - port_ = kNotConnected; -} - -void InspectorFrontendImpl::SendMessage(const mojo::String& message) { - if (connection_id_ == kNotConnected) - return; - web_server_->SendOverWebSocket(connection_id_, message); -} - -} // namespace inspector -} // namespace sky diff --git a/services/inspector/inspector_frontend_impl.h b/services/inspector/inspector_frontend_impl.h deleted file mode 100644 index 6521760351bcdf3178de391a1ceb3b18037ceb63..0000000000000000000000000000000000000000 --- a/services/inspector/inspector_frontend_impl.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2014 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 SKY_SERVICES_INSPECTOR_INSPECTOR_FRONTEND_IMPL_H_ -#define SKY_SERVICES_INSPECTOR_INSPECTOR_FRONTEND_IMPL_H_ - -#include "mojo/public/cpp/application/interface_factory_impl.h" -#include "mojo/public/cpp/bindings/interface_impl.h" -#include "net/server/http_server.h" -#include "net/socket/tcp_server_socket.h" -#include "sky/services/inspector/inspector.mojom.h" - -namespace sky { -namespace inspector { - -class InspectorFrontendImpl : public mojo::InterfaceImpl, - public net::HttpServer::Delegate { - public: - InspectorFrontendImpl(); - virtual ~InspectorFrontendImpl(); - - private: - // From net::HttpServer::Delegate - virtual void OnConnect(int connection_id) override; - virtual void OnHttpRequest( - int connection_id, const net::HttpServerRequestInfo& info) override; - virtual void OnWebSocketRequest( - int connection_id, const net::HttpServerRequestInfo& info) override; - virtual void OnWebSocketMessage( - int connection_id, const std::string& data) override; - virtual void OnClose(int connection_id) override; - - // From InspectorFrontend - virtual void Listen(int32_t port) override; - virtual void SendMessage(const mojo::String&) override; - - void StopListening(); - - void Register(int port); - void Unregister(); - - int port_; - int connection_id_; - scoped_ptr web_server_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(InspectorFrontendImpl); -}; - -typedef mojo::InterfaceFactoryImpl< - InspectorFrontendImpl> InspectorFrontendFactory; - -} // namespace tester -} // namespace sky - -#endif // SKY_SERVICES_INSPECTOR_INSPECTOR_FRONTEND_IMPL_H_ diff --git a/services/inspector/server.cc b/services/inspector/server.cc index d052cc257b01185058697692dd63ab94c2dfa6b9..0963dd18b7e6bd614a4c3e2b03c281d97fb967c9 100644 --- a/services/inspector/server.cc +++ b/services/inspector/server.cc @@ -6,32 +6,244 @@ #include "mojo/public/c/system/main.h" #include "mojo/public/cpp/application/application_delegate.h" #include "mojo/public/cpp/application/application_impl.h" -#include "sky/services/inspector/inspector_frontend_impl.h" +#include "mojo/public/cpp/application/interface_factory_impl.h" +#include "mojo/public/cpp/bindings/interface_impl.h" +#include "net/server/http_server.h" +#include "net/socket/tcp_server_socket.h" +#include "sky/services/inspector/inspector.mojom.h" + namespace sky { namespace inspector { -class Server : public mojo::ApplicationDelegate { +// TODO(eseidel): None of this Impl nonsense is necessary: crbug.com/431963 +class InspectorServerImpl : public mojo::InterfaceImpl { +public: + class Delegate { + public: + virtual void Register(InspectorServerImpl* impl) = 0; + virtual void Unregister(InspectorServerImpl* impl) = 0; + virtual void Listen(int32_t port) = 0; + }; + InspectorServerImpl(Delegate* delegate) : delegate_(delegate) { + delegate_->Register(this); + } + virtual ~InspectorServerImpl() { + delegate_->Unregister(this); + } + + // InspectorServer: + void Listen(int32_t port, const mojo::Callback& callback) override { + delegate_->Listen(port); + callback.Run(); + } + + void OnShutdown() { + delete this; + } + +private: + // InterfaceImpl: + void OnConnectionError() override { + delete this; // crbug.com/431911 + } + + Delegate* delegate_; +}; + +class InspectorFrontendImpl : public mojo::InterfaceImpl { public: - Server() {} - virtual ~Server() {} + class Delegate { + public: + virtual void Register(InspectorFrontendImpl*) = 0; + virtual void Unregister(InspectorFrontendImpl*) = 0; + virtual void SendMessage(const mojo::String&) = 0; + }; + + InspectorFrontendImpl(Delegate* delegate); + virtual ~InspectorFrontendImpl(); + + void OnShutdown(); private: - // Overridden from mojo::ApplicationDelegate: - virtual void Initialize(mojo::ApplicationImpl* app) override { - } + // InspectorFrontend: + void SendMessage(const mojo::String& message) override; + + // InterfaceImpl: + void OnConnectionError() override; + + Delegate* delegate_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(InspectorFrontendImpl); +}; + +InspectorFrontendImpl::InspectorFrontendImpl(Delegate* delegate) + : delegate_(delegate) { + delegate_->Register(this); +} + +InspectorFrontendImpl::~InspectorFrontendImpl() { + delegate_->Unregister(this); +} + +void InspectorFrontendImpl::OnShutdown() { + client()->OnDisconnect(); + delete this; +} + +void InspectorFrontendImpl::OnConnectionError() { + delete this; // crbug.com/431911 +} - virtual bool ConfigureIncomingConnection( +void InspectorFrontendImpl::SendMessage(const mojo::String& message) { + delegate_->SendMessage(message); +} + + +namespace { +const int kNotConnected = -1; +} + +class Server : public mojo::ApplicationDelegate, + public InspectorFrontendImpl::Delegate, + public InspectorServerImpl::Delegate, + public mojo::InterfaceFactory, + public mojo::InterfaceFactory, + public net::HttpServer::Delegate { + public: + Server() : connection_id_(kNotConnected) {} + virtual ~Server(); + + private: + // mojo::ApplicationDelegate: + void Initialize(mojo::ApplicationImpl* app) override { + } + bool ConfigureIncomingConnection( mojo::ApplicationConnection* connection) override { - connection->AddService(&frontend_factory_); + connection->AddService(this); + connection->AddService(this); return true; } - InspectorFrontendFactory frontend_factory_; + // InterfaceFactory: + void Create(mojo::ApplicationConnection* connection, + mojo::InterfaceRequest request) override { + // Weak instead of strong, per crbug.com/431911 + WeakBindToRequest(new InspectorFrontendImpl(this), &request); + } + + // InterfaceFactory: + void Create(mojo::ApplicationConnection* connection, + mojo::InterfaceRequest request) override { + // Weak instead of strong, per crbug.com/431911 + WeakBindToRequest(new InspectorServerImpl(this), &request); + } + + // InspectorServerImpl::Delegate: + void Register(InspectorServerImpl*) override; + void Unregister(InspectorServerImpl*) 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 web_server_; + ObserverList agents_; + ObserverList clients_; DISALLOW_COPY_AND_ASSIGN(Server); }; +Server::~Server() +{ + FOR_EACH_OBSERVER(InspectorServerImpl, 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(InspectorServerImpl* client) { + clients_.AddObserver(client); +} + +void Server::Unregister(InspectorServerImpl* client) { + clients_.RemoveObserver(client); +} + +void Server::Register(InspectorFrontendImpl* agent) { + agents_.AddObserver(agent); +} + +void Server::Unregister(InspectorFrontendImpl* agent) { + agents_.RemoveObserver(agent); +} + +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. + web_server_.reset(); + scoped_ptr 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 diff --git a/viewer/BUILD.gn b/viewer/BUILD.gn index 4018a3103532a31b39370e6ad694a0e814cfb9a3..3b834d5114a3ef675189f6d5aaac9f16e9a51046 100644 --- a/viewer/BUILD.gn +++ b/viewer/BUILD.gn @@ -42,16 +42,18 @@ shared_library("viewer") { include_dirs = [ ".." ] deps = [ + ":bindings", + ":sky_modules", "//base:i18n", "//cc", "//cc/surfaces", "//gin", "//mojo/application", - "//mojo/edk/js", "//mojo/cc", "//mojo/common", "//mojo/converters/geometry", "//mojo/converters/surfaces", + "//mojo/edk/js", "//mojo/public/c/system:for_shared_library", "//mojo/public/cpp/bindings", "//mojo/public/cpp/system", @@ -67,12 +69,11 @@ shared_library("viewer") { "//net", "//skia", "//sky/engine/public:blink", + "//sky/services/inspector:bindings", "//sky/viewer/cc", "//third_party/icu", "//ui/native_theme", "//url", - ":bindings", - ":sky_modules", ] } diff --git a/viewer/services/inspector_impl.cc b/viewer/services/inspector_impl.cc index a5343fa9600723ac64b2513f202966330e1700ab..4c8d086f3ed98ed58d565e0bcd090da8482667ae 100644 --- a/viewer/services/inspector_impl.cc +++ b/viewer/services/inspector_impl.cc @@ -4,10 +4,12 @@ #include "sky/viewer/services/inspector_impl.h" +#include "base/bind.h" #include "sky/engine/public/web/WebDocument.h" #include "sky/engine/public/web/WebElement.h" #include "sky/engine/public/web/WebFrame.h" #include "sky/engine/public/web/WebView.h" +#include "sky/services/inspector/inspector.mojom.h" #include "sky/viewer/document_view.h" namespace sky { @@ -19,9 +21,21 @@ InspectorServiceImpl::InspectorServiceImpl(DocumentView* view) InspectorServiceImpl::~InspectorServiceImpl() { } +void Ignored() {} + void InspectorServiceImpl::Inject() { if (!view_) return; + + mojo::ServiceProviderPtr inpector_service_provider; + view_->shell()->ConnectToApplication("mojo:sky_inspector_server", + GetProxy(&inpector_service_provider)); + InspectorServerPtr inspector; + ConnectToService(inpector_service_provider.get(), &inspector); + inspector->Listen(9898, base::Bind(&Ignored)); + // Listen drops existing agents/backends, wait before registering new ones. + inspector.WaitForIncomingMethodCall(); + view_->web_view()->injectModule("/sky/framework/inspector/inspector.sky"); }