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 |