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/file_util.h"
9 #include "base/location.h"
10 #include "base/memory/ref_counted_memory.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "base/prefs/pref_service.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/feedback/feedback_util.h"
15 #include "chrome/common/pref_names.h"
16 #include "content/public/browser/tracing_controller.h"
19 // Only once trace manager can exist at a time.
20 TracingManager
* g_tracing_manager
= NULL
;
21 // Trace IDs start at 1 and increase.
22 int g_next_trace_id
= 1;
23 // Name of the file to store the tracing data as.
24 const base::FilePath::CharType kTracingFilename
[] =
25 FILE_PATH_LITERAL("tracing.json");
28 TracingManager::TracingManager()
29 : current_trace_id_(0),
30 weak_ptr_factory_(this) {
31 DCHECK(!g_tracing_manager
);
32 g_tracing_manager
= this;
36 TracingManager::~TracingManager() {
37 DCHECK(g_tracing_manager
== this);
38 g_tracing_manager
= NULL
;
41 int TracingManager::RequestTrace() {
42 // Return the current trace if one is being collected.
43 if (current_trace_id_
)
44 return current_trace_id_
;
46 current_trace_id_
= g_next_trace_id
;
48 content::TracingController::GetInstance()->DisableRecording(
50 base::Bind(&TracingManager::OnTraceDataCollected
,
51 weak_ptr_factory_
.GetWeakPtr()));
52 return current_trace_id_
;
55 bool TracingManager::GetTraceData(int id
, const TraceDataCallback
& callback
) {
56 // If a trace is being collected currently, send it via callback when
58 if (current_trace_id_
) {
59 // Only allow one trace data request at a time.
60 if (trace_callback_
.is_null()) {
61 trace_callback_
= callback
;
67 std::map
<int, scoped_refptr
<base::RefCountedString
> >::iterator data
=
69 if (data
== trace_data_
.end())
72 // Always return the data asychronously, so the behavior is consistant.
73 base::MessageLoopProxy::current()->PostTask(
75 base::Bind(callback
, data
->second
));
80 void TracingManager::DiscardTraceData(int id
) {
81 trace_data_
.erase(id
);
83 // If the trace is discarded before it is complete, clean up the accumulators.
84 if (id
== current_trace_id_
) {
85 current_trace_id_
= 0;
87 // If the trace has already been requested, provide an empty string.
88 if (!trace_callback_
.is_null()) {
89 trace_callback_
.Run(scoped_refptr
<base::RefCountedString
>());
90 trace_callback_
.Reset();
95 void TracingManager::StartTracing() {
96 content::TracingController::GetInstance()->EnableRecording(
97 "", content::TracingController::DEFAULT_OPTIONS
,
98 content::TracingController::EnableRecordingDoneCallback());
101 void TracingManager::OnTraceDataCollected(const base::FilePath
& path
) {
102 if (!current_trace_id_
)
106 if (!base::ReadFileToString(path
, &data
)) {
107 LOG(ERROR
) << "Failed to read trace data from: " << path
.value();
110 base::DeleteFile(path
, false);
112 std::string output_val
;
113 feedback_util::ZipString(
114 base::FilePath(kTracingFilename
), data
, &output_val
);
116 scoped_refptr
<base::RefCountedString
> output(
117 base::RefCountedString::TakeString(&output_val
));
119 trace_data_
[current_trace_id_
] = output
;
121 if (!trace_callback_
.is_null()) {
122 trace_callback_
.Run(output
);
123 trace_callback_
.Reset();
126 current_trace_id_
= 0;
128 // Tracing has to be restarted asynchronous, so the TracingController can
130 base::MessageLoopProxy::current()->PostTask(
132 base::Bind(&TracingManager::StartTracing
,
133 weak_ptr_factory_
.GetWeakPtr()));
137 scoped_ptr
<TracingManager
> TracingManager::Create() {
138 if (g_tracing_manager
)
139 return scoped_ptr
<TracingManager
>();
140 return scoped_ptr
<TracingManager
>(new TracingManager());
143 TracingManager
* TracingManager::Get() {
144 return g_tracing_manager
;