Only fsync leveldb's directory when the manifest is being updated.
[chromium-blink-merge.git] / chromeos / dbus / debug_daemon_client.cc
blob21841e4e59fd35d6324112ad4af02f81446c78f2
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 <fcntl.h>
6 #include <unistd.h>
8 #include "chromeos/dbus/debug_daemon_client.h"
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/chromeos/chromeos_version.h"
13 #include "base/memory/ref_counted_memory.h"
14 #include "base/message_loop.h"
15 #include "base/platform_file.h"
16 #include "base/posix/eintr_wrapper.h"
17 #include "base/string_util.h"
18 #include "base/threading/worker_pool.h"
19 #include "dbus/bus.h"
20 #include "dbus/message.h"
21 #include "dbus/object_path.h"
22 #include "dbus/object_proxy.h"
23 #include "net/base/file_stream.h"
24 #include "net/base/io_buffer.h"
25 #include "net/base/net_errors.h"
26 #include "third_party/cros_system_api/dbus/service_constants.h"
28 namespace {
30 // Used in DebugDaemonClient::EmptySystemStopTracingCallback().
31 void EmptyStopSystemTracingCallbackBody(
32 const scoped_refptr<base::RefCountedString>& unused_result) {
35 // Simple class to encapsulate collecting data from a pipe into a
36 // string. To use, instantiate the class, start i/o, and then delete
37 // the instance on callback. The data should be retrieved before
38 // delete and extracted or copied.
40 // TODO(sleffler) move data collection to a sub-class so this
41 // can be reused to process data as it is received
42 class PipeReader {
43 public:
44 typedef base::Callback<void(void)>IOCompleteCallback;
46 explicit PipeReader(IOCompleteCallback callback)
47 : data_stream_(NULL),
48 io_buffer_(new net::IOBufferWithSize(4096)),
49 callback_(callback),
50 weak_ptr_factory_(this) {
51 pipe_fd_[0] = pipe_fd_[1] = -1;
54 virtual ~PipeReader() {
55 // Don't close pipe_fd_[0] as it's closed by data_stream_.
56 if (pipe_fd_[1] != -1)
57 if (HANDLE_EINTR(close(pipe_fd_[1])) < 0)
58 PLOG(ERROR) << "close[1]";
61 // Returns descriptor for the writeable side of the pipe.
62 int GetWriteFD() { return pipe_fd_[1]; }
64 // Closes writeable descriptor; normally used in parent process after fork.
65 void CloseWriteFD() {
66 if (pipe_fd_[1] != -1) {
67 if (HANDLE_EINTR(close(pipe_fd_[1])) < 0)
68 PLOG(ERROR) << "close";
69 pipe_fd_[1] = -1;
73 // Returns collected data.
74 std::string* data() { return &data_; }
76 // Starts data collection. Returns true if stream was setup correctly.
77 // On success data will automatically be accumulated into a string that
78 // can be retrieved with PipeReader::data(). To shutdown collection delete
79 // the instance and/or use PipeReader::OnDataReady(-1).
80 bool StartIO() {
81 // Use a pipe to collect data
82 const int status = HANDLE_EINTR(pipe(pipe_fd_));
83 if (status < 0) {
84 PLOG(ERROR) << "pipe";
85 return false;
87 base::PlatformFile data_file_ = pipe_fd_[0]; // read side
88 data_stream_.reset(new net::FileStream(data_file_,
89 base::PLATFORM_FILE_READ | base::PLATFORM_FILE_ASYNC,
90 NULL));
92 // Post an initial async read to setup data collection
93 int rv = data_stream_->Read(io_buffer_.get(), io_buffer_->size(),
94 base::Bind(&PipeReader::OnDataReady, weak_ptr_factory_.GetWeakPtr()));
95 if (rv != net::ERR_IO_PENDING) {
96 LOG(ERROR) << "Unable to post initial read";
97 return false;
99 return true;
102 // Called when pipe data are available. Can also be used to shutdown
103 // data collection by passing -1 for |byte_count|.
104 void OnDataReady(int byte_count) {
105 DVLOG(1) << "OnDataReady byte_count " << byte_count;
106 if (byte_count <= 0) {
107 callback_.Run(); // signal creator to take data and delete us
108 return;
110 data_.append(io_buffer_->data(), byte_count);
112 // Post another read
113 int rv = data_stream_->Read(io_buffer_.get(), io_buffer_->size(),
114 base::Bind(&PipeReader::OnDataReady, weak_ptr_factory_.GetWeakPtr()));
115 if (rv != net::ERR_IO_PENDING) {
116 LOG(ERROR) << "Unable to post another read";
117 // TODO(sleffler) do something more intelligent?
121 private:
122 friend class base::RefCounted<PipeReader>;
124 int pipe_fd_[2];
125 scoped_ptr<net::FileStream> data_stream_;
126 scoped_refptr<net::IOBufferWithSize> io_buffer_;
127 std::string data_;
128 IOCompleteCallback callback_;
130 // Note: This should remain the last member so it'll be destroyed and
131 // invalidate its weak pointers before any other members are destroyed.
132 base::WeakPtrFactory<PipeReader> weak_ptr_factory_;
134 DISALLOW_COPY_AND_ASSIGN(PipeReader);
137 } // namespace
139 namespace chromeos {
141 // The DebugDaemonClient implementation used in production.
142 class DebugDaemonClientImpl : public DebugDaemonClient {
143 public:
144 explicit DebugDaemonClientImpl(dbus::Bus* bus)
145 : debugdaemon_proxy_(NULL),
146 pipe_reader_(NULL),
147 weak_ptr_factory_(this) {
148 debugdaemon_proxy_ = bus->GetObjectProxy(
149 debugd::kDebugdServiceName,
150 dbus::ObjectPath(debugd::kDebugdServicePath));
153 virtual ~DebugDaemonClientImpl() {}
155 // DebugDaemonClient override.
156 virtual void GetDebugLogs(base::PlatformFile file,
157 const GetDebugLogsCallback& callback) OVERRIDE {
159 dbus::FileDescriptor* file_descriptor = new dbus::FileDescriptor(file);
160 // Punt descriptor validity check to a worker thread; on return we'll
161 // issue the D-Bus request to stop tracing and collect results.
162 base::WorkerPool::PostTaskAndReply(
163 FROM_HERE,
164 base::Bind(&DebugDaemonClientImpl::CheckValidity,
165 file_descriptor),
166 base::Bind(&DebugDaemonClientImpl::OnCheckValidityGetDebugLogs,
167 weak_ptr_factory_.GetWeakPtr(),
168 base::Owned(file_descriptor),
169 callback),
170 false);
173 virtual void SetDebugMode(const std::string& subsystem,
174 const SetDebugModeCallback& callback) OVERRIDE {
175 dbus::MethodCall method_call(debugd::kDebugdInterface,
176 debugd::kSetDebugMode);
177 dbus::MessageWriter writer(&method_call);
178 writer.AppendString(subsystem);
179 debugdaemon_proxy_->CallMethod(
180 &method_call,
181 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
182 base::Bind(&DebugDaemonClientImpl::OnSetDebugMode,
183 weak_ptr_factory_.GetWeakPtr(),
184 callback));
187 virtual void GetRoutes(bool numeric, bool ipv6,
188 const GetRoutesCallback& callback) OVERRIDE {
189 dbus::MethodCall method_call(debugd::kDebugdInterface,
190 debugd::kGetRoutes);
191 dbus::MessageWriter writer(&method_call);
192 dbus::MessageWriter sub_writer(NULL);
193 writer.OpenArray("{sv}", &sub_writer);
194 dbus::MessageWriter elem_writer(NULL);
195 sub_writer.OpenDictEntry(&elem_writer);
196 elem_writer.AppendString("numeric");
197 elem_writer.AppendVariantOfBool(numeric);
198 sub_writer.CloseContainer(&elem_writer);
199 sub_writer.OpenDictEntry(&elem_writer);
200 elem_writer.AppendString("v6");
201 elem_writer.AppendVariantOfBool(ipv6);
202 sub_writer.CloseContainer(&elem_writer);
203 writer.CloseContainer(&sub_writer);
204 debugdaemon_proxy_->CallMethod(
205 &method_call,
206 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
207 base::Bind(&DebugDaemonClientImpl::OnGetRoutes,
208 weak_ptr_factory_.GetWeakPtr(),
209 callback));
212 virtual void GetNetworkStatus(const GetNetworkStatusCallback& callback)
213 OVERRIDE {
214 dbus::MethodCall method_call(debugd::kDebugdInterface,
215 debugd::kGetNetworkStatus);
216 debugdaemon_proxy_->CallMethod(
217 &method_call,
218 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
219 base::Bind(&DebugDaemonClientImpl::OnGetNetworkStatus,
220 weak_ptr_factory_.GetWeakPtr(),
221 callback));
224 virtual void GetModemStatus(const GetModemStatusCallback& callback)
225 OVERRIDE {
226 dbus::MethodCall method_call(debugd::kDebugdInterface,
227 debugd::kGetModemStatus);
228 debugdaemon_proxy_->CallMethod(
229 &method_call,
230 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
231 base::Bind(&DebugDaemonClientImpl::OnGetModemStatus,
232 weak_ptr_factory_.GetWeakPtr(),
233 callback));
236 virtual void GetNetworkInterfaces(
237 const GetNetworkInterfacesCallback& callback) OVERRIDE {
238 dbus::MethodCall method_call(debugd::kDebugdInterface,
239 debugd::kGetInterfaces);
240 debugdaemon_proxy_->CallMethod(
241 &method_call,
242 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
243 base::Bind(&DebugDaemonClientImpl::OnGetNetworkInterfaces,
244 weak_ptr_factory_.GetWeakPtr(),
245 callback));
248 virtual void GetPerfData(uint32_t duration,
249 const GetPerfDataCallback& callback) OVERRIDE {
250 dbus::MethodCall method_call(debugd::kDebugdInterface,
251 debugd::kGetPerfData);
252 dbus::MessageWriter writer(&method_call);
253 writer.AppendUint32(duration);
255 debugdaemon_proxy_->CallMethod(
256 &method_call,
257 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
258 base::Bind(&DebugDaemonClientImpl::OnGetPerfData,
259 weak_ptr_factory_.GetWeakPtr(),
260 callback));
263 virtual void GetAllLogs(const GetLogsCallback& callback)
264 OVERRIDE {
265 dbus::MethodCall method_call(debugd::kDebugdInterface,
266 debugd::kGetAllLogs);
267 debugdaemon_proxy_->CallMethod(
268 &method_call,
269 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
270 base::Bind(&DebugDaemonClientImpl::OnGetAllLogs,
271 weak_ptr_factory_.GetWeakPtr(),
272 callback));
275 virtual void GetUserLogFiles(
276 const GetLogsCallback& callback) OVERRIDE {
277 dbus::MethodCall method_call(debugd::kDebugdInterface,
278 debugd::kGetUserLogFiles);
279 debugdaemon_proxy_->CallMethod(
280 &method_call,
281 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
282 base::Bind(&DebugDaemonClientImpl::OnGetUserLogFiles,
283 weak_ptr_factory_.GetWeakPtr(),
284 callback));
287 virtual void StartSystemTracing() OVERRIDE {
288 dbus::MethodCall method_call(
289 debugd::kDebugdInterface,
290 debugd::kSystraceStart);
291 dbus::MessageWriter writer(&method_call);
292 writer.AppendString("all"); // TODO(sleffler) parameterize category list
294 DVLOG(1) << "Requesting a systrace start";
295 debugdaemon_proxy_->CallMethod(
296 &method_call,
297 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
298 base::Bind(&DebugDaemonClientImpl::OnStartSystemTracing,
299 weak_ptr_factory_.GetWeakPtr()));
302 virtual bool RequestStopSystemTracing(const StopSystemTracingCallback&
303 callback) OVERRIDE {
304 if (pipe_reader_ != NULL) {
305 LOG(ERROR) << "Busy doing StopSystemTracing";
306 return false;
309 pipe_reader_.reset(new PipeReader(
310 base::Bind(&DebugDaemonClientImpl::OnIOComplete,
311 weak_ptr_factory_.GetWeakPtr())));
312 int write_fd = -1;
313 if (!pipe_reader_->StartIO()) {
314 LOG(ERROR) << "Cannot create pipe reader";
315 // NB: continue anyway to shutdown tracing; toss trace data
316 write_fd = HANDLE_EINTR(open("/dev/null", O_WRONLY));
317 // TODO(sleffler) if this fails AppendFileDescriptor will abort
318 } else {
319 write_fd = pipe_reader_->GetWriteFD();
322 dbus::FileDescriptor* file_descriptor = new dbus::FileDescriptor(write_fd);
323 // Punt descriptor validity check to a worker thread; on return we'll
324 // issue the D-Bus request to stop tracing and collect results.
325 base::WorkerPool::PostTaskAndReply(
326 FROM_HERE,
327 base::Bind(&DebugDaemonClientImpl::CheckValidity,
328 file_descriptor),
329 base::Bind(&DebugDaemonClientImpl::OnCheckValidityRequestStopSystem,
330 weak_ptr_factory_.GetWeakPtr(),
331 base::Owned(file_descriptor),
332 callback),
333 false);
335 return true;
338 virtual void TestICMP(const std::string& ip_address,
339 const TestICMPCallback& callback) OVERRIDE {
340 dbus::MethodCall method_call(debugd::kDebugdInterface,
341 debugd::kTestICMP);
342 dbus::MessageWriter writer(&method_call);
343 writer.AppendString(ip_address);
344 debugdaemon_proxy_->CallMethod(
345 &method_call,
346 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
347 base::Bind(&DebugDaemonClientImpl::OnTestICMP,
348 weak_ptr_factory_.GetWeakPtr(),
349 callback));
352 private:
353 // Called to check descriptor validity on a thread where i/o is permitted.
354 static void CheckValidity(dbus::FileDescriptor* file_descriptor) {
355 file_descriptor->CheckValidity();
358 // Called when a CheckValidity response is received.
359 void OnCheckValidityGetDebugLogs(dbus::FileDescriptor* file_descriptor,
360 const GetDebugLogsCallback& callback) {
361 // Issue the dbus request to get debug logs.
362 dbus::MethodCall method_call(
363 debugd::kDebugdInterface,
364 debugd::kGetDebugLogs);
365 dbus::MessageWriter writer(&method_call);
366 writer.AppendFileDescriptor(*file_descriptor);
368 debugdaemon_proxy_->CallMethod(
369 &method_call,
370 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
371 base::Bind(&DebugDaemonClientImpl::OnGetDebugLogs,
372 weak_ptr_factory_.GetWeakPtr(),
373 callback));
376 // Called when a response for GetDebugLogs() is received.
377 void OnGetDebugLogs(const GetDebugLogsCallback& callback,
378 dbus::Response* response) {
379 if (!response) {
380 LOG(ERROR) << "Failed to get debug logs";
381 callback.Run(false);
382 return;
384 callback.Run(true);
387 // Called when a response for SetDebugMode() is received.
388 void OnSetDebugMode(const SetDebugModeCallback& callback,
389 dbus::Response* response) {
390 if (!response) {
391 LOG(ERROR) << "Failed to change debug mode";
392 callback.Run(false);
393 } else {
394 callback.Run(true);
398 void OnGetRoutes(const GetRoutesCallback& callback,
399 dbus::Response* response) {
400 std::vector<std::string> routes;
401 if (response) {
402 dbus::MessageReader reader(response);
403 if (reader.PopArrayOfStrings(&routes)) {
404 callback.Run(true, routes);
405 } else {
406 LOG(ERROR) << "Got non-array response from GetRoutes";
407 callback.Run(false, routes);
409 } else {
410 callback.Run(false, routes);
414 void OnGetNetworkStatus(const GetNetworkStatusCallback& callback,
415 dbus::Response* response) {
416 std::string status;
417 if (response && dbus::MessageReader(response).PopString(&status))
418 callback.Run(true, status);
419 else
420 callback.Run(false, "");
423 void OnGetModemStatus(const GetModemStatusCallback& callback,
424 dbus::Response* response) {
425 std::string status;
426 if (response && dbus::MessageReader(response).PopString(&status))
427 callback.Run(true, status);
428 else
429 callback.Run(false, "");
432 void OnGetNetworkInterfaces(const GetNetworkInterfacesCallback& callback,
433 dbus::Response* response) {
434 std::string status;
435 if (response && dbus::MessageReader(response).PopString(&status))
436 callback.Run(true, status);
437 else
438 callback.Run(false, "");
441 void OnGetPerfData(const GetPerfDataCallback& callback,
442 dbus::Response* response) {
443 std::vector<uint8> data;
445 if (!response) {
446 return;
449 dbus::MessageReader reader(response);
450 uint8* buffer = NULL;
451 size_t buf_size = 0;
452 if (!reader.PopArrayOfBytes(reinterpret_cast<uint8**>(
453 &buffer), &buf_size)) {
454 return;
457 // TODO(asharif): Figure out a way to avoid this copy.
458 data.insert(data.end(), buffer, buffer + buf_size);
460 callback.Run(data);
463 void OnGetAllLogs(const GetLogsCallback& callback,
464 dbus::Response* response) {
465 std::map<std::string, std::string> logs;
466 bool broken = false; // did we see a broken (k,v) pair?
467 dbus::MessageReader sub_reader(NULL);
468 if (!response || !dbus::MessageReader(response).PopArray(&sub_reader)) {
469 callback.Run(false, logs);
470 return;
472 while (sub_reader.HasMoreData()) {
473 dbus::MessageReader sub_sub_reader(NULL);
474 std::string key, value;
475 if (!sub_reader.PopDictEntry(&sub_sub_reader)
476 || !sub_sub_reader.PopString(&key)
477 || !sub_sub_reader.PopString(&value)) {
478 broken = true;
479 break;
481 logs[key] = value;
483 callback.Run(!sub_reader.HasMoreData() && !broken, logs);
486 void OnGetUserLogFiles(const GetLogsCallback& callback,
487 dbus::Response* response) {
488 return OnGetAllLogs(callback, response);
491 // Called when a response for StartSystemTracing() is received.
492 void OnStartSystemTracing(dbus::Response* response) {
493 if (!response) {
494 LOG(ERROR) << "Failed to request systrace start";
495 return;
499 // Called when a CheckValidity response is received.
500 void OnCheckValidityRequestStopSystem(
501 dbus::FileDescriptor* file_descriptor,
502 const StopSystemTracingCallback& callback) {
503 // Issue the dbus request to stop system tracing
504 dbus::MethodCall method_call(
505 debugd::kDebugdInterface,
506 debugd::kSystraceStop);
507 dbus::MessageWriter writer(&method_call);
508 writer.AppendFileDescriptor(*file_descriptor);
510 callback_ = callback;
512 DVLOG(1) << "Requesting a systrace stop";
513 debugdaemon_proxy_->CallMethod(
514 &method_call,
515 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
516 base::Bind(&DebugDaemonClientImpl::OnRequestStopSystemTracing,
517 weak_ptr_factory_.GetWeakPtr()));
519 pipe_reader_->CloseWriteFD(); // close our copy of fd after send
522 // Called when a response for RequestStopSystemTracing() is received.
523 void OnRequestStopSystemTracing(dbus::Response* response) {
524 if (!response) {
525 LOG(ERROR) << "Failed to request systrace stop";
526 // If debugd crashes or completes I/O before this message is processed
527 // then pipe_reader_ can be NULL, see OnIOComplete().
528 if (pipe_reader_.get())
529 pipe_reader_->OnDataReady(-1); // terminate data stream
531 // NB: requester is signaled when i/o completes
534 void OnTestICMP(const TestICMPCallback& callback, dbus::Response* response) {
535 std::string status;
536 if (response && dbus::MessageReader(response).PopString(&status))
537 callback.Run(true, status);
538 else
539 callback.Run(false, "");
542 // Called when pipe i/o completes; pass data on and delete the instance.
543 void OnIOComplete() {
544 callback_.Run(base::RefCountedString::TakeString(pipe_reader_->data()));
545 pipe_reader_.reset();
548 dbus::ObjectProxy* debugdaemon_proxy_;
549 scoped_ptr<PipeReader> pipe_reader_;
550 StopSystemTracingCallback callback_;
551 base::WeakPtrFactory<DebugDaemonClientImpl> weak_ptr_factory_;
553 DISALLOW_COPY_AND_ASSIGN(DebugDaemonClientImpl);
556 // The DebugDaemonClient implementation used on Linux desktop,
557 // which does nothing.
558 class DebugDaemonClientStubImpl : public DebugDaemonClient {
559 // DebugDaemonClient overrides.
560 virtual void GetDebugLogs(base::PlatformFile file,
561 const GetDebugLogsCallback& callback) OVERRIDE {
562 callback.Run(false);
564 virtual void SetDebugMode(const std::string& subsystem,
565 const SetDebugModeCallback& callback) OVERRIDE {
566 callback.Run(false);
568 virtual void StartSystemTracing() OVERRIDE {}
569 virtual bool RequestStopSystemTracing(const StopSystemTracingCallback&
570 callback) OVERRIDE {
571 std::string no_data;
572 callback.Run(base::RefCountedString::TakeString(&no_data));
573 return true;
575 virtual void GetRoutes(bool numeric, bool ipv6,
576 const GetRoutesCallback& callback) OVERRIDE {
577 std::vector<std::string> empty;
578 base::MessageLoop::current()->PostTask(FROM_HERE,
579 base::Bind(callback, false, empty));
581 virtual void GetNetworkStatus(const GetNetworkStatusCallback& callback)
582 OVERRIDE {
583 base::MessageLoop::current()->PostTask(FROM_HERE,
584 base::Bind(callback, false, ""));
586 virtual void GetModemStatus(const GetModemStatusCallback& callback)
587 OVERRIDE {
588 base::MessageLoop::current()->PostTask(FROM_HERE,
589 base::Bind(callback, false, ""));
591 virtual void GetNetworkInterfaces(
592 const GetNetworkInterfacesCallback& callback) OVERRIDE {
593 base::MessageLoop::current()->PostTask(FROM_HERE,
594 base::Bind(callback, false, ""));
596 virtual void GetPerfData(uint32_t duration,
597 const GetPerfDataCallback& callback) OVERRIDE {
598 std::vector<uint8> data;
599 base::MessageLoop::current()->PostTask(FROM_HERE,
600 base::Bind(callback, data));
602 virtual void GetAllLogs(const GetLogsCallback& callback) OVERRIDE {
603 std::map<std::string, std::string> empty;
604 base::MessageLoop::current()->PostTask(FROM_HERE,
605 base::Bind(callback, false, empty));
607 virtual void GetUserLogFiles(const GetLogsCallback& callback) OVERRIDE {
608 std::map<std::string, std::string> user_logs;
609 user_logs["preferences"] = "Preferences";
610 user_logs["invalid_file"] = "Invalid File";
611 base::MessageLoop::current()->PostTask(FROM_HERE,
612 base::Bind(callback, true, user_logs));
615 virtual void TestICMP(const std::string& ip_address,
616 const TestICMPCallback& callback) OVERRIDE {
617 base::MessageLoop::current()->PostTask(FROM_HERE,
618 base::Bind(callback, false, ""));
622 DebugDaemonClient::DebugDaemonClient() {
625 DebugDaemonClient::~DebugDaemonClient() {
628 // static
629 DebugDaemonClient::StopSystemTracingCallback
630 DebugDaemonClient::EmptyStopSystemTracingCallback() {
631 return base::Bind(&EmptyStopSystemTracingCallbackBody);
634 // static
635 DebugDaemonClient* DebugDaemonClient::Create(DBusClientImplementationType type,
636 dbus::Bus* bus) {
637 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
638 return new DebugDaemonClientImpl(bus);
639 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
640 return new DebugDaemonClientStubImpl();
643 } // namespace chromeos