diff options
author | armansito@chromium.org <armansito@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-18 08:47:17 +0000 |
---|---|---|
committer | armansito@chromium.org <armansito@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-18 08:47:17 +0000 |
commit | 20e38b8e9730ae28f077269d67e75a231bea7ca3 (patch) | |
tree | 24416175bfded4f8df6d13d99c8713df9caea7d3 /chromeos | |
parent | b826fa8f5432ba0e02306d9901aa584653130e0d (diff) | |
download | chromium_src-20e38b8e9730ae28f077269d67e75a231bea7ca3.zip chromium_src-20e38b8e9730ae28f077269d67e75a231bea7ca3.tar.gz chromium_src-20e38b8e9730ae28f077269d67e75a231bea7ca3.tar.bz2 |
nfc: Implement device::NfcTagChromeOS.
Implemented device::NfcTag for the Chrome OS platform. With this patch,
Chrome can now interact with remote NFC tags.
BUG=316471
TEST=device_unittests
Review URL: https://codereview.chromium.org/116143009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@245753 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos')
-rw-r--r-- | chromeos/dbus/fake_nfc_adapter_client.cc | 76 | ||||
-rw-r--r-- | chromeos/dbus/fake_nfc_adapter_client.h | 27 | ||||
-rw-r--r-- | chromeos/dbus/fake_nfc_device_client.cc | 17 | ||||
-rw-r--r-- | chromeos/dbus/fake_nfc_device_client.h | 9 | ||||
-rw-r--r-- | chromeos/dbus/fake_nfc_record_client.cc | 276 | ||||
-rw-r--r-- | chromeos/dbus/fake_nfc_record_client.h | 31 | ||||
-rw-r--r-- | chromeos/dbus/fake_nfc_tag_client.cc | 169 | ||||
-rw-r--r-- | chromeos/dbus/fake_nfc_tag_client.h | 75 | ||||
-rw-r--r-- | chromeos/dbus/nfc_record_client.cc | 5 | ||||
-rw-r--r-- | chromeos/dbus/nfc_record_client.h | 10 | ||||
-rw-r--r-- | chromeos/dbus/nfc_tag_client.cc | 25 | ||||
-rw-r--r-- | chromeos/dbus/nfc_tag_client.h | 14 |
12 files changed, 612 insertions, 122 deletions
diff --git a/chromeos/dbus/fake_nfc_adapter_client.cc b/chromeos/dbus/fake_nfc_adapter_client.cc index f36c262..8da285e 100644 --- a/chromeos/dbus/fake_nfc_adapter_client.cc +++ b/chromeos/dbus/fake_nfc_adapter_client.cc @@ -7,6 +7,7 @@ #include "base/logging.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_nfc_device_client.h" +#include "chromeos/dbus/fake_nfc_tag_client.h" #include "chromeos/dbus/nfc_client_helpers.h" #include "dbus/message.h" #include "dbus/object_path.h" @@ -81,7 +82,8 @@ void FakeNfcAdapterClient::Properties::Set( FakeNfcAdapterClient::FakeNfcAdapterClient() : present_(true), second_present_(false), - start_pairing_on_poll_(true) { + start_pairing_on_poll_(true), + device_pairing_(false) { VLOG(1) << "Creating FakeNfcAdapterClient"; std::vector<std::string> protocols; @@ -147,28 +149,37 @@ void FakeNfcAdapterClient::StartPollLoop( return; } if (!properties_->powered.value()) { - error_callback.Run("org.neard.Error.Failed", "Adapter not powered."); + error_callback.Run(nfc_error::kFailed, "Adapter not powered."); return; } if (properties_->polling.value()) { - error_callback.Run("org.neard.Error.Failed", "Already polling."); + error_callback.Run(nfc_error::kFailed, "Already polling."); return; } if (!properties_->devices.value().empty() || !properties_->tags.value().empty()) { - error_callback.Run("org.neard.Error.Failed", "Adapter busy."); + error_callback.Run(nfc_error::kFailed, "Adapter busy."); return; } properties_->polling.ReplaceValue(true); properties_->mode.ReplaceValue(mode); callback.Run(); - FakeNfcDeviceClient* device_client = - static_cast<FakeNfcDeviceClient*>( - DBusThreadManager::Get()->GetNfcDeviceClient()); + if (!start_pairing_on_poll_) + return; - if (start_pairing_on_poll_) + if (device_pairing_) { + FakeNfcDeviceClient* device_client = + static_cast<FakeNfcDeviceClient*>( + DBusThreadManager::Get()->GetNfcDeviceClient()); device_client->BeginPairingSimulation(3000, 2000); + } else { + FakeNfcTagClient* tag_client = + static_cast<FakeNfcTagClient*>( + DBusThreadManager::Get()->GetNfcTagClient()); + tag_client->BeginPairingSimulation(2000); + } + device_pairing_ = !device_pairing_; } void FakeNfcAdapterClient::StopPollLoop( @@ -188,6 +199,10 @@ void FakeNfcAdapterClient::StopPollLoop( static_cast<FakeNfcDeviceClient*>( DBusThreadManager::Get()->GetNfcDeviceClient()); device_client->EndPairingSimulation(); + FakeNfcTagClient* tag_client = + static_cast<FakeNfcTagClient*>( + DBusThreadManager::Get()->GetNfcTagClient()); + tag_client->EndPairingSimulation(); properties_->polling.ReplaceValue(false); callback.Run(); } @@ -221,7 +236,7 @@ void FakeNfcAdapterClient::SetSecondAdapterPresent(bool present) { void FakeNfcAdapterClient::SetDevice(const dbus::ObjectPath& device_path) { LOG(INFO) << "Add device path to the fake adapter: " << device_path.value(); if (!properties_->polling.value()) { - LOG(ERROR) << "Device not polling, cannot set device."; + LOG(ERROR) << "Adapter not polling, cannot set device."; return; } const ObjectPathVector& devices(properties_->devices.value()); @@ -240,8 +255,31 @@ void FakeNfcAdapterClient::SetDevice(const dbus::ObjectPath& device_path) { properties_->devices.ReplaceValue(new_devices); } +void FakeNfcAdapterClient::SetTag(const dbus::ObjectPath& tag_path) { + LOG(INFO) << "Add tag path to the fake adapter: " << tag_path.value(); + if (!properties_->polling.value()) { + LOG(ERROR) << "Adapter not polling, cannot set tag."; + return; + } + const ObjectPathVector& tags(properties_->tags.value()); + for (ObjectPathVector::const_iterator iter = tags.begin(); + iter != tags.end(); ++iter) { + if (*iter == tag_path) { + LOG(WARNING) << "Tag path already in list of tags."; + return; + } + } + // Mark as not polling. + properties_->polling.ReplaceValue(false); + + ObjectPathVector new_tags = tags; + new_tags.push_back(tag_path); + properties_->tags.ReplaceValue(new_tags); +} + void FakeNfcAdapterClient::UnsetDevice(const dbus::ObjectPath& device_path) { - LOG(INFO) << "Add device path to the fake adapter: " << device_path.value(); + LOG(INFO) << "Remove device path from the fake adapter: " + << device_path.value(); ObjectPathVector new_devices = properties_->devices.value(); for (ObjectPathVector::iterator iter = new_devices.begin(); iter != new_devices.end(); ++iter) { @@ -258,6 +296,24 @@ void FakeNfcAdapterClient::UnsetDevice(const dbus::ObjectPath& device_path) { LOG(WARNING) << "Device path not in list of devices."; } +void FakeNfcAdapterClient::UnsetTag(const dbus::ObjectPath& tag_path) { + LOG(INFO) << "Add tag path to the fake adapter: " << tag_path.value(); + ObjectPathVector new_tags = properties_->tags.value(); + for (ObjectPathVector::iterator iter = new_tags.begin(); + iter != new_tags.end(); ++iter) { + if (*iter == tag_path) { + new_tags.erase(iter); + properties_->tags.ReplaceValue(new_tags); + + // Mark as polling. + DCHECK(!properties_->polling.value()); + properties_->polling.ReplaceValue(true); + return; + } + } + LOG(WARNING) << "Tag path not in list of tags."; +} + void FakeNfcAdapterClient::EnablePairingOnPoll(bool enabled) { start_pairing_on_poll_ = enabled; } diff --git a/chromeos/dbus/fake_nfc_adapter_client.h b/chromeos/dbus/fake_nfc_adapter_client.h index 6752458..0bd353a 100644 --- a/chromeos/dbus/fake_nfc_adapter_client.h +++ b/chromeos/dbus/fake_nfc_adapter_client.h @@ -60,22 +60,29 @@ class CHROMEOS_EXPORT FakeNfcAdapterClient : public NfcAdapterClient { void SetAdapterPresent(bool present); void SetSecondAdapterPresent(bool present); - // Tells the FakeNfcAdapterClient to add the device with path |device_path| - // to its list of devices exposed for |kAdapterPath0|, if it is not already in + // Tells the FakeNfcAdapterClient to add the device or tag with the given path + // to its corresponding list for |kAdapterPath0|, if it is not already in // the list and promptly triggers a property changed signal. This method will // also fail, if the polling property of the adapter is false and will set it // to false on success. void SetDevice(const dbus::ObjectPath& device_path); + void SetTag(const dbus::ObjectPath& tag_path); - // Talls the FakeNfcAdapterClient to remove the device with path - // |device_path| from its list of devices exposed for |kAdapterPath0|, if it - // is in its list of devices. On success, this method will mark the polling - // property of the adapter to true. + // Tells the FakeNfcAdapterClient to remove the device or tag with the given + // path from its corresponding list exposed for |kAdapterPath0|, if it + // is in the list. On success, this method will mark the polling property of + // the adapter to true. void UnsetDevice(const dbus::ObjectPath& device_path); + void UnsetTag(const dbus::ObjectPath& tag_path); // Sets a flag that determines whether FakeNfcAdapterClient should notify - // FakeNfcDeviceClient to start a pairing simulation as a result of a call - // to StartPollLoop(). This is enabled by default. + // FakeNfcDeviceClient or FakeNfcTagClient to start a pairing simulation as a + // result of a call to StartPollLoop(). This is enabled by default. If + // enabled, the first call to StartPollLoop, will initiate a tag pairing + // simulation. The simulation will alternate between device and tag pairing on + // each successive call to StartPollLoop. This behavior, which is meant for + // feature development based on fake classes, can be disabled to allow manual + // control for unit tests. void EnablePairingOnPoll(bool enabled); private: @@ -98,6 +105,10 @@ class CHROMEOS_EXPORT FakeNfcAdapterClient : public NfcAdapterClient { // StartPollLoop(). bool start_pairing_on_poll_; + // If true, device pairing will be simulated on the next call to + // StartPollLoop. Otherwise, tag pairing will be simulated. + bool device_pairing_; + DISALLOW_COPY_AND_ASSIGN(FakeNfcAdapterClient); }; diff --git a/chromeos/dbus/fake_nfc_device_client.cc b/chromeos/dbus/fake_nfc_device_client.cc index d5f7a21..cf43f08 100644 --- a/chromeos/dbus/fake_nfc_device_client.cc +++ b/chromeos/dbus/fake_nfc_device_client.cc @@ -13,6 +13,7 @@ #include "chromeos/dbus/fake_nfc_record_client.h" #include "chromeos/dbus/nfc_client_helpers.h" #include "dbus/object_path.h" +#include "third_party/cros_system_api/dbus/service_constants.h" namespace chromeos { @@ -77,7 +78,7 @@ std::vector<dbus::ObjectPath> FakeNfcDeviceClient::GetDevicesForAdapter( const dbus::ObjectPath& adapter_path) { std::vector<dbus::ObjectPath> device_paths; if (device_visible_ && - adapter_path == dbus::ObjectPath(FakeNfcAdapterClient::kAdapterPath0)) + adapter_path.value() == FakeNfcAdapterClient::kAdapterPath0) device_paths.push_back(dbus::ObjectPath(kDevicePath)); return device_paths; } @@ -97,6 +98,11 @@ void FakeNfcDeviceClient::Push( VLOG(1) << "FakeNfcDeviceClient::Write called."; // Success! + if (!device_visible_) { + LOG(ERROR) << "Device not visible. Cannot push record."; + error_callback.Run(nfc_error::kDoesNotExist, "No such device."); + return; + } callback.Run(); } @@ -107,10 +113,7 @@ void FakeNfcDeviceClient::BeginPairingSimulation(int visibility_delay, return; } DCHECK(!device_visible_); - - // Cap the |visibility_delay| value at zero. Leave |record_push_delay| as is, - // as a negative value has a special meaning for it. - visibility_delay = visibility_delay < 0 ? 0 : visibility_delay; + DCHECK(visibility_delay >= 0); pairing_started_ = true; @@ -133,7 +136,7 @@ void FakeNfcDeviceClient::EndPairingSimulation() { FakeNfcRecordClient* record_client = static_cast<FakeNfcRecordClient*>( DBusThreadManager::Get()->GetNfcRecordClient()); - record_client->SetRecordsVisible(false); + record_client->SetDeviceRecordsVisible(false); } // Remove the device. FOR_EACH_OBSERVER(Observer, observers_, @@ -218,7 +221,7 @@ void FakeNfcDeviceClient::MakeRecordsVisible() { FakeNfcRecordClient* record_client = static_cast<FakeNfcRecordClient*>( DBusThreadManager::Get()->GetNfcRecordClient()); - record_client->SetRecordsVisible(true); + record_client->SetDeviceRecordsVisible(true); if (simulation_timeout_ < 0) return; diff --git a/chromeos/dbus/fake_nfc_device_client.h b/chromeos/dbus/fake_nfc_device_client.h index 50734e3..ab89c08 100644 --- a/chromeos/dbus/fake_nfc_device_client.h +++ b/chromeos/dbus/fake_nfc_device_client.h @@ -56,8 +56,8 @@ class CHROMEOS_EXPORT FakeNfcDeviceClient : public NfcDeviceClient { // Simulates the appearance of a device. The fake device will show up after // exactly |visibility_delay| milliseconds, and will simulate pushing a single // record to the local fake adapter after exactly |record_push_delay| - // milliseconds after the the device appears. If |visibility_delay| has a - // negative value, it will be treated as 0. If |record_push_delay| has a + // milliseconds after the the device appears. |visibility_delay| must have a + // non-negative value. |record_push_delay| CAN be negative: if it has a // negative value, the record push step will not be simulated. The // side-effects of this method occur asynchronously, i.e. even with arguments // with value 0, the pairing won't take place until after this method has @@ -72,8 +72,9 @@ class CHROMEOS_EXPORT FakeNfcDeviceClient : public NfcDeviceClient { // Enables or disables automatic unpairing. When enabled, a pairing // simulation will end |simulation_timeout| milliseconds after records have - // been exposed. This is enabled by default and the timeout is set to - // |kDefaultSimulationTimeoutMilliseconds|. + // been exposed (or after the tag has been exposed, if |record_push_delay| was + // given as a negative value to BeginPairingSimulation) This is enabled by + // default and the timeout is set to |kDefaultSimulationTimeoutMilliseconds|. void EnableSimulationTimeout(int simulation_timeout); void DisableSimulationTimeout(); diff --git a/chromeos/dbus/fake_nfc_record_client.cc b/chromeos/dbus/fake_nfc_record_client.cc index ef77aad..c16b300 100644 --- a/chromeos/dbus/fake_nfc_record_client.cc +++ b/chromeos/dbus/fake_nfc_record_client.cc @@ -7,13 +7,47 @@ #include "base/logging.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_nfc_device_client.h" +#include "chromeos/dbus/fake_nfc_tag_client.h" #include "third_party/cros_system_api/dbus/service_constants.h" namespace chromeos { -const char FakeNfcRecordClient::kSmartPosterRecordPath[] = "/fake/record0"; -const char FakeNfcRecordClient::kTextRecordPath[] = "/fake/record1"; -const char FakeNfcRecordClient::kUriRecordPath[] = "/fake/record2"; +namespace { + +// Gets and returns the value for |key| in |dictionary| as a string. If |key| is +// not found, returns an empty string. +std::string GetStringValue(const base::DictionaryValue& dictionary, + const std::string& key) { + std::string value; + bool result = dictionary.GetString(key, &value); + + // Simply return |value|. |value| will remain untouched if + // base::DictionaryValue::GetString returns false. + DCHECK(result || value.empty()); + return value; +} + +// Gets and returns the value for |key| in |dictionary| as a double. If |key| is +// not found, returns 0. +double GetDoubleValue(const base::DictionaryValue& dictionary, + const std::string& key) { + double value = 0; + bool result = dictionary.GetDouble(key, &value); + + // Simply return |value|. |value| will remain untouched if + // base::DictionaryValue::GetString returns false. + DCHECK(result || !value); + return value; +} + +} // namespace + +const char FakeNfcRecordClient::kDeviceSmartPosterRecordPath[] = + "/fake/device/record0"; +const char FakeNfcRecordClient::kDeviceTextRecordPath[] = + "/fake/device/record1"; +const char FakeNfcRecordClient::kDeviceUriRecordPath[] = "/fake/device/record2"; +const char FakeNfcRecordClient::kTagRecordPath[] = "/fake/tag/record0"; FakeNfcRecordClient::Properties::Properties( const PropertyChangedCallback& callback) @@ -43,34 +77,42 @@ void FakeNfcRecordClient::Properties::Set( callback.Run(false); } -FakeNfcRecordClient::FakeNfcRecordClient() : records_visible_(false) { +FakeNfcRecordClient::FakeNfcRecordClient() + : device_records_visible_(false), + tag_records_visible_(false) { VLOG(1) << "Creating FakeNfcRecordClient"; - smart_poster_record_properties_.reset(new Properties( + + device_smart_poster_record_properties_.reset(new Properties( base::Bind(&FakeNfcRecordClient::OnPropertyChanged, base::Unretained(this), - dbus::ObjectPath(kSmartPosterRecordPath)))); - smart_poster_record_properties_->SetAllPropertiesReceivedCallback( + dbus::ObjectPath(kDeviceSmartPosterRecordPath)))); + device_smart_poster_record_properties_->SetAllPropertiesReceivedCallback( base::Bind(&FakeNfcRecordClient::OnPropertiesReceived, base::Unretained(this), - dbus::ObjectPath(kSmartPosterRecordPath))); + dbus::ObjectPath(kDeviceSmartPosterRecordPath))); - text_record_properties_.reset(new Properties( + device_text_record_properties_.reset(new Properties( base::Bind(&FakeNfcRecordClient::OnPropertyChanged, base::Unretained(this), - dbus::ObjectPath(kTextRecordPath)))); - text_record_properties_->SetAllPropertiesReceivedCallback( + dbus::ObjectPath(kDeviceTextRecordPath)))); + device_text_record_properties_->SetAllPropertiesReceivedCallback( base::Bind(&FakeNfcRecordClient::OnPropertiesReceived, base::Unretained(this), - dbus::ObjectPath(kTextRecordPath))); + dbus::ObjectPath(kDeviceTextRecordPath))); - uri_record_properties_.reset(new Properties( + device_uri_record_properties_.reset(new Properties( base::Bind(&FakeNfcRecordClient::OnPropertyChanged, base::Unretained(this), - dbus::ObjectPath(kUriRecordPath)))); - uri_record_properties_->SetAllPropertiesReceivedCallback( + dbus::ObjectPath(kDeviceUriRecordPath)))); + device_uri_record_properties_->SetAllPropertiesReceivedCallback( base::Bind(&FakeNfcRecordClient::OnPropertiesReceived, base::Unretained(this), - dbus::ObjectPath(kUriRecordPath))); + dbus::ObjectPath(kDeviceUriRecordPath))); + + tag_record_properties_.reset(new Properties( + base::Bind(&FakeNfcRecordClient::OnPropertyChanged, + base::Unretained(this), + dbus::ObjectPath(kTagRecordPath)))); } FakeNfcRecordClient::~FakeNfcRecordClient() { @@ -90,30 +132,41 @@ void FakeNfcRecordClient::RemoveObserver(Observer* observer) { std::vector<dbus::ObjectPath> FakeNfcRecordClient::GetRecordsForDevice( const dbus::ObjectPath& device_path) { std::vector<dbus::ObjectPath> record_paths; - if (records_visible_ && + if (device_records_visible_ && device_path == dbus::ObjectPath(FakeNfcDeviceClient::kDevicePath)) { - record_paths.push_back(dbus::ObjectPath(kSmartPosterRecordPath)); - record_paths.push_back(dbus::ObjectPath(kTextRecordPath)); - record_paths.push_back(dbus::ObjectPath(kUriRecordPath)); + record_paths.push_back(dbus::ObjectPath(kDeviceSmartPosterRecordPath)); + record_paths.push_back(dbus::ObjectPath(kDeviceTextRecordPath)); + record_paths.push_back(dbus::ObjectPath(kDeviceUriRecordPath)); } return record_paths; } +std::vector<dbus::ObjectPath> FakeNfcRecordClient::GetRecordsForTag( + const dbus::ObjectPath& tag_path) { + std::vector<dbus::ObjectPath> record_paths; + if (tag_records_visible_ && tag_path.value() == FakeNfcTagClient::kTagPath) + record_paths.push_back(dbus::ObjectPath(kTagRecordPath)); + return record_paths; +} + FakeNfcRecordClient::Properties* FakeNfcRecordClient::GetProperties(const dbus::ObjectPath& object_path) { - if (!records_visible_) + if (device_records_visible_) { + if (object_path.value() == kDeviceSmartPosterRecordPath) + return device_smart_poster_record_properties_.get(); + if (object_path.value() == kDeviceTextRecordPath) + return device_text_record_properties_.get(); + if (object_path.value() == kDeviceUriRecordPath) + return device_uri_record_properties_.get(); return NULL; - if (object_path.value() == kSmartPosterRecordPath) - return smart_poster_record_properties_.get(); - if (object_path.value() == kTextRecordPath) - return text_record_properties_.get(); - if (object_path.value() == kUriRecordPath) - return uri_record_properties_.get(); + } + if (tag_records_visible_ && object_path.value() == kTagRecordPath) + return tag_record_properties_.get(); return NULL; } -void FakeNfcRecordClient::SetRecordsVisible(bool visible) { - if (records_visible_ == visible) { +void FakeNfcRecordClient::SetDeviceRecordsVisible(bool visible) { + if (device_records_visible_ == visible) { VLOG(1) << "Record visibility is already: " << visible; return; } @@ -123,55 +176,132 @@ void FakeNfcRecordClient::SetRecordsVisible(bool visible) { VLOG(1) << "Cannot set records when device is not visible."; return; } - if (visible) { - records_visible_ = visible; - std::vector<dbus::ObjectPath> record_paths = - GetRecordsForDevice( - dbus::ObjectPath(FakeNfcDeviceClient::kDevicePath)); - device_client->SetRecords(record_paths); - - // Reassign each property and send signals. - FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_, - RecordAdded(dbus::ObjectPath(kSmartPosterRecordPath))); - smart_poster_record_properties_->type.ReplaceValue( - nfc_record::kTypeSmartPoster); - smart_poster_record_properties_->uri.ReplaceValue( - "http://www.fake-uri0.com"); - smart_poster_record_properties_->mime_type.ReplaceValue("text/fake"); - smart_poster_record_properties_->size.ReplaceValue(128); - smart_poster_record_properties_->representation.ReplaceValue("Fake Title"); - smart_poster_record_properties_->encoding.ReplaceValue( - nfc_record::kEncodingUtf16); - smart_poster_record_properties_->language.ReplaceValue("en"); - OnPropertiesReceived(dbus::ObjectPath(kSmartPosterRecordPath)); - - FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_, - RecordAdded(dbus::ObjectPath(kTextRecordPath))); - text_record_properties_->type.ReplaceValue(nfc_record::kTypeText); - text_record_properties_->representation.ReplaceValue( - "Sahte Ba\xC5\x9fl\xC4\xB1k"); - text_record_properties_->encoding.ReplaceValue( - nfc_record::kEncodingUtf8); - text_record_properties_->language.ReplaceValue("tr"); - OnPropertiesReceived(dbus::ObjectPath(kTextRecordPath)); - - FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_, - RecordAdded(dbus::ObjectPath(kUriRecordPath))); - uri_record_properties_->type.ReplaceValue(nfc_record::kTypeUri); - uri_record_properties_->uri.ReplaceValue("file://some/fake/path"); - uri_record_properties_->mime_type.ReplaceValue("text/fake"); - uri_record_properties_->size.ReplaceValue(512); - OnPropertiesReceived(dbus::ObjectPath(kUriRecordPath)); - } else { + if (!visible) { device_client->ClearRecords(); + FOR_EACH_OBSERVER( + NfcRecordClient::Observer, observers_, + RecordRemoved(dbus::ObjectPath(kDeviceSmartPosterRecordPath))); FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_, - RecordRemoved(dbus::ObjectPath(kSmartPosterRecordPath))); + RecordRemoved(dbus::ObjectPath(kDeviceTextRecordPath))); FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_, - RecordRemoved(dbus::ObjectPath(kTextRecordPath))); + RecordRemoved(dbus::ObjectPath(kDeviceUriRecordPath))); + device_records_visible_ = visible; + return; + } + device_records_visible_ = visible; + std::vector<dbus::ObjectPath> record_paths = + GetRecordsForDevice( + dbus::ObjectPath(FakeNfcDeviceClient::kDevicePath)); + device_client->SetRecords(record_paths); + + // Reassign each property and send signals. + FOR_EACH_OBSERVER( + NfcRecordClient::Observer, observers_, + RecordAdded(dbus::ObjectPath(kDeviceSmartPosterRecordPath))); + device_smart_poster_record_properties_->type.ReplaceValue( + nfc_record::kTypeSmartPoster); + device_smart_poster_record_properties_->uri.ReplaceValue( + "http://fake.uri0.fake"); + device_smart_poster_record_properties_->mime_type.ReplaceValue("text/fake"); + device_smart_poster_record_properties_->size.ReplaceValue(128); + device_smart_poster_record_properties_-> + representation.ReplaceValue("Fake Title"); + device_smart_poster_record_properties_->encoding.ReplaceValue( + nfc_record::kEncodingUtf16); + device_smart_poster_record_properties_->language.ReplaceValue("en"); + OnPropertiesReceived(dbus::ObjectPath(kDeviceSmartPosterRecordPath)); + + FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_, + RecordAdded(dbus::ObjectPath(kDeviceTextRecordPath))); + device_text_record_properties_->type.ReplaceValue(nfc_record::kTypeText); + device_text_record_properties_->representation.ReplaceValue( + "Kablosuz \xC4\xb0leti\xC5\x9fim"); + device_text_record_properties_->encoding.ReplaceValue( + nfc_record::kEncodingUtf8); + device_text_record_properties_->language.ReplaceValue("tr"); + OnPropertiesReceived(dbus::ObjectPath(kDeviceTextRecordPath)); + + FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_, + RecordAdded(dbus::ObjectPath(kDeviceUriRecordPath))); + device_uri_record_properties_->type.ReplaceValue(nfc_record::kTypeUri); + device_uri_record_properties_->uri.ReplaceValue("file://some/fake/path"); + device_uri_record_properties_->mime_type.ReplaceValue("text/fake"); + device_uri_record_properties_->size.ReplaceValue(512); + OnPropertiesReceived(dbus::ObjectPath(kDeviceUriRecordPath)); +} + +void FakeNfcRecordClient::SetTagRecordsVisible(bool visible) { + if (tag_records_visible_ == visible) { + VLOG(1) << "Record visibility is already: " << visible; + return; + } + FakeNfcTagClient* tag_client = static_cast<FakeNfcTagClient*>( + DBusThreadManager::Get()->GetNfcTagClient()); + if (!tag_client->tag_visible()) { + VLOG(1) << "Cannot set records when tag is not visible."; + return; + } + if (!visible) { + tag_client->ClearRecords(); FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_, - RecordRemoved(dbus::ObjectPath(kUriRecordPath))); - records_visible_ = visible; + RecordRemoved(dbus::ObjectPath(kTagRecordPath))); + tag_records_visible_ = visible; + return; } + tag_records_visible_ = visible; + std::vector<dbus::ObjectPath> record_paths = + GetRecordsForTag(dbus::ObjectPath(FakeNfcTagClient::kTagPath)); + tag_client->SetRecords(record_paths); + + // Reassign each property to its current value to trigger a property change + // signal. + FOR_EACH_OBSERVER(NfcRecordClient::Observer, observers_, + RecordAdded(dbus::ObjectPath(kTagRecordPath))); + tag_record_properties_->type.ReplaceValue( + tag_record_properties_->type.value()); + tag_record_properties_->representation.ReplaceValue( + tag_record_properties_->representation.value()); + tag_record_properties_->encoding.ReplaceValue( + tag_record_properties_->encoding.value()); + tag_record_properties_->language.ReplaceValue( + tag_record_properties_->language.value()); + tag_record_properties_->uri.ReplaceValue( + tag_record_properties_->uri.value()); + tag_record_properties_->mime_type.ReplaceValue( + tag_record_properties_->mime_type.value()); + tag_record_properties_->size.ReplaceValue( + tag_record_properties_->size.value()); + tag_record_properties_->action.ReplaceValue( + tag_record_properties_->action.value()); + OnPropertiesReceived(dbus::ObjectPath(kTagRecordPath)); +} + +bool FakeNfcRecordClient::WriteTagRecord( + const base::DictionaryValue& attributes) { + if (attributes.empty()) + return false; + + tag_record_properties_->type.ReplaceValue( + GetStringValue(attributes, nfc_record::kTypeProperty)); + tag_record_properties_->encoding.ReplaceValue( + GetStringValue(attributes, nfc_record::kEncodingProperty)); + tag_record_properties_->language.ReplaceValue( + GetStringValue(attributes, nfc_record::kLanguageProperty)); + tag_record_properties_->representation.ReplaceValue( + GetStringValue(attributes, nfc_record::kRepresentationProperty)); + tag_record_properties_->uri.ReplaceValue( + GetStringValue(attributes, nfc_record::kUriProperty)); + tag_record_properties_->mime_type.ReplaceValue( + GetStringValue(attributes, nfc_record::kMimeTypeProperty)); + tag_record_properties_->action.ReplaceValue( + GetStringValue(attributes, nfc_record::kActionProperty)); + tag_record_properties_->size.ReplaceValue(static_cast<uint32>( + GetDoubleValue(attributes, nfc_record::kSizeProperty))); + + SetTagRecordsVisible(false); + SetTagRecordsVisible(true); + + return true; } void FakeNfcRecordClient::OnPropertyChanged( diff --git a/chromeos/dbus/fake_nfc_record_client.h b/chromeos/dbus/fake_nfc_record_client.h index db53094..9af1bcc 100644 --- a/chromeos/dbus/fake_nfc_record_client.h +++ b/chromeos/dbus/fake_nfc_record_client.h @@ -7,6 +7,7 @@ #include "base/memory/scoped_ptr.h" #include "base/observer_list.h" +#include "base/values.h" #include "chromeos/chromeos_export.h" #include "chromeos/dbus/nfc_record_client.h" #include "dbus/object_path.h" @@ -18,9 +19,10 @@ namespace chromeos { class CHROMEOS_EXPORT FakeNfcRecordClient : public NfcRecordClient { public: // Paths of the records exposed. - static const char kSmartPosterRecordPath[]; - static const char kTextRecordPath[]; - static const char kUriRecordPath[]; + static const char kDeviceSmartPosterRecordPath[]; + static const char kDeviceTextRecordPath[]; + static const char kDeviceUriRecordPath[]; + static const char kTagRecordPath[]; // Properties structure that provides fake behavior for D-Bus calls. struct Properties : public NfcRecordClient::Properties { @@ -44,11 +46,22 @@ class CHROMEOS_EXPORT FakeNfcRecordClient : public NfcRecordClient { virtual void RemoveObserver(Observer* observer) OVERRIDE; virtual std::vector<dbus::ObjectPath> GetRecordsForDevice( const dbus::ObjectPath& device_path) OVERRIDE; + virtual std::vector<dbus::ObjectPath> GetRecordsForTag( + const dbus::ObjectPath& tag_path) OVERRIDE; virtual Properties* GetProperties( const dbus::ObjectPath& object_path) OVERRIDE; // Adds or removes the fake record objects and notifies the observers. - void SetRecordsVisible(bool visible); + void SetDeviceRecordsVisible(bool visible); + void SetTagRecordsVisible(bool visible); + + // Modifies the contents of the tag record. |attributes| should be the + // same as the argument to NfcTagClient::Write. Each field will be directly + // assigned to the underlying record based on the type property, with + // no validity checking. Invalid tag content can be passed here to test + // the case where the remote application returns an incorrectly formatted + // record. + bool WriteTagRecord(const base::DictionaryValue& attributes); private: // Property changed callback passed when we create Properties* structures. @@ -59,15 +72,17 @@ class CHROMEOS_EXPORT FakeNfcRecordClient : public NfcRecordClient { void OnPropertiesReceived(const dbus::ObjectPath& object_path); // If true, the records are currently visible. - bool records_visible_; + bool device_records_visible_; + bool tag_records_visible_; // List of observers interested in event notifications from us. ObserverList<Observer> observers_; // Fake properties that are returned for the fake records. - scoped_ptr<Properties> smart_poster_record_properties_; - scoped_ptr<Properties> text_record_properties_; - scoped_ptr<Properties> uri_record_properties_; + scoped_ptr<Properties> device_smart_poster_record_properties_; + scoped_ptr<Properties> device_text_record_properties_; + scoped_ptr<Properties> device_uri_record_properties_; + scoped_ptr<Properties> tag_record_properties_; DISALLOW_COPY_AND_ASSIGN(FakeNfcRecordClient); }; diff --git a/chromeos/dbus/fake_nfc_tag_client.cc b/chromeos/dbus/fake_nfc_tag_client.cc index 6875ad0..1de3efd 100644 --- a/chromeos/dbus/fake_nfc_tag_client.cc +++ b/chromeos/dbus/fake_nfc_tag_client.cc @@ -5,14 +5,22 @@ #include "chromeos/dbus/fake_nfc_tag_client.h" #include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "base/time/time.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/fake_nfc_adapter_client.h" +#include "chromeos/dbus/fake_nfc_record_client.h" +#include "chromeos/dbus/nfc_client_helpers.h" #include "dbus/object_path.h" - -// TODO(armansito): For now, this class doesn't do anything. Implement fake -// behavior in conjunction with unit tests while implementing the src/device -// layer. +#include "third_party/cros_system_api/dbus/service_constants.h" namespace chromeos { +using nfc_client_helpers::ObjectPathVector; + +const char FakeNfcTagClient::kTagPath[] = "/fake/tag0"; +const int FakeNfcTagClient::kDefaultSimulationTimeoutMilliseconds = 20000; + FakeNfcTagClient::Properties::Properties( const PropertyChangedCallback& callback) : NfcTagClient::Properties(NULL, callback) { @@ -39,8 +47,15 @@ void FakeNfcTagClient::Properties::Set( callback.Run(false); } -FakeNfcTagClient::FakeNfcTagClient() { +FakeNfcTagClient::FakeNfcTagClient() + : pairing_started_(false), + tag_visible_(false), + simulation_timeout_(kDefaultSimulationTimeoutMilliseconds) { VLOG(1) << "Creating FakeNfcTagClient"; + properties_.reset(new Properties( + base::Bind(&FakeNfcTagClient::OnPropertyChanged, + base::Unretained(this), + dbus::ObjectPath(kTagPath)))); } FakeNfcTagClient::~FakeNfcTagClient() { @@ -50,14 +65,27 @@ void FakeNfcTagClient::Init(dbus::Bus* bus) { } void FakeNfcTagClient::AddObserver(Observer* observer) { + observers_.AddObserver(observer); } void FakeNfcTagClient::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +std::vector<dbus::ObjectPath> FakeNfcTagClient::GetTagsForAdapter( + const dbus::ObjectPath& adapter_path) { + std::vector<dbus::ObjectPath> tag_paths; + if (tag_visible_ && + adapter_path.value() == FakeNfcAdapterClient::kAdapterPath0) + tag_paths.push_back(dbus::ObjectPath(kTagPath)); + return tag_paths; } FakeNfcTagClient::Properties* FakeNfcTagClient::GetProperties(const dbus::ObjectPath& object_path) { - return NULL; + if (!tag_visible_) + return NULL; + return properties_.get(); } void FakeNfcTagClient::Write( @@ -66,6 +94,135 @@ void FakeNfcTagClient::Write( const base::Closure& callback, const nfc_client_helpers::ErrorCallback& error_callback) { VLOG(1) << "FakeNfcTagClient::Write called. Nothing happened."; + + if (!tag_visible_ || object_path.value() != kTagPath) { + LOG(ERROR) << "No such tag: " << object_path.value(); + error_callback.Run(nfc_error::kDoesNotExist, "No such tag."); + return; + } + + FakeNfcRecordClient* record_client = static_cast<FakeNfcRecordClient*>( + DBusThreadManager::Get()->GetNfcRecordClient()); + if (!record_client->WriteTagRecord(attributes)) { + LOG(ERROR) << "Failed to tag: " << object_path.value(); + error_callback.Run(nfc_error::kFailed, "Failed."); + return; + } + + // Success! + callback.Run(); +} + +void FakeNfcTagClient::BeginPairingSimulation(int visibility_delay) { + if (pairing_started_) { + VLOG(1) << "Simulation already started."; + return; + } + DCHECK(!tag_visible_); + DCHECK(visibility_delay >= 0); + + pairing_started_ = true; + + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeNfcTagClient::MakeTagVisible, + base::Unretained(this)), + base::TimeDelta::FromMilliseconds(visibility_delay)); +} + +void FakeNfcTagClient::EndPairingSimulation() { + if (!pairing_started_) { + VLOG(1) << "No simulation started."; + return; + } + + pairing_started_ = false; + if (!tag_visible_) + return; + + // Remove records, if they were added. + if (!properties_->records.value().empty()) { + FakeNfcRecordClient* record_client = + static_cast<FakeNfcRecordClient*>( + DBusThreadManager::Get()->GetNfcRecordClient()); + record_client->SetTagRecordsVisible(false); + } + // Remove the tag. + FOR_EACH_OBSERVER(Observer, observers_, + TagRemoved(dbus::ObjectPath(kTagPath))); + FakeNfcAdapterClient* adapter_client = + static_cast<FakeNfcAdapterClient*>( + DBusThreadManager::Get()->GetNfcAdapterClient()); + adapter_client->UnsetTag(dbus::ObjectPath(kTagPath)); + tag_visible_ = false; +} + +void FakeNfcTagClient::EnableSimulationTimeout(int simulation_timeout) { + DCHECK(simulation_timeout >= 0); + simulation_timeout_ = simulation_timeout; +} + +void FakeNfcTagClient::DisableSimulationTimeout() { + simulation_timeout_ = -1; +} + +void FakeNfcTagClient::SetRecords( + const std::vector<dbus::ObjectPath>& record_paths) { + if (!tag_visible_) { + VLOG(1) << "Tag not visible."; + return; + } + properties_->records.ReplaceValue(record_paths); +} + +void FakeNfcTagClient::ClearRecords() { + ObjectPathVector records; + SetRecords(records); +} + +void FakeNfcTagClient::OnPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name) { + FOR_EACH_OBSERVER(Observer, observers_, + TagPropertyChanged(object_path, property_name)); +} + +void FakeNfcTagClient::MakeTagVisible() { + if (!pairing_started_) { + VLOG(1) << "Tag pairing was cancelled."; + return; + } + tag_visible_ = true; + + // Set the tag properties. + FakeNfcAdapterClient* adapter_client = + static_cast<FakeNfcAdapterClient*>( + DBusThreadManager::Get()->GetNfcAdapterClient()); + adapter_client->SetTag(dbus::ObjectPath(kTagPath)); + FOR_EACH_OBSERVER(Observer, observers_, + TagAdded(dbus::ObjectPath(kTagPath))); + + properties_->type.ReplaceValue(nfc_tag::kTagType2); + properties_->protocol.ReplaceValue(nfc_common::kProtocolNfcDep); + properties_->read_only.ReplaceValue(false); + FOR_EACH_OBSERVER(Observer, observers_, + TagPropertiesReceived(dbus::ObjectPath(kTagPath))); + + if (simulation_timeout_ >= 0) { + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeNfcTagClient::HandleSimulationTimeout, + base::Unretained(this)), + base::TimeDelta::FromMilliseconds(simulation_timeout_)); + return; + } +} + +void FakeNfcTagClient::HandleSimulationTimeout() { + if (simulation_timeout_ < 0) { + VLOG(1) << "Simulation timeout was cancelled. Nothing to do."; + return; + } + EndPairingSimulation(); } } // namespace chromeos diff --git a/chromeos/dbus/fake_nfc_tag_client.h b/chromeos/dbus/fake_nfc_tag_client.h index 90321ee..244d373 100644 --- a/chromeos/dbus/fake_nfc_tag_client.h +++ b/chromeos/dbus/fake_nfc_tag_client.h @@ -5,6 +5,7 @@ #ifndef CHROMEOS_DBUS_FAKE_NFC_TAG_CLIENT_H_ #define CHROMEOS_DBUS_FAKE_NFC_TAG_CLIENT_H_ +#include "base/observer_list.h" #include "chromeos/chromeos_export.h" #include "chromeos/dbus/nfc_client_helpers.h" #include "chromeos/dbus/nfc_tag_client.h" @@ -13,11 +14,14 @@ namespace chromeos { // FakeNfcTagClient simulates the behavior of the NFC tag objects // and is used both in test cases in place of a mock and on the Linux desktop. -// TODO(armansito): For now, this doesn't do anything. Implement fake -// behavior in conjunction with unit tests while implementing the src/device -// layer. class CHROMEOS_EXPORT FakeNfcTagClient : public NfcTagClient { public: + // The fake tag object path. + static const char kTagPath[]; + + // The default simulation timeout interval. + static const int kDefaultSimulationTimeoutMilliseconds; + struct Properties : public NfcTagClient::Properties { explicit Properties(const PropertyChangedCallback& callback); virtual ~Properties(); @@ -37,6 +41,8 @@ class CHROMEOS_EXPORT FakeNfcTagClient : public NfcTagClient { virtual void Init(dbus::Bus* bus) OVERRIDE; virtual void AddObserver(Observer* observer) OVERRIDE; virtual void RemoveObserver(Observer* observer) OVERRIDE; + virtual std::vector<dbus::ObjectPath> GetTagsForAdapter( + const dbus::ObjectPath& adapter_path) OVERRIDE; virtual Properties* GetProperties( const dbus::ObjectPath& object_path) OVERRIDE; virtual void Write( @@ -45,7 +51,70 @@ class CHROMEOS_EXPORT FakeNfcTagClient : public NfcTagClient { const base::Closure& callback, const nfc_client_helpers::ErrorCallback& error_callback) OVERRIDE; + // Simulates the appearance of a tag. The fake tag will show up after + // exactly |visibility_delay| milliseconds. |visibility_delay| must have a + // non-negative value. The side-effects of this method + // occur asynchronously, i.e. even with an argument of 0, the pairing will not + // take place until after this method has returned. + void BeginPairingSimulation(int visibility_delay); + + // If tag pairing was previously started, simulates the disappearance of + // the tag. Any tag object presented and their records will disappear + // after this call. Delayed events that were set up by a previous call to + // BeginPairing() will be canceled through a call to EndPairing(). + void EndPairingSimulation(); + + // Enables or disables automatic unpairing. When enabled, a pairing + // simulation will end |simulation_timeout| milliseconds after the tag has + // been exposed. This is enabled by default and the timeout is set to + // |kDefaultSimulationTimeoutMilliseconds|. |simulation_timeout| must be + // non-negative. + void EnableSimulationTimeout(int simulation_timeout); + void DisableSimulationTimeout(); + + // Tells the FakeNfcDeviceClient to add the records in |record_paths| to its + // list of records exposed for |kDevicePath|. This method will immediately + // assign the records and trigger a property changed signal, only if the + // tag is currently visible. + void SetRecords(const std::vector<dbus::ObjectPath>& record_paths); + + // Tells the FakeNfcDeviceClient to clear the list of records exposed for + // |kDevicePath|. This method takes effect immediately and triggers a + // property changed signal. + void ClearRecords(); + + // Returns true, if a pairing simulation is currently going on. + bool tag_visible() const { return tag_visible_; } + private: + // Property changed callback passed when we create Properties* structures. + void OnPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name); + + // Makes the fake tag visible if it is not already visible. + void MakeTagVisible(); + + // Called when the simulation timeout expires. + void HandleSimulationTimeout(); + + // List of observers interested in event notifications from us. + ObserverList<Observer> observers_; + + // Fake properties that are returned for the emulated tag. + scoped_ptr<Properties> properties_; + + // If true, a pairing simulation was begun using BeginPairing() and no call + // to EndPairing() has been made. + bool pairing_started_; + + // If true, observers have been notified that a tag has been created and + // the tag properties are accesible. + bool tag_visible_; + + // If non-negative, the tag will disappear this many milliseconds after + // its records have been exposed. + int simulation_timeout_; + DISALLOW_COPY_AND_ASSIGN(FakeNfcTagClient); }; diff --git a/chromeos/dbus/nfc_record_client.cc b/chromeos/dbus/nfc_record_client.cc index 7564c76..f0bbd9b 100644 --- a/chromeos/dbus/nfc_record_client.cc +++ b/chromeos/dbus/nfc_record_client.cc @@ -80,6 +80,11 @@ class NfcRecordClientImpl : public NfcRecordClient, return object_map->GetObjectPaths(); } + virtual std::vector<dbus::ObjectPath> GetRecordsForTag( + const dbus::ObjectPath& tag_path) OVERRIDE { + return GetRecordsForDevice(tag_path); + } + // NfcRecordClient override. virtual Properties* GetProperties( const dbus::ObjectPath& object_path) OVERRIDE { diff --git a/chromeos/dbus/nfc_record_client.h b/chromeos/dbus/nfc_record_client.h index 84e2ef9..37a277e 100644 --- a/chromeos/dbus/nfc_record_client.h +++ b/chromeos/dbus/nfc_record_client.h @@ -96,8 +96,9 @@ class CHROMEOS_EXPORT NfcRecordClient : public DBusClient { // have been received. This method will be called after // Observer::RecordPropertyChanged has been called for all properties that // were received through the initial property fetch that is done when the - // object proxy is first created. Observers can use this method to be - // notified when all existing properties of a record are available for use. + // object proxy is first created or after a call to + // dbus::PropertySet::GetAll Observers can use this method to be notified + // when all existing properties of a record are available for use. virtual void RecordPropertiesReceived( const dbus::ObjectPath& object_path) {} }; @@ -115,6 +116,11 @@ class CHROMEOS_EXPORT NfcRecordClient : public DBusClient { virtual std::vector<dbus::ObjectPath> GetRecordsForDevice( const dbus::ObjectPath& device_path) = 0; + // Returns the list of record object paths associated with the given tag + // identified by the D-Bus object path |tag_path|. + virtual std::vector<dbus::ObjectPath> GetRecordsForTag( + const dbus::ObjectPath& tag_path) = 0; + // Obtain the properties for the NFC record with object path |object_path|; // any values should be copied if needed. virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; diff --git a/chromeos/dbus/nfc_tag_client.cc b/chromeos/dbus/nfc_tag_client.cc index de7e1ef..6c439fa 100644 --- a/chromeos/dbus/nfc_tag_client.cc +++ b/chromeos/dbus/nfc_tag_client.cc @@ -63,6 +63,16 @@ class NfcTagClientImpl : public NfcTagClient, } // NfcTagClient override. + virtual std::vector<dbus::ObjectPath> GetTagsForAdapter( + const dbus::ObjectPath& adapter_path) OVERRIDE { + DBusObjectMap* object_map = + adapters_to_object_maps_.GetObjectMap(adapter_path); + if (!object_map) + return std::vector<dbus::ObjectPath>(); + return object_map->GetObjectPaths(); + } + + // NfcTagClient override. virtual Properties* GetProperties( const dbus::ObjectPath& object_path) OVERRIDE { return static_cast<Properties*>( @@ -182,11 +192,16 @@ class NfcTagClientImpl : public NfcTagClient, // nfc_client_helpers::DBusObjectMap::Delegate override. virtual NfcPropertySet* CreateProperties( dbus::ObjectProxy* object_proxy) OVERRIDE { - return new Properties( + Properties* properties = new Properties( object_proxy, base::Bind(&NfcTagClientImpl::OnPropertyChanged, weak_ptr_factory_.GetWeakPtr(), object_proxy->object_path())); + properties->SetAllPropertiesReceivedCallback( + base::Bind(&NfcTagClientImpl::OnPropertiesReceived, + weak_ptr_factory_.GetWeakPtr(), + object_proxy->object_path())); + return properties; } // nfc_client_helpers::DBusObjectMap::Delegate override. @@ -210,6 +225,14 @@ class NfcTagClientImpl : public NfcTagClient, TagPropertyChanged(object_path, property_name)); } + // Called by NfcPropertySet when all properties have been processed as a + // result of a call to GetAll. + void OnPropertiesReceived(const dbus::ObjectPath& object_path) { + VLOG(1) << "All tag properties received; Path: " << object_path.value(); + FOR_EACH_OBSERVER(NfcTagClient::Observer, observers_, + TagPropertiesReceived(object_path)); + } + // We maintain a pointer to the bus to be able to request proxies for // new NFC tags that appear. dbus::Bus* bus_; diff --git a/chromeos/dbus/nfc_tag_client.h b/chromeos/dbus/nfc_tag_client.h index 2875359..444a0ae 100644 --- a/chromeos/dbus/nfc_tag_client.h +++ b/chromeos/dbus/nfc_tag_client.h @@ -66,6 +66,15 @@ class CHROMEOS_EXPORT NfcTagClient : public DBusClient { // object path |object_path| has acquired a new value. virtual void TagPropertyChanged(const dbus::ObjectPath& object_path, const std::string& property_name) {} + + // Called when all properties for the tag with object path |object_path| + // have been received. This method will be called after + // Observer::TagPropertyChanged has been called for all properties that + // were received through the initial property fetch that is done when the + // object proxy is first created or after a call to + // dbus::PropertySet::GetAll. Observers can use this method to be notified + // when all existing properties of a tag are available for use. + virtual void TagPropertiesReceived(const dbus::ObjectPath& object_path) {} }; virtual ~NfcTagClient(); @@ -76,6 +85,11 @@ class CHROMEOS_EXPORT NfcTagClient : public DBusClient { virtual void AddObserver(Observer* observer) = 0; virtual void RemoveObserver(Observer* observer) = 0; + // Returns the list of tag object paths associated with the given adapter + // identified by the D-Bus object path |adapter_path|. + virtual std::vector<dbus::ObjectPath> GetTagsForAdapter( + const dbus::ObjectPath& adapter_path) = 0; + // Obtain the properties for the NFC tag with object path |object_path|; any // values should be copied if needed. virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; |