| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chromeos/ash/components/dbus/debug_daemon/debug_daemon_client.h" |
| |
| #include <fcntl.h> |
| #include <stddef.h> |
| #include <stdint.h> |
| #include <unistd.h> |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/files/file_path.h" |
| #include "base/functional/bind.h" |
| #include "base/functional/callback_helpers.h" |
| #include "base/json/json_string_value_serializer.h" |
| #include "base/location.h" |
| #include "base/logging.h" |
| #include "base/observer_list.h" |
| #include "base/posix/eintr_wrapper.h" |
| #include "base/strings/string_split.h" |
| #include "base/strings/string_util.h" |
| #include "base/task/single_thread_task_runner.h" |
| #include "base/task/thread_pool.h" |
| #include "base/trace_event/trace_config.h" |
| #include "chromeos/ash/components/dbus/cryptohome/rpc.pb.h" |
| #include "chromeos/ash/components/dbus/debug_daemon/fake_debug_daemon_client.h" |
| #include "chromeos/ash/components/dbus/debug_daemon/metrics.h" |
| #include "chromeos/dbus/common/dbus_library_error.h" |
| #include "chromeos/dbus/common/pipe_reader.h" |
| #include "dbus/bus.h" |
| #include "dbus/message.h" |
| #include "dbus/object_path.h" |
| #include "dbus/object_proxy.h" |
| |
| namespace ash { |
| |
| namespace { |
| |
| const char kCrOSTracingAgentName[] = "cros"; |
| const char kCrOSTraceLabel[] = "systemTraceEvents"; |
| |
| // Because the cheets logs are very huge, we set the D-Bus timeout to 2 minutes. |
| const int kBigLogsDBusTimeoutMS = 120 * 1000; |
| |
| // crash_sender could take a while to run if the network connection is slow, so |
| // wait up to 20 seconds for it. |
| const int kCrashSenderTimeoutMS = 20 * 1000; |
| |
| // NOTE: This does not use the typical pattern of a single `g_instance` variable |
| // due to browser_tests that need to temporarily override the existing instance |
| // with a specialized subclass. |
| DebugDaemonClient* g_instance = nullptr; |
| DebugDaemonClient* g_instance_for_test = nullptr; |
| |
| // A self-deleting object that wraps the pipe reader operations for reading the |
| // big feedback logs. It will delete itself once the pipe stream has been |
| // terminated. Once the data has been completely read from the pipe, it invokes |
| // the GetLogsCallback |callback| passing the deserialized logs data back to |
| // the requester. |
| class PipeReaderWrapper : public base::SupportsWeakPtr<PipeReaderWrapper> { |
| public: |
| explicit PipeReaderWrapper(DebugDaemonClient::GetLogsCallback callback) |
| : pipe_reader_(base::ThreadPool::CreateTaskRunner( |
| {base::MayBlock(), |
| base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})), |
| callback_(std::move(callback)) {} |
| |
| PipeReaderWrapper(const PipeReaderWrapper&) = delete; |
| PipeReaderWrapper& operator=(const PipeReaderWrapper&) = delete; |
| |
| base::ScopedFD Initialize() { |
| return pipe_reader_.StartIO( |
| base::BindOnce(&PipeReaderWrapper::OnIOComplete, AsWeakPtr())); |
| } |
| |
| void OnIOComplete(absl::optional<std::string> result) { |
| if (!result.has_value()) { |
| VLOG(1) << "Failed to read data."; |
| RecordGetFeedbackLogsV2DbusResult( |
| GetFeedbackLogsV2DbusResult::kErrorReadingData); |
| RunCallbackAndDestroy(absl::nullopt); |
| return; |
| } |
| |
| JSONStringValueDeserializer json_reader(result.value()); |
| std::unique_ptr<base::Value> logs( |
| json_reader.Deserialize(nullptr, nullptr)); |
| if (!logs.get() || !logs->is_dict()) { |
| VLOG(1) << "Failed to deserialize the JSON logs."; |
| RecordGetFeedbackLogsV2DbusResult( |
| GetFeedbackLogsV2DbusResult::kErrorDeserializingJSonLogs); |
| RunCallbackAndDestroy(absl::nullopt); |
| return; |
| } |
| std::map<std::string, std::string> data; |
| for (const auto [dict_key, dict_value] : logs->GetDict()) { |
| data[dict_key] = dict_value.GetString(); |
| } |
| RunCallbackAndDestroy(std::move(data)); |
| } |
| |
| void TerminateStream() { |
| VLOG(1) << "Terminated"; |
| RunCallbackAndDestroy(absl::nullopt); |
| } |
| |
| private: |
| void RunCallbackAndDestroy( |
| absl::optional<std::map<std::string, std::string>> result) { |
| if (result.has_value()) { |
| std::move(callback_).Run(true, std::move(result.value())); |
| } else { |
| std::move(callback_).Run(false, std::map<std::string, std::string>()); |
| } |
| delete this; |
| } |
| |
| chromeos::PipeReader pipe_reader_; |
| DebugDaemonClient::GetLogsCallback callback_; |
| }; |
| |
| // The DebugDaemonClient implementation used in production. |
| class DebugDaemonClientImpl : public DebugDaemonClient { |
| public: |
| DebugDaemonClientImpl() : debugdaemon_proxy_(nullptr) {} |
| |
| DebugDaemonClientImpl(const DebugDaemonClientImpl&) = delete; |
| DebugDaemonClientImpl& operator=(const DebugDaemonClientImpl&) = delete; |
| |
| ~DebugDaemonClientImpl() override = default; |
| |
| // DebugDaemonClient override. |
| void DumpDebugLogs(bool is_compressed, |
| int file_descriptor, |
| chromeos::VoidDBusMethodCallback callback) override { |
| // Issue the dbus request to get debug logs. |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kDumpDebugLogs); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendBool(is_compressed); |
| writer.AppendFileDescriptor(file_descriptor); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, kBigLogsDBusTimeoutMS, |
| base::BindOnce(&DebugDaemonClientImpl::OnVoidMethod, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void SetDebugMode(const std::string& subsystem, |
| chromeos::VoidDBusMethodCallback callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kSetDebugMode); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString(subsystem); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnVoidMethod, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void GetRoutes(bool numeric, |
| bool ipv6, |
| bool all_tables, |
| chromeos::DBusMethodCallback<std::vector<std::string>> |
| callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, debugd::kGetRoutes); |
| dbus::MessageWriter writer(&method_call); |
| dbus::MessageWriter sub_writer(NULL); |
| writer.OpenArray("{sv}", &sub_writer); |
| dbus::MessageWriter elem_writer(NULL); |
| sub_writer.OpenDictEntry(&elem_writer); |
| elem_writer.AppendString("numeric"); |
| elem_writer.AppendVariantOfBool(numeric); |
| sub_writer.CloseContainer(&elem_writer); |
| sub_writer.OpenDictEntry(&elem_writer); |
| elem_writer.AppendString("v6"); |
| elem_writer.AppendVariantOfBool(ipv6); |
| sub_writer.CloseContainer(&elem_writer); |
| sub_writer.OpenDictEntry(&elem_writer); |
| elem_writer.AppendString("all"); |
| elem_writer.AppendVariantOfBool(all_tables); |
| sub_writer.CloseContainer(&elem_writer); |
| writer.CloseContainer(&sub_writer); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnGetRoutes, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void GetNetworkStatus( |
| chromeos::DBusMethodCallback<std::string> callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kGetNetworkStatus); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnStringMethod, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void GetNetworkInterfaces( |
| chromeos::DBusMethodCallback<std::string> callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kGetInterfaces); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnStringMethod, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void GetPerfOutput(const std::vector<std::string>& quipper_args, |
| bool disable_cpu_idle, |
| int file_descriptor, |
| chromeos::DBusMethodCallback<uint64_t> callback) override { |
| DCHECK(file_descriptor); |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kGetPerfOutputV2); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendArrayOfStrings(quipper_args); |
| writer.AppendBool(disable_cpu_idle); |
| writer.AppendFileDescriptor(file_descriptor); |
| |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnUint64Method, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void StopPerf(uint64_t session_id, |
| chromeos::VoidDBusMethodCallback callback) override { |
| DCHECK(session_id); |
| dbus::MethodCall method_call(debugd::kDebugdInterface, debugd::kStopPerf); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendUint64(session_id); |
| |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnVoidMethod, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void GetFeedbackLogsV2( |
| const cryptohome::AccountIdentifier& id, |
| const std::vector<debugd::FeedbackLogType>& requested_logs, |
| GetLogsCallback callback) override { |
| // The PipeReaderWrapper is a self-deleting object; we don't have to worry |
| // about ownership or lifetime. We need to create a new one for each Big |
| // Logs requests in order to queue these requests. One request can take a |
| // long time to be processed and a new request should never be ignored nor |
| // cancels the on-going one. |
| PipeReaderWrapper* pipe_reader = new PipeReaderWrapper(std::move(callback)); |
| base::ScopedFD pipe_write_end = pipe_reader->Initialize(); |
| |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kGetFeedbackLogsV2); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendFileDescriptor(pipe_write_end.get()); |
| writer.AppendString(id.account_id()); |
| // Write |requested_logs|. |
| dbus::MessageWriter sub_writer(nullptr); |
| writer.OpenArray("i", &sub_writer); |
| for (auto log_type : requested_logs) { |
| sub_writer.AppendInt32(log_type); |
| } |
| writer.CloseContainer(&sub_writer); |
| |
| DVLOG(1) << "Requesting feedback logs"; |
| debugdaemon_proxy_->CallMethodWithErrorResponse( |
| &method_call, kBigLogsDBusTimeoutMS, |
| base::BindOnce(&DebugDaemonClientImpl::OnFeedbackLogsResponse, |
| weak_ptr_factory_.GetWeakPtr(), |
| pipe_reader->AsWeakPtr())); |
| } |
| |
| void GetFeedbackLogsV3( |
| const cryptohome::AccountIdentifier& id, |
| const std::vector<debugd::FeedbackLogType>& requested_logs, |
| GetLogsCallback callback) override { |
| // The PipeReaderWrapper is a self-deleting object; we don't have to worry |
| // about ownership or lifetime. We need to create a new one for each Big |
| // Logs requests in order to queue these requests. One request can take a |
| // long time to be processed and a new request should never be ignored nor |
| // cancels the on-going one. |
| PipeReaderWrapper* pipe_reader = new PipeReaderWrapper(std::move(callback)); |
| base::ScopedFD pipe_write_end = pipe_reader->Initialize(); |
| |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kGetFeedbackLogsV3); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendFileDescriptor(pipe_write_end.get()); |
| writer.AppendString(id.account_id()); |
| // Write |requested_logs|. |
| dbus::MessageWriter sub_writer(nullptr); |
| writer.OpenArray("i", &sub_writer); |
| for (auto log_type : requested_logs) { |
| sub_writer.AppendInt32(log_type); |
| } |
| writer.CloseContainer(&sub_writer); |
| |
| DVLOG(1) << "Requesting feedback logs"; |
| debugdaemon_proxy_->CallMethodWithErrorResponse( |
| &method_call, kBigLogsDBusTimeoutMS, |
| base::BindOnce(&DebugDaemonClientImpl::OnFeedbackLogsResponse, |
| weak_ptr_factory_.GetWeakPtr(), |
| pipe_reader->AsWeakPtr())); |
| } |
| |
| void BackupArcBugReport(const cryptohome::AccountIdentifier& id, |
| chromeos::VoidDBusMethodCallback callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kBackupArcBugReport); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString(id.account_id()); |
| |
| DVLOG(1) << "Backing up ARC bug report"; |
| debugdaemon_proxy_->CallMethod( |
| &method_call, kBigLogsDBusTimeoutMS, |
| base::BindOnce(&DebugDaemonClientImpl::OnVoidMethod, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void GetAllLogs(GetLogsCallback callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, debugd::kGetAllLogs); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnGetAllLogs, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void GetLog(const std::string& log_name, |
| chromeos::DBusMethodCallback<std::string> callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, debugd::kGetLog); |
| dbus::MessageWriter(&method_call).AppendString(log_name); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnStringMethod, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| // base::trace_event::TracingAgent implementation. |
| std::string GetTracingAgentName() override { return kCrOSTracingAgentName; } |
| |
| std::string GetTraceEventLabel() override { return kCrOSTraceLabel; } |
| |
| void StartAgentTracing(const base::trace_event::TraceConfig& trace_config, |
| StartAgentTracingCallback callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kSystraceStart); |
| dbus::MessageWriter writer(&method_call); |
| if (trace_config.systrace_events().empty()) { |
| writer.AppendString("all"); // TODO(sleffler) parameterize category list |
| } else { |
| std::string events; |
| for (const std::string& event : trace_config.systrace_events()) { |
| if (!events.empty()) |
| events += " "; |
| events += event; |
| } |
| writer.AppendString(events); |
| } |
| |
| DVLOG(1) << "Requesting a systrace start"; |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnStartMethod, |
| weak_ptr_factory_.GetWeakPtr())); |
| |
| base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( |
| FROM_HERE, base::BindOnce(std::move(callback), GetTracingAgentName(), |
| true /* success */)); |
| } |
| |
| void StopAgentTracing(StopAgentTracingCallback callback) override { |
| DCHECK(stop_agent_tracing_task_runner_); |
| if (pipe_reader_ != NULL) { |
| LOG(ERROR) << "Busy doing StopSystemTracing"; |
| return; |
| } |
| |
| pipe_reader_ = |
| std::make_unique<chromeos::PipeReader>(stop_agent_tracing_task_runner_); |
| callback_ = std::move(callback); |
| base::ScopedFD pipe_write_end = pipe_reader_->StartIO(base::BindOnce( |
| &DebugDaemonClientImpl::OnIOComplete, weak_ptr_factory_.GetWeakPtr())); |
| |
| DCHECK(pipe_write_end.is_valid()); |
| // Issue the dbus request to stop system tracing |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kSystraceStop); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendFileDescriptor(pipe_write_end.get()); |
| |
| DVLOG(1) << "Requesting a systrace stop"; |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnStopAgentTracing, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void SetStopAgentTracingTaskRunner( |
| scoped_refptr<base::TaskRunner> task_runner) override { |
| stop_agent_tracing_task_runner_ = task_runner; |
| } |
| |
| void TestICMP(const std::string& ip_address, |
| TestICMPCallback callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, debugd::kTestICMP); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString(ip_address); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnTestICMP, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void TestICMPWithOptions(const std::string& ip_address, |
| const std::map<std::string, std::string>& options, |
| TestICMPCallback callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kTestICMPWithOptions); |
| dbus::MessageWriter writer(&method_call); |
| dbus::MessageWriter sub_writer(NULL); |
| dbus::MessageWriter elem_writer(NULL); |
| |
| // Write the host. |
| writer.AppendString(ip_address); |
| |
| // Write the options. |
| writer.OpenArray("{ss}", &sub_writer); |
| std::map<std::string, std::string>::const_iterator it; |
| for (it = options.begin(); it != options.end(); ++it) { |
| sub_writer.OpenDictEntry(&elem_writer); |
| elem_writer.AppendString(it->first); |
| elem_writer.AppendString(it->second); |
| sub_writer.CloseContainer(&elem_writer); |
| } |
| writer.CloseContainer(&sub_writer); |
| |
| // Call the function. |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnTestICMP, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void UploadCrashes(UploadCrashesCallback callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kUploadCrashes); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, kCrashSenderTimeoutMS, |
| base::BindOnce(&DebugDaemonClientImpl::OnUploadCrashes, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void OnUploadCrashes(UploadCrashesCallback callback, |
| dbus::Response* response) { |
| if (callback.is_null()) { |
| return; |
| } |
| |
| std::move(callback).Run(response != nullptr); |
| } |
| |
| void EnableDebuggingFeatures(const std::string& password, |
| EnableDebuggingCallback callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kEnableChromeDevFeatures); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString(password); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnEnableDebuggingFeatures, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void QueryDebuggingFeatures(QueryDevFeaturesCallback callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kQueryDevFeatures); |
| dbus::MessageWriter writer(&method_call); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnQueryDebuggingFeatures, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void RemoveRootfsVerification(EnableDebuggingCallback callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kRemoveRootfsVerification); |
| dbus::MessageWriter writer(&method_call); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnRemoveRootfsVerification, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void WaitForServiceToBeAvailable( |
| chromeos::WaitForServiceToBeAvailableCallback callback) override { |
| debugdaemon_proxy_->WaitForServiceToBeAvailable(std::move(callback)); |
| } |
| |
| void SetOomScoreAdj(const std::map<pid_t, int32_t>& pid_to_oom_score_adj, |
| SetOomScoreAdjCallback callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kSetOomScoreAdj); |
| dbus::MessageWriter writer(&method_call); |
| |
| dbus::MessageWriter sub_writer(nullptr); |
| writer.OpenArray("{ii}", &sub_writer); |
| |
| dbus::MessageWriter elem_writer(nullptr); |
| for (const auto& entry : pid_to_oom_score_adj) { |
| sub_writer.OpenDictEntry(&elem_writer); |
| elem_writer.AppendInt32(entry.first); |
| elem_writer.AppendInt32(entry.second); |
| sub_writer.CloseContainer(&elem_writer); |
| } |
| writer.CloseContainer(&sub_writer); |
| |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnSetOomScoreAdj, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void CupsAddManuallyConfiguredPrinter( |
| const std::string& name, |
| const std::string& uri, |
| const std::string& ppd_contents, |
| DebugDaemonClient::CupsAddPrinterCallback callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kCupsAddManuallyConfiguredPrinter); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString(name); |
| writer.AppendString(uri); |
| writer.AppendArrayOfBytes( |
| reinterpret_cast<const uint8_t*>(ppd_contents.data()), |
| ppd_contents.size()); |
| |
| debugdaemon_proxy_->CallMethodWithErrorResponse( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnPrinterAdded, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void CupsAddAutoConfiguredPrinter( |
| const std::string& name, |
| const std::string& uri, |
| DebugDaemonClient::CupsAddPrinterCallback callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kCupsAddAutoConfiguredPrinter); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString(name); |
| writer.AppendString(uri); |
| |
| debugdaemon_proxy_->CallMethodWithErrorResponse( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnPrinterAdded, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void CupsRemovePrinter(const std::string& name, |
| DebugDaemonClient::CupsRemovePrinterCallback callback, |
| base::OnceClosure error_callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kCupsRemovePrinter); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString(name); |
| |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnPrinterRemoved, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback), |
| std::move(error_callback))); |
| } |
| |
| void CupsRetrievePrinterPpd( |
| const std::string& name, |
| DebugDaemonClient::CupsRetrievePrinterPpdCallback callback, |
| base::OnceClosure error_callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kCupsRetrievePpd); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString(name); |
| |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnRetrievedPrinterPpd, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback), |
| std::move(error_callback))); |
| } |
| |
| void StartPluginVmDispatcher(const std::string& owner_id, |
| const std::string& lang, |
| PluginVmDispatcherCallback callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kStartVmPluginDispatcher); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString(owner_id); |
| writer.AppendString(lang); |
| debugdaemon_proxy_->CallMethodWithErrorResponse( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnStartPluginVmDispatcher, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void StopPluginVmDispatcher(PluginVmDispatcherCallback callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kStopVmPluginDispatcher); |
| dbus::MessageWriter writer(&method_call); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnStopPluginVmDispatcher, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void SetRlzPingSent(SetRlzPingSentCallback callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kSetRlzPingSent); |
| dbus::MessageWriter writer(&method_call); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnSetRlzPingSent, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void SetKstaledRatio(uint8_t val, KstaledRatioCallback callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kKstaledSetRatio); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendByte(val); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnSetKstaledRatio, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void SetSchedulerConfigurationV2( |
| const std::string& config_name, |
| bool lock_policy, |
| SetSchedulerConfigurationV2Callback callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kSetSchedulerConfigurationV2); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString(config_name); |
| writer.AppendBool(lock_policy); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnSetSchedulerConfigurationV2, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void SetU2fFlags(const std::set<std::string>& flags, |
| chromeos::VoidDBusMethodCallback callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kSetU2fFlags); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString(base::JoinString( |
| std::vector<std::string>(flags.begin(), flags.end()), ",")); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnVoidMethod, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void GetU2fFlags( |
| chromeos::DBusMethodCallback<std::set<std::string>> callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kGetU2fFlags); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnGetU2fFlags, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void SetSwapParameter( |
| const std::string& parameter, |
| int32_t value, |
| chromeos::DBusMethodCallback<std::string> callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, "SwapSetParameter"); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString(parameter); |
| writer.AppendInt32(value); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnSetSwapParameter, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void SwapZramEnableWriteback( |
| uint32_t size_mb, |
| chromeos::DBusMethodCallback<std::string> callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kSwapZramEnableWriteback); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendUint32(size_mb); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnZramWritebackOptionResult, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void SwapZramSetWritebackLimit( |
| uint32_t limit_pages, |
| chromeos::DBusMethodCallback<std::string> callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kSwapZramSetWritebackLimit); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendUint32(limit_pages); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnZramWritebackOptionResult, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void SwapZramMarkIdle( |
| uint32_t age_seconds, |
| chromeos::DBusMethodCallback<std::string> callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kSwapZramMarkIdle); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendUint32(age_seconds); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnZramWritebackOptionResult, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void InitiateSwapZramWriteback( |
| debugd::ZramWritebackMode mode, |
| chromeos::DBusMethodCallback<std::string> callback) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| "InitiateSwapZramWriteback"); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendUint32(mode); |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnZramWritebackOptionResult, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| } |
| |
| void StopPacketCapture(const std::string& handle) override { |
| dbus::MethodCall method_call(debugd::kDebugdInterface, |
| debugd::kPacketCaptureStop); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString(handle); |
| |
| debugdaemon_proxy_->CallMethod( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| base::BindOnce(&DebugDaemonClientImpl::OnStopMethod, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| // DebugDaemonClient Observer overrides. |
| void AddObserver(Observer* observer) override { |
| DCHECK(observer); |
| observers_.AddObserver(observer); |
| } |
| |
| void RemoveObserver(Observer* observer) override { |
| DCHECK(observer); |
| observers_.RemoveObserver(observer); |
| } |
| |
| void Init(dbus::Bus* bus) override { |
| debugdaemon_proxy_ = |
| bus->GetObjectProxy(debugd::kDebugdServiceName, |
| dbus::ObjectPath(debugd::kDebugdServicePath)); |
| // Listen to D-Bus signals emitted by debugd. |
| auto on_connected_callback = |
| base::BindRepeating(&DebugDaemonClientImpl::SignalConnected, |
| weak_ptr_factory_.GetWeakPtr()); |
| debugdaemon_proxy_->ConnectToSignal( |
| debugd::kDebugdInterface, debugd::kPacketCaptureStartSignal, |
| base::BindRepeating( |
| &DebugDaemonClientImpl::PacketCaptureStartSignalReceived, |
| weak_ptr_factory_.GetWeakPtr()), |
| on_connected_callback); |
| debugdaemon_proxy_->ConnectToSignal( |
| debugd::kDebugdInterface, debugd::kPacketCaptureStopSignal, |
| base::BindRepeating( |
| &DebugDaemonClientImpl::PacketCaptureStopSignalReceived, |
| weak_ptr_factory_.GetWeakPtr()), |
| on_connected_callback); |
| } |
| |
| private: |
| void OnGetRoutes( |
| chromeos::DBusMethodCallback<std::vector<std::string>> callback, |
| dbus::Response* response) { |
| if (!response) { |
| std::move(callback).Run(absl::nullopt); |
| return; |
| } |
| |
| std::vector<std::string> routes; |
| dbus::MessageReader reader(response); |
| if (!reader.PopArrayOfStrings(&routes)) { |
| LOG(ERROR) << "Got non-array response from GetRoutes"; |
| std::move(callback).Run(absl::nullopt); |
| return; |
| } |
| |
| std::move(callback).Run(std::move(routes)); |
| } |
| |
| void OnSetSwapParameter(chromeos::DBusMethodCallback<std::string> callback, |
| dbus::Response* response) { |
| if (!response) { |
| std::move(callback).Run(absl::nullopt); |
| return; |
| } |
| |
| std::string res; |
| dbus::MessageReader reader(response); |
| if (!reader.PopString(&res)) { |
| LOG(ERROR) << "Received a non-string response from dbus"; |
| std::move(callback).Run(absl::nullopt); |
| return; |
| } |
| |
| std::move(callback).Run(std::move(res)); |
| } |
| |
| void OnGetAllLogs(GetLogsCallback callback, dbus::Response* response) { |
| std::map<std::string, std::string> logs; |
| bool broken = false; // did we see a broken (k,v) pair? |
| dbus::MessageReader sub_reader(NULL); |
| if (!response || !dbus::MessageReader(response).PopArray(&sub_reader)) { |
| std::move(callback).Run(false, logs); |
| return; |
| } |
| while (sub_reader.HasMoreData()) { |
| dbus::MessageReader sub_sub_reader(NULL); |
| std::string key, value; |
| if (!sub_reader.PopDictEntry(&sub_sub_reader) || |
| !sub_sub_reader.PopString(&key) || |
| !sub_sub_reader.PopString(&value)) { |
| broken = true; |
| break; |
| } |
| logs[key] = value; |
| } |
| std::move(callback).Run(!sub_reader.HasMoreData() && !broken, logs); |
| } |
| |
| void OnFeedbackLogsResponse(base::WeakPtr<PipeReaderWrapper> pipe_reader, |
| dbus::Response* response, |
| dbus::ErrorResponse* err_response) { |
| RecordGetFeedbackLogsV2DbusError(err_response); |
| if (!response && pipe_reader.get()) { |
| // We need to terminate the data stream if an error occurred while the |
| // pipe reader is still waiting on read. |
| pipe_reader->TerminateStream(); |
| } |
| } |
| |
| // Called when a response for a simple start is received. |
| void OnStartMethod(dbus::Response* response) { |
| if (!response) { |
| LOG(ERROR) << "Failed to request start"; |
| return; |
| } |
| } |
| |
| // Called when a response for a simple stop is received. |
| void OnStopMethod(dbus::Response* response) { |
| if (!response) { |
| LOG(ERROR) << "Failed to request stop method through D-Bus"; |
| return; |
| } |
| } |
| |
| // Called when D-Bus method call which does not return the result is |
| // completed or on its error. |
| void OnVoidMethod(chromeos::VoidDBusMethodCallback callback, |
| dbus::Response* response) { |
| std::move(callback).Run(response); |
| } |
| |
| void OnUint64Method(chromeos::DBusMethodCallback<uint64_t> callback, |
| dbus::Response* response) { |
| if (!response) { |
| std::move(callback).Run(absl::nullopt); |
| return; |
| } |
| |
| dbus::MessageReader reader(response); |
| uint64_t result; |
| if (!reader.PopUint64(&result)) { |
| std::move(callback).Run(absl::nullopt); |
| return; |
| } |
| |
| std::move(callback).Run(std::move(result)); |
| } |
| |
| // Called when D-Bus method call which returns a string is completed or on |
| // its error. |
| void OnStringMethod(chromeos::DBusMethodCallback<std::string> callback, |
| dbus::Response* response) { |
| if (!response) { |
| std::move(callback).Run(absl::nullopt); |
| return; |
| } |
| |
| dbus::MessageReader reader(response); |
| std::string result; |
| if (!reader.PopString(&result)) { |
| std::move(callback).Run(absl::nullopt); |
| return; |
| } |
| |
| std::move(callback).Run(std::move(result)); |
| } |
| |
| void OnEnableDebuggingFeatures(EnableDebuggingCallback callback, |
| dbus::Response* response) { |
| if (callback.is_null()) |
| return; |
| |
| std::move(callback).Run(response != nullptr); |
| } |
| |
| void OnQueryDebuggingFeatures(QueryDevFeaturesCallback callback, |
| dbus::Response* response) { |
| if (callback.is_null()) |
| return; |
| |
| int32_t feature_mask = DEV_FEATURE_NONE; |
| if (!response || !dbus::MessageReader(response).PopInt32(&feature_mask)) { |
| std::move(callback).Run(false, |
| debugd::DevFeatureFlag::DEV_FEATURES_DISABLED); |
| return; |
| } |
| |
| std::move(callback).Run(true, feature_mask); |
| } |
| |
| void OnRemoveRootfsVerification(EnableDebuggingCallback callback, |
| dbus::Response* response) { |
| if (callback.is_null()) |
| return; |
| |
| std::move(callback).Run(response != nullptr); |
| } |
| |
| // Called when a response for StopAgentTracing() is received. |
| void OnStopAgentTracing(dbus::Response* response) { |
| if (!response) { |
| LOG(ERROR) << "Failed to request systrace stop"; |
| // If debugd crashes or completes I/O before this message is processed |
| // then pipe_reader_ can be NULL, see OnIOComplete(). |
| if (pipe_reader_.get()) { |
| pipe_reader_.reset(); |
| std::move(callback_).Run(GetTracingAgentName(), GetTraceEventLabel(), |
| scoped_refptr<base::RefCountedString>( |
| new base::RefCountedString())); |
| } |
| } |
| // NB: requester is signaled when i/o completes |
| } |
| |
| void OnTestICMP(TestICMPCallback callback, dbus::Response* response) { |
| std::string status; |
| if (!response || !dbus::MessageReader(response).PopString(&status)) { |
| std::move(callback).Run(absl::nullopt); |
| return; |
| } |
| |
| std::move(callback).Run(status); |
| } |
| |
| // Called when pipe i/o completes; pass data on and delete the instance. |
| void OnIOComplete(absl::optional<std::string> result) { |
| pipe_reader_.reset(); |
| std::string pipe_data = |
| result.has_value() ? std::move(result).value() : std::string(); |
| std::move(callback_).Run( |
| GetTracingAgentName(), GetTraceEventLabel(), |
| base::MakeRefCounted<base::RefCountedString>(std::move(pipe_data))); |
| } |
| |
| void OnSetOomScoreAdj(SetOomScoreAdjCallback callback, |
| dbus::Response* response) { |
| std::string output; |
| if (response && dbus::MessageReader(response).PopString(&output)) |
| std::move(callback).Run(true, output); |
| else |
| std::move(callback).Run(false, ""); |
| } |
| |
| void OnPrinterAdded(CupsAddPrinterCallback callback, |
| dbus::Response* response, |
| dbus::ErrorResponse* err_response) { |
| int32_t result; |
| |
| // If we get a normal response, we need not examine the error response. |
| if (response && dbus::MessageReader(response).PopInt32(&result)) { |
| DCHECK_GE(result, 0); |
| std::move(callback).Run(result); |
| return; |
| } |
| |
| // Without a normal response, we communicate the D-Bus error response |
| // to the callback. |
| std::string err_str; |
| if (err_response) { |
| dbus::MessageReader err_reader(err_response); |
| err_str = err_response->GetErrorName(); |
| } |
| chromeos::DBusLibraryError dbus_error = |
| chromeos::DBusLibraryErrorFromString(err_str); |
| std::move(callback).Run(dbus_error); |
| } |
| |
| void OnPrinterRemoved(CupsRemovePrinterCallback callback, |
| base::OnceClosure error_callback, |
| dbus::Response* response) { |
| bool result = false; |
| if (response && dbus::MessageReader(response).PopBool(&result)) |
| std::move(callback).Run(result); |
| else |
| std::move(error_callback).Run(); |
| } |
| |
| void OnRetrievedPrinterPpd(CupsRetrievePrinterPpdCallback callback, |
| base::OnceClosure error_callback, |
| dbus::Response* response) { |
| size_t length = 0; |
| const uint8_t* bytes = nullptr; |
| |
| if (!(response && |
| dbus::MessageReader(response).PopArrayOfBytes(&bytes, &length)) || |
| length == 0 || bytes == nullptr) { |
| LOG(ERROR) << "Failed to retrieve printer PPD"; |
| std::move(error_callback).Run(); |
| return; |
| } |
| |
| std::vector<uint8_t> data(bytes, bytes + length); |
| std::move(callback).Run(data); |
| } |
| |
| void OnStartPluginVmDispatcher(PluginVmDispatcherCallback callback, |
| dbus::Response* response, |
| dbus::ErrorResponse* error) { |
| if (error) { |
| LOG(ERROR) << "Failed to start dispatcher, DBus error " |
| << error->GetErrorName(); |
| std::move(callback).Run(false); |
| return; |
| } |
| |
| bool result = false; |
| if (response) { |
| dbus::MessageReader reader(response); |
| reader.PopBool(&result); |
| } |
| std::move(callback).Run(result); |
| } |
| |
| void OnStopPluginVmDispatcher(PluginVmDispatcherCallback callback, |
| dbus::Response* response) { |
| // Debugd just sends back an empty response, so we just check if |
| // the response exists |
| std::move(callback).Run(response != nullptr); |
| } |
| |
| void OnSetRlzPingSent(SetRlzPingSentCallback callback, |
| dbus::Response* response) { |
| bool result = false; |
| if (response) { |
| dbus::MessageReader reader(response); |
| reader.PopBool(&result); |
| } |
| std::move(callback).Run(result); |
| } |
| |
| void OnSetKstaledRatio(KstaledRatioCallback callback, |
| dbus::Response* response) { |
| if (!response) { |
| LOG(ERROR) << "Failed to read debugd response"; |
| std::move(callback).Run(false); |
| return; |
| } |
| |
| bool result = false; |
| dbus::MessageReader reader(response); |
| if (!reader.PopBool(&result)) { |
| LOG(ERROR) << "Debugd response did not contain a bool"; |
| std::move(callback).Run(false); |
| return; |
| } |
| |
| std::move(callback).Run(result); |
| } |
| |
| void OnSetSchedulerConfigurationV2( |
| SetSchedulerConfigurationV2Callback callback, |
| dbus::Response* response) { |
| if (!response) { |
| std::move(callback).Run(false, 0); |
| return; |
| } |
| |
| bool result = false; |
| uint32_t num_cores_disabled = 0; |
| dbus::MessageReader reader(response); |
| if (!reader.PopBool(&result) || !reader.PopUint32(&num_cores_disabled)) { |
| LOG(ERROR) << "Failed to read SetSchedulerConfigurationV2 response"; |
| std::move(callback).Run(false, 0); |
| return; |
| } |
| |
| std::move(callback).Run(result, num_cores_disabled); |
| } |
| |
| void OnGetU2fFlags( |
| chromeos::DBusMethodCallback<std::set<std::string>> callback, |
| dbus::Response* response) { |
| if (!response) { |
| std::move(callback).Run(absl::nullopt); |
| return; |
| } |
| |
| std::string flags_string; |
| dbus::MessageReader reader(response); |
| if (!reader.PopString(&flags_string)) { |
| LOG(ERROR) << "Failed to read GetU2fFlags response"; |
| std::move(callback).Run(absl::nullopt); |
| return; |
| } |
| |
| std::set<std::string> flags; |
| for (const auto& flag : |
| base::SplitString(flags_string, ",", base::TRIM_WHITESPACE, |
| base::SPLIT_WANT_NONEMPTY)) { |
| flags.insert(flag); |
| } |
| |
| std::move(callback).Run(std::move(flags)); |
| } |
| |
| void OnZramWritebackOptionResult( |
| chromeos::DBusMethodCallback<std::string> callback, |
| dbus::Response* response) { |
| if (!response) { |
| std::move(callback).Run(absl::nullopt); |
| return; |
| } |
| |
| std::string res; |
| dbus::MessageReader reader(response); |
| if (!reader.PopString(&res)) { |
| LOG(ERROR) << "Received a non-string response from dbus"; |
| std::move(callback).Run(absl::nullopt); |
| return; |
| } |
| |
| std::move(callback).Run(std::move(res)); |
| } |
| |
| // Called when a D-Bus signal is initially connected. |
| void SignalConnected(const std::string& interface_name, |
| const std::string& signal_name, |
| bool success) { |
| if (!success) |
| LOG(ERROR) << "Failed to connect to signal " << signal_name << "."; |
| } |
| |
| void PacketCaptureStartSignalReceived(dbus::Signal* signal) override { |
| for (auto& observer : observers_) |
| observer.OnPacketCaptureStarted(); |
| } |
| |
| void PacketCaptureStopSignalReceived(dbus::Signal* signal) override { |
| for (auto& observer : observers_) |
| observer.OnPacketCaptureStopped(); |
| } |
| |
| dbus::ObjectProxy* debugdaemon_proxy_; |
| std::unique_ptr<chromeos::PipeReader> pipe_reader_; |
| StopAgentTracingCallback callback_; |
| scoped_refptr<base::TaskRunner> stop_agent_tracing_task_runner_; |
| base::ObserverList<Observer> observers_; |
| base::WeakPtrFactory<DebugDaemonClientImpl> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace |
| |
| // static |
| DebugDaemonClient* DebugDaemonClient::Get() { |
| if (g_instance_for_test) |
| return g_instance_for_test; |
| return g_instance; |
| } |
| |
| // static |
| void DebugDaemonClient::Initialize(dbus::Bus* bus) { |
| CHECK(bus); |
| CHECK(!g_instance); |
| g_instance = new DebugDaemonClientImpl(); |
| g_instance->Init(bus); |
| } |
| |
| // static |
| void DebugDaemonClient::InitializeFake() { |
| CHECK(!g_instance); |
| g_instance = new FakeDebugDaemonClient(); |
| g_instance->Init(nullptr); |
| } |
| |
| // static |
| void DebugDaemonClient::SetInstanceForTest(DebugDaemonClient* client) { |
| g_instance_for_test = client; |
| } |
| |
| // static |
| void DebugDaemonClient::Shutdown() { |
| CHECK(g_instance); |
| delete g_instance; |
| g_instance = nullptr; |
| } |
| |
| DebugDaemonClient::DebugDaemonClient() = default; |
| |
| DebugDaemonClient::~DebugDaemonClient() = default; |
| |
| // static |
| std::unique_ptr<DebugDaemonClient> DebugDaemonClient::CreateInstance() { |
| return std::make_unique<DebugDaemonClientImpl>(); |
| } |
| |
| } // namespace ash |