blob: 3639803b816782a467ad66ae64e533cce8b76921 [file] [log] [blame]
Christopher Wileya4915c42014-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 Vakulenkob3aac252014-05-07 17:35:24 -07007#include <map>
8#include <string>
9
Christopher Wileya4915c42014-03-27 14:45:37 -070010#include <base/bind.h>
11#include <base/bind_helpers.h>
Christopher Wileyb76eb292014-05-05 16:09:16 -070012#include <base/json/json_writer.h>
13#include <dbus/bus.h>
Christopher Wiley90016242014-04-01 17:33:29 -070014#include <dbus/object_path.h>
Alex Vakulenko3cb466c2014-04-15 11:36:32 -070015#include <dbus/values_util.h>
Christopher Wileya4915c42014-03-27 14:45:37 -070016
Christopher Wiley90016242014-04-01 17:33:29 -070017#include "buffet/async_event_sequencer.h"
Christopher Wileya4915c42014-03-27 14:45:37 -070018#include "buffet/dbus_constants.h"
Christopher Wileya4915c42014-03-27 14:45:37 -070019#include "buffet/dbus_utils.h"
Alex Vakulenkob3aac252014-05-07 17:35:24 -070020#include "buffet/error.h"
Christopher Wileyadb901d2014-05-07 09:58:45 -070021#include "buffet/exported_object_manager.h"
Christopher Wileya4915c42014-03-27 14:45:37 -070022
Christopher Wileyadb901d2014-05-07 09:58:45 -070023using buffet::dbus_utils::AsyncEventSequencer;
Christopher Wileya4915c42014-03-27 14:45:37 -070024using buffet::dbus_utils::GetBadArgsError;
Alex Vakulenkob3aac252014-05-07 17:35:24 -070025using buffet::dbus_utils::GetDBusError;
Christopher Wileya4915c42014-03-27 14:45:37 -070026
27namespace buffet {
28
Christopher Wileyadb901d2014-05-07 09:58:45 -070029Manager::Manager(
30 scoped_refptr<dbus::Bus> bus,
31 base::WeakPtr<dbus_utils::ExportedObjectManager> object_manager)
Christopher Wiley90016242014-04-01 17:33:29 -070032 : bus_(bus),
33 exported_object_(bus->GetExportedObject(
Christopher Wileyadb901d2014-05-07 09:58:45 -070034 dbus::ObjectPath(dbus_constants::kManagerServicePath))),
35 object_manager_(object_manager) { }
Christopher Wileya4915c42014-03-27 14:45:37 -070036
37Manager::~Manager() {
Christopher Wileyadb901d2014-05-07 09:58:45 -070038 object_manager_->ReleaseInterface(
39 dbus::ObjectPath(dbus_constants::kManagerServicePath),
40 dbus_constants::kManagerInterface);
Christopher Wileyaa3f29c2014-03-27 14:51:26 -070041 // Prevent the properties object from making calls to the exported object.
42 properties_.reset(nullptr);
Christopher Wileya4915c42014-03-27 14:45:37 -070043 // Unregister ourselves from the Bus. This prevents the bus from calling
44 // our callbacks in between the Manager's death and the bus unregistering
45 // our exported object on shutdown. Unretained makes no promises of memory
46 // management.
Christopher Wiley90016242014-04-01 17:33:29 -070047 exported_object_->Unregister();
48 exported_object_ = nullptr;
49}
50
51void Manager::Init(const OnInitFinish& cb) {
Christopher Wileyadb901d2014-05-07 09:58:45 -070052 scoped_refptr<AsyncEventSequencer> sequencer(
53 new AsyncEventSequencer());
Christopher Wiley90016242014-04-01 17:33:29 -070054 exported_object_->ExportMethod(
55 dbus_constants::kManagerInterface,
Alex Vakulenko3cb466c2014-04-15 11:36:32 -070056 dbus_constants::kManagerCheckDeviceRegistered,
Christopher Wiley90016242014-04-01 17:33:29 -070057 dbus_utils::GetExportableDBusMethod(
Alex Vakulenko3cb466c2014-04-15 11:36:32 -070058 base::Bind(&Manager::HandleCheckDeviceRegistered,
Christopher Wiley90016242014-04-01 17:33:29 -070059 base::Unretained(this))),
60 sequencer->GetExportHandler(
61 dbus_constants::kManagerInterface,
Alex Vakulenko3cb466c2014-04-15 11:36:32 -070062 dbus_constants::kManagerCheckDeviceRegistered,
63 "Failed exporting CheckDeviceRegistered method",
64 true));
65 exported_object_->ExportMethod(
66 dbus_constants::kManagerInterface,
67 dbus_constants::kManagerGetDeviceInfo,
68 dbus_utils::GetExportableDBusMethod(
69 base::Bind(&Manager::HandleGetDeviceInfo,
70 base::Unretained(this))),
71 sequencer->GetExportHandler(
72 dbus_constants::kManagerInterface,
73 dbus_constants::kManagerGetDeviceInfo,
74 "Failed exporting GetDeviceInfo method",
75 true));
76 exported_object_->ExportMethod(
77 dbus_constants::kManagerInterface,
78 dbus_constants::kManagerStartRegisterDevice,
79 dbus_utils::GetExportableDBusMethod(
80 base::Bind(&Manager::HandleStartRegisterDevice,
81 base::Unretained(this))),
82 sequencer->GetExportHandler(
83 dbus_constants::kManagerInterface,
84 dbus_constants::kManagerStartRegisterDevice,
85 "Failed exporting StartRegisterDevice method",
86 true));
87 exported_object_->ExportMethod(
88 dbus_constants::kManagerInterface,
89 dbus_constants::kManagerFinishRegisterDevice,
90 dbus_utils::GetExportableDBusMethod(
91 base::Bind(&Manager::HandleFinishRegisterDevice,
92 base::Unretained(this))),
93 sequencer->GetExportHandler(
94 dbus_constants::kManagerInterface,
95 dbus_constants::kManagerFinishRegisterDevice,
96 "Failed exporting FinishRegisterDevice method",
Christopher Wiley90016242014-04-01 17:33:29 -070097 true));
98 exported_object_->ExportMethod(
99 dbus_constants::kManagerInterface,
100 dbus_constants::kManagerUpdateStateMethod,
101 dbus_utils::GetExportableDBusMethod(
102 base::Bind(&Manager::HandleUpdateState,
103 base::Unretained(this))),
104 sequencer->GetExportHandler(
105 dbus_constants::kManagerInterface,
106 dbus_constants::kManagerUpdateStateMethod,
107 "Failed exporting UpdateState method",
108 true));
Christopher Wileyb76eb292014-05-05 16:09:16 -0700109 exported_object_->ExportMethod(
110 dbus_constants::kManagerInterface, dbus_constants::kManagerTestMethod,
111 dbus_utils::GetExportableDBusMethod(
112 base::Bind(&Manager::HandleTestMethod, base::Unretained(this))),
113 sequencer->GetExportHandler(
114 dbus_constants::kManagerInterface, dbus_constants::kManagerTestMethod,
115 "Failed exporting TestMethod method",
116 true));
Christopher Wiley90016242014-04-01 17:33:29 -0700117 properties_.reset(new Properties(bus_));
118 // TODO(wiley): Initialize all properties appropriately before claiming
119 // the properties interface.
120 properties_->state_.SetValue("{}");
121 properties_->Init(
122 sequencer->GetHandler("Manager properties export failed.", true));
Christopher Wileyadb901d2014-05-07 09:58:45 -0700123 auto claim_interface_task = sequencer->WrapCompletionTask(
124 base::Bind(&dbus_utils::ExportedObjectManager::ClaimInterface,
125 object_manager_->AsWeakPtr(),
126 dbus::ObjectPath(dbus_constants::kManagerServicePath),
127 dbus_constants::kManagerInterface,
128 properties_->GetPropertyWriter(
129 dbus_constants::kManagerInterface)));
130 sequencer->OnAllTasksCompletedCall({claim_interface_task, cb});
Alex Vakulenko3cb466c2014-04-15 11:36:32 -0700131 device_info_.Load();
Christopher Wileya4915c42014-03-27 14:45:37 -0700132}
133
Alex Vakulenko3cb466c2014-04-15 11:36:32 -0700134scoped_ptr<dbus::Response> Manager::HandleCheckDeviceRegistered(
Christopher Wileya4915c42014-03-27 14:45:37 -0700135 dbus::MethodCall* method_call) {
136 // Read the parameters to the method.
137 dbus::MessageReader reader(method_call);
Christopher Wileya4915c42014-03-27 14:45:37 -0700138 if (reader.HasMoreData()) {
Alex Vakulenko3cb466c2014-04-15 11:36:32 -0700139 return GetBadArgsError(method_call,
140 "Too many parameters to CheckDeviceRegistered");
Christopher Wileya4915c42014-03-27 14:45:37 -0700141 }
142
Alex Vakulenko3cb466c2014-04-15 11:36:32 -0700143 LOG(INFO) << "Received call to Manager.CheckDeviceRegistered()";
144
Alex Vakulenkoaf23b322014-05-08 16:25:45 -0700145 buffet::ErrorPtr error;
Alex Vakulenkob3aac252014-05-07 17:35:24 -0700146 bool registered = device_info_.CheckRegistration(&error);
147 // If it fails due to any reason other than 'device not registered',
148 // treat it as a real error and report it to the caller.
149 if (!registered &&
150 !error->HasError(kErrorDomainGCD, "device_not_registered")) {
151 return GetDBusError(method_call, error.get());
152 }
Christopher Wileya4915c42014-03-27 14:45:37 -0700153
Alex Vakulenkob3aac252014-05-07 17:35:24 -0700154 std::string device_id;
155 if (registered) {
156 device_id = device_info_.GetDeviceId(&error);
157 if (device_id.empty())
158 return GetDBusError(method_call, error.get());
159 }
Christopher Wileya4915c42014-03-27 14:45:37 -0700160 // Send back our response.
161 scoped_ptr<dbus::Response> response(
162 dbus::Response::FromMethodCall(method_call));
163 dbus::MessageWriter writer(response.get());
Alex Vakulenkob3aac252014-05-07 17:35:24 -0700164 writer.AppendString(device_id);
Alex Vakulenko3cb466c2014-04-15 11:36:32 -0700165 return response.Pass();
166}
167
168scoped_ptr<dbus::Response> Manager::HandleGetDeviceInfo(
169 dbus::MethodCall* method_call) {
170 // Read the parameters to the method.
171 dbus::MessageReader reader(method_call);
172 if (reader.HasMoreData()) {
173 return GetBadArgsError(method_call,
174 "Too many parameters to GetDeviceInfo");
175 }
176
177 LOG(INFO) << "Received call to Manager.GetDeviceInfo()";
178
179 std::string device_info_str;
Alex Vakulenkoaf23b322014-05-08 16:25:45 -0700180 buffet::ErrorPtr error;
Alex Vakulenkob3aac252014-05-07 17:35:24 -0700181 auto device_info = device_info_.GetDeviceInfo(&error);
182 if (!device_info)
183 return GetDBusError(method_call, error.get());
184
185 base::JSONWriter::Write(device_info.get(), &device_info_str);
Alex Vakulenko3cb466c2014-04-15 11:36:32 -0700186
187 // Send back our response.
188 scoped_ptr<dbus::Response> response(
189 dbus::Response::FromMethodCall(method_call));
190 dbus::MessageWriter writer(response.get());
191 writer.AppendString(device_info_str);
192 return response.Pass();
193}
194
195scoped_ptr<dbus::Response> Manager::HandleStartRegisterDevice(
196 dbus::MethodCall* method_call) {
197 // Read the parameters to the method.
198 dbus::MessageReader reader(method_call);
199 if (!reader.HasMoreData()) {
200 return GetBadArgsError(method_call, "No parameters to StartRegisterDevice");
201 }
202
203 dbus::MessageReader array_reader(nullptr);
204 if (!reader.PopArray(&array_reader))
205 return GetBadArgsError(method_call, "Failed to read the parameter array");
206 std::map<std::string, std::shared_ptr<base::Value>> params;
207 while (array_reader.HasMoreData()) {
208 dbus::MessageReader dict_entry_reader(nullptr);
209 if (!array_reader.PopDictEntry(&dict_entry_reader))
210 return GetBadArgsError(method_call, "Failed to get a call parameter");
211 std::string key;
212 if (!dict_entry_reader.PopString(&key))
213 return GetBadArgsError(method_call, "Failed to read parameter key");
214 base::Value* value = dbus::PopDataAsValue(&dict_entry_reader);
215 if (!value)
216 return GetBadArgsError(method_call, "Failed to read parameter value");
217 params.insert(std::make_pair(key, std::shared_ptr<base::Value>(value)));
218 }
219 if (reader.HasMoreData())
220 return GetBadArgsError(method_call,
221 "Too many parameters to StartRegisterDevice");
222
223 LOG(INFO) << "Received call to Manager.StartRegisterDevice()";
224
Alex Vakulenkoaf23b322014-05-08 16:25:45 -0700225 buffet::ErrorPtr error;
Alex Vakulenkob3aac252014-05-07 17:35:24 -0700226 std::string id = device_info_.StartRegistration(params, &error);
227 if (id.empty())
228 return GetDBusError(method_call, error.get());
Alex Vakulenko3cb466c2014-04-15 11:36:32 -0700229
230 // Send back our response.
231 scoped_ptr<dbus::Response> response(
232 dbus::Response::FromMethodCall(method_call));
233 dbus::MessageWriter writer(response.get());
234 writer.AppendString(id);
235 return response.Pass();
236}
237
238scoped_ptr<dbus::Response> Manager::HandleFinishRegisterDevice(
239 dbus::MethodCall* method_call) {
240 // Read the parameters to the method.
241 dbus::MessageReader reader(method_call);
242 if (!reader.HasMoreData()) {
243 return GetBadArgsError(method_call,
244 "No parameters to FinishRegisterDevice");
245 }
246 std::string user_auth_code;
247 if (!reader.PopString(&user_auth_code)) {
248 return GetBadArgsError(method_call, "Failed to read UserAuthCode");
249 }
250 if (reader.HasMoreData()) {
251 return GetBadArgsError(method_call,
252 "Too many parameters to FinishRegisterDevice");
253 }
254
255 LOG(INFO) << "Received call to Manager.FinishRegisterDevice()";
Alex Vakulenkoaf23b322014-05-08 16:25:45 -0700256 buffet::ErrorPtr error;
Alex Vakulenkob3aac252014-05-07 17:35:24 -0700257 if (!device_info_.FinishRegistration(user_auth_code, &error))
258 return GetDBusError(method_call, error.get());
259
260 std::string device_id = device_info_.GetDeviceId(&error);
261 if (device_id.empty())
262 return GetDBusError(method_call, error.get());
Alex Vakulenko3cb466c2014-04-15 11:36:32 -0700263
264 // Send back our response.
265 scoped_ptr<dbus::Response> response(
266 dbus::Response::FromMethodCall(method_call));
267 dbus::MessageWriter writer(response.get());
Alex Vakulenkob3aac252014-05-07 17:35:24 -0700268 writer.AppendString(device_id);
Christopher Wileya4915c42014-03-27 14:45:37 -0700269 return response.Pass();
270}
271
272scoped_ptr<dbus::Response> Manager::HandleUpdateState(
273 dbus::MethodCall *method_call) {
274 // Read the parameters to the method.
275 dbus::MessageReader reader(method_call);
276 if (!reader.HasMoreData()) {
277 return GetBadArgsError(method_call, "No parameters to UpdateState");
278 }
279 std::string json_state_fragment;
280 if (!reader.PopString(&json_state_fragment)) {
281 return GetBadArgsError(method_call, "Failed to read json_state_fragment");
282 }
283 if (reader.HasMoreData()) {
284 return GetBadArgsError(method_call, "Too many parameters to UpdateState");
285 }
286
287 LOG(INFO) << "Received call to Manager.UpdateState()";
Christopher Wileyaa3f29c2014-03-27 14:51:26 -0700288 // TODO(wiley): Merge json state blobs intelligently.
289 properties_->state_.SetValue(json_state_fragment);
Christopher Wileya4915c42014-03-27 14:45:37 -0700290
291 // Send back our response.
292 return dbus::Response::FromMethodCall(method_call);
293}
294
Christopher Wileyb76eb292014-05-05 16:09:16 -0700295scoped_ptr<dbus::Response> Manager::HandleTestMethod(
296 dbus::MethodCall* method_call) {
297 LOG(INFO) << "Received call to test method.";
298 return scoped_ptr<dbus::Response>();
299}
300
Christopher Wileya4915c42014-03-27 14:45:37 -0700301} // namespace buffet