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/debug/trace_event.h"
8 #include "base/files/file_path.h"
9 #include "base/files/file_util.h"
10 #include "base/memory/singleton.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/strings/string_util.h"
13 #include "base/timer/timer.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 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(BrowserThread::CurrentlyOn(BrowserThread::UI
));
59 return content::TracingController::GetInstance()->EnableRecording(
60 base::debug::CategoryFilter(category_patterns
),
61 base::debug::TraceOptions(),
62 content::TracingController::EnableRecordingDoneCallback());
65 bool BeginTracingWithWatch(const std::string
& category_patterns
,
66 const std::string
& category_name
,
67 const std::string
& event_name
,
68 int num_occurrences
) {
69 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
70 DCHECK(num_occurrences
> 0);
71 watch_notification_count_
= num_occurrences
;
72 if (!content::TracingController::GetInstance()->SetWatchEvent(
73 category_name
, event_name
,
74 base::Bind(&InProcessTraceController::OnWatchEventMatched
,
75 base::Unretained(this)))) {
78 if (!content::TracingController::GetInstance()->EnableRecording(
79 base::debug::CategoryFilter(category_patterns
),
80 base::debug::TraceOptions(),
81 base::Bind(&InProcessTraceController::OnEnableTracingComplete
,
82 base::Unretained(this)))) {
86 message_loop_runner_
= new content::MessageLoopRunner
;
87 message_loop_runner_
->Run();
91 bool WaitForWatchEvent(base::TimeDelta timeout
) {
92 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
93 if (watch_notification_count_
== 0)
96 if (timeout
!= base::TimeDelta()) {
97 timer_
.Start(FROM_HERE
, timeout
, this,
98 &InProcessTraceController::Timeout
);
101 is_waiting_on_watch_
= true;
102 message_loop_runner_
= new content::MessageLoopRunner
;
103 message_loop_runner_
->Run();
104 is_waiting_on_watch_
= false;
106 return watch_notification_count_
== 0;
109 bool EndTracing(std::string
* json_trace_output
) {
110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
111 using namespace base::debug
;
113 if (!content::TracingController::GetInstance()->DisableRecording(
116 base::Bind(&InProcessTraceController::OnTracingComplete
,
117 base::Unretained(this))))) {
120 // Wait for OnEndTracingComplete() to quit the message loop.
121 message_loop_runner_
= new content::MessageLoopRunner
;
122 message_loop_runner_
->Run();
124 // Watch notifications can occur during this method's message loop run, but
125 // not after, so clear them here.
126 watch_notification_count_
= 0;
131 friend struct DefaultSingletonTraits
<InProcessTraceController
>;
133 void OnEnableTracingComplete() {
134 message_loop_runner_
->Quit();
137 void OnTracingComplete() { message_loop_runner_
->Quit(); }
139 void OnWatchEventMatched() {
140 if (watch_notification_count_
== 0)
142 if (--watch_notification_count_
== 0) {
144 if (is_waiting_on_watch_
)
145 message_loop_runner_
->Quit();
150 DCHECK(is_waiting_on_watch_
);
151 message_loop_runner_
->Quit();
154 scoped_refptr
<content::MessageLoopRunner
> message_loop_runner_
;
156 base::OneShotTimer
<InProcessTraceController
> timer_
;
158 bool is_waiting_on_watch_
;
159 int watch_notification_count_
;
161 DISALLOW_COPY_AND_ASSIGN(InProcessTraceController
);
168 bool BeginTracing(const std::string
& category_patterns
) {
169 return InProcessTraceController::GetInstance()->BeginTracing(
173 bool BeginTracingWithWatch(const std::string
& category_patterns
,
174 const std::string
& category_name
,
175 const std::string
& event_name
,
176 int num_occurrences
) {
177 return InProcessTraceController::GetInstance()->BeginTracingWithWatch(
178 category_patterns
, category_name
, event_name
, num_occurrences
);
181 bool WaitForWatchEvent(base::TimeDelta timeout
) {
182 return InProcessTraceController::GetInstance()->WaitForWatchEvent(timeout
);
185 bool EndTracing(std::string
* json_trace_output
) {
186 return InProcessTraceController::GetInstance()->EndTracing(json_trace_output
);
189 } // namespace tracing