summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/app/generated_resources.grd88
-rw-r--r--chrome/browser/browser_resources.grd3
-rw-r--r--chrome/browser/resources/chromeos/nfc_debug.css85
-rw-r--r--chrome/browser/resources/chromeos/nfc_debug.html130
-rw-r--r--chrome/browser/resources/chromeos/nfc_debug.js375
-rw-r--r--chrome/browser/ui/webui/DEPS1
-rw-r--r--chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc3
-rw-r--r--chrome/browser/ui/webui/chromeos/nfc_debug_ui.cc752
-rw-r--r--chrome/browser/ui/webui/chromeos/nfc_debug_ui.h23
-rw-r--r--chrome/chrome_browser_ui.gypi3
-rw-r--r--chrome/common/url_constants.cc2
-rw-r--r--chrome/common/url_constants.h2
12 files changed, 1467 insertions, 0 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 225f0d2..b7c3a2d 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -15476,6 +15476,94 @@ Do you accept?
</message>
</if>
+ <!-- About NFC Debug UI display strings -->
+ <if expr="pp_ifdef('chromeos')">
+ <message name="IDS_NFC_DEBUG_TITLE" desc="Title of the debug page meant for developers to test NFC functionality">
+ NFC API Test Page
+ </message>
+ <message name="IDS_NFC_DEBUG_NOT_SUPPORTED" desc="Message shown if the NFC API is not supported on platform">
+ NFC is not supported on the current platform.
+ </message>
+ <message name="IDS_NFC_DEBUG_ADAPTER_HEADER" desc="Header of the 'NFC Adapter' box, that shows the state of the NFC adapter">
+ NFC Adapter
+ </message>
+ <message name="IDS_NFC_DEBUG_ADAPTER_POWER_ON" desc="Adapter power button text to turn the adapter on">
+ Power ON
+ </message>
+ <message name="IDS_NFC_DEBUG_ADAPTER_POWER_OFF" desc="Adapter power button text to turn the adapter off">
+ Power OFF
+ </message>
+ <message name="IDS_NFC_DEBUG_ADAPTER_START_POLL" desc="Adapter poll button text to start polling">
+ Start Poll
+ </message>
+ <message name="IDS_NFC_DEBUG_ADAPTER_STOP_POLL" desc="Adapter poll button text to stop polling">
+ Stop Poll
+ </message>
+ <message name="IDS_NFC_DEBUG_NDEF_FORM_HEADER" desc="Header of the 'NFC NDEF message form' box used send a message to tag/peer">
+ Push/Write NDEF Message
+ </message>
+ <message name="IDS_NFC_DEBUG_NDEF_FORM_TYPE_TEXT" desc="NDEF message form dropdown menu item for message type 'Text'">
+ Text
+ </message>
+ <message name="IDS_NFC_DEBUG_NDEF_FORM_TYPE_URI" desc="NDEF message form dropdown menu item for message type 'URI'">
+ URI
+ </message>
+ <message name="IDS_NFC_DEBUG_NDEF_FORM_TYPE_SMART_POSTER" desc="NDEF message form dropdown menu text for message type 'SmartPoster'">
+ SmartPoster
+ </message>
+ <message name="IDS_NFC_DEBUG_NDEF_FORM_FIELD_TEXT" desc="Label for required input field 'Text'">
+ Text (required):
+ </message>
+ <message name="IDS_NFC_DEBUG_NDEF_FORM_FIELD_ENCODING" desc="Label for required input field 'Encoding'">
+ Encoding (required):
+ </message>
+ <message name="IDS_NFC_DEBUG_NDEF_FORM_FIELD_LANGUAGE_CODE" desc="Label for required input field 'Language Code'">
+ Language Code (required):
+ </message>
+ <message name="IDS_NFC_DEBUG_NDEF_FORM_FIELD_URI" desc="Label for required input field 'URI'">
+ URI (required):
+ </message>
+ <message name="IDS_NFC_DEBUG_NDEF_FORM_FIELD_MIME_TYPE" desc="Label for input field 'MIME Type'">
+ MIME Type:
+ </message>
+ <message name="IDS_NFC_DEBUG_NDEF_FORM_FIELD_TARGET_SIZE" desc="Label for input field 'Target Size'">
+ Target Size:
+ </message>
+ <message name="IDS_NFC_DEBUG_NDEF_FORM_FIELD_TITLE_TEXT" desc="Label for required input field 'Title Text'">
+ Title Text (required):
+ </message>
+ <message name="IDS_NFC_DEBUG_NDEF_FORM_FIELD_TITLE_ENCODING" desc="Label for required input field 'Title Encoding'">
+ Title Encoding (required):
+ </message>
+ <message name="IDS_NFC_DEBUG_NDEF_FORM_FIELD_TITLE_LANGUAGE_CODE" desc="Label for required input field 'Title Language Code'">
+ Title Language Code (required):
+ </message>
+ <message name="IDS_NFC_DEBUG_NDEF_FORM_WRITE_BUTTON" desc="NDEF message form button text for writing message to an NFC tag">
+ Write to Tag
+ </message>
+ <message name="IDS_NFC_DEBUG_NDEF_FORM_PUSH_BUTTON" desc="NDEF message form button text for pushing a message to an NFC peer device">
+ Push to Peer
+ </message>
+ <message name="IDS_NFC_DEBUG_NFC_PEER_HEADER" desc="Header of the 'NFC Peer' box">
+ NDEF Peer
+ </message>
+ <message name="IDS_NFC_DEBUG_NFC_TAG_HEADER" desc="Header of the 'NFC Tag' box">
+ NDEF Tag
+ </message>
+ <message name="IDS_NFC_DEBUG_RECORDS_HEADER" desc="Header of the 'Records' section in the tag and peer boxes">
+ Records
+ </message>
+ <message name="IDS_NFC_DEBUG_ERROR_FAILED_TO_SET_POWER" desc="Error message shown when adapter power could not be set.">
+ Failed to set adapter power.
+ </message>
+ <message name="IDS_NFC_DEBUG_ERROR_FAILED_TO_SET_POLLING" desc="Error message shown when polling state could not be set.">
+ Failed to start/stop polling.
+ </message>
+ <message name="IDS_NFC_DEBUG_ERROR_FAILED_TO_SUBMIT_PREFIX" desc="Error message shown when an NDEF form could not be submitted.">
+ Failed to submit NDEF:
+ </message>
+ </if>
+
<!-- About power UI display strings -->
<if expr="pp_ifdef('chromeos')">
<message name="IDS_ABOUT_POWER_TITLE" desc="Title of the page">
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 47d97c0..ae7e692 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -320,6 +320,9 @@
<include name="IDR_MOBILE_SETUP_PORTAL_PAGE_HTML" file="resources\chromeos\mobile_setup_portal.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_NETWORK_MENU_CSS" file="resources\chromeos\network_menu.css" flattenhtml="true" type="BINDATA" />
<include name="IDR_NETWORK_MENU_JS" file="resources\chromeos\network_menu.js" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_NFC_DEBUG_HTML" file="resources\chromeos\nfc_debug.html" type="BINDATA" />
+ <include name="IDR_NFC_DEBUG_CSS" file="resources\chromeos\nfc_debug.css" type="BINDATA" />
+ <include name="IDR_NFC_DEBUG_JS" file="resources\chromeos\nfc_debug.js" type="BINDATA" />
<include name="IDR_NOTIFICATION_ICON_LINK_HTML" file="resources\chromeos\notification_icon_link.html" type="BINDATA" />
<include name="IDR_ECHO_MANIFEST" file="resources\chromeos\echo\manifest.json" type="BINDATA" />
<include name="IDR_OFFLINE_APP_LOAD_HTML" file="resources\chromeos\offline_app_load.html" flattenhtml="true" type="BINDATA" />
diff --git a/chrome/browser/resources/chromeos/nfc_debug.css b/chrome/browser/resources/chromeos/nfc_debug.css
new file mode 100644
index 0000000..ee23a5c
--- /dev/null
+++ b/chrome/browser/resources/chromeos/nfc_debug.css
@@ -0,0 +1,85 @@
+/* Copyright 2014 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+body {
+ margin: 0
+}
+
+p {
+ white-space: pre-wrap;
+}
+
+label {
+ display: block;
+}
+
+h1 {
+ margin: 1%;
+}
+
+div.entity-div {
+ -webkit-box-shadow: 0 0 20px 2px #aaa;
+ box-shadow: 0 0 20px 2px #aaa;
+ display: inline-block;
+ margin: 10px 5px;
+ overflow: hidden;
+ padding: 10px;
+ vertical-align: top;
+}
+
+#nfc-adapter-info {
+ width: 165px;
+}
+
+#ndef-record-form {
+ width: 300px;
+}
+
+#nfc-tag-info,
+#nfc-peer-info {
+ width: 270px;
+ word-wrap: break-word;
+}
+
+#ndef-record-form input {
+ width: 99%;
+}
+
+.parameters-table td {
+ padding: 0 10px 10px 0;
+}
+
+.transition-in {
+ -webkit-transition: opacity 250ms ease-in-out;
+ opacity: 1;
+ transition: opacity 250ms ease-in-out;
+}
+
+.transition-out {
+ -webkit-transition: opacity 250ms ease-in-out;
+ opacity: 0.25;
+ transition: opacity 250ms ease-in-out;
+}
+
+hr {
+ background: #888;
+ border: 0;
+ border-bottom: 1px dashed #ccc;
+}
+
+div.record-key-value-div {
+ margin-bottom: 10px;
+}
+
+span.record-key-span,
+div.record-key-div {
+ font-style: italic;
+ font-weight: bold;
+ margin-right: 10px;
+}
+
+.record-value-div > * {
+ margin: 10px;
+}
diff --git a/chrome/browser/resources/chromeos/nfc_debug.html b/chrome/browser/resources/chromeos/nfc_debug.html
new file mode 100644
index 0000000..5601d36
--- /dev/null
+++ b/chrome/browser/resources/chromeos/nfc_debug.html
@@ -0,0 +1,130 @@
+<!DOCTYPE html>
+<html i18n-values="dir:textdirection;">
+<head>
+ <meta charset="utf-8">
+ <title i18n-content="titleText"></title>
+ <link rel="stylesheet" type="text/css" href="nfc_debug.css">
+ <script src="chrome://resources/js/cr.js"></script>
+ <script src="chrome://resources/js/load_time_data.js"></script>
+ <script src="chrome://resources/js/util.js"></script>
+ <script src="strings.js"></script>
+ <script src="nfc_debug.js"></script>
+</head>
+<body i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize">
+ <h1 i18n-content="titleText"></h1>
+ <p id="nfc-not-supported" i18n-content="notSupportedText"></p>
+ <div id="wrapper">
+ <div id="nfc-adapter-info" class="entity-div">
+ <h3 i18n-content="adapterHeaderText"></h3>
+ <div id="adapter-parameters"></div>
+ <div id="adapter-toggles">
+ <button id="power-toggle"></button>
+ <button id="poll-toggle"></button>
+ </div>
+ </div>
+ <div id="ndef-record-form" class="entity-div">
+ <h3 i18n-content="ndefFormHeaderText"></h3>
+ <select id="record-type-menu">
+ <option i18n-content="ndefFormTypeTextText" value="text"></option>
+ <option i18n-content="ndefFormTypeUriText" value="uri"></option>
+ <option i18n-content="ndefFormTypeSmartPosterText" value="smart-poster">
+ </option>
+ </select>
+ <div id="text-form" class="record-form">
+ <div>
+ <label for="text-form-text" class="required"
+ i18n-content="ndefFormFieldTextText">
+ </label>
+ <input type="text" id="text-form-text">
+ </div>
+ <div>
+ <label for="text-form-encoding" class="required"
+ i18n-content="ndefFormFieldEncodingText">
+ </label>
+ <input type="text" id="text-form-encoding">
+ </div>
+ <div>
+ <label for="text-form-language-code" class="required"
+ i18n-content="ndefFormFieldLanguageCodeText">
+ </label>
+ <input type="text" id="text-form-language-code">
+ </div>
+ </div>
+ <div id="uri-form" class="record-form">
+ <div>
+ <label for="uri-form-uri" class="required"
+ i18n-content="ndefFormFieldUriText"></label>
+ <input type="text" id="uri-form-uri">
+ </div>
+ <div>
+ <label for="uri-form-mime-type"
+ i18n-content="ndefFormFieldMimeTypeText"></label>
+ <input type="text" id="uri-form-mime-type">
+ </div>
+ <div>
+ <label for="uri-form-target-size"
+ i18n-content="ndefFormFieldTargetSizeText"></label>
+ <input type="text" id="uri-form-target-size">
+ </div>
+ </div>
+ <div id="smart-poster-form" class="record-form">
+ <div>
+ <label for="smart-poster-form-uri"
+ i18n-content="ndefFormFieldUriText"></label>
+ <input type="text" id="smart-poster-form-uri">
+ </div>
+ <div>
+ <label for="smart-poster-form-mime-type"
+ i18n-content="ndefFormFieldMimeTypeText"></label>
+ <input type="text" id="smart-poster-form-mime-type">
+ </div>
+ <div>
+ <label for="smart-poster-form-target-size"
+ i18n-content="ndefFormFieldTargetSizeText"></label>
+ <input type="text" id="smart-poster-form-target-size">
+ </div>
+ <div>
+ <label for="smart-poster-form-title-text"
+ i18n-content="ndefFormFieldTitleTextText">
+ </label>
+ <input type="text" id="smart-poster-form-title-text">
+ </div>
+ <div>
+ <label for="smart-poster-form-title-encoding"
+ i18n-content="ndefFormFieldTitleEncodingText">
+ </label>
+ <input type="text" id="smart-poster-form-title-encoding">
+ </div>
+ <div>
+ <label for="smart-poster-form-title-language-code"
+ i18n-content="ndefFormFieldTitleLanguageCodeText">
+ </label>
+ <input type="text" id="smart-poster-form-title-language-code">
+ </div>
+ </div>
+ <button id="record-form-submit-button"></button>
+ </div>
+ <div id="nfc-peer-info" class="entity-div">
+ <h3 i18n-content="nfcPeerHeaderText"></h3>
+ <div id="peer-parameters"></div>
+ <div id="peer-records-entry" class="records-entry">
+ <h3 i18n-content="recordsHeaderText"></h3>
+ <hr/>
+ <div id="peer-records-container"></div>
+ <hr/>
+ </div>
+ </div>
+ <div id="nfc-tag-info" class="entity-div">
+ <h3 i18n-content="nfcTagHeaderText"></h3>
+ <div id="tag-parameters"></div>
+ <div id="tag-records-entry" class="records-entry">
+ <h3 i18n-content="recordsHeaderText"></h3>
+ <hr/>
+ <div id="tag-records-container"></div>
+ <hr/>
+ </div>
+ </div>
+ </div>
+ <script src="chrome://resources/js/i18n_template2.js"></script>
+</body>
+</html>
diff --git a/chrome/browser/resources/chromeos/nfc_debug.js b/chrome/browser/resources/chromeos/nfc_debug.js
new file mode 100644
index 0000000..02ccf51
--- /dev/null
+++ b/chrome/browser/resources/chromeos/nfc_debug.js
@@ -0,0 +1,375 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('nfcDebug', function() {
+ 'use strict';
+
+ function NfcDebugUI() {
+ this.adapterData_ = {};
+ this.peerData_ = {};
+ this.tagData_ = {};
+ }
+
+ NfcDebugUI.prototype = {
+ setAdapterData: function(data) {
+ this.adapterData_ = data;
+ },
+
+ setPeerData: function(data) {
+ this.peerData_ = data;
+ },
+
+ setTagData: function(data) {
+ this.tagData_ = data;
+ },
+
+ /**
+ * Powers the NFC adapter ON or OFF.
+ */
+ toggleAdapterPower: function() {
+ chrome.send('setAdapterPower', [!this.adapterData_.powered]);
+ },
+
+ /**
+ * Tells the NFC adapter to start or stop polling.
+ */
+ toggleAdapterPolling: function() {
+ chrome.send('setAdapterPolling', [!this.adapterData_.polling]);
+ },
+
+ /**
+ * Notifies the UI that the user made an NDEF type selection and the
+ * appropriate form should be displayed.
+ */
+ recordTypeChanged: function() {
+ this.updateRecordFormContents();
+ },
+
+ /**
+ * Creates a table element and populates it for each record contained
+ * in the given list of records and adds them as a child of the given
+ * DOMElement. This method will replace the contents of the given element
+ * with the tables.
+ *
+ * @param {DOMElement} div The container that the records should be rendered
+ * to.
+ * @param {Array} records List of NDEF record data.
+ */
+ renderRecords: function(div, records) {
+ div.textContent = '';
+ if (records.length == 0) {
+ return;
+ }
+ var self = this;
+ records.forEach(function(record) {
+ var recordDiv = document.createElement('div');
+ recordDiv.setAttribute('class', 'record-div');
+ for (var key in record) {
+ if (!record.hasOwnProperty(key))
+ continue;
+
+ var rowDiv = document.createElement('div');
+ rowDiv.setAttribute('class', 'record-key-value-div');
+
+ var keyElement, valueElement;
+ if (key == 'titles') {
+ keyElement = document.createElement('div');
+ keyElement.setAttribute('class', 'record-key-div');
+ keyElement.appendChild(document.createTextNode(key));
+ valueElement = document.createElement('div');
+ valueElement.setAttribute('class', 'record-value-div');
+ self.renderRecords(valueElement, record[key]);
+ } else {
+ keyElement = document.createElement('span');
+ keyElement.setAttribute('class', 'record-key-span');
+ keyElement.appendChild(document.createTextNode(key));
+ valueElement = document.createElement('span');
+ valueElement.setAttribute('class', 'record-value-span');
+ valueElement.appendChild(document.createTextNode(record[key]));
+ }
+ rowDiv.appendChild(keyElement);
+ rowDiv.appendChild(valueElement);
+ recordDiv.appendChild(rowDiv);
+ }
+ div.appendChild(recordDiv);
+ if (records[records.length - 1] !== record)
+ div.appendChild(document.createElement('hr'));
+ });
+ },
+
+ /**
+ * Updates which record type form is displayed based on the currently
+ * selected type.
+ */
+ updateRecordFormContents: function() {
+ var recordTypeMenu = $('record-type-menu');
+ var selectedType =
+ recordTypeMenu.options[recordTypeMenu.selectedIndex].value;
+ this.updateRecordFormContentsFromType(selectedType);
+ },
+
+ /**
+ * Updates which record type form is displayed based on the passed in
+ * type string.
+ *
+ * @param {string} type The record type.
+ */
+ updateRecordFormContentsFromType: function(type) {
+ $('text-form').hidden = (type != 'text');
+ $('uri-form').hidden = (type != 'uri');
+ $('smart-poster-form').hidden = (type != 'smart-poster');
+ },
+
+ /**
+ * Tries to push or write the record to the remote tag or device based on
+ * the contents of the record form fields.
+ */
+ submitRecordForm: function() {
+ var recordTypeMenu = $('record-type-menu');
+ var selectedType =
+ recordTypeMenu.options[recordTypeMenu.selectedIndex].value;
+ var recordData = {};
+ if (selectedType == 'text') {
+ recordData.type = 'TEXT';
+ if ($('text-form-text').value)
+ recordData.text = $('text-form-text').value;
+ if ($('text-form-encoding').value)
+ recordData.encoding = $('text-form-encoding').value;
+ if ($('text-form-language-code').value)
+ recordData.languageCode = $('text-form-language-code').value;
+ } else if (selectedType == 'uri') {
+ recordData.type = 'URI';
+ if ($('uri-form-uri').value)
+ recordData.uri = $('uri-form-uri').value;
+ if ($('uri-form-mime-type').value)
+ recordData.mimeType = $('uri-form-mime-type').value;
+ if ($('uri-form-target-size').value) {
+ var targetSize = $('uri-form-target-size').value;
+ targetSize = parseFloat(targetSize);
+ recordData.targetSize = isNaN(targetSize) ? 0.0 : targetSize;
+ }
+ } else if (selectedType == 'smart-poster') {
+ recordData.type = 'SMART_POSTER';
+ if ($('smart-poster-form-uri').value)
+ recordData.uri = $('smart-poster-form-uri').value;
+ if ($('smart-poster-form-mime-type').value)
+ recordData.mimeType = $('smart-poster-form-mime-type').value;
+ if ($('smart-poster-form-target-size').value) {
+ var targetSize = $('smart-poster-form-target-size').value;
+ targetSize = parseFloat(targetSize);
+ recordData.targetSize = isNaN(targetSize) ? 0.0 : targetSize;
+ }
+ var title = {};
+ if ($('smart-poster-form-title-text').value)
+ title.text = $('smart-poster-form-title-text').value;
+ if ($('smart-poster-form-title-encoding').value)
+ title.encoding = $('smart-poster-form-title-encoding').value;
+ if ($('smart-poster-form-title-language-code').value)
+ title.languageCode =
+ $('smart-poster-form-title-language-code').value;
+ if (Object.keys(title).length != 0)
+ recordData.titles = [title];
+ }
+ chrome.send('submitRecordForm', [recordData]);
+ },
+
+ /**
+ * Given a dictionary |data|, builds a table where each row contains the
+ * a key and its value. The resulting table is then added as the sole child
+ * of |div|. |data| contains information about an adapter, tag, or peer and
+ * this method creates a table for display, thus the value of some keys
+ * will be processed.
+ *
+ * @param {DOMElement} div The container that the table should be rendered
+ * to.
+ * @param {dictionary} data Data to generate the table from.
+ */
+ createTableFromData: function(div, data) {
+ div.textContent = '';
+ var table = document.createElement('table');
+ table.classList.add('parameters-table');
+ for (var key in data) {
+ var row = document.createElement('tr');
+ var col = document.createElement('td');
+ col.textContent = key;
+ row.appendChild(col);
+
+ col = document.createElement('td');
+ var value = data[key];
+ if (key == 'records')
+ value = value.length;
+ else if (key == 'supportedTechnologies')
+ value = value.join(', ');
+ col.textContent = value;
+ row.appendChild(col);
+ table.appendChild(row);
+ }
+ div.appendChild(table);
+ },
+ };
+
+ cr.addSingletonGetter(NfcDebugUI);
+
+ /**
+ * Initializes the page after the content has loaded.
+ */
+ NfcDebugUI.initialize = function() {
+ $('nfc-adapter-info').hidden = true;
+ $('adapter-toggles').hidden = true;
+ $('nfc-adapter-info').classList.add('transition-out');
+ $('ndef-record-form').classList.add('transition-out');
+ $('nfc-peer-info').classList.add('transition-out');
+ $('nfc-tag-info').classList.add('transition-out');
+ $('power-toggle').onclick = function() {
+ NfcDebugUI.getInstance().toggleAdapterPower();
+ };
+ $('poll-toggle').onclick = function() {
+ NfcDebugUI.getInstance().toggleAdapterPolling();
+ };
+ $('record-type-menu').onchange = function() {
+ NfcDebugUI.getInstance().recordTypeChanged();
+ };
+ $('record-form-submit-button').onclick = function() {
+ NfcDebugUI.getInstance().submitRecordForm();
+ };
+ $('record-form-submit-button').hidden = true;
+ NfcDebugUI.getInstance().updateRecordFormContents();
+ chrome.send('initialize');
+ };
+
+ /**
+ * Updates the UI based on the NFC availability on the current platform.
+ *
+ * @param {bool} available If true, NFC is supported on the current platform.
+ */
+ NfcDebugUI.onNfcAvailabilityDetermined = function(available) {
+ $('nfc-not-supported').hidden = available;
+ };
+
+ /**
+ * Notifies the UI that information about the NFC adapter has been received.
+ *
+ * @param {dictionary} data Properties of the NFC adapter.
+ */
+ NfcDebugUI.onNfcAdapterInfoChanged = function(data) {
+ NfcDebugUI.getInstance().setAdapterData(data);
+
+ $('nfc-adapter-info').hidden = false;
+ NfcDebugUI.getInstance().createTableFromData($('adapter-parameters'), data);
+
+ $('nfc-adapter-info').classList.toggle('transition-out', !data.present);
+ $('nfc-adapter-info').classList.toggle('transition-in', data.present);
+ $('ndef-record-form').classList.toggle('transition-out', !data.present);
+ $('ndef-record-form').classList.toggle('transition-in', data.present);
+
+ $('adapter-toggles').hidden = !data.present;
+ $('ndef-record-form').hidden = !data.present;
+
+ $('power-toggle').textContent = loadTimeData.getString(
+ data.powered ? 'adapterPowerOffText' : 'adapterPowerOnText');
+ $('poll-toggle').textContent = loadTimeData.getString(
+ data.polling ? 'adapterStopPollText' : 'adapterStartPollText');
+ };
+
+ /**
+ * Notifies the UI that information about an NFC peer has been received.
+ *
+ * @param {dictionary} data Properties of the NFC peer device.
+ */
+ NfcDebugUI.onNfcPeerDeviceInfoChanged = function(data) {
+ NfcDebugUI.getInstance().setPeerData(data);
+
+ if (Object.keys(data).length == 0) {
+ $('nfc-peer-info').classList.add('transition-out');
+ $('nfc-peer-info').classList.remove('transition-in');
+ $('record-form-submit-button').hidden = true;
+ return;
+ }
+
+ $('nfc-peer-info').classList.remove('transition-out');
+ $('nfc-peer-info').classList.add('transition-in');
+
+ NfcDebugUI.getInstance().createTableFromData($('peer-parameters'), data);
+
+ $('record-form-submit-button').hidden = false;
+ $('record-form-submit-button').textContent =
+ loadTimeData.getString('ndefFormPushButtonText');
+
+ if (data.records.length == 0) {
+ $('peer-records-entry').hidden = true;
+ return;
+ }
+
+ $('peer-records-entry').hidden = false;
+ NfcDebugUI.getInstance().renderRecords($('peer-records-container'),
+ data.records);
+ };
+
+ /**
+ * Notifies the UI that information about an NFC tag has been received.
+ *
+ * @param {dictionary} data Properties of the NFC tag.
+ */
+ NfcDebugUI.onNfcTagInfoChanged = function(data) {
+ NfcDebugUI.getInstance().setTagData(data);
+
+ if (Object.keys(data).length == 0) {
+ $('nfc-tag-info').classList.add('transition-out');
+ $('nfc-tag-info').classList.remove('transition-in');
+ $('record-form-submit-button').hidden = true;
+ return;
+ }
+
+ $('nfc-tag-info').classList.remove('transition-out');
+ $('nfc-tag-info').classList.add('transition-in');
+
+ NfcDebugUI.getInstance().createTableFromData($('tag-parameters'), data);
+
+ $('record-form-submit-button').hidden = false;
+ $('record-form-submit-button').textContent =
+ loadTimeData.getString('ndefFormWriteButtonText');
+
+ if (data.records.length == 0) {
+ $('tag-records-entry').hidden = true;
+ return;
+ }
+
+ $('tag-records-entry').hidden = false;
+ NfcDebugUI.getInstance().renderRecords($('tag-records-container'),
+ data.records);
+ };
+
+ /**
+ * Notifies the UI that a call to "setAdapterPower" failed. Displays an
+ * alert.
+ */
+ NfcDebugUI.onSetAdapterPowerFailed = function() {
+ alert(loadTimeData.getString('errorFailedToSetPowerText'));
+ };
+
+ /**
+ * Notifies the UI that a call to "setAdapterPolling" failed. Displays an
+ * alert.
+ */
+ NfcDebugUI.onSetAdapterPollingFailed = function() {
+ alert(loadTimeData.getString('errorFailedToSetPollingText'));
+ };
+
+ /**
+ * Notifies the UI that an error occurred while submitting an NDEF record
+ * form.
+ * @param {string} errorMessage An error message, describing the failure.
+ */
+ NfcDebugUI.onSubmitRecordFormFailed = function(errorMessage) {
+ alert(loadTimeData.getString('errorFailedToSubmitPrefixText') +
+ ' ' + errorMessage);
+ };
+
+ // Export
+ return {
+ NfcDebugUI: NfcDebugUI
+ };
+});
+
+document.addEventListener('DOMContentLoaded', nfcDebug.NfcDebugUI.initialize);
diff --git a/chrome/browser/ui/webui/DEPS b/chrome/browser/ui/webui/DEPS
index 7a5531e..f154c9a 100644
--- a/chrome/browser/ui/webui/DEPS
+++ b/chrome/browser/ui/webui/DEPS
@@ -7,6 +7,7 @@ include_rules = [
# Other libraries.
"+device/bluetooth",
+ "+device/nfc",
"+third_party/angle", # For ANGLE version.
"+third_party/zlib/zlib.h", # For compression level constants.
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index 6a40d3c..34b32d8 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -111,6 +111,7 @@
#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
#include "chrome/browser/ui/webui/chromeos/mobile_setup_ui.h"
#include "chrome/browser/ui/webui/chromeos/network_ui.h"
+#include "chrome/browser/ui/webui/chromeos/nfc_debug_ui.h"
#include "chrome/browser/ui/webui/chromeos/power_ui.h"
#include "chrome/browser/ui/webui/chromeos/proxy_settings_ui.h"
#include "chrome/browser/ui/webui/chromeos/salsa_ui.h"
@@ -393,6 +394,8 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
return &NewWebUI<KeyboardOverlayUI>;
if (url.host() == chrome::kChromeUIMobileSetupHost)
return &NewWebUI<MobileSetupUI>;
+ if (url.host() == chrome::kChromeUINfcDebugHost)
+ return &NewWebUI<chromeos::NfcDebugUI>;
if (url.host() == chrome::kChromeUIOobeHost)
return &NewWebUI<chromeos::OobeUI>;
if (url.host() == chrome::kChromeUIProxySettingsHost)
diff --git a/chrome/browser/ui/webui/chromeos/nfc_debug_ui.cc b/chrome/browser/ui/webui/chromeos/nfc_debug_ui.cc
new file mode 100644
index 0000000..8726218
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/nfc_debug_ui.cc
@@ -0,0 +1,752 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/chromeos/nfc_debug_ui.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/values.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/url_constants.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "content/public/browser/web_ui_message_handler.h"
+#include "device/nfc/nfc_adapter.h"
+#include "device/nfc/nfc_adapter_factory.h"
+#include "device/nfc/nfc_peer.h"
+#include "device/nfc/nfc_tag.h"
+#include "grit/browser_resources.h"
+#include "grit/generated_resources.h"
+
+using device::NfcAdapter;
+using device::NfcAdapterFactory;
+using device::NfcNdefMessage;
+using device::NfcNdefRecord;
+using device::NfcNdefTagTechnology;
+using device::NfcPeer;
+using device::NfcTag;
+using device::NfcTagTechnology;
+
+namespace chromeos {
+
+namespace {
+
+// Keys for various NFC properties that are used by JS.
+const char kAdapterPeersProperty[] = "peers";
+const char kAdapterPollingProperty[] = "polling";
+const char kAdapterPoweredProperty[] = "powered";
+const char kAdapterPresentProperty[] = "present";
+const char kAdapterTagsProperty[] = "tags";
+
+const char kPeerIdentifierProperty[] = "identifier";
+const char kPeerRecordsProperty[] = "records";
+
+const char kTagIdentifierProperty[] = "identifier";
+const char kTagTypeProperty[] = "type";
+const char kTagReadOnlyProperty[] = "readOnly";
+const char kTagRecordsProperty[] = "records";
+const char kTagSupportedProtocolProperty[] = "supportedProtocol";
+const char kTagSupportedTechnologiesProperty[] = "supportedTechnologies";
+const char kRecordTypeProperty[] = "type";
+
+// Tag types.
+const char kTagType1[] = "TYPE-1";
+const char kTagType2[] = "TYPE-2";
+const char kTagType3[] = "TYPE-3";
+const char kTagType4[] = "TYPE-4";
+const char kTagTypeUnknown[] = "UNKNOWN";
+
+// NFC transfer protocols.
+const char kTagProtocolFelica[] = "FELICA";
+const char kTagProtocolIsoDep[] = "ISO-DEP";
+const char kTagProtocolJewel[] = "JEWEL";
+const char kTagProtocolMifare[] = "MIFARE";
+const char kTagProtocolNfcDep[] = "NFC-DEP";
+const char kTagProtocolUnknown[] = "UNKNOWN";
+
+// NFC tag technologies.
+const char kTagTechnologyNfcA[] = "NFC-A";
+const char kTagTechnologyNfcB[] = "NFC-B";
+const char kTagTechnologyNfcF[] = "NFC-F";
+const char kTagTechnologyNfcV[] = "NFC-V";
+const char kTagTechnologyIsoDep[] = "ISO-DEP";
+const char kTagTechnologyNdef[] = "NDEF";
+
+// NDEF types.
+const char kTypeHandoverCarrier[] = "HANDOVER_CARRIER";
+const char kTypeHandoverRequest[] = "HANDOVER_REQUEST";
+const char kTypeHandoverSelect[] = "HANDOVER_SELECT";
+const char kTypeSmartPoster[] = "SMART_POSTER";
+const char kTypeText[] = "TEXT";
+const char kTypeURI[] = "URI";
+const char kTypeUnknown[] = "UNKNOWN";
+
+// JavaScript callback constants.
+const char kInitializeCallback[] = "initialize";
+const char kSetAdapterPowerCallback[] = "setAdapterPower";
+const char kSetAdapterPollingCallback[] = "setAdapterPolling";
+const char kSubmitRecordFormCallback[] = "submitRecordForm";
+
+// Constants for JavaScript functions that we can call.
+const char kOnNfcAdapterInfoChangedFunction[] =
+ "nfcDebug.NfcDebugUI.onNfcAdapterInfoChanged";
+const char kOnNfcAvailabilityDeterminedFunction[] =
+ "nfcDebug.NfcDebugUI.onNfcAvailabilityDetermined";
+const char kOnNfcPeerDeviceInfoChangedFunction[] =
+ "nfcDebug.NfcDebugUI.onNfcPeerDeviceInfoChanged";
+const char kOnNfcTagInfoChangedFunction[] =
+ "nfcDebug.NfcDebugUI.onNfcTagInfoChanged";
+const char kOnSetAdapterPollingFailedFunction[] =
+ "nfcDebug.NfcDebugUI.onSetAdapterPollingFailed";
+const char kOnSetAdapterPowerFailedFunction[] =
+ "nfcDebug.NfcDebugUI.onSetAdapterPowerFailed";
+const char kOnSubmitRecordFormFailedFunction[] =
+ "nfcDebug.NfcDebugUI.onSubmitRecordFormFailed";
+
+std::string RecordTypeToString(NfcNdefRecord::Type type) {
+ switch (type) {
+ case NfcNdefRecord::kTypeHandoverCarrier:
+ return kTypeHandoverCarrier;
+ case NfcNdefRecord::kTypeHandoverRequest:
+ return kTypeHandoverRequest;
+ case NfcNdefRecord::kTypeHandoverSelect:
+ return kTypeHandoverSelect;
+ case NfcNdefRecord::kTypeSmartPoster:
+ return kTypeSmartPoster;
+ case NfcNdefRecord::kTypeText:
+ return kTypeText;
+ case NfcNdefRecord::kTypeURI:
+ return kTypeURI;
+ case NfcNdefRecord::kTypeUnknown:
+ return kTypeUnknown;
+ }
+ return kTypeUnknown;
+}
+
+NfcNdefRecord::Type RecordTypeStringValueToEnum(const std::string& type) {
+ if (type == kTypeHandoverCarrier)
+ return NfcNdefRecord::kTypeHandoverCarrier;
+ if (type == kTypeHandoverRequest)
+ return NfcNdefRecord::kTypeHandoverRequest;
+ if (type == kTypeHandoverSelect)
+ return NfcNdefRecord::kTypeHandoverSelect;
+ if (type == kTypeSmartPoster)
+ return NfcNdefRecord::kTypeSmartPoster;
+ if (type == kTypeText)
+ return NfcNdefRecord::kTypeText;
+ if (type == kTypeURI)
+ return NfcNdefRecord::kTypeURI;
+ return NfcNdefRecord::kTypeUnknown;
+}
+
+std::string TagTypeToString(NfcTag::TagType type) {
+ switch (type) {
+ case NfcTag::kTagType1:
+ return kTagType1;
+ case NfcTag::kTagType2:
+ return kTagType2;
+ case NfcTag::kTagType3:
+ return kTagType3;
+ case NfcTag::kTagType4:
+ return kTagType4;
+ case NfcTag::kTagTypeUnknown:
+ return kTagTypeUnknown;
+ }
+ return kTagTypeUnknown;
+}
+
+std::string TagProtocolToString(NfcTag::Protocol protocol) {
+ switch (protocol) {
+ case NfcTag::kProtocolFelica:
+ return kTagProtocolFelica;
+ case NfcTag::kProtocolIsoDep:
+ return kTagProtocolIsoDep;
+ case NfcTag::kProtocolJewel:
+ return kTagProtocolJewel;
+ case NfcTag::kProtocolMifare:
+ return kTagProtocolMifare;
+ case NfcTag::kProtocolNfcDep:
+ return kTagProtocolNfcDep;
+ case NfcTag::kProtocolUnknown:
+ return kTagProtocolUnknown;
+ }
+ return kTagProtocolUnknown;
+}
+
+// content::WebUIMessageHandler implementation for this page.
+class NfcDebugMessageHandler : public content::WebUIMessageHandler,
+ public NfcAdapter::Observer,
+ public NfcNdefTagTechnology::Observer,
+ public NfcPeer::Observer,
+ public NfcTag::Observer {
+ public:
+ NfcDebugMessageHandler();
+ virtual ~NfcDebugMessageHandler();
+
+ // WebUIMessageHandler implementation.
+ virtual void RegisterMessages() OVERRIDE;
+
+ // NfcAdapter::Observer overrides.
+ virtual void AdapterPresentChanged(
+ NfcAdapter* adapter,
+ bool present) OVERRIDE;
+ virtual void AdapterPoweredChanged(
+ NfcAdapter* adapter,
+ bool powered) OVERRIDE;
+ virtual void AdapterPollingChanged(
+ NfcAdapter* adapter,
+ bool polling) OVERRIDE;
+ virtual void TagFound(NfcAdapter* adapter, NfcTag* tag) OVERRIDE;
+ virtual void TagLost(NfcAdapter*adapter, NfcTag* tag) OVERRIDE;
+ virtual void PeerFound(NfcAdapter* adaper, NfcPeer* peer) OVERRIDE;
+ virtual void PeerLost(NfcAdapter* adapter, NfcPeer* peer) OVERRIDE;
+
+ // NfcNdefTagTechnology::Observer override.
+ virtual void RecordReceived(
+ NfcTag* tag,
+ const NfcNdefRecord* record) OVERRIDE;
+
+ // NfcPeer::Observer override.
+ virtual void RecordReceived(
+ NfcPeer* peer,
+ const NfcNdefRecord* record) OVERRIDE;
+
+ // NfcTag::Observer override.
+ virtual void TagReady(NfcTag* tag) OVERRIDE;
+
+ private:
+ // Called by the UI when the page loads. This method requests information
+ // about NFC availability on the current platform and requests the underlying
+ // Adapter object. The UI is notified once the information is available.
+ void Initialize(const base::ListValue* args);
+
+ // Called by the UI to toggle the adapter power. |args| will contain one
+ // boolean that indicates whether the power should be set to ON or OFF.
+ void SetAdapterPower(const base::ListValue* args);
+ void OnSetAdapterPowerError();
+
+ // Called by the UI set the adapter's poll status. |args| will contain one
+ // boolean that indicates whether polling should be started or stopped.
+ void SetAdapterPolling(const base::ListValue* args);
+ void OnSetAdapterPollingError();
+
+ // Called by the UI to push an NDEF record to a remote device or tag. |args|
+ // will contain one dictionary that contains the record data.
+ void SubmitRecordForm(const base::ListValue* args);
+ void OnSubmitRecordFormFailed(const std::string& error_message);
+
+ // Callback passed to NfcAdapterFactory::GetAdapter.
+ void OnGetAdapter(scoped_refptr<NfcAdapter> adapter);
+
+ // Stores the properties of the NFC adapter in |out|, mapping these to keys
+ // that will be read by JS.
+ void GetAdapterProperties(base::DictionaryValue* out);
+
+ // Stores the properties of the NFC peer in |out|, mapping these to keys
+ // that will be read by JS. |out| will not be modified, if no peer is known.
+ void GetPeerProperties(base::DictionaryValue* out);
+
+ // Stores the properties of the NFC tag in |out|, mapping these to keys
+ // that will be read by JS. |out| will not be modified, if no tag is known.
+ void GetTagProperties(base::DictionaryValue* out);
+
+ // Returns the records in |message| by populating |out|, in which
+ // they have been converted to a JS friendly format.
+ void GetRecordList(const NfcNdefMessage& message, base::ListValue* out);
+
+ // Updates the data displayed in the UI for the current adapter.
+ void UpdateAdapterInfo();
+
+ // Updates the data displayed in the UI for the current peer.
+ void UpdatePeerInfo();
+
+ // Updates the data displayed in the UI for the current tag.
+ void UpdateTagInfo();
+
+ // The NfcAdapter object.
+ scoped_refptr<NfcAdapter> nfc_adapter_;
+
+ // The cached identifier of the most recent NFC peer device found.
+ std::string peer_identifier_;
+
+ // The cached identifier of the most recent NFC tag found.
+ std::string tag_identifier_;
+
+ DISALLOW_COPY_AND_ASSIGN(NfcDebugMessageHandler);
+};
+
+NfcDebugMessageHandler::NfcDebugMessageHandler() {
+}
+
+NfcDebugMessageHandler::~NfcDebugMessageHandler() {
+ if (!nfc_adapter_.get())
+ return;
+ nfc_adapter_->RemoveObserver(this);
+ if (!peer_identifier_.empty()) {
+ NfcPeer* peer = nfc_adapter_->GetPeer(peer_identifier_);
+ if (peer)
+ peer->RemoveObserver(this);
+ }
+ if (!tag_identifier_.empty()) {
+ NfcTag* tag = nfc_adapter_->GetTag(tag_identifier_);
+ if (tag)
+ tag->RemoveObserver(this);
+ }
+}
+
+void NfcDebugMessageHandler::AdapterPresentChanged(
+ NfcAdapter* adapter,
+ bool present) {
+ UpdateAdapterInfo();
+}
+
+void NfcDebugMessageHandler::AdapterPoweredChanged(
+ NfcAdapter* adapter,
+ bool powered) {
+ UpdateAdapterInfo();
+}
+
+void NfcDebugMessageHandler::AdapterPollingChanged(
+ NfcAdapter* adapter,
+ bool polling) {
+ UpdateAdapterInfo();
+}
+
+void NfcDebugMessageHandler::TagFound(NfcAdapter* adapter, NfcTag* tag) {
+ VLOG(1) << "Found NFC tag: " << tag->GetIdentifier();
+ tag->AddObserver(this);
+ tag_identifier_ = tag->GetIdentifier();
+ tag->GetNdefTagTechnology()->AddObserver(this);
+ UpdateAdapterInfo();
+ UpdateTagInfo();
+}
+
+void NfcDebugMessageHandler::TagLost(NfcAdapter*adapter, NfcTag* tag) {
+ VLOG(1) << "Lost NFC tag: " << tag->GetIdentifier();
+ tag->RemoveObserver(this);
+ tag->GetNdefTagTechnology()->RemoveObserver(this);
+ tag_identifier_.clear();
+ UpdateAdapterInfo();
+ UpdateTagInfo();
+}
+
+void NfcDebugMessageHandler::PeerFound(NfcAdapter* adaper, NfcPeer* peer) {
+ VLOG(1) << "Found NFC peer device: " << peer->GetIdentifier();
+ peer->AddObserver(this);
+ peer_identifier_ = peer->GetIdentifier();
+ UpdateAdapterInfo();
+ UpdatePeerInfo();
+}
+
+void NfcDebugMessageHandler::PeerLost(NfcAdapter* adapter, NfcPeer* peer) {
+ VLOG(1) << "Lost NFC peer device: " << peer->GetIdentifier();
+ peer->RemoveObserver(this);
+ peer_identifier_.clear();
+ UpdateAdapterInfo();
+ UpdatePeerInfo();
+}
+
+void NfcDebugMessageHandler::RecordReceived(
+ NfcTag* tag,
+ const NfcNdefRecord* record) {
+ if (tag->GetIdentifier() != tag_identifier_) {
+ LOG(WARNING) << "Records received from unknown tag: "
+ << tag->GetIdentifier();
+ return;
+ }
+ UpdateTagInfo();
+}
+
+void NfcDebugMessageHandler::RecordReceived(
+ NfcPeer* peer,
+ const NfcNdefRecord* record) {
+ if (peer->GetIdentifier() != peer_identifier_) {
+ LOG(WARNING) << "Records received from unknown peer: "
+ << peer->GetIdentifier();
+ return;
+ }
+ UpdatePeerInfo();
+}
+
+void NfcDebugMessageHandler::TagReady(NfcTag* tag) {
+ if (tag_identifier_ != tag->GetIdentifier()) {
+ LOG(WARNING) << "Unknown tag became ready: " << tag->GetIdentifier();
+ return;
+ }
+ VLOG(1) << "Tag ready: " << tag->GetIdentifier();
+ UpdateTagInfo();
+}
+
+void NfcDebugMessageHandler::RegisterMessages() {
+ web_ui()->RegisterMessageCallback(
+ kInitializeCallback,
+ base::Bind(&NfcDebugMessageHandler::Initialize,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ kSetAdapterPowerCallback,
+ base::Bind(&NfcDebugMessageHandler::SetAdapterPower,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ kSetAdapterPollingCallback,
+ base::Bind(&NfcDebugMessageHandler::SetAdapterPolling,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ kSubmitRecordFormCallback,
+ base::Bind(&NfcDebugMessageHandler::SubmitRecordForm,
+ base::Unretained(this)));
+}
+
+void NfcDebugMessageHandler::Initialize(const base::ListValue* args) {
+ bool nfc_available = NfcAdapterFactory::IsNfcAvailable();
+ base::FundamentalValue available(nfc_available);
+ web_ui()->CallJavascriptFunction(kOnNfcAvailabilityDeterminedFunction,
+ available);
+ if (!nfc_available) {
+ LOG(WARNING) << "NFC is not available on current platform.";
+ return;
+ }
+ NfcAdapterFactory::GetAdapter(
+ base::Bind(&NfcDebugMessageHandler::OnGetAdapter,
+ base::Unretained(this)));
+}
+
+void NfcDebugMessageHandler::SetAdapterPower(const base::ListValue* args) {
+ DCHECK(1 == args->GetSize());
+ DCHECK(nfc_adapter_.get());
+ bool powered;
+ args->GetBoolean(0, &powered);
+ VLOG(1) << "Setting adapter power: " << powered;
+ nfc_adapter_->SetPowered(
+ powered, base::Bind(&base::DoNothing),
+ base::Bind(&NfcDebugMessageHandler::OnSetAdapterPowerError,
+ base::Unretained(this)));
+}
+
+void NfcDebugMessageHandler::OnSetAdapterPowerError() {
+ LOG(ERROR) << "Failed to set NFC adapter power.";
+ web_ui()->CallJavascriptFunction(kOnSetAdapterPowerFailedFunction);
+}
+
+void NfcDebugMessageHandler::SetAdapterPolling(const base::ListValue* args) {
+ DCHECK(1 == args->GetSize());
+ DCHECK(nfc_adapter_.get());
+ bool start = false;
+ bool result = args->GetBoolean(0, &start);
+ DCHECK(result);
+ if (start) {
+ VLOG(1) << "Starting NFC poll loop.";
+ nfc_adapter_->StartPolling(
+ base::Bind(&base::DoNothing),
+ base::Bind(&NfcDebugMessageHandler::OnSetAdapterPollingError,
+ base::Unretained(this)));
+ } else {
+ VLOG(1) << "Stopping NFC poll loop.";
+ nfc_adapter_->StopPolling(
+ base::Bind(&base::DoNothing),
+ base::Bind(&NfcDebugMessageHandler::OnSetAdapterPollingError,
+ base::Unretained(this)));
+ }
+}
+
+void NfcDebugMessageHandler::OnSetAdapterPollingError() {
+ LOG(ERROR) << "Failed to start/stop polling.";
+ web_ui()->CallJavascriptFunction(kOnSetAdapterPollingFailedFunction);
+}
+
+void NfcDebugMessageHandler::SubmitRecordForm(const base::ListValue* args) {
+ DCHECK(1 == args->GetSize());
+ DCHECK(nfc_adapter_.get());
+ const base::DictionaryValue* record_data_const = NULL;
+ if (!args->GetDictionary(0, &record_data_const)) {
+ NOTREACHED();
+ return;
+ }
+
+ if (peer_identifier_.empty() && tag_identifier_.empty()) {
+ OnSubmitRecordFormFailed("No peer or tag present.");
+ return;
+ }
+
+ std::string type;
+ if (!record_data_const->GetString(kRecordTypeProperty, &type)) {
+ OnSubmitRecordFormFailed("Record type not provided.");
+ return;
+ }
+
+ base::DictionaryValue* record_data = record_data_const->DeepCopy();
+ record_data->Remove(kRecordTypeProperty, NULL);
+
+ // Convert the "targetSize" field to a double, in case JS stored it as an
+ // integer.
+ int target_size;
+ if (record_data->GetInteger(NfcNdefRecord::kFieldTargetSize, &target_size)) {
+ record_data->SetDouble(NfcNdefRecord::kFieldTargetSize,
+ static_cast<double>(target_size));
+ }
+
+ NfcNdefRecord record;
+ if (!record.Populate(RecordTypeStringValueToEnum(type), record_data)) {
+ OnSubmitRecordFormFailed("Invalid record data provided. Missing required "
+ "fields?");
+ return;
+ }
+
+ if (!peer_identifier_.empty()) {
+ NfcPeer* peer = nfc_adapter_->GetPeer(peer_identifier_);
+ if (!peer) {
+ OnSubmitRecordFormFailed("The current NFC adapter doesn't seem to know "
+ "about peer: " + peer_identifier_);
+ return;
+ }
+ NfcNdefMessage message;
+ message.AddRecord(&record);
+ peer->PushNdef(message,
+ base::Bind(&base::DoNothing),
+ base::Bind(&NfcDebugMessageHandler::OnSubmitRecordFormFailed,
+ base::Unretained(this),
+ "Failed to push NDEF record."));
+ return;
+ }
+ NfcTag* tag = nfc_adapter_->GetTag(tag_identifier_);
+ if (!tag) {
+ OnSubmitRecordFormFailed("The current NFC tag doesn't seem to known about "
+ "tag: " + tag_identifier_);
+ return;
+ }
+ NfcNdefMessage message;
+ message.AddRecord(&record);
+ tag->GetNdefTagTechnology()->WriteNdef(
+ message,
+ base::Bind(&base::DoNothing),
+ base::Bind(&NfcDebugMessageHandler::OnSubmitRecordFormFailed,
+ base::Unretained(this),
+ "Failed to write NDEF record."));
+}
+
+void NfcDebugMessageHandler::OnSubmitRecordFormFailed(
+ const std::string& error_message) {
+ LOG(ERROR) << "SubmitRecordForm failed: " << error_message;
+ web_ui()->CallJavascriptFunction(kOnSubmitRecordFormFailedFunction,
+ base::StringValue(error_message));
+}
+
+void NfcDebugMessageHandler::OnGetAdapter(
+ scoped_refptr<NfcAdapter> adapter) {
+ if (nfc_adapter_.get())
+ return;
+ nfc_adapter_ = adapter;
+ nfc_adapter_->AddObserver(this);
+ UpdateAdapterInfo();
+
+ NfcAdapter::PeerList peers;
+ nfc_adapter_->GetPeers(&peers);
+ for (NfcAdapter::PeerList::const_iterator iter = peers.begin();
+ iter != peers.end(); ++iter) {
+ PeerFound(nfc_adapter_.get(), *iter);
+ }
+
+ NfcAdapter::TagList tags;
+ nfc_adapter_->GetTags(&tags);
+ for (NfcAdapter::TagList::const_iterator iter = tags.begin();
+ iter != tags.end(); ++iter) {
+ TagFound(nfc_adapter_.get(), *iter);
+ }
+}
+
+void NfcDebugMessageHandler::GetAdapterProperties(
+ base::DictionaryValue* out) {
+ if (!nfc_adapter_.get()) {
+ VLOG(1) << "NFC adapter hasn't been received yet.";
+ return;
+ }
+ out->SetBoolean(kAdapterPresentProperty, nfc_adapter_->IsPresent());
+ out->SetBoolean(kAdapterPollingProperty, nfc_adapter_->IsPolling());
+ out->SetBoolean(kAdapterPoweredProperty, nfc_adapter_->IsPowered());
+
+ NfcAdapter::PeerList peers;
+ nfc_adapter_->GetPeers(&peers);
+ out->SetInteger(kAdapterPeersProperty, static_cast<int>(peers.size()));
+
+ NfcAdapter::TagList tags;
+ nfc_adapter_->GetTags(&tags);
+ out->SetInteger(kAdapterTagsProperty, static_cast<int>(tags.size()));
+}
+
+void NfcDebugMessageHandler::GetPeerProperties(base::DictionaryValue* out) {
+ if (peer_identifier_.empty()) {
+ VLOG(1) << "No known peer exists.";
+ return;
+ }
+ if (!nfc_adapter_.get()) {
+ VLOG(1) << "NFC adapter hasn't been received yet.";
+ return;
+ }
+ NfcPeer* peer = nfc_adapter_->GetPeer(peer_identifier_);
+ if (!peer) {
+ LOG(ERROR) << "The current NFC adapter doesn't seem to know about peer: "
+ << peer_identifier_;
+ return;
+ }
+ out->SetString(kPeerIdentifierProperty, peer_identifier_);
+
+ base::ListValue* records = new base::ListValue();
+ GetRecordList(peer->GetNdefMessage(), records);
+ out->Set(kPeerRecordsProperty, records);
+}
+
+void NfcDebugMessageHandler::GetTagProperties(base::DictionaryValue* out) {
+ if (tag_identifier_.empty()) {
+ VLOG(1) << "No known tag exists.";
+ return;
+ }
+ if (!nfc_adapter_.get()) {
+ VLOG(1) << "NFC adapter hasn't been received yet.";
+ return;
+ }
+ NfcTag* tag = nfc_adapter_->GetTag(tag_identifier_);
+ if (!tag) {
+ LOG(ERROR) << "The current NFC adapter doesn't seem to know about tag: "
+ << tag_identifier_;
+ return;
+ }
+ out->SetString(kTagIdentifierProperty, tag_identifier_);
+ out->SetString(kTagTypeProperty, TagTypeToString(tag->GetType()));
+ out->SetBoolean(kTagReadOnlyProperty, tag->IsReadOnly());
+ out->SetString(kTagSupportedProtocolProperty,
+ TagProtocolToString(tag->GetSupportedProtocol()));
+
+ base::ListValue* technologies = new base::ListValue();
+ NfcTagTechnology::TechnologyTypeMask technology_mask =
+ tag->GetSupportedTechnologies();
+ if (technology_mask & NfcTagTechnology::kTechnologyTypeNfcA)
+ technologies->AppendString(kTagTechnologyNfcA);
+ if (technology_mask & NfcTagTechnology::kTechnologyTypeNfcB)
+ technologies->AppendString(kTagTechnologyNfcB);
+ if (technology_mask & NfcTagTechnology::kTechnologyTypeNfcF)
+ technologies->AppendString(kTagTechnologyNfcF);
+ if (technology_mask & NfcTagTechnology::kTechnologyTypeNfcV)
+ technologies->AppendString(kTagTechnologyNfcV);
+ if (technology_mask & NfcTagTechnology::kTechnologyTypeIsoDep)
+ technologies->AppendString(kTagTechnologyIsoDep);
+ if (technology_mask & NfcTagTechnology::kTechnologyTypeNdef)
+ technologies->AppendString(kTagTechnologyNdef);
+ out->Set(kTagSupportedTechnologiesProperty, technologies);
+
+ base::ListValue* records = new base::ListValue();
+ GetRecordList(tag->GetNdefTagTechnology()->GetNdefMessage(), records);
+ out->Set(kTagRecordsProperty, records);
+}
+
+void NfcDebugMessageHandler::GetRecordList(const NfcNdefMessage& message,
+ base::ListValue* out) {
+ for (NfcNdefMessage::RecordList::const_iterator iter =
+ message.records().begin();
+ iter != message.records().end(); ++iter) {
+ const NfcNdefRecord* record = (*iter);
+ base::DictionaryValue* record_data = record->data().DeepCopy();
+ record_data->SetString(kRecordTypeProperty,
+ RecordTypeToString(record->type()));
+ out->Append(record_data);
+ }
+}
+
+void NfcDebugMessageHandler::UpdateAdapterInfo() {
+ base::DictionaryValue data;
+ GetAdapterProperties(&data);
+ web_ui()->CallJavascriptFunction(kOnNfcAdapterInfoChangedFunction, data);
+}
+
+void NfcDebugMessageHandler::UpdatePeerInfo() {
+ base::DictionaryValue data;
+ GetPeerProperties(&data);
+ web_ui()->CallJavascriptFunction(kOnNfcPeerDeviceInfoChangedFunction, data);
+}
+
+void NfcDebugMessageHandler::UpdateTagInfo() {
+ base::DictionaryValue data;
+ GetTagProperties(&data);
+ web_ui()->CallJavascriptFunction(kOnNfcTagInfoChangedFunction, data);
+}
+
+} // namespace
+
+NfcDebugUI::NfcDebugUI(content::WebUI* web_ui)
+ : content::WebUIController(web_ui) {
+ web_ui->AddMessageHandler(new NfcDebugMessageHandler());
+
+ content::WebUIDataSource* html_source =
+ content::WebUIDataSource::Create(chrome::kChromeUINfcDebugHost);
+ html_source->SetUseJsonJSFormatV2();
+
+ html_source->AddLocalizedString("titleText", IDS_NFC_DEBUG_TITLE);
+ html_source->AddLocalizedString("notSupportedText",
+ IDS_NFC_DEBUG_NOT_SUPPORTED);
+ html_source->AddLocalizedString("adapterHeaderText",
+ IDS_NFC_DEBUG_ADAPTER_HEADER);
+ html_source->AddLocalizedString("adapterPowerOnText",
+ IDS_NFC_DEBUG_ADAPTER_POWER_ON);
+ html_source->AddLocalizedString("adapterPowerOffText",
+ IDS_NFC_DEBUG_ADAPTER_POWER_OFF);
+ html_source->AddLocalizedString("adapterStartPollText",
+ IDS_NFC_DEBUG_ADAPTER_START_POLL);
+ html_source->AddLocalizedString("adapterStopPollText",
+ IDS_NFC_DEBUG_ADAPTER_STOP_POLL);
+ html_source->AddLocalizedString("ndefFormHeaderText",
+ IDS_NFC_DEBUG_NDEF_FORM_HEADER);
+ html_source->AddLocalizedString("ndefFormTypeTextText",
+ IDS_NFC_DEBUG_NDEF_FORM_TYPE_TEXT);
+ html_source->AddLocalizedString("ndefFormTypeUriText",
+ IDS_NFC_DEBUG_NDEF_FORM_TYPE_URI);
+ html_source->AddLocalizedString("ndefFormTypeSmartPosterText",
+ IDS_NFC_DEBUG_NDEF_FORM_TYPE_SMART_POSTER);
+ html_source->AddLocalizedString("ndefFormWriteButtonText",
+ IDS_NFC_DEBUG_NDEF_FORM_WRITE_BUTTON);
+ html_source->AddLocalizedString("ndefFormFieldTextText",
+ IDS_NFC_DEBUG_NDEF_FORM_FIELD_TEXT);
+ html_source->AddLocalizedString("ndefFormFieldEncodingText",
+ IDS_NFC_DEBUG_NDEF_FORM_FIELD_ENCODING);
+ html_source->AddLocalizedString("ndefFormFieldLanguageCodeText",
+ IDS_NFC_DEBUG_NDEF_FORM_FIELD_LANGUAGE_CODE);
+ html_source->AddLocalizedString("ndefFormFieldUriText",
+ IDS_NFC_DEBUG_NDEF_FORM_FIELD_URI);
+ html_source->AddLocalizedString("ndefFormFieldMimeTypeText",
+ IDS_NFC_DEBUG_NDEF_FORM_FIELD_MIME_TYPE);
+ html_source->AddLocalizedString("ndefFormFieldTargetSizeText",
+ IDS_NFC_DEBUG_NDEF_FORM_FIELD_TARGET_SIZE);
+ html_source->AddLocalizedString("ndefFormFieldTitleTextText",
+ IDS_NFC_DEBUG_NDEF_FORM_FIELD_TITLE_TEXT);
+ html_source->AddLocalizedString("ndefFormFieldTitleEncodingText",
+ IDS_NFC_DEBUG_NDEF_FORM_FIELD_TITLE_ENCODING);
+ html_source->AddLocalizedString(
+ "ndefFormFieldTitleLanguageCodeText",
+ IDS_NFC_DEBUG_NDEF_FORM_FIELD_TITLE_LANGUAGE_CODE);
+ html_source->AddLocalizedString("ndefFormPushButtonText",
+ IDS_NFC_DEBUG_NDEF_FORM_PUSH_BUTTON);
+ html_source->AddLocalizedString("nfcPeerHeaderText",
+ IDS_NFC_DEBUG_NFC_PEER_HEADER);
+ html_source->AddLocalizedString("nfcTagHeaderText",
+ IDS_NFC_DEBUG_NFC_TAG_HEADER);
+ html_source->AddLocalizedString("recordsHeaderText",
+ IDS_NFC_DEBUG_RECORDS_HEADER);
+ html_source->AddLocalizedString("errorFailedToSetPowerText",
+ IDS_NFC_DEBUG_ERROR_FAILED_TO_SET_POWER);
+ html_source->AddLocalizedString("errorFailedToSetPollingText",
+ IDS_NFC_DEBUG_ERROR_FAILED_TO_SET_POLLING);
+ html_source->AddLocalizedString("errorFailedToSubmitPrefixText",
+ IDS_NFC_DEBUG_ERROR_FAILED_TO_SUBMIT_PREFIX);
+ html_source->SetJsonPath("strings.js");
+
+ // Add required resources.
+ html_source->AddResourcePath("nfc_debug.css", IDR_NFC_DEBUG_CSS);
+ html_source->AddResourcePath("nfc_debug.js", IDR_NFC_DEBUG_JS);
+ html_source->SetDefaultResource(IDR_NFC_DEBUG_HTML);
+
+ Profile* profile = Profile::FromWebUI(web_ui);
+ content::WebUIDataSource::Add(profile, html_source);
+}
+
+NfcDebugUI::~NfcDebugUI() {
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/nfc_debug_ui.h b/chrome/browser/ui/webui/chromeos/nfc_debug_ui.h
new file mode 100644
index 0000000..270cfe47
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/nfc_debug_ui.h
@@ -0,0 +1,23 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_NFC_DEBUG_UI_H_
+#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_NFC_DEBUG_UI_H_
+
+#include "content/public/browser/web_ui_controller.h"
+
+namespace chromeos {
+
+class NfcDebugUI : public content::WebUIController {
+ public:
+ explicit NfcDebugUI(content::WebUI* web_ui);
+ virtual ~NfcDebugUI();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NfcDebugUI);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_NFC_DEBUG_UI_H_
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi
index f6e9467..a4dbb98 100644
--- a/chrome/chrome_browser_ui.gypi
+++ b/chrome/chrome_browser_ui.gypi
@@ -2281,6 +2281,8 @@
'browser/ui/webui/chromeos/mobile_setup_ui.h',
'browser/ui/webui/chromeos/network_ui.cc',
'browser/ui/webui/chromeos/network_ui.h',
+ 'browser/ui/webui/chromeos/nfc_debug_ui.cc',
+ 'browser/ui/webui/chromeos/nfc_debug_ui.h',
'browser/ui/webui/chromeos/power_ui.cc',
'browser/ui/webui/chromeos/power_ui.h',
'browser/ui/webui/chromeos/proxy_settings_ui.cc',
@@ -2638,6 +2640,7 @@
'../third_party/re2/re2.gyp:re2',
'../components/components.gyp:autofill_content_risk_proto',
'../device/bluetooth/bluetooth.gyp:device_bluetooth',
+ '../device/nfc/nfc.gyp:device_nfc',
'../media/media.gyp:media',
'../net/net.gyp:net_with_v8',
'../third_party/adobe/flash/flash_player.gyp:flapper_version_h',
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index ada5218..1a225e2 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -106,6 +106,7 @@ const char kChromeUIKeyboardOverlayURL[] = "chrome://keyboardoverlay/";
const char kChromeUILockScreenURL[] = "chrome://lock/";
const char kChromeUIMediaplayerURL[] = "chrome://mediaplayer/";
const char kChromeUIMobileSetupURL[] = "chrome://mobilesetup/";
+const char kChromeUINfcDebugURL[] = "chrome://nfc-debug/";
const char kChromeUIOobeURL[] = "chrome://oobe/";
const char kChromeUIOSCreditsURL[] = "chrome://os-credits/";
const char kChromeUIProxySettingsURL[] = "chrome://proxy-settings/";
@@ -259,6 +260,7 @@ const char kChromeUILoginContainerHost[] = "login-container";
const char kChromeUILoginHost[] = "login";
const char kChromeUIMediaplayerHost[] = "mediaplayer";
const char kChromeUIMobileSetupHost[] = "mobilesetup";
+const char kChromeUINfcDebugHost[] = "nfc-debug";
const char kChromeUINetworkHost[] = "network";
const char kChromeUIOobeHost[] = "oobe";
const char kChromeUIOSCreditsHost[] = "os-credits";
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
index 07936f4..8d873c2 100644
--- a/chrome/common/url_constants.h
+++ b/chrome/common/url_constants.h
@@ -100,6 +100,7 @@ extern const char kChromeUIKeyboardOverlayURL[];
extern const char kChromeUILockScreenURL[];
extern const char kChromeUIMediaplayerURL[];
extern const char kChromeUIMobileSetupURL[];
+extern const char kChromeUINfcDebugURL[];
extern const char kChromeUIOobeURL[];
extern const char kChromeUIOSCreditsURL[];
extern const char kChromeUIProxySettingsURL[];
@@ -253,6 +254,7 @@ extern const char kChromeUILoginHost[];
extern const char kChromeUIMediaplayerHost[];
extern const char kChromeUIMobileSetupHost[];
extern const char kChromeUINetworkHost[];
+extern const char kChromeUINfcDebugHost[];
extern const char kChromeUIOobeHost[];
extern const char kChromeUIOSCreditsHost[];
extern const char kChromeUIPowerHost[];