1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/feedback/tracing_manager.h"
8 #include "base/prefs/pref_service.h"
9 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/feedback/feedback_util.h"
11 #include "chrome/common/pref_names.h"
12 #include "content/public/browser/trace_controller.h"
15 // Only once trace manager can exist at a time.
16 TracingManager* g_tracing_manager = NULL;
17 // Trace IDs start at 1 and increase.
18 int g_next_trace_id = 1;
19 // Name of the file to store the tracing data as.
20 const base::FilePath::CharType kTracingFilename[] =
21 FILE_PATH_LITERAL("tracing.json");
24 TracingManager::TracingManager()
25 : current_trace_id_(0),
26 weak_ptr_factory_(this) {
27 DCHECK(!g_tracing_manager);
28 g_tracing_manager = this;
32 TracingManager::~TracingManager() {
33 DCHECK(g_tracing_manager == this);
34 g_tracing_manager = NULL;
37 int TracingManager::RequestTrace() {
38 // Return the current trace if one is being collected.
39 if (current_trace_id_)
40 return current_trace_id_;
42 current_trace_id_ = g_next_trace_id;
44 content::TraceController::GetInstance()->EndTracingAsync(this);
45 return current_trace_id_;
48 bool TracingManager::GetTraceData(int id, const TraceDataCallback& callback) {
49 // If a trace is being collected currently, send it via callback when
51 if (current_trace_id_) {
52 // Only allow one trace data request at a time.
53 if (trace_callback_.is_null()) {
54 trace_callback_ = callback;
60 std::map<int, scoped_refptr<base::RefCountedString> >::iterator data =
62 if (data == trace_data_.end())
65 // Always return the data asychronously, so the behavior is consistant.
66 base::MessageLoopProxy::current()->PostTask(
68 base::Bind(callback, data->second));
73 void TracingManager::DiscardTraceData(int id) {
74 trace_data_.erase(id);
76 // If the trace is discarded before it is complete, clean up the accumulators.
77 if (id == current_trace_id_) {
78 current_trace_id_ = 0;
81 // If the trace has already been requested, provide an empty string.
82 if (!trace_callback_.is_null()) {
83 trace_callback_.Run(scoped_refptr<base::RefCountedString>());
84 trace_callback_.Reset();
89 void TracingManager::StartTracing() {
90 content::TraceController::GetInstance()->BeginTracing(
92 base::debug::TraceLog::RECORD_CONTINUOUSLY);
95 void TracingManager::OnEndTracingComplete() {
96 if (!current_trace_id_)
99 data_ = std::string("[") + data_ + "]";
101 std::string output_val;
102 feedback_util::ZipString(
103 base::FilePath(kTracingFilename), data_, &output_val);
105 scoped_refptr<base::RefCountedString> output(
106 base::RefCountedString::TakeString(&output_val));
108 trace_data_[current_trace_id_] = output;
110 if (!trace_callback_.is_null()) {
111 trace_callback_.Run(output);
112 trace_callback_.Reset();
115 current_trace_id_ = 0;
118 // Tracing has to be restarted asynchronous, so the TracingController can
120 base::MessageLoopProxy::current()->PostTask(
122 base::Bind(&TracingManager::StartTracing,
123 weak_ptr_factory_.GetWeakPtr()));
126 void TracingManager::OnTraceDataCollected(
127 const scoped_refptr<base::RefCountedString>& trace_fragment) {
128 if (current_trace_id_) {
131 data_ += trace_fragment->data();
136 scoped_ptr<TracingManager> TracingManager::Create() {
137 if (g_tracing_manager)
138 return scoped_ptr<TracingManager>();
139 return scoped_ptr<TracingManager>(new TracingManager());
142 TracingManager* TracingManager::Get() {
143 return g_tracing_manager;