Add an extension override bubble and warning box for proxy extensions.
[chromium-blink-merge.git] / chromeos / dbus / debug_daemon_client.cc
blobb73ccaa246f79d17dc3f4c6aad6fb8d38c647116
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/callback.h"
15 #include "base/files/file_path.h"
16 #include "base/location.h"
17 #include "base/memory/ref_counted_memory.h"
18 #include "base/message_loop/message_loop.h"
19 #include "base/posix/eintr_wrapper.h"
20 #include "base/strings/string_util.h"
21 #include "base/task_runner_util.h"
22 #include "base/threading/worker_pool.h"
23 #include "chromeos/dbus/pipe_reader.h"
24 #include "dbus/bus.h"
25 #include "dbus/message.h"
26 #include "dbus/object_path.h"
27 #include "dbus/object_proxy.h"
28 #include "third_party/cros_system_api/dbus/service_constants.h"
30 namespace {
32 // Used in DebugDaemonClient::EmptySystemStopTracingCallback().
33 void EmptyStopSystemTracingCallbackBody(
34 const scoped_refptr<base::RefCountedString>& unused_result) {
37 } // namespace
39 namespace chromeos {
41 // The DebugDaemonClient implementation used in production.
42 class DebugDaemonClientImpl : public DebugDaemonClient {
43 public:
44 DebugDaemonClientImpl() : debugdaemon_proxy_(NULL), weak_ptr_factory_(this) {}
46 virtual ~DebugDaemonClientImpl() {}
48 // DebugDaemonClient override.
49 virtual void GetDebugLogs(base::File file,
50 const GetDebugLogsCallback& callback) OVERRIDE {
52 dbus::FileDescriptor* file_descriptor = new dbus::FileDescriptor;
53 file_descriptor->PutValue(file.TakePlatformFile());
54 // Punt descriptor validity check to a worker thread; on return we'll
55 // issue the D-Bus request to stop tracing and collect results.
56 base::WorkerPool::PostTaskAndReply(
57 FROM_HERE,
58 base::Bind(&dbus::FileDescriptor::CheckValidity,
59 base::Unretained(file_descriptor)),
60 base::Bind(&DebugDaemonClientImpl::OnCheckValidityGetDebugLogs,
61 weak_ptr_factory_.GetWeakPtr(),
62 base::Owned(file_descriptor),
63 callback),
64 false);
67 virtual void SetDebugMode(const std::string& subsystem,
68 const SetDebugModeCallback& callback) OVERRIDE {
69 dbus::MethodCall method_call(debugd::kDebugdInterface,
70 debugd::kSetDebugMode);
71 dbus::MessageWriter writer(&method_call);
72 writer.AppendString(subsystem);
73 debugdaemon_proxy_->CallMethod(
74 &method_call,
75 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
76 base::Bind(&DebugDaemonClientImpl::OnSetDebugMode,
77 weak_ptr_factory_.GetWeakPtr(),
78 callback));
81 virtual void GetRoutes(bool numeric, bool ipv6,
82 const GetRoutesCallback& callback) OVERRIDE {
83 dbus::MethodCall method_call(debugd::kDebugdInterface,
84 debugd::kGetRoutes);
85 dbus::MessageWriter writer(&method_call);
86 dbus::MessageWriter sub_writer(NULL);
87 writer.OpenArray("{sv}", &sub_writer);
88 dbus::MessageWriter elem_writer(NULL);
89 sub_writer.OpenDictEntry(&elem_writer);
90 elem_writer.AppendString("numeric");
91 elem_writer.AppendVariantOfBool(numeric);
92 sub_writer.CloseContainer(&elem_writer);
93 sub_writer.OpenDictEntry(&elem_writer);
94 elem_writer.AppendString("v6");
95 elem_writer.AppendVariantOfBool(ipv6);
96 sub_writer.CloseContainer(&elem_writer);
97 writer.CloseContainer(&sub_writer);
98 debugdaemon_proxy_->CallMethod(
99 &method_call,
100 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
101 base::Bind(&DebugDaemonClientImpl::OnGetRoutes,
102 weak_ptr_factory_.GetWeakPtr(),
103 callback));
106 virtual void GetNetworkStatus(const GetNetworkStatusCallback& callback)
107 OVERRIDE {
108 dbus::MethodCall method_call(debugd::kDebugdInterface,
109 debugd::kGetNetworkStatus);
110 debugdaemon_proxy_->CallMethod(
111 &method_call,
112 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
113 base::Bind(&DebugDaemonClientImpl::OnGetNetworkStatus,
114 weak_ptr_factory_.GetWeakPtr(),
115 callback));
118 virtual void GetModemStatus(const GetModemStatusCallback& callback)
119 OVERRIDE {
120 dbus::MethodCall method_call(debugd::kDebugdInterface,
121 debugd::kGetModemStatus);
122 debugdaemon_proxy_->CallMethod(
123 &method_call,
124 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
125 base::Bind(&DebugDaemonClientImpl::OnGetModemStatus,
126 weak_ptr_factory_.GetWeakPtr(),
127 callback));
130 virtual void GetWiMaxStatus(const GetWiMaxStatusCallback& callback)
131 OVERRIDE {
132 dbus::MethodCall method_call(debugd::kDebugdInterface,
133 debugd::kGetWiMaxStatus);
134 debugdaemon_proxy_->CallMethod(
135 &method_call,
136 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
137 base::Bind(&DebugDaemonClientImpl::OnGetWiMaxStatus,
138 weak_ptr_factory_.GetWeakPtr(),
139 callback));
142 virtual void GetNetworkInterfaces(
143 const GetNetworkInterfacesCallback& callback) OVERRIDE {
144 dbus::MethodCall method_call(debugd::kDebugdInterface,
145 debugd::kGetInterfaces);
146 debugdaemon_proxy_->CallMethod(
147 &method_call,
148 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
149 base::Bind(&DebugDaemonClientImpl::OnGetNetworkInterfaces,
150 weak_ptr_factory_.GetWeakPtr(),
151 callback));
154 virtual void GetPerfData(uint32_t duration,
155 const GetPerfDataCallback& callback) OVERRIDE {
156 dbus::MethodCall method_call(debugd::kDebugdInterface,
157 debugd::kGetRichPerfData);
158 dbus::MessageWriter writer(&method_call);
159 writer.AppendUint32(duration);
161 debugdaemon_proxy_->CallMethod(
162 &method_call,
163 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
164 base::Bind(&DebugDaemonClientImpl::OnGetPerfData,
165 weak_ptr_factory_.GetWeakPtr(),
166 callback));
169 virtual void GetScrubbedLogs(const GetLogsCallback& callback) OVERRIDE {
170 dbus::MethodCall method_call(debugd::kDebugdInterface,
171 debugd::kGetFeedbackLogs);
172 debugdaemon_proxy_->CallMethod(
173 &method_call,
174 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
175 base::Bind(&DebugDaemonClientImpl::OnGetAllLogs,
176 weak_ptr_factory_.GetWeakPtr(),
177 callback));
180 virtual void GetAllLogs(const GetLogsCallback& callback)
181 OVERRIDE {
182 dbus::MethodCall method_call(debugd::kDebugdInterface,
183 debugd::kGetAllLogs);
184 debugdaemon_proxy_->CallMethod(
185 &method_call,
186 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
187 base::Bind(&DebugDaemonClientImpl::OnGetAllLogs,
188 weak_ptr_factory_.GetWeakPtr(),
189 callback));
192 virtual void GetUserLogFiles(
193 const GetLogsCallback& callback) OVERRIDE {
194 dbus::MethodCall method_call(debugd::kDebugdInterface,
195 debugd::kGetUserLogFiles);
196 debugdaemon_proxy_->CallMethod(
197 &method_call,
198 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
199 base::Bind(&DebugDaemonClientImpl::OnGetUserLogFiles,
200 weak_ptr_factory_.GetWeakPtr(),
201 callback));
204 virtual void StartSystemTracing() OVERRIDE {
205 dbus::MethodCall method_call(
206 debugd::kDebugdInterface,
207 debugd::kSystraceStart);
208 dbus::MessageWriter writer(&method_call);
209 writer.AppendString("all"); // TODO(sleffler) parameterize category list
211 DVLOG(1) << "Requesting a systrace start";
212 debugdaemon_proxy_->CallMethod(
213 &method_call,
214 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
215 base::Bind(&DebugDaemonClientImpl::OnStartMethod,
216 weak_ptr_factory_.GetWeakPtr()));
219 virtual bool RequestStopSystemTracing(const StopSystemTracingCallback&
220 callback) OVERRIDE {
221 if (pipe_reader_ != NULL) {
222 LOG(ERROR) << "Busy doing StopSystemTracing";
223 return false;
226 scoped_refptr<base::TaskRunner> task_runner =
227 base::WorkerPool::GetTaskRunner(true /* task_is_slow */);
229 pipe_reader_.reset(new PipeReaderForString(
230 task_runner,
231 base::Bind(&DebugDaemonClientImpl::OnIOComplete,
232 weak_ptr_factory_.GetWeakPtr())));
234 base::File pipe_write_end = pipe_reader_->StartIO();
235 // Create dbus::FileDescriptor on the worker thread; on return we'll
236 // issue the D-Bus request to stop tracing and collect results.
237 base::PostTaskAndReplyWithResult(
238 task_runner,
239 FROM_HERE,
240 base::Bind(
241 &DebugDaemonClientImpl::CreateFileDescriptorToStopSystemTracing,
242 base::Passed(&pipe_write_end)),
243 base::Bind(
244 &DebugDaemonClientImpl::OnCreateFileDescriptorRequestStopSystem,
245 weak_ptr_factory_.GetWeakPtr(),
246 callback));
247 return true;
250 virtual void TestICMP(const std::string& ip_address,
251 const TestICMPCallback& callback) OVERRIDE {
252 dbus::MethodCall method_call(debugd::kDebugdInterface,
253 debugd::kTestICMP);
254 dbus::MessageWriter writer(&method_call);
255 writer.AppendString(ip_address);
256 debugdaemon_proxy_->CallMethod(
257 &method_call,
258 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
259 base::Bind(&DebugDaemonClientImpl::OnTestICMP,
260 weak_ptr_factory_.GetWeakPtr(),
261 callback));
264 virtual void TestICMPWithOptions(
265 const std::string& ip_address,
266 const std::map<std::string, std::string>& options,
267 const TestICMPCallback& callback) OVERRIDE {
268 dbus::MethodCall method_call(debugd::kDebugdInterface,
269 debugd::kTestICMPWithOptions);
270 dbus::MessageWriter writer(&method_call);
271 dbus::MessageWriter sub_writer(NULL);
272 dbus::MessageWriter elem_writer(NULL);
274 // Write the host.
275 writer.AppendString(ip_address);
277 // Write the options.
278 writer.OpenArray("{ss}", &sub_writer);
279 std::map<std::string, std::string>::const_iterator it;
280 for (it = options.begin(); it != options.end(); ++it) {
281 sub_writer.OpenDictEntry(&elem_writer);
282 elem_writer.AppendString(it->first);
283 elem_writer.AppendString(it->second);
284 sub_writer.CloseContainer(&elem_writer);
286 writer.CloseContainer(&sub_writer);
288 // Call the function.
289 debugdaemon_proxy_->CallMethod(
290 &method_call,
291 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
292 base::Bind(&DebugDaemonClientImpl::OnTestICMP,
293 weak_ptr_factory_.GetWeakPtr(),
294 callback));
297 virtual void UploadCrashes() OVERRIDE {
298 dbus::MethodCall method_call(debugd::kDebugdInterface,
299 debugd::kUploadCrashes);
300 debugdaemon_proxy_->CallMethod(
301 &method_call,
302 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
303 base::Bind(&DebugDaemonClientImpl::OnStartMethod,
304 weak_ptr_factory_.GetWeakPtr()));
307 protected:
308 virtual void Init(dbus::Bus* bus) OVERRIDE {
309 debugdaemon_proxy_ =
310 bus->GetObjectProxy(debugd::kDebugdServiceName,
311 dbus::ObjectPath(debugd::kDebugdServicePath));
314 private:
315 // Called when a CheckValidity response is received.
316 void OnCheckValidityGetDebugLogs(dbus::FileDescriptor* file_descriptor,
317 const GetDebugLogsCallback& callback) {
318 // Issue the dbus request to get debug logs.
319 dbus::MethodCall method_call(
320 debugd::kDebugdInterface,
321 debugd::kGetDebugLogs);
322 dbus::MessageWriter writer(&method_call);
323 writer.AppendFileDescriptor(*file_descriptor);
325 debugdaemon_proxy_->CallMethod(
326 &method_call,
327 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
328 base::Bind(&DebugDaemonClientImpl::OnGetDebugLogs,
329 weak_ptr_factory_.GetWeakPtr(),
330 callback));
333 // Called when a response for GetDebugLogs() is received.
334 void OnGetDebugLogs(const GetDebugLogsCallback& callback,
335 dbus::Response* response) {
336 if (!response) {
337 LOG(ERROR) << "Failed to get debug logs";
338 callback.Run(false);
339 return;
341 callback.Run(true);
344 // Called when a response for SetDebugMode() is received.
345 void OnSetDebugMode(const SetDebugModeCallback& callback,
346 dbus::Response* response) {
347 if (!response) {
348 LOG(ERROR) << "Failed to change debug mode";
349 callback.Run(false);
350 } else {
351 callback.Run(true);
355 void OnGetRoutes(const GetRoutesCallback& callback,
356 dbus::Response* response) {
357 std::vector<std::string> routes;
358 if (response) {
359 dbus::MessageReader reader(response);
360 if (reader.PopArrayOfStrings(&routes)) {
361 callback.Run(true, routes);
362 } else {
363 LOG(ERROR) << "Got non-array response from GetRoutes";
364 callback.Run(false, routes);
366 } else {
367 callback.Run(false, routes);
371 void OnGetNetworkStatus(const GetNetworkStatusCallback& callback,
372 dbus::Response* response) {
373 std::string status;
374 if (response && dbus::MessageReader(response).PopString(&status))
375 callback.Run(true, status);
376 else
377 callback.Run(false, "");
380 void OnGetModemStatus(const GetModemStatusCallback& callback,
381 dbus::Response* response) {
382 std::string status;
383 if (response && dbus::MessageReader(response).PopString(&status))
384 callback.Run(true, status);
385 else
386 callback.Run(false, "");
389 void OnGetWiMaxStatus(const GetWiMaxStatusCallback& callback,
390 dbus::Response* response) {
391 std::string status;
392 if (response && dbus::MessageReader(response).PopString(&status))
393 callback.Run(true, status);
394 else
395 callback.Run(false, "");
398 void OnGetNetworkInterfaces(const GetNetworkInterfacesCallback& callback,
399 dbus::Response* response) {
400 std::string status;
401 if (response && dbus::MessageReader(response).PopString(&status))
402 callback.Run(true, status);
403 else
404 callback.Run(false, "");
407 void OnGetPerfData(const GetPerfDataCallback& callback,
408 dbus::Response* response) {
409 std::vector<uint8> data;
411 if (!response) {
412 return;
415 dbus::MessageReader reader(response);
416 const uint8* buffer = NULL;
417 size_t buf_size = 0;
418 if (!reader.PopArrayOfBytes(&buffer, &buf_size))
419 return;
421 // TODO(asharif): Figure out a way to avoid this copy.
422 data.insert(data.end(), buffer, buffer + buf_size);
424 callback.Run(data);
427 void OnGetAllLogs(const GetLogsCallback& callback,
428 dbus::Response* response) {
429 std::map<std::string, std::string> logs;
430 bool broken = false; // did we see a broken (k,v) pair?
431 dbus::MessageReader sub_reader(NULL);
432 if (!response || !dbus::MessageReader(response).PopArray(&sub_reader)) {
433 callback.Run(false, logs);
434 return;
436 while (sub_reader.HasMoreData()) {
437 dbus::MessageReader sub_sub_reader(NULL);
438 std::string key, value;
439 if (!sub_reader.PopDictEntry(&sub_sub_reader)
440 || !sub_sub_reader.PopString(&key)
441 || !sub_sub_reader.PopString(&value)) {
442 broken = true;
443 break;
445 logs[key] = value;
447 callback.Run(!sub_reader.HasMoreData() && !broken, logs);
450 void OnGetUserLogFiles(const GetLogsCallback& callback,
451 dbus::Response* response) {
452 return OnGetAllLogs(callback, response);
455 // Called when a response for a simple start is received.
456 void OnStartMethod(dbus::Response* response) {
457 if (!response) {
458 LOG(ERROR) << "Failed to request start";
459 return;
463 // Creates dbus::FileDescriptor from base::File.
464 static scoped_ptr<dbus::FileDescriptor>
465 CreateFileDescriptorToStopSystemTracing(base::File pipe_write_end) {
466 if (!pipe_write_end.IsValid()) {
467 LOG(ERROR) << "Cannot create pipe reader";
468 // NB: continue anyway to shutdown tracing; toss trace data
469 pipe_write_end.Initialize(base::FilePath(FILE_PATH_LITERAL("/dev/null")),
470 base::File::FLAG_OPEN | base::File::FLAG_WRITE);
471 // TODO(sleffler) if this fails AppendFileDescriptor will abort
473 scoped_ptr<dbus::FileDescriptor> file_descriptor(new dbus::FileDescriptor);
474 file_descriptor->PutValue(pipe_write_end.TakePlatformFile());
475 file_descriptor->CheckValidity();
476 return file_descriptor.Pass();
479 // Called when a CheckValidity response is received.
480 void OnCreateFileDescriptorRequestStopSystem(
481 const StopSystemTracingCallback& callback,
482 scoped_ptr<dbus::FileDescriptor> file_descriptor) {
483 DCHECK(file_descriptor);
485 // Issue the dbus request to stop system tracing
486 dbus::MethodCall method_call(
487 debugd::kDebugdInterface,
488 debugd::kSystraceStop);
489 dbus::MessageWriter writer(&method_call);
490 writer.AppendFileDescriptor(*file_descriptor);
492 callback_ = callback;
494 DVLOG(1) << "Requesting a systrace stop";
495 debugdaemon_proxy_->CallMethod(
496 &method_call,
497 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
498 base::Bind(&DebugDaemonClientImpl::OnRequestStopSystemTracing,
499 weak_ptr_factory_.GetWeakPtr()));
502 // Called when a response for RequestStopSystemTracing() is received.
503 void OnRequestStopSystemTracing(dbus::Response* response) {
504 if (!response) {
505 LOG(ERROR) << "Failed to request systrace stop";
506 // If debugd crashes or completes I/O before this message is processed
507 // then pipe_reader_ can be NULL, see OnIOComplete().
508 if (pipe_reader_.get())
509 pipe_reader_->OnDataReady(-1); // terminate data stream
511 // NB: requester is signaled when i/o completes
514 void OnTestICMP(const TestICMPCallback& callback, dbus::Response* response) {
515 std::string status;
516 if (response && dbus::MessageReader(response).PopString(&status))
517 callback.Run(true, status);
518 else
519 callback.Run(false, "");
522 // Called when pipe i/o completes; pass data on and delete the instance.
523 void OnIOComplete() {
524 std::string pipe_data;
525 pipe_reader_->GetData(&pipe_data);
526 callback_.Run(base::RefCountedString::TakeString(&pipe_data));
527 pipe_reader_.reset();
530 dbus::ObjectProxy* debugdaemon_proxy_;
531 scoped_ptr<PipeReaderForString> pipe_reader_;
532 StopSystemTracingCallback callback_;
533 base::WeakPtrFactory<DebugDaemonClientImpl> weak_ptr_factory_;
535 DISALLOW_COPY_AND_ASSIGN(DebugDaemonClientImpl);
538 DebugDaemonClient::DebugDaemonClient() {
541 DebugDaemonClient::~DebugDaemonClient() {
544 // static
545 DebugDaemonClient::StopSystemTracingCallback
546 DebugDaemonClient::EmptyStopSystemTracingCallback() {
547 return base::Bind(&EmptyStopSystemTracingCallbackBody);
550 // static
551 DebugDaemonClient* DebugDaemonClient::Create() {
552 return new DebugDaemonClientImpl();
555 } // namespace chromeos