Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / test / base / tracing.cc
blob83cbbcce575d319b5ffe4a882f798076541d3e0c
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"
18 namespace {
20 using content::BrowserThread;
22 class StringTraceSink : public content::TracingController::TraceDataSink {
23 public:
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() ? "[" : ",";
29 *result_ += chunk;
31 void Close() override {
32 if (!result_->empty())
33 *result_ += "]";
34 completion_callback_.Run();
37 private:
38 ~StringTraceSink() override {}
40 std::string* result_;
41 base::Closure completion_callback_;
43 DISALLOW_COPY_AND_ASSIGN(StringTraceSink);
46 class InProcessTraceController {
47 public:
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)))) {
75 return false;
77 if (!content::TracingController::GetInstance()->EnableRecording(
78 base::trace_event::TraceConfig(category_patterns, ""),
79 base::Bind(&InProcessTraceController::OnEnableTracingComplete,
80 base::Unretained(this)))) {
81 return false;
84 message_loop_runner_ = new content::MessageLoopRunner;
85 message_loop_runner_->Run();
86 return true;
89 bool WaitForWatchEvent(base::TimeDelta timeout) {
90 DCHECK_CURRENTLY_ON(BrowserThread::UI);
91 if (watch_notification_count_ == 0)
92 return true;
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(
112 new StringTraceSink(
113 json_trace_output,
114 base::Bind(&InProcessTraceController::OnTracingComplete,
115 base::Unretained(this))))) {
116 return false;
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;
125 return true;
128 private:
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)
139 return;
140 if (--watch_notification_count_ == 0) {
141 timer_.Stop();
142 if (is_waiting_on_watch_)
143 message_loop_runner_->Quit();
147 void Timeout() {
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);
162 } // namespace
164 namespace tracing {
166 bool BeginTracing(const std::string& category_patterns) {
167 return InProcessTraceController::GetInstance()->BeginTracing(
168 category_patterns);
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