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.
8 #include "chromeos/dbus/debug_daemon_client.h"
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/memory/ref_counted_memory.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/platform_file.h"
15 #include "base/posix/eintr_wrapper.h"
16 #include "base/strings/string_util.h"
17 #include "base/threading/worker_pool.h"
19 #include "dbus/message.h"
20 #include "dbus/object_path.h"
21 #include "dbus/object_proxy.h"
22 #include "net/base/file_stream.h"
23 #include "net/base/io_buffer.h"
24 #include "net/base/net_errors.h"
25 #include "third_party/cros_system_api/dbus/service_constants.h"
29 // Used in DebugDaemonClient::EmptySystemStopTracingCallback().
30 void EmptyStopSystemTracingCallbackBody(
31 const scoped_refptr<base::RefCountedString>& unused_result) {
34 // Simple class to encapsulate collecting data from a pipe into a
35 // string. To use, instantiate the class, start i/o, and then delete
36 // the instance on callback. The data should be retrieved before
37 // delete and extracted or copied.
39 // TODO(sleffler) move data collection to a sub-class so this
40 // can be reused to process data as it is received
43 typedef base::Callback<void(void)>IOCompleteCallback;
45 explicit PipeReader(IOCompleteCallback callback)
46 : io_buffer_(new net::IOBufferWithSize(4096)),
48 weak_ptr_factory_(this) {
49 pipe_fd_[0] = pipe_fd_[1] = -1;
52 virtual ~PipeReader() {
53 // Don't close pipe_fd_[0] as it's closed by data_stream_.
54 if (pipe_fd_[1] != -1)
55 if (HANDLE_EINTR(close(pipe_fd_[1])) < 0)
56 PLOG(ERROR) << "close[1]";
59 // Returns descriptor for the writeable side of the pipe.
60 int GetWriteFD() { return pipe_fd_[1]; }
62 // Closes writeable descriptor; normally used in parent process after fork.
64 if (pipe_fd_[1] != -1) {
65 if (HANDLE_EINTR(close(pipe_fd_[1])) < 0)
66 PLOG(ERROR) << "close";
71 // Returns collected data.
72 std::string* data() { return &data_; }
74 // Starts data collection. Returns true if stream was setup correctly.
75 // On success data will automatically be accumulated into a string that
76 // can be retrieved with PipeReader::data(). To shutdown collection delete
77 // the instance and/or use PipeReader::OnDataReady(-1).
79 // Use a pipe to collect data
80 const int status = HANDLE_EINTR(pipe(pipe_fd_));
82 PLOG(ERROR) << "pipe";
85 base::PlatformFile data_file_ = pipe_fd_[0]; // read side
86 data_stream_.reset(new net::FileStream(data_file_,
87 base::PLATFORM_FILE_READ | base::PLATFORM_FILE_ASYNC,
90 // Post an initial async read to setup data collection
91 int rv = data_stream_->Read(io_buffer_.get(), io_buffer_->size(),
92 base::Bind(&PipeReader::OnDataReady, weak_ptr_factory_.GetWeakPtr()));
93 if (rv != net::ERR_IO_PENDING) {
94 LOG(ERROR) << "Unable to post initial read";
100 // Called when pipe data are available. Can also be used to shutdown
101 // data collection by passing -1 for |byte_count|.
102 void OnDataReady(int byte_count) {
103 DVLOG(1) << "OnDataReady byte_count " << byte_count;
104 if (byte_count <= 0) {
105 callback_.Run(); // signal creator to take data and delete us
108 data_.append(io_buffer_->data(), byte_count);
111 int rv = data_stream_->Read(io_buffer_.get(), io_buffer_->size(),
112 base::Bind(&PipeReader::OnDataReady, weak_ptr_factory_.GetWeakPtr()));
113 if (rv != net::ERR_IO_PENDING) {
114 LOG(ERROR) << "Unable to post another read";
115 // TODO(sleffler) do something more intelligent?
120 friend class base::RefCounted<PipeReader>;
123 scoped_ptr<net::FileStream> data_stream_;
124 scoped_refptr<net::IOBufferWithSize> io_buffer_;
126 IOCompleteCallback callback_;
128 // Note: This should remain the last member so it'll be destroyed and
129 // invalidate its weak pointers before any other members are destroyed.
130 base::WeakPtrFactory<PipeReader> weak_ptr_factory_;
132 DISALLOW_COPY_AND_ASSIGN(PipeReader);
139 // The DebugDaemonClient implementation used in production.
140 class DebugDaemonClientImpl : public DebugDaemonClient {
142 DebugDaemonClientImpl() : debugdaemon_proxy_(NULL), weak_ptr_factory_(this) {}
144 virtual ~DebugDaemonClientImpl() {}
146 // DebugDaemonClient override.
147 virtual void GetDebugLogs(base::PlatformFile file,
148 const GetDebugLogsCallback& callback) OVERRIDE {
150 dbus::FileDescriptor* file_descriptor = new dbus::FileDescriptor(file);
151 // Punt descriptor validity check to a worker thread; on return we'll
152 // issue the D-Bus request to stop tracing and collect results.
153 base::WorkerPool::PostTaskAndReply(
155 base::Bind(&DebugDaemonClientImpl::CheckValidity,
157 base::Bind(&DebugDaemonClientImpl::OnCheckValidityGetDebugLogs,
158 weak_ptr_factory_.GetWeakPtr(),
159 base::Owned(file_descriptor),
164 virtual void SetDebugMode(const std::string& subsystem,
165 const SetDebugModeCallback& callback) OVERRIDE {
166 dbus::MethodCall method_call(debugd::kDebugdInterface,
167 debugd::kSetDebugMode);
168 dbus::MessageWriter writer(&method_call);
169 writer.AppendString(subsystem);
170 debugdaemon_proxy_->CallMethod(
172 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
173 base::Bind(&DebugDaemonClientImpl::OnSetDebugMode,
174 weak_ptr_factory_.GetWeakPtr(),
178 virtual void GetRoutes(bool numeric, bool ipv6,
179 const GetRoutesCallback& callback) OVERRIDE {
180 dbus::MethodCall method_call(debugd::kDebugdInterface,
182 dbus::MessageWriter writer(&method_call);
183 dbus::MessageWriter sub_writer(NULL);
184 writer.OpenArray("{sv}", &sub_writer);
185 dbus::MessageWriter elem_writer(NULL);
186 sub_writer.OpenDictEntry(&elem_writer);
187 elem_writer.AppendString("numeric");
188 elem_writer.AppendVariantOfBool(numeric);
189 sub_writer.CloseContainer(&elem_writer);
190 sub_writer.OpenDictEntry(&elem_writer);
191 elem_writer.AppendString("v6");
192 elem_writer.AppendVariantOfBool(ipv6);
193 sub_writer.CloseContainer(&elem_writer);
194 writer.CloseContainer(&sub_writer);
195 debugdaemon_proxy_->CallMethod(
197 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
198 base::Bind(&DebugDaemonClientImpl::OnGetRoutes,
199 weak_ptr_factory_.GetWeakPtr(),
203 virtual void GetNetworkStatus(const GetNetworkStatusCallback& callback)
205 dbus::MethodCall method_call(debugd::kDebugdInterface,
206 debugd::kGetNetworkStatus);
207 debugdaemon_proxy_->CallMethod(
209 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
210 base::Bind(&DebugDaemonClientImpl::OnGetNetworkStatus,
211 weak_ptr_factory_.GetWeakPtr(),
215 virtual void GetModemStatus(const GetModemStatusCallback& callback)
217 dbus::MethodCall method_call(debugd::kDebugdInterface,
218 debugd::kGetModemStatus);
219 debugdaemon_proxy_->CallMethod(
221 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
222 base::Bind(&DebugDaemonClientImpl::OnGetModemStatus,
223 weak_ptr_factory_.GetWeakPtr(),
227 virtual void GetWiMaxStatus(const GetWiMaxStatusCallback& callback)
229 dbus::MethodCall method_call(debugd::kDebugdInterface,
230 debugd::kGetWiMaxStatus);
231 debugdaemon_proxy_->CallMethod(
233 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
234 base::Bind(&DebugDaemonClientImpl::OnGetWiMaxStatus,
235 weak_ptr_factory_.GetWeakPtr(),
239 virtual void GetNetworkInterfaces(
240 const GetNetworkInterfacesCallback& callback) OVERRIDE {
241 dbus::MethodCall method_call(debugd::kDebugdInterface,
242 debugd::kGetInterfaces);
243 debugdaemon_proxy_->CallMethod(
245 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
246 base::Bind(&DebugDaemonClientImpl::OnGetNetworkInterfaces,
247 weak_ptr_factory_.GetWeakPtr(),
251 virtual void GetPerfData(uint32_t duration,
252 const GetPerfDataCallback& callback) OVERRIDE {
253 dbus::MethodCall method_call(debugd::kDebugdInterface,
254 debugd::kGetRichPerfData);
255 dbus::MessageWriter writer(&method_call);
256 writer.AppendUint32(duration);
258 debugdaemon_proxy_->CallMethod(
260 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
261 base::Bind(&DebugDaemonClientImpl::OnGetPerfData,
262 weak_ptr_factory_.GetWeakPtr(),
266 virtual void GetScrubbedLogs(const GetLogsCallback& callback) OVERRIDE {
267 dbus::MethodCall method_call(debugd::kDebugdInterface,
268 debugd::kGetFeedbackLogs);
269 debugdaemon_proxy_->CallMethod(
271 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
272 base::Bind(&DebugDaemonClientImpl::OnGetAllLogs,
273 weak_ptr_factory_.GetWeakPtr(),
277 virtual void GetAllLogs(const GetLogsCallback& callback)
279 dbus::MethodCall method_call(debugd::kDebugdInterface,
280 debugd::kGetAllLogs);
281 debugdaemon_proxy_->CallMethod(
283 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
284 base::Bind(&DebugDaemonClientImpl::OnGetAllLogs,
285 weak_ptr_factory_.GetWeakPtr(),
289 virtual void GetUserLogFiles(
290 const GetLogsCallback& callback) OVERRIDE {
291 dbus::MethodCall method_call(debugd::kDebugdInterface,
292 debugd::kGetUserLogFiles);
293 debugdaemon_proxy_->CallMethod(
295 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
296 base::Bind(&DebugDaemonClientImpl::OnGetUserLogFiles,
297 weak_ptr_factory_.GetWeakPtr(),
301 virtual void StartSystemTracing() OVERRIDE {
302 dbus::MethodCall method_call(
303 debugd::kDebugdInterface,
304 debugd::kSystraceStart);
305 dbus::MessageWriter writer(&method_call);
306 writer.AppendString("all"); // TODO(sleffler) parameterize category list
308 DVLOG(1) << "Requesting a systrace start";
309 debugdaemon_proxy_->CallMethod(
311 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
312 base::Bind(&DebugDaemonClientImpl::OnStartSystemTracing,
313 weak_ptr_factory_.GetWeakPtr()));
316 virtual bool RequestStopSystemTracing(const StopSystemTracingCallback&
318 if (pipe_reader_ != NULL) {
319 LOG(ERROR) << "Busy doing StopSystemTracing";
323 pipe_reader_.reset(new PipeReader(
324 base::Bind(&DebugDaemonClientImpl::OnIOComplete,
325 weak_ptr_factory_.GetWeakPtr())));
327 if (!pipe_reader_->StartIO()) {
328 LOG(ERROR) << "Cannot create pipe reader";
329 // NB: continue anyway to shutdown tracing; toss trace data
330 write_fd = HANDLE_EINTR(open("/dev/null", O_WRONLY));
331 // TODO(sleffler) if this fails AppendFileDescriptor will abort
333 write_fd = pipe_reader_->GetWriteFD();
336 dbus::FileDescriptor* file_descriptor = new dbus::FileDescriptor(write_fd);
337 // Punt descriptor validity check to a worker thread; on return we'll
338 // issue the D-Bus request to stop tracing and collect results.
339 base::WorkerPool::PostTaskAndReply(
341 base::Bind(&DebugDaemonClientImpl::CheckValidity,
343 base::Bind(&DebugDaemonClientImpl::OnCheckValidityRequestStopSystem,
344 weak_ptr_factory_.GetWeakPtr(),
345 base::Owned(file_descriptor),
352 virtual void TestICMP(const std::string& ip_address,
353 const TestICMPCallback& callback) OVERRIDE {
354 dbus::MethodCall method_call(debugd::kDebugdInterface,
356 dbus::MessageWriter writer(&method_call);
357 writer.AppendString(ip_address);
358 debugdaemon_proxy_->CallMethod(
360 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
361 base::Bind(&DebugDaemonClientImpl::OnTestICMP,
362 weak_ptr_factory_.GetWeakPtr(),
366 virtual void TestICMPWithOptions(
367 const std::string& ip_address,
368 const std::map<std::string, std::string>& options,
369 const TestICMPCallback& callback) OVERRIDE {
370 dbus::MethodCall method_call(debugd::kDebugdInterface,
371 debugd::kTestICMPWithOptions);
372 dbus::MessageWriter writer(&method_call);
373 dbus::MessageWriter sub_writer(NULL);
374 dbus::MessageWriter elem_writer(NULL);
377 writer.AppendString(ip_address);
379 // Write the options.
380 writer.OpenArray("{ss}", &sub_writer);
381 std::map<std::string, std::string>::const_iterator it;
382 for (it = options.begin(); it != options.end(); ++it) {
383 sub_writer.OpenDictEntry(&elem_writer);
384 elem_writer.AppendString(it->first);
385 elem_writer.AppendString(it->second);
386 sub_writer.CloseContainer(&elem_writer);
388 writer.CloseContainer(&sub_writer);
390 // Call the function.
391 debugdaemon_proxy_->CallMethod(
393 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
394 base::Bind(&DebugDaemonClientImpl::OnTestICMP,
395 weak_ptr_factory_.GetWeakPtr(),
400 virtual void Init(dbus::Bus* bus) OVERRIDE {
402 bus->GetObjectProxy(debugd::kDebugdServiceName,
403 dbus::ObjectPath(debugd::kDebugdServicePath));
407 // Called to check descriptor validity on a thread where i/o is permitted.
408 static void CheckValidity(dbus::FileDescriptor* file_descriptor) {
409 file_descriptor->CheckValidity();
412 // Called when a CheckValidity response is received.
413 void OnCheckValidityGetDebugLogs(dbus::FileDescriptor* file_descriptor,
414 const GetDebugLogsCallback& callback) {
415 // Issue the dbus request to get debug logs.
416 dbus::MethodCall method_call(
417 debugd::kDebugdInterface,
418 debugd::kGetDebugLogs);
419 dbus::MessageWriter writer(&method_call);
420 writer.AppendFileDescriptor(*file_descriptor);
422 debugdaemon_proxy_->CallMethod(
424 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
425 base::Bind(&DebugDaemonClientImpl::OnGetDebugLogs,
426 weak_ptr_factory_.GetWeakPtr(),
430 // Called when a response for GetDebugLogs() is received.
431 void OnGetDebugLogs(const GetDebugLogsCallback& callback,
432 dbus::Response* response) {
434 LOG(ERROR) << "Failed to get debug logs";
441 // Called when a response for SetDebugMode() is received.
442 void OnSetDebugMode(const SetDebugModeCallback& callback,
443 dbus::Response* response) {
445 LOG(ERROR) << "Failed to change debug mode";
452 void OnGetRoutes(const GetRoutesCallback& callback,
453 dbus::Response* response) {
454 std::vector<std::string> routes;
456 dbus::MessageReader reader(response);
457 if (reader.PopArrayOfStrings(&routes)) {
458 callback.Run(true, routes);
460 LOG(ERROR) << "Got non-array response from GetRoutes";
461 callback.Run(false, routes);
464 callback.Run(false, routes);
468 void OnGetNetworkStatus(const GetNetworkStatusCallback& callback,
469 dbus::Response* response) {
471 if (response && dbus::MessageReader(response).PopString(&status))
472 callback.Run(true, status);
474 callback.Run(false, "");
477 void OnGetModemStatus(const GetModemStatusCallback& callback,
478 dbus::Response* response) {
480 if (response && dbus::MessageReader(response).PopString(&status))
481 callback.Run(true, status);
483 callback.Run(false, "");
486 void OnGetWiMaxStatus(const GetWiMaxStatusCallback& callback,
487 dbus::Response* response) {
489 if (response && dbus::MessageReader(response).PopString(&status))
490 callback.Run(true, status);
492 callback.Run(false, "");
495 void OnGetNetworkInterfaces(const GetNetworkInterfacesCallback& callback,
496 dbus::Response* response) {
498 if (response && dbus::MessageReader(response).PopString(&status))
499 callback.Run(true, status);
501 callback.Run(false, "");
504 void OnGetPerfData(const GetPerfDataCallback& callback,
505 dbus::Response* response) {
506 std::vector<uint8> data;
512 dbus::MessageReader reader(response);
513 uint8* buffer = NULL;
515 if (!reader.PopArrayOfBytes(reinterpret_cast<uint8**>(
516 &buffer), &buf_size)) {
520 // TODO(asharif): Figure out a way to avoid this copy.
521 data.insert(data.end(), buffer, buffer + buf_size);
526 void OnGetAllLogs(const GetLogsCallback& callback,
527 dbus::Response* response) {
528 std::map<std::string, std::string> logs;
529 bool broken = false; // did we see a broken (k,v) pair?
530 dbus::MessageReader sub_reader(NULL);
531 if (!response || !dbus::MessageReader(response).PopArray(&sub_reader)) {
532 callback.Run(false, logs);
535 while (sub_reader.HasMoreData()) {
536 dbus::MessageReader sub_sub_reader(NULL);
537 std::string key, value;
538 if (!sub_reader.PopDictEntry(&sub_sub_reader)
539 || !sub_sub_reader.PopString(&key)
540 || !sub_sub_reader.PopString(&value)) {
546 callback.Run(!sub_reader.HasMoreData() && !broken, logs);
549 void OnGetUserLogFiles(const GetLogsCallback& callback,
550 dbus::Response* response) {
551 return OnGetAllLogs(callback, response);
554 // Called when a response for StartSystemTracing() is received.
555 void OnStartSystemTracing(dbus::Response* response) {
557 LOG(ERROR) << "Failed to request systrace start";
562 // Called when a CheckValidity response is received.
563 void OnCheckValidityRequestStopSystem(
564 dbus::FileDescriptor* file_descriptor,
565 const StopSystemTracingCallback& callback) {
566 // Issue the dbus request to stop system tracing
567 dbus::MethodCall method_call(
568 debugd::kDebugdInterface,
569 debugd::kSystraceStop);
570 dbus::MessageWriter writer(&method_call);
571 writer.AppendFileDescriptor(*file_descriptor);
573 callback_ = callback;
575 DVLOG(1) << "Requesting a systrace stop";
576 debugdaemon_proxy_->CallMethod(
578 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
579 base::Bind(&DebugDaemonClientImpl::OnRequestStopSystemTracing,
580 weak_ptr_factory_.GetWeakPtr()));
582 pipe_reader_->CloseWriteFD(); // close our copy of fd after send
585 // Called when a response for RequestStopSystemTracing() is received.
586 void OnRequestStopSystemTracing(dbus::Response* response) {
588 LOG(ERROR) << "Failed to request systrace stop";
589 // If debugd crashes or completes I/O before this message is processed
590 // then pipe_reader_ can be NULL, see OnIOComplete().
591 if (pipe_reader_.get())
592 pipe_reader_->OnDataReady(-1); // terminate data stream
594 // NB: requester is signaled when i/o completes
597 void OnTestICMP(const TestICMPCallback& callback, dbus::Response* response) {
599 if (response && dbus::MessageReader(response).PopString(&status))
600 callback.Run(true, status);
602 callback.Run(false, "");
605 // Called when pipe i/o completes; pass data on and delete the instance.
606 void OnIOComplete() {
607 callback_.Run(base::RefCountedString::TakeString(pipe_reader_->data()));
608 pipe_reader_.reset();
611 dbus::ObjectProxy* debugdaemon_proxy_;
612 scoped_ptr<PipeReader> pipe_reader_;
613 StopSystemTracingCallback callback_;
614 base::WeakPtrFactory<DebugDaemonClientImpl> weak_ptr_factory_;
616 DISALLOW_COPY_AND_ASSIGN(DebugDaemonClientImpl);
619 // The DebugDaemonClient implementation used on Linux desktop,
620 // which does nothing.
621 class DebugDaemonClientStubImpl : public DebugDaemonClient {
622 // DebugDaemonClient overrides.
623 virtual void Init(dbus::Bus* bus) OVERRIDE {}
624 virtual void GetDebugLogs(base::PlatformFile file,
625 const GetDebugLogsCallback& callback) OVERRIDE {
628 virtual void SetDebugMode(const std::string& subsystem,
629 const SetDebugModeCallback& callback) OVERRIDE {
632 virtual void StartSystemTracing() OVERRIDE {}
633 virtual bool RequestStopSystemTracing(const StopSystemTracingCallback&
636 callback.Run(base::RefCountedString::TakeString(&no_data));
639 virtual void GetRoutes(bool numeric, bool ipv6,
640 const GetRoutesCallback& callback) OVERRIDE {
641 std::vector<std::string> empty;
642 base::MessageLoop::current()->PostTask(FROM_HERE,
643 base::Bind(callback, false, empty));
645 virtual void GetNetworkStatus(const GetNetworkStatusCallback& callback)
647 base::MessageLoop::current()->PostTask(FROM_HERE,
648 base::Bind(callback, false, ""));
650 virtual void GetModemStatus(const GetModemStatusCallback& callback)
652 base::MessageLoop::current()->PostTask(FROM_HERE,
653 base::Bind(callback, false, ""));
655 virtual void GetWiMaxStatus(const GetWiMaxStatusCallback& callback)
657 base::MessageLoop::current()->PostTask(FROM_HERE,
658 base::Bind(callback, false, ""));
660 virtual void GetNetworkInterfaces(
661 const GetNetworkInterfacesCallback& callback) OVERRIDE {
662 base::MessageLoop::current()->PostTask(FROM_HERE,
663 base::Bind(callback, false, ""));
665 virtual void GetPerfData(uint32_t duration,
666 const GetPerfDataCallback& callback) OVERRIDE {
667 std::vector<uint8> data;
668 base::MessageLoop::current()->PostTask(FROM_HERE,
669 base::Bind(callback, data));
671 virtual void GetScrubbedLogs(const GetLogsCallback& callback) OVERRIDE {
672 std::map<std::string, std::string> sample;
673 sample["Sample Scrubbed Log"] = "Your email address is xxxxxxxx";
674 base::MessageLoop::current()->PostTask(
675 FROM_HERE, base::Bind(callback, false, sample));
677 virtual void GetAllLogs(const GetLogsCallback& callback) OVERRIDE {
678 std::map<std::string, std::string> sample;
679 sample["Sample Log"] = "Your email address is abc@abc.com";
680 base::MessageLoop::current()->PostTask(
681 FROM_HERE, base::Bind(callback, false, sample));
683 virtual void GetUserLogFiles(const GetLogsCallback& callback) OVERRIDE {
684 std::map<std::string, std::string> user_logs;
685 user_logs["preferences"] = "Preferences";
686 user_logs["invalid_file"] = "Invalid File";
687 base::MessageLoop::current()->PostTask(
689 base::Bind(callback, true, user_logs));
692 virtual void TestICMP(const std::string& ip_address,
693 const TestICMPCallback& callback) OVERRIDE {
694 base::MessageLoop::current()->PostTask(FROM_HERE,
695 base::Bind(callback, false, ""));
698 virtual void TestICMPWithOptions(
699 const std::string& ip_address,
700 const std::map<std::string, std::string>& options,
701 const TestICMPCallback& callback) OVERRIDE {
702 base::MessageLoop::current()->PostTask(FROM_HERE,
703 base::Bind(callback, false, ""));
707 DebugDaemonClient::DebugDaemonClient() {
710 DebugDaemonClient::~DebugDaemonClient() {
714 DebugDaemonClient::StopSystemTracingCallback
715 DebugDaemonClient::EmptyStopSystemTracingCallback() {
716 return base::Bind(&EmptyStopSystemTracingCallbackBody);
720 DebugDaemonClient* DebugDaemonClient::Create(
721 DBusClientImplementationType type) {
722 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
723 return new DebugDaemonClientImpl();
724 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
725 return new DebugDaemonClientStubImpl();
728 } // namespace chromeos