1 // Copyright 2012 The ChromiumOS Authors
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 "include/prop_registry.h"
6
7 #include <set>
8 #include <string>
9
10 #include <json/value.h>
11
12 #include "include/activity_log.h"
13 #include "include/gestures.h"
14
15 using std::set;
16 using std::string;
17
18 namespace gestures {
19
Register(Property * prop)20 void PropRegistry::Register(Property* prop) {
21 props_.insert(prop);
22 if (prop_provider_)
23 prop->CreateProp();
24 }
25
Unregister(Property * prop)26 void PropRegistry::Unregister(Property* prop) {
27 if (props_.erase(prop) != 1)
28 Err("Unregister failed?");
29 if (prop_provider_)
30 prop->DestroyProp();
31 }
32
SetPropProvider(GesturesPropProvider * prop_provider,void * data)33 void PropRegistry::SetPropProvider(GesturesPropProvider* prop_provider,
34 void* data) {
35 if (prop_provider_ == prop_provider)
36 return;
37 if (prop_provider_) {
38 for (std::set<Property*>::iterator it = props_.begin(), e= props_.end();
39 it != e; ++it)
40 (*it)->DestroyProp();
41 }
42 prop_provider_ = prop_provider;
43 prop_provider_data_ = data;
44 if (prop_provider_)
45 for (std::set<Property*>::iterator it = props_.begin(), e= props_.end();
46 it != e; ++it)
47 (*it)->CreateProp();
48 }
49
CreateProp()50 void Property::CreateProp() {
51 if (gprop_)
52 Err("Property already created");
53 CreatePropImpl();
54 if (parent_) {
55 parent_->PropProvider()->register_handlers_fn(
56 parent_->PropProviderData(),
57 gprop_,
58 this,
59 &StaticHandleGesturesPropWillRead,
60 &StaticHandleGesturesPropWritten);
61 }
62 }
63
DestroyProp()64 void Property::DestroyProp() {
65 if (!gprop_) {
66 Err("gprop_ already freed!");
67 return;
68 }
69 parent_->PropProvider()->free_fn(parent_->PropProviderData(), gprop_);
70 gprop_ = nullptr;
71 }
72
CreatePropImpl()73 void BoolProperty::CreatePropImpl() {
74 GesturesPropBool orig_val = val_;
75 gprop_ = parent_->PropProvider()->create_bool_fn(
76 parent_->PropProviderData(),
77 name(),
78 &val_,
79 1,
80 &val_);
81 if (delegate_ && orig_val != val_)
82 delegate_->BoolWasWritten(this);
83 }
84
NewValue() const85 Json::Value BoolProperty::NewValue() const {
86 return Json::Value(val_ != 0);
87 }
88
SetValue(const Json::Value & value)89 bool BoolProperty::SetValue(const Json::Value& value) {
90 if (value.type() != Json::booleanValue) {
91 return false;
92 }
93 val_ = value.asBool();
94 return true;
95 }
96
HandleGesturesPropWritten()97 void BoolProperty::HandleGesturesPropWritten() {
98 if (parent_ && parent_->activity_log()) {
99 ActivityLog::PropChangeEntry entry = {
100 name(), { val_ }
101 };
102 parent_->activity_log()->LogPropChange(entry);
103 }
104 if (delegate_)
105 delegate_->BoolWasWritten(this);
106 }
107
CreatePropImpl()108 void BoolArrayProperty::CreatePropImpl() {
109 auto orig_vals = std::make_unique<GesturesPropBool[]>(count_);
110
111 memcpy(orig_vals.get(), vals_, count_ * sizeof(GesturesPropBool));
112 gprop_ = parent_->PropProvider()->create_bool_fn(
113 parent_->PropProviderData(),
114 name(),
115 vals_,
116 count_,
117 vals_);
118 if (delegate_ && memcmp(orig_vals.get(), vals_,
119 count_ * sizeof(GesturesPropBool)))
120 delegate_->BoolArrayWasWritten(this);
121 }
122
NewValue() const123 Json::Value BoolArrayProperty::NewValue() const {
124 Json::Value list(Json::arrayValue);
125 for (size_t i = 0; i < count_; i++)
126 list.append(Json::Value(vals_[i] != 0));
127 return list;
128 }
129
SetValue(const Json::Value & list)130 bool BoolArrayProperty::SetValue(const Json::Value& list) {
131 AssertWithReturnValue(list.type() == Json::arrayValue, false);
132 AssertWithReturnValue(list.size() == count_, false);
133
134 for (size_t i = 0; i < count_; i++) {
135 const Json::Value& elt_value = list[static_cast<int>(i)];
136 AssertWithReturnValue(elt_value.type() == Json::booleanValue, false);
137 vals_[i] = elt_value.asBool();
138 }
139
140 return true;
141 }
142
HandleGesturesPropWritten()143 void BoolArrayProperty::HandleGesturesPropWritten() {
144 // TODO(b/191802713): Log array property changes
145 if (delegate_)
146 delegate_->BoolArrayWasWritten(this);
147 }
148
CreatePropImpl()149 void DoubleProperty::CreatePropImpl() {
150 double orig_val = val_;
151 gprop_ = parent_->PropProvider()->create_real_fn(
152 parent_->PropProviderData(),
153 name(),
154 &val_,
155 1,
156 &val_);
157 if (delegate_ && orig_val != val_)
158 delegate_->DoubleWasWritten(this);
159 }
160
NewValue() const161 Json::Value DoubleProperty::NewValue() const {
162 return Json::Value(val_);
163 }
164
SetValue(const Json::Value & value)165 bool DoubleProperty::SetValue(const Json::Value& value) {
166 if (value.type() != Json::realValue &&
167 value.type() != Json::intValue &&
168 value.type() != Json::uintValue) {
169 return false;
170 }
171 val_ = value.asDouble();
172 return true;
173 }
174
HandleGesturesPropWritten()175 void DoubleProperty::HandleGesturesPropWritten() {
176 if (parent_ && parent_->activity_log()) {
177 ActivityLog::PropChangeEntry entry = {
178 name(), { val_ }
179 };
180 parent_->activity_log()->LogPropChange(entry);
181 }
182 if (delegate_)
183 delegate_->DoubleWasWritten(this);
184 }
185
CreatePropImpl()186 void DoubleArrayProperty::CreatePropImpl() {
187 auto orig_vals = std::make_unique<float[]>(count_);
188
189 memcpy(orig_vals.get(), vals_, count_ * sizeof(float));
190 gprop_ = parent_->PropProvider()->create_real_fn(
191 parent_->PropProviderData(),
192 name(),
193 vals_,
194 count_,
195 vals_);
196 if (delegate_ && memcmp(orig_vals.get(), vals_, count_ * sizeof(float)))
197 delegate_->DoubleArrayWasWritten(this);
198 }
199
NewValue() const200 Json::Value DoubleArrayProperty::NewValue() const {
201 Json::Value list(Json::arrayValue);
202 for (size_t i = 0; i < count_; i++) {
203 // Avoid infinity
204 double log_val = std::max(-1e30, std::min(vals_[i], 1e30));
205 list.append(Json::Value(log_val));
206 }
207 return list;
208 }
209
SetValue(const Json::Value & list)210 bool DoubleArrayProperty::SetValue(const Json::Value& list) {
211 AssertWithReturnValue(list.type() == Json::arrayValue, false);
212 AssertWithReturnValue(list.size() == count_, false);
213
214 for (size_t i = 0; i < count_; i++) {
215 Json::Value elt_value = list[static_cast<int>(i)];
216 AssertWithReturnValue(elt_value.type() == Json::realValue ||
217 elt_value.type() == Json::intValue ||
218 elt_value.type() == Json::uintValue, false);
219 vals_[i] = elt_value.asDouble();
220 }
221
222 return true;
223 }
224
HandleGesturesPropWritten()225 void DoubleArrayProperty::HandleGesturesPropWritten() {
226 // TODO(b/191802713): Log array property changes
227 if (delegate_)
228 delegate_->DoubleArrayWasWritten(this);
229 }
230
CreatePropImpl()231 void IntProperty::CreatePropImpl() {
232 int orig_val = val_;
233 gprop_ = parent_->PropProvider()->create_int_fn(
234 parent_->PropProviderData(),
235 name(),
236 &val_,
237 1,
238 &val_);
239 if (delegate_ && orig_val != val_)
240 delegate_->IntWasWritten(this);
241 }
242
NewValue() const243 Json::Value IntProperty::NewValue() const {
244 return Json::Value(val_);
245 }
246
SetValue(const Json::Value & value)247 bool IntProperty::SetValue(const Json::Value& value) {
248 if (value.type() != Json::intValue &&
249 value.type() != Json::uintValue) {
250 Err("Failing here %d", value.type());
251 return false;
252 }
253 val_ = value.asInt();
254 return true;
255 }
256
HandleGesturesPropWritten()257 void IntProperty::HandleGesturesPropWritten() {
258 if (parent_ && parent_->activity_log()) {
259 ActivityLog::PropChangeEntry entry = {
260 name(), { val_ }
261 };
262 parent_->activity_log()->LogPropChange(entry);
263 }
264 if (delegate_)
265 delegate_->IntWasWritten(this);
266 }
267
CreatePropImpl()268 void IntArrayProperty::CreatePropImpl() {
269 auto orig_vals = std::make_unique<int[]>(count_);
270
271 memcpy(orig_vals.get(), vals_, count_ * sizeof(int));
272 gprop_ = parent_->PropProvider()->create_int_fn(
273 parent_->PropProviderData(),
274 name(),
275 vals_,
276 count_,
277 vals_);
278 if (delegate_ && memcmp(orig_vals.get(), vals_, count_ * sizeof(int)))
279 delegate_->IntArrayWasWritten(this);
280 }
281
NewValue() const282 Json::Value IntArrayProperty::NewValue() const {
283 Json::Value list(Json::arrayValue);
284 for (size_t i = 0; i < count_; i++)
285 list.append(Json::Value(vals_[static_cast<int>(i)]));
286 return list;
287 }
288
SetValue(const Json::Value & list)289 bool IntArrayProperty::SetValue(const Json::Value& list) {
290 AssertWithReturnValue(list.type() == Json::arrayValue, false);
291 AssertWithReturnValue(list.size() == count_, false);
292
293 for (size_t i = 0; i < count_; i++) {
294 Json::Value elt_value = list[static_cast<int>(i)];
295 AssertWithReturnValue(elt_value.type() == Json::intValue ||
296 elt_value.type() == Json::uintValue, false);
297 vals_[i] = elt_value.asInt();
298 }
299
300 return true;
301 }
302
HandleGesturesPropWritten()303 void IntArrayProperty::HandleGesturesPropWritten() {
304 // TODO(b/191802713): Log array property changes
305 if (delegate_)
306 delegate_->IntArrayWasWritten(this);
307 }
308
CreatePropImpl()309 void StringProperty::CreatePropImpl() {
310 const char* orig_val = val_;
311 gprop_ = parent_->PropProvider()->create_string_fn(
312 parent_->PropProviderData(),
313 name(),
314 &val_,
315 val_);
316 if (delegate_ && strcmp(orig_val, val_) != 0)
317 delegate_->StringWasWritten(this);
318 }
319
NewValue() const320 Json::Value StringProperty::NewValue() const {
321 return Json::Value(val_);
322 }
323
SetValue(const Json::Value & value)324 bool StringProperty::SetValue(const Json::Value& value) {
325 if (value.type() != Json::stringValue) {
326 return false;
327 }
328 parsed_val_ = value.asString();
329 val_ = parsed_val_.c_str();
330 return true;
331 }
332
HandleGesturesPropWritten()333 void StringProperty::HandleGesturesPropWritten() {
334 if (delegate_)
335 delegate_->StringWasWritten(this);
336 }
337
338 } // namespace gestures
339