Chromium Code Reviews| Index: content/browser/devtools/protocol/tracing_handler.cc |
| diff --git a/content/browser/devtools/protocol/tracing_handler.cc b/content/browser/devtools/protocol/tracing_handler.cc |
| index d85695731cd3410809e28c56421b338f7b71dd0d..81fbfb071ef6054f43caa15993098168abab2f9b 100644 |
| --- a/content/browser/devtools/protocol/tracing_handler.cc |
| +++ b/content/browser/devtools/protocol/tracing_handler.cc |
| @@ -8,6 +8,7 @@ |
| #include "base/bind.h" |
| #include "base/format_macros.h" |
| +#include "base/json/json_writer.h" |
| #include "base/memory/ref_counted_memory.h" |
| #include "base/strings/string_split.h" |
| #include "base/strings/stringprintf.h" |
| @@ -30,6 +31,46 @@ namespace { |
| const double kMinimumReportingInterval = 250.0; |
| +const char kRecordModeParam[] = "record_mode"; |
| + |
| +// Convert from camel case to separator + lowercase. |
| +std::string ConvertFromCamelCase(const std::string& in_str, char separator) { |
| + std::string out_str; |
| + for (const char& c : in_str) { |
|
Primiano Tucci (use gerrit)
2016/03/14 16:53:02
maybe if you add a out_str.reserve(in_str.size())
Zhen Wang
2016/03/14 21:41:45
Done.
|
| + if (isupper(c)) { |
| + out_str.push_back(separator); |
| + out_str.push_back(tolower(c)); |
| + } else { |
| + out_str.push_back(c); |
| + } |
| + } |
| + return out_str; |
| +} |
| + |
| +scoped_ptr<base::Value> ConvertDictKeyStyle(const base::Value& value) { |
| + const base::DictionaryValue* dict = nullptr; |
| + if (value.GetAsDictionary(&dict)) { |
| + scoped_ptr<base::DictionaryValue> out_dict(new base::DictionaryValue()); |
| + for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); |
| + it.Advance()) { |
| + out_dict->Set(ConvertFromCamelCase(it.key(), '_'), |
| + ConvertDictKeyStyle(it.value())); |
| + } |
| + return std::move(out_dict); |
| + } |
| + |
| + const base::ListValue* list = nullptr; |
| + if (value.GetAsList(&list)) { |
| + scoped_ptr<base::ListValue> out_list(new base::ListValue()); |
| + for (const auto& value : *list) { |
|
petrcermak
2016/03/14 18:05:09
nit: No need for braces
Zhen Wang
2016/03/14 21:41:45
Done.
|
| + out_list->Append(ConvertDictKeyStyle(*value)); |
| + } |
| + return std::move(out_list); |
| + } |
| + |
| + return value.CreateDeepCopy(); |
| +} |
| + |
| class DevToolsTraceSinkProxy : public TracingController::TraceDataSink { |
| public: |
| explicit DevToolsTraceSinkProxy(base::WeakPtr<TracingHandler> handler) |
| @@ -130,23 +171,37 @@ void TracingHandler::OnTraceToStreamComplete(const std::string& stream_handle) { |
| TracingCompleteParams::Create()->set_stream(stream_handle)); |
| } |
| -Response TracingHandler::Start(DevToolsCommandId command_id, |
| - const std::string* categories, |
| - const std::string* options, |
| - const double* buffer_usage_reporting_interval, |
| - const std::string* transfer_mode) { |
| +Response TracingHandler::Start( |
| + DevToolsCommandId command_id, |
| + const std::string* categories, |
| + const std::string* options, |
| + const double* buffer_usage_reporting_interval, |
| + const std::string* transfer_mode, |
| + const scoped_ptr<base::DictionaryValue>& config) { |
| if (IsTracing()) |
| return Response::InternalError("Tracing is already started"); |
| + if (config && (categories || options)) { |
| + return Response::InternalError( |
| + "Either trace config (preferred) or categories/options should be " |
|
petrcermak
2016/03/14 18:05:09
nit: I'd say "categories+options" instead of "cate
petrcermak
2016/03/14 18:05:09
nit: Since this is an exclusive "or", there should
Zhen Wang
2016/03/14 21:41:45
done
|
| + "specified, but not both."); |
| + } |
| + |
| did_initiate_recording_ = true; |
| return_as_stream_ = |
| transfer_mode && *transfer_mode == start::kTransferModeReturnAsStream; |
| - base::trace_event::TraceConfig trace_config( |
| - categories ? *categories : std::string(), |
| - options ? *options : std::string()); |
| if (buffer_usage_reporting_interval) |
| SetupTimer(*buffer_usage_reporting_interval); |
| + base::trace_event::TraceConfig trace_config; |
| + if (config) { |
| + trace_config = GetTraceConfigFromDevtoolsConfig(*config); |
| + } else if (categories || options) { |
| + trace_config = base::trace_event::TraceConfig( |
| + categories ? *categories : std::string(), |
| + options ? *options : std::string()); |
| + } |
| + |
| // If inspected target is a render process Tracing.start will be handled by |
| // tracing agent in the renderer. |
| TracingController::GetInstance()->StartTracing( |
| @@ -281,6 +336,21 @@ bool TracingHandler::IsStartupTracingActive() { |
| TracingController::GetInstance()->IsTracing(); |
| } |
| +// static |
| +base::trace_event::TraceConfig TracingHandler::GetTraceConfigFromDevtoolsConfig( |
| + const base::DictionaryValue& devtools_config) { |
| + scoped_ptr<base::Value> value = ConvertDictKeyStyle(devtools_config); |
| + DCHECK(value && value->IsType(base::Value::TYPE_DICTIONARY)); |
| + scoped_ptr<base::DictionaryValue> tracing_dict( |
| + static_cast<base::DictionaryValue*>(value.release())); |
| + |
| + std::string mode; |
| + if (tracing_dict->GetString(kRecordModeParam, &mode)) |
| + tracing_dict->SetString(kRecordModeParam, ConvertFromCamelCase(mode, '-')); |
| + |
| + return base::trace_event::TraceConfig(*tracing_dict); |
| +} |
| + |
| } // namespace tracing |
| } // namespace devtools |
| } // namespace content |