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
3 // found in the LICENSE file.
5 #include "chrome/test/base/tracing.h"
7 #include "base/files/file_path.h"
8 #include "base/files/file_util.h"
9 #include "base/memory/singleton.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/strings/string_util.h"
12 #include "base/timer/timer.h"
13 #include "base/trace_event/trace_event.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "content/public/browser/tracing_controller.h"
16 #include "content/public/test/test_utils.h"
20 using content::BrowserThread
;
22 class StringTraceSink
: public content::TracingController::TraceDataSink
{
24 StringTraceSink(std::string
* result
, const base::Closure
& callback
)
25 : result_(result
), completion_callback_(callback
) {}
27 void AddTraceChunk(const std::string
& chunk
) override
{
28 *result_
+= result_
->empty() ? "[" : ",";
31 void Close() override
{
32 if (!result_
->empty())
34 completion_callback_
.Run();
38 ~StringTraceSink() override
{}
41 base::Closure completion_callback_
;
43 DISALLOW_COPY_AND_ASSIGN(StringTraceSink
);
46 class InProcessTraceController
{
48 static InProcessTraceController
* GetInstance() {
49 return base::Singleton
<InProcessTraceController
>::get();
52 InProcessTraceController()
53 : is_waiting_on_watch_(false),
54 watch_notification_count_(0) {}
55 virtual ~InProcessTraceController() {}
57 bool BeginTracing(const std::string
& category_patterns
) {
58 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
59 return content::TracingController::GetInstance()->EnableRecording(
60 base::trace_event::TraceConfig(category_patterns
, ""),
61 content::TracingController::EnableRecordingDoneCallback());
64 bool BeginTracingWithWatch(const std::string
& category_patterns
,
65 const std::string
& category_name
,
66 const std::string
& event_name
,
67 int num_occurrences
) {
68 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
69 DCHECK(num_occurrences
> 0);
70 watch_notification_count_
= num_occurrences
;
71 if (!content::TracingController::GetInstance()->SetWatchEvent(
72 category_name
, event_name
,
73 base::Bind(&InProcessTraceController::OnWatchEventMatched
,
74 base::Unretained(this)))) {
77 if (!content::TracingController::GetInstance()->EnableRecording(
78 base::trace_event::TraceConfig(category_patterns
, ""),
79 base::Bind(&InProcessTraceController::OnEnableTracingComplete
,
80 base::Unretained(this)))) {
84 message_loop_runner_
= new content::MessageLoopRunner
;
85 message_loop_runner_
->Run();
89 bool WaitForWatchEvent(base::TimeDelta timeout
) {
90 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
91 if (watch_notification_count_
== 0)
94 if (timeout
!= base::TimeDelta()) {
95 timer_
.Start(FROM_HERE
, timeout
, this,
96 &InProcessTraceController::Timeout
);
99 is_waiting_on_watch_
= true;
100 message_loop_runner_
= new content::MessageLoopRunner
;
101 message_loop_runner_
->Run();
102 is_waiting_on_watch_
= false;
104 return watch_notification_count_
== 0;
107 bool EndTracing(std::string
* json_trace_output
) {
108 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
109 using namespace base::debug
;
111 if (!content::TracingController::GetInstance()->DisableRecording(
114 base::Bind(&InProcessTraceController::OnTracingComplete
,
115 base::Unretained(this))))) {
118 // Wait for OnEndTracingComplete() to quit the message loop.
119 message_loop_runner_
= new content::MessageLoopRunner
;
120 message_loop_runner_
->Run();
122 // Watch notifications can occur during this method's message loop run, but
123 // not after, so clear them here.
124 watch_notification_count_
= 0;
129 friend struct base::DefaultSingletonTraits
<InProcessTraceController
>;
131 void OnEnableTracingComplete() {
132 message_loop_runner_
->Quit();
135 void OnTracingComplete() { message_loop_runner_
->Quit(); }
137 void OnWatchEventMatched() {
138 if (watch_notification_count_
== 0)
140 if (--watch_notification_count_
== 0) {
142 if (is_waiting_on_watch_
)
143 message_loop_runner_
->Quit();
148 DCHECK(is_waiting_on_watch_
);
149 message_loop_runner_
->Quit();
152 scoped_refptr
<content::MessageLoopRunner
> message_loop_runner_
;
154 base::OneShotTimer
<InProcessTraceController
> timer_
;
156 bool is_waiting_on_watch_
;
157 int watch_notification_count_
;
159 DISALLOW_COPY_AND_ASSIGN(InProcessTraceController
);
166 bool BeginTracing(const std::string
& category_patterns
) {
167 return InProcessTraceController::GetInstance()->BeginTracing(
171 bool BeginTracingWithWatch(const std::string
& category_patterns
,
172 const std::string
& category_name
,
173 const std::string
& event_name
,
174 int num_occurrences
) {
175 return InProcessTraceController::GetInstance()->BeginTracingWithWatch(
176 category_patterns
, category_name
, event_name
, num_occurrences
);
179 bool WaitForWatchEvent(base::TimeDelta timeout
) {
180 return InProcessTraceController::GetInstance()->WaitForWatchEvent(timeout
);
183 bool EndTracing(std::string
* json_trace_output
) {
184 return InProcessTraceController::GetInstance()->EndTracing(json_trace_output
);
187 } // namespace tracing