blob: aa29552d643845d1b15717a91d591d97f9ecf53a [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"
Alex Vakulenkoc2bc9a42014-07-23 10:57:58 -070018#include "buffet/commands/command_manager.h"
Christopher Wileya4915c42014-03-27 14:45:37 -070019#include "buffet/dbus_constants.h"
Christopher Wileya4915c42014-03-27 14:45:37 -070020#include "buffet/dbus_utils.h"
Alex Vakulenkob3aac252014-05-07 17:35:24 -070021#include "buffet/error.h"
Christopher Wileyadb901d2014-05-07 09:58:45 -070022#include "buffet/exported_object_manager.h"
Christopher Wileya4915c42014-03-27 14:45:37 -070023
Christopher Wileyadb901d2014-05-07 09:58:45 -070024using buffet::dbus_utils::AsyncEventSequencer;
Christopher Wileya4915c42014-03-27 14:45:37 -070025using buffet::dbus_utils::GetBadArgsError;
Alex Vakulenkob3aac252014-05-07 17:35:24 -070026using buffet::dbus_utils::GetDBusError;
Christopher Wileya4915c42014-03-27 14:45:37 -070027
28namespace buffet {
29
Christopher Wileyadb901d2014-05-07 09:58:45 -070030Manager::Manager(
31 scoped_refptr<dbus::Bus> bus,
32 base::WeakPtr<dbus_utils::ExportedObjectManager> object_manager)
Christopher Wiley90016242014-04-01 17:33:29 -070033 : bus_(bus),
34 exported_object_(bus->GetExportedObject(
Christopher Wileyadb901d2014-05-07 09:58:45 -070035 dbus::ObjectPath(dbus_constants::kManagerServicePath))),
36 object_manager_(object_manager) { }
Christopher Wileya4915c42014-03-27 14:45:37 -070037
38Manager::~Manager() {
Christopher Wileyadb901d2014-05-07 09:58:45 -070039 object_manager_->ReleaseInterface(
40 dbus::ObjectPath(dbus_constants::kManagerServicePath),
41 dbus_constants::kManagerInterface);
Christopher Wileyaa3f29c2014-03-27 14:51:26 -070042 // Prevent the properties object from making calls to the exported object.
43 properties_.reset(nullptr);
Christopher Wileya4915c42014-03-27 14:45:37 -070044 // Unregister ourselves from the Bus. This prevents the bus from calling
45 // our callbacks in between the Manager's death and the bus unregistering
46 // our exported object on shutdown. Unretained makes no promises of memory
47 // management.
Christopher Wiley90016242014-04-01 17:33:29 -070048 exported_object_->Unregister();
49 exported_object_ = nullptr;
50}
51
52void Manager::Init(const OnInitFinish& cb) {
Christopher Wileyadb901d2014-05-07 09:58:45 -070053 scoped_refptr<AsyncEventSequencer> sequencer(
54 new AsyncEventSequencer());
Christopher Wiley90016242014-04-01 17:33:29 -070055 exported_object_->ExportMethod(
56 dbus_constants::kManagerInterface,
Alex Vakulenko3cb466c2014-04-15 11:36:32 -070057 dbus_constants::kManagerCheckDeviceRegistered,
Christopher Wiley90016242014-04-01 17:33:29 -070058 dbus_utils::GetExportableDBusMethod(
Alex Vakulenko3cb466c2014-04-15 11:36:32 -070059 base::Bind(&Manager::HandleCheckDeviceRegistered,
Christopher Wiley90016242014-04-01 17:33:29 -070060 base::Unretained(this))),
61 sequencer->GetExportHandler(
62 dbus_constants::kManagerInterface,
Alex Vakulenko3cb466c2014-04-15 11:36:32 -070063 dbus_constants::kManagerCheckDeviceRegistered,
64 "Failed exporting CheckDeviceRegistered method",
65 true));
66 exported_object_->ExportMethod(
67 dbus_constants::kManagerInterface,
68 dbus_constants::kManagerGetDeviceInfo,
69 dbus_utils::GetExportableDBusMethod(
70 base::Bind(&Manager::HandleGetDeviceInfo,
71 base::Unretained(this))),
72 sequencer->GetExportHandler(
73 dbus_constants::kManagerInterface,
74 dbus_constants::kManagerGetDeviceInfo,
75 "Failed exporting GetDeviceInfo method",
76 true));
77 exported_object_->ExportMethod(
78 dbus_constants::kManagerInterface,
79 dbus_constants::kManagerStartRegisterDevice,
80 dbus_utils::GetExportableDBusMethod(
81 base::Bind(&Manager::HandleStartRegisterDevice,
82 base::Unretained(this))),
83 sequencer->GetExportHandler(
84 dbus_constants::kManagerInterface,
85 dbus_constants::kManagerStartRegisterDevice,
86 "Failed exporting StartRegisterDevice method",
87 true));
88 exported_object_->ExportMethod(
89 dbus_constants::kManagerInterface,
90 dbus_constants::kManagerFinishRegisterDevice,
91 dbus_utils::GetExportableDBusMethod(
92 base::Bind(&Manager::HandleFinishRegisterDevice,
93 base::Unretained(this))),
94 sequencer->GetExportHandler(
95 dbus_constants::kManagerInterface,
96 dbus_constants::kManagerFinishRegisterDevice,
97 "Failed exporting FinishRegisterDevice method",
Christopher Wiley90016242014-04-01 17:33:29 -070098 true));
99 exported_object_->ExportMethod(
100 dbus_constants::kManagerInterface,
101 dbus_constants::kManagerUpdateStateMethod,
102 dbus_utils::GetExportableDBusMethod(
103 base::Bind(&Manager::HandleUpdateState,
104 base::Unretained(this))),
105 sequencer->GetExportHandler(
106 dbus_constants::kManagerInterface,
107 dbus_constants::kManagerUpdateStateMethod,
108 "Failed exporting UpdateState method",
109 true));
Christopher Wileyb76eb292014-05-05 16:09:16 -0700110 exported_object_->ExportMethod(
111 dbus_constants::kManagerInterface, dbus_constants::kManagerTestMethod,
112 dbus_utils::GetExportableDBusMethod(
113 base::Bind(&Manager::HandleTestMethod, base::Unretained(this))),
114 sequencer->GetExportHandler(
115 dbus_constants::kManagerInterface, dbus_constants::kManagerTestMethod,
116 "Failed exporting TestMethod method",
117 true));
Christopher Wiley90016242014-04-01 17:33:29 -0700118 properties_.reset(new Properties(bus_));
119 // TODO(wiley): Initialize all properties appropriately before claiming
120 // the properties interface.
121 properties_->state_.SetValue("{}");
122 properties_->Init(
123 sequencer->GetHandler("Manager properties export failed.", true));
Christopher Wileyadb901d2014-05-07 09:58:45 -0700124 auto claim_interface_task = sequencer->WrapCompletionTask(
125 base::Bind(&dbus_utils::ExportedObjectManager::ClaimInterface,
126 object_manager_->AsWeakPtr(),
127 dbus::ObjectPath(dbus_constants::kManagerServicePath),
128 dbus_constants::kManagerInterface,
129 properties_->GetPropertyWriter(
130 dbus_constants::kManagerInterface)));
131 sequencer->OnAllTasksCompletedCall({claim_interface_task, cb});
Alex Vakulenkoc2bc9a42014-07-23 10:57:58 -0700132 command_manager_ = std::make_shared<CommandManager>();
133 command_manager_->Startup();
Alex Vakulenko1f30a622014-07-23 11:13:15 -0700134 device_info_ = std::unique_ptr<DeviceRegistrationInfo>(
135 new DeviceRegistrationInfo(command_manager_));
136 device_info_->Load();
Christopher Wileya4915c42014-03-27 14:45:37 -0700137}
138
Alex Vakulenko3cb466c2014-04-15 11:36:32 -0700139scoped_ptr<dbus::Response> Manager::HandleCheckDeviceRegistered(
Christopher Wileya4915c42014-03-27 14:45:37 -0700140 dbus::MethodCall* method_call) {
141 // Read the parameters to the method.
142 dbus::MessageReader reader(method_call);
Christopher Wileya4915c42014-03-27 14:45:37 -0700143 if (reader.HasMoreData()) {
Alex Vakulenko3cb466c2014-04-15 11:36:32 -0700144 return GetBadArgsError(method_call,
145 "Too many parameters to CheckDeviceRegistered");
Christopher Wileya4915c42014-03-27 14:45:37 -0700146 }
147
Alex Vakulenko3cb466c2014-04-15 11:36:32 -0700148 LOG(INFO) << "Received call to Manager.CheckDeviceRegistered()";
149
Alex Vakulenkoaf23b322014-05-08 16:25:45 -0700150 buffet::ErrorPtr error;
Alex Vakulenko1f30a622014-07-23 11:13:15 -0700151 bool registered = device_info_->CheckRegistration(&error);
Alex Vakulenkob3aac252014-05-07 17:35:24 -0700152 // If it fails due to any reason other than 'device not registered',
153 // treat it as a real error and report it to the caller.
154 if (!registered &&
155 !error->HasError(kErrorDomainGCD, "device_not_registered")) {
156 return GetDBusError(method_call, error.get());
157 }
Christopher Wileya4915c42014-03-27 14:45:37 -0700158
Alex Vakulenkob3aac252014-05-07 17:35:24 -0700159 std::string device_id;
160 if (registered) {
Alex Vakulenko1f30a622014-07-23 11:13:15 -0700161 device_id = device_info_->GetDeviceId(&error);
Alex Vakulenkob3aac252014-05-07 17:35:24 -0700162 if (device_id.empty())
163 return GetDBusError(method_call, error.get());
164 }
Christopher Wileya4915c42014-03-27 14:45:37 -0700165 // Send back our response.
166 scoped_ptr<dbus::Response> response(
167 dbus::Response::FromMethodCall(method_call));
168 dbus::MessageWriter writer(response.get());
Alex Vakulenkob3aac252014-05-07 17:35:24 -0700169 writer.AppendString(device_id);
Alex Vakulenko3cb466c2014-04-15 11:36:32 -0700170 return response.Pass();
171}
172
173scoped_ptr<dbus::Response> Manager::HandleGetDeviceInfo(
174 dbus::MethodCall* method_call) {
175 // Read the parameters to the method.
176 dbus::MessageReader reader(method_call);
177 if (reader.HasMoreData()) {
178 return GetBadArgsError(method_call,
179 "Too many parameters to GetDeviceInfo");
180 }
181
182 LOG(INFO) << "Received call to Manager.GetDeviceInfo()";
183
184 std::string device_info_str;
Alex Vakulenkoaf23b322014-05-08 16:25:45 -0700185 buffet::ErrorPtr error;
Alex Vakulenko1f30a622014-07-23 11:13:15 -0700186 auto device_info = device_info_->GetDeviceInfo(&error);
Alex Vakulenkob3aac252014-05-07 17:35:24 -0700187 if (!device_info)
188 return GetDBusError(method_call, error.get());
189
190 base::JSONWriter::Write(device_info.get(), &device_info_str);
Alex Vakulenko3cb466c2014-04-15 11:36:32 -0700191
192 // Send back our response.
193 scoped_ptr<dbus::Response> response(
194 dbus::Response::FromMethodCall(method_call));
195 dbus::MessageWriter writer(response.get());
196 writer.AppendString(device_info_str);
197 return response.Pass();
198}
199
200scoped_ptr<dbus::Response> Manager::HandleStartRegisterDevice(
201 dbus::MethodCall* method_call) {
202 // Read the parameters to the method.
203 dbus::MessageReader reader(method_call);
204 if (!reader.HasMoreData()) {
205 return GetBadArgsError(method_call, "No parameters to StartRegisterDevice");
206 }
207
208 dbus::MessageReader array_reader(nullptr);
209 if (!reader.PopArray(&array_reader))
210 return GetBadArgsError(method_call, "Failed to read the parameter array");
211 std::map<std::string, std::shared_ptr<base::Value>> params;
212 while (array_reader.HasMoreData()) {
213 dbus::MessageReader dict_entry_reader(nullptr);
214 if (!array_reader.PopDictEntry(&dict_entry_reader))
215 return GetBadArgsError(method_call, "Failed to get a call parameter");
216 std::string key;
217 if (!dict_entry_reader.PopString(&key))
218 return GetBadArgsError(method_call, "Failed to read parameter key");
219 base::Value* value = dbus::PopDataAsValue(&dict_entry_reader);
220 if (!value)
221 return GetBadArgsError(method_call, "Failed to read parameter value");
222 params.insert(std::make_pair(key, std::shared_ptr<base::Value>(value)));
223 }
224 if (reader.HasMoreData())
225 return GetBadArgsError(method_call,
226 "Too many parameters to StartRegisterDevice");
227
228 LOG(INFO) << "Received call to Manager.StartRegisterDevice()";
229
Alex Vakulenkoaf23b322014-05-08 16:25:45 -0700230 buffet::ErrorPtr error;
Alex Vakulenko1f30a622014-07-23 11:13:15 -0700231 std::string id = device_info_->StartRegistration(params, &error);
Alex Vakulenkob3aac252014-05-07 17:35:24 -0700232 if (id.empty())
233 return GetDBusError(method_call, error.get());
Alex Vakulenko3cb466c2014-04-15 11:36:32 -0700234
235 // Send back our response.
236 scoped_ptr<dbus::Response> response(
237 dbus::Response::FromMethodCall(method_call));
238 dbus::MessageWriter writer(response.get());
239 writer.AppendString(id);
240 return response.Pass();
241}
242
243scoped_ptr<dbus::Response> Manager::HandleFinishRegisterDevice(
244 dbus::MethodCall* method_call) {
245 // Read the parameters to the method.
246 dbus::MessageReader reader(method_call);
247 if (!reader.HasMoreData()) {
248 return GetBadArgsError(method_call,
249 "No parameters to FinishRegisterDevice");
250 }
251 std::string user_auth_code;
252 if (!reader.PopString(&user_auth_code)) {
253 return GetBadArgsError(method_call, "Failed to read UserAuthCode");
254 }
255 if (reader.HasMoreData()) {
256 return GetBadArgsError(method_call,
257 "Too many parameters to FinishRegisterDevice");
258 }
259
260 LOG(INFO) << "Received call to Manager.FinishRegisterDevice()";
Alex Vakulenkoaf23b322014-05-08 16:25:45 -0700261 buffet::ErrorPtr error;
Alex Vakulenko1f30a622014-07-23 11:13:15 -0700262 if (!device_info_->FinishRegistration(user_auth_code, &error))
Alex Vakulenkob3aac252014-05-07 17:35:24 -0700263 return GetDBusError(method_call, error.get());
264
Alex Vakulenko1f30a622014-07-23 11:13:15 -0700265 std::string device_id = device_info_->GetDeviceId(&error);
Alex Vakulenkob3aac252014-05-07 17:35:24 -0700266 if (device_id.empty())
267 return GetDBusError(method_call, error.get());
Alex Vakulenko3cb466c2014-04-15 11:36:32 -0700268
269 // Send back our response.
270 scoped_ptr<dbus::Response> response(
271 dbus::Response::FromMethodCall(method_call));
272 dbus::MessageWriter writer(response.get());
Alex Vakulenkob3aac252014-05-07 17:35:24 -0700273 writer.AppendString(device_id);
Christopher Wileya4915c42014-03-27 14:45:37 -0700274 return response.Pass();
275}
276
277scoped_ptr<dbus::Response> Manager::HandleUpdateState(
278 dbus::MethodCall *method_call) {
279 // Read the parameters to the method.
280 dbus::MessageReader reader(method_call);
281 if (!reader.HasMoreData()) {
282 return GetBadArgsError(method_call, "No parameters to UpdateState");
283 }
284 std::string json_state_fragment;
285 if (!reader.PopString(&json_state_fragment)) {
286 return GetBadArgsError(method_call, "Failed to read json_state_fragment");
287 }
288 if (reader.HasMoreData()) {
289 return GetBadArgsError(method_call, "Too many parameters to UpdateState");
290 }
291
292 LOG(INFO) << "Received call to Manager.UpdateState()";
Christopher Wileyaa3f29c2014-03-27 14:51:26 -0700293 // TODO(wiley): Merge json state blobs intelligently.
294 properties_->state_.SetValue(json_state_fragment);
Christopher Wileya4915c42014-03-27 14:45:37 -0700295
296 // Send back our response.
297 return dbus::Response::FromMethodCall(method_call);
298}
299
Christopher Wileyb76eb292014-05-05 16:09:16 -0700300scoped_ptr<dbus::Response> Manager::HandleTestMethod(
301 dbus::MethodCall* method_call) {
302 LOG(INFO) << "Received call to test method.";
303 return scoped_ptr<dbus::Response>();
304}
305
Christopher Wileya4915c42014-03-27 14:45:37 -0700306} // namespace buffet