blob: 5016b0b750ce0508115439642ed83204ff7902a2 [file] [log] [blame]
Alex Vakulenkob511e562014-09-12 10:27:23 -07001// Copyright 2014 The Chromium OS 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.
4
5// This is a sample daemon that "handles" Buffet commands.
6// It just prints the information about the command received to stdout and
7// marks the command as processed.
8
9#include <string>
10#include <sysexits.h>
11
12#include <base/bind.h>
13#include <base/command_line.h>
14#include <base/format_macros.h>
Vitaly Bukae25f6fa2015-04-29 12:16:58 -070015#include <base/json/json_writer.h>
16#include <base/values.h>
Alex Vakulenkob511e562014-09-12 10:27:23 -070017#include <chromeos/daemons/dbus_daemon.h>
18#include <chromeos/map_utils.h>
19#include <chromeos/strings/string_utils.h>
20#include <chromeos/syslog_logging.h>
21
Alex Vakulenko94858962014-12-01 17:53:27 -080022#include "buffet/dbus-proxies.h"
Alex Vakulenkob511e562014-09-12 10:27:23 -070023
Alex Vakulenko62c1b3a2015-04-13 16:05:10 -070024namespace {
Vitaly Bukae25f6fa2015-04-29 12:16:58 -070025
26std::unique_ptr<base::DictionaryValue> DictionaryToJson(
27 const chromeos::VariantDictionary& dictionary);
28
29std::unique_ptr<base::Value> AnyToJson(const chromeos::Any& value) {
30 if (value.IsTypeCompatible<chromeos::VariantDictionary>())
31 return DictionaryToJson(value.Get<chromeos::VariantDictionary>());
32
33 if (value.IsTypeCompatible<std::string>()) {
34 return std::unique_ptr<base::Value>{
35 new base::StringValue(value.Get<std::string>())};
36 }
37
38 if (value.IsTypeCompatible<double>()) {
39 return std::unique_ptr<base::Value>{
40 new base::FundamentalValue(value.Get<double>())};
41 }
42
43 if (value.IsTypeCompatible<bool>()) {
44 return std::unique_ptr<base::Value>{
45 new base::FundamentalValue(value.Get<bool>())};
46 }
47
48 if (value.IsTypeCompatible<int>()) {
49 return std::unique_ptr<base::Value>{
50 new base::FundamentalValue(value.Get<int>())};
51 }
52
53 LOG(FATAL) << "Unsupported type:" << value.GetType().name();
54 return {};
55}
56
57std::unique_ptr<base::DictionaryValue> DictionaryToJson(
58 const chromeos::VariantDictionary& dictionary) {
59 std::unique_ptr<base::DictionaryValue> result{new base::DictionaryValue};
60 for (const auto& it : dictionary)
61 result->Set(it.first, AnyToJson(it.second).release());
62 return result;
63}
64
65std::string DictionaryToString(const chromeos::VariantDictionary& dictionary) {
66 std::unique_ptr<base::DictionaryValue> json{DictionaryToJson(dictionary)};
67 std::string str;
Alex Vakulenkoab4e4ff2015-06-15 12:53:22 -070068 base::JSONWriter::Write(*json, &str);
Vitaly Bukae25f6fa2015-04-29 12:16:58 -070069 return str;
70}
71
Alex Vakulenko62c1b3a2015-04-13 16:05:10 -070072} // anonymous namespace
73
Alex Vakulenko1e3a66b2015-05-22 15:48:53 -070074class Daemon final : public chromeos::DBusDaemon {
Alex Vakulenkob511e562014-09-12 10:27:23 -070075 public:
76 Daemon() = default;
77
78 protected:
79 int OnInit() override;
80 void OnShutdown(int* return_code) override;
81
82 private:
Alex Vakulenko63bdf082015-08-21 09:27:12 -070083 std::unique_ptr<com::android::Weave::ObjectManagerProxy> object_manager_;
Alex Vakulenkob511e562014-09-12 10:27:23 -070084
Alex Vakulenko63bdf082015-08-21 09:27:12 -070085 void OnBuffetCommand(com::android::Weave::CommandProxy* command);
Alex Vakulenko94858962014-12-01 17:53:27 -080086 void OnBuffetCommandRemoved(const dbus::ObjectPath& object_path);
Alex Vakulenko63bdf082015-08-21 09:27:12 -070087 void OnPropertyChange(com::android::Weave::CommandProxy* command,
Alex Vakulenko94858962014-12-01 17:53:27 -080088 const std::string& property_name);
Alex Vakulenko63bdf082015-08-21 09:27:12 -070089 void OnCommandProgress(com::android::Weave::CommandProxy* command,
Alex Vakulenko94858962014-12-01 17:53:27 -080090 int progress);
Alex Vakulenkob511e562014-09-12 10:27:23 -070091
92 DISALLOW_COPY_AND_ASSIGN(Daemon);
93};
94
95int Daemon::OnInit() {
96 int return_code = chromeos::DBusDaemon::OnInit();
97 if (return_code != EX_OK)
98 return return_code;
99
Alex Vakulenko63bdf082015-08-21 09:27:12 -0700100 object_manager_.reset(new com::android::Weave::ObjectManagerProxy{bus_});
Alex Vakulenko94858962014-12-01 17:53:27 -0800101 object_manager_->SetCommandAddedCallback(
102 base::Bind(&Daemon::OnBuffetCommand, base::Unretained(this)));
103 object_manager_->SetCommandRemovedCallback(
104 base::Bind(&Daemon::OnBuffetCommandRemoved, base::Unretained(this)));
Alex Vakulenkob511e562014-09-12 10:27:23 -0700105
106 printf("Waiting for commands...\n");
107 return EX_OK;
108}
109
110void Daemon::OnShutdown(int* return_code) {
111 printf("Shutting down...\n");
112}
113
Alex Vakulenko63bdf082015-08-21 09:27:12 -0700114void Daemon::OnPropertyChange(com::android::Weave::CommandProxy* command,
Alex Vakulenko94858962014-12-01 17:53:27 -0800115 const std::string& property_name) {
116 printf("Notification: property '%s' on command '%s' changed.\n",
117 property_name.c_str(), command->id().c_str());
Vitaly Bukae25f6fa2015-04-29 12:16:58 -0700118 printf(" Current command status: '%s'\n", command->status().c_str());
119 std::string progress = DictionaryToString(command->progress());
120 printf(" Current command progress: %s\n", progress.c_str());
121 std::string results = DictionaryToString(command->results());
122 printf(" Current command results: %s\n", results.c_str());
Alex Vakulenko94858962014-12-01 17:53:27 -0800123}
124
Alex Vakulenko63bdf082015-08-21 09:27:12 -0700125void Daemon::OnBuffetCommand(com::android::Weave::CommandProxy* command) {
Alex Vakulenko62c1b3a2015-04-13 16:05:10 -0700126 // "Handle" only commands that belong to this daemon's category.
Alex Vakulenko2915a7b2015-10-07 17:04:00 -0700127 if (command->status() == "done")
Alex Vakulenko62c1b3a2015-04-13 16:05:10 -0700128 return;
129
Alex Vakulenko94858962014-12-01 17:53:27 -0800130 command->SetPropertyChangedCallback(base::Bind(&Daemon::OnPropertyChange,
131 base::Unretained(this)));
132 printf("++++++++++++++++++++++++++++++++++++++++++++++++\n");
133 printf("Command received: %s\n", command->name().c_str());
134 printf("DBus Object Path: %s\n", command->GetObjectPath().value().c_str());
Alex Vakulenko94858962014-12-01 17:53:27 -0800135 printf(" ID: %s\n", command->id().c_str());
136 printf(" status: %s\n", command->status().c_str());
Alex Vakulenkod4190442015-04-20 12:33:52 -0700137 printf(" origin: %s\n", command->origin().c_str());
Vitaly Bukae25f6fa2015-04-29 12:16:58 -0700138 std::string param_names = DictionaryToString(command->parameters());
139 printf(" parameters: %s\n", param_names.c_str());
Alex Vakulenko94858962014-12-01 17:53:27 -0800140 OnCommandProgress(command, 0);
141}
142
Alex Vakulenko63bdf082015-08-21 09:27:12 -0700143void Daemon::OnCommandProgress(com::android::Weave::CommandProxy* command,
Alex Vakulenko94858962014-12-01 17:53:27 -0800144 int progress) {
Vitaly Bukae25f6fa2015-04-29 12:16:58 -0700145 printf("Updating command '%s' progress to %d%%\n", command->id().c_str(),
146 progress);
147 auto new_progress = command->progress();
148 new_progress["progress"] = progress;
149 command->SetProgress(new_progress, nullptr);
150
Alex Vakulenko94858962014-12-01 17:53:27 -0800151 if (progress >= 100) {
152 command->Done(nullptr);
153 } else {
Alex Vakulenko94858962014-12-01 17:53:27 -0800154 base::MessageLoop::current()->PostDelayedTask(
Vitaly Bukae25f6fa2015-04-29 12:16:58 -0700155 FROM_HERE, base::Bind(&Daemon::OnCommandProgress,
156 base::Unretained(this), command, progress + 10),
Alex Vakulenko94858962014-12-01 17:53:27 -0800157 base::TimeDelta::FromSeconds(1));
158 }
159}
160
161void Daemon::OnBuffetCommandRemoved(const dbus::ObjectPath& object_path) {
162 printf("------------------------------------------------\n");
163 printf("Command removed\n");
164 printf("DBus Object Path: %s\n", object_path.value().c_str());
Alex Vakulenkob511e562014-09-12 10:27:23 -0700165}
166
167int main(int argc, char* argv[]) {
Alex Vakulenko18862e42015-04-02 14:31:10 -0700168 base::CommandLine::Init(argc, argv);
Alex Vakulenkob511e562014-09-12 10:27:23 -0700169 chromeos::InitLog(chromeos::kLogToSyslog |
170 chromeos::kLogToStderr |
171 chromeos::kLogHeader);
172 Daemon daemon;
173 return daemon.Run();
174}