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