blob: 0da72c224b8552645c308e978a969c32139a9bee [file] [log] [blame]
Alex Vakulenko89d9d5e2014-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 Buka4129dfa2015-04-29 12:16:58 -070015#include <base/json/json_writer.h>
16#include <base/values.h>
Alex Vakulenko89d9d5e2014-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 Vakulenko420e49f2014-12-01 17:53:27 -080022#include "buffet/dbus-proxies.h"
Alex Vakulenko89d9d5e2014-09-12 10:27:23 -070023
Alex Vakulenko5dd84342015-04-13 16:05:10 -070024namespace {
25const char kTestCommandCategory[] = "test";
Vitaly Buka4129dfa2015-04-29 12:16:58 -070026
27std::unique_ptr<base::DictionaryValue> DictionaryToJson(
28 const chromeos::VariantDictionary& dictionary);
29
30std::unique_ptr<base::Value> AnyToJson(const chromeos::Any& value) {
31 if (value.IsTypeCompatible<chromeos::VariantDictionary>())
32 return DictionaryToJson(value.Get<chromeos::VariantDictionary>());
33
34 if (value.IsTypeCompatible<std::string>()) {
35 return std::unique_ptr<base::Value>{
36 new base::StringValue(value.Get<std::string>())};
37 }
38
39 if (value.IsTypeCompatible<double>()) {
40 return std::unique_ptr<base::Value>{
41 new base::FundamentalValue(value.Get<double>())};
42 }
43
44 if (value.IsTypeCompatible<bool>()) {
45 return std::unique_ptr<base::Value>{
46 new base::FundamentalValue(value.Get<bool>())};
47 }
48
49 if (value.IsTypeCompatible<int>()) {
50 return std::unique_ptr<base::Value>{
51 new base::FundamentalValue(value.Get<int>())};
52 }
53
54 LOG(FATAL) << "Unsupported type:" << value.GetType().name();
55 return {};
56}
57
58std::unique_ptr<base::DictionaryValue> DictionaryToJson(
59 const chromeos::VariantDictionary& dictionary) {
60 std::unique_ptr<base::DictionaryValue> result{new base::DictionaryValue};
61 for (const auto& it : dictionary)
62 result->Set(it.first, AnyToJson(it.second).release());
63 return result;
64}
65
66std::string DictionaryToString(const chromeos::VariantDictionary& dictionary) {
67 std::unique_ptr<base::DictionaryValue> json{DictionaryToJson(dictionary)};
68 std::string str;
69 base::JSONWriter::Write(json.get(), &str);
70 return str;
71}
72
Alex Vakulenko5dd84342015-04-13 16:05:10 -070073} // anonymous namespace
74
Alex Vakulenko89d9d5e2014-09-12 10:27:23 -070075class Daemon : public chromeos::DBusDaemon {
76 public:
77 Daemon() = default;
78
79 protected:
80 int OnInit() override;
81 void OnShutdown(int* return_code) override;
82
83 private:
Alex Vakulenko420e49f2014-12-01 17:53:27 -080084 std::unique_ptr<org::chromium::Buffet::ObjectManagerProxy> object_manager_;
Alex Vakulenko89d9d5e2014-09-12 10:27:23 -070085
Alex Vakulenko420e49f2014-12-01 17:53:27 -080086 void OnBuffetCommand(org::chromium::Buffet::CommandProxy* command);
87 void OnBuffetCommandRemoved(const dbus::ObjectPath& object_path);
88 void OnPropertyChange(org::chromium::Buffet::CommandProxy* command,
89 const std::string& property_name);
90 void OnCommandProgress(org::chromium::Buffet::CommandProxy* command,
91 int progress);
Alex Vakulenko89d9d5e2014-09-12 10:27:23 -070092
93 DISALLOW_COPY_AND_ASSIGN(Daemon);
94};
95
96int Daemon::OnInit() {
97 int return_code = chromeos::DBusDaemon::OnInit();
98 if (return_code != EX_OK)
99 return return_code;
100
Alex Vakulenko420e49f2014-12-01 17:53:27 -0800101 object_manager_.reset(new org::chromium::Buffet::ObjectManagerProxy{bus_});
102 object_manager_->SetCommandAddedCallback(
103 base::Bind(&Daemon::OnBuffetCommand, base::Unretained(this)));
104 object_manager_->SetCommandRemovedCallback(
105 base::Bind(&Daemon::OnBuffetCommandRemoved, base::Unretained(this)));
Alex Vakulenko89d9d5e2014-09-12 10:27:23 -0700106
107 printf("Waiting for commands...\n");
108 return EX_OK;
109}
110
111void Daemon::OnShutdown(int* return_code) {
112 printf("Shutting down...\n");
113}
114
Alex Vakulenko420e49f2014-12-01 17:53:27 -0800115void Daemon::OnPropertyChange(org::chromium::Buffet::CommandProxy* command,
116 const std::string& property_name) {
117 printf("Notification: property '%s' on command '%s' changed.\n",
118 property_name.c_str(), command->id().c_str());
Vitaly Buka4129dfa2015-04-29 12:16:58 -0700119 printf(" Current command status: '%s'\n", command->status().c_str());
120 std::string progress = DictionaryToString(command->progress());
121 printf(" Current command progress: %s\n", progress.c_str());
122 std::string results = DictionaryToString(command->results());
123 printf(" Current command results: %s\n", results.c_str());
Alex Vakulenko420e49f2014-12-01 17:53:27 -0800124}
125
126void Daemon::OnBuffetCommand(org::chromium::Buffet::CommandProxy* command) {
Alex Vakulenko5dd84342015-04-13 16:05:10 -0700127 // "Handle" only commands that belong to this daemon's category.
Alex Vakulenkof784e212015-04-20 12:33:52 -0700128 if (command->category() != kTestCommandCategory ||
129 command->status() == "done") {
Alex Vakulenko5dd84342015-04-13 16:05:10 -0700130 return;
Alex Vakulenkof784e212015-04-20 12:33:52 -0700131 }
Alex Vakulenko5dd84342015-04-13 16:05:10 -0700132
Alex Vakulenko420e49f2014-12-01 17:53:27 -0800133 command->SetPropertyChangedCallback(base::Bind(&Daemon::OnPropertyChange,
134 base::Unretained(this)));
135 printf("++++++++++++++++++++++++++++++++++++++++++++++++\n");
136 printf("Command received: %s\n", command->name().c_str());
137 printf("DBus Object Path: %s\n", command->GetObjectPath().value().c_str());
138 printf(" category: %s\n", command->category().c_str());
139 printf(" ID: %s\n", command->id().c_str());
140 printf(" status: %s\n", command->status().c_str());
Alex Vakulenkof784e212015-04-20 12:33:52 -0700141 printf(" origin: %s\n", command->origin().c_str());
Vitaly Buka4129dfa2015-04-29 12:16:58 -0700142 std::string param_names = DictionaryToString(command->parameters());
143 printf(" parameters: %s\n", param_names.c_str());
Alex Vakulenko420e49f2014-12-01 17:53:27 -0800144 OnCommandProgress(command, 0);
145}
146
147void Daemon::OnCommandProgress(org::chromium::Buffet::CommandProxy* command,
148 int progress) {
Vitaly Buka4129dfa2015-04-29 12:16:58 -0700149 printf("Updating command '%s' progress to %d%%\n", command->id().c_str(),
150 progress);
151 auto new_progress = command->progress();
152 new_progress["progress"] = progress;
153 command->SetProgress(new_progress, nullptr);
154
Alex Vakulenko420e49f2014-12-01 17:53:27 -0800155 if (progress >= 100) {
156 command->Done(nullptr);
157 } else {
Alex Vakulenko420e49f2014-12-01 17:53:27 -0800158 base::MessageLoop::current()->PostDelayedTask(
Vitaly Buka4129dfa2015-04-29 12:16:58 -0700159 FROM_HERE, base::Bind(&Daemon::OnCommandProgress,
160 base::Unretained(this), command, progress + 10),
Alex Vakulenko420e49f2014-12-01 17:53:27 -0800161 base::TimeDelta::FromSeconds(1));
162 }
163}
164
165void Daemon::OnBuffetCommandRemoved(const dbus::ObjectPath& object_path) {
166 printf("------------------------------------------------\n");
167 printf("Command removed\n");
168 printf("DBus Object Path: %s\n", object_path.value().c_str());
Alex Vakulenko89d9d5e2014-09-12 10:27:23 -0700169}
170
171int main(int argc, char* argv[]) {
Alex Vakulenkofc575a42015-04-02 14:31:10 -0700172 base::CommandLine::Init(argc, argv);
Alex Vakulenko89d9d5e2014-09-12 10:27:23 -0700173 chromeos::InitLog(chromeos::kLogToSyslog |
174 chromeos::kLogToStderr |
175 chromeos::kLogHeader);
176 Daemon daemon;
177 return daemon.Run();
178}