summaryrefslogtreecommitdiffstats
path: root/chrome/browser/debugger
diff options
context:
space:
mode:
authorpfeldman@chromium.org <pfeldman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-06 10:13:00 +0000
committerpfeldman@chromium.org <pfeldman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-06 10:13:00 +0000
commita9bf679843d02a5655cccb53655d8561b140709a (patch)
tree4345425b602e964deeb4f1cc22f0d2ece6b12414 /chrome/browser/debugger
parent02d8de1ba500e934ef840062a8d1fd03f88ddce1 (diff)
downloadchromium_src-a9bf679843d02a5655cccb53655d8561b140709a.zip
chromium_src-a9bf679843d02a5655cccb53655d8561b140709a.tar.gz
chromium_src-a9bf679843d02a5655cccb53655d8561b140709a.tar.bz2
DevTools: add stub for HTTP-based remote debugger interface.
Review URL: http://codereview.chromium.org/2802032 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@51661 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/debugger')
-rw-r--r--chrome/browser/debugger/debugger_wrapper.cc36
-rw-r--r--chrome/browser/debugger/debugger_wrapper.h4
-rw-r--r--chrome/browser/debugger/devtools_http_protocol_handler.cc256
-rw-r--r--chrome/browser/debugger/devtools_http_protocol_handler.h70
4 files changed, 351 insertions, 15 deletions
diff --git a/chrome/browser/debugger/debugger_wrapper.cc b/chrome/browser/debugger/debugger_wrapper.cc
index c551846..644bf05 100644
--- a/chrome/browser/debugger/debugger_wrapper.cc
+++ b/chrome/browser/debugger/debugger_wrapper.cc
@@ -4,29 +4,37 @@
#include "chrome/browser/debugger/debugger_wrapper.h"
+#include "chrome/browser/debugger/devtools_http_protocol_handler.h"
#include "chrome/browser/debugger/debugger_remote_service.h"
#include "chrome/browser/debugger/devtools_protocol_handler.h"
#include "chrome/browser/debugger/devtools_remote_service.h"
#include "chrome/browser/debugger/extension_ports_remote_service.h"
-DebuggerWrapper::DebuggerWrapper(int port) {
+DebuggerWrapper::DebuggerWrapper(int port, bool useHttp) {
if (port > 0) {
- proto_handler_ = new DevToolsProtocolHandler(port);
- proto_handler_->RegisterDestination(
- new DevToolsRemoteService(proto_handler_),
- DevToolsRemoteService::kToolName);
- proto_handler_->RegisterDestination(
- new DebuggerRemoteService(proto_handler_),
- DebuggerRemoteService::kToolName);
- proto_handler_->RegisterDestination(
- new ExtensionPortsRemoteService(proto_handler_),
- ExtensionPortsRemoteService::kToolName);
- proto_handler_->Start();
+ if (useHttp) {
+ http_handler_ = new DevToolsHttpProtocolHandler(port);
+ http_handler_->Start();
+ } else {
+ proto_handler_ = new DevToolsProtocolHandler(port);
+ proto_handler_->RegisterDestination(
+ new DevToolsRemoteService(proto_handler_),
+ DevToolsRemoteService::kToolName);
+ proto_handler_->RegisterDestination(
+ new DebuggerRemoteService(proto_handler_),
+ DebuggerRemoteService::kToolName);
+ proto_handler_->RegisterDestination(
+ new ExtensionPortsRemoteService(proto_handler_),
+ ExtensionPortsRemoteService::kToolName);
+ proto_handler_->Start();
+ }
}
}
DebuggerWrapper::~DebuggerWrapper() {
- if (proto_handler_.get() != NULL) {
+ if (proto_handler_.get() != NULL)
proto_handler_->Stop();
- }
+
+ if (http_handler_.get() != NULL)
+ http_handler_->Stop();
}
diff --git a/chrome/browser/debugger/debugger_wrapper.h b/chrome/browser/debugger/debugger_wrapper.h
index 11ecb0c..0a82366 100644
--- a/chrome/browser/debugger/debugger_wrapper.h
+++ b/chrome/browser/debugger/debugger_wrapper.h
@@ -15,12 +15,13 @@
#include "base/ref_counted.h"
class DebuggerHost;
+class DevToolsHttpProtocolHandler;
class DevToolsProtocolHandler;
class DevToolsRemoteListenSocket;
class DebuggerWrapper : public base::RefCountedThreadSafe<DebuggerWrapper> {
public:
- explicit DebuggerWrapper(int port);
+ DebuggerWrapper(int port, bool useHttp);
private:
friend class base::RefCountedThreadSafe<DebuggerWrapper>;
@@ -28,6 +29,7 @@ class DebuggerWrapper : public base::RefCountedThreadSafe<DebuggerWrapper> {
virtual ~DebuggerWrapper();
scoped_refptr<DevToolsProtocolHandler> proto_handler_;
+ scoped_refptr<DevToolsHttpProtocolHandler> http_handler_;
};
#endif // CHROME_BROWSER_DEBUGGER_DEBUGGER_WRAPPER_H_
diff --git a/chrome/browser/debugger/devtools_http_protocol_handler.cc b/chrome/browser/debugger/devtools_http_protocol_handler.cc
new file mode 100644
index 0000000..8d8718c
--- /dev/null
+++ b/chrome/browser/debugger/devtools_http_protocol_handler.cc
@@ -0,0 +1,256 @@
+// Copyright (c) 2010 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 "chrome/browser/debugger/devtools_http_protocol_handler.h"
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/message_loop_proxy.h"
+#include "base/string_util.h"
+#include "base/thread.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/debugger/devtools_client_host.h"
+#include "chrome/browser/debugger/devtools_manager.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/devtools_messages.h"
+#include "chrome/common/net/url_request_context_getter.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/io_buffer.h"
+#include "net/base/listen_socket.h"
+#include "net/server/http_server_request_info.h"
+#include "net/url_request/url_request_context.h"
+
+const int kBufferSize = 16 * 1024;
+
+namespace {
+
+// An internal implementation of DevToolsClientHost that delegates
+// messages sent for DevToolsClient to a DebuggerShell instance.
+class DevToolsClientHostImpl : public DevToolsClientHost {
+ public:
+ explicit DevToolsClientHostImpl(HttpListenSocket* socket)
+ : socket_(socket) {}
+ ~DevToolsClientHostImpl() {}
+
+ // DevToolsClientHost interface
+ virtual void InspectedTabClosing() {}
+ virtual void SendMessageToClient(const IPC::Message& msg) {
+ IPC_BEGIN_MESSAGE_MAP(DevToolsClientHostImpl, msg)
+ IPC_MESSAGE_HANDLER(DevToolsClientMsg_RpcMessage, OnRpcMessage);
+ IPC_MESSAGE_UNHANDLED_ERROR()
+ IPC_END_MESSAGE_MAP()
+ }
+
+ private:
+ // Message handling routines
+ void OnRpcMessage(const DevToolsMessageData& data) {
+ std::string message;
+ message += "devtools$$dispatch(\"" + data.class_name + "\", \"" +
+ data.method_name + "\"";
+ for (std::vector<std::string>::const_iterator it = data.arguments.begin();
+ it != data.arguments.end(); ++it) {
+ std::string param = *it;
+ if (!param.empty())
+ message += ", " + param;
+ }
+ message += ")";
+ socket_->SendOverWebSocket(message);
+ }
+ HttpListenSocket* socket_;
+};
+
+}
+
+DevToolsHttpProtocolHandler::~DevToolsHttpProtocolHandler() {
+ // Stop() must be called prior to this being called
+ DCHECK(server_.get() == NULL);
+}
+
+void DevToolsHttpProtocolHandler::Start() {
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(this, &DevToolsHttpProtocolHandler::Init));
+}
+
+void DevToolsHttpProtocolHandler::Stop() {
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(this, &DevToolsHttpProtocolHandler::Teardown));
+}
+
+void DevToolsHttpProtocolHandler::OnHttpRequest(HttpListenSocket* socket,
+ HttpServerRequestInfo* info) {
+ URLRequest* request = new URLRequest(GURL("chrome:/" + info->path), this);
+ Bind(request, socket);
+ request->set_context(
+ Profile::GetDefaultRequestContext()->GetURLRequestContext());
+ request->Start();
+}
+
+void DevToolsHttpProtocolHandler::OnWebSocketRequest(
+ HttpListenSocket* socket,
+ HttpServerRequestInfo* request) {
+ socket->AcceptWebSocket(request);
+}
+
+void DevToolsHttpProtocolHandler::OnWebSocketMessage(HttpListenSocket* socket,
+ const std::string& data) {
+ ChromeThread::PostTask(
+ ChromeThread::UI,
+ FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &DevToolsHttpProtocolHandler::OnWebSocketMessageUI,
+ socket,
+ data));
+}
+
+void DevToolsHttpProtocolHandler::OnWebSocketMessageUI(
+ HttpListenSocket* socket,
+ const std::string& d) {
+ std::string data = d;
+ if (!client_host_.get() && data == "attach") {
+ client_host_.reset(new DevToolsClientHostImpl(socket));
+ BrowserList::const_iterator it = BrowserList::begin();
+ TabContents* tab_contents = (*it)->tabstrip_model()->GetTabContentsAt(0);
+ DevToolsManager* manager = DevToolsManager::GetInstance();
+ manager->RegisterDevToolsClientHostFor(tab_contents->render_view_host(),
+ client_host_.get());
+ } else {
+ // TODO(pfeldman): Replace with proper parsing / dispatching.
+ DevToolsMessageData message_data;
+ message_data.class_name = "ToolsAgent";
+ message_data.method_name = "dispatchOnInspectorController";
+
+ size_t pos = data.find(" ");
+ message_data.arguments.push_back(data.substr(0, pos));
+ data = data.substr(pos + 1);
+
+ pos = data.find(" ");
+ message_data.arguments.push_back(data.substr(0, pos));
+ data = data.substr(pos + 1);
+
+ message_data.arguments.push_back(data);
+
+ DevToolsManager* manager = DevToolsManager::GetInstance();
+ manager->ForwardToDevToolsAgent(client_host_.get(),
+ DevToolsAgentMsg_RpcMessage(DevToolsMessageData(message_data)));
+ }
+}
+
+void DevToolsHttpProtocolHandler::OnClose(HttpListenSocket* socket) {
+ SocketToRequestsMap::iterator it = socket_to_requests_.find(socket);
+ if (it == socket_to_requests_.end())
+ return;
+
+ for (std::set<URLRequest*>::iterator it2 = it->second.begin();
+ it2 != it->second.end(); ++it2) {
+ URLRequest* request = *it2;
+ request->Cancel();
+ request_to_socket_.erase(request);
+ request_to_buffer_.erase(request);
+ delete request;
+ }
+ socket_to_requests_.erase(socket);
+}
+
+void DevToolsHttpProtocolHandler::OnResponseStarted(URLRequest* request) {
+ RequestToSocketMap::iterator it = request_to_socket_.find(request);
+ if (it == request_to_socket_.end())
+ return;
+
+ HttpListenSocket* socket = it->second;
+
+ int64 expected_size = request->GetExpectedContentSize();
+
+ std::string content_type;
+ request->GetMimeType(&content_type);
+
+ if (request->status().is_success()) {
+ socket->Send(StringPrintf("HTTP/1.1 200 OK\r\n"
+ "Content-Type:%s\r\n"
+ "Content-Length:%lld\r\n"
+ "\r\n",
+ content_type.c_str(),
+ expected_size));
+ } else {
+ socket->Send("HTTP/1.1 404 Not Found\r\n"
+ "Content-Length: 0\r\n"
+ "\r\n");
+ }
+
+ int bytes_read = 0;
+ // Some servers may treat HEAD requests as GET requests. To free up the
+ // network connection as soon as possible, signal that the request has
+ // completed immediately, without trying to read any data back (all we care
+ // about is the response code and headers, which we already have).
+ net::IOBuffer* buffer = request_to_buffer_[request].get();
+ if (request->status().is_success())
+ request->Read(buffer, kBufferSize, &bytes_read);
+ OnReadCompleted(request, bytes_read);
+}
+
+void DevToolsHttpProtocolHandler::OnReadCompleted(URLRequest* request,
+ int bytes_read) {
+ RequestToSocketMap::iterator it = request_to_socket_.find(request);
+ if (it == request_to_socket_.end())
+ return;
+
+ HttpListenSocket* socket = it->second;
+
+ net::IOBuffer* buffer = request_to_buffer_[request].get();
+ do {
+ if (!request->status().is_success() || bytes_read <= 0)
+ break;
+ socket->Send(buffer->data(), bytes_read);
+ } while (request->Read(buffer, kBufferSize, &bytes_read));
+
+ // See comments re: HEAD requests in OnResponseStarted().
+ if (!request->status().is_io_pending())
+ RequestCompleted(request);
+}
+
+DevToolsHttpProtocolHandler::DevToolsHttpProtocolHandler(int port)
+ : port_(port),
+ server_(NULL) {
+}
+
+void DevToolsHttpProtocolHandler::Init() {
+ server_ = HttpListenSocket::Listen("127.0.0.1", port_, this);
+}
+
+// Run on I/O thread
+void DevToolsHttpProtocolHandler::Teardown() {
+ server_ = NULL;
+}
+
+void DevToolsHttpProtocolHandler::Bind(URLRequest* request,
+ HttpListenSocket* socket) {
+ request_to_socket_[request] = socket;
+ SocketToRequestsMap::iterator it = socket_to_requests_.find(socket);
+ if (it == socket_to_requests_.end()) {
+ std::pair<HttpListenSocket*, std::set<URLRequest*> > value(
+ socket,
+ std::set<URLRequest*>());
+ it = socket_to_requests_.insert(value).first;
+ }
+ it->second.insert(request);
+ request_to_buffer_[request] = new net::IOBuffer(kBufferSize);
+}
+
+void DevToolsHttpProtocolHandler::RequestCompleted(URLRequest* request) {
+ RequestToSocketMap::iterator it = request_to_socket_.find(request);
+ if (it == request_to_socket_.end())
+ return;
+
+ HttpListenSocket* socket = it->second;
+ request_to_socket_.erase(request);
+ SocketToRequestsMap::iterator it2 = socket_to_requests_.find(socket);
+ it2->second.erase(request);
+ request_to_buffer_.erase(request);
+ delete request;
+}
diff --git a/chrome/browser/debugger/devtools_http_protocol_handler.h b/chrome/browser/debugger/devtools_http_protocol_handler.h
new file mode 100644
index 0000000..14163d5
--- /dev/null
+++ b/chrome/browser/debugger/devtools_http_protocol_handler.h
@@ -0,0 +1,70 @@
+// Copyright (c) 2010 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 CHROME_BROWSER_DEBUGGER_DEVTOOLS_HTTP_PROTOCOL_HANDLER_H_
+#define CHROME_BROWSER_DEBUGGER_DEVTOOLS_HTTP_PROTOCOL_HANDLER_H_
+
+#include <set>
+#include <string>
+
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "net/server/http_listen_socket.h"
+#include "net/url_request/url_request.h"
+
+class DevToolsClientHost;
+class DevToolsHttpServer;
+
+class DevToolsHttpProtocolHandler
+ : public HttpListenSocket::Delegate,
+ public URLRequest::Delegate,
+ public base::RefCountedThreadSafe<DevToolsHttpProtocolHandler> {
+ public:
+ explicit DevToolsHttpProtocolHandler(int port);
+
+ // This method should be called after the object construction.
+ void Start();
+
+ // This method should be called before the object destruction.
+ void Stop();
+
+ // HttpListenSocket::Delegate implementation.
+ virtual void OnHttpRequest(HttpListenSocket* socket,
+ HttpServerRequestInfo* info);
+ virtual void OnWebSocketRequest(HttpListenSocket* socket,
+ HttpServerRequestInfo* info);
+ virtual void OnWebSocketMessage(HttpListenSocket* socket,
+ const std::string& data);
+ virtual void OnClose(HttpListenSocket* socket);
+
+ // URLRequest::Delegate implementation.
+ virtual void OnResponseStarted(URLRequest* request);
+ virtual void OnReadCompleted(URLRequest* request, int bytes_read);
+
+ private:
+ friend class base::RefCountedThreadSafe<DevToolsHttpProtocolHandler>;
+ virtual ~DevToolsHttpProtocolHandler();
+
+ void Init();
+ void Teardown();
+ void Bind(URLRequest* request, HttpListenSocket* socket);
+ void RequestCompleted(URLRequest* request);
+ void OnWebSocketMessageUI(HttpListenSocket* socket, const std::string& data);
+
+ int port_;
+ scoped_refptr<HttpListenSocket> server_;
+ typedef std::map<URLRequest*, HttpListenSocket*>
+ RequestToSocketMap;
+ RequestToSocketMap request_to_socket_;
+ typedef std::map<HttpListenSocket*, std::set<URLRequest*> >
+ SocketToRequestsMap;
+ SocketToRequestsMap socket_to_requests_;
+ typedef std::map<URLRequest*, scoped_refptr<net::IOBuffer> >
+ BuffersMap;
+ BuffersMap request_to_buffer_;
+ scoped_ptr<DevToolsClientHost> client_host_;
+ DISALLOW_COPY_AND_ASSIGN(DevToolsHttpProtocolHandler);
+};
+
+#endif // CHROME_BROWSER_DEBUGGER_DEVTOOLS_HTTP_PROTOCOL_HANDLER_H_