[Tizen] Implement W3C NFC API
authorAlexander Shalamov <alexander.shalamov@gmail.com>
Mon, 9 Jun 2014 12:07:41 +0000 (15:07 +0300)
committerAlexander Shalamov <alexander.shalamov@gmail.com>
Wed, 23 Jul 2014 11:47:27 +0000 (14:47 +0300)
This patch adds initial implementation of W3C NFC API for Tizen platform.
API specification can be found here: http://www.w3.org/TR/nfc/

BUG=XWALK-432

examples/nfc.html [new file with mode: 0644]
nfc/README.md [new file with mode: 0644]
nfc/nfc.gyp [new file with mode: 0644]
nfc/nfc_api.js [new file with mode: 0644]
nfc/nfc_callbacks.h [new file with mode: 0644]
nfc/nfc_extension.cc [new file with mode: 0644]
nfc/nfc_extension.h [new file with mode: 0644]
nfc/nfc_instance.cc [new file with mode: 0644]
nfc/nfc_instance.h [new file with mode: 0644]
packaging/tizen-extensions-crosswalk.spec
tizen-wrt.gyp

diff --git a/examples/nfc.html b/examples/nfc.html
new file mode 100644 (file)
index 0000000..4d42cc0
--- /dev/null
@@ -0,0 +1,144 @@
+<html>
+<head>
+<title>NFC example</title>
+</head>
+<body>
+
+<button onclick='powerOn()'>Power ON</button>
+<button onclick='powerOff()'>Power OFF</button>
+<button onclick='startPoll()'>Start polling</button>
+<button onclick='stopPoll()'>Stop polling</button>
+
+<button onclick='createNDEFRecord()'>Create NDEF record</button>
+
+<div id='tag_methods' style='display: none;'>
+<button onclick='readNDEF()'>Read NDEF</button>
+<button onclick='writeTextNDEF()'>Write text NDEF</button>
+<button onclick='writeURINDEF()'>Write URI NDEF</button>
+<button onclick='writeMediaNDEF()'>Write Media NDEF</button>
+</div>
+
+<div id='peer_methods' style='display: none;'>
+<button onclick='sendURINDEF()'>Send URI NDEF to peer</button>
+</div>
+
+<div id='log'></div>
+<div id='eventLog'></div>
+
+<script>
+
+var tag = null;
+var peer = null;
+
+function addMessage(obj) {
+  if(typeof obj === 'string')
+    document.getElementById('log').innerHTML = obj;
+  else
+    document.getElementById('eventLog').innerHTML = "Received event: " + obj.type;
+}
+
+var events = [
+  'poweron',
+  'poweroff',
+  'pollstart',
+  'pollstop',
+  'tagfound',
+  'taglost',
+  'peerfound',
+  'peerlost'
+];
+
+function handleEvent(e) { 
+  addMessage(e);
+}
+
+events.forEach(function(event) {
+  navigator.nfc.addEventListener(event, handleEvent);
+});
+
+navigator.nfc.addEventListener('tagfound', tagFound);
+navigator.nfc.addEventListener('taglost', tagLost);
+navigator.nfc.addEventListener('peerfound', peerFound);
+navigator.nfc.addEventListener('peerlost', peerLost);
+
+function tagFound(e) {
+  tag = e.tag;
+  document.getElementById('tag_methods').style.display = 'block';
+}
+
+function tagLost(e) {
+  tag = null;
+  document.getElementById('tag_methods').style.display = 'none';
+}
+
+function peerFound(e) {
+  peer = e.peer;
+  peer.addEventListener('messageread', onMessageRead);
+  document.getElementById('peer_methods').style.display = 'block';
+}
+
+function peerLost(e) {
+  peer = null;
+  document.getElementById('peer_methods').style.display = 'none';
+}
+
+function onMessageRead(e) {
+  addMessage("Received message: " + JSON.stringify(e.message));
+}
+
+function readNDEF() {
+  tag.readNDEF().then(function(record) { 
+    addMessage("Read ndef: " + JSON.stringify(record)); 
+    }, function(){ addMessage("Cannot read tag"); });
+}
+function writeTextNDEF() {
+  var text = new NDEFRecordText("hello world", "en-US", "UTF-8");
+  tag.writeNDEF(new NDEFMessage([text])).then();
+}
+
+function writeURINDEF() {
+  var uri = new NDEFRecordURI("http://www.intel.com");
+  tag.writeNDEF(new NDEFMessage([uri])).then();
+}
+
+function sendURINDEF() {
+  var uri = new NDEFRecordURI("http://www.google.com");
+  peer.sendNDEF(new NDEFMessage([uri])).then();
+}
+
+function writeMediaNDEF() {
+  var media = new NDEFRecordMedia("text/plain", [104, 101, 108, 108, 111]);
+  tag.writeNDEF(new NDEFMessage([media])).then();
+}
+
+function createNDEFRecord() {
+  var uri = new NDEFRecordURI("http://www.intel.com");
+  uri.getPayload().then(function(res){ addMessage("payload: " + res); },
+                        function(){ addMessage("getPayload Failed"); });
+}
+
+function powerOn() {
+  navigator.nfc.powerOn().then(function(){ addMessage("powerOn Succeeded"); },
+                               function(){ addMessage("powerOn Failed"); });
+}
+
+function powerOff() {
+  navigator.nfc.powerOff().then(function(){ addMessage("powerOff Succeeded"); },
+                                function(){ addMessage("powerOff Failed"); });
+}
+
+function startPoll() {
+  navigator.nfc.startPoll().then(function(){addMessage("startPoll Succeeded");},
+                                 function(){addMessage("startPoll Failed"); });
+}
+
+function stopPoll() {
+  navigator.nfc.stopPoll().then(function(){addMessage("stopPoll Succeeded");},
+                                function(){addMessage("stopPoll Failed"); });
+}
+
+</script>
+
+</body>
+</html>
diff --git a/nfc/README.md b/nfc/README.md
new file mode 100644 (file)
index 0000000..4b43113
--- /dev/null
@@ -0,0 +1,5 @@
+## Introduction
+This folder contains implementation of NFC API for Crosswalk runtime.
+API specification can be located at http://www.w3.org/TR/nfc/
+
+Backend that provides core functionality is capi-network-nfc
\ No newline at end of file
diff --git a/nfc/nfc.gyp b/nfc/nfc.gyp
new file mode 100644 (file)
index 0000000..0a84a51
--- /dev/null
@@ -0,0 +1,26 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_nfc',
+      'type': 'loadable_module',
+      'variables': {
+        'packages': [
+          'capi-network-nfc',
+        ],
+      },
+      'sources': [
+        'nfc_api.js',
+        'nfc_extension.cc',
+        'nfc_extension.h',
+        'nfc_instance.cc',
+        'nfc_instance.h',
+      ],
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+    },
+  ],
+}
diff --git a/nfc/nfc_api.js b/nfc/nfc_api.js
new file mode 100644 (file)
index 0000000..322c936
--- /dev/null
@@ -0,0 +1,480 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+///////////////////////////////////////////////////////////////////////////////
+// Utilities
+///////////////////////////////////////////////////////////////////////////////
+
+var g_next_async_call_id = 1;
+var g_async_calls = {};
+var v8tools = requireNative('v8tools');
+var connected_peer_ = null;
+
+function AsyncCall(resolve, reject) {
+  this.resolve = resolve;
+  this.reject = reject;
+}
+
+function createPromise(msg) {
+  var promise = new Promise(function(resolve, reject) {
+    g_async_calls[g_next_async_call_id] = new AsyncCall(resolve, reject);
+  });
+  msg.asyncCallId = g_next_async_call_id;
+  extension.postMessage(JSON.stringify(msg));
+  ++g_next_async_call_id;
+  return promise;
+}
+
+function _addConstProperty(obj, propertyKey, propertyValue) {
+  if (typeof propertyValue !== 'undefined')
+    Object.defineProperty(obj, propertyKey, {
+      configurable: true,
+      enumerable: true,
+      writable: false,
+      value: propertyValue
+    });
+}
+
+function _addHiddenProperty(obj, propertyKey, propertyValue) {
+  Object.defineProperty(obj, propertyKey, {
+    enumerable: false,
+    writable: true,
+    value: propertyValue
+  });
+}
+
+function _addConstructorProperty(obj, constructor) {
+  Object.defineProperty(obj, 'constructor', {
+    enumerable: false,
+    value: constructor
+  });
+}
+
+function derive(child, parent) {
+  child.prototype = Object.create(parent.prototype);
+  child.prototype.constructor = child;
+  _addConstructorProperty(child.prototype, child);
+}
+
+function EventTargetInterface(eventListeners, isValidType) {
+  _addHiddenProperty(this, 'listeners_', eventListeners);
+  _addHiddenProperty(this, 'isValidType_', isValidType);
+}
+
+EventTargetInterface.prototype.addEventListener = function(type, callback) {
+  if (callback != null && typeof callback === 'function' &&
+      this.isValidType_(type))
+    if (~~this.listeners_[type].indexOf(callback))
+      this.listeners_[type].push(callback);
+};
+
+EventTargetInterface.prototype.removeEventListener = function(type, callback) {
+  if (callback != null &&
+      typeof callback === 'function' && this.isValidType_(type)) {
+    var index = this.listeners_[type].indexOf(callback);
+    if (~index)
+      this.listeners_[type].slice(index, 1);
+  }
+};
+
+EventTargetInterface.prototype.dispatchEvent = function(event) {
+  var handled = true;
+
+  if (typeof event !== 'object' || !this.isValidType_(event.type))
+    return false;
+
+  this.listeners_[event.type].forEach(function(callback) {
+    var res = callback(event);
+    if (!res && handled)
+      handled = false;
+  });
+
+  return handled;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Extension message listener
+///////////////////////////////////////////////////////////////////////////////
+
+extension.setMessageListener(function(json) {
+  var msg = JSON.parse(json);
+  switch (msg.cmd) {
+    case 'poweron':
+      v8tools.forceSetProperty(g_nfc_manager, 'powered', true);
+      break;
+    case 'poweroff':
+      v8tools.forceSetProperty(g_nfc_manager, 'powered', false);
+      break;
+    case 'pollstart':
+      v8tools.forceSetProperty(g_nfc_manager, 'polling', true);
+      break;
+    case 'pollstop':
+      v8tools.forceSetProperty(g_nfc_manager, 'polling', false);
+      break;
+    case 'messageread':
+      handleMessageRead(msg);
+      break;
+    case 'readNDEF':
+      handleReadNDEF(msg);
+      break;
+    case 'sendNDEF':
+      handleAsyncCallSuccess(msg.asyncCallId);
+      break;
+    case 'getPayload':
+      handleAsyncCallSuccess(msg.asyncCallId, msg.result);
+      break;
+    case 'asyncCallError':
+      handleAsyncCallError(msg);
+      break;
+    default:
+      console.log('Received unknown command');
+      break;
+  }
+
+  if (msg.cmd in NFCManagerEventNames)
+    handleEvent(msg);
+});
+
+///////////////////////////////////////////////////////////////////////////////
+// NFCManager
+///////////////////////////////////////////////////////////////////////////////
+
+var NFCManagerEventNames = {
+  poweron: 0,
+  poweroff: 1,
+  pollstart: 2,
+  pollstop: 3,
+  tagfound: 4,
+  taglost: 5,
+  peerfound: 6,
+  peerlost: 7
+};
+
+function handleEvent(msg) {
+  if (msg.asyncCallId in g_async_calls) {
+    g_async_calls[msg.asyncCallId].resolve();
+    delete g_async_calls[msg.asyncCallId];
+  }
+  dispatchEventForName(msg.cmd);
+}
+
+function handleAsyncCallSuccess(callId, result) {
+  if (callId in g_async_calls) {
+    g_async_calls[callId].resolve(result);
+    delete g_async_calls[callId];
+  }
+}
+
+function toNDEFRecord(rec) {
+  var ndef = null;
+  switch (rec.recordType) {
+    case 'text':
+      ndef = new NDEFRecordText(rec.text, rec.languageCode, rec.encoding);
+      break;
+    case 'uri':
+      ndef = new NDEFRecordURI(rec.uri);
+      break;
+    case 'media':
+      ndef = new NDEFRecordMedia(rec.mimeType, rec.payload);
+      break;
+    case 'smartPoster':
+    default:
+      ndef = new NDEFRecord(rec.recordType, rec.tnf,
+          rec.type, rec.payload, rec.id);
+      break;
+  }
+  v8tools.forceSetProperty(ndef, 'payload', rec.payload);
+  return ndef;
+}
+
+function handleReadNDEF(msg) {
+  handleAsyncCallSuccess(msg.asyncCallId, toNDEFRecord(msg.result[0]));
+}
+
+function handleAsyncCallError(msg) {
+  if (msg.asyncCallId in g_async_calls) {
+    g_async_calls[msg.asyncCallId].reject(Error('Async operation failed'));
+    delete g_async_calls[msg.asyncCallId];
+  }
+}
+
+function dispatchEventForName(eventName) {
+  var event = new CustomEvent(eventName);
+  if (eventName === 'tagfound')
+    _addConstProperty(event, 'tag', new NFCTag());
+  else if (eventName === 'peerfound')
+    _addConstProperty(event, 'peer', connected_peer_ = new NFCPeer());
+  else if (eventName === 'peerlost')
+    connected_peer_ = null;
+  dispatchEvent(event, eventName);
+}
+
+function dispatchEvent(event, eventName) {
+  g_nfc_manager.dispatchEvent(event);
+  if (g_nfc_manager[eventName] &&
+      typeof g_nfc_manager[eventName] === 'function')
+    g_nfc_manager[eventName](event);
+}
+
+function NFCManager() {
+  var nfc_manager_listeners = {};
+  for (var key in NFCManagerEventNames)
+    nfc_manager_listeners[key] = [];
+
+  EventTargetInterface.call(this,
+      nfc_manager_listeners,
+      function(type) {return type in NFCManagerEventNames;});
+  var is_powered = JSON.parse(extension.internal.sendSyncMessage(
+      JSON.stringify({cmd: 'is_powered'})));
+  _addConstProperty(this, 'powered', is_powered);
+  _addConstProperty(this, 'polling', false);
+  this.onpoweron = null;
+  this.onpoweroff = null;
+  this.onpollstart = null;
+  this.onpollstop = null;
+  this.ontagfound = null;
+  this.ontaglost = null;
+  this.onpeerfound = null;
+  this.onpeerlost = null;
+}
+derive(NFCManager, EventTargetInterface);
+
+NFCManager.prototype.powerOn = function() {
+  return createPromise({'cmd': 'poweron'});
+};
+
+NFCManager.prototype.powerOff = function() {
+  return createPromise({'cmd': 'poweroff'});
+};
+
+NFCManager.prototype.startPoll = function() {
+  return createPromise({'cmd': 'pollstart'});
+};
+
+NFCManager.prototype.stopPoll = function() {
+  return createPromise({'cmd': 'pollstop'});
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// NFC - NFCTag
+///////////////////////////////////////////////////////////////////////////////
+
+function NFCTag() {}
+
+NFCTag.prototype.readNDEF = function() {
+  return createPromise({'cmd': 'readNDEF'});
+};
+
+// NDEFMessage message
+NFCTag.prototype.writeNDEF = function(message) {
+  var msg = {
+    'cmd': 'writeNDEF',
+    'message': message
+  };
+  return createPromise(msg);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// NFC - NFCPeer
+///////////////////////////////////////////////////////////////////////////////
+
+function NFCPeer() {
+  var nfc_peer_listeners = {};
+  nfc_peer_listeners['messageread'] = [];
+  EventTargetInterface.call(this,
+      nfc_peer_listeners, function(type) { return type === 'messageread';});
+  this.onmessageread = null;
+}
+derive(NFCPeer, EventTargetInterface);
+
+// NDEFMessage message
+NFCPeer.prototype.sendNDEF = function(message) {
+  var msg = {
+    'cmd': 'sendNDEF',
+    'message': message
+  };
+  return createPromise(msg);
+};
+
+// HandoverType handoverType
+NFCPeer.prototype.startHandover = function(handoverType) {
+  var msg = {
+    'cmd': 'startHandover',
+    'handoverType': handoverType
+  };
+  return createPromise(msg);
+};
+
+function handleMessageRead(msg) {
+  if (connected_peer_ !== null) {
+    var ndefRecords = [];
+    msg.result.forEach(function(record) {
+      ndefRecords.push(toNDEFRecord(record));
+    });
+    var event = new CustomEvent('messageread');
+    var ndefMessage = new NDEFMessage(ndefRecords);
+    _addConstProperty(event, 'message', ndefMessage);
+    connected_peer_.dispatchEvent(event);
+    if (connected_peer_.onmessageread &&
+        typeof connected_peer_.onmessageread === 'function')
+      connected_peer_.onmessageread(ndefMessage);
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// NFC - NDEFMessage
+///////////////////////////////////////////////////////////////////////////////
+
+function NDEFMessage(data) {
+  var records = data;
+  if (Array.isArray(data) && data.length > 0 &&
+      typeof data[0] === 'number')
+    records = [new NDEFRecord('unknown', 5, null, data)];
+  _addConstProperty(this, 'records', records);
+}
+
+NDEFMessage.prototype.getBytes = function() {
+  var msg = {
+    'cmd': 'getBytes',
+    'records': records
+  };
+  return createPromise(msg);
+};
+
+window.NDEFMessage = NDEFMessage;
+
+///////////////////////////////////////////////////////////////////////////////
+// NFC - NDEFRecord
+// TNF types:
+// 0 (Empty), 1 (Well known), 2 (Media), 3 (URI), 4 (External), 5 (Unknown)
+///////////////////////////////////////////////////////////////////////////////
+
+// NDEFRecordType recordType
+// byte tnf
+// DOMString type
+// byte array
+// DOMString id
+
+function NDEFRecord(recordType, tnf, type, payload, id) {
+  _addConstProperty(this, 'recordType', recordType);
+  _addConstProperty(this, 'tnf', tnf);
+  _addConstProperty(this, 'type', type);
+  _addConstProperty(this, 'payload', payload);
+  _addConstProperty(this, 'id', id);
+}
+
+NDEFRecord.prototype.getPayload = function() {
+  var msg = {
+    'cmd': 'getPayload',
+    'record': this
+  };
+  return createPromise(msg);
+};
+
+window.NDEFRecord = NDEFRecord;
+
+///////////////////////////////////////////////////////////////////////////////
+// NFC - NDEFRecordText
+///////////////////////////////////////////////////////////////////////////////
+
+function NDEFRecordText(text, languageCode, encoding) {
+  NDEFRecord.call(this, 'text', 1, 'T');
+  _addConstProperty(this, 'text', text);
+  _addConstProperty(this, 'languageCode', languageCode);
+  _addConstProperty(this, 'encoding', encoding);
+}
+
+derive(NDEFRecordText, NDEFRecord);
+window.NDEFRecordText = NDEFRecordText;
+
+///////////////////////////////////////////////////////////////////////////////
+// NFC - NDEFRecordURI
+///////////////////////////////////////////////////////////////////////////////
+
+// DOMString uri
+function NDEFRecordURI(uri) {
+  NDEFRecord.call(this, 'uri', 1, 'U');
+  _addConstProperty(this, 'uri', uri);
+}
+
+derive(NDEFRecordURI, NDEFRecord);
+window.NDEFRecordURI = NDEFRecordURI;
+
+///////////////////////////////////////////////////////////////////////////////
+// NFC - NDEFRecordMedia
+///////////////////////////////////////////////////////////////////////////////
+
+// DOMString mimeType
+// byte array payload
+function NDEFRecordMedia(mimeType, payload) {
+  NDEFRecord.call(this, 'media', 2, mimeType, payload);
+  _addConstProperty(this, 'mimeType', mimeType);
+}
+
+derive(NDEFRecordMedia, NDEFRecord);
+window.NDEFRecordMedia = NDEFRecordMedia;
+
+///////////////////////////////////////////////////////////////////////////////
+// NFC - NDEFRecordSmartPoster
+///////////////////////////////////////////////////////////////////////////////
+
+// constructor
+// DOMString uri,
+// optional NDEFRecordText array titles,
+// optional DOMString action,
+// optional NDEFRecordMedia array icons,
+// optional unsigned long targetSize,
+// optional DOMString targetMIME
+
+function NDEFRecordSmartPoster(uri, titles, action,
+    icons, targetSize, targetMIME) {
+  NDEFRecord.call(this, 'smartPoster', 3, 'Sp');
+  _addConstProperty(this, 'uri', uri);
+  _addConstProperty(this, 'titles', titles);
+  _addConstProperty(this, 'action', action);
+  _addConstProperty(this, 'icons', icons);
+  _addConstProperty(this, 'targetSize', targetSize);
+  _addConstProperty(this, 'targetMIME', targetMIME);
+}
+
+derive(NDEFRecordSmartPoster, NDEFRecord);
+window.NDEFRecordSmartPoster = NDEFRecordSmartPoster;
+
+///////////////////////////////////////////////////////////////////////////////
+// NFC - NDEFRecordType
+///////////////////////////////////////////////////////////////////////////////
+
+var NDEFRecordType = {
+  text: 0,
+  uri: 1,
+  media: 2,
+  smartPoster: 3,
+  unknown: 4
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// NFC - SmartPosterAction
+///////////////////////////////////////////////////////////////////////////////
+
+var SmartPosterAction = {
+  do: 0,
+  save: 1,
+  open: 2
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// NFC - HandoverType
+///////////////////////////////////////////////////////////////////////////////
+
+var HandoverType = {
+  wifi: 0,
+  bluetooth: 1
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// NFCManager - Instance
+///////////////////////////////////////////////////////////////////////////////
+
+var g_nfc_manager = new NFCManager();
+exports = g_nfc_manager;
diff --git a/nfc/nfc_callbacks.h b/nfc/nfc_callbacks.h
new file mode 100644 (file)
index 0000000..236e2c9
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NFC_NFC_CALLBACKS_H_
+#define NFC_NFC_CALLBACKS_H_
+
+#include <string>
+
+typedef struct _ndef_message_s *nfc_ndef_message_h;
+
+struct CallbackData {
+  CallbackData(void* data, double async_id,
+      const std::string& event_name, nfc_ndef_message_h message = 0)
+      : data_(data),
+        async_id_(async_id),
+        event_name_(event_name),
+        message_(message) {}
+  void* data_;
+  double async_id_;
+  std::string event_name_;
+  nfc_ndef_message_h message_;
+};
+
+#define CALLBACK_METHOD(METHOD, ARG0, DATA_TYPE)                               \
+  static void METHOD ## CallBack(ARG0 res, void* userdata) {                   \
+    reinterpret_cast<DATA_TYPE*>(userdata)->METHOD(res);                       \
+  }                                                                            \
+                                                                               \
+  void METHOD(ARG0);
+
+#define CALLBACK_METHOD_2(METHOD, ARG0, ARG1, DATA_TYPE)                       \
+  static void METHOD ## CallBack(ARG0 arg0, ARG1 arg1, void* userdata) {       \
+    reinterpret_cast<DATA_TYPE*>(userdata)->METHOD(arg0, arg1);                \
+  }                                                                            \
+                                                                               \
+  void METHOD(ARG0, ARG1);
+
+#define CALLBACK_METHOD_WITH_DATA(METHOD, ARG0, DATA_TYPE)                     \
+  static void METHOD ## CallBack(ARG0 res, void* userdata) {                   \
+    CallbackData* d = static_cast<CallbackData*>(userdata);                    \
+    DATA_TYPE* data = reinterpret_cast<DATA_TYPE*>(d->data_);                  \
+    data->METHOD(res, d);                                                      \
+    delete d;                                                                  \
+  }                                                                            \
+                                                                               \
+  void METHOD(ARG0, CallbackData* cd);
+
+#define CALLBACK_METHOD_WITH_DATA_2(METHOD, ARG0, ARG1, DATA_TYPE)             \
+  static void METHOD ## CallBack(ARG0 arg0, ARG1 arg1, void* userdata) {       \
+    CallbackData* d = static_cast<CallbackData*>(userdata);                    \
+    DATA_TYPE* data = reinterpret_cast<DATA_TYPE*>(d->data_);                  \
+    data->METHOD(arg0, arg1, d);                                               \
+    delete d;                                                                  \
+  }                                                                            \
+                                                                               \
+  void METHOD(ARG0, ARG1, CallbackData* cd);
+
+#endif  // NFC_NFC_CALLBACKS_H_
diff --git a/nfc/nfc_extension.cc b/nfc/nfc_extension.cc
new file mode 100644 (file)
index 0000000..608f08e
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "nfc/nfc_extension.h"
+
+#include "nfc/nfc_instance.h"
+
+common::Extension* CreateExtension() {
+  return new NfcExtension;
+}
+
+extern const char kSource_nfc_api[];
+
+NfcExtension::NfcExtension() {
+  SetExtensionName("navigator.nfc");
+  SetJavaScriptAPI(kSource_nfc_api);
+  const char* entry_points[] = {
+    "window.NDEFMessage",
+    "window.NDEFRecord",
+    "window.NDEFRecordText",
+    "window.NDEFRecordURI",
+    "window.NDEFRecordMedia",
+    "window.NDEFRecordSmartPoster",
+    NULL
+  };
+  SetExtraJSEntryPoints(entry_points);
+}
+
+NfcExtension::~NfcExtension() {}
+
+common::Instance* NfcExtension::CreateInstance() {
+  return new NfcInstance;
+}
diff --git a/nfc/nfc_extension.h b/nfc/nfc_extension.h
new file mode 100644 (file)
index 0000000..92d4bd0
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NFC_NFC_EXTENSION_H_
+#define NFC_NFC_EXTENSION_H_
+
+#include "common/extension.h"
+
+class NfcExtension : public common::Extension {
+ public:
+  NfcExtension();
+  virtual ~NfcExtension();
+
+ private:
+  // common::Extension implementation.
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // NFC_NFC_EXTENSION_H_
diff --git a/nfc/nfc_instance.cc b/nfc/nfc_instance.cc
new file mode 100644 (file)
index 0000000..c9a9261
--- /dev/null
@@ -0,0 +1,527 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "nfc/nfc_instance.h"
+
+#include <string>
+
+#include "common/picojson.h"
+
+namespace {
+
+const char kTypeText[] = "T";
+const char kTypeSmartPoster[] = "Sp";
+const char kTypeUri[] = "U";
+const char kTypeMime[] = "mime";
+const char kTypeAlternativeCarrier[] = "ac";
+const char kTypeHandoverCarrier[] = "Hc";
+const char kTypeHandoverRequest[] = "Hr";
+const char kTypeHandoverSelect[] = "Hs";
+
+const char kJSTypeText[] = "text";
+const char kJSTypeUri[] = "uri";
+const char kJSTypeMedia[] = "media";
+const char kJSTypeSmartPoster[] = "smartPoster";
+const char kJSTypeUnknown[] = "unknown";
+
+std::string NfcRecordTypeToJsType(const std::string& type) {
+  if (type == kTypeText)
+    return kJSTypeText;
+  else if (type == kTypeSmartPoster)
+    return kJSTypeSmartPoster;
+  else if (type == kTypeUri)
+    return kJSTypeUri;
+  else if (type == kTypeMime)
+    return kJSTypeMedia;
+  else if (type.empty())
+    return kJSTypeUnknown;
+  else
+    return type;
+}
+
+void SetTextProperties(nfc_ndef_record_h record,
+    picojson::object& out_value) {
+  char* text = NULL;
+  if (nfc_ndef_record_get_text(record, &text) == NFC_ERROR_NONE)
+    out_value["text"] = picojson::value(text);
+
+  char* lang_code = NULL;
+  if (nfc_ndef_record_get_langcode(record, &lang_code) == NFC_ERROR_NONE)
+    out_value["languageCode"] = picojson::value(lang_code);
+
+  nfc_encode_type_e encode;
+  if (nfc_ndef_record_get_encode_type(record, &encode) == NFC_ERROR_NONE)
+    out_value["encoding"] =
+        picojson::value(encode == NFC_ENCODE_UTF_8 ? "UTF-8" : "UTF-16");
+}
+
+void SetUriProperties(nfc_ndef_record_h record,
+    picojson::object& out_value) {
+  char* uri = NULL;
+  if (nfc_ndef_record_get_uri(record, &uri) == NFC_ERROR_NONE) {
+    out_value["uri"] = picojson::value(uri);
+    free(uri);
+  }
+}
+
+void SetMIMEProperties(nfc_ndef_record_h record,
+    picojson::object& out_value) {
+  char* mime_type = NULL;
+  if (nfc_ndef_record_get_mime_type(record, &mime_type) == NFC_ERROR_NONE) {
+    out_value["mimeType"] = picojson::value(mime_type);
+    free(mime_type);
+  }
+}
+
+void SetType(const std::string& type, picojson::object& out_value) {
+  out_value["recordType"] = picojson::value(NfcRecordTypeToJsType(type));
+}
+
+void SetTnf(nfc_record_tnf_e tnf, picojson::object& out_value) {
+  out_value["tnf"] = picojson::value(static_cast<double>(tnf));
+}
+
+void SetId(nfc_ndef_record_h record, picojson::object& out_value) {
+  unsigned char* id = NULL;
+  int id_size = 0;
+  int err = nfc_ndef_record_get_id(record, &id, &id_size);
+  if (err == NFC_ERROR_NONE && id_size > 0)
+    out_value["id"] =
+        picojson::value(std::string(reinterpret_cast<char*>(id), id_size));
+}
+
+void SetPayload(nfc_ndef_record_h record, picojson::object& out_value) {
+  unsigned char* payload = NULL;
+  unsigned int payload_size = 0;
+  int err = nfc_ndef_record_get_payload(record, &payload, &payload_size);
+  if (err == NFC_ERROR_NONE) {
+    picojson::array array;
+    for (int i = 0; i < payload_size; i++)
+      array.push_back(picojson::value(static_cast<double>(payload[i])));
+    out_value["payload"] = picojson::value(array);
+  }
+}
+
+int NdefRecordToJson(nfc_ndef_record_h record,
+    picojson::value& out_value) {
+  picojson::object json_record;
+  nfc_record_tnf_e tnf;
+  int ret = nfc_ndef_record_get_tnf(record, &tnf);
+  if (ret != NFC_ERROR_NONE)
+    return ret;
+
+  unsigned char* type = 0;
+  int type_size = 0;
+  nfc_ndef_record_get_type(record, &type, &type_size);
+
+  std::string type_str(reinterpret_cast<char*>(type), type_size);
+  SetType(type_str, json_record);
+  SetTnf(tnf, json_record);
+  SetId(record, json_record);
+  SetPayload(record, json_record);
+
+  switch (tnf) {
+    case NFC_RECORD_TNF_WELL_KNOWN:
+      if (type_str == kTypeText)
+        SetTextProperties(record, json_record);
+      else if (type_str == kTypeUri)
+        SetUriProperties(record, json_record);
+      break;
+    case NFC_RECORD_TNF_MIME_MEDIA:
+      SetType(kJSTypeMedia, json_record);
+      SetMIMEProperties(record, json_record);
+      break;
+    case NFC_RECORD_TNF_URI:
+      SetUriProperties(record, json_record);
+      break;
+  }
+
+  if (ret == NFC_ERROR_NONE)
+    out_value = picojson::value(json_record);
+
+  return ret;
+}
+
+int NdefMessageToJson(nfc_ndef_message_h message,
+    picojson::value& out_value) {
+  picojson::value::array records;
+  int record_count = 0;
+  int ret = nfc_ndef_message_get_record_count(message, &record_count);
+  if (ret == NFC_ERROR_NONE) {
+    for (int i = 0; i < record_count; i++) {
+      nfc_ndef_record_h record = NULL;
+      ret = nfc_ndef_message_get_record(message, i, &record);
+      picojson::value json_record;
+      if (ret == NFC_ERROR_NONE
+          && NdefRecordToJson(record, json_record) == NFC_ERROR_NONE)
+        records.push_back(json_record);
+      else
+        break;
+    }
+  }
+
+  if (ret == NFC_ERROR_NONE)
+    out_value = picojson::value(records);
+  return ret;
+}
+
+int CreateTextRecord(nfc_ndef_record_h* out_ndef_record,
+    const picojson::value& record) {
+  return nfc_ndef_record_create_text(out_ndef_record,
+      record.get("text").to_str().c_str(),
+      record.get("languageCode").to_str().c_str(),
+      record.get("encoding").to_str() == "UTF-8" ? NFC_ENCODE_UTF_8
+                                                 : NFC_ENCODE_UTF_16);
+}
+
+int CreateUriRecord(nfc_ndef_record_h* out_ndef_record,
+    const picojson::value& record) {
+  return nfc_ndef_record_create_uri(out_ndef_record,
+      record.get("uri").to_str().c_str());
+}
+
+int CreateMediaRecord(nfc_ndef_record_h* out_ndef_record,
+    const picojson::value& record) {
+  picojson::array payload = record.get("payload").get<picojson::array>();
+  size_t payload_size = payload.size();
+  unsigned char* data = new unsigned char[payload_size];
+
+  for (size_t i = 0; i < payload_size; i++)
+    data[i] = static_cast<unsigned char>(payload[i].get<double>());
+
+  int ret = nfc_ndef_record_create_mime(out_ndef_record,
+      record.get("mimeType").to_str().c_str(), data, payload_size);
+
+  delete[] data;
+  return ret;
+}
+
+int JsonRecordToNdefRecord(const picojson::value& record,
+    nfc_ndef_record_h* out_ndef_record) {
+  if (!record.is<picojson::object>())
+    return NFC_ERROR_INVALID_PARAMETER;
+
+  int ret = NFC_ERROR_NONE;
+  std::string recordType = record.get("recordType").to_str();
+  if (recordType == kJSTypeText)
+    ret = CreateTextRecord(out_ndef_record, record);
+  else if (recordType == kJSTypeUri)
+    ret = CreateUriRecord(out_ndef_record, record);
+  else if (recordType == kJSTypeMedia)
+    ret = CreateMediaRecord(out_ndef_record, record);
+  else if (recordType == kJSTypeSmartPoster)
+    // TODO(shalamov): Not implemented.
+    ret = NFC_ERROR_INVALID_PARAMETER;
+  else if (recordType == kJSTypeUnknown)
+    // TODO(shalamov): Not implemented.
+    ret = NFC_ERROR_INVALID_PARAMETER;
+
+  return ret;
+}
+
+int JsonMessageToNdefMessage(const picojson::value& message,
+    nfc_ndef_message_h* out_ndef_message) {
+  if (!message.is<picojson::array>())
+    return NFC_ERROR_INVALID_PARAMETER;
+
+  int ret = nfc_ndef_message_create(out_ndef_message);
+  if (ret != NFC_ERROR_NONE)
+    return ret;
+
+  picojson::array records = message.get<picojson::array>();
+  picojson::array::const_iterator it = records.begin();
+  picojson::array::const_iterator end = records.end();
+  while (it != end) {
+    nfc_ndef_record_h ndef_record = NULL;
+    ret = JsonRecordToNdefRecord(*it, &ndef_record);
+    if (ret == NFC_ERROR_NONE) {
+      ret = nfc_ndef_message_append_record(*out_ndef_message, ndef_record);
+      it++;
+    } else {
+      nfc_ndef_message_destroy(*out_ndef_message);
+      break;
+    }
+  }
+
+  return ret;
+}
+
+}  // namespace
+
+NfcInstance::NfcInstance()
+    : nfc_manager_activated_(nfc_manager_is_activated()) {
+  nfc_manager_init_code_ = nfc_manager_initialize_sync();
+  nfc_manager_set_activation_changed_cb(OnActivationChangedCallBack, this);
+}
+
+NfcInstance::~NfcInstance() {
+}
+
+void NfcInstance::HandleMessage(const char* message) {
+  picojson::value v;
+
+  std::string err;
+  picojson::parse(v, message, message + strlen(message), &err);
+  if (!err.empty())
+    return;
+
+  if (nfc_manager_init_code_) {
+    PostError(v.get("asyncCallId").get<double>());
+    return;
+  }
+
+  std::string cmd = v.get("cmd").to_str();
+  if (cmd == "poweron")
+    SwitchPower(true, v);
+  else if (cmd == "poweroff")
+    SwitchPower(false, v);
+  else if (cmd == "pollstart")
+    PollStart(v);
+  else if (cmd == "pollstop")
+    PollStop(v);
+  else if (cmd == "readNdef")
+    ReadNdef(v);
+  else if (cmd == "writeNdef")
+    WriteNdef(v);
+  else if (cmd == "sendNdef")
+    SendNdef(v);
+  else if (cmd == "startHandover")
+    StartHandover(v);
+  else if (cmd == "getBytes")
+    GetBytes(v);
+  else if (cmd == "getPayload")
+    GetPayload(v);
+  else
+    std::cerr << "Received unknown message: " << cmd << "\n";
+}
+
+void NfcInstance::HandleSyncMessage(const char* message) {
+  picojson::value v;
+
+  std::string err;
+  picojson::parse(v, message, message + strlen(message), &err);
+  if (!err.empty()) {
+    return;
+  }
+
+  std::string cmd = v.get("cmd").to_str();
+  if (cmd == "is_powered")
+    SendSyncReply(picojson::value(nfc_manager_activated_).to_str().c_str());
+  else
+    std::cerr << "Ignoring unknown command: " << cmd;
+}
+
+void NfcInstance::SwitchPower(bool state, const picojson::value& value) {
+  double async_call_id = value.get("asyncCallId").get<double>();
+  CallbackData* cd =
+      new CallbackData(this, async_call_id, value.get("cmd").to_str());
+  int ret = nfc_manager_set_activation(state, OnPoweredCallBack, cd);
+  if (ret != NFC_ERROR_NONE) {
+    PostError(async_call_id);
+    delete cd;
+  }
+}
+
+void NfcInstance::PollStart(const picojson::value& value) {
+  nfc_manager_set_tag_discovered_cb(OnTagDiscoveredCallBack, this);
+  nfc_manager_set_p2p_target_discovered_cb(OnP2PDiscoveredCallBack, this);
+  PostSuccess("pollstart", value.get("asyncCallId").get<double>());
+}
+
+void NfcInstance::PollStop(const picojson::value& value) {
+  nfc_manager_unset_tag_discovered_cb();
+  nfc_manager_unset_p2p_target_discovered_cb();
+  PostSuccess("pollstop", value.get("asyncCallId").get<double>());
+}
+
+void NfcInstance::ReadNdef(const picojson::value& value) {
+  double async_id = value.get("asyncCallId").get<double>();
+  int ret = NFC_ERROR_NONE;
+  if (attached_tag_) {
+    bool ndef_supported = false;
+    ret = nfc_tag_is_support_ndef(attached_tag_, &ndef_supported);
+    if (ret == NFC_ERROR_NONE && ndef_supported) {
+      CallbackData* cd = new CallbackData(this, async_id, "readNdef");
+      ret = nfc_tag_read_ndef(attached_tag_, OnReadNdefCallBack, cd);
+      if (ret != NFC_ERROR_NONE)
+        delete cd;
+    }
+  }
+
+  if (ret != NFC_ERROR_NONE)
+    PostError(async_id);
+}
+
+void NfcInstance::WriteNdef(const picojson::value& value) {
+  double async_id = value.get("asyncCallId").get<double>();
+  nfc_ndef_message_h ndef_message = NULL;
+  picojson::value message = value.get("message");
+  int ret = JsonMessageToNdefMessage(message.get("records"), &ndef_message);
+  if (ret == NFC_ERROR_NONE) {
+    CallbackData* cd =
+        new CallbackData(this, async_id, "writeNdef", ndef_message);
+    ret = nfc_tag_write_ndef(attached_tag_, ndef_message,
+        OnWriteNdefCallBack, cd);
+    if (ret != NFC_ERROR_NONE) {
+      nfc_ndef_message_destroy(ndef_message);
+      delete cd;
+    }
+  }
+
+  if (ret != NFC_ERROR_NONE)
+    PostError(async_id);
+}
+
+void NfcInstance::SendNdef(const picojson::value& value) {
+  double async_id = value.get("asyncCallId").get<double>();
+  nfc_ndef_message_h ndef_message = NULL;
+  picojson::value message = value.get("message");
+  int ret = JsonMessageToNdefMessage(message.get("records"), &ndef_message);
+  if (ret == NFC_ERROR_NONE) {
+    CallbackData* cd =
+        new CallbackData(this, async_id, "sendNdef", ndef_message);
+    ret = nfc_p2p_send(connected_peer_, ndef_message,
+        OnP2PMessageSentCallBack, cd);
+    if (ret != NFC_ERROR_NONE) {
+      nfc_ndef_message_destroy(ndef_message);
+      delete cd;
+    }
+  }
+
+  if (ret != NFC_ERROR_NONE)
+    PostError(async_id);
+}
+
+void NfcInstance::StartHandover(const picojson::value& value) {
+  // TODO(shalamov): Not implemented.
+}
+
+void NfcInstance::GetBytes(const picojson::value& value) {
+  // TODO(shalamov): Not implemented.
+}
+
+void NfcInstance::GetPayload(const picojson::value& value) {
+  double async_id = value.get("asyncCallId").get<double>();
+  if (value.contains("record")
+     && value.get("record").contains("payload")) {
+    PostResult("getPayload",
+        value.get("record").get("payload"), async_id);
+  } else {
+    nfc_ndef_record_h out_ndef_record;
+    int ret = JsonRecordToNdefRecord(value.get("record"), &out_ndef_record);
+    if (ret == NFC_ERROR_NONE) {
+      picojson::object payload;
+      SetPayload(out_ndef_record, payload);
+      nfc_ndef_record_destroy(out_ndef_record);
+      PostResult("getPayload", picojson::value(payload["payload"]), async_id);
+    } else {
+      PostError(async_id);
+    }
+  }
+}
+
+void NfcInstance::PostError(double async_operation_id) {
+  PostResult("asyncCallError", async_operation_id);
+}
+
+void NfcInstance::PostSuccess(const std::string& event,
+    double async_operation_id) {
+  PostResult(event, async_operation_id);
+}
+
+void NfcInstance::PostResult(
+    const std::string& command,
+    double async_operation_id) {
+  picojson::value::object object;
+  object["cmd"] = picojson::value(command);
+  object["asyncCallId"] = picojson::value(async_operation_id);
+  picojson::value value(object);
+  PostMessage(value.serialize().c_str());
+}
+
+void NfcInstance::PostResult(
+    const std::string& command,
+    const picojson::value& result,
+    double async_operation_id) {
+  picojson::value::object object;
+  object["cmd"] = picojson::value(command);
+  object["result"] = picojson::value(result);
+  object["asyncCallId"] = picojson::value(async_operation_id);
+  picojson::value value(object);
+  PostMessage(value.serialize().c_str());
+}
+
+void NfcInstance::OnActivationChanged(bool activated) {
+  nfc_manager_activated_ = activated;
+  nfc_manager_activated_ ? PostSuccess("poweron") :
+                           PostSuccess("poweroff");
+}
+
+void NfcInstance::OnPowered(nfc_error_e error, CallbackData* cd) {
+  error == NFC_ERROR_NONE ? PostSuccess(cd->event_name_, cd->async_id_)
+                          : PostError(cd->async_id_);
+}
+
+void NfcInstance::OnTagDiscovered(nfc_discovered_type_e type, nfc_tag_h tag) {
+  if (type == NFC_DISCOVERED_TYPE_ATTACHED) {
+    attached_tag_ = tag;
+    PostSuccess("tagfound");
+  } else {
+    attached_tag_ = NULL;
+    PostSuccess("taglost");
+  }
+}
+
+void NfcInstance::OnP2PDiscovered(nfc_discovered_type_e type,
+    nfc_p2p_target_h target) {
+  if (type == NFC_DISCOVERED_TYPE_ATTACHED) {
+    connected_peer_ = target;
+    CallbackData* cd = new CallbackData(this, 0, "messageread");
+    if (nfc_p2p_set_data_received_cb(connected_peer_,
+        OnP2PDataRecievedCallBack, cd) == NFC_ERROR_NONE)
+      PostSuccess("peerfound");
+    else
+      delete cd;
+  } else {
+    nfc_p2p_unset_data_received_cb(connected_peer_);
+    connected_peer_ = NULL;
+    PostSuccess("peerlost");
+  }
+}
+
+void NfcInstance::OnReadNdef(nfc_error_e result,
+    nfc_ndef_message_h message, CallbackData* cd) {
+  picojson::value retval;
+  if (result == NFC_ERROR_NONE
+      && NdefMessageToJson(message, retval) == NFC_ERROR_NONE)
+    PostResult(cd->event_name_, retval, cd->async_id_);
+  else
+    PostError(cd->async_id_);
+}
+
+void NfcInstance::OnWriteNdef(nfc_error_e result, CallbackData* cd) {
+  if (result == NFC_ERROR_NONE) {
+    PostSuccess(cd->event_name_, cd->async_id_);
+    nfc_ndef_message_destroy(cd->message_);
+  } else {
+    PostError(cd->async_id_);
+  }
+}
+
+void NfcInstance::OnP2PDataRecieved(nfc_p2p_target_h target,
+    nfc_ndef_message_h message, CallbackData* cd) {
+  picojson::value retval;
+  if (target == connected_peer_
+      && NdefMessageToJson(message, retval) == NFC_ERROR_NONE)
+    PostResult(cd->event_name_, retval, cd->async_id_);
+}
+
+void NfcInstance::OnP2PMessageSent(nfc_error_e result, CallbackData* cd) {
+  if (result == NFC_ERROR_NONE) {
+    PostSuccess(cd->event_name_, cd->async_id_);
+    nfc_ndef_message_destroy(cd->message_);
+  } else {
+    PostError(cd->async_id_);
+  }
+}
diff --git a/nfc/nfc_instance.h b/nfc/nfc_instance.h
new file mode 100644 (file)
index 0000000..3f5d7d5
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NFC_NFC_INSTANCE_H_
+#define NFC_NFC_INSTANCE_H_
+
+#include <nfc.h>
+#include <string>
+#include "common/extension.h"
+#include "nfc/nfc_callbacks.h"
+
+namespace picojson {
+
+class value;
+
+}  // namespace picojson
+
+class NfcInstance : public common::Instance {
+ public:
+  NfcInstance();
+  virtual ~NfcInstance();
+
+ private:
+  // common::Instance implementation.
+  virtual void HandleMessage(const char* msg);
+  virtual void HandleSyncMessage(const char* msg);
+
+  void PollStart(const picojson::value& value);
+  void PollStop(const picojson::value& value);
+  void ReadNdef(const picojson::value& value);
+  void WriteNdef(const picojson::value& value);
+  void SendNdef(const picojson::value& value);
+  void StartHandover(const picojson::value& value);
+  void GetBytes(const picojson::value& value);
+  void GetPayload(const picojson::value& value);
+
+  void SwitchPower(bool state, const picojson::value& value);
+  void PostError(double async_operation_id);
+  void PostSuccess(const std::string& event, double async_operation_id = 0);
+  void PostResult(const std::string& command, double async_operation_id);
+  void PostResult(const std::string& command, const picojson::value& value,
+      double async_operation_id);
+
+  CALLBACK_METHOD(OnActivationChanged, bool, NfcInstance);
+  CALLBACK_METHOD_2(OnTagDiscovered, nfc_discovered_type_e,
+      nfc_tag_h, NfcInstance);
+  CALLBACK_METHOD_2(OnP2PDiscovered, nfc_discovered_type_e,
+      nfc_p2p_target_h, NfcInstance);
+  CALLBACK_METHOD_WITH_DATA(OnPowered, nfc_error_e, NfcInstance);
+  CALLBACK_METHOD_WITH_DATA_2(OnReadNdef, nfc_error_e,
+      nfc_ndef_message_h, NfcInstance);
+  CALLBACK_METHOD_WITH_DATA(OnWriteNdef, nfc_error_e, NfcInstance);
+  CALLBACK_METHOD_WITH_DATA_2(OnP2PDataRecieved, nfc_p2p_target_h,
+      nfc_ndef_message_h, NfcInstance);
+  CALLBACK_METHOD_WITH_DATA(OnP2PMessageSent, nfc_error_e, NfcInstance);
+
+ private:
+  int nfc_manager_init_code_ = 0;
+  bool nfc_manager_activated_ = false;
+  nfc_tag_h attached_tag_ = NULL;
+  nfc_p2p_target_h connected_peer_ = NULL;
+};
+
+#endif  // NFC_NFC_INSTANCE_H_
index 51f1625..0a76175 100644 (file)
@@ -31,6 +31,7 @@ BuildRequires: pkgconfig(capi-appfw-app-manager)
 BuildRequires: pkgconfig(capi-appfw-package-manager)
 BuildRequires: pkgconfig(capi-network-bluetooth)
 BuildRequires: pkgconfig(capi-network-connection)
+BuildRequires: pkgconfig(capi-network-nfc)
 BuildRequires: pkgconfig(capi-system-device)
 BuildRequires: pkgconfig(capi-system-info)
 BuildRequires: pkgconfig(capi-system-power)
index 52d9080..03f2ed4 100644 (file)
@@ -32,6 +32,7 @@
             'download/download.gyp:*',
             'filesystem/filesystem.gyp:*',
             'messageport/messageport.gyp:*',
+            'nfc/nfc.gyp:*',
           ],
         }],
         [ 'extension_host_os == "mobile"', {