Chromium Code Reviews| 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 "content/browser/tracing/tracing_controller_impl.h" | 5 #include "content/browser/tracing/tracing_controller_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/debug/trace_event.h" | |
| 8 #include "base/file_util.h" | 9 #include "base/file_util.h" |
| 9 #include "base/json/string_escape.h" | 10 #include "base/values.h" |
| 10 #include "base/strings/string_number_conversions.h" | |
| 11 #include "base/threading/thread_restrictions.h" | |
| 12 #include "content/browser/tracing/trace_message_filter.h" | 11 #include "content/browser/tracing/trace_message_filter.h" |
| 13 #include "content/common/child_process_messages.h" | 12 #include "content/common/child_process_messages.h" |
| 14 #include "content/public/browser/browser_message_filter.h" | 13 #include "content/public/browser/browser_message_filter.h" |
| 15 #include "content/public/common/content_switches.h" | 14 #include "content/public/common/content_switches.h" |
| 16 | 15 |
| 17 using base::debug::TraceLog; | 16 using base::debug::TraceLog; |
| 18 | 17 |
| 19 namespace content { | 18 namespace content { |
| 20 | 19 |
| 21 namespace { | 20 namespace { |
| 22 | 21 |
| 23 base::LazyInstance<TracingControllerImpl>::Leaky g_controller = | 22 base::LazyInstance<TracingControllerImpl>::Leaky g_controller = |
| 24 LAZY_INSTANCE_INITIALIZER; | 23 LAZY_INSTANCE_INITIALIZER; |
| 25 | 24 |
| 25 // The keys of tracing parameters in JSON. Must keep consistent with | |
| 26 // third_party/trace-viewer/src/about_tracing/begin_recording.js. | |
| 27 const char kCategoryFilter[] = "categoryFilter"; | |
| 28 const char kUseSystemTracing[] = "useSystemTracing"; | |
| 29 const char kUseContinuousTracing[] = "useContinuousTracing"; | |
| 30 const char kUseSampling[] = "useSampling"; | |
| 31 | |
| 26 } // namespace | 32 } // namespace |
| 27 | 33 |
| 28 TracingController* TracingController::GetInstance() { | 34 TracingController* TracingController::GetInstance() { |
| 29 return TracingControllerImpl::GetInstance(); | 35 return TracingControllerImpl::GetInstance(); |
| 30 } | 36 } |
| 31 | 37 |
| 32 class TracingControllerImpl::ResultFile { | 38 class TracingControllerImpl::ResultFile { |
| 33 public: | 39 public: |
| 34 ResultFile(const base::FilePath& path); | 40 ResultFile(const base::FilePath& path); |
| 35 void Write(const scoped_refptr<base::RefCountedString>& events_str_ptr) { | 41 void Write(const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 111 | 117 |
| 112 | 118 |
| 113 TracingControllerImpl::TracingControllerImpl() : | 119 TracingControllerImpl::TracingControllerImpl() : |
| 114 pending_disable_recording_ack_count_(0), | 120 pending_disable_recording_ack_count_(0), |
| 115 pending_capture_monitoring_snapshot_ack_count_(0), | 121 pending_capture_monitoring_snapshot_ack_count_(0), |
| 116 pending_trace_buffer_percent_full_ack_count_(0), | 122 pending_trace_buffer_percent_full_ack_count_(0), |
| 117 maximum_trace_buffer_percent_full_(0), | 123 maximum_trace_buffer_percent_full_(0), |
| 118 // Tracing may have been enabled by ContentMainRunner if kTraceStartup | 124 // Tracing may have been enabled by ContentMainRunner if kTraceStartup |
| 119 // is specified in command line. | 125 // is specified in command line. |
| 120 is_recording_(TraceLog::GetInstance()->IsEnabled()), | 126 is_recording_(TraceLog::GetInstance()->IsEnabled()), |
| 121 is_monitoring_(false), | 127 is_monitoring_(false) { |
| 122 category_filter_( | |
| 123 base::debug::CategoryFilter::kDefaultCategoryFilterString) { | |
| 124 } | 128 } |
| 125 | 129 |
| 126 TracingControllerImpl::~TracingControllerImpl() { | 130 TracingControllerImpl::~TracingControllerImpl() { |
| 127 // This is a Leaky instance. | 131 // This is a Leaky instance. |
| 128 NOTREACHED(); | 132 NOTREACHED(); |
| 129 } | 133 } |
| 130 | 134 |
| 131 TracingControllerImpl* TracingControllerImpl::GetInstance() { | 135 TracingControllerImpl* TracingControllerImpl::GetInstance() { |
| 132 return g_controller.Pointer(); | 136 return g_controller.Pointer(); |
| 133 } | 137 } |
| 134 | 138 |
| 135 void TracingControllerImpl::GetCategories( | 139 void TracingControllerImpl::GetCategories( |
| 136 const GetCategoriesDoneCallback& callback) { | 140 const GetCategoriesDoneCallback& callback) { |
| 137 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 141 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 138 | 142 |
| 139 // Known categories come back from child processes with the EndTracingAck | 143 // Known categories come back from child processes with the EndTracingAck |
| 140 // message. So to get known categories, just begin and end tracing immediately | 144 // message. So to get known categories, just begin and end tracing immediately |
| 141 // afterwards. This will ping all the child processes for categories. | 145 // afterwards. This will ping all the child processes for categories. |
| 142 pending_get_categories_done_callback_ = callback; | 146 pending_get_categories_done_callback_ = callback; |
| 143 EnableRecording(base::debug::CategoryFilter("*"), | 147 EnableRecording("*", TracingController::Options(), |
| 144 TracingController::Options(), | |
| 145 EnableRecordingDoneCallback()); | 148 EnableRecordingDoneCallback()); |
| 146 DisableRecording(base::FilePath(), TracingFileResultCallback()); | 149 DisableRecording(base::FilePath(), TracingFileResultCallback()); |
| 147 } | 150 } |
| 148 | 151 |
| 149 bool TracingControllerImpl::EnableRecording( | 152 bool TracingControllerImpl::EnableRecording( |
| 150 const base::debug::CategoryFilter& filter, | 153 const std::string& category_filter, |
| 151 TracingController::Options options, | 154 TracingController::Options options, |
| 152 const EnableRecordingDoneCallback& callback) { | 155 const EnableRecordingDoneCallback& callback) { |
| 153 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 154 | 157 |
| 155 if (!can_enable_recording()) | 158 if (!can_enable_recording()) |
| 156 return false; | 159 return false; |
| 157 | 160 |
| 158 #if defined(OS_ANDROID) | 161 #if defined(OS_ANDROID) |
| 159 if (pending_get_categories_done_callback_.is_null()) | 162 if (pending_get_categories_done_callback_.is_null()) |
| 160 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); | 163 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); |
| 161 #endif | 164 #endif |
| 162 | 165 |
| 163 TraceLog::Options trace_options = (options & RECORD_CONTINUOUSLY) ? | 166 TraceLog::Options trace_options = (options & RECORD_CONTINUOUSLY) ? |
| 164 TraceLog::RECORD_CONTINUOUSLY : TraceLog::RECORD_UNTIL_FULL; | 167 TraceLog::RECORD_CONTINUOUSLY : TraceLog::RECORD_UNTIL_FULL; |
| 165 if (options & ENABLE_SAMPLING) { | 168 if (options & ENABLE_SAMPLING) { |
| 166 trace_options = static_cast<TraceLog::Options>( | 169 trace_options = static_cast<TraceLog::Options>( |
| 167 trace_options | TraceLog::ENABLE_SAMPLING); | 170 trace_options | TraceLog::ENABLE_SAMPLING); |
| 168 } | 171 } |
| 169 // TODO(haraken): How to handle ENABLE_SYSTRACE? | 172 // TODO(haraken): How to handle ENABLE_SYSTRACE? |
| 170 | 173 |
| 171 TraceLog::GetInstance()->SetEnabled(filter, trace_options); | 174 TraceLog::GetInstance()->SetEnabled( |
| 175 base::debug::CategoryFilter(category_filter), trace_options); | |
| 172 is_recording_ = true; | 176 is_recording_ = true; |
| 173 category_filter_ = TraceLog::GetInstance()->GetCurrentCategoryFilter(); | |
| 174 | 177 |
| 175 // Notify all child processes. | 178 // Notify all child processes. |
| 176 for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { | 179 for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); |
| 177 it->get()->SendBeginTracing(category_filter_.ToString(), trace_options); | 180 it != trace_message_filters_.end(); ++it) { |
| 181 it->get()->SendBeginTracing(category_filter, trace_options); | |
| 178 } | 182 } |
| 179 | 183 |
| 180 if (!callback.is_null()) | 184 if (!callback.is_null()) |
| 181 callback.Run(); | 185 callback.Run(); |
| 182 return true; | 186 return true; |
| 183 } | 187 } |
| 184 | 188 |
| 185 bool TracingControllerImpl::DisableRecording( | 189 bool TracingControllerImpl::DisableRecording( |
| 186 const base::FilePath& result_file_path, | 190 const base::FilePath& result_file_path, |
| 187 const TracingFileResultCallback& callback) { | 191 const TracingFileResultCallback& callback) { |
| 188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 192 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 189 | 193 |
| 190 if (!can_disable_recording()) | 194 if (!can_disable_recording()) |
| 191 return false; | 195 return false; |
| 192 | 196 |
| 193 pending_disable_recording_done_callback_ = callback; | 197 pending_disable_recording_done_callback_ = callback; |
| 194 | 198 |
| 195 // Disable local trace early to avoid traces during end-tracing process from | 199 // Disable local trace early to avoid traces during end-tracing process from |
| 196 // interfering with the process. | 200 // interfering with the process. |
| 197 TraceLog::GetInstance()->SetDisabled(); | 201 TraceLog::GetInstance()->SetDisabled(); |
| 198 | 202 |
| 199 #if defined(OS_ANDROID) | 203 #if defined(OS_ANDROID) |
| 200 if (pending_get_categories_done_callback_.is_null()) | 204 if (pending_get_categories_done_callback_.is_null()) |
| 201 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); | 205 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); |
| 202 #endif | 206 #endif |
| 203 | 207 |
| 204 if (!callback.is_null() || !result_file_path.empty()) | 208 if (!callback.is_null() || !result_file_path.empty()) |
| 205 result_file_.reset(new ResultFile(result_file_path)); | 209 result_file_.reset(new ResultFile(result_file_path)); |
| 206 | 210 |
| 207 // There could be a case where there are no child processes and filters_ | |
| 208 // is empty. In that case we can immediately tell the subscriber that tracing | |
| 209 // has ended. To avoid recursive calls back to the subscriber, we will just | |
| 210 // use the existing asynchronous OnDisableRecordingAcked code. | |
| 211 // Count myself (local trace) in pending_disable_recording_ack_count_, | 211 // Count myself (local trace) in pending_disable_recording_ack_count_, |
| 212 // acked below. | 212 // acked below. |
| 213 pending_disable_recording_ack_count_ = filters_.size() + 1; | 213 pending_disable_recording_ack_count_ = trace_message_filters_.size() + 1; |
| 214 | 214 |
| 215 // Handle special case of zero child processes. | 215 // Handle special case of zero child processes by immediately telling the |
| 216 // caller that tracing has ended. Use asynchronous OnDisableRecordingAcked | |
| 217 // to avoid recursive call back to the caller. | |
| 216 if (pending_disable_recording_ack_count_ == 1) { | 218 if (pending_disable_recording_ack_count_ == 1) { |
| 217 // Ack asynchronously now, because we don't have any children to wait for. | 219 // Ack asynchronously now, because we don't have any children to wait for. |
| 218 std::vector<std::string> category_groups; | 220 std::vector<std::string> category_groups; |
| 219 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups); | 221 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups); |
| 220 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 222 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 221 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked, | 223 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked, |
| 222 base::Unretained(this), category_groups)); | 224 base::Unretained(this), category_groups)); |
| 223 } | 225 } |
| 224 | 226 |
| 225 // Notify all child processes. | 227 // Notify all child processes. |
| 226 for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { | 228 for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); |
| 229 it != trace_message_filters_.end(); ++it) { | |
| 227 it->get()->SendEndTracing(); | 230 it->get()->SendEndTracing(); |
| 228 } | 231 } |
| 229 return true; | 232 return true; |
| 230 } | 233 } |
| 231 | 234 |
| 232 bool TracingControllerImpl::EnableMonitoring( | 235 bool TracingControllerImpl::EnableMonitoring( |
| 233 const base::debug::CategoryFilter& filter, | 236 const std::string& category_filter, |
| 234 TracingController::Options options, | 237 TracingController::Options options, |
| 235 const EnableMonitoringDoneCallback& callback) { | 238 const EnableMonitoringDoneCallback& callback) { |
| 236 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 237 | 240 |
| 238 if (!can_enable_monitoring()) | 241 if (!can_enable_monitoring()) |
| 239 return false; | 242 return false; |
| 240 is_monitoring_ = true; | 243 is_monitoring_ = true; |
| 241 | 244 |
| 242 #if defined(OS_ANDROID) | 245 #if defined(OS_ANDROID) |
| 243 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); | 246 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); |
| 244 #endif | 247 #endif |
| 245 | 248 |
| 246 int monitoring_tracing_options = 0; | 249 int monitoring_tracing_options = 0; |
| 247 if (options & ENABLE_SAMPLING) | 250 if (options & ENABLE_SAMPLING) |
| 248 monitoring_tracing_options |= base::debug::TraceLog::MONITOR_SAMPLING; | 251 monitoring_tracing_options |= base::debug::TraceLog::MONITOR_SAMPLING; |
| 249 | 252 |
| 250 // Notify all child processes. | 253 // Notify all child processes. |
| 251 for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { | 254 for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); |
| 252 it->get()->SendEnableMonitoring(filter.ToString(), | 255 it != trace_message_filters_.end(); ++it) { |
| 256 it->get()->SendEnableMonitoring(category_filter, | |
| 253 base::debug::TraceLog::Options(monitoring_tracing_options)); | 257 base::debug::TraceLog::Options(monitoring_tracing_options)); |
| 254 } | 258 } |
| 255 | 259 |
| 256 if (!callback.is_null()) | 260 if (!callback.is_null()) |
| 257 callback.Run(); | 261 callback.Run(); |
| 258 return true; | 262 return true; |
| 259 } | 263 } |
| 260 | 264 |
| 261 bool TracingControllerImpl::DisableMonitoring( | 265 bool TracingControllerImpl::DisableMonitoring( |
| 262 const DisableMonitoringDoneCallback& callback) { | 266 const DisableMonitoringDoneCallback& callback) { |
| 263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 264 | 268 |
| 265 if (!can_disable_monitoring()) | 269 if (!can_disable_monitoring()) |
| 266 return false; | 270 return false; |
| 267 is_monitoring_ = false; | 271 is_monitoring_ = false; |
| 268 | 272 |
| 269 // Notify all child processes. | 273 // Notify all child processes. |
| 270 for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { | 274 for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); |
| 275 it != trace_message_filters_.end(); ++it) { | |
| 271 it->get()->SendDisableMonitoring(); | 276 it->get()->SendDisableMonitoring(); |
| 272 } | 277 } |
| 273 | 278 |
| 274 if (!callback.is_null()) | 279 if (!callback.is_null()) |
| 275 callback.Run(); | 280 callback.Run(); |
| 276 return true; | 281 return true; |
| 277 } | 282 } |
| 278 | 283 |
| 279 void TracingControllerImpl::GetMonitoringStatus( | 284 void TracingControllerImpl::GetMonitoringStatus( |
| 280 bool* out_enabled, | 285 bool* out_enabled, |
| 281 base::debug::CategoryFilter* out_filter, | 286 std::string* out_category_filter, |
| 282 TracingController::Options* out_options) { | 287 TracingController::Options* out_options) { |
| 283 NOTIMPLEMENTED(); | 288 NOTIMPLEMENTED(); |
| 284 } | 289 } |
| 285 | 290 |
| 286 void TracingControllerImpl::CaptureMonitoringSnapshot( | 291 void TracingControllerImpl::CaptureMonitoringSnapshot( |
| 287 const base::FilePath& result_file_path, | 292 const base::FilePath& result_file_path, |
| 288 const TracingFileResultCallback& callback) { | 293 const TracingFileResultCallback& callback) { |
| 289 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 290 | 295 |
| 291 if (!can_disable_monitoring()) | 296 if (!can_disable_monitoring()) |
| 292 return; | 297 return; |
| 293 | 298 |
| 294 pending_capture_monitoring_snapshot_done_callback_ = callback; | 299 pending_capture_monitoring_snapshot_done_callback_ = callback; |
| 295 | 300 |
| 296 if (!callback.is_null() || !result_file_path.empty()) | 301 if (!callback.is_null() || !result_file_path.empty()) |
| 297 monitoring_snapshot_file_.reset(new ResultFile(result_file_path)); | 302 monitoring_snapshot_file_.reset(new ResultFile(result_file_path)); |
| 298 | 303 |
| 299 // There could be a case where there are no child processes and filters_ | |
| 300 // is empty. In that case we can immediately tell the subscriber that tracing | |
| 301 // has ended. To avoid recursive calls back to the subscriber, we will just | |
| 302 // use the existing asynchronous OnCaptureMonitoringSnapshotAcked code. | |
| 303 // Count myself in pending_capture_monitoring_snapshot_ack_count_, | 304 // Count myself in pending_capture_monitoring_snapshot_ack_count_, |
| 304 // acked below. | 305 // acked below. |
| 305 pending_capture_monitoring_snapshot_ack_count_ = filters_.size() + 1; | 306 pending_capture_monitoring_snapshot_ack_count_ = |
| 307 trace_message_filters_.size() + 1; | |
| 306 | 308 |
| 307 // Handle special case of zero child processes. | 309 // Handle special case of zero child processes by immediately telling the |
| 310 // caller that capturing snapshot has ended. Use asynchronous | |
| 311 // OnCaptureMonitoringSnapshotAcked to avoid recursive call back to the | |
| 312 // caller. | |
| 308 if (pending_capture_monitoring_snapshot_ack_count_ == 1) { | 313 if (pending_capture_monitoring_snapshot_ack_count_ == 1) { |
| 309 // Ack asynchronously now, because we don't have any children to wait for. | 314 // Ack asynchronously now, because we don't have any children to wait for. |
| 310 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 315 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 311 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked, | 316 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked, |
| 312 base::Unretained(this))); | 317 base::Unretained(this))); |
| 313 } | 318 } |
| 314 | 319 |
| 315 // Notify all child processes. | 320 // Notify all child processes. |
| 316 for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { | 321 for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); |
| 322 it != trace_message_filters_.end(); ++it) { | |
| 317 it->get()->SendCaptureMonitoringSnapshot(); | 323 it->get()->SendCaptureMonitoringSnapshot(); |
| 318 } | 324 } |
| 319 | 325 |
| 320 #if defined(OS_ANDROID) | 326 #if defined(OS_ANDROID) |
| 321 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); | 327 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); |
| 322 #endif | 328 #endif |
| 323 } | 329 } |
| 324 | 330 |
| 325 bool TracingControllerImpl::GetTraceBufferPercentFull( | 331 bool TracingControllerImpl::GetTraceBufferPercentFull( |
| 326 const GetTraceBufferPercentFullCallback& callback) { | 332 const GetTraceBufferPercentFullCallback& callback) { |
| 327 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 333 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 328 | 334 |
| 329 if (!can_get_trace_buffer_percent_full() || callback.is_null()) | 335 if (!can_get_trace_buffer_percent_full() || callback.is_null()) |
| 330 return false; | 336 return false; |
| 331 | 337 |
| 332 pending_trace_buffer_percent_full_callback_ = callback; | 338 pending_trace_buffer_percent_full_callback_ = callback; |
| 333 | 339 |
| 334 // Count myself in pending_trace_buffer_percent_full_ack_count_, acked below. | 340 // Count myself in pending_trace_buffer_percent_full_ack_count_, acked below. |
| 335 pending_trace_buffer_percent_full_ack_count_ = filters_.size() + 1; | 341 pending_trace_buffer_percent_full_ack_count_ = |
| 342 trace_message_filters_.size() + 1; | |
| 336 | 343 |
| 337 // Handle special case of zero child processes. | 344 // Handle special case of zero child processes. |
| 338 if (pending_trace_buffer_percent_full_ack_count_ == 1) { | 345 if (pending_trace_buffer_percent_full_ack_count_ == 1) { |
| 339 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 346 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 340 base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply, | 347 base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply, |
| 341 base::Unretained(this), | 348 base::Unretained(this), |
| 342 TraceLog::GetInstance()->GetBufferPercentFull())); | 349 TraceLog::GetInstance()->GetBufferPercentFull())); |
| 343 } | 350 } |
| 344 | 351 |
| 345 // Notify all child processes. | 352 // Notify all child processes. |
| 346 for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { | 353 for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); |
| 354 it != trace_message_filters_.end(); ++it) { | |
| 347 it->get()->SendGetTraceBufferPercentFull(); | 355 it->get()->SendGetTraceBufferPercentFull(); |
| 348 } | 356 } |
| 349 return true; | 357 return true; |
| 350 } | 358 } |
| 351 | 359 |
| 352 void TracingControllerImpl::AddFilter(TraceMessageFilter* filter) { | 360 bool TracingControllerImpl::SetWatchEvent( |
| 361 const std::string& category_name, | |
| 362 const std::string& event_name, | |
| 363 const WatchEventCallback& callback) { | |
| 364 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 365 | |
| 366 if (!can_set_watch_event() || callback.is_null()) | |
| 367 return false; | |
| 368 | |
| 369 watch_event_callback_ = callback; | |
| 370 | |
| 371 for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); | |
| 372 it != trace_message_filters_.end(); ++it) { | |
| 373 it->get()->SendSetWatchEvent(category_name, event_name); | |
| 374 } | |
| 375 return true; | |
| 376 } | |
| 377 | |
| 378 bool TracingControllerImpl::CancelWatchEvent() { | |
| 379 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 380 | |
| 381 if (!can_cancel_watch_event()) | |
| 382 return false; | |
| 383 | |
| 384 for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); | |
| 385 it != trace_message_filters_.end(); ++it) { | |
| 386 it->get()->SendCancelWatchEvent(); | |
| 387 } | |
| 388 | |
| 389 watch_event_callback_.Reset(); | |
| 390 return true; | |
| 391 } | |
| 392 | |
| 393 void TracingControllerImpl::AddTraceMessageFilter( | |
| 394 TraceMessageFilter* trace_message_filter) { | |
| 353 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 395 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 354 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 396 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 355 base::Bind(&TracingControllerImpl::AddFilter, base::Unretained(this), | 397 base::Bind(&TracingControllerImpl::AddTraceMessageFilter, |
| 356 make_scoped_refptr(filter))); | 398 base::Unretained(this), |
| 399 make_scoped_refptr(trace_message_filter))); | |
| 357 return; | 400 return; |
| 358 } | 401 } |
| 359 | 402 |
| 360 filters_.insert(filter); | 403 trace_message_filters_.insert(trace_message_filter); |
| 361 if (can_disable_recording()) { | 404 if (can_disable_recording()) { |
| 362 std::string cf_str = category_filter_.ToString(); | 405 trace_message_filter->SendBeginTracing( |
| 363 filter->SendBeginTracing(cf_str, TraceLog::GetInstance()->trace_options()); | 406 TraceLog::GetInstance()->GetCurrentCategoryFilter().ToString(), |
| 407 TraceLog::GetInstance()->trace_options()); | |
| 364 } | 408 } |
| 365 } | 409 } |
| 366 | 410 |
| 367 void TracingControllerImpl::RemoveFilter(TraceMessageFilter* filter) { | 411 void TracingControllerImpl::RemoveTraceMessageFilter( |
| 412 TraceMessageFilter* trace_message_filter) { | |
| 368 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 413 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 369 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 414 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 370 base::Bind(&TracingControllerImpl::RemoveFilter, base::Unretained(this), | 415 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter, |
| 371 make_scoped_refptr(filter))); | 416 base::Unretained(this), |
| 417 make_scoped_refptr(trace_message_filter))); | |
| 372 return; | 418 return; |
| 373 } | 419 } |
| 374 | 420 |
| 375 filters_.erase(filter); | 421 trace_message_filters_.erase(trace_message_filter); |
| 376 } | 422 } |
| 377 | 423 |
| 378 void TracingControllerImpl::OnDisableRecordingAcked( | 424 void TracingControllerImpl::OnDisableRecordingAcked( |
| 379 const std::vector<std::string>& known_category_groups) { | 425 const std::vector<std::string>& known_category_groups) { |
| 380 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 426 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 381 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 427 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 382 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked, | 428 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked, |
| 383 base::Unretained(this), known_category_groups)); | 429 base::Unretained(this), known_category_groups)); |
| 384 return; | 430 return; |
| 385 } | 431 } |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 555 if (pending_trace_buffer_percent_full_ack_count_ == 1) { | 601 if (pending_trace_buffer_percent_full_ack_count_ == 1) { |
| 556 // The last ack represents local trace, so we need to ack it now. Note that | 602 // The last ack represents local trace, so we need to ack it now. Note that |
| 557 // this code only executes if there were child processes. | 603 // this code only executes if there were child processes. |
| 558 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 604 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 559 base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply, | 605 base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply, |
| 560 base::Unretained(this), | 606 base::Unretained(this), |
| 561 TraceLog::GetInstance()->GetBufferPercentFull())); | 607 TraceLog::GetInstance()->GetBufferPercentFull())); |
| 562 } | 608 } |
| 563 } | 609 } |
| 564 | 610 |
| 611 void TracingControllerImpl::OnWatchEventMatched() { | |
| 612 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
| 613 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 614 base::Bind(&TracingControllerImpl::OnWatchEventMatched, | |
| 615 base::Unretained(this))); | |
|
piman
2013/11/15 23:42:52
What makes Unretained here safe?
Xianzhu
2013/11/16 01:16:14
TracingControllerImpl instance is a leaky singleto
| |
| 616 } | |
| 617 | |
| 618 if (!watch_event_callback_.is_null()) | |
| 619 watch_event_callback_.Run(); | |
| 620 } | |
| 621 | |
| 622 // static | |
| 623 bool TracingControllerImpl::ParseTracingParams( | |
| 624 const base::DictionaryValue* params, | |
| 625 std::string* category_filter, | |
| 626 Options* options) { | |
| 627 bool use_system_tracing; | |
| 628 bool use_continuous_tracing; | |
| 629 bool use_sampling; | |
| 630 | |
| 631 if (!params->GetString(kCategoryFilter, category_filter) || | |
| 632 !params->GetBoolean(kUseSystemTracing, &use_system_tracing) || | |
| 633 !params->GetBoolean(kUseContinuousTracing, &use_continuous_tracing) || | |
| 634 !params->GetBoolean(kUseSampling, &use_sampling)) { | |
| 635 LOG(ERROR) << "Malformed params"; | |
| 636 return false; | |
| 637 } | |
| 638 | |
| 639 int tracing_options = 0; | |
| 640 if (use_system_tracing) | |
| 641 tracing_options |= ENABLE_SYSTRACE; | |
| 642 if (use_continuous_tracing) | |
| 643 tracing_options |= RECORD_CONTINUOUSLY; | |
| 644 if (use_sampling) | |
| 645 tracing_options |= ENABLE_SAMPLING; | |
| 646 | |
| 647 *options = static_cast<Options>(tracing_options); | |
| 648 return true; | |
| 649 } | |
| 650 | |
| 651 // static | |
| 652 void TracingControllerImpl::EncodeTracingParams( | |
| 653 const std::string& category_filter, | |
| 654 Options options, | |
| 655 base::DictionaryValue* result) { | |
| 656 result->SetString(kCategoryFilter, category_filter); | |
| 657 result->SetBoolean(kUseSystemTracing, options & ENABLE_SYSTRACE); | |
| 658 result->SetBoolean(kUseContinuousTracing, options & RECORD_CONTINUOUSLY); | |
| 659 result->SetBoolean(kUseSampling, options & ENABLE_SAMPLING); | |
| 660 } | |
| 661 | |
| 565 } // namespace content | 662 } // namespace content |
| OLD | NEW |