diff options
author | bulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-18 00:32:10 +0000 |
---|---|---|
committer | bulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-18 00:32:10 +0000 |
commit | a0a5a3a03e51c8d8cf6fa2e4bd1d55ba72a836cc (patch) | |
tree | 15a2aecb6b8191703e2ae50f58361367bf237c3e /content | |
parent | 36ed2103b130db30ad7fe5a50675ecb48d5c78de (diff) | |
download | chromium_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.cc | 118 | ||||
-rw-r--r-- | content/browser/debugger/devtools_browser_target.h | 68 | ||||
-rw-r--r-- | content/browser/debugger/devtools_http_handler_impl.cc | 36 | ||||
-rw-r--r-- | content/browser/debugger/devtools_http_handler_impl.h | 4 | ||||
-rw-r--r-- | content/browser/debugger/devtools_tracing_handler.cc | 103 | ||||
-rw-r--r-- | content/browser/debugger/devtools_tracing_handler.h | 50 | ||||
-rw-r--r-- | content/content_browser.gypi | 4 |
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", ¶ms); + + 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', |