diff options
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/app/generated_resources.grd | 88 | ||||
-rw-r--r-- | chrome/browser/browser_resources.grd | 3 | ||||
-rw-r--r-- | chrome/browser/resources/chromeos/nfc_debug.css | 85 | ||||
-rw-r--r-- | chrome/browser/resources/chromeos/nfc_debug.html | 130 | ||||
-rw-r--r-- | chrome/browser/resources/chromeos/nfc_debug.js | 375 | ||||
-rw-r--r-- | chrome/browser/ui/webui/DEPS | 1 | ||||
-rw-r--r-- | chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc | 3 | ||||
-rw-r--r-- | chrome/browser/ui/webui/chromeos/nfc_debug_ui.cc | 752 | ||||
-rw-r--r-- | chrome/browser/ui/webui/chromeos/nfc_debug_ui.h | 23 | ||||
-rw-r--r-- | chrome/chrome_browser_ui.gypi | 3 | ||||
-rw-r--r-- | chrome/common/url_constants.cc | 2 | ||||
-rw-r--r-- | chrome/common/url_constants.h | 2 |
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[]; |