summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorbulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-18 00:32:10 +0000
committerbulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-18 00:32:10 +0000
commita0a5a3a03e51c8d8cf6fa2e4bd1d55ba72a836cc (patch)
tree15a2aecb6b8191703e2ae50f58361367bf237c3e /content
parent36ed2103b130db30ad7fe5a50675ecb48d5c78de (diff)
downloadchromium_src-a0a5a3a03e51c8d8cf6fa2e4bd1d55ba72a836cc.zip
chromium_src-a0a5a3a03e51c8d8cf6fa2e4bd1d55ba72a836cc.tar.gz
chromium_src-a0a5a3a03e51c8d8cf6fa2e4bd1d55ba72a836cc.tar.bz2
Telemetry / Devtools TraceHandler: exposes tracing via dev tools.
- exposes start / stop / get request methods via devtools. This allows Telemetry to integrate trace collection across all platforms in a consistent way. BUG= TEST=./tools/telemetry/run_tests --browser=android-content-shell testGotTrace Review URL: https://chromiumcodereview.appspot.com/11548032 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@173595 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/debugger/devtools_browser_target.cc118
-rw-r--r--content/browser/debugger/devtools_browser_target.h68
-rw-r--r--content/browser/debugger/devtools_http_handler_impl.cc36
-rw-r--r--content/browser/debugger/devtools_http_handler_impl.h4
-rw-r--r--content/browser/debugger/devtools_tracing_handler.cc103
-rw-r--r--content/browser/debugger/devtools_tracing_handler.h50
-rw-r--r--content/content_browser.gypi4
7 files changed, 379 insertions, 4 deletions
diff --git a/content/browser/debugger/devtools_browser_target.cc b/content/browser/debugger/devtools_browser_target.cc
new file mode 100644
index 0000000..95d57a9
--- /dev/null
+++ b/content/browser/debugger/devtools_browser_target.cc
@@ -0,0 +1,118 @@
+// Copyright (c) 2012 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 "content/browser/debugger/devtools_browser_target.h"
+
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+
+
+namespace content {
+
+DevToolsBrowserTarget::DevToolsBrowserTarget(int connection_id)
+ : connection_id_(connection_id) {
+}
+
+DevToolsBrowserTarget::~DevToolsBrowserTarget() {
+ for (HandlersMap::iterator i = handlers_.begin(); i != handlers_.end(); ++i)
+ delete i->second;
+}
+
+void DevToolsBrowserTarget::RegisterHandler(Handler* handler) {
+ std::string domain = handler->Domain();
+ DCHECK(handlers_.find(domain) == handlers_.end());
+ handlers_[domain] = handler;
+}
+
+std::string DevToolsBrowserTarget::HandleMessage(const std::string& data) {
+ int error_code;
+ std::string error_message;
+ scoped_ptr<base::Value> command(
+ base::JSONReader::ReadAndReturnError(
+ data, 0, &error_code, &error_message));
+
+ if (!command || !command->IsType(base::Value::TYPE_DICTIONARY))
+ return SerializeErrorResponse(
+ -1, CreateErrorObject(error_code, error_message));
+
+ int request_id;
+ std::string domain;
+ std::string method;
+ base::DictionaryValue* command_dict = NULL;
+ bool ok = true;
+ ok &= command->GetAsDictionary(&command_dict);
+ ok &= command_dict->GetInteger("id", &request_id);
+ ok &= command_dict->GetString("method", &method);
+ if (!ok)
+ return SerializeErrorResponse(
+ request_id, CreateErrorObject(-1, "Malformed request"));
+
+ base::DictionaryValue* params = NULL;
+ command_dict->GetDictionary("params", &params);
+
+ size_t pos = method.find(".");
+ if (pos == std::string::npos)
+ return SerializeErrorResponse(
+ request_id, CreateErrorObject(-1, "Method unsupported"));
+
+ domain = method.substr(0, pos);
+ if (domain.empty() || handlers_.find(domain) == handlers_.end())
+ return SerializeErrorResponse(
+ request_id, CreateErrorObject(-1, "Domain unsupported"));
+
+ base::Value* error_object = NULL;
+ base::Value* domain_result = handlers_[domain]->OnProtocolCommand(
+ method, params, &error_object);
+
+ if (error_object)
+ return SerializeErrorResponse(request_id, error_object);
+
+ if (!domain_result)
+ return SerializeErrorResponse(
+ request_id, CreateErrorObject(-1, "Invalid call"));
+
+ DictionaryValue* response = new DictionaryValue();
+ response->Set("result", domain_result);
+ return SerializeResponse(request_id, response);
+}
+
+std::string DevToolsBrowserTarget::SerializeErrorResponse(
+ int request_id, base::Value* error_object) {
+ scoped_ptr<base::DictionaryValue> error_response(new base::DictionaryValue());
+ error_response->SetInteger("id", request_id);
+ error_response->Set("error", error_object);
+ // Serialize response.
+ std::string json_response;
+ base::JSONWriter::WriteWithOptions(error_response.get(),
+ base::JSONWriter::OPTIONS_PRETTY_PRINT,
+ &json_response);
+ return json_response;
+}
+
+base::Value* DevToolsBrowserTarget::CreateErrorObject(
+ int error_code, const std::string& message) {
+ base::DictionaryValue* error_object = new base::DictionaryValue();
+ error_object->SetInteger("code", error_code);
+ error_object->SetString("message", message);
+ return error_object;
+}
+
+std::string DevToolsBrowserTarget::SerializeResponse(
+ int request_id, base::Value* response) {
+ scoped_ptr<base::DictionaryValue> ret(new base::DictionaryValue());
+ ret->SetInteger("id", request_id);
+ ret->Set("response", response);
+
+ // Serialize response.
+ std::string json_response;
+ base::JSONWriter::WriteWithOptions(ret.get(),
+ base::JSONWriter::OPTIONS_PRETTY_PRINT,
+ &json_response);
+ return json_response;
+}
+
+} // namespace content
diff --git a/content/browser/debugger/devtools_browser_target.h b/content/browser/debugger/devtools_browser_target.h
new file mode 100644
index 0000000..14e141f
--- /dev/null
+++ b/content/browser/debugger/devtools_browser_target.h
@@ -0,0 +1,68 @@
+// Copyright (c) 2012 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 CONTENT_BROWSER_DEBUGGER_DEVTOOLS_BROWSER_TARGET_H_
+#define CONTENT_BROWSER_DEBUGGER_DEVTOOLS_BROWSER_TARGET_H_
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+
+namespace base {
+
+class DictionaryValue;
+class Value;
+
+} // namespace base
+
+namespace content {
+
+// This class handles the "Browser" target for remote debugging.
+class DevToolsBrowserTarget {
+ public:
+ class Handler {
+ public:
+ virtual ~Handler() {}
+
+ // Returns the domain name for this handler.
+ virtual std::string Domain() = 0;
+
+ // |return_value| and |error_message_out| ownership is transferred to the
+ // caller.
+ virtual base::Value* OnProtocolCommand(
+ const std::string& method,
+ const base::DictionaryValue* params,
+ base::Value** error_message_out) = 0;
+ };
+
+ explicit DevToolsBrowserTarget(int connection_id);
+ ~DevToolsBrowserTarget();
+
+ int connection_id() const { return connection_id_; }
+
+ // Takes ownership of |handler|.
+ void RegisterHandler(Handler* handler);
+
+ std::string HandleMessage(const std::string& data);
+
+ private:
+ const int connection_id_;
+
+ typedef std::map<std::string, Handler*> HandlersMap;
+ HandlersMap handlers_;
+
+ // Takes ownership of |error_object|.
+ std::string SerializeErrorResponse(int request_id, base::Value* error_object);
+
+ base::Value* CreateErrorObject(int error_code, const std::string& message);
+
+ std::string SerializeResponse(int request_id, base::Value* response);
+
+ DISALLOW_COPY_AND_ASSIGN(DevToolsBrowserTarget);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEBUGGER_DEVTOOLS_BROWSER_TARGET_H_
diff --git a/content/browser/debugger/devtools_http_handler_impl.cc b/content/browser/debugger/devtools_http_handler_impl.cc
index a9feb7e..a62d4bd 100644
--- a/content/browser/debugger/devtools_http_handler_impl.cc
+++ b/content/browser/debugger/devtools_http_handler_impl.cc
@@ -19,6 +19,8 @@
#include "base/threading/thread.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
+#include "content/browser/debugger/devtools_browser_target.h"
+#include "content/browser/debugger/devtools_tracing_handler.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/devtools_messages.h"
#include "content/public/browser/browser_thread.h"
@@ -597,15 +599,27 @@ void DevToolsHttpHandlerImpl::OnWebSocketRequestUI(
const net::HttpServerRequestInfo& request) {
if (!thread_.get())
return;
+ std::string browser_prefix = "/devtools/browser";
+ size_t browser_pos = request.path.find(browser_prefix);
+ if (browser_pos == 0) {
+ if (browser_target_) {
+ Send500(connection_id, "Another client already attached");
+ return;
+ }
+ browser_target_.reset(new DevToolsBrowserTarget(connection_id));
+ browser_target_->RegisterHandler(new DevToolsTracingHandler());
+ AcceptWebSocket(connection_id, request);
+ return;
+ }
- std::string prefix = "/devtools/page/";
- size_t pos = request.path.find(prefix);
+ std::string page_prefix = "/devtools/page/";
+ size_t pos = request.path.find(page_prefix);
if (pos != 0) {
Send404(connection_id);
return;
}
- std::string page_id = request.path.substr(prefix.length());
+ std::string page_id = request.path.substr(page_prefix.length());
RenderViewHost* rvh = binding_->ForIdentifier(page_id);
if (!rvh) {
Send500(connection_id, "No such target id: " + page_id);
@@ -635,6 +649,18 @@ void DevToolsHttpHandlerImpl::OnWebSocketRequestUI(
void DevToolsHttpHandlerImpl::OnWebSocketMessageUI(
int connection_id,
const std::string& data) {
+ if (browser_target_ && connection_id == browser_target_->connection_id()) {
+ std::string json_response = browser_target_->HandleMessage(data);
+
+ thread_->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&net::HttpServer::SendOverWebSocket,
+ server_.get(),
+ connection_id,
+ json_response));
+ return;
+ }
+
ConnectionToClientHostMap::iterator it =
connection_to_client_host_ui_.find(connection_id);
if (it == connection_to_client_host_ui_.end())
@@ -654,6 +680,10 @@ void DevToolsHttpHandlerImpl::OnCloseUI(int connection_id) {
delete client_host;
connection_to_client_host_ui_.erase(connection_id);
}
+ if (browser_target_ && browser_target_->connection_id() == connection_id) {
+ browser_target_.reset();
+ return;
+ }
}
DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl(
diff --git a/content/browser/debugger/devtools_http_handler_impl.h b/content/browser/debugger/devtools_http_handler_impl.h
index c912b92..ef36be8 100644
--- a/content/browser/debugger/devtools_http_handler_impl.h
+++ b/content/browser/debugger/devtools_http_handler_impl.h
@@ -32,6 +32,7 @@ class URLRequestContextGetter;
namespace content {
+class DevToolsBrowserTarget;
class DevToolsClientHost;
class RenderViewHost;
@@ -79,7 +80,7 @@ class DevToolsHttpHandlerImpl
void OnJsonRequestUI(int connection_id,
const net::HttpServerRequestInfo& info);
void OnThumbnailRequestUI(int connection_id,
- const net::HttpServerRequestInfo& info);
+ const net::HttpServerRequestInfo& info);
void OnDiscoveryPageRequestUI(int connection_id);
void OnWebSocketRequestUI(int connection_id,
@@ -133,6 +134,7 @@ class DevToolsHttpHandlerImpl
RenderViewHostBinding* binding_;
scoped_ptr<RenderViewHostBinding> default_binding_;
NotificationRegistrar registrar_;
+ scoped_ptr<DevToolsBrowserTarget> browser_target_;
DISALLOW_COPY_AND_ASSIGN(DevToolsHttpHandlerImpl);
};
diff --git a/content/browser/debugger/devtools_tracing_handler.cc b/content/browser/debugger/devtools_tracing_handler.cc
new file mode 100644
index 0000000..f1eb740
--- /dev/null
+++ b/content/browser/debugger/devtools_tracing_handler.cc
@@ -0,0 +1,103 @@
+// Copyright (c) 2012 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 "content/browser/debugger/devtools_tracing_handler.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/values.h"
+#include "content/browser/debugger/devtools_http_handler_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/trace_controller.h"
+#include "content/public/browser/trace_subscriber.h"
+
+namespace content {
+
+DevToolsTracingHandler::DevToolsTracingHandler()
+ : has_completed_(false),
+ buffer_data_size_(0) {
+}
+
+DevToolsTracingHandler::~DevToolsTracingHandler() {
+}
+
+std::string DevToolsTracingHandler::Domain() {
+ return "Tracing";
+}
+
+void DevToolsTracingHandler::OnEndTracingComplete() {
+ has_completed_ = true;
+}
+
+void DevToolsTracingHandler::OnTraceDataCollected(
+ const scoped_refptr<base::RefCountedString>& trace_fragment) {
+ buffer_.push_back(trace_fragment->data());
+ buffer_data_size_ += trace_fragment->data().size();
+}
+
+base::Value* DevToolsTracingHandler::OnProtocolCommand(
+ const std::string& method,
+ const base::DictionaryValue* params,
+ base::Value** error_out) {
+ if (method == "Tracing.start")
+ return Start(params);
+ else if (method == "Tracing.end")
+ return End(params);
+ else if (method == "Tracing.hasCompleted")
+ return HasCompleted(params);
+ else if (method == "Tracing.getTraceAndReset")
+ return GetTraceAndReset(params);
+
+ base::DictionaryValue* error_object = new base::DictionaryValue();
+ error_object->SetInteger("code", -1);
+ error_object->SetString("message", "Invalid method");
+
+ *error_out = error_object;
+
+ return NULL;
+}
+
+base::Value* DevToolsTracingHandler::Start(
+ const base::DictionaryValue* params) {
+ std::string categories;
+ if (params && params->HasKey("categories"))
+ params->GetString("categories", &categories);
+ TraceController::GetInstance()->BeginTracing(this, categories);
+
+ return base::Value::CreateBooleanValue(true);
+}
+
+base::Value* DevToolsTracingHandler::End(
+ const base::DictionaryValue* /* params */) {
+ TraceController::GetInstance()->EndTracingAsync(this);
+
+ return base::Value::CreateBooleanValue(true);
+}
+
+
+base::Value* DevToolsTracingHandler::HasCompleted(
+ const base::DictionaryValue* /* params */) {
+
+ return base::Value::CreateBooleanValue(has_completed_);
+}
+
+base::Value* DevToolsTracingHandler::GetTraceAndReset(
+ const base::DictionaryValue* /* params */) {
+ std::string ret;
+ ret.reserve(buffer_data_size_);
+ for (std::vector<std::string>::const_iterator i = buffer_.begin();
+ i != buffer_.end(); ++i) {
+ if (!ret.empty())
+ ret.append(",");
+ ret.append(*i);
+ }
+ buffer_.clear();
+ has_completed_ = false;
+ buffer_data_size_ = 0;
+
+ return base::Value::CreateStringValue(ret);
+}
+
+} // namespace content
diff --git a/content/browser/debugger/devtools_tracing_handler.h b/content/browser/debugger/devtools_tracing_handler.h
new file mode 100644
index 0000000..a5858fc
--- /dev/null
+++ b/content/browser/debugger/devtools_tracing_handler.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2012 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 CONTENT_BROWSER_DEBUGGER_DEVTOOLS_TRACING_HANDLER_H_
+#define CONTENT_BROWSER_DEBUGGER_DEVTOOLS_TRACING_HANDLER_H_
+
+#include "content/browser/debugger/devtools_browser_target.h"
+#include "content/public/browser/trace_subscriber.h"
+
+namespace content {
+
+// This class bridges DevTools remote debugging server with the trace
+// infrastructure.
+class DevToolsTracingHandler
+ : public TraceSubscriber,
+ public DevToolsBrowserTarget::Handler {
+ public:
+ DevToolsTracingHandler();
+ virtual ~DevToolsTracingHandler();
+
+ // TraceSubscriber:
+ virtual void OnEndTracingComplete() OVERRIDE;;
+ virtual void OnTraceDataCollected(
+ const scoped_refptr<base::RefCountedString>& trace_fragment) OVERRIDE;
+
+ // DevToolBrowserTarget::Handler:
+ virtual std::string Domain() OVERRIDE;
+ virtual base::Value* OnProtocolCommand(
+ const std::string& method,
+ const base::DictionaryValue* params,
+ base::Value** error_out) OVERRIDE;
+
+ private:
+ base::Value* Start(const base::DictionaryValue* params);
+ base::Value* End(const base::DictionaryValue* params);
+ base::Value* HasCompleted(const base::DictionaryValue* params);
+ base::Value* GetTraceAndReset(const base::DictionaryValue* params);
+
+ bool has_completed_;
+
+ std::vector<std::string> buffer_;
+ int buffer_data_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(DevToolsTracingHandler);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEBUGGER_DEVTOOLS_TRACING_HANDLER_H_
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 03c9331..3fdb8fd 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -287,6 +287,8 @@
'browser/cross_site_request_manager.h',
'browser/debugger/devtools_agent_host.cc',
'browser/debugger/devtools_agent_host.h',
+ 'browser/debugger/devtools_browser_target.cc',
+ 'browser/debugger/devtools_browser_target.h',
'browser/debugger/devtools_frontend_host.cc',
'browser/debugger/devtools_frontend_host.h',
'browser/debugger/devtools_http_handler_impl.cc',
@@ -295,6 +297,8 @@
'browser/debugger/devtools_manager_impl.h',
'browser/debugger/devtools_netlog_observer.cc',
'browser/debugger/devtools_netlog_observer.h',
+ 'browser/debugger/devtools_tracing_handler.h',
+ 'browser/debugger/devtools_tracing_handler.cc',
'browser/debugger/render_view_devtools_agent_host.cc',
'browser/debugger/render_view_devtools_agent_host.h',
'browser/debugger/worker_devtools_manager.cc',