Home | History | Annotate | Download | only in chromeos
      1 // Copyright 2014 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 "chrome/browser/ui/webui/chromeos/nfc_debug_ui.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/values.h"
     10 #include "chrome/browser/profiles/profile.h"
     11 #include "chrome/common/url_constants.h"
     12 #include "content/public/browser/web_ui.h"
     13 #include "content/public/browser/web_ui_data_source.h"
     14 #include "content/public/browser/web_ui_message_handler.h"
     15 #include "device/nfc/nfc_adapter.h"
     16 #include "device/nfc/nfc_adapter_factory.h"
     17 #include "device/nfc/nfc_peer.h"
     18 #include "device/nfc/nfc_tag.h"
     19 #include "grit/browser_resources.h"
     20 #include "grit/generated_resources.h"
     21 
     22 using device::NfcAdapter;
     23 using device::NfcAdapterFactory;
     24 using device::NfcNdefMessage;
     25 using device::NfcNdefRecord;
     26 using device::NfcNdefTagTechnology;
     27 using device::NfcPeer;
     28 using device::NfcTag;
     29 using device::NfcTagTechnology;
     30 
     31 namespace chromeos {
     32 
     33 namespace {
     34 
     35 // Keys for various NFC properties that are used by JS.
     36 const char kAdapterPeersProperty[] = "peers";
     37 const char kAdapterPollingProperty[] = "polling";
     38 const char kAdapterPoweredProperty[] = "powered";
     39 const char kAdapterPresentProperty[] = "present";
     40 const char kAdapterTagsProperty[] = "tags";
     41 
     42 const char kPeerIdentifierProperty[] = "identifier";
     43 const char kPeerRecordsProperty[] = "records";
     44 
     45 const char kTagIdentifierProperty[] = "identifier";
     46 const char kTagTypeProperty[] = "type";
     47 const char kTagReadOnlyProperty[] = "readOnly";
     48 const char kTagRecordsProperty[] = "records";
     49 const char kTagSupportedProtocolProperty[] = "supportedProtocol";
     50 const char kTagSupportedTechnologiesProperty[] = "supportedTechnologies";
     51 const char kRecordTypeProperty[] = "type";
     52 
     53 // Tag types.
     54 const char kTagType1[] = "TYPE-1";
     55 const char kTagType2[] = "TYPE-2";
     56 const char kTagType3[] = "TYPE-3";
     57 const char kTagType4[] = "TYPE-4";
     58 const char kTagTypeUnknown[] = "UNKNOWN";
     59 
     60 // NFC transfer protocols.
     61 const char kTagProtocolFelica[] = "FELICA";
     62 const char kTagProtocolIsoDep[] = "ISO-DEP";
     63 const char kTagProtocolJewel[] = "JEWEL";
     64 const char kTagProtocolMifare[] = "MIFARE";
     65 const char kTagProtocolNfcDep[] = "NFC-DEP";
     66 const char kTagProtocolUnknown[] = "UNKNOWN";
     67 
     68 // NFC tag technologies.
     69 const char kTagTechnologyNfcA[] = "NFC-A";
     70 const char kTagTechnologyNfcB[] = "NFC-B";
     71 const char kTagTechnologyNfcF[] = "NFC-F";
     72 const char kTagTechnologyNfcV[] = "NFC-V";
     73 const char kTagTechnologyIsoDep[] = "ISO-DEP";
     74 const char kTagTechnologyNdef[] = "NDEF";
     75 
     76 // NDEF types.
     77 const char kTypeHandoverCarrier[] = "HANDOVER_CARRIER";
     78 const char kTypeHandoverRequest[] = "HANDOVER_REQUEST";
     79 const char kTypeHandoverSelect[] = "HANDOVER_SELECT";
     80 const char kTypeSmartPoster[] = "SMART_POSTER";
     81 const char kTypeText[] = "TEXT";
     82 const char kTypeURI[] = "URI";
     83 const char kTypeUnknown[] = "UNKNOWN";
     84 
     85 // JavaScript callback constants.
     86 const char kInitializeCallback[] = "initialize";
     87 const char kSetAdapterPowerCallback[] = "setAdapterPower";
     88 const char kSetAdapterPollingCallback[] = "setAdapterPolling";
     89 const char kSubmitRecordFormCallback[] = "submitRecordForm";
     90 
     91 // Constants for JavaScript functions that we can call.
     92 const char kOnNfcAdapterInfoChangedFunction[] =
     93     "nfcDebug.NfcDebugUI.onNfcAdapterInfoChanged";
     94 const char kOnNfcAvailabilityDeterminedFunction[] =
     95     "nfcDebug.NfcDebugUI.onNfcAvailabilityDetermined";
     96 const char kOnNfcPeerDeviceInfoChangedFunction[] =
     97     "nfcDebug.NfcDebugUI.onNfcPeerDeviceInfoChanged";
     98 const char kOnNfcTagInfoChangedFunction[] =
     99     "nfcDebug.NfcDebugUI.onNfcTagInfoChanged";
    100 const char kOnSetAdapterPollingFailedFunction[] =
    101     "nfcDebug.NfcDebugUI.onSetAdapterPollingFailed";
    102 const char kOnSetAdapterPowerFailedFunction[] =
    103     "nfcDebug.NfcDebugUI.onSetAdapterPowerFailed";
    104 const char kOnSubmitRecordFormFailedFunction[] =
    105     "nfcDebug.NfcDebugUI.onSubmitRecordFormFailed";
    106 
    107 std::string RecordTypeToString(NfcNdefRecord::Type type) {
    108   switch (type) {
    109     case NfcNdefRecord::kTypeHandoverCarrier:
    110       return kTypeHandoverCarrier;
    111     case NfcNdefRecord::kTypeHandoverRequest:
    112       return kTypeHandoverRequest;
    113     case NfcNdefRecord::kTypeHandoverSelect:
    114       return kTypeHandoverSelect;
    115     case NfcNdefRecord::kTypeSmartPoster:
    116       return kTypeSmartPoster;
    117     case NfcNdefRecord::kTypeText:
    118       return kTypeText;
    119     case NfcNdefRecord::kTypeURI:
    120       return kTypeURI;
    121     case NfcNdefRecord::kTypeUnknown:
    122       return kTypeUnknown;
    123   }
    124   return kTypeUnknown;
    125 }
    126 
    127 NfcNdefRecord::Type RecordTypeStringValueToEnum(const std::string& type) {
    128   if (type == kTypeHandoverCarrier)
    129     return NfcNdefRecord::kTypeHandoverCarrier;
    130   if (type == kTypeHandoverRequest)
    131     return NfcNdefRecord::kTypeHandoverRequest;
    132   if (type == kTypeHandoverSelect)
    133     return NfcNdefRecord::kTypeHandoverSelect;
    134   if (type == kTypeSmartPoster)
    135     return NfcNdefRecord::kTypeSmartPoster;
    136   if (type == kTypeText)
    137     return NfcNdefRecord::kTypeText;
    138   if (type == kTypeURI)
    139     return NfcNdefRecord::kTypeURI;
    140   return NfcNdefRecord::kTypeUnknown;
    141 }
    142 
    143 std::string TagTypeToString(NfcTag::TagType type) {
    144   switch (type) {
    145     case NfcTag::kTagType1:
    146       return kTagType1;
    147     case NfcTag::kTagType2:
    148       return kTagType2;
    149     case NfcTag::kTagType3:
    150       return kTagType3;
    151     case NfcTag::kTagType4:
    152       return kTagType4;
    153     case NfcTag::kTagTypeUnknown:
    154       return kTagTypeUnknown;
    155   }
    156   return kTagTypeUnknown;
    157 }
    158 
    159 std::string TagProtocolToString(NfcTag::Protocol protocol) {
    160   switch (protocol) {
    161     case NfcTag::kProtocolFelica:
    162       return kTagProtocolFelica;
    163     case NfcTag::kProtocolIsoDep:
    164       return kTagProtocolIsoDep;
    165     case NfcTag::kProtocolJewel:
    166       return kTagProtocolJewel;
    167     case NfcTag::kProtocolMifare:
    168       return kTagProtocolMifare;
    169     case NfcTag::kProtocolNfcDep:
    170       return kTagProtocolNfcDep;
    171     case NfcTag::kProtocolUnknown:
    172       return kTagProtocolUnknown;
    173   }
    174   return kTagProtocolUnknown;
    175 }
    176 
    177 // content::WebUIMessageHandler implementation for this page.
    178 class NfcDebugMessageHandler : public content::WebUIMessageHandler,
    179                                public NfcAdapter::Observer,
    180                                public NfcNdefTagTechnology::Observer,
    181                                public NfcPeer::Observer,
    182                                public NfcTag::Observer {
    183  public:
    184   NfcDebugMessageHandler();
    185   virtual ~NfcDebugMessageHandler();
    186 
    187   // WebUIMessageHandler implementation.
    188   virtual void RegisterMessages() OVERRIDE;
    189 
    190   // NfcAdapter::Observer overrides.
    191   virtual void AdapterPresentChanged(
    192       NfcAdapter* adapter,
    193       bool present) OVERRIDE;
    194   virtual void AdapterPoweredChanged(
    195       NfcAdapter* adapter,
    196       bool powered) OVERRIDE;
    197   virtual void AdapterPollingChanged(
    198       NfcAdapter* adapter,
    199       bool polling) OVERRIDE;
    200   virtual void TagFound(NfcAdapter* adapter, NfcTag* tag) OVERRIDE;
    201   virtual void TagLost(NfcAdapter*adapter, NfcTag* tag) OVERRIDE;
    202   virtual void PeerFound(NfcAdapter* adaper, NfcPeer* peer) OVERRIDE;
    203   virtual void PeerLost(NfcAdapter* adapter, NfcPeer* peer) OVERRIDE;
    204 
    205   // NfcNdefTagTechnology::Observer override.
    206   virtual void RecordReceived(
    207       NfcTag* tag,
    208       const NfcNdefRecord* record) OVERRIDE;
    209 
    210   // NfcPeer::Observer override.
    211   virtual void RecordReceived(
    212       NfcPeer* peer,
    213       const NfcNdefRecord* record) OVERRIDE;
    214 
    215   // NfcTag::Observer override.
    216   virtual void TagReady(NfcTag* tag) OVERRIDE;
    217 
    218  private:
    219   // Called by the UI when the page loads. This method requests information
    220   // about NFC availability on the current platform and requests the underlying
    221   // Adapter object. The UI is notified once the information is available.
    222   void Initialize(const base::ListValue* args);
    223 
    224   // Called by the UI to toggle the adapter power. |args| will contain one
    225   // boolean that indicates whether the power should be set to ON or OFF.
    226   void SetAdapterPower(const base::ListValue* args);
    227   void OnSetAdapterPowerError();
    228 
    229   // Called by the UI set the adapter's poll status. |args| will contain one
    230   // boolean that indicates whether polling should be started or stopped.
    231   void SetAdapterPolling(const base::ListValue* args);
    232   void OnSetAdapterPollingError();
    233 
    234   // Called by the UI to push an NDEF record to a remote device or tag. |args|
    235   // will contain one dictionary that contains the record data.
    236   void SubmitRecordForm(const base::ListValue* args);
    237   void OnSubmitRecordFormFailed(const std::string& error_message);
    238 
    239   // Callback passed to NfcAdapterFactory::GetAdapter.
    240   void OnGetAdapter(scoped_refptr<NfcAdapter> adapter);
    241 
    242   // Stores the properties of the NFC adapter in |out|, mapping these to keys
    243   // that will be read by JS.
    244   void GetAdapterProperties(base::DictionaryValue* out);
    245 
    246   // Stores the properties of the NFC peer in |out|, mapping these to keys
    247   // that will be read by JS. |out| will not be modified, if no peer is known.
    248   void GetPeerProperties(base::DictionaryValue* out);
    249 
    250   // Stores the properties of the NFC tag in |out|, mapping these to keys
    251   // that will be read by JS. |out| will not be modified, if no tag is known.
    252   void GetTagProperties(base::DictionaryValue* out);
    253 
    254   // Returns the records in |message| by populating |out|, in which
    255   // they have been converted to a JS friendly format.
    256   void GetRecordList(const NfcNdefMessage& message, base::ListValue* out);
    257 
    258   // Updates the data displayed in the UI for the current adapter.
    259   void UpdateAdapterInfo();
    260 
    261   // Updates the data displayed in the UI for the current peer.
    262   void UpdatePeerInfo();
    263 
    264   // Updates the data displayed in the UI for the current tag.
    265   void UpdateTagInfo();
    266 
    267   // The NfcAdapter object.
    268   scoped_refptr<NfcAdapter> nfc_adapter_;
    269 
    270   // The cached identifier of the most recent NFC peer device found.
    271   std::string peer_identifier_;
    272 
    273   // The cached identifier of the most recent NFC tag found.
    274   std::string tag_identifier_;
    275 
    276   DISALLOW_COPY_AND_ASSIGN(NfcDebugMessageHandler);
    277 };
    278 
    279 NfcDebugMessageHandler::NfcDebugMessageHandler() {
    280 }
    281 
    282 NfcDebugMessageHandler::~NfcDebugMessageHandler() {
    283   if (!nfc_adapter_.get())
    284     return;
    285   nfc_adapter_->RemoveObserver(this);
    286   if (!peer_identifier_.empty()) {
    287     NfcPeer* peer = nfc_adapter_->GetPeer(peer_identifier_);
    288     if (peer)
    289       peer->RemoveObserver(this);
    290   }
    291   if (!tag_identifier_.empty()) {
    292     NfcTag* tag = nfc_adapter_->GetTag(tag_identifier_);
    293     if (tag)
    294       tag->RemoveObserver(this);
    295   }
    296 }
    297 
    298 void NfcDebugMessageHandler::AdapterPresentChanged(
    299     NfcAdapter* adapter,
    300     bool present) {
    301   UpdateAdapterInfo();
    302 }
    303 
    304 void NfcDebugMessageHandler::AdapterPoweredChanged(
    305     NfcAdapter* adapter,
    306     bool powered) {
    307   UpdateAdapterInfo();
    308 }
    309 
    310 void NfcDebugMessageHandler::AdapterPollingChanged(
    311     NfcAdapter* adapter,
    312     bool polling) {
    313   UpdateAdapterInfo();
    314 }
    315 
    316 void NfcDebugMessageHandler::TagFound(NfcAdapter* adapter, NfcTag* tag) {
    317   VLOG(1) << "Found NFC tag: " << tag->GetIdentifier();
    318   tag->AddObserver(this);
    319   tag_identifier_ = tag->GetIdentifier();
    320   tag->GetNdefTagTechnology()->AddObserver(this);
    321   UpdateAdapterInfo();
    322   UpdateTagInfo();
    323 }
    324 
    325 void NfcDebugMessageHandler::TagLost(NfcAdapter*adapter, NfcTag* tag) {
    326   VLOG(1) << "Lost NFC tag: " << tag->GetIdentifier();
    327   tag->RemoveObserver(this);
    328   tag->GetNdefTagTechnology()->RemoveObserver(this);
    329   tag_identifier_.clear();
    330   UpdateAdapterInfo();
    331   UpdateTagInfo();
    332 }
    333 
    334 void NfcDebugMessageHandler::PeerFound(NfcAdapter* adaper, NfcPeer* peer) {
    335   VLOG(1) << "Found NFC peer device: " << peer->GetIdentifier();
    336   peer->AddObserver(this);
    337   peer_identifier_ = peer->GetIdentifier();
    338   UpdateAdapterInfo();
    339   UpdatePeerInfo();
    340 }
    341 
    342 void NfcDebugMessageHandler::PeerLost(NfcAdapter* adapter, NfcPeer* peer) {
    343   VLOG(1) << "Lost NFC peer device: " << peer->GetIdentifier();
    344   peer->RemoveObserver(this);
    345   peer_identifier_.clear();
    346   UpdateAdapterInfo();
    347   UpdatePeerInfo();
    348 }
    349 
    350 void NfcDebugMessageHandler::RecordReceived(
    351       NfcTag* tag,
    352       const NfcNdefRecord* record) {
    353   if (tag->GetIdentifier() != tag_identifier_) {
    354     LOG(WARNING) << "Records received from unknown tag: "
    355                  << tag->GetIdentifier();
    356     return;
    357   }
    358   UpdateTagInfo();
    359 }
    360 
    361 void NfcDebugMessageHandler::RecordReceived(
    362       NfcPeer* peer,
    363       const NfcNdefRecord* record) {
    364   if (peer->GetIdentifier() != peer_identifier_) {
    365     LOG(WARNING) << "Records received from unknown peer: "
    366                  << peer->GetIdentifier();
    367     return;
    368   }
    369   UpdatePeerInfo();
    370 }
    371 
    372 void NfcDebugMessageHandler::TagReady(NfcTag* tag) {
    373   if (tag_identifier_ != tag->GetIdentifier()) {
    374     LOG(WARNING) << "Unknown tag became ready: " << tag->GetIdentifier();
    375     return;
    376   }
    377   VLOG(1) << "Tag ready: " << tag->GetIdentifier();
    378   UpdateTagInfo();
    379 }
    380 
    381 void NfcDebugMessageHandler::RegisterMessages() {
    382   web_ui()->RegisterMessageCallback(
    383       kInitializeCallback,
    384       base::Bind(&NfcDebugMessageHandler::Initialize,
    385                  base::Unretained(this)));
    386   web_ui()->RegisterMessageCallback(
    387       kSetAdapterPowerCallback,
    388       base::Bind(&NfcDebugMessageHandler::SetAdapterPower,
    389                  base::Unretained(this)));
    390   web_ui()->RegisterMessageCallback(
    391       kSetAdapterPollingCallback,
    392       base::Bind(&NfcDebugMessageHandler::SetAdapterPolling,
    393                  base::Unretained(this)));
    394   web_ui()->RegisterMessageCallback(
    395       kSubmitRecordFormCallback,
    396       base::Bind(&NfcDebugMessageHandler::SubmitRecordForm,
    397                  base::Unretained(this)));
    398 }
    399 
    400 void NfcDebugMessageHandler::Initialize(const base::ListValue* args) {
    401   bool nfc_available = NfcAdapterFactory::IsNfcAvailable();
    402   base::FundamentalValue available(nfc_available);
    403   web_ui()->CallJavascriptFunction(kOnNfcAvailabilityDeterminedFunction,
    404                                    available);
    405   if (!nfc_available) {
    406     LOG(WARNING) << "NFC is not available on current platform.";
    407     return;
    408   }
    409   NfcAdapterFactory::GetAdapter(
    410       base::Bind(&NfcDebugMessageHandler::OnGetAdapter,
    411                  base::Unretained(this)));
    412 }
    413 
    414 void NfcDebugMessageHandler::SetAdapterPower(const base::ListValue* args) {
    415   DCHECK(1 == args->GetSize());
    416   DCHECK(nfc_adapter_.get());
    417   bool powered;
    418   args->GetBoolean(0, &powered);
    419   VLOG(1) << "Setting adapter power: " << powered;
    420   nfc_adapter_->SetPowered(
    421       powered, base::Bind(&base::DoNothing),
    422       base::Bind(&NfcDebugMessageHandler::OnSetAdapterPowerError,
    423                  base::Unretained(this)));
    424 }
    425 
    426 void NfcDebugMessageHandler::OnSetAdapterPowerError() {
    427   LOG(ERROR) << "Failed to set NFC adapter power.";
    428   web_ui()->CallJavascriptFunction(kOnSetAdapterPowerFailedFunction);
    429 }
    430 
    431 void NfcDebugMessageHandler::SetAdapterPolling(const base::ListValue* args) {
    432   DCHECK(1 == args->GetSize());
    433   DCHECK(nfc_adapter_.get());
    434   bool start = false;
    435   bool result = args->GetBoolean(0, &start);
    436   DCHECK(result);
    437   if (start) {
    438     VLOG(1) << "Starting NFC poll loop.";
    439     nfc_adapter_->StartPolling(
    440         base::Bind(&base::DoNothing),
    441         base::Bind(&NfcDebugMessageHandler::OnSetAdapterPollingError,
    442                    base::Unretained(this)));
    443   } else {
    444     VLOG(1) << "Stopping NFC poll loop.";
    445     nfc_adapter_->StopPolling(
    446         base::Bind(&base::DoNothing),
    447         base::Bind(&NfcDebugMessageHandler::OnSetAdapterPollingError,
    448                    base::Unretained(this)));
    449   }
    450 }
    451 
    452 void NfcDebugMessageHandler::OnSetAdapterPollingError() {
    453   LOG(ERROR) << "Failed to start/stop polling.";
    454   web_ui()->CallJavascriptFunction(kOnSetAdapterPollingFailedFunction);
    455 }
    456 
    457 void NfcDebugMessageHandler::SubmitRecordForm(const base::ListValue* args) {
    458   DCHECK(1 == args->GetSize());
    459   DCHECK(nfc_adapter_.get());
    460   const base::DictionaryValue* record_data_const = NULL;
    461   if (!args->GetDictionary(0, &record_data_const)) {
    462     NOTREACHED();
    463     return;
    464   }
    465 
    466   if (peer_identifier_.empty() && tag_identifier_.empty()) {
    467     OnSubmitRecordFormFailed("No peer or tag present.");
    468     return;
    469   }
    470 
    471   std::string type;
    472   if (!record_data_const->GetString(kRecordTypeProperty, &type)) {
    473     OnSubmitRecordFormFailed("Record type not provided.");
    474     return;
    475   }
    476 
    477   base::DictionaryValue* record_data = record_data_const->DeepCopy();
    478   record_data->Remove(kRecordTypeProperty, NULL);
    479 
    480   // Convert the "targetSize" field to a double, in case JS stored it as an
    481   // integer.
    482   int target_size;
    483   if (record_data->GetInteger(NfcNdefRecord::kFieldTargetSize, &target_size)) {
    484     record_data->SetDouble(NfcNdefRecord::kFieldTargetSize,
    485                            static_cast<double>(target_size));
    486   }
    487 
    488   NfcNdefRecord record;
    489   if (!record.Populate(RecordTypeStringValueToEnum(type), record_data)) {
    490     OnSubmitRecordFormFailed("Invalid record data provided. Missing required "
    491                              "fields?");
    492     return;
    493   }
    494 
    495   if (!peer_identifier_.empty()) {
    496     NfcPeer* peer = nfc_adapter_->GetPeer(peer_identifier_);
    497     if (!peer) {
    498       OnSubmitRecordFormFailed("The current NFC adapter doesn't seem to know "
    499                                "about peer: " + peer_identifier_);
    500       return;
    501     }
    502     NfcNdefMessage message;
    503     message.AddRecord(&record);
    504     peer->PushNdef(message,
    505                    base::Bind(&base::DoNothing),
    506                    base::Bind(&NfcDebugMessageHandler::OnSubmitRecordFormFailed,
    507                               base::Unretained(this),
    508                               "Failed to push NDEF record."));
    509     return;
    510   }
    511   NfcTag* tag = nfc_adapter_->GetTag(tag_identifier_);
    512   if (!tag) {
    513     OnSubmitRecordFormFailed("The current NFC tag doesn't seem to known about "
    514                              "tag: " + tag_identifier_);
    515     return;
    516   }
    517   NfcNdefMessage message;
    518   message.AddRecord(&record);
    519   tag->GetNdefTagTechnology()->WriteNdef(
    520                  message,
    521                  base::Bind(&base::DoNothing),
    522                  base::Bind(&NfcDebugMessageHandler::OnSubmitRecordFormFailed,
    523                             base::Unretained(this),
    524                             "Failed to write NDEF record."));
    525 }
    526 
    527 void NfcDebugMessageHandler::OnSubmitRecordFormFailed(
    528     const std::string& error_message) {
    529   LOG(ERROR) << "SubmitRecordForm failed: " << error_message;
    530   web_ui()->CallJavascriptFunction(kOnSubmitRecordFormFailedFunction,
    531                                    base::StringValue(error_message));
    532 }
    533 
    534 void NfcDebugMessageHandler::OnGetAdapter(
    535     scoped_refptr<NfcAdapter> adapter) {
    536   if (nfc_adapter_.get())
    537     return;
    538   nfc_adapter_ = adapter;
    539   nfc_adapter_->AddObserver(this);
    540   UpdateAdapterInfo();
    541 
    542   NfcAdapter::PeerList peers;
    543   nfc_adapter_->GetPeers(&peers);
    544   for (NfcAdapter::PeerList::const_iterator iter = peers.begin();
    545        iter != peers.end(); ++iter) {
    546     PeerFound(nfc_adapter_.get(), *iter);
    547   }
    548 
    549   NfcAdapter::TagList tags;
    550   nfc_adapter_->GetTags(&tags);
    551   for (NfcAdapter::TagList::const_iterator iter = tags.begin();
    552        iter != tags.end(); ++iter) {
    553     TagFound(nfc_adapter_.get(), *iter);
    554   }
    555 }
    556 
    557 void NfcDebugMessageHandler::GetAdapterProperties(
    558     base::DictionaryValue* out) {
    559   if (!nfc_adapter_.get()) {
    560     VLOG(1) << "NFC adapter hasn't been received yet.";
    561     return;
    562   }
    563   out->SetBoolean(kAdapterPresentProperty, nfc_adapter_->IsPresent());
    564   out->SetBoolean(kAdapterPollingProperty, nfc_adapter_->IsPolling());
    565   out->SetBoolean(kAdapterPoweredProperty, nfc_adapter_->IsPowered());
    566 
    567   NfcAdapter::PeerList peers;
    568   nfc_adapter_->GetPeers(&peers);
    569   out->SetInteger(kAdapterPeersProperty, static_cast<int>(peers.size()));
    570 
    571   NfcAdapter::TagList tags;
    572   nfc_adapter_->GetTags(&tags);
    573   out->SetInteger(kAdapterTagsProperty, static_cast<int>(tags.size()));
    574 }
    575 
    576 void NfcDebugMessageHandler::GetPeerProperties(base::DictionaryValue* out) {
    577   if (peer_identifier_.empty()) {
    578     VLOG(1) << "No known peer exists.";
    579     return;
    580   }
    581   if (!nfc_adapter_.get()) {
    582     VLOG(1) << "NFC adapter hasn't been received yet.";
    583     return;
    584   }
    585   NfcPeer* peer = nfc_adapter_->GetPeer(peer_identifier_);
    586   if (!peer) {
    587     LOG(ERROR) << "The current NFC adapter doesn't seem to know about peer: "
    588                << peer_identifier_;
    589     return;
    590   }
    591   out->SetString(kPeerIdentifierProperty, peer_identifier_);
    592 
    593   base::ListValue* records = new base::ListValue();
    594   GetRecordList(peer->GetNdefMessage(), records);
    595   out->Set(kPeerRecordsProperty, records);
    596 }
    597 
    598 void NfcDebugMessageHandler::GetTagProperties(base::DictionaryValue* out) {
    599   if (tag_identifier_.empty()) {
    600     VLOG(1) << "No known tag exists.";
    601     return;
    602   }
    603   if (!nfc_adapter_.get()) {
    604     VLOG(1) << "NFC adapter hasn't been received yet.";
    605     return;
    606   }
    607   NfcTag* tag = nfc_adapter_->GetTag(tag_identifier_);
    608   if (!tag) {
    609     LOG(ERROR) << "The current NFC adapter doesn't seem to know about tag: "
    610                << tag_identifier_;
    611     return;
    612   }
    613   out->SetString(kTagIdentifierProperty, tag_identifier_);
    614   out->SetString(kTagTypeProperty, TagTypeToString(tag->GetType()));
    615   out->SetBoolean(kTagReadOnlyProperty, tag->IsReadOnly());
    616   out->SetString(kTagSupportedProtocolProperty,
    617                  TagProtocolToString(tag->GetSupportedProtocol()));
    618 
    619   base::ListValue* technologies = new base::ListValue();
    620   NfcTagTechnology::TechnologyTypeMask technology_mask =
    621       tag->GetSupportedTechnologies();
    622   if (technology_mask & NfcTagTechnology::kTechnologyTypeNfcA)
    623     technologies->AppendString(kTagTechnologyNfcA);
    624   if (technology_mask & NfcTagTechnology::kTechnologyTypeNfcB)
    625     technologies->AppendString(kTagTechnologyNfcB);
    626   if (technology_mask & NfcTagTechnology::kTechnologyTypeNfcF)
    627     technologies->AppendString(kTagTechnologyNfcF);
    628   if (technology_mask & NfcTagTechnology::kTechnologyTypeNfcV)
    629     technologies->AppendString(kTagTechnologyNfcV);
    630   if (technology_mask & NfcTagTechnology::kTechnologyTypeIsoDep)
    631     technologies->AppendString(kTagTechnologyIsoDep);
    632   if (technology_mask & NfcTagTechnology::kTechnologyTypeNdef)
    633     technologies->AppendString(kTagTechnologyNdef);
    634   out->Set(kTagSupportedTechnologiesProperty, technologies);
    635 
    636   base::ListValue* records = new base::ListValue();
    637   GetRecordList(tag->GetNdefTagTechnology()->GetNdefMessage(), records);
    638   out->Set(kTagRecordsProperty, records);
    639 }
    640 
    641 void NfcDebugMessageHandler::GetRecordList(const NfcNdefMessage& message,
    642                                            base::ListValue* out) {
    643   for (NfcNdefMessage::RecordList::const_iterator iter =
    644           message.records().begin();
    645       iter != message.records().end(); ++iter) {
    646     const NfcNdefRecord* record = (*iter);
    647     base::DictionaryValue* record_data = record->data().DeepCopy();
    648     record_data->SetString(kRecordTypeProperty,
    649                            RecordTypeToString(record->type()));
    650     out->Append(record_data);
    651   }
    652 }
    653 
    654 void NfcDebugMessageHandler::UpdateAdapterInfo() {
    655   base::DictionaryValue data;
    656   GetAdapterProperties(&data);
    657   web_ui()->CallJavascriptFunction(kOnNfcAdapterInfoChangedFunction, data);
    658 }
    659 
    660 void NfcDebugMessageHandler::UpdatePeerInfo() {
    661   base::DictionaryValue data;
    662   GetPeerProperties(&data);
    663   web_ui()->CallJavascriptFunction(kOnNfcPeerDeviceInfoChangedFunction, data);
    664 }
    665 
    666 void NfcDebugMessageHandler::UpdateTagInfo() {
    667   base::DictionaryValue data;
    668   GetTagProperties(&data);
    669   web_ui()->CallJavascriptFunction(kOnNfcTagInfoChangedFunction, data);
    670 }
    671 
    672 }  // namespace
    673 
    674 NfcDebugUI::NfcDebugUI(content::WebUI* web_ui)
    675     : content::WebUIController(web_ui) {
    676   web_ui->AddMessageHandler(new NfcDebugMessageHandler());
    677 
    678   content::WebUIDataSource* html_source =
    679     content::WebUIDataSource::Create(chrome::kChromeUINfcDebugHost);
    680   html_source->SetUseJsonJSFormatV2();
    681 
    682   html_source->AddLocalizedString("titleText", IDS_NFC_DEBUG_TITLE);
    683   html_source->AddLocalizedString("notSupportedText",
    684                                   IDS_NFC_DEBUG_NOT_SUPPORTED);
    685   html_source->AddLocalizedString("adapterHeaderText",
    686                                   IDS_NFC_DEBUG_ADAPTER_HEADER);
    687   html_source->AddLocalizedString("adapterPowerOnText",
    688                                   IDS_NFC_DEBUG_ADAPTER_POWER_ON);
    689   html_source->AddLocalizedString("adapterPowerOffText",
    690                                   IDS_NFC_DEBUG_ADAPTER_POWER_OFF);
    691   html_source->AddLocalizedString("adapterStartPollText",
    692                                   IDS_NFC_DEBUG_ADAPTER_START_POLL);
    693   html_source->AddLocalizedString("adapterStopPollText",
    694                                   IDS_NFC_DEBUG_ADAPTER_STOP_POLL);
    695   html_source->AddLocalizedString("ndefFormHeaderText",
    696                                   IDS_NFC_DEBUG_NDEF_FORM_HEADER);
    697   html_source->AddLocalizedString("ndefFormTypeTextText",
    698                                   IDS_NFC_DEBUG_NDEF_FORM_TYPE_TEXT);
    699   html_source->AddLocalizedString("ndefFormTypeUriText",
    700                                   IDS_NFC_DEBUG_NDEF_FORM_TYPE_URI);
    701   html_source->AddLocalizedString("ndefFormTypeSmartPosterText",
    702                                   IDS_NFC_DEBUG_NDEF_FORM_TYPE_SMART_POSTER);
    703   html_source->AddLocalizedString("ndefFormWriteButtonText",
    704                                   IDS_NFC_DEBUG_NDEF_FORM_WRITE_BUTTON);
    705   html_source->AddLocalizedString("ndefFormFieldTextText",
    706                                   IDS_NFC_DEBUG_NDEF_FORM_FIELD_TEXT);
    707   html_source->AddLocalizedString("ndefFormFieldEncodingText",
    708                                   IDS_NFC_DEBUG_NDEF_FORM_FIELD_ENCODING);
    709   html_source->AddLocalizedString("ndefFormFieldLanguageCodeText",
    710                                   IDS_NFC_DEBUG_NDEF_FORM_FIELD_LANGUAGE_CODE);
    711   html_source->AddLocalizedString("ndefFormFieldUriText",
    712                                   IDS_NFC_DEBUG_NDEF_FORM_FIELD_URI);
    713   html_source->AddLocalizedString("ndefFormFieldMimeTypeText",
    714                                   IDS_NFC_DEBUG_NDEF_FORM_FIELD_MIME_TYPE);
    715   html_source->AddLocalizedString("ndefFormFieldTargetSizeText",
    716                                   IDS_NFC_DEBUG_NDEF_FORM_FIELD_TARGET_SIZE);
    717   html_source->AddLocalizedString("ndefFormFieldTitleTextText",
    718                                   IDS_NFC_DEBUG_NDEF_FORM_FIELD_TITLE_TEXT);
    719   html_source->AddLocalizedString("ndefFormFieldTitleEncodingText",
    720                                   IDS_NFC_DEBUG_NDEF_FORM_FIELD_TITLE_ENCODING);
    721   html_source->AddLocalizedString(
    722       "ndefFormFieldTitleLanguageCodeText",
    723       IDS_NFC_DEBUG_NDEF_FORM_FIELD_TITLE_LANGUAGE_CODE);
    724   html_source->AddLocalizedString("ndefFormPushButtonText",
    725                                   IDS_NFC_DEBUG_NDEF_FORM_PUSH_BUTTON);
    726   html_source->AddLocalizedString("nfcPeerHeaderText",
    727                                   IDS_NFC_DEBUG_NFC_PEER_HEADER);
    728   html_source->AddLocalizedString("nfcTagHeaderText",
    729                                   IDS_NFC_DEBUG_NFC_TAG_HEADER);
    730   html_source->AddLocalizedString("recordsHeaderText",
    731                                   IDS_NFC_DEBUG_RECORDS_HEADER);
    732   html_source->AddLocalizedString("errorFailedToSetPowerText",
    733                                   IDS_NFC_DEBUG_ERROR_FAILED_TO_SET_POWER);
    734   html_source->AddLocalizedString("errorFailedToSetPollingText",
    735                                   IDS_NFC_DEBUG_ERROR_FAILED_TO_SET_POLLING);
    736   html_source->AddLocalizedString("errorFailedToSubmitPrefixText",
    737                                   IDS_NFC_DEBUG_ERROR_FAILED_TO_SUBMIT_PREFIX);
    738   html_source->SetJsonPath("strings.js");
    739 
    740   // Add required resources.
    741   html_source->AddResourcePath("nfc_debug.css", IDR_NFC_DEBUG_CSS);
    742   html_source->AddResourcePath("nfc_debug.js", IDR_NFC_DEBUG_JS);
    743   html_source->SetDefaultResource(IDR_NFC_DEBUG_HTML);
    744 
    745   Profile* profile = Profile::FromWebUI(web_ui);
    746   content::WebUIDataSource::Add(profile, html_source);
    747 }
    748 
    749 NfcDebugUI::~NfcDebugUI() {
    750 }
    751 
    752 }  // namespace chromeos
    753