diff options
author | armansito@chromium.org <armansito@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-08 07:18:54 +0000 |
---|---|---|
committer | armansito@chromium.org <armansito@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-08 07:18:54 +0000 |
commit | 42716047fd8604517a73070401470fada6971b23 (patch) | |
tree | f17388c8038fb91984dc2c727ae58649862f96de /device | |
parent | 6fe561067c842ec9d884f1b3356b4218af9a0dfa (diff) | |
download | chromium_src-42716047fd8604517a73070401470fada6971b23.zip chromium_src-42716047fd8604517a73070401470fada6971b23.tar.gz chromium_src-42716047fd8604517a73070401470fada6971b23.tar.bz2 |
nfc: Implement NfcAdapterChromeOS.
Added the basic implementation of NfcAdapterChromeOS, with no tag/peer logic.
BUG=316471
TEST=device_unittests
Review URL: https://codereview.chromium.org/100393011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@239388 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'device')
-rw-r--r-- | device/device_tests.gyp | 1 | ||||
-rw-r--r-- | device/nfc/nfc.gyp | 2 | ||||
-rw-r--r-- | device/nfc/nfc_adapter.cc | 2 | ||||
-rw-r--r-- | device/nfc/nfc_adapter_chromeos.cc | 304 | ||||
-rw-r--r-- | device/nfc/nfc_adapter_chromeos.h | 117 | ||||
-rw-r--r-- | device/nfc/nfc_adapter_factory.cc | 38 | ||||
-rw-r--r-- | device/nfc/nfc_chromeos_unittest.cc | 202 |
7 files changed, 660 insertions, 6 deletions
diff --git a/device/device_tests.gyp b/device/device_tests.gyp index 00bd47b..e0564b5 100644 --- a/device/device_tests.gyp +++ b/device/device_tests.gyp @@ -30,6 +30,7 @@ 'bluetooth/bluetooth_service_record_win_unittest.cc', 'bluetooth/bluetooth_task_manager_win_unittest.cc', 'bluetooth/bluetooth_utils_unittest.cc', + 'nfc/nfc_chromeos_unittest.cc', 'nfc/nfc_ndef_record_unittest.cc', 'usb/usb_ids_unittest.cc', ], diff --git a/device/nfc/nfc.gyp b/device/nfc/nfc.gyp index eafa31d..d5e519b 100644 --- a/device/nfc/nfc.gyp +++ b/device/nfc/nfc.gyp @@ -16,6 +16,8 @@ 'sources': [ 'nfc_adapter.cc', 'nfc_adapter.h', + 'nfc_adapter_chromeos.cc', + 'nfc_adapter_chromeos.h', 'nfc_adapter_factory.cc', 'nfc_adapter_factory.h', 'nfc_ndef_record.cc', diff --git a/device/nfc/nfc_adapter.cc b/device/nfc/nfc_adapter.cc index dd790b2..1bef83d3 100644 --- a/device/nfc/nfc_adapter.cc +++ b/device/nfc/nfc_adapter.cc @@ -4,8 +4,6 @@ #include "device/nfc/nfc_adapter.h" -#include "base/lazy_instance.h" -#include "base/memory/weak_ptr.h" #include "base/stl_util.h" #include "device/nfc/nfc_peer.h" #include "device/nfc/nfc_tag.h" diff --git a/device/nfc/nfc_adapter_chromeos.cc b/device/nfc/nfc_adapter_chromeos.cc new file mode 100644 index 0000000..071b080 --- /dev/null +++ b/device/nfc/nfc_adapter_chromeos.cc @@ -0,0 +1,304 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/nfc/nfc_adapter_chromeos.h" + +#include <vector> + +#include "base/callback.h" +#include "base/logging.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "device/nfc/nfc_peer.h" +#include "device/nfc/nfc_tag.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace chromeos { + +NfcAdapterChromeOS::NfcAdapterChromeOS() + : weak_ptr_factory_(this) { + DBusThreadManager::Get()->GetNfcAdapterClient()->AddObserver(this); + DBusThreadManager::Get()->GetNfcDeviceClient()->AddObserver(this); + DBusThreadManager::Get()->GetNfcTagClient()->AddObserver(this); + + const std::vector<dbus::ObjectPath>& object_paths = + DBusThreadManager::Get()->GetNfcAdapterClient()->GetAdapters(); + if (!object_paths.empty()) { + VLOG(1) << object_paths.size() << " NFC adapter(s) available."; + SetAdapter(object_paths[0]); + } +} + +NfcAdapterChromeOS::~NfcAdapterChromeOS() { + DBusThreadManager::Get()->GetNfcAdapterClient()->RemoveObserver(this); + DBusThreadManager::Get()->GetNfcDeviceClient()->RemoveObserver(this); + DBusThreadManager::Get()->GetNfcTagClient()->RemoveObserver(this); +} + +void NfcAdapterChromeOS::AddObserver(NfcAdapter::Observer* observer) { + DCHECK(observer); + observers_.AddObserver(observer); +} + +void NfcAdapterChromeOS::RemoveObserver(NfcAdapter::Observer* observer) { + DCHECK(observer); + observers_.RemoveObserver(observer); +} + +bool NfcAdapterChromeOS::IsPresent() const { + return !object_path_.value().empty(); +} + +bool NfcAdapterChromeOS::IsPowered() const { + if (!IsPresent()) + return false; + return DBusThreadManager::Get()->GetNfcAdapterClient()-> + GetProperties(object_path_)->powered.value(); +} + +bool NfcAdapterChromeOS::IsPolling() const { + if (!IsPresent()) + return false; + return DBusThreadManager::Get()->GetNfcAdapterClient()-> + GetProperties(object_path_)->polling.value(); +} + +bool NfcAdapterChromeOS::IsInitialized() const { + return true; +} + +void NfcAdapterChromeOS::SetPowered(bool powered, + const base::Closure& callback, + const ErrorCallback& error_callback) { + if (!IsPresent()) { + LOG(WARNING) << "Adapter not present. Cannot power up the antenna."; + error_callback.Run(); + return; + } + DBusThreadManager::Get()->GetNfcAdapterClient()-> + GetProperties(object_path_)->powered.Set( + powered, + base::Bind(&NfcAdapterChromeOS::OnSetPowered, + weak_ptr_factory_.GetWeakPtr(), + callback, + error_callback)); +} + +void NfcAdapterChromeOS::StartPolling(const base::Closure& callback, + const ErrorCallback& error_callback) { + // Always poll in "Initiator" mode. + DBusThreadManager::Get()->GetNfcAdapterClient()-> + StartPollLoop(object_path_, + nfc_adapter::kModeInitiator, + base::Bind(&NfcAdapterChromeOS::OnStartPolling, + weak_ptr_factory_.GetWeakPtr(), + callback), + base::Bind(&NfcAdapterChromeOS::OnStartPollingError, + weak_ptr_factory_.GetWeakPtr(), + error_callback)); +} + +void NfcAdapterChromeOS::StopPolling(const base::Closure& callback, + const ErrorCallback& error_callback) { + DBusThreadManager::Get()->GetNfcAdapterClient()-> + StopPollLoop(object_path_, + base::Bind(&NfcAdapterChromeOS::OnStopPolling, + weak_ptr_factory_.GetWeakPtr(), + callback), + base::Bind(&NfcAdapterChromeOS::OnStopPollingError, + weak_ptr_factory_.GetWeakPtr(), + error_callback)); +} + +void NfcAdapterChromeOS::AdapterAdded(const dbus::ObjectPath& object_path) { + // Set the adapter to the newly added adapter only if no adapter is present. + if (!IsPresent()) + SetAdapter(object_path); +} + +void NfcAdapterChromeOS::AdapterRemoved(const dbus::ObjectPath& object_path) { + if (object_path != object_path_) + return; + + // The current adapter was removed, so mark us as not present and clean up + // peers and tags. + RemoveAdapter(); + + // There may still be other adapters present on the system. Set the next + // available adapter as the current one. + const std::vector<dbus::ObjectPath>& object_paths = + DBusThreadManager::Get()->GetNfcAdapterClient()->GetAdapters(); + for (std::vector<dbus::ObjectPath>::const_iterator iter = + object_paths.begin(); + iter != object_paths.end(); ++iter) { + // The removed object will still be available until the call to + // AdapterRemoved returns. Make sure that we are not re-adding the + // removed adapter. + if (*iter == object_path) + continue; + SetAdapter(*iter); + } +} + +void NfcAdapterChromeOS::AdapterPropertyChanged( + const dbus::ObjectPath& object_path, + const std::string& property_name) { + if (object_path != object_path_) + return; + NfcAdapterClient::Properties* properties = + DBusThreadManager::Get()->GetNfcAdapterClient()-> + GetProperties(object_path_); + if (property_name == properties->powered.name()) + PoweredChanged(properties->powered.value()); + else if (property_name == properties->polling.name()) + PollingChanged(properties->polling.value()); +} + +void NfcAdapterChromeOS::DeviceAdded(const dbus::ObjectPath& object_path) { + VLOG(1) << "NFC device found: " << object_path.value(); + // TODO(armansito): Implement device logic. +} + +void NfcAdapterChromeOS::DeviceRemoved(const dbus::ObjectPath& object_path) { + VLOG(1) << "NFC device lost: " << object_path.value(); + // TODO(armansito): Implement device logic. +} + +void NfcAdapterChromeOS::DevicePropertyChanged( + const dbus::ObjectPath& object_path, + const std::string& property_name) { + // TODO(armansito): Implement device logic. +} + +void NfcAdapterChromeOS::TagAdded(const dbus::ObjectPath& object_path) { + VLOG(1) << "NFC tag found: " << object_path.value(); + // TODO(armansito): Implement tag logic. +} + +void NfcAdapterChromeOS::TagRemoved(const dbus::ObjectPath& object_path) { + VLOG(1) << "NFC tag found: " << object_path.value(); + // TODO(armansito): Implement tag logic. +} + +void NfcAdapterChromeOS::TagPropertyChanged( + const dbus::ObjectPath& object_path, + const std::string& property_name) { + // TODO(armansito): Implement tag logic. +} + +void NfcAdapterChromeOS::SetAdapter(const dbus::ObjectPath& object_path) { + DCHECK(!IsPresent()); + object_path_ = object_path; + VLOG(1) << "Using NFC adapter: " << object_path.value(); + + NfcAdapterClient::Properties* properties = + DBusThreadManager::Get()->GetNfcAdapterClient()-> + GetProperties(object_path_); + PresentChanged(true); + if (properties->powered.value()) + PoweredChanged(true); + if (properties->polling.value()) + PollingChanged(true); + + // TODO(armansito): Create device::NfcPeer and device::NfcTag instances for + // all peers and tags that exist, once they have been implemented for + // ChromeOS. +} + +void NfcAdapterChromeOS::RemoveAdapter() { + DCHECK(IsPresent()); + VLOG(1) << "NFC adapter removed: " << object_path_.value(); + + NfcAdapterClient::Properties* properties = + DBusThreadManager::Get()->GetNfcAdapterClient()-> + GetProperties(object_path_); + if (properties->powered.value()) + PoweredChanged(false); + if (properties->polling.value()) + PollingChanged(false); + + // Copy the tags and peers here and clear the original containers so that + // GetPeers and GetTags return no values during the *Removed observer calls. + PeersMap peers = peers_; + TagsMap tags = tags_; + peers_.clear(); + tags_.clear(); + + for (PeersMap::iterator iter = peers_.begin(); + iter != peers_.end(); ++iter) { + FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_, + PeerLost(this, iter->second)); + delete iter->second; + } + for (TagsMap::iterator iter = tags_.begin(); + iter != tags_.end(); ++iter) { + FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_, + TagLost(this, iter->second)); + delete iter->second; + } + + object_path_ = dbus::ObjectPath(""); + PresentChanged(false); +} + +void NfcAdapterChromeOS::PoweredChanged(bool powered) { + FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_, + AdapterPoweredChanged(this, powered)); +} + +void NfcAdapterChromeOS::PollingChanged(bool polling) { + FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_, + AdapterPollingChanged(this, polling)); +} + +void NfcAdapterChromeOS::PresentChanged(bool present) { + FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_, + AdapterPresentChanged(this, present)); +} + +void NfcAdapterChromeOS::OnSetPowered(const base::Closure& callback, + const ErrorCallback& error_callback, + bool success) { + VLOG(1) << "NfcAdapterChromeOS::OnSetPowered result: " << success; + if (success) { + // TODO(armansito): There is a bug in neard 0.13 that causes it not to emit + // a signal when the "Powered" property changes. Sync the properties here, + // but remove it in neard 0.14. + if (IsPresent()) { + DBusThreadManager::Get()->GetNfcAdapterClient()-> + GetProperties(object_path_)->GetAll(); + } + callback.Run(); + } else { + LOG(WARNING) << "Failed to power up the NFC antenna radio."; + error_callback.Run(); + } +} + +void NfcAdapterChromeOS::OnStartPolling(const base::Closure& callback) { + callback.Run(); +} + +void NfcAdapterChromeOS::OnStartPollingError( + const ErrorCallback& error_callback, + const std::string& error_name, + const std::string& error_message) { + LOG(WARNING) << object_path_.value() << ": Failed to start polling: " + << error_name << ": " << error_message; + error_callback.Run(); +} + +void NfcAdapterChromeOS::OnStopPolling(const base::Closure& callback) { + callback.Run(); +} + +void NfcAdapterChromeOS::OnStopPollingError( + const ErrorCallback& error_callback, + const std::string& error_name, + const std::string& error_message) { + LOG(WARNING) << object_path_.value() << ": Failed to stop polling: " + << error_name << ": " << error_message; + error_callback.Run(); +} + +} // namespace chromeos diff --git a/device/nfc/nfc_adapter_chromeos.h b/device/nfc/nfc_adapter_chromeos.h new file mode 100644 index 0000000..d70a98d --- /dev/null +++ b/device/nfc/nfc_adapter_chromeos.h @@ -0,0 +1,117 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_NFC_NFC_ADAPTER_CHROMEOS_H_ +#define DEVICE_NFC_NFC_ADAPTER_CHROMEOS_H_ + +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "chromeos/dbus/nfc_adapter_client.h" +#include "chromeos/dbus/nfc_device_client.h" +#include "chromeos/dbus/nfc_tag_client.h" +#include "dbus/object_path.h" +#include "device/nfc/nfc_adapter.h" + +namespace device { + +class NfcAdapterFactory; + +} // namespace device + +namespace chromeos { + +// The NfcAdapterChromeOS class implements NfcAdapter for the Chrome OS +// platform. +class NfcAdapterChromeOS : public device::NfcAdapter, + public chromeos::NfcAdapterClient::Observer, + public chromeos::NfcDeviceClient::Observer, + public chromeos::NfcTagClient::Observer { + public: + // NfcAdapter overrides. + virtual void AddObserver(NfcAdapter::Observer* observer) OVERRIDE; + virtual void RemoveObserver(NfcAdapter::Observer* observer) OVERRIDE; + virtual bool IsPresent() const OVERRIDE; + virtual bool IsPowered() const OVERRIDE; + virtual bool IsPolling() const OVERRIDE; + virtual bool IsInitialized() const OVERRIDE; + virtual void SetPowered(bool powered, + const base::Closure& callback, + const ErrorCallback& error_callback) OVERRIDE; + virtual void StartPolling(const base::Closure& callback, + const ErrorCallback& error_callback) OVERRIDE; + virtual void StopPolling(const base::Closure& callback, + const ErrorCallback& error_callback) OVERRIDE; + + private: + friend class device::NfcAdapterFactory; + friend class NfcChromeOSTest; + + NfcAdapterChromeOS(); + virtual ~NfcAdapterChromeOS(); + + // NfcAdapterClient::Observer overrides. + virtual void AdapterAdded(const dbus::ObjectPath& object_path) OVERRIDE; + virtual void AdapterRemoved(const dbus::ObjectPath& object_path) OVERRIDE; + virtual void AdapterPropertyChanged( + const dbus::ObjectPath& object_path, + const std::string& property_name) OVERRIDE; + + // NfcDeviceClient::Observer overrides. + virtual void DeviceAdded(const dbus::ObjectPath& object_path) OVERRIDE; + virtual void DeviceRemoved(const dbus::ObjectPath& object_path) OVERRIDE; + virtual void DevicePropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name) OVERRIDE; + + // NfcTagClient::Observer overrides. + virtual void TagAdded(const dbus::ObjectPath& object_path) OVERRIDE; + virtual void TagRemoved(const dbus::ObjectPath& object_path) OVERRIDE; + virtual void TagPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name) OVERRIDE; + + // Set the tracked adapter to the one in |object_path|, this object will + // subsequently operate on that adapter until it is removed. + void SetAdapter(const dbus::ObjectPath& object_path); + + // Remove the currently tracked adapter. IsPresent() will return false after + // this is called. + void RemoveAdapter(); + + // Announce to observers a change in the adapter state. + void PoweredChanged(bool powered); + void PollingChanged(bool polling); + void PresentChanged(bool present); + + // Called by dbus:: on completion of the powered property change. + void OnSetPowered(const base::Closure& callback, + const ErrorCallback& error_callback, + bool success); + + // Called by dbus:: on completion of the D-Bus method call to start polling. + void OnStartPolling(const base::Closure& callback); + void OnStartPollingError(const ErrorCallback& error_callback, + const std::string& error_name, + const std::string& error_message); + + // Called by dbus:: on completion of the D-Bus method call to stop polling. + void OnStopPolling(const base::Closure& callback); + void OnStopPollingError(const ErrorCallback& error_callback, + const std::string& error_name, + const std::string& error_message); + + // Object path of the adapter that we are currently tracking. + dbus::ObjectPath object_path_; + + // List of observers interested in event notifications from us. + ObserverList<device::NfcAdapter::Observer> observers_; + + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<NfcAdapterChromeOS> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(NfcAdapterChromeOS); +}; + +} // namespace chromeos + +#endif // DEVICE_NFC_NFC_ADAPTER_CHROMEOS_H_ diff --git a/device/nfc/nfc_adapter_factory.cc b/device/nfc/nfc_adapter_factory.cc index c05c933..1ba533a 100644 --- a/device/nfc/nfc_adapter_factory.cc +++ b/device/nfc/nfc_adapter_factory.cc @@ -5,20 +5,50 @@ #include "device/nfc/nfc_adapter_factory.h" #include "base/lazy_instance.h" +#include "base/logging.h" #include "base/memory/weak_ptr.h" +#if defined(OS_CHROMEOS) +#include "device/nfc/nfc_adapter_chromeos.h" +#endif + namespace device { +namespace { + +// Shared default adapter instance, we don't want to keep this class around +// if nobody is using it so use a WeakPtr and create the object when needed; +// since Google C++ Style (and clang's static analyzer) forbids us having +// exit-time destructors we use a leaky lazy instance for it. +base::LazyInstance<base::WeakPtr<device::NfcAdapter> >::Leaky + default_adapter = LAZY_INSTANCE_INITIALIZER; + +} // namespace + // static bool NfcAdapterFactory::IsNfcAvailable() { - // TODO(armansito): Return true on supported platforms here. +#if defined(OS_CHROMEOS) + return true; +#else return false; +#endif } // static -void NfcAdapterFactory::GetAdapter(const AdapterCallback& /* callback */) { - // TODO(armansito): Create platform-specific implementation instances here. - // No platform currently supports NFC, so we never invoke the callback. +void NfcAdapterFactory::GetAdapter(const AdapterCallback& callback) { + if (!IsNfcAvailable()) { + LOG(WARNING) << "NFC is not available on the current platform."; + return; + } + if (!default_adapter.Get().get()) { +#if defined(OS_CHROMEOS) + chromeos::NfcAdapterChromeOS* new_adapter = + new chromeos::NfcAdapterChromeOS(); + default_adapter.Get() = new_adapter->weak_ptr_factory_.GetWeakPtr(); +#endif + } + if (default_adapter.Get()->IsInitialized()) + callback.Run(scoped_refptr<NfcAdapter>(default_adapter.Get().get())); } } // namespace device diff --git a/device/nfc/nfc_chromeos_unittest.cc b/device/nfc/nfc_chromeos_unittest.cc new file mode 100644 index 0000000..dd94beb --- /dev/null +++ b/device/nfc/nfc_chromeos_unittest.cc @@ -0,0 +1,202 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/message_loop/message_loop.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/fake_nfc_adapter_client.h" +#include "device/nfc/nfc_adapter_chromeos.h" +#include "testing/gtest/include/gtest/gtest.h" + +using device::NfcAdapter; + +namespace chromeos { + +namespace { + +class TestObserver : public NfcAdapter::Observer { + public: + TestObserver(scoped_refptr<NfcAdapter> adapter) + : present_changed_count_(0), + powered_changed_count_(0), + adapter_(adapter) { + } + + virtual ~TestObserver() {} + + // NfcAdapter::Observer override. + virtual void AdapterPresentChanged(NfcAdapter* adapter, + bool present) OVERRIDE { + EXPECT_EQ(adapter_, adapter); + present_changed_count_++; + } + + // NfcAdapter::Observer override. + virtual void AdapterPoweredChanged(NfcAdapter* adapter, + bool powered) OVERRIDE { + EXPECT_EQ(adapter_, adapter); + powered_changed_count_++; + } + + int present_changed_count_; + int powered_changed_count_; + scoped_refptr<NfcAdapter> adapter_; +}; + +} // namespace + +class NfcChromeOSTest : public testing::Test { + public: + virtual void SetUp() { + DBusThreadManager::InitializeWithStub(); + fake_nfc_adapter_client_ = static_cast<FakeNfcAdapterClient*>( + DBusThreadManager::Get()->GetNfcAdapterClient()); + SetAdapter(); + message_loop_.RunUntilIdle(); + + success_callback_count_ = 0; + error_callback_count_ = 0; + } + + virtual void TearDown() { + adapter_ = NULL; + DBusThreadManager::Shutdown(); + } + + // Assigns a new instance of NfcAdapterChromeOS to |adapter_|. + void SetAdapter() { + adapter_ = new NfcAdapterChromeOS(); + ASSERT_TRUE(adapter_.get() != NULL); + ASSERT_TRUE(adapter_->IsInitialized()); + } + + // Generic callbacks for success and error. + void SuccessCallback() { + success_callback_count_++; + } + + void ErrorCallback() { + error_callback_count_++; + } + + protected: + // Fields for storing the number of times SuccessCallback and ErrorCallback + // have been called. + int success_callback_count_; + int error_callback_count_; + + // A message loop to emulate asynchronous behavior. + base::MessageLoop message_loop_; + + // The NfcAdapter instance under test. + scoped_refptr<NfcAdapter> adapter_; + + // The fake D-Bus client instances used for testing. + FakeNfcAdapterClient* fake_nfc_adapter_client_; +}; + +TEST_F(NfcChromeOSTest, PresentChanged) { + EXPECT_TRUE(adapter_->IsPresent()); + + TestObserver observer(adapter_); + adapter_->AddObserver(&observer); + + // Remove all adapters. + fake_nfc_adapter_client_->SetAdapterPresent(false); + EXPECT_EQ(1, observer.present_changed_count_); + EXPECT_FALSE(adapter_->IsPresent()); + + // Add two adapters. + fake_nfc_adapter_client_->SetAdapterPresent(true); + fake_nfc_adapter_client_->SetSecondAdapterPresent(true); + EXPECT_EQ(2, observer.present_changed_count_); + EXPECT_TRUE(adapter_->IsPresent()); + + // Remove the first adapter. Adapter should update to the second one. + fake_nfc_adapter_client_->SetAdapterPresent(false); + EXPECT_EQ(4, observer.present_changed_count_); + EXPECT_TRUE(adapter_->IsPresent()); + + fake_nfc_adapter_client_->SetSecondAdapterPresent(false); + EXPECT_EQ(5, observer.present_changed_count_); + EXPECT_FALSE(adapter_->IsPresent()); +} + +TEST_F(NfcChromeOSTest, SetPowered) { + TestObserver observer(adapter_); + adapter_->AddObserver(&observer); + + EXPECT_FALSE(adapter_->IsPowered()); + + // SetPowered(false), while not powered. + adapter_->SetPowered( + false, + base::Bind(&NfcChromeOSTest::SuccessCallback, + base::Unretained(this)), + base::Bind(&NfcChromeOSTest::ErrorCallback, + base::Unretained(this))); + EXPECT_FALSE(adapter_->IsPowered()); + EXPECT_EQ(0, observer.powered_changed_count_); + EXPECT_EQ(0, success_callback_count_); + EXPECT_EQ(1, error_callback_count_); + + // SetPowered(true). + adapter_->SetPowered( + true, + base::Bind(&NfcChromeOSTest::SuccessCallback, + base::Unretained(this)), + base::Bind(&NfcChromeOSTest::ErrorCallback, + base::Unretained(this))); + EXPECT_TRUE(adapter_->IsPowered()); + EXPECT_EQ(1, observer.powered_changed_count_); + EXPECT_EQ(1, success_callback_count_); + EXPECT_EQ(1, error_callback_count_); + + // SetPowered(true), while powered. + adapter_->SetPowered( + true, + base::Bind(&NfcChromeOSTest::SuccessCallback, + base::Unretained(this)), + base::Bind(&NfcChromeOSTest::ErrorCallback, + base::Unretained(this))); + EXPECT_TRUE(adapter_->IsPowered()); + EXPECT_EQ(1, observer.powered_changed_count_); + EXPECT_EQ(1, success_callback_count_); + EXPECT_EQ(2, error_callback_count_); + + // SetPowered(false). + adapter_->SetPowered( + false, + base::Bind(&NfcChromeOSTest::SuccessCallback, + base::Unretained(this)), + base::Bind(&NfcChromeOSTest::ErrorCallback, + base::Unretained(this))); + EXPECT_FALSE(adapter_->IsPowered()); + EXPECT_EQ(2, observer.powered_changed_count_); + EXPECT_EQ(2, success_callback_count_); + EXPECT_EQ(2, error_callback_count_); +} + +TEST_F(NfcChromeOSTest, PresentChangedWhilePowered) { + TestObserver observer(adapter_); + adapter_->AddObserver(&observer); + + EXPECT_FALSE(adapter_->IsPowered()); + EXPECT_TRUE(adapter_->IsPresent()); + + adapter_->SetPowered( + true, + base::Bind(&NfcChromeOSTest::SuccessCallback, + base::Unretained(this)), + base::Bind(&NfcChromeOSTest::ErrorCallback, + base::Unretained(this))); + EXPECT_TRUE(adapter_->IsPowered()); + + fake_nfc_adapter_client_->SetAdapterPresent(false); + EXPECT_EQ(1, observer.present_changed_count_); + EXPECT_EQ(2, observer.powered_changed_count_); + EXPECT_FALSE(adapter_->IsPowered()); + EXPECT_FALSE(adapter_->IsPresent()); +} + +} // namespace chromeos |