OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/trace_controller_impl.h" | 5 #include "content/browser/tracing/trace_controller_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 | 141 |
142 return true; | 142 return true; |
143 } | 143 } |
144 | 144 |
145 bool TraceControllerImpl::EndTracingAsync(TraceSubscriber* subscriber) { | 145 bool TraceControllerImpl::EndTracingAsync(TraceSubscriber* subscriber) { |
146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
147 | 147 |
148 if (!can_end_tracing() || subscriber != subscriber_) | 148 if (!can_end_tracing() || subscriber != subscriber_) |
149 return false; | 149 return false; |
150 | 150 |
| 151 // Disable local trace early to avoid traces during end-tracing process from |
| 152 // interfering with the process. |
| 153 TraceLog::GetInstance()->SetDisabled(); |
| 154 |
151 // There could be a case where there are no child processes and filters_ | 155 // There could be a case where there are no child processes and filters_ |
152 // is empty. In that case we can immediately tell the subscriber that tracing | 156 // is empty. In that case we can immediately tell the subscriber that tracing |
153 // has ended. To avoid recursive calls back to the subscriber, we will just | 157 // has ended. To avoid recursive calls back to the subscriber, we will just |
154 // use the existing asynchronous OnEndTracingAck code. | 158 // use the existing asynchronous OnEndTracingAck code. |
155 // Count myself (local trace) in pending_end_ack_count_, acked below. | 159 // Count myself (local trace) in pending_end_ack_count_, acked below. |
156 pending_end_ack_count_ = filters_.size() + 1; | 160 pending_end_ack_count_ = filters_.size() + 1; |
157 | 161 |
158 // Handle special case of zero child processes. | 162 // Handle special case of zero child processes. |
159 if (pending_end_ack_count_ == 1) { | 163 if (pending_end_ack_count_ == 1) { |
160 // Ack asynchronously now, because we don't have any children to wait for. | 164 // Ack asynchronously now, because we don't have any children to wait for. |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 return; | 298 return; |
295 } | 299 } |
296 | 300 |
297 // Merge known_category_groups with known_category_groups_ | 301 // Merge known_category_groups with known_category_groups_ |
298 known_category_groups_.insert(known_category_groups.begin(), | 302 known_category_groups_.insert(known_category_groups.begin(), |
299 known_category_groups.end()); | 303 known_category_groups.end()); |
300 | 304 |
301 if (pending_end_ack_count_ == 0) | 305 if (pending_end_ack_count_ == 0) |
302 return; | 306 return; |
303 | 307 |
304 if (--pending_end_ack_count_ == 0) { | 308 |
305 // All acks have been received. | 309 if (--pending_end_ack_count_ == 1) { |
| 310 // All acks from subprocesses have been received. Now flush the local trace. |
| 311 // During or after this call, our OnLocalTraceDataCollected will be |
| 312 // called with the last of the local trace data. |
| 313 TraceLog::GetInstance()->Flush( |
| 314 base::Bind(&TraceControllerImpl::OnLocalTraceDataCollected, |
| 315 base::Unretained(this))); |
| 316 } |
| 317 |
| 318 if (pending_end_ack_count_ == 0) { |
| 319 // All acks (including from the subprocesses and the local trace) have been |
| 320 // received. |
306 is_tracing_ = false; | 321 is_tracing_ = false; |
307 | 322 |
308 // Disable local trace. | |
309 TraceLog::GetInstance()->SetDisabled(); | |
310 | |
311 // During this call, our OnTraceDataCollected will be | |
312 // called with the last of the local trace data. Since we are on the UI | |
313 // thread, the call to OnTraceDataCollected will be synchronous, so we can | |
314 // immediately call OnEndTracingComplete below. | |
315 TraceLog::GetInstance()->Flush( | |
316 base::Bind(&TraceControllerImpl::OnTraceDataCollected, | |
317 base::Unretained(this))); | |
318 | |
319 // Trigger callback if one is set. | 323 // Trigger callback if one is set. |
320 if (subscriber_) { | 324 if (subscriber_) { |
321 if (is_get_category_groups_) | 325 if (is_get_category_groups_) |
322 subscriber_->OnKnownCategoriesCollected(known_category_groups_); | 326 subscriber_->OnKnownCategoriesCollected(known_category_groups_); |
323 else | 327 else |
324 subscriber_->OnEndTracingComplete(); | 328 subscriber_->OnEndTracingComplete(); |
325 // Clear subscriber so that others can use TraceController. | 329 // Clear subscriber so that others can use TraceController. |
326 subscriber_ = NULL; | 330 subscriber_ = NULL; |
327 } | 331 } |
328 | 332 |
329 is_get_category_groups_ = false; | 333 is_get_category_groups_ = false; |
330 } | 334 } |
331 | |
332 if (pending_end_ack_count_ == 1) { | |
333 // The last ack represents local trace, so we need to ack it now. Note that | |
334 // this code only executes if there were child processes. | |
335 std::vector<std::string> category_groups; | |
336 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups); | |
337 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
338 base::Bind(&TraceControllerImpl::OnEndTracingAck, | |
339 base::Unretained(this), category_groups)); | |
340 } | |
341 } | 335 } |
342 | 336 |
343 void TraceControllerImpl::OnTraceDataCollected( | 337 void TraceControllerImpl::OnTraceDataCollected( |
344 const scoped_refptr<base::RefCountedString>& events_str_ptr) { | 338 const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
345 // OnTraceDataCollected may be called from any browser thread, either by the | 339 // OnTraceDataCollected may be called from any browser thread, either by the |
346 // local event trace system or from child processes via TraceMessageFilter. | 340 // local event trace system or from child processes via TraceMessageFilter. |
347 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 341 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
348 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 342 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
349 base::Bind(&TraceControllerImpl::OnTraceDataCollected, | 343 base::Bind(&TraceControllerImpl::OnTraceDataCollected, |
350 base::Unretained(this), events_str_ptr)); | 344 base::Unretained(this), events_str_ptr)); |
351 return; | 345 return; |
352 } | 346 } |
353 | 347 |
354 // Drop trace events if we are just getting categories. | 348 // Drop trace events if we are just getting categories. |
355 if (subscriber_ && !is_get_category_groups_) | 349 if (subscriber_ && !is_get_category_groups_) |
356 subscriber_->OnTraceDataCollected(events_str_ptr); | 350 subscriber_->OnTraceDataCollected(events_str_ptr); |
357 } | 351 } |
358 | 352 |
| 353 void TraceControllerImpl::OnLocalTraceDataCollected( |
| 354 const scoped_refptr<base::RefCountedString>& events_str_ptr, |
| 355 bool has_more_events) { |
| 356 if (events_str_ptr->data().size()) |
| 357 OnTraceDataCollected(events_str_ptr); |
| 358 |
| 359 if (!has_more_events) { |
| 360 // Simulate an EndTrackingAck for the local trace. |
| 361 std::vector<std::string> category_groups; |
| 362 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups); |
| 363 OnEndTracingAck(category_groups); |
| 364 } |
| 365 } |
| 366 |
359 void TraceControllerImpl::OnTraceNotification(int notification) { | 367 void TraceControllerImpl::OnTraceNotification(int notification) { |
360 // OnTraceNotification may be called from any browser thread, either by the | 368 // OnTraceNotification may be called from any browser thread, either by the |
361 // local event trace system or from child processes via TraceMessageFilter. | 369 // local event trace system or from child processes via TraceMessageFilter. |
362 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 370 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
363 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 371 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
364 base::Bind(&TraceControllerImpl::OnTraceNotification, | 372 base::Bind(&TraceControllerImpl::OnTraceNotification, |
365 base::Unretained(this), notification)); | 373 base::Unretained(this), notification)); |
366 return; | 374 return; |
367 } | 375 } |
368 | 376 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
400 // The last ack represents local trace, so we need to ack it now. Note that | 408 // The last ack represents local trace, so we need to ack it now. Note that |
401 // this code only executes if there were child processes. | 409 // this code only executes if there were child processes. |
402 float bpf = TraceLog::GetInstance()->GetBufferPercentFull(); | 410 float bpf = TraceLog::GetInstance()->GetBufferPercentFull(); |
403 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 411 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
404 base::Bind(&TraceControllerImpl::OnTraceBufferPercentFullReply, | 412 base::Bind(&TraceControllerImpl::OnTraceBufferPercentFullReply, |
405 base::Unretained(this), bpf)); | 413 base::Unretained(this), bpf)); |
406 } | 414 } |
407 } | 415 } |
408 | 416 |
409 } // namespace content | 417 } // namespace content |
OLD | NEW |