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) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/debug/trace_event.h" 8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/files/file_path.h" 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h" 119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/strings/string_util.h" 13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/timer/timer.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/browser/tracing_controller.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_utils.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass StringTraceSink : public content::TracingController::TraceDataSink { 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public: 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci StringTraceSink(std::string* result, const base::Closure& callback) 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : result_(result), completion_callback_(callback) {} 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual void AddTraceChunk(const std::string& chunk) OVERRIDE { 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *result_ += result_->empty() ? "[" : ","; 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *result_ += chunk; 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual void Close() OVERRIDE { 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!result_->empty()) 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *result_ += "]"; 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci completion_callback_.Run(); 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private: 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual ~StringTraceSink() {} 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::string* result_; 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Closure completion_callback_; 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DISALLOW_COPY_AND_ASSIGN(StringTraceSink); 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class InProcessTraceController { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static InProcessTraceController* GetInstance() { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Singleton<InProcessTraceController>::get(); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InProcessTraceController() 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : is_waiting_on_watch_(false), 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) watch_notification_count_(0) {} 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~InProcessTraceController() {} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool BeginTracing(const std::string& category_patterns) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return content::TracingController::GetInstance()->EnableRecording( 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::debug::CategoryFilter(category_patterns), 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::debug::TraceOptions(), 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) content::TracingController::EnableRecordingDoneCallback()); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool BeginTracingWithWatch(const std::string& category_patterns, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& category_name, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& event_name, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_occurrences) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(num_occurrences > 0); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) watch_notification_count_ = num_occurrences; 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!content::TracingController::GetInstance()->SetWatchEvent( 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) category_name, event_name, 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&InProcessTraceController::OnWatchEventMatched, 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Unretained(this)))) { 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!content::TracingController::GetInstance()->EnableRecording( 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::debug::CategoryFilter(category_patterns), 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::debug::TraceOptions(), 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&InProcessTraceController::OnEnableTracingComplete, 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Unretained(this)))) { 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_loop_runner_ = new content::MessageLoopRunner; 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_loop_runner_->Run(); 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool WaitForWatchEvent(base::TimeDelta timeout) { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (watch_notification_count_ == 0) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (timeout != base::TimeDelta()) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timer_.Start(FROM_HERE, timeout, this, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &InProcessTraceController::Timeout); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_waiting_on_watch_ = true; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_runner_ = new content::MessageLoopRunner; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_runner_->Run(); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_waiting_on_watch_ = false; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return watch_notification_count_ == 0; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool EndTracing(std::string* json_trace_output) { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using namespace base::debug; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!content::TracingController::GetInstance()->DisableRecording( 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new StringTraceSink( 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci json_trace_output, 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&InProcessTraceController::OnTracingComplete, 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(this))))) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait for OnEndTracingComplete() to quit the message loop. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_runner_ = new content::MessageLoopRunner; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_runner_->Run(); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Watch notifications can occur during this method's message loop run, but 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not after, so clear them here. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) watch_notification_count_ = 0; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend struct DefaultSingletonTraits<InProcessTraceController>; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void OnEnableTracingComplete() { 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_loop_runner_->Quit(); 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void OnTracingComplete() { message_loop_runner_->Quit(); } 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void OnWatchEventMatched() { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (watch_notification_count_ == 0) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (--watch_notification_count_ == 0) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timer_.Stop(); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_waiting_on_watch_) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_runner_->Quit(); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Timeout() { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(is_waiting_on_watch_); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_runner_->Quit(); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<content::MessageLoopRunner> message_loop_runner_; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::OneShotTimer<InProcessTraceController> timer_; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_waiting_on_watch_; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int watch_notification_count_; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(InProcessTraceController); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace tracing { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool BeginTracing(const std::string& category_patterns) { 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return InProcessTraceController::GetInstance()->BeginTracing( 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) category_patterns); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool BeginTracingWithWatch(const std::string& category_patterns, 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& category_name, 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& event_name, 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_occurrences) { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InProcessTraceController::GetInstance()->BeginTracingWithWatch( 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) category_patterns, category_name, event_name, num_occurrences); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WaitForWatchEvent(base::TimeDelta timeout) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InProcessTraceController::GetInstance()->WaitForWatchEvent(timeout); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EndTracing(std::string* json_trace_output) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InProcessTraceController::GetInstance()->EndTracing(json_trace_output); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace tracing 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 191