OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/feedback/tracing_manager.h" | 5 #include "chrome/browser/feedback/tracing_manager.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.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" |
8 #include "base/prefs/pref_service.h" | 12 #include "base/prefs/pref_service.h" |
9 #include "chrome/browser/browser_process.h" | 13 #include "chrome/browser/browser_process.h" |
10 #include "chrome/browser/feedback/feedback_util.h" | 14 #include "chrome/browser/feedback/feedback_util.h" |
11 #include "chrome/common/pref_names.h" | 15 #include "chrome/common/pref_names.h" |
12 #include "content/public/browser/trace_controller.h" | 16 #include "content/public/browser/tracing_controller.h" |
13 | 17 |
14 namespace { | 18 namespace { |
15 // Only once trace manager can exist at a time. | 19 // Only once trace manager can exist at a time. |
16 TracingManager* g_tracing_manager = NULL; | 20 TracingManager* g_tracing_manager = NULL; |
17 // Trace IDs start at 1 and increase. | 21 // Trace IDs start at 1 and increase. |
18 int g_next_trace_id = 1; | 22 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"); | |
22 } | 23 } |
23 | 24 |
24 TracingManager::TracingManager() | 25 TracingManager::TracingManager() |
25 : current_trace_id_(0), | 26 : current_trace_id_(0), |
26 weak_ptr_factory_(this) { | 27 weak_ptr_factory_(this) { |
27 DCHECK(!g_tracing_manager); | 28 DCHECK(!g_tracing_manager); |
28 g_tracing_manager = this; | 29 g_tracing_manager = this; |
29 StartTracing(); | 30 StartTracing(); |
30 } | 31 } |
31 | 32 |
32 TracingManager::~TracingManager() { | 33 TracingManager::~TracingManager() { |
33 DCHECK(g_tracing_manager == this); | 34 DCHECK(g_tracing_manager == this); |
34 g_tracing_manager = NULL; | 35 g_tracing_manager = NULL; |
35 } | 36 } |
36 | 37 |
37 int TracingManager::RequestTrace() { | 38 int TracingManager::RequestTrace() { |
38 // Return the current trace if one is being collected. | 39 // Return the current trace if one is being collected. |
39 if (current_trace_id_) | 40 if (current_trace_id_) |
40 return current_trace_id_; | 41 return current_trace_id_; |
41 | 42 |
42 current_trace_id_ = g_next_trace_id; | 43 current_trace_id_ = g_next_trace_id; |
43 ++g_next_trace_id; | 44 ++g_next_trace_id; |
44 content::TraceController::GetInstance()->EndTracingAsync(this); | 45 content::TracingController::GetInstance()->DisableRecording( |
| 46 base::FilePath(), |
| 47 base::Bind(&TracingManager::OnTraceDataCollected, |
| 48 weak_ptr_factory_.GetWeakPtr())); |
45 return current_trace_id_; | 49 return current_trace_id_; |
46 } | 50 } |
47 | 51 |
48 bool TracingManager::GetTraceData(int id, const TraceDataCallback& callback) { | 52 bool TracingManager::GetTraceData(int id, const TraceDataCallback& callback) { |
49 // If a trace is being collected currently, send it via callback when | 53 // If a trace is being collected currently, send it via callback when |
50 // complete. | 54 // complete. |
51 if (current_trace_id_) { | 55 if (current_trace_id_) { |
52 // Only allow one trace data request at a time. | 56 // Only allow one trace data request at a time. |
53 if (trace_callback_.is_null()) { | 57 if (trace_callback_.is_null()) { |
54 trace_callback_ = callback; | 58 trace_callback_ = callback; |
(...skipping 14 matching lines...) Expand all Loading... |
69 return true; | 73 return true; |
70 } | 74 } |
71 } | 75 } |
72 | 76 |
73 void TracingManager::DiscardTraceData(int id) { | 77 void TracingManager::DiscardTraceData(int id) { |
74 trace_data_.erase(id); | 78 trace_data_.erase(id); |
75 | 79 |
76 // If the trace is discarded before it is complete, clean up the accumulators. | 80 // If the trace is discarded before it is complete, clean up the accumulators. |
77 if (id == current_trace_id_) { | 81 if (id == current_trace_id_) { |
78 current_trace_id_ = 0; | 82 current_trace_id_ = 0; |
79 data_ = ""; | |
80 | 83 |
81 // If the trace has already been requested, provide an empty string. | 84 // If the trace has already been requested, provide an empty string. |
82 if (!trace_callback_.is_null()) { | 85 if (!trace_callback_.is_null()) { |
83 trace_callback_.Run(scoped_refptr<base::RefCountedString>()); | 86 trace_callback_.Run(scoped_refptr<base::RefCountedString>()); |
84 trace_callback_.Reset(); | 87 trace_callback_.Reset(); |
85 } | 88 } |
86 } | 89 } |
87 } | 90 } |
88 | 91 |
89 void TracingManager::StartTracing() { | 92 void TracingManager::StartTracing() { |
90 content::TraceController::GetInstance()->BeginTracing( | 93 content::TracingController::GetInstance()->EnableRecording( |
91 this, "-test_*", | 94 "", content::TracingController::DEFAULT_OPTIONS, |
92 base::debug::TraceLog::RECORD_CONTINUOUSLY); | 95 content::TracingController::EnableRecordingDoneCallback()); |
93 } | 96 } |
94 | 97 |
95 void TracingManager::OnEndTracingComplete() { | 98 void TracingManager::OnTraceDataCollected(const base::FilePath& path) { |
96 if (!current_trace_id_) | 99 if (!current_trace_id_) |
97 return; | 100 return; |
98 | 101 |
99 data_ = std::string("[") + data_ + "]"; | |
100 | |
101 std::string output_val; | 102 std::string output_val; |
102 feedback_util::ZipString( | 103 feedback_util::ZipFile(path, &output_val); |
103 base::FilePath(kTracingFilename), data_, &output_val); | 104 base::DeleteFile(path, false); |
104 | 105 |
105 scoped_refptr<base::RefCountedString> output( | 106 scoped_refptr<base::RefCountedString> output( |
106 base::RefCountedString::TakeString(&output_val)); | 107 base::RefCountedString::TakeString(&output_val)); |
107 | 108 |
108 trace_data_[current_trace_id_] = output; | 109 trace_data_[current_trace_id_] = output; |
109 | 110 |
110 if (!trace_callback_.is_null()) { | 111 if (!trace_callback_.is_null()) { |
111 trace_callback_.Run(output); | 112 trace_callback_.Run(output); |
112 trace_callback_.Reset(); | 113 trace_callback_.Reset(); |
113 } | 114 } |
114 | 115 |
115 current_trace_id_ = 0; | 116 current_trace_id_ = 0; |
116 data_ = ""; | |
117 | 117 |
118 // Tracing has to be restarted asynchronous, so the TracingController can | 118 // Tracing has to be restarted asynchronous, so the TracingController can |
119 // clean up. | 119 // clean up. |
120 base::MessageLoopProxy::current()->PostTask( | 120 base::MessageLoopProxy::current()->PostTask( |
121 FROM_HERE, | 121 FROM_HERE, |
122 base::Bind(&TracingManager::StartTracing, | 122 base::Bind(&TracingManager::StartTracing, |
123 weak_ptr_factory_.GetWeakPtr())); | 123 weak_ptr_factory_.GetWeakPtr())); |
124 } | 124 } |
125 | 125 |
126 void TracingManager::OnTraceDataCollected( | |
127 const scoped_refptr<base::RefCountedString>& trace_fragment) { | |
128 if (current_trace_id_) { | |
129 if (!data_.empty()) | |
130 data_ += ","; | |
131 data_ += trace_fragment->data(); | |
132 } | |
133 } | |
134 | |
135 // static | 126 // static |
136 scoped_ptr<TracingManager> TracingManager::Create() { | 127 scoped_ptr<TracingManager> TracingManager::Create() { |
137 if (g_tracing_manager) | 128 if (g_tracing_manager) |
138 return scoped_ptr<TracingManager>(); | 129 return scoped_ptr<TracingManager>(); |
139 return scoped_ptr<TracingManager>(new TracingManager()); | 130 return scoped_ptr<TracingManager>(new TracingManager()); |
140 } | 131 } |
141 | 132 |
142 TracingManager* TracingManager::Get() { | 133 TracingManager* TracingManager::Get() { |
143 return g_tracing_manager; | 134 return g_tracing_manager; |
144 } | 135 } |
OLD | NEW |