Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / devtools / devtools_http_handler_impl.cc
index b0d866e..e7b7fb9 100644 (file)
 #include "base/strings/string_number_conversions.h"
 #include "base/threading/thread.h"
 #include "base/values.h"
-#include "content/browser/devtools/devtools_browser_target.h"
 #include "content/browser/devtools/devtools_manager.h"
 #include "content/browser/devtools/devtools_protocol.h"
 #include "content/browser/devtools/devtools_protocol_constants.h"
 #include "content/browser/devtools/devtools_system_info_handler.h"
-#include "content/browser/devtools/devtools_tracing_handler.h"
+#include "content/browser/devtools/protocol/devtools_protocol_handler_impl.h"
+#include "content/browser/devtools/protocol/tracing_handler.h"
 #include "content/browser/devtools/tethering_handler.h"
 #include "content/common/devtools_messages.h"
 #include "content/public/browser/browser_thread.h"
@@ -71,6 +71,8 @@ const char kTargetDevtoolsFrontendUrlField[] = "devtoolsFrontendUrl";
 // Maximum write buffer size of devtools http/websocket connectinos.
 const int32 kSendBufferSizeForDevTools = 100 * 1024 * 1024;  // 100Mb
 
+// DevToolsAgentHostClientImpl -----------------------------------------------
+
 // An internal implementation of DevToolsAgentHostClient that delegates
 // messages sent to a DebuggerShell instance.
 class DevToolsAgentHostClientImpl : public DevToolsAgentHostClient {
@@ -86,14 +88,13 @@ class DevToolsAgentHostClientImpl : public DevToolsAgentHostClient {
     agent_host_->AttachClient(this);
   }
 
-  virtual ~DevToolsAgentHostClientImpl() {
+  ~DevToolsAgentHostClientImpl() override {
     if (agent_host_.get())
       agent_host_->DetachClient();
   }
 
-  virtual void AgentHostClosed(
-      DevToolsAgentHost* agent_host,
-      bool replaced_with_another_client) OVERRIDE {
+  void AgentHostClosed(DevToolsAgentHost* agent_host,
+                       bool replaced_with_another_client) override {
     DCHECK(agent_host == agent_host_.get());
     agent_host_ = NULL;
 
@@ -119,8 +120,8 @@ class DevToolsAgentHostClientImpl : public DevToolsAgentHostClient {
                    connection_id_));
   }
 
-  virtual void DispatchProtocolMessage(
-      DevToolsAgentHost* agent_host, const std::string& message) OVERRIDE {
+  void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
+                               const std::string& message) override {
     DCHECK(agent_host == agent_host_.get());
     message_loop_->PostTask(
         FROM_HERE,
@@ -149,6 +150,83 @@ static bool TimeComparator(const DevToolsTarget* target1,
 
 }  // namespace
 
+// DevToolsHttpHandlerImpl::BrowserTarget ------------------------------------
+
+class DevToolsHttpHandlerImpl::BrowserTarget {
+ public:
+  BrowserTarget(base::MessageLoop* message_loop,
+                net::HttpServer* server,
+                int connection_id)
+      : message_loop_(message_loop),
+        server_(server),
+        connection_id_(connection_id),
+        tracing_handler_(new devtools::tracing::TracingHandler(
+            devtools::tracing::TracingHandler::Browser)),
+        protocol_handler_(new DevToolsProtocolHandlerImpl()) {
+    protocol_handler_->SetNotifier(
+        base::Bind(&BrowserTarget::Respond, base::Unretained(this)));
+    protocol_handler_->SetTracingHandler(tracing_handler_.get());
+  }
+
+  ~BrowserTarget() {
+    STLDeleteElements(&handlers_);
+  }
+
+  // Takes ownership.
+  void RegisterHandler(DevToolsProtocol::Handler* handler) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    handler->SetNotifier(
+        base::Bind(&BrowserTarget::Respond, base::Unretained(this)));
+    handlers_.push_back(handler);
+  }
+
+  void HandleMessage(const std::string& message) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    std::string error_response;
+    scoped_refptr<DevToolsProtocol::Command> command =
+        DevToolsProtocol::ParseCommand(message, &error_response);
+    if (!command.get()) {
+      Respond(error_response);
+      return;
+    }
+
+    scoped_refptr<DevToolsProtocol::Response> response =
+        protocol_handler_->HandleCommand(command);
+    for (const auto& handler : handlers_) {
+      if (response.get())
+        break;
+      response = handler->HandleCommand(command);
+    }
+
+    if (response.get()) {
+      if (!response->is_async_promise())
+        Respond(response->Serialize());
+    } else {
+      Respond(command->NoSuchMethodErrorResponse()->Serialize());
+    }
+  }
+
+  void Respond(const std::string& message) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    message_loop_->PostTask(
+        FROM_HERE,
+        base::Bind(&net::HttpServer::SendOverWebSocket,
+                   base::Unretained(server_),
+                   connection_id_,
+                   message));
+  }
+
+ private:
+  base::MessageLoop* const message_loop_;
+  net::HttpServer* const server_;
+  const int connection_id_;
+  scoped_ptr<devtools::tracing::TracingHandler> tracing_handler_;
+  scoped_ptr<DevToolsProtocolHandlerImpl> protocol_handler_;
+  std::vector<DevToolsProtocol::Handler*> handlers_;
+};
+
+// DevToolsHttpHandler -------------------------------------------------------
+
 // static
 bool DevToolsHttpHandler::IsSupportedProtocolVersion(
     const std::string& version) {
@@ -179,6 +257,8 @@ DevToolsHttpHandler* DevToolsHttpHandler::Start(
   return http_handler;
 }
 
+// DevToolsHttpHandler::ServerSocketFactory ----------------------------------
+
 DevToolsHttpHandler::ServerSocketFactory::ServerSocketFactory(
     const std::string& address,
     int port,
@@ -201,6 +281,8 @@ DevToolsHttpHandler::ServerSocketFactory::CreateAndListen() const {
   return scoped_ptr<net::ServerSocket>();
 }
 
+// DevToolsHttpHandlerImpl ---------------------------------------------------
+
 DevToolsHttpHandlerImpl::~DevToolsHttpHandlerImpl() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   // Stop() must be called prior to destruction.
@@ -236,6 +318,7 @@ void DevToolsHttpHandlerImpl::StartHandlerThread() {
 
 void DevToolsHttpHandlerImpl::ResetHandlerThread() {
   thread_.reset();
+  server_ip_address_.reset();
 }
 
 void DevToolsHttpHandlerImpl::ResetHandlerThreadAndRelease() {
@@ -262,10 +345,9 @@ void DevToolsHttpHandlerImpl::StopWithoutRelease() {
 }
 
 GURL DevToolsHttpHandlerImpl::GetFrontendURL() {
-  net::IPEndPoint ip_address;
-  if (server_ && server_->GetLocalAddress(&ip_address))
+  if (!server_ip_address_)
     return GURL();
-  return GURL(std::string("http://") + ip_address.ToString() + frontend_url_);
+  return GURL(std::string("http://") + server_ip_address_->ToString() + frontend_url_);
 }
 
 static std::string PathWithoutParams(const std::string& path) {
@@ -360,7 +442,7 @@ void DevToolsHttpHandlerImpl::OnHttpRequest(
     int resource_id = DevToolsHttpHandler::GetFrontendResourceId(filename);
     if (resource_id != -1) {
       base::StringPiece data = GetContentClient()->GetDataResource(
-              resource_id, ui::SCALE_FACTOR_NONE);
+          resource_id, ui::SCALE_FACTOR_NONE);
       server_->Send200(connection_id, data.as_string(), mime_type);
       return;
     }
@@ -371,30 +453,6 @@ void DevToolsHttpHandlerImpl::OnHttpRequest(
 void DevToolsHttpHandlerImpl::OnWebSocketRequest(
     int connection_id,
     const net::HttpServerRequestInfo& request) {
-  std::string browser_prefix = "/devtools/browser";
-  size_t browser_pos = request.path.find(browser_prefix);
-  if (browser_pos == 0) {
-    scoped_refptr<DevToolsBrowserTarget> browser_target =
-        new DevToolsBrowserTarget(server_.get(), connection_id);
-    browser_target->RegisterDomainHandler(
-        devtools::Tracing::kName,
-        new DevToolsTracingHandler(DevToolsTracingHandler::Browser),
-        true /* handle on UI thread */);
-    browser_target->RegisterDomainHandler(
-        devtools::Tethering::kName,
-        new TetheringHandler(delegate_.get()),
-        false /* handle on this thread */);
-    browser_target->RegisterDomainHandler(
-        devtools::SystemInfo::kName,
-        new DevToolsSystemInfoHandler(),
-        true /* handle on UI thread */);
-    browser_targets_[connection_id] = browser_target;
-
-    server_->SetSendBufferSize(connection_id, kSendBufferSizeForDevTools);
-    server_->AcceptWebSocket(connection_id, request);
-    return;
-  }
-
   BrowserThread::PostTask(
       BrowserThread::UI,
       FROM_HERE,
@@ -408,12 +466,6 @@ void DevToolsHttpHandlerImpl::OnWebSocketRequest(
 void DevToolsHttpHandlerImpl::OnWebSocketMessage(
     int connection_id,
     const std::string& data) {
-  BrowserTargets::iterator it = browser_targets_.find(connection_id);
-  if (it != browser_targets_.end()) {
-    it->second->HandleMessage(data);
-    return;
-  }
-
   BrowserThread::PostTask(
       BrowserThread::UI,
       FROM_HERE,
@@ -425,13 +477,6 @@ void DevToolsHttpHandlerImpl::OnWebSocketMessage(
 }
 
 void DevToolsHttpHandlerImpl::OnClose(int connection_id) {
-  BrowserTargets::iterator it = browser_targets_.find(connection_id);
-  if (it != browser_targets_.end()) {
-    it->second->Detach();
-    browser_targets_.erase(it);
-    return;
-  }
-
   BrowserThread::PostTask(
       BrowserThread::UI,
       FROM_HERE,
@@ -652,6 +697,20 @@ void DevToolsHttpHandlerImpl::OnWebSocketRequestUI(
   if (!thread_)
     return;
 
+  std::string browser_prefix = "/devtools/browser";
+  size_t browser_pos = request.path.find(browser_prefix);
+  if (browser_pos == 0) {
+    BrowserTarget* browser_target = new BrowserTarget(
+        thread_->message_loop(), server_.get(), connection_id);
+    browser_target->RegisterHandler(
+        new TetheringHandler(delegate_.get(), thread_->message_loop_proxy()));
+    browser_target->RegisterHandler(
+        new DevToolsSystemInfoHandler());
+    browser_targets_[connection_id] = browser_target;
+    AcceptWebSocket(connection_id, request);
+    return;
+  }
+
   size_t pos = request.path.find(kPageUrlPrefix);
   if (pos != 0) {
     Send404(connection_id);
@@ -683,6 +742,12 @@ void DevToolsHttpHandlerImpl::OnWebSocketRequestUI(
 void DevToolsHttpHandlerImpl::OnWebSocketMessageUI(
     int connection_id,
     const std::string& data) {
+  BrowserTargets::iterator browser_it = browser_targets_.find(connection_id);
+  if (browser_it != browser_targets_.end()) {
+    browser_it->second->HandleMessage(data);
+    return;
+  }
+
   ConnectionToClientMap::iterator it =
       connection_to_client_ui_.find(connection_id);
   if (it == connection_to_client_ui_.end())
@@ -694,6 +759,13 @@ void DevToolsHttpHandlerImpl::OnWebSocketMessageUI(
 }
 
 void DevToolsHttpHandlerImpl::OnCloseUI(int connection_id) {
+  BrowserTargets::iterator browser_it = browser_targets_.find(connection_id);
+  if (browser_it != browser_targets_.end()) {
+    delete browser_it->second;
+    browser_targets_.erase(connection_id);
+    return;
+  }
+
   ConnectionToClientMap::iterator it =
       connection_to_client_ui_.find(connection_id);
   if (it != connection_to_client_ui_.end()) {
@@ -704,6 +776,11 @@ void DevToolsHttpHandlerImpl::OnCloseUI(int connection_id) {
   }
 }
 
+void DevToolsHttpHandlerImpl::OnHttpServerInitialized(
+    const net::IPEndPoint& ip_address) {
+  server_ip_address_.reset(new net::IPEndPoint(ip_address));
+}
+
 DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl(
     scoped_ptr<ServerSocketFactory> server_socket_factory,
     const std::string& frontend_url,
@@ -733,13 +810,19 @@ void DevToolsHttpHandlerImpl::Init() {
   }
 
   server_.reset(new net::HttpServer(server_socket.Pass(), this));
+  net::IPEndPoint ip_address;
+  server_->GetLocalAddress(&ip_address);
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      base::Bind(&DevToolsHttpHandlerImpl::OnHttpServerInitialized,
+                 this, ip_address));
   if (!active_port_output_directory_.empty())
     WriteActivePortToUserProfile();
 }
 
 // Runs on the handler thread
 void DevToolsHttpHandlerImpl::Teardown() {
-  server_.reset(NULL);
+  server_.reset();
 }
 
 // Runs on FILE thread to make sure that it is serialized against