blob: 39ccf7db249243499b5c1fdcc6931a33003637a9 [file] [log] [blame]
Christopher Wiley4b5f04c2014-03-27 14:45:37 -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#include "buffet/manager.h"
6
Alex Vakulenko7c3226e2014-05-07 17:35:24 -07007#include <map>
8#include <string>
9
Christopher Wiley4b5f04c2014-03-27 14:45:37 -070010#include <base/bind.h>
11#include <base/bind_helpers.h>
Christopher Wiley2ffa0042014-05-05 16:09:16 -070012#include <base/json/json_writer.h>
Christopher Wiley68c07cc2014-07-29 14:07:10 -070013#include <chromeos/async_event_sequencer.h>
Christopher Wileyda358132014-08-07 15:47:24 -070014#include <chromeos/dbus_utils.h>
Christopher Wiley2ffa0042014-05-05 16:09:16 -070015#include <dbus/bus.h>
Christopher Wiley54028f92014-04-01 17:33:29 -070016#include <dbus/object_path.h>
Alex Vakulenkof3d77e52014-04-15 11:36:32 -070017#include <dbus/values_util.h>
Christopher Wiley4b5f04c2014-03-27 14:45:37 -070018
Alex Vakulenkocf9c1462014-07-23 10:57:58 -070019#include "buffet/commands/command_manager.h"
Christopher Wiley4b5f04c2014-03-27 14:45:37 -070020#include "buffet/dbus_constants.h"
Christopher Wiley4b5f04c2014-03-27 14:45:37 -070021#include "buffet/dbus_utils.h"
Alex Vakulenko7c3226e2014-05-07 17:35:24 -070022#include "buffet/error.h"
Christopher Wileyd71774f2014-05-07 09:58:45 -070023#include "buffet/exported_object_manager.h"
Christopher Wiley4b5f04c2014-03-27 14:45:37 -070024
Christopher Wiley68c07cc2014-07-29 14:07:10 -070025using chromeos::dbus_utils::AsyncEventSequencer;
Christopher Wileyda358132014-08-07 15:47:24 -070026using chromeos::dbus_utils::GetBadArgsError;
Alex Vakulenko7c3226e2014-05-07 17:35:24 -070027using buffet::dbus_utils::GetDBusError;
Christopher Wiley4b5f04c2014-03-27 14:45:37 -070028
29namespace buffet {
30
Christopher Wileyd71774f2014-05-07 09:58:45 -070031Manager::Manager(
32 scoped_refptr<dbus::Bus> bus,
33 base::WeakPtr<dbus_utils::ExportedObjectManager> object_manager)
Christopher Wiley54028f92014-04-01 17:33:29 -070034 : bus_(bus),
35 exported_object_(bus->GetExportedObject(
Christopher Wileyd71774f2014-05-07 09:58:45 -070036 dbus::ObjectPath(dbus_constants::kManagerServicePath))),
37 object_manager_(object_manager) { }
Christopher Wiley4b5f04c2014-03-27 14:45:37 -070038
39Manager::~Manager() {
Christopher Wileyd71774f2014-05-07 09:58:45 -070040 object_manager_->ReleaseInterface(
41 dbus::ObjectPath(dbus_constants::kManagerServicePath),
42 dbus_constants::kManagerInterface);
Christopher Wiley106686a2014-03-27 14:51:26 -070043 // Prevent the properties object from making calls to the exported object.
44 properties_.reset(nullptr);
Christopher Wiley4b5f04c2014-03-27 14:45:37 -070045 // Unregister ourselves from the Bus. This prevents the bus from calling
46 // our callbacks in between the Manager's death and the bus unregistering
47 // our exported object on shutdown. Unretained makes no promises of memory
48 // management.
Christopher Wiley54028f92014-04-01 17:33:29 -070049 exported_object_->Unregister();
50 exported_object_ = nullptr;
51}
52
53void Manager::Init(const OnInitFinish& cb) {
Christopher Wileyd71774f2014-05-07 09:58:45 -070054 scoped_refptr<AsyncEventSequencer> sequencer(
55 new AsyncEventSequencer());
Christopher Wiley54028f92014-04-01 17:33:29 -070056 exported_object_->ExportMethod(
57 dbus_constants::kManagerInterface,
Alex Vakulenkof3d77e52014-04-15 11:36:32 -070058 dbus_constants::kManagerCheckDeviceRegistered,
Christopher Wiley54028f92014-04-01 17:33:29 -070059 dbus_utils::GetExportableDBusMethod(
Alex Vakulenkof3d77e52014-04-15 11:36:32 -070060 base::Bind(&Manager::HandleCheckDeviceRegistered,
Christopher Wiley54028f92014-04-01 17:33:29 -070061 base::Unretained(this))),
62 sequencer->GetExportHandler(
63 dbus_constants::kManagerInterface,
Alex Vakulenkof3d77e52014-04-15 11:36:32 -070064 dbus_constants::kManagerCheckDeviceRegistered,
65 "Failed exporting CheckDeviceRegistered method",
66 true));
67 exported_object_->ExportMethod(
68 dbus_constants::kManagerInterface,
69 dbus_constants::kManagerGetDeviceInfo,
70 dbus_utils::GetExportableDBusMethod(
71 base::Bind(&Manager::HandleGetDeviceInfo,
72 base::Unretained(this))),
73 sequencer->GetExportHandler(
74 dbus_constants::kManagerInterface,
75 dbus_constants::kManagerGetDeviceInfo,
76 "Failed exporting GetDeviceInfo method",
77 true));
78 exported_object_->ExportMethod(
79 dbus_constants::kManagerInterface,
80 dbus_constants::kManagerStartRegisterDevice,
81 dbus_utils::GetExportableDBusMethod(
82 base::Bind(&Manager::HandleStartRegisterDevice,
83 base::Unretained(this))),
84 sequencer->GetExportHandler(
85 dbus_constants::kManagerInterface,
86 dbus_constants::kManagerStartRegisterDevice,
87 "Failed exporting StartRegisterDevice method",
88 true));
89 exported_object_->ExportMethod(
90 dbus_constants::kManagerInterface,
91 dbus_constants::kManagerFinishRegisterDevice,
92 dbus_utils::GetExportableDBusMethod(
93 base::Bind(&Manager::HandleFinishRegisterDevice,
94 base::Unretained(this))),
95 sequencer->GetExportHandler(
96 dbus_constants::kManagerInterface,
97 dbus_constants::kManagerFinishRegisterDevice,
98 "Failed exporting FinishRegisterDevice method",
Christopher Wiley54028f92014-04-01 17:33:29 -070099 true));
100 exported_object_->ExportMethod(
101 dbus_constants::kManagerInterface,
102 dbus_constants::kManagerUpdateStateMethod,
103 dbus_utils::GetExportableDBusMethod(
104 base::Bind(&Manager::HandleUpdateState,
105 base::Unretained(this))),
106 sequencer->GetExportHandler(
107 dbus_constants::kManagerInterface,
108 dbus_constants::kManagerUpdateStateMethod,
109 "Failed exporting UpdateState method",
110 true));
Christopher Wiley2ffa0042014-05-05 16:09:16 -0700111 exported_object_->ExportMethod(
112 dbus_constants::kManagerInterface, dbus_constants::kManagerTestMethod,
113 dbus_utils::GetExportableDBusMethod(
114 base::Bind(&Manager::HandleTestMethod, base::Unretained(this))),
115 sequencer->GetExportHandler(
116 dbus_constants::kManagerInterface, dbus_constants::kManagerTestMethod,
117 "Failed exporting TestMethod method",
118 true));
Christopher Wiley54028f92014-04-01 17:33:29 -0700119 properties_.reset(new Properties(bus_));
120 // TODO(wiley): Initialize all properties appropriately before claiming
121 // the properties interface.
122 properties_->state_.SetValue("{}");
123 properties_->Init(
124 sequencer->GetHandler("Manager properties export failed.", true));
Christopher Wileyd71774f2014-05-07 09:58:45 -0700125 auto claim_interface_task = sequencer->WrapCompletionTask(
126 base::Bind(&dbus_utils::ExportedObjectManager::ClaimInterface,
127 object_manager_->AsWeakPtr(),
128 dbus::ObjectPath(dbus_constants::kManagerServicePath),
129 dbus_constants::kManagerInterface,
130 properties_->GetPropertyWriter(
131 dbus_constants::kManagerInterface)));
132 sequencer->OnAllTasksCompletedCall({claim_interface_task, cb});
Alex Vakulenkocf9c1462014-07-23 10:57:58 -0700133 command_manager_ = std::make_shared<CommandManager>();
134 command_manager_->Startup();
Alex Vakulenko98025c22014-07-23 11:13:15 -0700135 device_info_ = std::unique_ptr<DeviceRegistrationInfo>(
136 new DeviceRegistrationInfo(command_manager_));
137 device_info_->Load();
Christopher Wiley4b5f04c2014-03-27 14:45:37 -0700138}
139
Alex Vakulenkof3d77e52014-04-15 11:36:32 -0700140scoped_ptr<dbus::Response> Manager::HandleCheckDeviceRegistered(
Christopher Wiley4b5f04c2014-03-27 14:45:37 -0700141 dbus::MethodCall* method_call) {
142 // Read the parameters to the method.
143 dbus::MessageReader reader(method_call);
Christopher Wiley4b5f04c2014-03-27 14:45:37 -0700144 if (reader.HasMoreData()) {
Alex Vakulenkof3d77e52014-04-15 11:36:32 -0700145 return GetBadArgsError(method_call,
146 "Too many parameters to CheckDeviceRegistered");
Christopher Wiley4b5f04c2014-03-27 14:45:37 -0700147 }
148
Alex Vakulenkof3d77e52014-04-15 11:36:32 -0700149 LOG(INFO) << "Received call to Manager.CheckDeviceRegistered()";
150
Alex Vakulenko25445932014-05-08 16:25:45 -0700151 buffet::ErrorPtr error;
Alex Vakulenko98025c22014-07-23 11:13:15 -0700152 bool registered = device_info_->CheckRegistration(&error);
Alex Vakulenko7c3226e2014-05-07 17:35:24 -0700153 // If it fails due to any reason other than 'device not registered',
154 // treat it as a real error and report it to the caller.
155 if (!registered &&
156 !error->HasError(kErrorDomainGCD, "device_not_registered")) {
157 return GetDBusError(method_call, error.get());
158 }
Christopher Wiley4b5f04c2014-03-27 14:45:37 -0700159
Alex Vakulenko7c3226e2014-05-07 17:35:24 -0700160 std::string device_id;
161 if (registered) {
Alex Vakulenko98025c22014-07-23 11:13:15 -0700162 device_id = device_info_->GetDeviceId(&error);
Alex Vakulenko7c3226e2014-05-07 17:35:24 -0700163 if (device_id.empty())
164 return GetDBusError(method_call, error.get());
165 }
Christopher Wiley4b5f04c2014-03-27 14:45:37 -0700166 // Send back our response.
167 scoped_ptr<dbus::Response> response(
168 dbus::Response::FromMethodCall(method_call));
169 dbus::MessageWriter writer(response.get());
Alex Vakulenko7c3226e2014-05-07 17:35:24 -0700170 writer.AppendString(device_id);
Alex Vakulenkof3d77e52014-04-15 11:36:32 -0700171 return response.Pass();
172}
173
174scoped_ptr<dbus::Response> Manager::HandleGetDeviceInfo(
175 dbus::MethodCall* method_call) {
176 // Read the parameters to the method.
177 dbus::MessageReader reader(method_call);
178 if (reader.HasMoreData()) {
179 return GetBadArgsError(method_call,
180 "Too many parameters to GetDeviceInfo");
181 }
182
183 LOG(INFO) << "Received call to Manager.GetDeviceInfo()";
184
185 std::string device_info_str;
Alex Vakulenko25445932014-05-08 16:25:45 -0700186 buffet::ErrorPtr error;
Alex Vakulenko98025c22014-07-23 11:13:15 -0700187 auto device_info = device_info_->GetDeviceInfo(&error);
Alex Vakulenko7c3226e2014-05-07 17:35:24 -0700188 if (!device_info)
189 return GetDBusError(method_call, error.get());
190
191 base::JSONWriter::Write(device_info.get(), &device_info_str);
Alex Vakulenkof3d77e52014-04-15 11:36:32 -0700192
193 // Send back our response.
194 scoped_ptr<dbus::Response> response(
195 dbus::Response::FromMethodCall(method_call));
196 dbus::MessageWriter writer(response.get());
197 writer.AppendString(device_info_str);
198 return response.Pass();
199}
200
201scoped_ptr<dbus::Response> Manager::HandleStartRegisterDevice(
202 dbus::MethodCall* method_call) {
203 // Read the parameters to the method.
204 dbus::MessageReader reader(method_call);
205 if (!reader.HasMoreData()) {
206 return GetBadArgsError(method_call, "No parameters to StartRegisterDevice");
207 }
208
209 dbus::MessageReader array_reader(nullptr);
210 if (!reader.PopArray(&array_reader))
211 return GetBadArgsError(method_call, "Failed to read the parameter array");
212 std::map<std::string, std::shared_ptr<base::Value>> params;
213 while (array_reader.HasMoreData()) {
214 dbus::MessageReader dict_entry_reader(nullptr);
215 if (!array_reader.PopDictEntry(&dict_entry_reader))
216 return GetBadArgsError(method_call, "Failed to get a call parameter");
217 std::string key;
218 if (!dict_entry_reader.PopString(&key))
219 return GetBadArgsError(method_call, "Failed to read parameter key");
220 base::Value* value = dbus::PopDataAsValue(&dict_entry_reader);
221 if (!value)
222 return GetBadArgsError(method_call, "Failed to read parameter value");
223 params.insert(std::make_pair(key, std::shared_ptr<base::Value>(value)));
224 }
225 if (reader.HasMoreData())
226 return GetBadArgsError(method_call,
227 "Too many parameters to StartRegisterDevice");
228
229 LOG(INFO) << "Received call to Manager.StartRegisterDevice()";
230
Alex Vakulenko25445932014-05-08 16:25:45 -0700231 buffet::ErrorPtr error;
Alex Vakulenko98025c22014-07-23 11:13:15 -0700232 std::string id = device_info_->StartRegistration(params, &error);
Alex Vakulenko7c3226e2014-05-07 17:35:24 -0700233 if (id.empty())
234 return GetDBusError(method_call, error.get());
Alex Vakulenkof3d77e52014-04-15 11:36:32 -0700235
236 // Send back our response.
237 scoped_ptr<dbus::Response> response(
238 dbus::Response::FromMethodCall(method_call));
239 dbus::MessageWriter writer(response.get());
240 writer.AppendString(id);
241 return response.Pass();
242}
243
244scoped_ptr<dbus::Response> Manager::HandleFinishRegisterDevice(
245 dbus::MethodCall* method_call) {
246 // Read the parameters to the method.
247 dbus::MessageReader reader(method_call);
248 if (!reader.HasMoreData()) {
249 return GetBadArgsError(method_call,
250 "No parameters to FinishRegisterDevice");
251 }
252 std::string user_auth_code;
253 if (!reader.PopString(&user_auth_code)) {
254 return GetBadArgsError(method_call, "Failed to read UserAuthCode");
255 }
256 if (reader.HasMoreData()) {
257 return GetBadArgsError(method_call,
258 "Too many parameters to FinishRegisterDevice");
259 }
260
261 LOG(INFO) << "Received call to Manager.FinishRegisterDevice()";
Alex Vakulenko25445932014-05-08 16:25:45 -0700262 buffet::ErrorPtr error;
Alex Vakulenko98025c22014-07-23 11:13:15 -0700263 if (!device_info_->FinishRegistration(user_auth_code, &error))
Alex Vakulenko7c3226e2014-05-07 17:35:24 -0700264 return GetDBusError(method_call, error.get());
265
Alex Vakulenko98025c22014-07-23 11:13:15 -0700266 std::string device_id = device_info_->GetDeviceId(&error);
Alex Vakulenko7c3226e2014-05-07 17:35:24 -0700267 if (device_id.empty())
268 return GetDBusError(method_call, error.get());
Alex Vakulenkof3d77e52014-04-15 11:36:32 -0700269
270 // Send back our response.
271 scoped_ptr<dbus::Response> response(
272 dbus::Response::FromMethodCall(method_call));
273 dbus::MessageWriter writer(response.get());
Alex Vakulenko7c3226e2014-05-07 17:35:24 -0700274 writer.AppendString(device_id);
Christopher Wiley4b5f04c2014-03-27 14:45:37 -0700275 return response.Pass();
276}
277
278scoped_ptr<dbus::Response> Manager::HandleUpdateState(
279 dbus::MethodCall *method_call) {
280 // Read the parameters to the method.
281 dbus::MessageReader reader(method_call);
282 if (!reader.HasMoreData()) {
283 return GetBadArgsError(method_call, "No parameters to UpdateState");
284 }
285 std::string json_state_fragment;
286 if (!reader.PopString(&json_state_fragment)) {
287 return GetBadArgsError(method_call, "Failed to read json_state_fragment");
288 }
289 if (reader.HasMoreData()) {
290 return GetBadArgsError(method_call, "Too many parameters to UpdateState");
291 }
292
293 LOG(INFO) << "Received call to Manager.UpdateState()";
Christopher Wiley106686a2014-03-27 14:51:26 -0700294 // TODO(wiley): Merge json state blobs intelligently.
295 properties_->state_.SetValue(json_state_fragment);
Christopher Wiley4b5f04c2014-03-27 14:45:37 -0700296
297 // Send back our response.
298 return dbus::Response::FromMethodCall(method_call);
299}
300
Christopher Wiley2ffa0042014-05-05 16:09:16 -0700301scoped_ptr<dbus::Response> Manager::HandleTestMethod(
302 dbus::MethodCall* method_call) {
303 LOG(INFO) << "Received call to test method.";
304 return scoped_ptr<dbus::Response>();
305}
306
Christopher Wiley4b5f04c2014-03-27 14:45:37 -0700307} // namespace buffet