OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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 #include "content/browser/tracing/tracing_controller_impl.h" | 4 #include "content/browser/tracing/tracing_controller_impl.h" |
5 | 5 |
6 #include <algorithm> | 6 #include <algorithm> |
7 #include <memory> | 7 #include <memory> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/cpu.h" | 12 #include "base/cpu.h" |
13 #include "base/files/file_util.h" | 13 #include "base/files/file_util.h" |
14 #include "base/guid.h" | 14 #include "base/guid.h" |
15 #include "base/json/string_escape.h" | 15 #include "base/json/string_escape.h" |
16 #include "base/macros.h" | 16 #include "base/macros.h" |
17 #include "base/memory/ref_counted_memory.h" | 17 #include "base/memory/ref_counted_memory.h" |
18 #include "base/strings/string_number_conversions.h" | 18 #include "base/strings/string_number_conversions.h" |
| 19 #include "base/strings/string_split.h" |
19 #include "base/sys_info.h" | 20 #include "base/sys_info.h" |
20 #include "base/threading/sequenced_worker_pool.h" | 21 #include "base/threading/sequenced_worker_pool.h" |
21 #include "base/threading/thread_task_runner_handle.h" | 22 #include "base/threading/thread_task_runner_handle.h" |
22 #include "base/time/time.h" | 23 #include "base/time/time.h" |
23 #include "base/trace_event/trace_event.h" | 24 #include "base/trace_event/trace_event.h" |
24 #include "build/build_config.h" | 25 #include "build/build_config.h" |
25 #include "components/tracing/common/process_metrics_memory_dump_provider.h" | 26 #include "components/tracing/common/process_metrics_memory_dump_provider.h" |
26 #include "content/browser/tracing/file_tracing_provider_impl.h" | 27 #include "content/browser/tracing/file_tracing_provider_impl.h" |
27 #include "content/browser/tracing/trace_message_filter.h" | 28 #include "content/browser/tracing/trace_message_filter.h" |
28 #include "content/browser/tracing/tracing_ui.h" | 29 #include "content/browser/tracing/tracing_ui.h" |
29 #include "content/common/child_process_messages.h" | 30 #include "content/common/child_process_messages.h" |
30 #include "content/public/browser/browser_message_filter.h" | 31 #include "content/public/browser/browser_message_filter.h" |
31 #include "content/public/browser/content_browser_client.h" | 32 #include "content/public/browser/content_browser_client.h" |
32 #include "content/public/browser/gpu_data_manager.h" | 33 #include "content/public/browser/gpu_data_manager.h" |
33 #include "content/public/browser/tracing_delegate.h" | 34 #include "content/public/browser/tracing_delegate.h" |
34 #include "content/public/common/child_process_host.h" | 35 #include "content/public/common/child_process_host.h" |
35 #include "content/public/common/content_client.h" | 36 #include "content/public/common/content_client.h" |
36 #include "content/public/common/content_switches.h" | 37 #include "content/public/common/content_switches.h" |
37 #include "gpu/config/gpu_info.h" | 38 #include "gpu/config/gpu_info.h" |
38 #include "net/base/network_change_notifier.h" | 39 #include "net/base/network_change_notifier.h" |
| 40 #include "services/resource_coordinator/tracing/coordinator_impl.h" |
| 41 #include "services/service_manager/public/cpp/connector.h" |
39 #include "v8/include/v8-version-string.h" | 42 #include "v8/include/v8-version-string.h" |
40 | 43 |
41 #if (defined(OS_POSIX) && defined(USE_UDEV)) || defined(OS_WIN) || \ | 44 #if (defined(OS_POSIX) && defined(USE_UDEV)) || defined(OS_WIN) || \ |
42 defined(OS_MACOSX) | 45 defined(OS_MACOSX) |
43 #define ENABLE_POWER_TRACING | 46 #define ENABLE_POWER_TRACING |
44 #endif | 47 #endif |
45 | 48 |
46 #if defined(ENABLE_POWER_TRACING) | 49 #if defined(ENABLE_POWER_TRACING) |
47 #include "content/browser/tracing/power_tracing_agent.h" | 50 #include "content/browser/tracing/power_tracing_agent.h" |
48 #endif | 51 #endif |
(...skipping 11 matching lines...) Expand all Loading... |
60 using base::trace_event::TraceLog; | 63 using base::trace_event::TraceLog; |
61 using base::trace_event::TraceConfig; | 64 using base::trace_event::TraceConfig; |
62 | 65 |
63 namespace content { | 66 namespace content { |
64 | 67 |
65 namespace { | 68 namespace { |
66 | 69 |
67 base::LazyInstance<TracingControllerImpl>::Leaky g_controller = | 70 base::LazyInstance<TracingControllerImpl>::Leaky g_controller = |
68 LAZY_INSTANCE_INITIALIZER; | 71 LAZY_INSTANCE_INITIALIZER; |
69 | 72 |
70 const char kChromeTracingAgentName[] = "chrome"; | |
71 const char kETWTracingAgentName[] = "etw"; | |
72 const char kArcTracingAgentName[] = "arc"; | |
73 const char kChromeTraceLabel[] = "traceEvents"; | |
74 | |
75 const int kStartTracingTimeoutSeconds = 30; | |
76 const int kIssueClockSyncTimeoutSeconds = 30; | |
77 const int kStopTracingRetryTimeMilliseconds = 100; | |
78 | |
79 std::string GetNetworkTypeString() { | |
80 switch (net::NetworkChangeNotifier::GetConnectionType()) { | |
81 case net::NetworkChangeNotifier::CONNECTION_ETHERNET: | |
82 return "Ethernet"; | |
83 case net::NetworkChangeNotifier::CONNECTION_WIFI: | |
84 return "WiFi"; | |
85 case net::NetworkChangeNotifier::CONNECTION_2G: | |
86 return "2G"; | |
87 case net::NetworkChangeNotifier::CONNECTION_3G: | |
88 return "3G"; | |
89 case net::NetworkChangeNotifier::CONNECTION_4G: | |
90 return "4G"; | |
91 case net::NetworkChangeNotifier::CONNECTION_NONE: | |
92 return "None"; | |
93 case net::NetworkChangeNotifier::CONNECTION_BLUETOOTH: | |
94 return "Bluetooth"; | |
95 case net::NetworkChangeNotifier::CONNECTION_UNKNOWN: | |
96 default: | |
97 break; | |
98 } | |
99 return "Unknown"; | |
100 } | |
101 | |
102 std::string GetClockString() { | |
103 switch (base::TimeTicks::GetClock()) { | |
104 case base::TimeTicks::Clock::LINUX_CLOCK_MONOTONIC: | |
105 return "LINUX_CLOCK_MONOTONIC"; | |
106 case base::TimeTicks::Clock::IOS_CF_ABSOLUTE_TIME_MINUS_KERN_BOOTTIME: | |
107 return "IOS_CF_ABSOLUTE_TIME_MINUS_KERN_BOOTTIME"; | |
108 case base::TimeTicks::Clock::MAC_MACH_ABSOLUTE_TIME: | |
109 return "MAC_MACH_ABSOLUTE_TIME"; | |
110 case base::TimeTicks::Clock::WIN_QPC: | |
111 return "WIN_QPC"; | |
112 case base::TimeTicks::Clock::WIN_ROLLOVER_PROTECTED_TIME_GET_TIME: | |
113 return "WIN_ROLLOVER_PROTECTED_TIME_GET_TIME"; | |
114 } | |
115 | |
116 NOTREACHED(); | |
117 return std::string(); | |
118 } | |
119 | |
120 } // namespace | 73 } // namespace |
121 | 74 |
122 TracingController* TracingController::GetInstance() { | 75 TracingController* TracingController::GetInstance() { |
123 return TracingControllerImpl::GetInstance(); | 76 return TracingControllerImpl::GetInstance(); |
124 } | 77 } |
125 | 78 |
126 TracingControllerImpl::TracingControllerImpl() | 79 TracingControllerImpl::TracingControllerImpl() { |
127 : pending_start_tracing_ack_count_(0), | |
128 pending_stop_tracing_ack_count_(0), | |
129 pending_trace_log_status_ack_count_(0), | |
130 maximum_trace_buffer_usage_(0), | |
131 approximate_event_count_(0), | |
132 pending_clock_sync_ack_count_(0), | |
133 enabled_tracing_modes_(0) { | |
134 // Deliberately leaked, like this class. | 80 // Deliberately leaked, like this class. |
135 base::FileTracing::SetProvider(new FileTracingProviderImpl); | 81 base::FileTracing::SetProvider(new FileTracingProviderImpl); |
136 } | 82 } |
137 | 83 |
| 84 void TracingControllerImpl::Initialize(service_manager::Connector* connector) { |
| 85 if (connector) { |
| 86 connector->BindInterface("tracing", &coordinator_); |
| 87 return; |
| 88 } |
| 89 // If connector is null, the coordinator must be running in this process. |
| 90 resource_coordinator::tracing::CoordinatorImpl* coordinator = |
| 91 resource_coordinator::tracing::CoordinatorImpl::GetInstance(); |
| 92 DCHECK(coordinator); |
| 93 coordinator->BindCoordinatorRequest(mojo::MakeRequest(&coordinator_)); |
| 94 } |
| 95 |
138 TracingControllerImpl::~TracingControllerImpl() { | 96 TracingControllerImpl::~TracingControllerImpl() { |
139 // This is a Leaky instance. | 97 // This is a Leaky instance. |
140 NOTREACHED(); | 98 NOTREACHED(); |
141 } | 99 } |
142 | 100 |
143 TracingControllerImpl* TracingControllerImpl::GetInstance() { | 101 TracingControllerImpl* TracingControllerImpl::GetInstance() { |
144 return g_controller.Pointer(); | 102 return g_controller.Pointer(); |
145 } | 103 } |
146 | 104 |
147 bool TracingControllerImpl::GetCategories( | 105 bool TracingControllerImpl::GetCategories( |
148 const GetCategoriesDoneCallback& callback) { | 106 const GetCategoriesDoneCallback& callback) { |
149 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 107 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
150 | 108 |
151 // Known categories come back from child processes with the EndTracingAck | 109 coordinator_->GetCategories( |
152 // message. So to get known categories, just begin and end tracing immediately | 110 base::BindRepeating(&TracingControllerImpl::GetCategoriesDone, |
153 // afterwards. This will ping all the child processes for categories. | 111 base::Unretained(this), callback)); |
154 pending_get_categories_done_callback_ = callback; | |
155 if (!StartTracing(TraceConfig("*", ""), StartTracingDoneCallback())) { | |
156 pending_get_categories_done_callback_.Reset(); | |
157 return false; | |
158 } | |
159 | |
160 bool ok = StopTracing(NULL); | |
161 DCHECK(ok); | |
162 return true; | 112 return true; |
163 } | 113 } |
164 | 114 |
165 void TracingControllerImpl::SetEnabledOnFileThread( | 115 void TracingControllerImpl::GetCategoriesDone( |
166 const TraceConfig& trace_config, | 116 const GetCategoriesDoneCallback& callback, |
167 const base::Closure& callback) { | 117 const std::string& categories) { |
168 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 118 const std::vector<std::string> split = base::SplitString( |
169 | 119 categories, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
170 TraceLog::GetInstance()->SetEnabled(trace_config, enabled_tracing_modes_); | 120 std::set<std::string> category_set; |
171 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); | 121 for (const auto& category : split) { |
172 } | 122 category_set.insert(category); |
173 | 123 } |
174 void TracingControllerImpl::SetDisabledOnFileThread( | 124 callback.Run(category_set); |
175 const base::Closure& callback) { | |
176 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | |
177 | |
178 DCHECK(enabled_tracing_modes_); | |
179 TraceLog::GetInstance()->SetDisabled(enabled_tracing_modes_); | |
180 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); | |
181 } | 125 } |
182 | 126 |
183 bool TracingControllerImpl::StartTracing( | 127 bool TracingControllerImpl::StartTracing( |
184 const TraceConfig& trace_config, | 128 const TraceConfig& trace_config, |
185 const StartTracingDoneCallback& callback) { | 129 const StartTracingDoneCallback& callback) { |
186 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 130 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
187 DCHECK(additional_tracing_agents_.empty()); | |
188 | 131 |
189 // TODO(ssid): Introduce a priority for tracing agents to handle multiple | 132 is_tracing_ = true; |
190 // start and stop requests, crbug.com/705087. | 133 mojo::DataPipe data_pipe; |
191 if (!can_start_tracing()) | 134 coordinator_->StartTracing(std::move(data_pipe.producer_handle), |
192 return false; | 135 trace_config.ToString()); |
193 start_tracing_done_callback_ = callback; | 136 drainer_.reset(new mojo::common::DataPipeDrainer( |
194 trace_config_.reset(new base::trace_event::TraceConfig(trace_config)); | 137 this, std::move(data_pipe.consumer_handle))); |
195 enabled_tracing_modes_ = TraceLog::RECORDING_MODE; | 138 if (!callback.is_null()) |
196 if (!trace_config_->event_filters().empty()) | 139 callback.Run(); |
197 enabled_tracing_modes_ |= TraceLog::FILTERING_MODE; | |
198 metadata_.reset(new base::DictionaryValue()); | |
199 pending_start_tracing_ack_count_ = 0; | |
200 | |
201 #if defined(OS_ANDROID) | |
202 if (pending_get_categories_done_callback_.is_null()) | |
203 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); | |
204 #endif | |
205 | |
206 if (trace_config.IsSystraceEnabled()) { | |
207 #if defined(ENABLE_POWER_TRACING) | |
208 PowerTracingAgent::GetInstance()->StartAgentTracing( | |
209 trace_config, | |
210 base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked, | |
211 base::Unretained(this))); | |
212 ++pending_start_tracing_ack_count_; | |
213 #endif | |
214 | |
215 #if defined(OS_CHROMEOS) | |
216 chromeos::DebugDaemonClient* debug_daemon = | |
217 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient(); | |
218 if (debug_daemon) { | |
219 debug_daemon->StartAgentTracing( | |
220 trace_config, | |
221 base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked, | |
222 base::Unretained(this))); | |
223 ++pending_start_tracing_ack_count_; | |
224 } | |
225 | |
226 ArcTracingAgent::GetInstance()->StartAgentTracing( | |
227 trace_config, | |
228 base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked, | |
229 base::Unretained(this))); | |
230 ++pending_start_tracing_ack_count_; | |
231 #elif defined(OS_WIN) | |
232 EtwTracingAgent::GetInstance()->StartAgentTracing( | |
233 trace_config, | |
234 base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked, | |
235 base::Unretained(this))); | |
236 ++pending_start_tracing_ack_count_; | |
237 #endif | |
238 } | |
239 | |
240 // TraceLog may have been enabled in startup tracing before threads are ready. | |
241 if (TraceLog::GetInstance()->IsEnabled()) | |
242 return true; | |
243 | |
244 StartAgentTracing(trace_config, | |
245 base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked, | |
246 base::Unretained(this))); | |
247 ++pending_start_tracing_ack_count_; | |
248 | |
249 // Set a deadline to ensure all agents ack within a reasonable time frame. | |
250 start_tracing_timer_.Start( | |
251 FROM_HERE, base::TimeDelta::FromSeconds(kStartTracingTimeoutSeconds), | |
252 base::Bind(&TracingControllerImpl::OnAllTracingAgentsStarted, | |
253 base::Unretained(this))); | |
254 | |
255 return true; | 140 return true; |
256 } | 141 } |
257 | 142 |
258 void TracingControllerImpl::OnAllTracingAgentsStarted() { | |
259 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
260 | |
261 TRACE_EVENT_API_ADD_METADATA_EVENT( | |
262 TraceLog::GetCategoryGroupEnabled("__metadata"), | |
263 "IsTimeTicksHighResolution", "value", | |
264 base::TimeTicks::IsHighResolution()); | |
265 | |
266 // Notify all child processes. | |
267 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); | |
268 it != trace_message_filters_.end(); ++it) { | |
269 it->get()->SendBeginTracing(*trace_config_); | |
270 } | |
271 | |
272 if (!start_tracing_done_callback_.is_null()) | |
273 start_tracing_done_callback_.Run(); | |
274 | |
275 start_tracing_done_callback_.Reset(); | |
276 } | |
277 | |
278 void TracingControllerImpl::AddMetadata(const base::DictionaryValue& data) { | |
279 if (metadata_) | |
280 metadata_->MergeDictionary(&data); | |
281 } | |
282 | |
283 bool TracingControllerImpl::StopTracing( | 143 bool TracingControllerImpl::StopTracing( |
284 const scoped_refptr<TraceDataSink>& trace_data_sink) { | 144 const scoped_refptr<TraceDataSink>& trace_data_sink) { |
285 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 145 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
286 | 146 |
287 if (!can_stop_tracing()) | |
288 return false; | |
289 | |
290 // If we're still waiting to start tracing, try again after a delay. | |
291 if (start_tracing_timer_.IsRunning()) { | |
292 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
293 FROM_HERE, | |
294 base::Bind(base::IgnoreResult(&TracingControllerImpl::StopTracing), | |
295 base::Unretained(this), trace_data_sink), | |
296 base::TimeDelta::FromMilliseconds(kStopTracingRetryTimeMilliseconds)); | |
297 return true; | |
298 } | |
299 | |
300 if (trace_data_sink) { | |
301 MetadataFilterPredicate metadata_filter; | |
302 if (TraceLog::GetInstance()->GetCurrentTraceConfig() | |
303 .IsArgumentFilterEnabled()) { | |
304 std::unique_ptr<TracingDelegate> delegate( | |
305 GetContentClient()->browser()->GetTracingDelegate()); | |
306 if (delegate) | |
307 metadata_filter = delegate->GetMetadataFilterPredicate(); | |
308 } | |
309 AddFilteredMetadata(trace_data_sink.get(), GenerateTracingMetadataDict(), | |
310 metadata_filter); | |
311 AddFilteredMetadata(trace_data_sink.get(), std::move(metadata_), | |
312 metadata_filter); | |
313 } else { | |
314 metadata_.reset(); | |
315 } | |
316 | |
317 trace_data_sink_ = trace_data_sink; | 147 trace_data_sink_ = trace_data_sink; |
318 trace_config_.reset(); | 148 coordinator_->StopAndFlush(); |
319 | |
320 // Issue clock sync marker before actually stopping tracing. | |
321 // StopTracingAfterClockSync() will be called after clock sync is done. | |
322 IssueClockSyncMarker(); | |
323 | |
324 return true; | 149 return true; |
325 } | 150 } |
326 | 151 |
327 void TracingControllerImpl::StopTracingAfterClockSync() { | |
328 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
329 | |
330 // |pending_clock_sync_ack_count_| could be non-zero if clock sync times out. | |
331 pending_clock_sync_ack_count_ = 0; | |
332 | |
333 // Disable local trace early to avoid traces during end-tracing process from | |
334 // interfering with the process. | |
335 base::Closure on_stop_tracing_done_callback = base::Bind( | |
336 &TracingControllerImpl::OnStopTracingDone, base::Unretained(this)); | |
337 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | |
338 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread, | |
339 base::Unretained(this), | |
340 on_stop_tracing_done_callback)); | |
341 } | |
342 | |
343 void TracingControllerImpl::OnStopTracingDone() { | |
344 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
345 | |
346 #if defined(OS_ANDROID) | |
347 if (pending_get_categories_done_callback_.is_null()) | |
348 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); | |
349 #endif | |
350 | |
351 // Count myself (local trace) in pending_stop_tracing_ack_count_, | |
352 // acked below. | |
353 pending_stop_tracing_ack_count_ = trace_message_filters_.size() + 1; | |
354 pending_stop_tracing_filters_ = trace_message_filters_; | |
355 | |
356 pending_stop_tracing_ack_count_ += additional_tracing_agents_.size(); | |
357 for (auto* it : additional_tracing_agents_) { | |
358 it->StopAgentTracing( | |
359 base::Bind(&TracingControllerImpl::OnEndAgentTracingAcked, | |
360 base::Unretained(this))); | |
361 } | |
362 additional_tracing_agents_.clear(); | |
363 | |
364 StopAgentTracing(StopAgentTracingCallback()); | |
365 } | |
366 | |
367 bool TracingControllerImpl::GetTraceBufferUsage( | 152 bool TracingControllerImpl::GetTraceBufferUsage( |
368 const GetTraceBufferUsageCallback& callback) { | 153 const GetTraceBufferUsageCallback& callback) { |
369 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 154 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
370 | 155 |
371 if (!can_get_trace_buffer_usage() || callback.is_null()) | 156 coordinator_->RequestBufferUsage( |
372 return false; | 157 base::BindRepeating(&TracingControllerImpl::GetTraceBufferUsageDone, |
373 | 158 base::Unretained(this), callback)); |
374 pending_trace_buffer_usage_callback_ = callback; | |
375 | |
376 // Count myself in pending_trace_log_status_ack_count_, acked below. | |
377 pending_trace_log_status_ack_count_ = trace_message_filters_.size() + 1; | |
378 pending_trace_log_status_filters_ = trace_message_filters_; | |
379 maximum_trace_buffer_usage_ = 0; | |
380 approximate_event_count_ = 0; | |
381 | |
382 base::trace_event::TraceLogStatus status = | |
383 TraceLog::GetInstance()->GetStatus(); | |
384 // Call OnTraceLogStatusReply unconditionally for the browser process. | |
385 // This will result in immediate execution of the callback if there are no | |
386 // child processes. | |
387 BrowserThread::PostTask( | |
388 BrowserThread::UI, FROM_HERE, | |
389 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply, | |
390 base::Unretained(this), nullptr, status)); | |
391 | |
392 // Notify all child processes. | |
393 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); | |
394 it != trace_message_filters_.end(); ++it) { | |
395 it->get()->SendGetTraceLogStatus(); | |
396 } | |
397 return true; | 159 return true; |
398 } | 160 } |
399 | 161 |
| 162 void TracingControllerImpl::AddMetadata(const base::DictionaryValue& metadata) { |
| 163 if (metadata_) |
| 164 metadata_->MergeDictionary(&metadata); |
| 165 } |
| 166 |
400 bool TracingControllerImpl::IsTracing() const { | 167 bool TracingControllerImpl::IsTracing() const { |
401 return !!enabled_tracing_modes_; | 168 return is_tracing_; |
| 169 } |
| 170 |
| 171 void TracingControllerImpl::GetTraceBufferUsageDone( |
| 172 const GetTraceBufferUsageCallback& callback, |
| 173 bool success, |
| 174 float percent_full, |
| 175 uint32_t approximate_count) { |
| 176 callback.Run(percent_full, approximate_count); |
402 } | 177 } |
403 | 178 |
404 void TracingControllerImpl::AddTraceMessageFilter( | 179 void TracingControllerImpl::AddTraceMessageFilter( |
405 TraceMessageFilter* trace_message_filter) { | 180 TraceMessageFilter* trace_message_filter) { |
406 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 181 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
407 BrowserThread::PostTask( | 182 BrowserThread::PostTask( |
408 BrowserThread::UI, FROM_HERE, | 183 BrowserThread::UI, FROM_HERE, |
409 base::Bind(&TracingControllerImpl::AddTraceMessageFilter, | 184 base::Bind(&TracingControllerImpl::AddTraceMessageFilter, |
410 base::Unretained(this), | 185 base::Unretained(this), |
411 base::RetainedRef(trace_message_filter))); | 186 base::RetainedRef(trace_message_filter))); |
412 return; | 187 return; |
413 } | 188 } |
414 | 189 |
415 #if defined(OS_LINUX) | 190 #if defined(OS_LINUX) |
416 // On Linux the browser process dumps process metrics for child process due to | 191 // On Linux the browser process dumps process metrics for child process due to |
417 // sandbox. | 192 // sandbox. |
418 tracing::ProcessMetricsMemoryDumpProvider::RegisterForProcess( | 193 tracing::ProcessMetricsMemoryDumpProvider::RegisterForProcess( |
419 trace_message_filter->peer_pid()); | 194 trace_message_filter->peer_pid()); |
420 #endif | 195 #endif |
421 | 196 |
422 trace_message_filters_.insert(trace_message_filter); | 197 trace_message_filters_.insert(trace_message_filter); |
423 if (can_stop_tracing()) { | |
424 trace_message_filter->SendBeginTracing( | |
425 TraceLog::GetInstance()->GetCurrentTraceConfig()); | |
426 } | |
427 | |
428 for (auto& observer : trace_message_filter_observers_) | 198 for (auto& observer : trace_message_filter_observers_) |
429 observer.OnTraceMessageFilterAdded(trace_message_filter); | 199 observer.OnTraceMessageFilterAdded(trace_message_filter); |
430 } | 200 } |
431 | 201 |
432 void TracingControllerImpl::RemoveTraceMessageFilter( | 202 void TracingControllerImpl::RemoveTraceMessageFilter( |
433 TraceMessageFilter* trace_message_filter) { | 203 TraceMessageFilter* trace_message_filter) { |
434 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 204 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
435 BrowserThread::PostTask( | 205 BrowserThread::PostTask( |
436 BrowserThread::UI, FROM_HERE, | 206 BrowserThread::UI, FROM_HERE, |
437 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter, | 207 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter, |
438 base::Unretained(this), | 208 base::Unretained(this), |
439 base::RetainedRef(trace_message_filter))); | 209 base::RetainedRef(trace_message_filter))); |
440 return; | 210 return; |
441 } | 211 } |
442 | 212 |
443 #if defined(OS_LINUX) | 213 #if defined(OS_LINUX) |
444 tracing::ProcessMetricsMemoryDumpProvider::UnregisterForProcess( | 214 tracing::ProcessMetricsMemoryDumpProvider::UnregisterForProcess( |
445 trace_message_filter->peer_pid()); | 215 trace_message_filter->peer_pid()); |
446 #endif | 216 #endif |
447 | 217 |
448 // If a filter is removed while a response from that filter is pending then | |
449 // simulate the response. Otherwise the response count will be wrong and the | |
450 // completion callback will never be executed. | |
451 if (pending_stop_tracing_ack_count_ > 0) { | |
452 TraceMessageFilterSet::const_iterator it = | |
453 pending_stop_tracing_filters_.find(trace_message_filter); | |
454 if (it != pending_stop_tracing_filters_.end()) { | |
455 BrowserThread::PostTask( | |
456 BrowserThread::UI, FROM_HERE, | |
457 base::Bind(&TracingControllerImpl::OnStopTracingAcked, | |
458 base::Unretained(this), | |
459 base::RetainedRef(trace_message_filter), | |
460 std::vector<std::string>())); | |
461 } | |
462 } | |
463 if (pending_trace_log_status_ack_count_ > 0) { | |
464 TraceMessageFilterSet::const_iterator it = | |
465 pending_trace_log_status_filters_.find(trace_message_filter); | |
466 if (it != pending_trace_log_status_filters_.end()) { | |
467 BrowserThread::PostTask( | |
468 BrowserThread::UI, FROM_HERE, | |
469 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply, | |
470 base::Unretained(this), | |
471 base::RetainedRef(trace_message_filter), | |
472 base::trace_event::TraceLogStatus())); | |
473 } | |
474 } | |
475 trace_message_filters_.erase(trace_message_filter); | 218 trace_message_filters_.erase(trace_message_filter); |
476 } | 219 } |
477 | 220 |
478 void TracingControllerImpl::AddTracingAgent(const std::string& agent_name) { | |
479 #if defined(OS_CHROMEOS) | |
480 auto* debug_daemon = | |
481 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient(); | |
482 if (agent_name == debug_daemon->GetTracingAgentName()) { | |
483 additional_tracing_agents_.push_back(debug_daemon); | |
484 debug_daemon->SetStopAgentTracingTaskRunner( | |
485 BrowserThread::GetBlockingPool()); | |
486 return; | |
487 } | |
488 | |
489 if (agent_name == kArcTracingAgentName) { | |
490 additional_tracing_agents_.push_back(ArcTracingAgent::GetInstance()); | |
491 return; | |
492 } | |
493 #elif defined(OS_WIN) | |
494 auto* etw_agent = EtwTracingAgent::GetInstance(); | |
495 if (agent_name == etw_agent->GetTracingAgentName()) { | |
496 additional_tracing_agents_.push_back(etw_agent); | |
497 return; | |
498 } | |
499 #endif | |
500 | |
501 #if defined(ENABLE_POWER_TRACING) | |
502 auto* power_agent = PowerTracingAgent::GetInstance(); | |
503 if (agent_name == power_agent->GetTracingAgentName()) { | |
504 additional_tracing_agents_.push_back(power_agent); | |
505 return; | |
506 } | |
507 #endif | |
508 | |
509 DCHECK(agent_name == kChromeTracingAgentName); | |
510 } | |
511 | |
512 void TracingControllerImpl::OnStartAgentTracingAcked( | |
513 const std::string& agent_name, | |
514 bool success) { | |
515 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
516 | |
517 // Don't taken any further action if the ack came after the deadline. | |
518 if (!start_tracing_timer_.IsRunning()) | |
519 return; | |
520 | |
521 if (success) | |
522 AddTracingAgent(agent_name); | |
523 | |
524 if (--pending_start_tracing_ack_count_ == 0) { | |
525 start_tracing_timer_.Stop(); | |
526 OnAllTracingAgentsStarted(); | |
527 } | |
528 } | |
529 | |
530 void TracingControllerImpl::OnStopTracingAcked( | |
531 TraceMessageFilter* trace_message_filter, | |
532 const std::vector<std::string>& known_category_groups) { | |
533 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
534 BrowserThread::PostTask( | |
535 BrowserThread::UI, FROM_HERE, | |
536 base::Bind( | |
537 &TracingControllerImpl::OnStopTracingAcked, base::Unretained(this), | |
538 base::RetainedRef(trace_message_filter), known_category_groups)); | |
539 return; | |
540 } | |
541 | |
542 // Merge known_category_groups with known_category_groups_ | |
543 known_category_groups_.insert(known_category_groups.begin(), | |
544 known_category_groups.end()); | |
545 | |
546 if (pending_stop_tracing_ack_count_ == 0) | |
547 return; | |
548 | |
549 if (trace_message_filter && | |
550 !pending_stop_tracing_filters_.erase(trace_message_filter)) { | |
551 // The response from the specified message filter has already been received. | |
552 return; | |
553 } | |
554 | |
555 if (--pending_stop_tracing_ack_count_ == 1) { | |
556 // All acks from subprocesses have been received. Now flush the local trace. | |
557 // During or after this call, our OnLocalTraceDataCollected will be | |
558 // called with the last of the local trace data. | |
559 if (trace_data_sink_) { | |
560 TraceLog::GetInstance()->Flush( | |
561 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected, | |
562 base::Unretained(this)), | |
563 true); | |
564 } else { | |
565 TraceLog::GetInstance()->CancelTracing( | |
566 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected, | |
567 base::Unretained(this))); | |
568 } | |
569 return; | |
570 } | |
571 | |
572 if (pending_stop_tracing_ack_count_ != 0) | |
573 return; | |
574 | |
575 // All acks (including from the subprocesses and the local trace) have been | |
576 // received. | |
577 enabled_tracing_modes_ = 0; | |
578 | |
579 // Trigger callback if one is set. | |
580 if (!pending_get_categories_done_callback_.is_null()) { | |
581 pending_get_categories_done_callback_.Run(known_category_groups_); | |
582 pending_get_categories_done_callback_.Reset(); | |
583 } else if (trace_data_sink_.get()) { | |
584 trace_data_sink_->Close(); | |
585 trace_data_sink_ = NULL; | |
586 } | |
587 } | |
588 | |
589 void TracingControllerImpl::OnEndAgentTracingAcked( | |
590 const std::string& agent_name, | |
591 const std::string& events_label, | |
592 const scoped_refptr<base::RefCountedString>& events_str_ptr) { | |
593 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
594 | |
595 if (trace_data_sink_.get() && events_str_ptr && | |
596 !events_str_ptr->data().empty()) { | |
597 if (agent_name == kETWTracingAgentName) { | |
598 // The Windows kernel events are kept into a JSON format stored as string | |
599 // and must not be escaped. | |
600 trace_data_sink_->AddAgentTrace(events_label, events_str_ptr->data()); | |
601 } else if (agent_name == kArcTracingAgentName) { | |
602 // The ARC events are kept into a JSON format stored as string | |
603 // and must not be escaped. | |
604 trace_data_sink_->AddTraceChunk(events_str_ptr->data()); | |
605 } else { | |
606 trace_data_sink_->AddAgentTrace( | |
607 events_label, base::GetQuotedJSONString(events_str_ptr->data())); | |
608 } | |
609 } | |
610 std::vector<std::string> category_groups; | |
611 OnStopTracingAcked(NULL, category_groups); | |
612 } | |
613 | |
614 void TracingControllerImpl::OnTraceDataCollected( | |
615 const scoped_refptr<base::RefCountedString>& events_str_ptr) { | |
616 // OnTraceDataCollected may be called from any browser thread, either by the | |
617 // local event trace system or from child processes via TraceMessageFilter. | |
618 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
619 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
620 base::Bind(&TracingControllerImpl::OnTraceDataCollected, | |
621 base::Unretained(this), events_str_ptr)); | |
622 return; | |
623 } | |
624 | |
625 if (trace_data_sink_.get()) | |
626 trace_data_sink_->AddTraceChunk(events_str_ptr->data()); | |
627 } | |
628 | |
629 void TracingControllerImpl::OnLocalTraceDataCollected( | |
630 const scoped_refptr<base::RefCountedString>& events_str_ptr, | |
631 bool has_more_events) { | |
632 if (events_str_ptr->data().size()) | |
633 OnTraceDataCollected(events_str_ptr); | |
634 | |
635 if (has_more_events) | |
636 return; | |
637 | |
638 // Simulate an StopTracingAcked for the local trace. | |
639 std::vector<std::string> category_groups; | |
640 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups); | |
641 OnStopTracingAcked(NULL, category_groups); | |
642 } | |
643 | |
644 void TracingControllerImpl::OnTraceLogStatusReply( | |
645 TraceMessageFilter* trace_message_filter, | |
646 const base::trace_event::TraceLogStatus& status) { | |
647 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
648 BrowserThread::PostTask( | |
649 BrowserThread::UI, FROM_HERE, | |
650 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply, | |
651 base::Unretained(this), | |
652 base::RetainedRef(trace_message_filter), status)); | |
653 return; | |
654 } | |
655 | |
656 if (pending_trace_log_status_ack_count_ == 0) | |
657 return; | |
658 | |
659 if (trace_message_filter && | |
660 !pending_trace_log_status_filters_.erase(trace_message_filter)) { | |
661 // The response from the specified message filter has already been received. | |
662 return; | |
663 } | |
664 | |
665 float percent_full = static_cast<float>( | |
666 static_cast<double>(status.event_count) / status.event_capacity); | |
667 maximum_trace_buffer_usage_ = | |
668 std::max(maximum_trace_buffer_usage_, percent_full); | |
669 approximate_event_count_ += status.event_count; | |
670 | |
671 if (--pending_trace_log_status_ack_count_ == 0) { | |
672 // Trigger callback if one is set. | |
673 pending_trace_buffer_usage_callback_.Run(maximum_trace_buffer_usage_, | |
674 approximate_event_count_); | |
675 pending_trace_buffer_usage_callback_.Reset(); | |
676 } | |
677 } | |
678 | |
679 void TracingControllerImpl::RegisterTracingUI(TracingUI* tracing_ui) { | 221 void TracingControllerImpl::RegisterTracingUI(TracingUI* tracing_ui) { |
680 DCHECK(tracing_uis_.find(tracing_ui) == tracing_uis_.end()); | 222 DCHECK(tracing_uis_.find(tracing_ui) == tracing_uis_.end()); |
681 tracing_uis_.insert(tracing_ui); | 223 tracing_uis_.insert(tracing_ui); |
682 } | 224 } |
683 | 225 |
684 void TracingControllerImpl::UnregisterTracingUI(TracingUI* tracing_ui) { | 226 void TracingControllerImpl::UnregisterTracingUI(TracingUI* tracing_ui) { |
685 std::set<TracingUI*>::iterator it = tracing_uis_.find(tracing_ui); | 227 std::set<TracingUI*>::iterator it = tracing_uis_.find(tracing_ui); |
686 DCHECK(it != tracing_uis_.end()); | 228 DCHECK(it != tracing_uis_.end()); |
687 tracing_uis_.erase(it); | 229 tracing_uis_.erase(it); |
688 } | 230 } |
689 | 231 |
690 std::string TracingControllerImpl::GetTracingAgentName() { | |
691 return kChromeTracingAgentName; | |
692 } | |
693 | |
694 std::string TracingControllerImpl::GetTraceEventLabel() { | |
695 return kChromeTraceLabel; | |
696 } | |
697 | |
698 void TracingControllerImpl::StartAgentTracing( | |
699 const base::trace_event::TraceConfig& trace_config, | |
700 const StartAgentTracingCallback& callback) { | |
701 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
702 | |
703 base::Closure on_agent_started = | |
704 base::Bind(callback, kChromeTracingAgentName, true); | |
705 if (!BrowserThread::PostTask( | |
706 BrowserThread::FILE, FROM_HERE, | |
707 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread, | |
708 base::Unretained(this), trace_config, | |
709 on_agent_started))) { | |
710 // BrowserThread::PostTask fails if the threads haven't been created yet, | |
711 // so it should be safe to just use TraceLog::SetEnabled directly. | |
712 TraceLog::GetInstance()->SetEnabled(trace_config, enabled_tracing_modes_); | |
713 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, on_agent_started); | |
714 } | |
715 } | |
716 | |
717 void TracingControllerImpl::StopAgentTracing( | |
718 const StopAgentTracingCallback& callback) { | |
719 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
720 // Handle special case of zero child processes by immediately flushing the | |
721 // trace log. Once the flush has completed the caller will be notified that | |
722 // tracing has ended. | |
723 if (pending_stop_tracing_ack_count_ == 1) { | |
724 // Flush/cancel asynchronously now, because we don't have any children to | |
725 // wait for. | |
726 if (trace_data_sink_) { | |
727 TraceLog::GetInstance()->Flush( | |
728 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected, | |
729 base::Unretained(this)), | |
730 true); | |
731 } else { | |
732 TraceLog::GetInstance()->CancelTracing( | |
733 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected, | |
734 base::Unretained(this))); | |
735 } | |
736 } | |
737 | |
738 // Notify all child processes. | |
739 for (auto it : trace_message_filters_) { | |
740 if (trace_data_sink_) | |
741 it->SendEndTracing(); | |
742 else | |
743 it->SendCancelTracing(); | |
744 } | |
745 } | |
746 | |
747 bool TracingControllerImpl::SupportsExplicitClockSync() { | |
748 return true; | |
749 } | |
750 | |
751 void TracingControllerImpl::RecordClockSyncMarker( | |
752 const std::string& sync_id, | |
753 const RecordClockSyncMarkerCallback& callback) { | |
754 DCHECK(SupportsExplicitClockSync()); | |
755 | |
756 TRACE_EVENT_CLOCK_SYNC_RECEIVER(sync_id); | |
757 } | |
758 | |
759 void TracingControllerImpl::IssueClockSyncMarker() { | |
760 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
761 DCHECK_EQ(0, pending_clock_sync_ack_count_); | |
762 | |
763 for (auto* it : additional_tracing_agents_) { | |
764 if (it->SupportsExplicitClockSync()) { | |
765 it->RecordClockSyncMarker( | |
766 base::GenerateGUID(), | |
767 base::Bind(&TracingControllerImpl::OnClockSyncMarkerRecordedByAgent, | |
768 base::Unretained(this))); | |
769 pending_clock_sync_ack_count_++; | |
770 } | |
771 } | |
772 | |
773 // If no clock sync is needed, stop tracing right away. Otherwise, schedule | |
774 // to stop tracing after timeout. | |
775 if (pending_clock_sync_ack_count_ == 0) { | |
776 StopTracingAfterClockSync(); | |
777 } else { | |
778 clock_sync_timer_.Start( | |
779 FROM_HERE, base::TimeDelta::FromSeconds(kIssueClockSyncTimeoutSeconds), | |
780 this, &TracingControllerImpl::StopTracingAfterClockSync); | |
781 } | |
782 } | |
783 | |
784 void TracingControllerImpl::OnClockSyncMarkerRecordedByAgent( | |
785 const std::string& sync_id, | |
786 const base::TimeTicks& issue_ts, | |
787 const base::TimeTicks& issue_end_ts) { | |
788 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
789 | |
790 // TODO(charliea): Change this function so that it can accept a boolean | |
791 // success indicator instead of having to rely on sentinel issue_ts and | |
792 // issue_end_ts values to signal failure. | |
793 if (!(issue_ts == base::TimeTicks() || issue_end_ts == base::TimeTicks())) | |
794 TRACE_EVENT_CLOCK_SYNC_ISSUER(sync_id, issue_ts, issue_end_ts); | |
795 | |
796 // Timer is not running means that clock sync already timed out. | |
797 if (!clock_sync_timer_.IsRunning()) | |
798 return; | |
799 | |
800 // Stop tracing only if all agents report back. | |
801 if (--pending_clock_sync_ack_count_ == 0) { | |
802 clock_sync_timer_.Stop(); | |
803 StopTracingAfterClockSync(); | |
804 } | |
805 } | |
806 | |
807 void TracingControllerImpl::AddFilteredMetadata( | |
808 TracingController::TraceDataSink* sink, | |
809 std::unique_ptr<base::DictionaryValue> metadata, | |
810 const MetadataFilterPredicate& filter) { | |
811 if (filter.is_null()) { | |
812 sink->AddMetadata(std::move(metadata)); | |
813 return; | |
814 } | |
815 std::unique_ptr<base::DictionaryValue> filtered_metadata( | |
816 new base::DictionaryValue); | |
817 for (base::DictionaryValue::Iterator it(*metadata); !it.IsAtEnd(); | |
818 it.Advance()) { | |
819 if (filter.Run(it.key())) | |
820 filtered_metadata->Set(it.key(), it.value().DeepCopy()); | |
821 else | |
822 filtered_metadata->SetString(it.key(), "__stripped__"); | |
823 } | |
824 sink->AddMetadata(std::move(filtered_metadata)); | |
825 } | |
826 | |
827 std::unique_ptr<base::DictionaryValue> | |
828 TracingControllerImpl::GenerateTracingMetadataDict() const { | |
829 // It's important that this function creates a new metadata dict and returns | |
830 // it rather than directly populating the metadata_ member, as the data may | |
831 // need filtering in some cases. | |
832 std::unique_ptr<base::DictionaryValue> metadata_dict( | |
833 new base::DictionaryValue()); | |
834 | |
835 metadata_dict->SetString("network-type", GetNetworkTypeString()); | |
836 metadata_dict->SetString("product-version", GetContentClient()->GetProduct()); | |
837 metadata_dict->SetString("v8-version", V8_VERSION_STRING); | |
838 metadata_dict->SetString("user-agent", GetContentClient()->GetUserAgent()); | |
839 | |
840 // OS | |
841 #if defined(OS_CHROMEOS) | |
842 metadata_dict->SetString("os-name", "CrOS"); | |
843 int32_t major_version; | |
844 int32_t minor_version; | |
845 int32_t bugfix_version; | |
846 // OperatingSystemVersion only has a POSIX implementation which returns the | |
847 // wrong versions for CrOS. | |
848 base::SysInfo::OperatingSystemVersionNumbers(&major_version, &minor_version, | |
849 &bugfix_version); | |
850 metadata_dict->SetString( | |
851 "os-version", base::StringPrintf("%d.%d.%d", major_version, minor_version, | |
852 bugfix_version)); | |
853 #else | |
854 metadata_dict->SetString("os-name", base::SysInfo::OperatingSystemName()); | |
855 metadata_dict->SetString("os-version", | |
856 base::SysInfo::OperatingSystemVersion()); | |
857 #endif | |
858 metadata_dict->SetString("os-arch", | |
859 base::SysInfo::OperatingSystemArchitecture()); | |
860 | |
861 // CPU | |
862 base::CPU cpu; | |
863 metadata_dict->SetInteger("cpu-family", cpu.family()); | |
864 metadata_dict->SetInteger("cpu-model", cpu.model()); | |
865 metadata_dict->SetInteger("cpu-stepping", cpu.stepping()); | |
866 metadata_dict->SetInteger("num-cpus", base::SysInfo::NumberOfProcessors()); | |
867 metadata_dict->SetInteger("physical-memory", | |
868 base::SysInfo::AmountOfPhysicalMemoryMB()); | |
869 | |
870 std::string cpu_brand = cpu.cpu_brand(); | |
871 // Workaround for crbug.com/249713. | |
872 // TODO(oysteine): Remove workaround when bug is fixed. | |
873 size_t null_pos = cpu_brand.find('\0'); | |
874 if (null_pos != std::string::npos) | |
875 cpu_brand.erase(null_pos); | |
876 metadata_dict->SetString("cpu-brand", cpu_brand); | |
877 | |
878 // GPU | |
879 gpu::GPUInfo gpu_info = content::GpuDataManager::GetInstance()->GetGPUInfo(); | |
880 | |
881 #if !defined(OS_ANDROID) | |
882 metadata_dict->SetInteger("gpu-venid", gpu_info.gpu.vendor_id); | |
883 metadata_dict->SetInteger("gpu-devid", gpu_info.gpu.device_id); | |
884 #endif | |
885 | |
886 metadata_dict->SetString("gpu-driver", gpu_info.driver_version); | |
887 metadata_dict->SetString("gpu-psver", gpu_info.pixel_shader_version); | |
888 metadata_dict->SetString("gpu-vsver", gpu_info.vertex_shader_version); | |
889 | |
890 #if defined(OS_MACOSX) | |
891 metadata_dict->SetString("gpu-glver", gpu_info.gl_version); | |
892 #elif defined(OS_POSIX) | |
893 metadata_dict->SetString("gpu-gl-vendor", gpu_info.gl_vendor); | |
894 metadata_dict->SetString("gpu-gl-renderer", gpu_info.gl_renderer); | |
895 #endif | |
896 | |
897 std::unique_ptr<TracingDelegate> delegate( | |
898 GetContentClient()->browser()->GetTracingDelegate()); | |
899 if (delegate) | |
900 delegate->GenerateMetadataDict(metadata_dict.get()); | |
901 | |
902 metadata_dict->SetString("clock-domain", GetClockString()); | |
903 metadata_dict->SetBoolean("highres-ticks", | |
904 base::TimeTicks::IsHighResolution()); | |
905 | |
906 metadata_dict->SetString("trace-config", trace_config_->ToString()); | |
907 | |
908 metadata_dict->SetString( | |
909 "command_line", | |
910 base::CommandLine::ForCurrentProcess()->GetCommandLineString()); | |
911 | |
912 base::Time::Exploded ctime; | |
913 base::Time::Now().UTCExplode(&ctime); | |
914 std::string time_string = base::StringPrintf( | |
915 "%u-%u-%u %d:%d:%d", ctime.year, ctime.month, ctime.day_of_month, | |
916 ctime.hour, ctime.minute, ctime.second); | |
917 metadata_dict->SetString("trace-capture-datetime", time_string); | |
918 | |
919 return metadata_dict; | |
920 } | |
921 | |
922 void TracingControllerImpl::AddTraceMessageFilterObserver( | 232 void TracingControllerImpl::AddTraceMessageFilterObserver( |
923 TraceMessageFilterObserver* observer) { | 233 TraceMessageFilterObserver* observer) { |
924 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 234 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
925 trace_message_filter_observers_.AddObserver(observer); | 235 trace_message_filter_observers_.AddObserver(observer); |
926 | 236 |
927 for (auto& filter : trace_message_filters_) | 237 for (auto& filter : trace_message_filters_) |
928 observer->OnTraceMessageFilterAdded(filter.get()); | 238 observer->OnTraceMessageFilterAdded(filter.get()); |
929 } | 239 } |
930 | 240 |
931 void TracingControllerImpl::RemoveTraceMessageFilterObserver( | 241 void TracingControllerImpl::RemoveTraceMessageFilterObserver( |
932 TraceMessageFilterObserver* observer) { | 242 TraceMessageFilterObserver* observer) { |
933 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 243 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
934 trace_message_filter_observers_.RemoveObserver(observer); | 244 trace_message_filter_observers_.RemoveObserver(observer); |
935 | 245 |
936 for (auto& filter : trace_message_filters_) | 246 for (auto& filter : trace_message_filters_) |
937 observer->OnTraceMessageFilterRemoved(filter.get()); | 247 observer->OnTraceMessageFilterRemoved(filter.get()); |
938 } | 248 } |
939 | 249 |
| 250 void TracingControllerImpl::OnDataAvailable(const void* data, |
| 251 size_t num_bytes) { |
| 252 if (trace_data_sink_.get()) { |
| 253 const std::string chunk(static_cast<const char*>(data), num_bytes); |
| 254 trace_data_sink_->AddTraceChunk(chunk); |
| 255 } |
| 256 } |
| 257 |
| 258 void TracingControllerImpl::OnDataComplete() { |
| 259 is_tracing_ = false; |
| 260 if (trace_data_sink_.get()) { |
| 261 trace_data_sink_->Close(); |
| 262 trace_data_sink_ = NULL; |
| 263 } |
| 264 } |
| 265 |
940 } // namespace content | 266 } // namespace content |
OLD | NEW |