1// Copyright 2013 The Chromium 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 "chromeos/dbus/fake_nfc_record_client.h"
6
7#include "base/logging.h"
8#include "chromeos/dbus/dbus_thread_manager.h"
9#include "chromeos/dbus/fake_nfc_device_client.h"
10#include "chromeos/dbus/fake_nfc_tag_client.h"
11#include "third_party/cros_system_api/dbus/service_constants.h"
12
13namespace chromeos {
14
15namespace {
16
17// Gets and returns the value for |key| in |dictionary| as a string. If |key| is
18// not found, returns an empty string.
19std::string GetStringValue(const base::DictionaryValue& dictionary,
20                           const std::string& key) {
21  std::string value;
22  bool result = dictionary.GetString(key, &value);
23
24  // Simply return |value|. |value| will remain untouched if
25  // base::DictionaryValue::GetString returns false.
26  DCHECK(result || value.empty());
27  return value;
28}
29
30// Gets and returns the value for |key| in |dictionary| as a double. If |key| is
31// not found, returns 0.
32double GetDoubleValue(const base::DictionaryValue& dictionary,
33                      const std::string& key) {
34  double value = 0;
35  bool result = dictionary.GetDouble(key, &value);
36
37  // Simply return |value|. |value| will remain untouched if
38  // base::DictionaryValue::GetString returns false.
39  DCHECK(result || !value);
40  return value;
41}
42
43}  // namespace
44
45const char FakeNfcRecordClient::kDeviceSmartPosterRecordPath[] =
46    "/fake/device/record0";
47const char FakeNfcRecordClient::kDeviceTextRecordPath[] =
48    "/fake/device/record1";
49const char FakeNfcRecordClient::kDeviceUriRecordPath[] = "/fake/device/record2";
50const char FakeNfcRecordClient::kTagRecordPath[] = "/fake/tag/record0";
51
52FakeNfcRecordClient::Properties::Properties(
53    const PropertyChangedCallback& callback)
54    : NfcRecordClient::Properties(NULL, callback) {
55}
56
57FakeNfcRecordClient::Properties::~Properties() {
58}
59
60void FakeNfcRecordClient::Properties::Get(
61    dbus::PropertyBase* property,
62    dbus::PropertySet::GetCallback callback) {
63  VLOG(1) << "Get " << property->name();
64  callback.Run(false);
65}
66
67void FakeNfcRecordClient::Properties::GetAll() {
68  VLOG(1) << "GetAll";
69  if (!on_get_all_callback().is_null())
70    on_get_all_callback().Run();
71}
72
73void FakeNfcRecordClient::Properties::Set(
74    dbus::PropertyBase* property,
75    dbus::PropertySet::SetCallback callback) {
76  VLOG(1) << "Set " << property->name();
77  callback.Run(false);
78}
79
80FakeNfcRecordClient::FakeNfcRecordClient()
81    : device_records_visible_(false),
82      tag_records_visible_(false) {
83  VLOG(1) << "Creating FakeNfcRecordClient";
84
85  device_smart_poster_record_properties_.reset(new Properties(
86      base::Bind(&FakeNfcRecordClient::OnPropertyChanged,
87                 base::Unretained(this),
88                 dbus::ObjectPath(kDeviceSmartPosterRecordPath))));
89  device_smart_poster_record_properties_->SetAllPropertiesReceivedCallback(
90      base::Bind(&FakeNfcRecordClient::OnPropertiesReceived,
91                 base::Unretained(this),
92                 dbus::ObjectPath(kDeviceSmartPosterRecordPath)));
93
94  device_text_record_properties_.reset(new Properties(
95      base::Bind(&FakeNfcRecordClient::OnPropertyChanged,
96                 base::Unretained(this),
97                 dbus::ObjectPath(kDeviceTextRecordPath))));
98  device_text_record_properties_->SetAllPropertiesReceivedCallback(
99      base::Bind(&FakeNfcRecordClient::OnPropertiesReceived,
100                 base::Unretained(this),
101                 dbus::ObjectPath(kDeviceTextRecordPath)));
102
103  device_uri_record_properties_.reset(new Properties(
104      base::Bind(&FakeNfcRecordClient::OnPropertyChanged,
105                 base::Unretained(this),
106                 dbus::ObjectPath(kDeviceUriRecordPath))));
107  device_uri_record_properties_->SetAllPropertiesReceivedCallback(
108      base::Bind(&FakeNfcRecordClient::OnPropertiesReceived,
109                 base::Unretained(this),
110                 dbus::ObjectPath(kDeviceUriRecordPath)));
111
112  tag_record_properties_.reset(new Properties(
113      base::Bind(&FakeNfcRecordClient::OnPropertyChanged,
114                 base::Unretained(this),
115                 dbus::ObjectPath(kTagRecordPath))));
116}
117
118FakeNfcRecordClient::~FakeNfcRecordClient() {
119}
120
121void FakeNfcRecordClient::Init(dbus::Bus* bus) {
122}
123
124void FakeNfcRecordClient::AddObserver(Observer* observer) {
125  observers_.AddObserver(observer);
126}
127
128void FakeNfcRecordClient::RemoveObserver(Observer* observer) {
129  observers_.RemoveObserver(observer);
130}
131
132std::vector<dbus::ObjectPath> FakeNfcRecordClient::GetRecordsForDevice(
133      const dbus::ObjectPath& device_path) {
134  std::vector<dbus::ObjectPath> record_paths;
135  if (device_records_visible_ &&
136      device_path == dbus::ObjectPath(FakeNfcDeviceClient::kDevicePath)) {
137    record_paths.push_back(dbus::ObjectPath(kDeviceSmartPosterRecordPath));
138    record_paths.push_back(dbus::ObjectPath(kDeviceTextRecordPath));
139    record_paths.push_back(dbus::ObjectPath(kDeviceUriRecordPath));
140  }
141  return record_paths;
142}
143
144std::vector<dbus::ObjectPath> FakeNfcRecordClient::GetRecordsForTag(
145      const dbus::ObjectPath& tag_path) {
146  std::vector<dbus::ObjectPath> record_paths;
147  if (tag_records_visible_ && tag_path.value() == FakeNfcTagClient::kTagPath)
148    record_paths.push_back(dbus::ObjectPath(kTagRecordPath));
149  return record_paths;
150}
151
152FakeNfcRecordClient::Properties*
153FakeNfcRecordClient::GetProperties(const dbus::ObjectPath& object_path) {
154  if (device_records_visible_) {
155    if (object_path.value() == kDeviceSmartPosterRecordPath)
156      return device_smart_poster_record_properties_.get();
157    if (object_path.value() == kDeviceTextRecordPath)
158      return device_text_record_properties_.get();
159    if (object_path.value() == kDeviceUriRecordPath)
160      return device_uri_record_properties_.get();
161    return NULL;
162  }
163  if (tag_records_visible_ && object_path.value() == kTagRecordPath)
164      return tag_record_properties_.get();
165  return NULL;
166}
167
168void FakeNfcRecordClient::SetDeviceRecordsVisible(bool visible) {
169  if (device_records_visible_ == visible) {
170    VLOG(1) << "Record visibility is already: " << visible;
171    return;
172  }
173  FakeNfcDeviceClient* device_client = static_cast<FakeNfcDeviceClient*>(
174      DBusThreadManager::Get()->GetNfcDeviceClient());
175  if (!device_client->device_visible()) {
176    VLOG(1) << "Cannot set records when device is not visible.";
177    return;
178  }
179  if (!visible) {
180    device_client->ClearRecords();
181    FOR_EACH_OBSERVER(
182        NfcRecordClient::Observer, observers_,
183        RecordRemoved(dbus::ObjectPath(kDeviceSmartPosterRecordPath)));
184    FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_,
185                      RecordRemoved(dbus::ObjectPath(kDeviceTextRecordPath)));
186    FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_,
187                      RecordRemoved(dbus::ObjectPath(kDeviceUriRecordPath)));
188    device_records_visible_ = visible;
189    return;
190  }
191  device_records_visible_ = visible;
192  std::vector<dbus::ObjectPath> record_paths =
193      GetRecordsForDevice(
194          dbus::ObjectPath(FakeNfcDeviceClient::kDevicePath));
195  device_client->SetRecords(record_paths);
196
197  // Reassign each property and send signals.
198  FOR_EACH_OBSERVER(
199      NfcRecordClient::Observer, observers_,
200      RecordAdded(dbus::ObjectPath(kDeviceSmartPosterRecordPath)));
201  device_smart_poster_record_properties_->type.ReplaceValue(
202      nfc_record::kTypeSmartPoster);
203  device_smart_poster_record_properties_->uri.ReplaceValue(
204      "http://fake.uri0.fake");
205  device_smart_poster_record_properties_->mime_type.ReplaceValue("text/fake");
206  device_smart_poster_record_properties_->size.ReplaceValue(128);
207  device_smart_poster_record_properties_->
208      representation.ReplaceValue("Fake Title");
209  device_smart_poster_record_properties_->encoding.ReplaceValue(
210      nfc_record::kEncodingUtf16);
211  device_smart_poster_record_properties_->language.ReplaceValue("en");
212  OnPropertiesReceived(dbus::ObjectPath(kDeviceSmartPosterRecordPath));
213
214  FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_,
215                    RecordAdded(dbus::ObjectPath(kDeviceTextRecordPath)));
216  device_text_record_properties_->type.ReplaceValue(nfc_record::kTypeText);
217  device_text_record_properties_->representation.ReplaceValue(
218      "Kablosuz \xC4\xb0leti\xC5\x9fim");
219  device_text_record_properties_->encoding.ReplaceValue(
220      nfc_record::kEncodingUtf8);
221  device_text_record_properties_->language.ReplaceValue("tr");
222  OnPropertiesReceived(dbus::ObjectPath(kDeviceTextRecordPath));
223
224  FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_,
225                    RecordAdded(dbus::ObjectPath(kDeviceUriRecordPath)));
226  device_uri_record_properties_->type.ReplaceValue(nfc_record::kTypeUri);
227  device_uri_record_properties_->uri.ReplaceValue("file://some/fake/path");
228  device_uri_record_properties_->mime_type.ReplaceValue("text/fake");
229  device_uri_record_properties_->size.ReplaceValue(512);
230  OnPropertiesReceived(dbus::ObjectPath(kDeviceUriRecordPath));
231}
232
233void FakeNfcRecordClient::SetTagRecordsVisible(bool visible) {
234  if (tag_records_visible_ == visible) {
235    VLOG(1) << "Record visibility is already: " << visible;
236    return;
237  }
238  FakeNfcTagClient* tag_client = static_cast<FakeNfcTagClient*>(
239      DBusThreadManager::Get()->GetNfcTagClient());
240  if (!tag_client->tag_visible()) {
241    VLOG(1) << "Cannot set records when tag is not visible.";
242    return;
243  }
244  if (!visible) {
245    tag_client->ClearRecords();
246    FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_,
247                      RecordRemoved(dbus::ObjectPath(kTagRecordPath)));
248    tag_records_visible_ = visible;
249    return;
250  }
251  tag_records_visible_ = visible;
252  std::vector<dbus::ObjectPath> record_paths =
253    GetRecordsForTag(dbus::ObjectPath(FakeNfcTagClient::kTagPath));
254  tag_client->SetRecords(record_paths);
255
256  // Reassign each property to its current value to trigger a property change
257  // signal.
258  FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_,
259                    RecordAdded(dbus::ObjectPath(kTagRecordPath)));
260  tag_record_properties_->type.ReplaceValue(
261      tag_record_properties_->type.value());
262  tag_record_properties_->representation.ReplaceValue(
263      tag_record_properties_->representation.value());
264  tag_record_properties_->encoding.ReplaceValue(
265      tag_record_properties_->encoding.value());
266  tag_record_properties_->language.ReplaceValue(
267      tag_record_properties_->language.value());
268  tag_record_properties_->uri.ReplaceValue(
269      tag_record_properties_->uri.value());
270  tag_record_properties_->mime_type.ReplaceValue(
271      tag_record_properties_->mime_type.value());
272  tag_record_properties_->size.ReplaceValue(
273      tag_record_properties_->size.value());
274  tag_record_properties_->action.ReplaceValue(
275      tag_record_properties_->action.value());
276  OnPropertiesReceived(dbus::ObjectPath(kTagRecordPath));
277}
278
279bool FakeNfcRecordClient::WriteTagRecord(
280    const base::DictionaryValue& attributes) {
281  if (attributes.empty())
282    return false;
283
284  tag_record_properties_->type.ReplaceValue(
285      GetStringValue(attributes, nfc_record::kTypeProperty));
286  tag_record_properties_->encoding.ReplaceValue(
287      GetStringValue(attributes, nfc_record::kEncodingProperty));
288  tag_record_properties_->language.ReplaceValue(
289      GetStringValue(attributes, nfc_record::kLanguageProperty));
290  tag_record_properties_->representation.ReplaceValue(
291      GetStringValue(attributes, nfc_record::kRepresentationProperty));
292  tag_record_properties_->uri.ReplaceValue(
293      GetStringValue(attributes, nfc_record::kUriProperty));
294  tag_record_properties_->mime_type.ReplaceValue(
295      GetStringValue(attributes, nfc_record::kMimeTypeProperty));
296  tag_record_properties_->action.ReplaceValue(
297      GetStringValue(attributes, nfc_record::kActionProperty));
298  tag_record_properties_->size.ReplaceValue(static_cast<uint32>(
299      GetDoubleValue(attributes, nfc_record::kSizeProperty)));
300
301  SetTagRecordsVisible(false);
302  SetTagRecordsVisible(true);
303
304  return true;
305}
306
307void FakeNfcRecordClient::OnPropertyChanged(
308    const dbus::ObjectPath& object_path,
309    const std::string& property_name) {
310  FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_,
311                    RecordPropertyChanged(object_path, property_name));
312}
313
314void FakeNfcRecordClient::OnPropertiesReceived(
315    const dbus::ObjectPath& object_path) {
316  FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_,
317                    RecordPropertiesReceived(object_path));
318}
319
320}  // namespace chromeos
321