Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / device / nfc / nfc_chromeos_unittest.cc
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
24 using device::NfcAdapter;
25 using device::NfcNdefMessage;
26 using device::NfcNdefRecord;
27 using device::NfcNdefTagTechnology;
28 using device::NfcPeer;
29 using device::NfcTag;
30
31 namespace chromeos {
32
33 namespace {
34
35 // Callback passed to property structures.
36 void OnPropertyChangedCallback(const std::string& property_name) {
37 }
38
39 // Callback passed to dbus::PropertyBase::Set.
40 void OnSet(bool success) {
41 }
42
43 class 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
142 class 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.
212 TEST_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.
241 TEST_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.
298 TEST_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.
323 TEST_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.
372 TEST_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.
441 TEST_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.
511 TEST_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.
566 TEST_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.
663 TEST_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
758 TEST_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