Add ICU message format support
[chromium-blink-merge.git] / chromeos / dbus / debug_daemon_client.cc
blob9a993b3fe517261073d6f06579a2c77505030c73
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 "chromeos/dbus/debug_daemon_client.h"
7 #include <fcntl.h>
8 #include <unistd.h>
9 #include <string>
10 #include <vector>
12 #include "base/bind.h"
13 #include "base/bind_helpers.h"
14 #include "base/files/file_path.h"
15 #include "base/location.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/posix/eintr_wrapper.h"
18 #include "base/strings/string_util.h"
19 #include "base/task_runner_util.h"
20 #include "chromeos/dbus/pipe_reader.h"
21 #include "dbus/bus.h"
22 #include "dbus/message.h"
23 #include "dbus/object_path.h"
24 #include "dbus/object_proxy.h"
26 namespace {
28 // Used in DebugDaemonClient::EmptySystemStopTracingCallback().
29 void EmptyStopSystemTracingCallbackBody(
30 const scoped_refptr<base::RefCountedString>& unused_result) {
33 } // namespace
35 namespace chromeos {
37 // The DebugDaemonClient implementation used in production.
38 class DebugDaemonClientImpl : public DebugDaemonClient {
39 public:
40 DebugDaemonClientImpl() : debugdaemon_proxy_(NULL), weak_ptr_factory_(this) {}
42 ~DebugDaemonClientImpl() override {}
44 // DebugDaemonClient override.
45 void DumpDebugLogs(bool is_compressed,
46 base::File file,
47 scoped_refptr<base::TaskRunner> task_runner,
48 const GetDebugLogsCallback& callback) override {
49 dbus::FileDescriptor* file_descriptor = new dbus::FileDescriptor;
50 file_descriptor->PutValue(file.TakePlatformFile());
51 // Punt descriptor validity check to a worker thread; on return we'll
52 // issue the D-Bus request to stop tracing and collect results.
53 task_runner->PostTaskAndReply(
54 FROM_HERE,
55 base::Bind(&dbus::FileDescriptor::CheckValidity,
56 base::Unretained(file_descriptor)),
57 base::Bind(&DebugDaemonClientImpl::OnCheckValidityGetDebugLogs,
58 weak_ptr_factory_.GetWeakPtr(),
59 is_compressed,
60 base::Owned(file_descriptor),
61 callback));
64 void SetDebugMode(const std::string& subsystem,
65 const SetDebugModeCallback& callback) override {
66 dbus::MethodCall method_call(debugd::kDebugdInterface,
67 debugd::kSetDebugMode);
68 dbus::MessageWriter writer(&method_call);
69 writer.AppendString(subsystem);
70 debugdaemon_proxy_->CallMethod(
71 &method_call,
72 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
73 base::Bind(&DebugDaemonClientImpl::OnSetDebugMode,
74 weak_ptr_factory_.GetWeakPtr(),
75 callback));
78 void GetRoutes(bool numeric,
79 bool ipv6,
80 const GetRoutesCallback& callback) override {
81 dbus::MethodCall method_call(debugd::kDebugdInterface,
82 debugd::kGetRoutes);
83 dbus::MessageWriter writer(&method_call);
84 dbus::MessageWriter sub_writer(NULL);
85 writer.OpenArray("{sv}", &sub_writer);
86 dbus::MessageWriter elem_writer(NULL);
87 sub_writer.OpenDictEntry(&elem_writer);
88 elem_writer.AppendString("numeric");
89 elem_writer.AppendVariantOfBool(numeric);
90 sub_writer.CloseContainer(&elem_writer);
91 sub_writer.OpenDictEntry(&elem_writer);
92 elem_writer.AppendString("v6");
93 elem_writer.AppendVariantOfBool(ipv6);
94 sub_writer.CloseContainer(&elem_writer);
95 writer.CloseContainer(&sub_writer);
96 debugdaemon_proxy_->CallMethod(
97 &method_call,
98 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
99 base::Bind(&DebugDaemonClientImpl::OnGetRoutes,
100 weak_ptr_factory_.GetWeakPtr(),
101 callback));
104 void GetNetworkStatus(const GetNetworkStatusCallback& callback) override {
105 dbus::MethodCall method_call(debugd::kDebugdInterface,
106 debugd::kGetNetworkStatus);
107 debugdaemon_proxy_->CallMethod(
108 &method_call,
109 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
110 base::Bind(&DebugDaemonClientImpl::OnGetNetworkStatus,
111 weak_ptr_factory_.GetWeakPtr(),
112 callback));
115 void GetModemStatus(const GetModemStatusCallback& callback) override {
116 dbus::MethodCall method_call(debugd::kDebugdInterface,
117 debugd::kGetModemStatus);
118 debugdaemon_proxy_->CallMethod(
119 &method_call,
120 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
121 base::Bind(&DebugDaemonClientImpl::OnGetModemStatus,
122 weak_ptr_factory_.GetWeakPtr(),
123 callback));
126 void GetWiMaxStatus(const GetWiMaxStatusCallback& callback) override {
127 dbus::MethodCall method_call(debugd::kDebugdInterface,
128 debugd::kGetWiMaxStatus);
129 debugdaemon_proxy_->CallMethod(
130 &method_call,
131 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
132 base::Bind(&DebugDaemonClientImpl::OnGetWiMaxStatus,
133 weak_ptr_factory_.GetWeakPtr(),
134 callback));
137 void GetNetworkInterfaces(
138 const GetNetworkInterfacesCallback& callback) override {
139 dbus::MethodCall method_call(debugd::kDebugdInterface,
140 debugd::kGetInterfaces);
141 debugdaemon_proxy_->CallMethod(
142 &method_call,
143 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
144 base::Bind(&DebugDaemonClientImpl::OnGetNetworkInterfaces,
145 weak_ptr_factory_.GetWeakPtr(),
146 callback));
149 void GetPerfData(uint32_t duration,
150 const GetPerfDataCallback& callback) override {
151 dbus::MethodCall method_call(debugd::kDebugdInterface,
152 debugd::kGetRichPerfData);
153 dbus::MessageWriter writer(&method_call);
154 writer.AppendUint32(duration);
156 debugdaemon_proxy_->CallMethod(
157 &method_call,
158 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
159 base::Bind(&DebugDaemonClientImpl::OnGetPerfData,
160 weak_ptr_factory_.GetWeakPtr(),
161 callback));
164 void GetPerfOutput(uint32_t duration,
165 const GetPerfOutputCallback& callback) override {
166 dbus::MethodCall method_call(debugd::kDebugdInterface,
167 debugd::kGetRandomPerfOutput);
168 dbus::MessageWriter writer(&method_call);
169 writer.AppendUint32(duration);
171 debugdaemon_proxy_->CallMethod(
172 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
173 base::Bind(&DebugDaemonClientImpl::OnGetPerfOutput,
174 weak_ptr_factory_.GetWeakPtr(), callback));
177 void GetScrubbedLogs(const GetLogsCallback& callback) override {
178 dbus::MethodCall method_call(debugd::kDebugdInterface,
179 debugd::kGetFeedbackLogs);
180 debugdaemon_proxy_->CallMethod(
181 &method_call,
182 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
183 base::Bind(&DebugDaemonClientImpl::OnGetAllLogs,
184 weak_ptr_factory_.GetWeakPtr(),
185 callback));
188 void GetAllLogs(const GetLogsCallback& callback) override {
189 dbus::MethodCall method_call(debugd::kDebugdInterface,
190 debugd::kGetAllLogs);
191 debugdaemon_proxy_->CallMethod(
192 &method_call,
193 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
194 base::Bind(&DebugDaemonClientImpl::OnGetAllLogs,
195 weak_ptr_factory_.GetWeakPtr(),
196 callback));
199 void GetUserLogFiles(const GetLogsCallback& callback) override {
200 dbus::MethodCall method_call(debugd::kDebugdInterface,
201 debugd::kGetUserLogFiles);
202 debugdaemon_proxy_->CallMethod(
203 &method_call,
204 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
205 base::Bind(&DebugDaemonClientImpl::OnGetUserLogFiles,
206 weak_ptr_factory_.GetWeakPtr(),
207 callback));
210 void StartSystemTracing() override {
211 dbus::MethodCall method_call(
212 debugd::kDebugdInterface,
213 debugd::kSystraceStart);
214 dbus::MessageWriter writer(&method_call);
215 writer.AppendString("all"); // TODO(sleffler) parameterize category list
217 DVLOG(1) << "Requesting a systrace start";
218 debugdaemon_proxy_->CallMethod(
219 &method_call,
220 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
221 base::Bind(&DebugDaemonClientImpl::OnStartMethod,
222 weak_ptr_factory_.GetWeakPtr()));
225 bool RequestStopSystemTracing(
226 scoped_refptr<base::TaskRunner> task_runner,
227 const StopSystemTracingCallback& callback) override {
228 if (pipe_reader_ != NULL) {
229 LOG(ERROR) << "Busy doing StopSystemTracing";
230 return false;
233 pipe_reader_.reset(new PipeReaderForString(
234 task_runner,
235 base::Bind(&DebugDaemonClientImpl::OnIOComplete,
236 weak_ptr_factory_.GetWeakPtr())));
238 base::File pipe_write_end = pipe_reader_->StartIO();
239 // Create dbus::FileDescriptor on the worker thread; on return we'll
240 // issue the D-Bus request to stop tracing and collect results.
241 base::PostTaskAndReplyWithResult(
242 task_runner.get(),
243 FROM_HERE,
244 base::Bind(
245 &DebugDaemonClientImpl::CreateFileDescriptorToStopSystemTracing,
246 base::Passed(&pipe_write_end)),
247 base::Bind(
248 &DebugDaemonClientImpl::OnCreateFileDescriptorRequestStopSystem,
249 weak_ptr_factory_.GetWeakPtr(),
250 callback));
251 return true;
254 void TestICMP(const std::string& ip_address,
255 const TestICMPCallback& callback) override {
256 dbus::MethodCall method_call(debugd::kDebugdInterface,
257 debugd::kTestICMP);
258 dbus::MessageWriter writer(&method_call);
259 writer.AppendString(ip_address);
260 debugdaemon_proxy_->CallMethod(
261 &method_call,
262 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
263 base::Bind(&DebugDaemonClientImpl::OnTestICMP,
264 weak_ptr_factory_.GetWeakPtr(),
265 callback));
268 void TestICMPWithOptions(const std::string& ip_address,
269 const std::map<std::string, std::string>& options,
270 const TestICMPCallback& callback) override {
271 dbus::MethodCall method_call(debugd::kDebugdInterface,
272 debugd::kTestICMPWithOptions);
273 dbus::MessageWriter writer(&method_call);
274 dbus::MessageWriter sub_writer(NULL);
275 dbus::MessageWriter elem_writer(NULL);
277 // Write the host.
278 writer.AppendString(ip_address);
280 // Write the options.
281 writer.OpenArray("{ss}", &sub_writer);
282 std::map<std::string, std::string>::const_iterator it;
283 for (it = options.begin(); it != options.end(); ++it) {
284 sub_writer.OpenDictEntry(&elem_writer);
285 elem_writer.AppendString(it->first);
286 elem_writer.AppendString(it->second);
287 sub_writer.CloseContainer(&elem_writer);
289 writer.CloseContainer(&sub_writer);
291 // Call the function.
292 debugdaemon_proxy_->CallMethod(
293 &method_call,
294 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
295 base::Bind(&DebugDaemonClientImpl::OnTestICMP,
296 weak_ptr_factory_.GetWeakPtr(),
297 callback));
300 void UploadCrashes() override {
301 dbus::MethodCall method_call(debugd::kDebugdInterface,
302 debugd::kUploadCrashes);
303 debugdaemon_proxy_->CallMethod(
304 &method_call,
305 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
306 base::Bind(&DebugDaemonClientImpl::OnStartMethod,
307 weak_ptr_factory_.GetWeakPtr()));
310 void EnableDebuggingFeatures(
311 const std::string& password,
312 const EnableDebuggingCallback& callback) override {
313 dbus::MethodCall method_call(debugd::kDebugdInterface,
314 debugd::kEnableChromeDevFeatures);
315 dbus::MessageWriter writer(&method_call);
316 writer.AppendString(password);
317 debugdaemon_proxy_->CallMethod(
318 &method_call,
319 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
320 base::Bind(&DebugDaemonClientImpl::OnEnableDebuggingFeatures,
321 weak_ptr_factory_.GetWeakPtr(),
322 callback));
325 void QueryDebuggingFeatures(
326 const QueryDevFeaturesCallback& callback) override {
327 dbus::MethodCall method_call(debugd::kDebugdInterface,
328 debugd::kQueryDevFeatures);
329 dbus::MessageWriter writer(&method_call);
330 debugdaemon_proxy_->CallMethod(
331 &method_call,
332 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
333 base::Bind(&DebugDaemonClientImpl::OnQueryDebuggingFeatures,
334 weak_ptr_factory_.GetWeakPtr(),
335 callback));
338 void RemoveRootfsVerification(
339 const EnableDebuggingCallback& callback) override {
340 dbus::MethodCall method_call(debugd::kDebugdInterface,
341 debugd::kRemoveRootfsVerification);
342 dbus::MessageWriter writer(&method_call);
343 debugdaemon_proxy_->CallMethod(
344 &method_call,
345 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
346 base::Bind(&DebugDaemonClientImpl::OnRemoveRootfsVerification,
347 weak_ptr_factory_.GetWeakPtr(),
348 callback));
351 void WaitForServiceToBeAvailable(
352 const WaitForServiceToBeAvailableCallback& callback) override {
353 debugdaemon_proxy_->WaitForServiceToBeAvailable(callback);
356 protected:
357 void Init(dbus::Bus* bus) override {
358 debugdaemon_proxy_ =
359 bus->GetObjectProxy(debugd::kDebugdServiceName,
360 dbus::ObjectPath(debugd::kDebugdServicePath));
363 private:
364 // Called when a CheckValidity response is received.
365 void OnCheckValidityGetDebugLogs(bool is_compressed,
366 dbus::FileDescriptor* file_descriptor,
367 const GetDebugLogsCallback& callback) {
368 // Issue the dbus request to get debug logs.
369 dbus::MethodCall method_call(debugd::kDebugdInterface,
370 debugd::kDumpDebugLogs);
371 dbus::MessageWriter writer(&method_call);
372 writer.AppendBool(is_compressed);
373 writer.AppendFileDescriptor(*file_descriptor);
375 debugdaemon_proxy_->CallMethod(
376 &method_call,
377 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
378 base::Bind(&DebugDaemonClientImpl::OnGetDebugLogs,
379 weak_ptr_factory_.GetWeakPtr(),
380 callback));
383 // Called when a response for GetDebugLogs() is received.
384 void OnGetDebugLogs(const GetDebugLogsCallback& callback,
385 dbus::Response* response) {
386 if (!response) {
387 LOG(ERROR) << "Failed to get debug logs";
388 callback.Run(false);
389 return;
391 callback.Run(true);
394 // Called when a response for SetDebugMode() is received.
395 void OnSetDebugMode(const SetDebugModeCallback& callback,
396 dbus::Response* response) {
397 if (!response) {
398 LOG(ERROR) << "Failed to change debug mode";
399 callback.Run(false);
400 } else {
401 callback.Run(true);
405 void OnGetRoutes(const GetRoutesCallback& callback,
406 dbus::Response* response) {
407 std::vector<std::string> routes;
408 if (response) {
409 dbus::MessageReader reader(response);
410 if (reader.PopArrayOfStrings(&routes)) {
411 callback.Run(true, routes);
412 } else {
413 LOG(ERROR) << "Got non-array response from GetRoutes";
414 callback.Run(false, routes);
416 } else {
417 callback.Run(false, routes);
421 void OnGetNetworkStatus(const GetNetworkStatusCallback& callback,
422 dbus::Response* response) {
423 std::string status;
424 if (response && dbus::MessageReader(response).PopString(&status))
425 callback.Run(true, status);
426 else
427 callback.Run(false, "");
430 void OnGetModemStatus(const GetModemStatusCallback& callback,
431 dbus::Response* response) {
432 std::string status;
433 if (response && dbus::MessageReader(response).PopString(&status))
434 callback.Run(true, status);
435 else
436 callback.Run(false, "");
439 void OnGetWiMaxStatus(const GetWiMaxStatusCallback& callback,
440 dbus::Response* response) {
441 std::string status;
442 if (response && dbus::MessageReader(response).PopString(&status))
443 callback.Run(true, status);
444 else
445 callback.Run(false, "");
448 void OnGetNetworkInterfaces(const GetNetworkInterfacesCallback& callback,
449 dbus::Response* response) {
450 std::string status;
451 if (response && dbus::MessageReader(response).PopString(&status))
452 callback.Run(true, status);
453 else
454 callback.Run(false, "");
457 void OnGetPerfData(const GetPerfDataCallback& callback,
458 dbus::Response* response) {
459 std::vector<uint8> data;
461 if (!response) {
462 return;
465 dbus::MessageReader reader(response);
466 const uint8* buffer = NULL;
467 size_t buf_size = 0;
468 if (!reader.PopArrayOfBytes(&buffer, &buf_size))
469 return;
471 // TODO(asharif): Figure out a way to avoid this copy.
472 data.insert(data.end(), buffer, buffer + buf_size);
474 callback.Run(data);
477 void OnGetPerfOutput(const GetPerfOutputCallback& callback,
478 dbus::Response* response) {
479 if (!response)
480 return;
482 dbus::MessageReader reader(response);
484 int status = 0;
485 if (!reader.PopInt32(&status))
486 return;
488 const uint8* buffer = nullptr;
489 size_t buf_size = 0;
491 if (!reader.PopArrayOfBytes(&buffer, &buf_size))
492 return;
493 std::vector<uint8> perf_data;
494 if (buf_size > 0)
495 perf_data.insert(perf_data.end(), buffer, buffer + buf_size);
497 if (!reader.PopArrayOfBytes(&buffer, &buf_size))
498 return;
499 std::vector<uint8> perf_stat;
500 if (buf_size > 0)
501 perf_stat.insert(perf_stat.end(), buffer, buffer + buf_size);
503 callback.Run(status, perf_data, perf_stat);
506 void OnGetAllLogs(const GetLogsCallback& callback,
507 dbus::Response* response) {
508 std::map<std::string, std::string> logs;
509 bool broken = false; // did we see a broken (k,v) pair?
510 dbus::MessageReader sub_reader(NULL);
511 if (!response || !dbus::MessageReader(response).PopArray(&sub_reader)) {
512 callback.Run(false, logs);
513 return;
515 while (sub_reader.HasMoreData()) {
516 dbus::MessageReader sub_sub_reader(NULL);
517 std::string key, value;
518 if (!sub_reader.PopDictEntry(&sub_sub_reader)
519 || !sub_sub_reader.PopString(&key)
520 || !sub_sub_reader.PopString(&value)) {
521 broken = true;
522 break;
524 logs[key] = value;
526 callback.Run(!sub_reader.HasMoreData() && !broken, logs);
529 void OnGetUserLogFiles(const GetLogsCallback& callback,
530 dbus::Response* response) {
531 return OnGetAllLogs(callback, response);
534 // Called when a response for a simple start is received.
535 void OnStartMethod(dbus::Response* response) {
536 if (!response) {
537 LOG(ERROR) << "Failed to request start";
538 return;
542 void OnEnableDebuggingFeatures(
543 const EnableDebuggingCallback& callback,
544 dbus::Response* response) {
545 if (callback.is_null())
546 return;
548 callback.Run(response != NULL);
551 void OnQueryDebuggingFeatures(
552 const QueryDevFeaturesCallback& callback,
553 dbus::Response* response) {
554 if (callback.is_null())
555 return;
557 int32 feature_mask = DEV_FEATURE_NONE;
558 if (!response || !dbus::MessageReader(response).PopInt32(&feature_mask)) {
559 callback.Run(false, debugd::DevFeatureFlag::DEV_FEATURES_DISABLED);
560 return;
563 callback.Run(true, feature_mask);
566 void OnRemoveRootfsVerification(
567 const EnableDebuggingCallback& callback,
568 dbus::Response* response) {
569 if (callback.is_null())
570 return;
572 callback.Run(response != NULL);
575 // Creates dbus::FileDescriptor from base::File.
576 static scoped_ptr<dbus::FileDescriptor>
577 CreateFileDescriptorToStopSystemTracing(base::File pipe_write_end) {
578 if (!pipe_write_end.IsValid()) {
579 LOG(ERROR) << "Cannot create pipe reader";
580 // NB: continue anyway to shutdown tracing; toss trace data
581 pipe_write_end.Initialize(base::FilePath(FILE_PATH_LITERAL("/dev/null")),
582 base::File::FLAG_OPEN | base::File::FLAG_WRITE);
583 // TODO(sleffler) if this fails AppendFileDescriptor will abort
585 scoped_ptr<dbus::FileDescriptor> file_descriptor(new dbus::FileDescriptor);
586 file_descriptor->PutValue(pipe_write_end.TakePlatformFile());
587 file_descriptor->CheckValidity();
588 return file_descriptor.Pass();
591 // Called when a CheckValidity response is received.
592 void OnCreateFileDescriptorRequestStopSystem(
593 const StopSystemTracingCallback& callback,
594 scoped_ptr<dbus::FileDescriptor> file_descriptor) {
595 DCHECK(file_descriptor);
597 // Issue the dbus request to stop system tracing
598 dbus::MethodCall method_call(
599 debugd::kDebugdInterface,
600 debugd::kSystraceStop);
601 dbus::MessageWriter writer(&method_call);
602 writer.AppendFileDescriptor(*file_descriptor);
604 callback_ = callback;
606 DVLOG(1) << "Requesting a systrace stop";
607 debugdaemon_proxy_->CallMethod(
608 &method_call,
609 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
610 base::Bind(&DebugDaemonClientImpl::OnRequestStopSystemTracing,
611 weak_ptr_factory_.GetWeakPtr()));
614 // Called when a response for RequestStopSystemTracing() is received.
615 void OnRequestStopSystemTracing(dbus::Response* response) {
616 if (!response) {
617 LOG(ERROR) << "Failed to request systrace stop";
618 // If debugd crashes or completes I/O before this message is processed
619 // then pipe_reader_ can be NULL, see OnIOComplete().
620 if (pipe_reader_.get())
621 pipe_reader_->OnDataReady(-1); // terminate data stream
623 // NB: requester is signaled when i/o completes
626 void OnTestICMP(const TestICMPCallback& callback, dbus::Response* response) {
627 std::string status;
628 if (response && dbus::MessageReader(response).PopString(&status))
629 callback.Run(true, status);
630 else
631 callback.Run(false, "");
634 // Called when pipe i/o completes; pass data on and delete the instance.
635 void OnIOComplete() {
636 std::string pipe_data;
637 pipe_reader_->GetData(&pipe_data);
638 callback_.Run(base::RefCountedString::TakeString(&pipe_data));
639 pipe_reader_.reset();
642 dbus::ObjectProxy* debugdaemon_proxy_;
643 scoped_ptr<PipeReaderForString> pipe_reader_;
644 StopSystemTracingCallback callback_;
645 base::WeakPtrFactory<DebugDaemonClientImpl> weak_ptr_factory_;
647 DISALLOW_COPY_AND_ASSIGN(DebugDaemonClientImpl);
650 DebugDaemonClient::DebugDaemonClient() {
653 DebugDaemonClient::~DebugDaemonClient() {
656 // static
657 DebugDaemonClient::StopSystemTracingCallback
658 DebugDaemonClient::EmptyStopSystemTracingCallback() {
659 return base::Bind(&EmptyStopSystemTracingCallbackBody);
662 // static
663 DebugDaemonClient* DebugDaemonClient::Create() {
664 return new DebugDaemonClientImpl();
667 } // namespace chromeos