1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file.
4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chromeos/dbus/nfc_record_client.h"
6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/bind.h"
8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/memory/weak_ptr.h"
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/observer_list.h"
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chromeos/dbus/nfc_device_client.h"
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chromeos/dbus/nfc_tag_client.h"
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "dbus/bus.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using chromeos::nfc_client_helpers::DBusObjectMap;
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using chromeos::nfc_client_helpers::ObjectProxyTree;
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace chromeos {
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)NfcRecordClient::Properties::Properties(
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    dbus::ObjectProxy* object_proxy,
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const PropertyChangedCallback& callback)
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : NfcPropertySet(object_proxy,
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                     nfc_record::kNfcRecordInterface,
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                     callback) {
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  RegisterProperty(nfc_record::kTypeProperty, &type);
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  RegisterProperty(nfc_record::kLanguageProperty, &language);
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  RegisterProperty(nfc_record::kEncodingProperty, &encoding);
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  RegisterProperty(nfc_record::kRepresentationProperty, &representation);
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  RegisterProperty(nfc_record::kUriProperty, &uri);
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  RegisterProperty(nfc_record::kMimeTypeProperty, &mime_type);
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  RegisterProperty(nfc_record::kSizeProperty, &size);
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  RegisterProperty(nfc_record::kActionProperty, &action);
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)NfcRecordClient::Properties::~Properties() {
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// The NfcRecordClient implementation used in production.
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class NfcRecordClientImpl : public NfcRecordClient,
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            public NfcDeviceClient::Observer,
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            public NfcTagClient::Observer,
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            public DBusObjectMap::Delegate {
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public:
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  explicit NfcRecordClientImpl(NfcDeviceClient* device_client,
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                               NfcTagClient* tag_client)
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      : bus_(NULL),
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        device_client_(device_client),
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        tag_client_(tag_client),
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        weak_ptr_factory_(this) {
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(device_client);
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(tag_client);
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual ~NfcRecordClientImpl() {
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(device_client_);
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(tag_client_);
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    device_client_->RemoveObserver(this);
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    tag_client_->RemoveObserver(this);
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // NfcRecordClient override.
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void AddObserver(NfcRecordClient::Observer* observer) OVERRIDE {
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(observer);
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    observers_.AddObserver(observer);
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // NfcRecordClient override.
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void RemoveObserver(NfcRecordClient::Observer* observer) OVERRIDE {
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(observer);
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    observers_.RemoveObserver(observer);
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual std::vector<dbus::ObjectPath> GetRecordsForDevice(
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const dbus::ObjectPath& device_path) OVERRIDE {
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DBusObjectMap* object_map =
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        devices_and_tags_to_object_maps_.GetObjectMap(device_path);
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!object_map)
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return std::vector<dbus::ObjectPath>();
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return object_map->GetObjectPaths();
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual std::vector<dbus::ObjectPath> GetRecordsForTag(
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const dbus::ObjectPath& tag_path) OVERRIDE {
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return GetRecordsForDevice(tag_path);
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // NfcRecordClient override.
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual Properties* GetProperties(
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      const dbus::ObjectPath& object_path) OVERRIDE {
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return static_cast<Properties*>(
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        devices_and_tags_to_object_maps_.FindObjectProperties(object_path));
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) protected:
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // DBusClient override.
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void Init(dbus::Bus* bus) OVERRIDE {
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    VLOG(1) << "Creating NfcRecordClient impl";
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(bus);
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bus_ = bus;
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(device_client_);
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(tag_client_);
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    device_client_->AddObserver(this);
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    tag_client_->AddObserver(this);
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private:
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // NfcDeviceClient::Observer override.
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void DeviceAdded(const dbus::ObjectPath& object_path) OVERRIDE {
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    VLOG(1) << "Device added. Creating map for record proxies belonging to "
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            << "device: " << object_path.value();
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    devices_and_tags_to_object_maps_.CreateObjectMap(
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        object_path, nfc_record::kNfcRecordServiceName, this, bus_);
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // NfcDeviceClient::Observer override.
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void DeviceRemoved(const dbus::ObjectPath& object_path) OVERRIDE {
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Neard doesn't send out property changed signals for the records that
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // are removed when the device they belong to is removed. Clean up the
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // object proxies for records that belong to the removed device.
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Note: DBusObjectMap guarantees that the Properties structure for the
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // removed adapter will be valid before this method returns.
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    VLOG(1) << "Device removed. Cleaning up record proxies belonging to "
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            << "device: " << object_path.value();
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    devices_and_tags_to_object_maps_.RemoveObjectMap(object_path);
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // NfcDeviceClient::Observer override.
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void DevicePropertyChanged(
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      const dbus::ObjectPath& object_path,
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      const std::string& property_name) OVERRIDE {
132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Update the record proxies using records from the device.
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(device_client_);
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    NfcDeviceClient::Properties* device_properties =
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        device_client_->GetProperties(object_path);
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Ignore changes to properties other than "Records".
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (property_name != device_properties->records.name())
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return;
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Update known records.
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    VLOG(1) << "NFC records changed.";
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::vector<dbus::ObjectPath>& received_records =
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        device_properties->records.value();
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DBusObjectMap* object_map =
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        devices_and_tags_to_object_maps_.GetObjectMap(object_path);
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(object_map);
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    object_map->UpdateObjects(received_records);
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // NfcTagClient::Observer override.
152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void TagAdded(const dbus::ObjectPath& object_path) OVERRIDE {
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    VLOG(1) << "Tag added. Creating map for record proxies belonging to "
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            << "tag: " << object_path.value();
155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    devices_and_tags_to_object_maps_.CreateObjectMap(
156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        object_path, nfc_record::kNfcRecordServiceName, this, bus_);
157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // NfcTagClient::Observer override.
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void TagRemoved(const dbus::ObjectPath& object_path) OVERRIDE {
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Neard doesn't send out property changed signals for the records that
162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // are removed when the tag they belong to is removed. Clean up the
163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // object proxies for records that belong to the removed tag.
164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Note: DBusObjectMap guarantees that the Properties structure for the
165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // removed adapter will be valid before this method returns.
166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    VLOG(1) << "Tag removed. Cleaning up record proxies belonging to "
167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            << "tag: " << object_path.value();
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    devices_and_tags_to_object_maps_.RemoveObjectMap(object_path);
169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // NfcTagClient::Observer override.
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void TagPropertyChanged(const dbus::ObjectPath& object_path,
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                  const std::string& property_name) OVERRIDE {
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Update the record proxies using records from the tag.
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(device_client_);
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    NfcTagClient::Properties* tag_properties =
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        tag_client_->GetProperties(object_path);
178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Ignore changes to properties other than "Records".
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (property_name != tag_properties->records.name())
181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return;
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Update known records.
184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    VLOG(1) << "NFC records changed.";
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::vector<dbus::ObjectPath>& received_records =
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        tag_properties->records.value();
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DBusObjectMap* object_map =
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        devices_and_tags_to_object_maps_.GetObjectMap(object_path);
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(object_map);
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    object_map->UpdateObjects(received_records);
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // When rewriting the record to a tag, neard fires a property changed
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // signal for the tags "Records" property, without creating a new object
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // path. Sync the properties of all records here, in case Update objects
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // doesn't do it.
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    VLOG(1) << "Fetch properties for all records.";
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    object_map->RefreshAllProperties();
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // nfc_client_helpers::DBusObjectMap::Delegate override.
201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual NfcPropertySet* CreateProperties(
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      dbus::ObjectProxy* object_proxy) OVERRIDE {
203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    Properties* properties = new Properties(
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        object_proxy,
205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        base::Bind(&NfcRecordClientImpl::OnPropertyChanged,
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(),
207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                   object_proxy->object_path()));
208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    properties->SetAllPropertiesReceivedCallback(
209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        base::Bind(&NfcRecordClientImpl::OnPropertiesReceived,
210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(),
211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                   object_proxy->object_path()));
212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return properties;
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // nfc_client_helpers::DBusObjectMap::Delegate override.
216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void ObjectAdded(const dbus::ObjectPath& object_path) OVERRIDE {
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_,
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                      RecordAdded(object_path));
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // nfc_client_helpers::DBusObjectMap::Delegate override.
222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void ObjectRemoved(const dbus::ObjectPath& object_path) OVERRIDE {
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_,
224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                      RecordRemoved(object_path));
225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Called by NfcPropertySet when a property value is changed, either by
228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // result of a signal or response to a GetAll() or Get() call.
229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void OnPropertyChanged(const dbus::ObjectPath& object_path,
230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                         const std::string& property_name) {
231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    VLOG(1) << "Record property changed; Path: " << object_path.value()
232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            << " Property: " << property_name;
233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_,
234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                      RecordPropertyChanged(object_path, property_name));
235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Called by NfcPropertySet when all properties have been processed as a
238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // result of a call to GetAll.
239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void OnPropertiesReceived(const dbus::ObjectPath& object_path) {
240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    VLOG(1) << "All record properties received; Path: " << object_path.value();
241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_,
242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                      RecordPropertiesReceived(object_path));
243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // We maintain a pointer to the bus to be able to request proxies for
246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // new NFC records that appear.
247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  dbus::Bus* bus_;
248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // List of observers interested in event notifications.
250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ObserverList<NfcRecordClient::Observer> observers_;
251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Mapping from object paths to object proxies and properties structures that
253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // were already created by us. Record objects belong to either Tag or Device
254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // objects. This structure stores a different DBusObjectMap for each known
255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // device and tag.
256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ObjectProxyTree devices_and_tags_to_object_maps_;
257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // The device and tag clients that we listen to events notifications from.
259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NfcDeviceClient* device_client_;
260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NfcTagClient* tag_client_;
261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Weak pointer factory for generating 'this' pointers that might live longer
262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // than we do.
263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Note: This should remain the last member so it'll be destroyed and
264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // invalidate its weak pointers before any other members are destroyed.
265f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::WeakPtrFactory<NfcRecordClientImpl> weak_ptr_factory_;
266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(NfcRecordClientImpl);
268f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
269f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)NfcRecordClient::NfcRecordClient() {
271f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
272f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)NfcRecordClient::~NfcRecordClient() {
274f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
276a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)NfcRecordClient* NfcRecordClient::Create(NfcDeviceClient* device_client,
277f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                         NfcTagClient* tag_client) {
278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return new NfcRecordClientImpl(device_client, tag_client);
279f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
280f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace chromeos
282