OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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. | |
4 | |
5 #include "content/browser/tracing/background_tracing_manager_impl.h" | |
6 | |
7 #include "base/macros.h" | |
8 #include "base/time/time.h" | |
9 #include "content/public/browser/background_tracing_preemptive_config.h" | |
10 #include "content/public/browser/background_tracing_reactive_config.h" | |
11 #include "content/public/browser/browser_thread.h" | |
12 | |
13 namespace content { | |
14 | |
15 namespace { | |
16 | |
17 base::LazyInstance<BackgroundTracingManagerImpl>::Leaky g_controller = | |
18 LAZY_INSTANCE_INITIALIZER; | |
19 | |
20 } // namespace | |
21 | |
22 BackgroundTracingManagerImpl::TraceDataEndpointWrapper:: | |
23 TraceDataEndpointWrapper(base::Callback< | |
24 void(scoped_refptr<base::RefCountedString>)> done_callback) | |
25 : done_callback_(done_callback) { | |
26 } | |
27 | |
28 BackgroundTracingManagerImpl::TraceDataEndpointWrapper:: | |
29 ~TraceDataEndpointWrapper() { | |
30 } | |
31 | |
32 void BackgroundTracingManagerImpl::TraceDataEndpointWrapper:: | |
33 ReceiveTraceFinalContents(const std::string& file_contents) { | |
34 std::string tmp = file_contents; | |
35 scoped_refptr<base::RefCountedString> contents_ptr = | |
36 base::RefCountedString::TakeString(&tmp); | |
37 | |
38 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
39 base::Bind(done_callback_, contents_ptr)); | |
40 } | |
41 | |
42 BackgroundTracingManagerImpl::TracingTimer:: | |
43 TracingTimer(StartedFinalizingCallback callback) : callback_(callback) { | |
44 } | |
45 | |
46 BackgroundTracingManagerImpl::TracingTimer::~TracingTimer() { | |
47 } | |
48 | |
49 void BackgroundTracingManagerImpl::TracingTimer::StartTimer() { | |
50 tracing_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(10), this, | |
51 &BackgroundTracingManagerImpl::TracingTimer::TracingTimerFired); | |
52 } | |
53 | |
54 void BackgroundTracingManagerImpl::TracingTimer::CancelTimer() { | |
shatch
2015/05/21 15:59:06
This isn't referenced anywhere.
| |
55 tracing_timer_.Stop(); | |
56 } | |
57 | |
58 void BackgroundTracingManagerImpl::TracingTimer::TracingTimerFired() { | |
59 BackgroundTracingManagerImpl::GetInstance()->BeginFinalizing(callback_); | |
shatch
2015/05/21 15:59:05
Both TriggerNamedEvent and this can trigger a Begi
| |
60 } | |
61 | |
62 BackgroundTracingManager* BackgroundTracingManager::GetInstance() { | |
63 return BackgroundTracingManagerImpl::GetInstance(); | |
64 } | |
65 | |
66 BackgroundTracingManagerImpl* BackgroundTracingManagerImpl::GetInstance() { | |
67 return g_controller.Pointer(); | |
68 } | |
69 | |
70 BackgroundTracingManagerImpl::BackgroundTracingManagerImpl() | |
71 : is_gathering_(false), | |
72 is_tracing_(false), | |
73 requires_anonymized_data_(true), | |
74 trigger_handle_ids_(0) { | |
75 data_endpoint_wrapper_ = new TraceDataEndpointWrapper( | |
76 base::Bind(&BackgroundTracingManagerImpl::OnFinalizeStarted, | |
77 base::Unretained(this))); | |
78 } | |
79 | |
80 BackgroundTracingManagerImpl::~BackgroundTracingManagerImpl() { | |
81 NOTREACHED(); | |
82 } | |
83 | |
84 void BackgroundTracingManagerImpl::WhenIdle( | |
85 base::Callback<void()> idle_callback) { | |
86 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
87 idle_callback_ = idle_callback; | |
88 } | |
89 | |
90 bool BackgroundTracingManagerImpl::IsSupportedConfig( | |
91 BackgroundTracingConfig* config) { | |
92 // No config is just fine, we just don't do anything. | |
93 if (!config) | |
94 return true; | |
95 | |
96 if (config->mode == BackgroundTracingConfig::PREEMPTIVE_TRACING_MODE) { | |
97 BackgroundTracingPreemptiveConfig* preemptive_config = | |
98 static_cast<BackgroundTracingPreemptiveConfig*>(config); | |
99 const std::vector<BackgroundTracingPreemptiveConfig::MonitoringRule>& | |
100 configs = preemptive_config->configs; | |
101 for (size_t i = 0; i < configs.size(); ++i) { | |
102 if (configs[i].type != | |
103 BackgroundTracingPreemptiveConfig:: | |
104 MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED) | |
105 return false; | |
106 } | |
107 } | |
108 | |
109 if (config->mode == BackgroundTracingConfig::REACTIVE_TRACING_MODE) { | |
110 BackgroundTracingReactiveConfig* reactive_config = | |
111 static_cast<BackgroundTracingReactiveConfig*>(config); | |
112 const std::vector<BackgroundTracingReactiveConfig::TracingRule>& | |
113 configs = reactive_config->configs; | |
114 for (size_t i = 0; i < configs.size(); ++i) { | |
115 if (configs[i].type != | |
116 BackgroundTracingReactiveConfig:: | |
117 TRACE_ON_MANUAL_TRIGGER_UNTIL_10S_OR_NEXT_TRIGGER_OR_FULL) | |
118 return false; | |
119 } | |
120 } | |
121 | |
122 return true; | |
123 } | |
124 | |
125 bool BackgroundTracingManagerImpl::SetActiveScenario( | |
126 scoped_ptr<BackgroundTracingConfig> config, | |
127 const BackgroundTracingManager::ReceiveCallback& receive_callback, | |
128 bool requires_anonymized_data) { | |
129 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
130 if (is_tracing_) | |
131 return false; | |
132 | |
133 if (!IsSupportedConfig(config.get())) | |
134 return false; | |
135 | |
136 // No point in tracing if there's nowhere to send it. | |
137 if (config && receive_callback.is_null()) | |
138 return false; | |
139 | |
140 config_ = config.Pass(); | |
141 receive_callback_ = receive_callback; | |
142 requires_anonymized_data_ = requires_anonymized_data; | |
143 | |
144 EnableRecordingIfConfigNeedsIt(); | |
145 | |
146 return true; | |
147 } | |
148 | |
149 void BackgroundTracingManagerImpl::EnableRecordingIfConfigNeedsIt() { | |
150 if (!config_) | |
151 return; | |
152 | |
153 if (config_->mode == BackgroundTracingConfig::PREEMPTIVE_TRACING_MODE) { | |
154 EnableRecording(GetCategoryFilterForCategoryPreset( | |
155 static_cast<BackgroundTracingPreemptiveConfig*>(config_.get()) | |
156 ->category_preset)); | |
157 } else { | |
158 // There is nothing to do in case of reactive tracing. | |
159 } | |
160 } | |
161 | |
162 bool BackgroundTracingManagerImpl::IsAbleToTriggerTracing( | |
163 TriggerHandle handle) const { | |
164 if (!config_) | |
165 return false; | |
166 | |
167 // If the last trace is still uploading, we don't allow a new one to trigger. | |
168 if (is_gathering_) | |
169 return false; | |
170 | |
171 if (!IsTriggerHandleValid(handle)) { | |
172 return false; | |
173 } | |
174 | |
175 std::string trigger_name = GetTriggerNameFromHandle(handle); | |
176 | |
177 if (config_->mode == BackgroundTracingConfig::PREEMPTIVE_TRACING_MODE) { | |
178 BackgroundTracingPreemptiveConfig* preemptive_config = | |
179 static_cast<BackgroundTracingPreemptiveConfig*>(config_.get()); | |
180 | |
181 const std::vector<BackgroundTracingPreemptiveConfig::MonitoringRule>& | |
182 configs = preemptive_config->configs; | |
183 | |
184 for (size_t i = 0; i < configs.size(); ++i) { | |
185 if (configs[i].type != BackgroundTracingPreemptiveConfig:: | |
186 MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED) | |
187 continue; | |
188 | |
189 if (trigger_name == configs[i].named_trigger_info.trigger_name) { | |
190 return true; | |
191 } | |
192 } | |
193 } else { | |
194 BackgroundTracingReactiveConfig* reactive_config = | |
195 static_cast<BackgroundTracingReactiveConfig*>(config_.get()); | |
196 | |
197 const std::vector<BackgroundTracingReactiveConfig::TracingRule>& | |
198 configs = reactive_config->configs; | |
199 | |
200 for (size_t i = 0; i < configs.size(); ++i) { | |
201 if (configs[i].type != | |
202 BackgroundTracingReactiveConfig:: | |
203 TRACE_ON_MANUAL_TRIGGER_UNTIL_10S_OR_NEXT_TRIGGER_OR_FULL) | |
204 continue; | |
205 if (trigger_name == configs[i].trigger_name) { | |
206 return true; | |
207 } | |
208 } | |
209 } | |
210 return false; | |
211 } | |
212 | |
213 | |
214 | |
215 void BackgroundTracingManagerImpl::TriggerNamedEvent( | |
216 BackgroundTracingManagerImpl::TriggerHandle handle, | |
217 StartedFinalizingCallback callback) { | |
218 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { | |
219 content::BrowserThread::PostTask( | |
220 content::BrowserThread::UI, FROM_HERE, | |
221 base::Bind(&BackgroundTracingManagerImpl::TriggerNamedEvent, | |
222 base::Unretained(this), handle, callback)); | |
223 return; | |
224 } | |
225 | |
226 if (!IsAbleToTriggerTracing(handle)) { | |
227 if (!callback.is_null()) | |
228 callback.Run(false); | |
229 return; | |
230 } | |
231 | |
232 if (config_->mode == BackgroundTracingConfig::PREEMPTIVE_TRACING_MODE) { | |
233 BeginFinalizing(callback); | |
234 } else { | |
235 if (is_tracing_) { | |
236 BeginFinalizing(callback); | |
shatch
2015/05/21 15:59:06
Just wondering, does deep reports need to know or
fmeawad
2015/05/21 16:09:38
No. The idea is to collect as many as we can, but
| |
237 return; | |
238 } else { | |
239 //TODO(fmeawad): Currently we only have BENCHMARD_DEEP for reactive mode, | |
240 // but this code need to be generalized. | |
241 EnableRecording( | |
242 GetCategoryFilterForCategoryPreset( | |
shatch
2015/05/21 15:59:06
BackgroundTracingReactiveConfig::TracingRule has a
fmeawad
2015/05/21 16:09:38
Yes, see todo above.
| |
243 BackgroundTracingConfig::CategoryPreset::BENCHMARK_DEEP)); | |
244 | |
245 TracingTimer* timer = new TracingTimer(callback); | |
shatch
2015/05/21 15:59:06
Maybe change this to a scoped_ptr member?
fmeawad
2015/05/21 16:09:38
Yes, that is the plan.
| |
246 timer->StartTimer(); | |
247 } | |
248 } | |
249 } | |
250 | |
251 BackgroundTracingManagerImpl::TriggerHandle | |
252 BackgroundTracingManagerImpl::RegisterTriggerType(const char* trigger_name) { | |
253 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
254 | |
255 trigger_handle_ids_ += 1; | |
256 | |
257 trigger_handles_.insert( | |
258 std::pair<TriggerHandle, std::string>(trigger_handle_ids_, trigger_name)); | |
259 | |
260 return static_cast<TriggerHandle>(trigger_handle_ids_); | |
261 } | |
262 | |
263 bool BackgroundTracingManagerImpl::IsTriggerHandleValid( | |
264 BackgroundTracingManager::TriggerHandle handle) const { | |
265 return trigger_handles_.find(handle) != trigger_handles_.end(); | |
266 } | |
267 | |
268 std::string BackgroundTracingManagerImpl::GetTriggerNameFromHandle( | |
269 BackgroundTracingManager::TriggerHandle handle) const { | |
270 CHECK(IsTriggerHandleValid(handle)); | |
271 return trigger_handles_.find(handle)->second; | |
272 } | |
273 | |
274 void BackgroundTracingManagerImpl::GetTriggerNameList( | |
275 std::vector<std::string>* trigger_names) { | |
276 for (std::map<TriggerHandle, std::string>::iterator it = | |
277 trigger_handles_.begin(); | |
278 it != trigger_handles_.end(); ++it) | |
279 trigger_names->push_back(it->second); | |
280 } | |
281 | |
282 void BackgroundTracingManagerImpl::InvalidateTriggerHandlesForTesting() { | |
283 trigger_handles_.clear(); | |
284 } | |
285 | |
286 void BackgroundTracingManagerImpl::EnableRecording( | |
287 base::trace_event::CategoryFilter category_filter) { | |
288 is_tracing_ = TracingController::GetInstance()->EnableRecording( | |
289 category_filter, | |
290 base::trace_event::TraceOptions(base::trace_event::RECORD_CONTINUOUSLY), | |
291 TracingController::EnableRecordingDoneCallback()); | |
292 } | |
293 | |
294 void BackgroundTracingManagerImpl::OnFinalizeStarted( | |
295 scoped_refptr<base::RefCountedString> file_contents) { | |
296 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
297 | |
298 if (!receive_callback_.is_null()) | |
299 receive_callback_.Run( | |
300 file_contents.get(), | |
301 base::Bind(&BackgroundTracingManagerImpl::OnFinalizeComplete, | |
302 base::Unretained(this))); | |
303 } | |
304 | |
305 void BackgroundTracingManagerImpl::OnTracingTimeout() { | |
shatch
2015/05/21 15:59:06
Is this reference somewhere? What does it do?
| |
306 | |
307 } | |
308 | |
309 void BackgroundTracingManagerImpl::OnFinalizeComplete() { | |
310 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
311 BrowserThread::PostTask( | |
312 BrowserThread::UI, FROM_HERE, | |
313 base::Bind(&BackgroundTracingManagerImpl::OnFinalizeComplete, | |
314 base::Unretained(this))); | |
315 return; | |
316 } | |
317 | |
318 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
319 | |
320 is_gathering_ = false; | |
321 | |
322 if (!idle_callback_.is_null()) | |
323 idle_callback_.Run(); | |
324 | |
325 // Now that a trace has completed, we may need to enable recording again. | |
326 EnableRecordingIfConfigNeedsIt(); | |
327 } | |
328 | |
329 void BackgroundTracingManagerImpl::BeginFinalizing( | |
330 StartedFinalizingCallback callback) { | |
331 is_gathering_ = true; | |
332 is_tracing_ = false; | |
333 | |
334 content::TracingController::GetInstance()->DisableRecording( | |
335 content::TracingController::CreateCompressedStringSink( | |
336 data_endpoint_wrapper_)); | |
337 | |
338 if (!callback.is_null()) | |
339 callback.Run(true); | |
340 } | |
341 | |
342 base::trace_event::CategoryFilter | |
343 BackgroundTracingManagerImpl::GetCategoryFilterForCategoryPreset( | |
344 BackgroundTracingConfig::CategoryPreset preset) const { | |
345 switch (preset) { | |
346 case BackgroundTracingConfig::CategoryPreset::BENCHMARK: | |
347 return base::trace_event::CategoryFilter( | |
348 "benchmark," | |
349 "disabled-by-default-toplevel.flow," | |
350 "disabled-by-default-ipc.flow"); | |
351 case BackgroundTracingConfig::CategoryPreset::BENCHMARK_DEEP: | |
352 return base::trace_event::CategoryFilter( | |
353 "*,disabled-by-default-blink.debug.layout"); | |
354 } | |
355 NOTREACHED(); | |
356 return base::trace_event::CategoryFilter(); | |
357 } | |
358 | |
359 BackgroundTracingConfig* BackgroundTracingConfig::FromDict( | |
360 const base::DictionaryValue* dict) { | |
361 // TODO(simonhatch): Implement this. | |
362 CHECK(false); | |
363 return NULL; | |
364 } | |
365 | |
366 void BackgroundTracingConfig::IntoDict(const BackgroundTracingConfig* config, | |
367 base::DictionaryValue* dict) { | |
368 // TODO(simonhatch): Implement this. | |
369 CHECK(false); | |
370 } | |
371 | |
372 } // namspace content | |
OLD | NEW |