15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/tracing.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h" 99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/trace_controller.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/trace_subscriber.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_utils.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InProcessTraceController : public content::TraceSubscriber { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static InProcessTraceController* GetInstance() { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Singleton<InProcessTraceController>::get(); 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InProcessTraceController() 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : is_waiting_on_watch_(false), 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) watch_notification_count_(0) {} 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~InProcessTraceController() {} 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool BeginTracing(const std::string& category_patterns) { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return content::TraceController::GetInstance()->BeginTracing( 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) this, category_patterns, base::debug::TraceLog::RECORD_UNTIL_FULL); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool BeginTracingWithWatch(const std::string& category_patterns, 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& category_name, 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& event_name, 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_occurrences) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(num_occurrences > 0); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) watch_notification_count_ = num_occurrences; 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return BeginTracing(category_patterns) && 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::TraceController::GetInstance()->SetWatchEvent( 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, category_name, event_name); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool WaitForWatchEvent(base::TimeDelta timeout) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (watch_notification_count_ == 0) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (timeout != base::TimeDelta()) { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timer_.Start(FROM_HERE, timeout, this, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &InProcessTraceController::Timeout); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_waiting_on_watch_ = true; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_runner_ = new content::MessageLoopRunner; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_runner_->Run(); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_waiting_on_watch_ = false; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return watch_notification_count_ == 0; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool EndTracing(std::string* json_trace_output) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using namespace base::debug; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TraceResultBuffer::SimpleOutput output; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trace_buffer_.SetOutputCallback(output.GetCallback()); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trace_buffer_.Start(); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!content::TraceController::GetInstance()->EndTracingAsync(this)) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait for OnEndTracingComplete() to quit the message loop. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // OnTraceDataCollected may be called multiple times while blocking here. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_runner_ = new content::MessageLoopRunner; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_runner_->Run(); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trace_buffer_.Finish(); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trace_buffer_.SetOutputCallback(TraceResultBuffer::OutputCallback()); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *json_trace_output = output.json_output; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Watch notifications can occur during this method's message loop run, but 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not after, so clear them here. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) watch_notification_count_ = 0; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend struct DefaultSingletonTraits<InProcessTraceController>; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TraceSubscriber implementation 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnEndTracingComplete() OVERRIDE { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_runner_->Quit(); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TraceSubscriber implementation 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnTraceDataCollected( 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const scoped_refptr<base::RefCountedString>& trace_fragment) OVERRIDE { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trace_buffer_.AddFragment(trace_fragment->data()); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TraceSubscriber implementation 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnEventWatchNotification() OVERRIDE { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (watch_notification_count_ == 0) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (--watch_notification_count_ == 0) { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timer_.Stop(); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_waiting_on_watch_) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_runner_->Quit(); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Timeout() { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(is_waiting_on_watch_); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_runner_->Quit(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For collecting trace data asynchronously. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::debug::TraceResultBuffer trace_buffer_; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<content::MessageLoopRunner> message_loop_runner_; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::OneShotTimer<InProcessTraceController> timer_; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_waiting_on_watch_; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int watch_notification_count_; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(InProcessTraceController); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace tracing { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool BeginTracing(const std::string& category_patterns) { 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return InProcessTraceController::GetInstance()->BeginTracing( 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) category_patterns); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool BeginTracingWithWatch(const std::string& category_patterns, 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& category_name, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& event_name, 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_occurrences) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InProcessTraceController::GetInstance()->BeginTracingWithWatch( 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) category_patterns, category_name, event_name, num_occurrences); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WaitForWatchEvent(base::TimeDelta timeout) { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InProcessTraceController::GetInstance()->WaitForWatchEvent(timeout); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EndTracing(std::string* json_trace_output) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InProcessTraceController::GetInstance()->EndTracing(json_trace_output); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace tracing 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 161