1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/callback.h" 6#include "base/memory/scoped_ptr.h" 7#include "base/message_loop/message_loop.h" 8#include "base/run_loop.h" 9#include "base/values.h" 10#include "chromeos/dbus/dbus_thread_manager.h" 11#include "chromeos/dbus/fake_nfc_adapter_client.h" 12#include "chromeos/dbus/fake_nfc_device_client.h" 13#include "chromeos/dbus/fake_nfc_record_client.h" 14#include "chromeos/dbus/fake_nfc_tag_client.h" 15#include "device/nfc/nfc_adapter_chromeos.h" 16#include "device/nfc/nfc_ndef_record.h" 17#include "device/nfc/nfc_ndef_record_utils_chromeos.h" 18#include "device/nfc/nfc_peer.h" 19#include "device/nfc/nfc_tag.h" 20#include "device/nfc/nfc_tag_technology.h" 21#include "testing/gtest/include/gtest/gtest.h" 22#include "third_party/cros_system_api/dbus/service_constants.h" 23 24using device::NfcAdapter; 25using device::NfcNdefMessage; 26using device::NfcNdefRecord; 27using device::NfcNdefTagTechnology; 28using device::NfcPeer; 29using device::NfcTag; 30 31namespace chromeos { 32 33namespace { 34 35// Callback passed to property structures. 36void OnPropertyChangedCallback(const std::string& property_name) { 37} 38 39// Callback passed to dbus::PropertyBase::Set. 40void OnSet(bool success) { 41} 42 43class TestObserver : public NfcAdapter::Observer, 44 public NfcPeer::Observer, 45 public NfcTag::Observer, 46 public NfcNdefTagTechnology::Observer { 47 public: 48 TestObserver(scoped_refptr<NfcAdapter> adapter) 49 : present_changed_count_(0), 50 powered_changed_count_(0), 51 polling_changed_count_(0), 52 peer_records_received_count_(0), 53 tag_records_received_count_(0), 54 peer_count_(0), 55 tag_count_(0), 56 adapter_(adapter) { 57 } 58 59 virtual ~TestObserver() {} 60 61 // NfcAdapter::Observer override. 62 virtual void AdapterPresentChanged(NfcAdapter* adapter, 63 bool present) OVERRIDE { 64 EXPECT_EQ(adapter_.get(), adapter); 65 present_changed_count_++; 66 } 67 68 // NfcAdapter::Observer override. 69 virtual void AdapterPoweredChanged(NfcAdapter* adapter, 70 bool powered) OVERRIDE { 71 EXPECT_EQ(adapter_.get(), adapter); 72 powered_changed_count_++; 73 } 74 75 // NfcAdapter::Observer override. 76 virtual void AdapterPollingChanged(NfcAdapter* adapter, 77 bool powered) OVERRIDE { 78 EXPECT_EQ(adapter_.get(), adapter); 79 polling_changed_count_++; 80 } 81 82 // NfcAdapter::Observer override. 83 virtual void PeerFound(NfcAdapter* adapter, NfcPeer* peer) OVERRIDE { 84 EXPECT_EQ(adapter_.get(), adapter); 85 peer_count_++; 86 peer_identifier_ = peer->GetIdentifier(); 87 } 88 89 // NfcAdapter::Observer override. 90 virtual void PeerLost(NfcAdapter* adapter, NfcPeer* peer) OVERRIDE { 91 EXPECT_EQ(adapter_.get(), adapter); 92 EXPECT_EQ(peer_identifier_, peer->GetIdentifier()); 93 peer_count_--; 94 peer_identifier_.clear(); 95 } 96 97 // NfcAdapter::Observer override. 98 virtual void TagFound(NfcAdapter* adapter, NfcTag* tag) OVERRIDE { 99 EXPECT_EQ(adapter_.get(), adapter); 100 tag_count_++; 101 tag_identifier_ = tag->GetIdentifier(); 102 } 103 104 // NfcAdapter::Observer override. 105 virtual void TagLost(NfcAdapter* adapter, NfcTag* tag) OVERRIDE { 106 EXPECT_EQ(adapter_.get(), adapter); 107 EXPECT_EQ(tag_identifier_, tag->GetIdentifier()); 108 tag_count_--; 109 tag_identifier_.clear(); 110 } 111 112 // NfcPeer::Observer override. 113 virtual void RecordReceived( 114 NfcPeer* peer, const NfcNdefRecord* record) OVERRIDE { 115 EXPECT_EQ(peer, adapter_->GetPeer(peer_identifier_)); 116 EXPECT_EQ(peer_identifier_, peer->GetIdentifier()); 117 peer_records_received_count_++; 118 } 119 120 // NfcNdefTagTechnology::Observer override. 121 virtual void RecordReceived( 122 NfcTag* tag, const NfcNdefRecord* record) OVERRIDE { 123 EXPECT_EQ(tag, adapter_->GetTag(tag_identifier_)); 124 EXPECT_EQ(tag_identifier_, tag->GetIdentifier()); 125 tag_records_received_count_++; 126 } 127 128 int present_changed_count_; 129 int powered_changed_count_; 130 int polling_changed_count_; 131 int peer_records_received_count_; 132 int tag_records_received_count_; 133 int peer_count_; 134 int tag_count_; 135 std::string peer_identifier_; 136 std::string tag_identifier_; 137 scoped_refptr<NfcAdapter> adapter_; 138}; 139 140} // namespace 141 142class NfcChromeOSTest : public testing::Test { 143 public: 144 virtual void SetUp() { 145 DBusThreadManager::Initialize(); 146 fake_nfc_adapter_client_ = static_cast<FakeNfcAdapterClient*>( 147 DBusThreadManager::Get()->GetNfcAdapterClient()); 148 fake_nfc_device_client_ = static_cast<FakeNfcDeviceClient*>( 149 DBusThreadManager::Get()->GetNfcDeviceClient()); 150 fake_nfc_record_client_ = static_cast<FakeNfcRecordClient*>( 151 DBusThreadManager::Get()->GetNfcRecordClient()); 152 fake_nfc_tag_client_ = static_cast<FakeNfcTagClient*>( 153 DBusThreadManager::Get()->GetNfcTagClient()); 154 155 fake_nfc_adapter_client_->EnablePairingOnPoll(false); 156 fake_nfc_device_client_->DisableSimulationTimeout(); 157 fake_nfc_tag_client_->DisableSimulationTimeout(); 158 success_callback_count_ = 0; 159 error_callback_count_ = 0; 160 } 161 162 virtual void TearDown() { 163 adapter_ = NULL; 164 DBusThreadManager::Shutdown(); 165 } 166 167 // Assigns a new instance of NfcAdapterChromeOS to |adapter_|. 168 void SetAdapter() { 169 adapter_ = new NfcAdapterChromeOS(); 170 ASSERT_TRUE(adapter_.get() != NULL); 171 ASSERT_TRUE(adapter_->IsInitialized()); 172 base::RunLoop().RunUntilIdle(); 173 } 174 175 // Generic callbacks for success and error. 176 void SuccessCallback() { 177 success_callback_count_++; 178 } 179 180 void ErrorCallback() { 181 error_callback_count_++; 182 } 183 184 void ErrorCallbackWithParameters(const std::string& error_name, 185 const std::string& error_message) { 186 LOG(INFO) << "Error callback called: " << error_name << ", " 187 << error_message; 188 error_callback_count_++; 189 } 190 191 protected: 192 // MessageLoop instance, used to simulate asynchronous behavior. 193 base::MessageLoop message_loop_; 194 195 // Fields for storing the number of times SuccessCallback and ErrorCallback 196 // have been called. 197 int success_callback_count_; 198 int error_callback_count_; 199 200 // The NfcAdapter instance under test. 201 scoped_refptr<NfcAdapter> adapter_; 202 203 // The fake D-Bus client instances used for testing. 204 FakeNfcAdapterClient* fake_nfc_adapter_client_; 205 FakeNfcDeviceClient* fake_nfc_device_client_; 206 FakeNfcRecordClient* fake_nfc_record_client_; 207 FakeNfcTagClient* fake_nfc_tag_client_; 208}; 209 210// Tests that the adapter updates correctly to reflect the current "default" 211// adapter, when multiple adapters appear and disappear. 212TEST_F(NfcChromeOSTest, PresentChanged) { 213 SetAdapter(); 214 EXPECT_TRUE(adapter_->IsPresent()); 215 216 TestObserver observer(adapter_); 217 adapter_->AddObserver(&observer); 218 219 // Remove all adapters. 220 fake_nfc_adapter_client_->SetAdapterPresent(false); 221 EXPECT_EQ(1, observer.present_changed_count_); 222 EXPECT_FALSE(adapter_->IsPresent()); 223 224 // Add two adapters. 225 fake_nfc_adapter_client_->SetAdapterPresent(true); 226 fake_nfc_adapter_client_->SetSecondAdapterPresent(true); 227 EXPECT_EQ(2, observer.present_changed_count_); 228 EXPECT_TRUE(adapter_->IsPresent()); 229 230 // Remove the first adapter. Adapter should update to the second one. 231 fake_nfc_adapter_client_->SetAdapterPresent(false); 232 EXPECT_EQ(4, observer.present_changed_count_); 233 EXPECT_TRUE(adapter_->IsPresent()); 234 235 fake_nfc_adapter_client_->SetSecondAdapterPresent(false); 236 EXPECT_EQ(5, observer.present_changed_count_); 237 EXPECT_FALSE(adapter_->IsPresent()); 238} 239 240// Tests that the adapter correctly reflects the power state. 241TEST_F(NfcChromeOSTest, SetPowered) { 242 SetAdapter(); 243 TestObserver observer(adapter_); 244 adapter_->AddObserver(&observer); 245 246 EXPECT_FALSE(adapter_->IsPowered()); 247 248 // SetPowered(false), while not powered. 249 adapter_->SetPowered( 250 false, 251 base::Bind(&NfcChromeOSTest::SuccessCallback, 252 base::Unretained(this)), 253 base::Bind(&NfcChromeOSTest::ErrorCallback, 254 base::Unretained(this))); 255 EXPECT_FALSE(adapter_->IsPowered()); 256 EXPECT_EQ(0, observer.powered_changed_count_); 257 EXPECT_EQ(0, success_callback_count_); 258 EXPECT_EQ(1, error_callback_count_); 259 260 // SetPowered(true). 261 adapter_->SetPowered( 262 true, 263 base::Bind(&NfcChromeOSTest::SuccessCallback, 264 base::Unretained(this)), 265 base::Bind(&NfcChromeOSTest::ErrorCallback, 266 base::Unretained(this))); 267 EXPECT_TRUE(adapter_->IsPowered()); 268 EXPECT_EQ(1, observer.powered_changed_count_); 269 EXPECT_EQ(1, success_callback_count_); 270 EXPECT_EQ(1, error_callback_count_); 271 272 // SetPowered(true), while powered. 273 adapter_->SetPowered( 274 true, 275 base::Bind(&NfcChromeOSTest::SuccessCallback, 276 base::Unretained(this)), 277 base::Bind(&NfcChromeOSTest::ErrorCallback, 278 base::Unretained(this))); 279 EXPECT_TRUE(adapter_->IsPowered()); 280 EXPECT_EQ(1, observer.powered_changed_count_); 281 EXPECT_EQ(1, success_callback_count_); 282 EXPECT_EQ(2, error_callback_count_); 283 284 // SetPowered(false). 285 adapter_->SetPowered( 286 false, 287 base::Bind(&NfcChromeOSTest::SuccessCallback, 288 base::Unretained(this)), 289 base::Bind(&NfcChromeOSTest::ErrorCallback, 290 base::Unretained(this))); 291 EXPECT_FALSE(adapter_->IsPowered()); 292 EXPECT_EQ(2, observer.powered_changed_count_); 293 EXPECT_EQ(2, success_callback_count_); 294 EXPECT_EQ(2, error_callback_count_); 295} 296 297// Tests that the power state updates correctly when the adapter disappears. 298TEST_F(NfcChromeOSTest, PresentChangedWhilePowered) { 299 SetAdapter(); 300 TestObserver observer(adapter_); 301 adapter_->AddObserver(&observer); 302 303 EXPECT_FALSE(adapter_->IsPowered()); 304 EXPECT_TRUE(adapter_->IsPresent()); 305 306 adapter_->SetPowered( 307 true, 308 base::Bind(&NfcChromeOSTest::SuccessCallback, 309 base::Unretained(this)), 310 base::Bind(&NfcChromeOSTest::ErrorCallback, 311 base::Unretained(this))); 312 EXPECT_TRUE(adapter_->IsPowered()); 313 314 fake_nfc_adapter_client_->SetAdapterPresent(false); 315 EXPECT_EQ(1, observer.present_changed_count_); 316 EXPECT_EQ(2, observer.powered_changed_count_); 317 EXPECT_FALSE(adapter_->IsPowered()); 318 EXPECT_FALSE(adapter_->IsPresent()); 319} 320 321// Tests that peer and record objects are created for all peers and records 322// that already exist when the adapter is created. 323TEST_F(NfcChromeOSTest, PeersInitializedWhenAdapterCreated) { 324 // Set up the adapter client. 325 NfcAdapterClient::Properties* properties = 326 fake_nfc_adapter_client_->GetProperties( 327 dbus::ObjectPath(FakeNfcAdapterClient::kAdapterPath0)); 328 properties->powered.Set(true, base::Bind(&OnSet)); 329 330 fake_nfc_adapter_client_->StartPollLoop( 331 dbus::ObjectPath(FakeNfcAdapterClient::kAdapterPath0), 332 nfc_adapter::kModeInitiator, 333 base::Bind(&NfcChromeOSTest::SuccessCallback, 334 base::Unretained(this)), 335 base::Bind(&NfcChromeOSTest::ErrorCallbackWithParameters, 336 base::Unretained(this))); 337 EXPECT_EQ(1, success_callback_count_); 338 EXPECT_TRUE(properties->powered.value()); 339 EXPECT_TRUE(properties->polling.value()); 340 341 // Start pairing simulation, which will add a fake device and fake records. 342 fake_nfc_device_client_->BeginPairingSimulation(0, 0); 343 base::RunLoop().RunUntilIdle(); 344 345 // Create the adapter. 346 SetAdapter(); 347 TestObserver observer(adapter_); 348 adapter_->AddObserver(&observer); 349 350 // Observer shouldn't have received any calls, as it got created AFTER the 351 // notifications were sent. 352 EXPECT_EQ(0, observer.present_changed_count_); 353 EXPECT_EQ(0, observer.powered_changed_count_); 354 EXPECT_EQ(0, observer.polling_changed_count_); 355 EXPECT_EQ(0, observer.peer_count_); 356 357 EXPECT_TRUE(adapter_->IsPresent()); 358 EXPECT_TRUE(adapter_->IsPowered()); 359 EXPECT_FALSE(adapter_->IsPolling()); 360 361 NfcAdapter::PeerList peers; 362 adapter_->GetPeers(&peers); 363 EXPECT_EQ(static_cast<size_t>(1), peers.size()); 364 365 NfcPeer* peer = peers[0]; 366 const NfcNdefMessage& message = peer->GetNdefMessage(); 367 EXPECT_EQ(static_cast<size_t>(3), message.records().size()); 368} 369 370// Tests that tag and record objects are created for all tags and records that 371// already exist when the adapter is created. 372TEST_F(NfcChromeOSTest, TagsInitializedWhenAdapterCreated) { 373 const char kTestURI[] = "fake://path/for/testing"; 374 375 // Set up the adapter client. 376 NfcAdapterClient::Properties* properties = 377 fake_nfc_adapter_client_->GetProperties( 378 dbus::ObjectPath(FakeNfcAdapterClient::kAdapterPath0)); 379 properties->powered.Set(true, base::Bind(&OnSet)); 380 381 fake_nfc_adapter_client_->StartPollLoop( 382 dbus::ObjectPath(FakeNfcAdapterClient::kAdapterPath0), 383 nfc_adapter::kModeInitiator, 384 base::Bind(&NfcChromeOSTest::SuccessCallback, 385 base::Unretained(this)), 386 base::Bind(&NfcChromeOSTest::ErrorCallbackWithParameters, 387 base::Unretained(this))); 388 EXPECT_EQ(1, success_callback_count_); 389 EXPECT_TRUE(properties->powered.value()); 390 EXPECT_TRUE(properties->polling.value()); 391 392 // Add the fake tag. 393 fake_nfc_tag_client_->BeginPairingSimulation(0); 394 base::RunLoop().RunUntilIdle(); 395 396 // Create a fake record. 397 base::DictionaryValue test_record_data; 398 test_record_data.SetString(nfc_record::kTypeProperty, nfc_record::kTypeUri); 399 test_record_data.SetString(nfc_record::kUriProperty, kTestURI); 400 fake_nfc_tag_client_->Write( 401 dbus::ObjectPath(FakeNfcTagClient::kTagPath), 402 test_record_data, 403 base::Bind(&NfcChromeOSTest::SuccessCallback, 404 base::Unretained(this)), 405 base::Bind(&NfcChromeOSTest::ErrorCallbackWithParameters, 406 base::Unretained(this))); 407 EXPECT_EQ(2, success_callback_count_); 408 409 // Create the adapter. 410 SetAdapter(); 411 TestObserver observer(adapter_); 412 adapter_->AddObserver(&observer); 413 414 // Observer shouldn't have received any calls, as it got created AFTER the 415 // notifications were sent. 416 EXPECT_EQ(0, observer.present_changed_count_); 417 EXPECT_EQ(0, observer.powered_changed_count_); 418 EXPECT_EQ(0, observer.polling_changed_count_); 419 EXPECT_EQ(0, observer.peer_count_); 420 421 EXPECT_TRUE(adapter_->IsPresent()); 422 EXPECT_TRUE(adapter_->IsPowered()); 423 EXPECT_FALSE(adapter_->IsPolling()); 424 425 NfcAdapter::TagList tags; 426 adapter_->GetTags(&tags); 427 EXPECT_EQ(static_cast<size_t>(1), tags.size()); 428 429 NfcTag* tag = tags[0]; 430 const NfcNdefMessage& message = tag->GetNdefTagTechnology()->GetNdefMessage(); 431 EXPECT_EQ(static_cast<size_t>(1), message.records().size()); 432 433 const NfcNdefRecord* record = message.records()[0]; 434 std::string uri; 435 EXPECT_TRUE(record->data().GetString(NfcNdefRecord::kFieldURI, &uri)); 436 EXPECT_EQ(kTestURI, uri); 437} 438 439// Tests that the adapter correctly updates its state when polling is started 440// and stopped. 441TEST_F(NfcChromeOSTest, StartAndStopPolling) { 442 SetAdapter(); 443 EXPECT_TRUE(adapter_->IsPresent()); 444 445 TestObserver observer(adapter_); 446 adapter_->AddObserver(&observer); 447 448 // Start polling while not powered. Should fail. 449 EXPECT_FALSE(adapter_->IsPowered()); 450 adapter_->StartPolling( 451 base::Bind(&NfcChromeOSTest::SuccessCallback, 452 base::Unretained(this)), 453 base::Bind(&NfcChromeOSTest::ErrorCallback, 454 base::Unretained(this))); 455 EXPECT_EQ(0, success_callback_count_); 456 EXPECT_EQ(1, error_callback_count_); 457 EXPECT_FALSE(adapter_->IsPolling()); 458 459 // Start polling while powered. Should succeed. 460 adapter_->SetPowered( 461 true, 462 base::Bind(&NfcChromeOSTest::SuccessCallback, 463 base::Unretained(this)), 464 base::Bind(&NfcChromeOSTest::ErrorCallback, 465 base::Unretained(this))); 466 EXPECT_EQ(1, success_callback_count_); 467 EXPECT_EQ(1, error_callback_count_); 468 EXPECT_TRUE(adapter_->IsPowered()); 469 470 adapter_->StartPolling( 471 base::Bind(&NfcChromeOSTest::SuccessCallback, 472 base::Unretained(this)), 473 base::Bind(&NfcChromeOSTest::ErrorCallback, 474 base::Unretained(this))); 475 EXPECT_EQ(2, success_callback_count_); 476 EXPECT_EQ(1, error_callback_count_); 477 EXPECT_TRUE(adapter_->IsPolling()); 478 479 // Start polling while already polling. Should fail. 480 adapter_->StartPolling( 481 base::Bind(&NfcChromeOSTest::SuccessCallback, 482 base::Unretained(this)), 483 base::Bind(&NfcChromeOSTest::ErrorCallback, 484 base::Unretained(this))); 485 EXPECT_EQ(2, success_callback_count_); 486 EXPECT_EQ(2, error_callback_count_); 487 EXPECT_TRUE(adapter_->IsPolling()); 488 489 // Stop polling. Should succeed. 490 adapter_->StopPolling( 491 base::Bind(&NfcChromeOSTest::SuccessCallback, 492 base::Unretained(this)), 493 base::Bind(&NfcChromeOSTest::ErrorCallback, 494 base::Unretained(this))); 495 EXPECT_EQ(3, success_callback_count_); 496 EXPECT_EQ(2, error_callback_count_); 497 EXPECT_FALSE(adapter_->IsPolling()); 498 499 // Stop polling while not polling. Should fail. 500 adapter_->StopPolling( 501 base::Bind(&NfcChromeOSTest::SuccessCallback, 502 base::Unretained(this)), 503 base::Bind(&NfcChromeOSTest::ErrorCallback, 504 base::Unretained(this))); 505 EXPECT_EQ(3, success_callback_count_); 506 EXPECT_EQ(3, error_callback_count_); 507 EXPECT_FALSE(adapter_->IsPolling()); 508} 509 510// Tests a simple peer pairing simulation. 511TEST_F(NfcChromeOSTest, PeerTest) { 512 SetAdapter(); 513 TestObserver observer(adapter_); 514 adapter_->AddObserver(&observer); 515 516 adapter_->SetPowered( 517 true, 518 base::Bind(&NfcChromeOSTest::SuccessCallback, 519 base::Unretained(this)), 520 base::Bind(&NfcChromeOSTest::ErrorCallback, 521 base::Unretained(this))); 522 adapter_->StartPolling( 523 base::Bind(&NfcChromeOSTest::SuccessCallback, 524 base::Unretained(this)), 525 base::Bind(&NfcChromeOSTest::ErrorCallback, 526 base::Unretained(this))); 527 EXPECT_EQ(2, success_callback_count_); 528 529 EXPECT_TRUE(adapter_->IsPowered()); 530 EXPECT_TRUE(adapter_->IsPolling()); 531 EXPECT_EQ(0, observer.peer_count_); 532 533 // Add the fake device. 534 fake_nfc_device_client_->BeginPairingSimulation(0, -1); 535 base::RunLoop().RunUntilIdle(); 536 537 EXPECT_EQ(1, observer.peer_count_); 538 EXPECT_EQ(FakeNfcDeviceClient::kDevicePath, observer.peer_identifier_); 539 540 NfcPeer* peer = adapter_->GetPeer(observer.peer_identifier_); 541 CHECK(peer); 542 peer->AddObserver(&observer); 543 544 // Peer should have no records on it. 545 EXPECT_TRUE(peer->GetNdefMessage().records().empty()); 546 EXPECT_EQ(0, observer.peer_records_received_count_); 547 548 // Make records visible. 549 fake_nfc_record_client_->SetDeviceRecordsVisible(true); 550 EXPECT_EQ(3, observer.peer_records_received_count_); 551 EXPECT_EQ(static_cast<size_t>(3), peer->GetNdefMessage().records().size()); 552 553 // End the simulation. Peer should get removed. 554 fake_nfc_device_client_->EndPairingSimulation(); 555 EXPECT_EQ(0, observer.peer_count_); 556 EXPECT_TRUE(observer.peer_identifier_.empty()); 557 558 peer = adapter_->GetPeer(observer.peer_identifier_); 559 EXPECT_FALSE(peer); 560 561 // No record related notifications will be sent when a peer gets removed. 562 EXPECT_EQ(3, observer.peer_records_received_count_); 563} 564 565// Tests a simple tag pairing simulation. 566TEST_F(NfcChromeOSTest, TagTest) { 567 const char kTestURI[] = "fake://path/for/testing"; 568 569 SetAdapter(); 570 TestObserver observer(adapter_); 571 adapter_->AddObserver(&observer); 572 573 adapter_->SetPowered( 574 true, 575 base::Bind(&NfcChromeOSTest::SuccessCallback, 576 base::Unretained(this)), 577 base::Bind(&NfcChromeOSTest::ErrorCallback, 578 base::Unretained(this))); 579 adapter_->StartPolling( 580 base::Bind(&NfcChromeOSTest::SuccessCallback, 581 base::Unretained(this)), 582 base::Bind(&NfcChromeOSTest::ErrorCallback, 583 base::Unretained(this))); 584 EXPECT_EQ(2, success_callback_count_); 585 586 EXPECT_TRUE(adapter_->IsPowered()); 587 EXPECT_TRUE(adapter_->IsPolling()); 588 EXPECT_EQ(0, observer.tag_count_); 589 590 // Add the fake tag. 591 fake_nfc_tag_client_->BeginPairingSimulation(0); 592 base::RunLoop().RunUntilIdle(); 593 594 EXPECT_EQ(1, observer.tag_count_); 595 EXPECT_EQ(FakeNfcTagClient::kTagPath, observer.tag_identifier_); 596 597 NfcTag* tag = adapter_->GetTag(observer.tag_identifier_); 598 CHECK(tag); 599 tag->AddObserver(&observer); 600 EXPECT_TRUE(tag->IsReady()); 601 CHECK(tag->GetNdefTagTechnology()); 602 tag->GetNdefTagTechnology()->AddObserver(&observer); 603 604 NfcNdefTagTechnology* tag_technology = tag->GetNdefTagTechnology(); 605 EXPECT_TRUE(tag_technology->IsSupportedByTag()); 606 607 // Tag should have no records on it. 608 EXPECT_TRUE(tag_technology->GetNdefMessage().records().empty()); 609 EXPECT_EQ(0, observer.tag_records_received_count_); 610 611 // Set the tag record visible. By default the record has no content, so no 612 // NfcNdefMessage should be received. 613 fake_nfc_record_client_->SetTagRecordsVisible(true); 614 EXPECT_TRUE(tag_technology->GetNdefMessage().records().empty()); 615 EXPECT_EQ(0, observer.tag_records_received_count_); 616 fake_nfc_record_client_->SetTagRecordsVisible(false); 617 618 // Write an NDEF record to the tag. 619 EXPECT_EQ(2, success_callback_count_); // 2 for SetPowered and StartPolling. 620 EXPECT_EQ(0, error_callback_count_); 621 622 base::DictionaryValue record_data; 623 record_data.SetString(NfcNdefRecord::kFieldURI, kTestURI); 624 NfcNdefRecord written_record; 625 written_record.Populate(NfcNdefRecord::kTypeURI, &record_data); 626 NfcNdefMessage written_message; 627 written_message.AddRecord(&written_record); 628 629 tag_technology->WriteNdef( 630 written_message, 631 base::Bind(&NfcChromeOSTest::SuccessCallback, 632 base::Unretained(this)), 633 base::Bind(&NfcChromeOSTest::ErrorCallback, 634 base::Unretained(this))); 635 EXPECT_EQ(3, success_callback_count_); 636 EXPECT_EQ(0, error_callback_count_); 637 638 EXPECT_EQ(static_cast<size_t>(1), 639 tag_technology->GetNdefMessage().records().size()); 640 EXPECT_EQ(1, observer.tag_records_received_count_); 641 642 NfcNdefRecord* received_record = 643 tag_technology->GetNdefMessage().records()[0]; 644 EXPECT_EQ(NfcNdefRecord::kTypeURI, received_record->type()); 645 std::string uri; 646 EXPECT_TRUE(received_record->data().GetString( 647 NfcNdefRecord::kFieldURI, &uri)); 648 EXPECT_EQ(kTestURI, uri); 649 650 // End the simulation. Tag should get removed. 651 fake_nfc_tag_client_->EndPairingSimulation(); 652 EXPECT_EQ(0, observer.tag_count_); 653 EXPECT_TRUE(observer.tag_identifier_.empty()); 654 655 tag = adapter_->GetTag(observer.tag_identifier_); 656 EXPECT_FALSE(tag); 657 658 // No record related notifications will be sent when a tag gets removed. 659 EXPECT_EQ(1, observer.tag_records_received_count_); 660} 661 662// Unit tests for nfc_ndef_record_utils methods. 663TEST_F(NfcChromeOSTest, NfcNdefRecordToDBusAttributes) { 664 const char kText[] = "text"; 665 const char kURI[] = "test://uri"; 666 const char kEncoding[] = "encoding"; 667 const char kLanguageCode[] = "en"; 668 const char kMimeType[] = "mime-type"; 669 const double kSize = 5; 670 671 // Text record. 672 base::DictionaryValue data; 673 data.SetString(NfcNdefRecord::kFieldText, kText); 674 data.SetString(NfcNdefRecord::kFieldLanguageCode, kLanguageCode); 675 data.SetString(NfcNdefRecord::kFieldEncoding, kEncoding); 676 677 scoped_ptr<NfcNdefRecord> record(new NfcNdefRecord()); 678 ASSERT_TRUE(record->Populate(NfcNdefRecord::kTypeText, &data)); 679 680 base::DictionaryValue result; 681 EXPECT_TRUE(nfc_ndef_record_utils::NfcNdefRecordToDBusAttributes( 682 record.get(), &result)); 683 684 std::string string_value; 685 EXPECT_TRUE(result.GetString( 686 nfc_record::kTypeProperty, &string_value)); 687 EXPECT_EQ(nfc_record::kTypeText, string_value); 688 EXPECT_TRUE(result.GetString( 689 nfc_record::kRepresentationProperty, &string_value)); 690 EXPECT_EQ(kText, string_value); 691 EXPECT_TRUE(result.GetString( 692 nfc_record::kLanguageProperty, &string_value)); 693 EXPECT_EQ(kLanguageCode, string_value); 694 EXPECT_TRUE(result.GetString( 695 nfc_record::kEncodingProperty, &string_value)); 696 EXPECT_EQ(kEncoding, string_value); 697 698 // URI record. 699 data.Clear(); 700 data.SetString(NfcNdefRecord::kFieldURI, kURI); 701 data.SetString(NfcNdefRecord::kFieldMimeType, kMimeType); 702 data.SetDouble(NfcNdefRecord::kFieldTargetSize, kSize); 703 704 record.reset(new NfcNdefRecord()); 705 ASSERT_TRUE(record->Populate(NfcNdefRecord::kTypeURI, &data)); 706 707 result.Clear(); 708 EXPECT_TRUE(nfc_ndef_record_utils::NfcNdefRecordToDBusAttributes( 709 record.get(), &result)); 710 711 EXPECT_TRUE(result.GetString(nfc_record::kTypeProperty, &string_value)); 712 EXPECT_EQ(nfc_record::kTypeUri, string_value); 713 EXPECT_TRUE(result.GetString(nfc_record::kUriProperty, &string_value)); 714 EXPECT_EQ(kURI, string_value); 715 EXPECT_TRUE(result.GetString(nfc_record::kMimeTypeProperty, &string_value)); 716 EXPECT_EQ(kMimeType, string_value); 717 double double_value; 718 EXPECT_TRUE(result.GetDouble(nfc_record::kSizeProperty, &double_value)); 719 EXPECT_EQ(kSize, double_value); 720 721 // SmartPoster record. 722 base::DictionaryValue* title = new base::DictionaryValue(); 723 title->SetString(NfcNdefRecord::kFieldText, kText); 724 title->SetString(NfcNdefRecord::kFieldLanguageCode, kLanguageCode); 725 title->SetString(NfcNdefRecord::kFieldEncoding, kEncoding); 726 727 base::ListValue* titles = new base::ListValue(); 728 titles->Append(title); 729 data.Set(NfcNdefRecord::kFieldTitles, titles); 730 731 record.reset(new NfcNdefRecord()); 732 ASSERT_TRUE(record->Populate(NfcNdefRecord::kTypeSmartPoster, &data)); 733 734 result.Clear(); 735 EXPECT_TRUE(nfc_ndef_record_utils::NfcNdefRecordToDBusAttributes( 736 record.get(), &result)); 737 738 EXPECT_TRUE(result.GetString( 739 nfc_record::kTypeProperty, &string_value)); 740 EXPECT_EQ(nfc_record::kTypeSmartPoster, string_value); 741 EXPECT_TRUE(result.GetString( 742 nfc_record::kRepresentationProperty, &string_value)); 743 EXPECT_EQ(kText, string_value); 744 EXPECT_TRUE(result.GetString( 745 nfc_record::kLanguageProperty, &string_value)); 746 EXPECT_EQ(kLanguageCode, string_value); 747 EXPECT_TRUE(result.GetString( 748 nfc_record::kEncodingProperty, &string_value)); 749 EXPECT_EQ(kEncoding, string_value); 750 EXPECT_TRUE(result.GetString(nfc_record::kUriProperty, &string_value)); 751 EXPECT_EQ(kURI, string_value); 752 EXPECT_TRUE(result.GetString(nfc_record::kMimeTypeProperty, &string_value)); 753 EXPECT_EQ(kMimeType, string_value); 754 EXPECT_TRUE(result.GetDouble(nfc_record::kSizeProperty, &double_value)); 755 EXPECT_EQ(kSize, double_value); 756} 757 758TEST_F(NfcChromeOSTest, RecordPropertiesToNfcNdefRecord) { 759 const char kText[] = "text"; 760 const char kURI[] = "test://uri"; 761 const char kEncoding[] = "encoding"; 762 const char kLanguageCode[] = "en"; 763 const char kMimeType[] = "mime-type"; 764 const uint32 kSize = 5; 765 766 FakeNfcRecordClient::Properties record_properties( 767 base::Bind(&OnPropertyChangedCallback)); 768 769 // Text record. 770 record_properties.type.ReplaceValue(nfc_record::kTypeText); 771 record_properties.representation.ReplaceValue(kText); 772 record_properties.language.ReplaceValue(kLanguageCode); 773 record_properties.encoding.ReplaceValue(kEncoding); 774 775 scoped_ptr<NfcNdefRecord> record(new NfcNdefRecord()); 776 EXPECT_TRUE(nfc_ndef_record_utils::RecordPropertiesToNfcNdefRecord( 777 &record_properties, record.get())); 778 EXPECT_TRUE(record->IsPopulated()); 779 780 std::string string_value; 781 EXPECT_EQ(NfcNdefRecord::kTypeText, record->type()); 782 EXPECT_TRUE(record->data().GetString( 783 NfcNdefRecord::kFieldText, &string_value)); 784 EXPECT_EQ(kText, string_value); 785 EXPECT_TRUE(record->data().GetString( 786 NfcNdefRecord::kFieldLanguageCode, &string_value)); 787 EXPECT_EQ(kLanguageCode, string_value); 788 EXPECT_TRUE(record->data().GetString( 789 NfcNdefRecord::kFieldEncoding, &string_value)); 790 EXPECT_EQ(kEncoding, string_value); 791 792 // URI record. 793 record_properties.representation.ReplaceValue(""); 794 record_properties.language.ReplaceValue(""); 795 record_properties.encoding.ReplaceValue(""); 796 797 record_properties.type.ReplaceValue(nfc_record::kTypeUri); 798 record_properties.uri.ReplaceValue(kURI); 799 record_properties.mime_type.ReplaceValue(kMimeType); 800 record_properties.size.ReplaceValue(kSize); 801 802 record.reset(new NfcNdefRecord()); 803 EXPECT_TRUE(nfc_ndef_record_utils::RecordPropertiesToNfcNdefRecord( 804 &record_properties, record.get())); 805 EXPECT_TRUE(record->IsPopulated()); 806 807 EXPECT_EQ(NfcNdefRecord::kTypeURI, record->type()); 808 EXPECT_TRUE(record->data().GetString( 809 NfcNdefRecord::kFieldURI, &string_value)); 810 EXPECT_EQ(kURI, string_value); 811 EXPECT_TRUE(record->data().GetString( 812 NfcNdefRecord::kFieldMimeType, &string_value)); 813 EXPECT_EQ(kMimeType, string_value); 814 double double_value; 815 EXPECT_TRUE(record->data().GetDouble( 816 NfcNdefRecord::kFieldTargetSize, &double_value)); 817 EXPECT_EQ(kSize, double_value); 818 819 // Contents not matching type. 820 record_properties.representation.ReplaceValue(kText); 821 record_properties.language.ReplaceValue(kLanguageCode); 822 record_properties.encoding.ReplaceValue(kEncoding); 823 824 record.reset(new NfcNdefRecord()); 825 EXPECT_FALSE(nfc_ndef_record_utils::RecordPropertiesToNfcNdefRecord( 826 &record_properties, record.get())); 827 EXPECT_FALSE(record->IsPopulated()); 828 829 // SmartPoster record. 830 record_properties.type.ReplaceValue(nfc_record::kTypeSmartPoster); 831 EXPECT_TRUE(nfc_ndef_record_utils::RecordPropertiesToNfcNdefRecord( 832 &record_properties, record.get())); 833 EXPECT_TRUE(record->IsPopulated()); 834 835 EXPECT_EQ(NfcNdefRecord::kTypeSmartPoster, record->type()); 836 EXPECT_TRUE(record->data().GetString( 837 NfcNdefRecord::kFieldURI, &string_value)); 838 EXPECT_EQ(kURI, string_value); 839 EXPECT_TRUE(record->data().GetString( 840 NfcNdefRecord::kFieldMimeType, &string_value)); 841 EXPECT_EQ(kMimeType, string_value); 842 EXPECT_TRUE(record->data().GetDouble( 843 NfcNdefRecord::kFieldTargetSize, &double_value)); 844 EXPECT_EQ(kSize, double_value); 845 846 const base::ListValue* titles = NULL; 847 EXPECT_TRUE(record->data().GetList(NfcNdefRecord::kFieldTitles, &titles)); 848 EXPECT_EQ(static_cast<size_t>(1), titles->GetSize()); 849 ASSERT_TRUE(titles); 850 const base::DictionaryValue* title = NULL; 851 EXPECT_TRUE(titles->GetDictionary(0, &title)); 852 CHECK(title); 853 854 EXPECT_TRUE(title->GetString(NfcNdefRecord::kFieldText, &string_value)); 855 EXPECT_EQ(kText, string_value); 856 EXPECT_TRUE(title->GetString( 857 NfcNdefRecord::kFieldLanguageCode, &string_value)); 858 EXPECT_EQ(kLanguageCode, string_value); 859 EXPECT_TRUE(title->GetString(NfcNdefRecord::kFieldEncoding, &string_value)); 860 EXPECT_EQ(kEncoding, string_value); 861} 862 863} // namespace chromeos 864