Redo: Adding a mojo interface to the mojo spy

This is the same as
https://codereview.chromium.org/284743002

Which was reverted because a mojo refactoring won the checking race
and I did not notice the revert.

Original message:

Adding more guts to the mojo spy.

This CL fleshes out the basic architecture of the spy. Introducing SpyServerImpl and enough code to operate the "start" and "stop" commands of the front-end.

Still a quite a few loose ends, specially on teardown.

I updated the design doc to reflect this CL:
https://docs.google.com/a/chromium.org/document/d/11FKYXf9mSohlsgl4JmGlyWE1ScX3DKdssdjub63tkwA/edit?usp=sharing

TBR=darin
BUG=360188
TEST=manual via test/spy_repl_test.html

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@281995 0039d316-1c4b-4281-b951-d872f2087c98


CrOS-Libchrome-Original-Commit: 1fd1a5243ff958c46d55ea9b9ceee74fcf9ed534
diff --git a/mojo/spy/websocket_server.cc b/mojo/spy/websocket_server.cc
index 649a135..baa8709 100644
--- a/mojo/spy/websocket_server.cc
+++ b/mojo/spy/websocket_server.cc
@@ -4,20 +4,29 @@
 
 #include "mojo/spy/websocket_server.h"
 
+#include <string>
+
 #include "base/bind.h"
 #include "base/strings/stringprintf.h"
+
+#include "mojo/public/cpp/bindings/message.h"
+
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_errors.h"
 #include "net/server/http_server_request_info.h"
 #include "net/server/http_server_response_info.h"
 #include "net/socket/tcp_listen_socket.h"
 
-namespace spy {
+namespace mojo {
 
 const int kNotConnected = -1;
 
-WebSocketServer::WebSocketServer(int port)
-    : port_(port), connection_id_(kNotConnected) {
+WebSocketServer::WebSocketServer(int port,
+                                 mojo::ScopedMessagePipeHandle server_pipe)
+    : port_(port),
+      connection_id_(kNotConnected),
+      spy_server_(MakeProxy<spy_api::SpyServer>(server_pipe.Pass())) {
+  spy_server_.set_client(this);
 }
 
 WebSocketServer::~WebSocketServer() {
@@ -25,9 +34,9 @@
 
 bool WebSocketServer::Start() {
   net::TCPListenSocketFactory factory("0.0.0.0", port_);
-  server_ = new net::HttpServer(factory, this);
+  web_server_ = new net::HttpServer(factory, this);
   net::IPEndPoint address;
-  int error = server_->GetLocalAddress(&address);
+  int error = web_server_->GetLocalAddress(&address);
   port_ = address.port();
   return (error == net::OK);
 }
@@ -35,7 +44,7 @@
 void WebSocketServer::OnHttpRequest(
     int connection_id,
     const net::HttpServerRequestInfo& info) {
-  server_->Send500(connection_id, "websockets protocol only");
+  web_server_->Send500(connection_id, "websockets protocol only");
 }
 
 void WebSocketServer::OnWebSocketRequest(
@@ -45,26 +54,63 @@
     // Reject connection since we already have our client.
     base::MessageLoop::current()->PostTask(
         FROM_HERE,
-        base::Bind(&net::HttpServer::Close, server_, connection_id));
+        base::Bind(&net::HttpServer::Close, web_server_, connection_id));
     return;
   }
   // Accept the connection.
-  server_->AcceptWebSocket(connection_id, info);
+  web_server_->AcceptWebSocket(connection_id, info);
   connection_id_ = connection_id;
 }
 
 void WebSocketServer::OnWebSocketMessage(
     int connection_id,
     const std::string& data) {
-  // TODO(cpu): remove this test code soon.
-  if (data == "\"hello\"")
-    server_->SendOverWebSocket(connection_id, "\"hi there!\"");
+
+  if (data == "\"start\"") {
+    spy_api::VersionPtr ver = spy_api::Version::New();
+    ver->v_major = 0;
+    ver->v_minor = 1;
+    spy_server_->StartSession(
+        ver.Pass(),
+        base::Bind(&WebSocketServer::OnStartSession, base::Unretained(this)));
+  } else if (data == "\"stop\"") {
+    spy_server_->StopSession(
+        base::Bind(&WebSocketServer::OnSessionEnd, base::Unretained(this)));
+  }
+}
+
+void WebSocketServer::OnFatalError(spy_api::Result result) {
+  web_server_->SendOverWebSocket(connection_id_, "\"fatal error\"");
 }
 
 void WebSocketServer::OnClose(
     int connection_id) {
-  if (connection_id == connection_id_)
-    connection_id_ = kNotConnected;
+  if (connection_id != connection_id_)
+    return;
+  connection_id_ = kNotConnected;
+
+  spy_server_->StopSession(
+      base::Bind(&WebSocketServer::OnSessionEnd, base::Unretained(this)));
 }
 
-}  // namespace spy
+void WebSocketServer::OnSessionEnd(spy_api::Result result) {
+  // Called when the spy session (not the websocket) ends.
+}
+
+void WebSocketServer::OnClientConnection(
+  const mojo::String& name,
+  uint32_t id,
+  spy_api::ConnectionOptions options) {
+  std::string cc("\"");
+  cc += name.To<std::string>() + "\"";
+  web_server_->SendOverWebSocket(connection_id_, cc);
+}
+
+void WebSocketServer::OnMessage(spy_api::MessagePtr message) {
+}
+
+void WebSocketServer::OnStartSession(spy_api::Result, mojo::String) {
+  web_server_->SendOverWebSocket(connection_id_, "\"ok start\"");
+}
+
+}  // namespace mojo