Commit f6329b4e authored by Steven Bennetts's avatar Steven Bennetts Committed by Commit Bot

Network UI: Support Device State

This shows the list of Shill devices in chrome://network

Bug: none
Cq-Include-Trybots: master.tryserver.chromium.linux:closure_compilation
Change-Id: Icf7fdce83722a3a84b82baee28b35bd5b40ad4c0
Reviewed-on: https://chromium-review.googlesource.com/656377Reviewed-by: default avatarToni Barzic <tbarzic@chromium.org>
Commit-Queue: Steven Bennetts <stevenjb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#501347}
parent a7ca6493
...@@ -4863,12 +4863,18 @@ All users must sign out to continue. ...@@ -4863,12 +4863,18 @@ All users must sign out to continue.
<message name="IDS_NETWORK_UI_GLOBAL_POLICY" desc="Label for global policy properties"> <message name="IDS_NETWORK_UI_GLOBAL_POLICY" desc="Label for global policy properties">
Global Policy: Global Policy:
</message> </message>
<message name="IDS_NETWORK_UI_NETWORK_LISTS" desc="Label for network lists section">
Network (Service) and Device properties
</message>
<message name="IDS_NETWORK_UI_VISIBLE_NETWORKS" desc="Label for list of visible networks"> <message name="IDS_NETWORK_UI_VISIBLE_NETWORKS" desc="Label for list of visible networks">
Visible Networks: Visible Networks:
</message> </message>
<message name="IDS_NETWORK_UI_FAVORITE_NETWORKS" desc="Label for list of favorite networks"> <message name="IDS_NETWORK_UI_FAVORITE_NETWORKS" desc="Label for list of favorite networks">
Favorite Networks: Favorite Networks:
</message> </message>
<message name="IDS_NETWORK_UI_DEVICES" desc="Label for list of network devices, e.g. wifi or cellular">
Devices:
</message>
<message name="IDS_DEVICE_LOG_LINK_TEXT" desc="Message preceeding link to chrome://device-log"> <message name="IDS_DEVICE_LOG_LINK_TEXT" desc="Message preceeding link to chrome://device-log">
For network logs, see: <ph name="DEVICE_LOG_LINK">&lt;a href="chrome://device-log"&gt;chrome://device-log&lt;/a&gt;</ph> For network logs, see: <ph name="DEVICE_LOG_LINK">&lt;a href="chrome://device-log"&gt;chrome://device-log&lt;/a&gt;</ph>
......
...@@ -26,6 +26,10 @@ paper-button[raised].colored { ...@@ -26,6 +26,10 @@ paper-button[raised].colored {
border-collapse: collapse; border-collapse: collapse;
} }
.state-table tr {
min-width: 800px;
}
.state-table tr td { .state-table tr td {
border: 1px solid rgb(220, 220, 220); border: 1px solid rgb(220, 220, 220);
font-size: 13px; font-size: 13px;
...@@ -50,6 +54,7 @@ paper-button[raised].colored { ...@@ -50,6 +54,7 @@ paper-button[raised].colored {
} }
.state-table-expanded-cell { .state-table-expanded-cell {
min-width: 400px;
white-space: pre-wrap; white-space: pre-wrap;
} }
......
...@@ -21,10 +21,10 @@ ...@@ -21,10 +21,10 @@
<div i18n-content="autoRefreshText"></div> <div i18n-content="autoRefreshText"></div>
<span i18n-values=".innerHTML:deviceLogLinkText"></span> <span i18n-values=".innerHTML:deviceLogLinkText"></span>
<h3 i18n-content="globalPolicyLabel"></h3> <h2 i18n-content="globalPolicyLabel"></h2>
<div id="global-policy"></div> <div id="global-policy"></div>
<h3>CrNetworkSelect</h3> <h2>CrNetworkSelect</h2>
<div id="select-div"> <div id="select-div">
<cr-network-select handle-network-item-selected> <cr-network-select handle-network-item-selected>
</cr-network-select> </cr-network-select>
...@@ -35,7 +35,8 @@ ...@@ -35,7 +35,8 @@
</paper-button> </paper-button>
</div> </div>
<h3 i18n-content="visibleNetworksLabel"></h3> <h2 i18n-content="networkListsLabel"></h2>
<div i18n-content="clickToExpandText"></div> <div i18n-content="clickToExpandText"></div>
<div> <div>
<span i18n-content="propertyFormatText"></span> <span i18n-content="propertyFormatText"></span>
...@@ -47,12 +48,22 @@ ...@@ -47,12 +48,22 @@
</select> </select>
</div> </div>
<h3 i18n-content="devicesLabel"></h3>
<table id="device-state-table" class="state-table">
<tr class="state-table-header">
<td></td>
<td></td>
<td>Type</td>
<td>State</td>
</tr>
</table>
<h3 i18n-content="visibleNetworksLabel"></h3>
<table id="network-state-table" class="state-table"> <table id="network-state-table" class="state-table">
<tr class="state-table-header"> <tr class="state-table-header">
<td></td> <td></td>
<td></td> <td></td>
<td>GUID</td> <td>GUID</td>
<td>Path</td>
<td>Name</td> <td>Name</td>
<td>Type</td> <td>Type</td>
<td>State</td> <td>State</td>
...@@ -73,7 +84,6 @@ ...@@ -73,7 +84,6 @@
<td></td> <td></td>
<td></td> <td></td>
<td>GUID</td> <td>GUID</td>
<td>Path</td>
<td>Name</td> <td>Name</td>
<td>Type</td> <td>Type</td>
<td>Profile</td> <td>Profile</td>
......
...@@ -2,6 +2,11 @@ ...@@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
var networkUI = {};
/** @typedef {CrOnc.NetworkStateProperties|CrOnc.DeviceStateProperties} */
networkUI.StateProperties;
var NetworkUI = (function() { var NetworkUI = (function() {
'use strict'; 'use strict';
...@@ -29,15 +34,16 @@ var NetworkUI = (function() { ...@@ -29,15 +34,16 @@ var NetworkUI = (function() {
// a single state field or an array of state fields. If more than one is // a single state field or an array of state fields. If more than one is
// specified then the first non empty value is used. // specified then the first non empty value is used.
var NETWORK_STATE_FIELDS = [ var NETWORK_STATE_FIELDS = [
'GUID', 'service_path', 'Name', 'Type', 'ConnectionState', 'connectable', 'GUID', 'Name', 'Type', 'ConnectionState', 'connectable', 'ErrorState',
'ErrorState', 'WiFi.Security', ['Cellular.NetworkTechnology', 'EAP.EAP'], 'WiFi.Security', ['Cellular.NetworkTechnology', 'EAP.EAP'],
'Cellular.ActivationState', 'Cellular.RoamingState', 'WiFi.Frequency', 'Cellular.ActivationState', 'Cellular.RoamingState', 'WiFi.Frequency',
'WiFi.SignalStrength' 'WiFi.SignalStrength'
]; ];
var FAVORITE_STATE_FIELDS = [ var FAVORITE_STATE_FIELDS =
'GUID', 'service_path', 'Name', 'Type', 'profile_path', 'visible', 'Source' ['GUID', 'Name', 'Type', 'profile_path', 'visible', 'Source'];
];
var DEVICE_STATE_FIELDS = ['Type', 'State'];
/** /**
* Creates and returns a typed HTMLTableCellElement. * Creates and returns a typed HTMLTableCellElement.
...@@ -58,19 +64,18 @@ var NetworkUI = (function() { ...@@ -58,19 +64,18 @@ var NetworkUI = (function() {
}; };
/** /**
* Returns the ONC data property for networkState associated with a key. Used * Returns the ONC data property for |state| associated with a key. Used
* to access properties in the networkState by |key| which may may refer to a * to access properties in the state by |key| which may may refer to a
* nested property, e.g. 'WiFi.Security'. If any part of a nested key is * nested property, e.g. 'WiFi.Security'. If any part of a nested key is
* missing, this will return undefined. * missing, this will return undefined.
* *
* @param {!chrome.networkingPrivate.NetworkStateProperties} networkState The * @param {!networkUI.StateProperties} state
* network state property dictionary.
* @param {string} key The ONC key for the property. * @param {string} key The ONC key for the property.
* @return {*} The value associated with the property or undefined if the * @return {*} The value associated with the property or undefined if the
* key (any part of it) is not defined. * key (any part of it) is not defined.
*/ */
var getOncProperty = function(networkState, key) { var getOncProperty = function(state, key) {
var dict = /** @type {!Object} */ (networkState); var dict = /** @type {!Object} */ (state);
var keys = key.split('.'); var keys = key.split('.');
while (keys.length > 1) { while (keys.length > 1) {
var k = keys.shift(); var k = keys.shift();
...@@ -84,16 +89,16 @@ var NetworkUI = (function() { ...@@ -84,16 +89,16 @@ var NetworkUI = (function() {
/** /**
* Creates a cell with a button for expanding a network state table row. * Creates a cell with a button for expanding a network state table row.
* *
* @param {string} guid The GUID identifying the network. * @param {!networkUI.StateProperties} state
* @return {!HTMLTableCellElement} The created td element that displays the * @return {!HTMLTableCellElement} The created td element that displays the
* given value. * given value.
*/ */
var createStateTableExpandButton = function(guid) { var createStateTableExpandButton = function(state) {
var cell = createTableCellElement(); var cell = createTableCellElement();
cell.className = 'state-table-expand-button-cell'; cell.className = 'state-table-expand-button-cell';
var button = document.createElement('button'); var button = document.createElement('button');
button.addEventListener('click', function(event) { button.addEventListener('click', function(event) {
toggleExpandRow(/** @type {!HTMLElement} */ (event.target), guid); toggleExpandRow(/** @type {!HTMLElement} */ (event.target), state);
}); });
button.className = 'state-table-expand-button'; button.className = 'state-table-expand-button';
button.textContent = '+'; button.textContent = '+';
...@@ -104,18 +109,20 @@ var NetworkUI = (function() { ...@@ -104,18 +109,20 @@ var NetworkUI = (function() {
/** /**
* Creates a cell with an icon representing the network state. * Creates a cell with an icon representing the network state.
* *
* @param {!chrome.networkingPrivate.NetworkStateProperties} networkState The * @param {!networkUI.StateProperties} state
* network state properties.
* @return {!HTMLTableCellElement} The created td element that displays the * @return {!HTMLTableCellElement} The created td element that displays the
* icon. * icon.
*/ */
var createStateTableIcon = function(networkState) { var createStateTableIcon = function(state) {
var cell = createTableCellElement(); var cell = createTableCellElement();
cell.className = 'state-table-icon-cell'; cell.className = 'state-table-icon-cell';
var icon = /** @type {!CrNetworkIconElement} */ ( var icon = /** @type {!CrNetworkIconElement} */ (
document.createElement('cr-network-icon')); document.createElement('cr-network-icon'));
icon.isListItem = true; icon.isListItem = true;
icon.networkState = networkState; icon.networkState = {
GUID: '',
Type: state.Type,
};
cell.appendChild(icon); cell.appendChild(icon);
return cell; return cell;
}; };
...@@ -137,25 +144,23 @@ var NetworkUI = (function() { ...@@ -137,25 +144,23 @@ var NetworkUI = (function() {
* Creates a row in the network state table. * Creates a row in the network state table.
* *
* @param {Array} stateFields The state fields to use for the row. * @param {Array} stateFields The state fields to use for the row.
* @param {!chrome.networkingPrivate.NetworkStateProperties} networkState The * @param {!networkUI.StateProperties} state
* network state properties.
* @return {!HTMLTableRowElement} The created tr element that contains the * @return {!HTMLTableRowElement} The created tr element that contains the
* network state information. * network state information.
*/ */
var createStateTableRow = function(stateFields, networkState) { var createStateTableRow = function(stateFields, state) {
var row = createTableRowElement(); var row = createTableRowElement();
row.className = 'state-table-row'; row.className = 'state-table-row';
var guid = networkState.GUID; row.appendChild(createStateTableExpandButton(state));
row.appendChild(createStateTableExpandButton(guid)); row.appendChild(createStateTableIcon(state));
row.appendChild(createStateTableIcon(networkState));
for (var i = 0; i < stateFields.length; ++i) { for (var i = 0; i < stateFields.length; ++i) {
var field = stateFields[i]; var field = stateFields[i];
var value; var value;
if (typeof field == 'string') { if (typeof field == 'string') {
value = getOncProperty(networkState, field); value = getOncProperty(state, field);
} else { } else {
for (var j = 0; j < field.length; ++j) { for (var j = 0; j < field.length; ++j) {
value = getOncProperty(networkState, field[j]); value = getOncProperty(state, field[j]);
if (value != undefined) if (value != undefined)
break; break;
} }
...@@ -172,8 +177,7 @@ var NetworkUI = (function() { ...@@ -172,8 +177,7 @@ var NetworkUI = (function() {
* *
* @param {string} tablename The name of the table to be created. * @param {string} tablename The name of the table to be created.
* @param {!Array<string>} stateFields The list of fields for the table. * @param {!Array<string>} stateFields The list of fields for the table.
* @param {!Array<!chrome.networkingPrivate.NetworkStateProperties>} states * @param {!Array<!networkUI.StateProperties>} states
* An array of network or favorite states.
*/ */
var createStateTable = function(tablename, stateFields, states) { var createStateTable = function(tablename, stateFields, states) {
var table = $(tablename); var table = $(tablename);
...@@ -195,11 +199,21 @@ var NetworkUI = (function() { ...@@ -195,11 +199,21 @@ var NetworkUI = (function() {
return '_' + guid.replace(/[{}]/g, ''); return '_' + guid.replace(/[{}]/g, '');
}; };
/**
* Returns a valid HTMLElement id from |type|. Note: |type| may be a Shill
* type or an ONC type, so strip _ and convert to lowercase to unify them.
*
* @param {string} type A Shill or ONC network type
* @return {string} A valid HTMLElement id.
*/
var idFromType = function(type) {
return '_' + type.replace(/[{}_]/g, '').toLowerCase();
};
/** /**
* This callback function is triggered when visible networks are received. * This callback function is triggered when visible networks are received.
* *
* @param {!Array<!chrome.networkingPrivate.NetworkStateProperties>} states * @param {!Array<!CrOnc.NetworkStateProperties>} states
* A list of network state information for each visible network.
*/ */
var onVisibleNetworksReceived = function(states) { var onVisibleNetworksReceived = function(states) {
createStateTable('network-state-table', NETWORK_STATE_FIELDS, states); createStateTable('network-state-table', NETWORK_STATE_FIELDS, states);
...@@ -208,21 +222,29 @@ var NetworkUI = (function() { ...@@ -208,21 +222,29 @@ var NetworkUI = (function() {
/** /**
* This callback function is triggered when favorite networks are received. * This callback function is triggered when favorite networks are received.
* *
* @param {!Array<!chrome.networkingPrivate.NetworkStateProperties>} states * @param {!Array<!CrOnc.NetworkStateProperties>} states
* A list of network state information for each favorite network.
*/ */
var onFavoriteNetworksReceived = function(states) { var onFavoriteNetworksReceived = function(states) {
createStateTable('favorite-state-table', FAVORITE_STATE_FIELDS, states); createStateTable('favorite-state-table', FAVORITE_STATE_FIELDS, states);
}; };
/**
* This callback function is triggered when device states are received.
*
* @param {!Array<!CrOnc.DeviceStateProperties>} states
*/
var onDeviceStatesReceived = function(states) {
createStateTable('device-state-table', DEVICE_STATE_FIELDS, states);
};
/** /**
* Toggles the button state and add or remove a row displaying the complete * Toggles the button state and add or remove a row displaying the complete
* state information for a row. * state information for a row.
* *
* @param {!HTMLElement} btn The button that was clicked. * @param {!HTMLElement} btn The button that was clicked.
* @param {string} guid GUID identifying the network. * @param {!networkUI.StateProperties} state
*/ */
var toggleExpandRow = function(btn, guid) { var toggleExpandRow = function(btn, state) {
var cell = btn.parentNode; var cell = btn.parentNode;
var row = /** @type {!HTMLTableRowElement} */ (cell.parentNode); var row = /** @type {!HTMLTableRowElement} */ (cell.parentNode);
if (btn.textContent == '-') { if (btn.textContent == '-') {
...@@ -230,7 +252,7 @@ var NetworkUI = (function() { ...@@ -230,7 +252,7 @@ var NetworkUI = (function() {
row.parentNode.removeChild(row.nextSibling); row.parentNode.removeChild(row.nextSibling);
} else { } else {
btn.textContent = '-'; btn.textContent = '-';
var expandedRow = createExpandedRow(guid, row); var expandedRow = createExpandedRow(state, row);
row.parentNode.insertBefore(expandedRow, row.nextSibling); row.parentNode.insertBefore(expandedRow, row.nextSibling);
} }
}; };
...@@ -238,59 +260,95 @@ var NetworkUI = (function() { ...@@ -238,59 +260,95 @@ var NetworkUI = (function() {
/** /**
* Creates the expanded row for displaying the complete state as JSON. * Creates the expanded row for displaying the complete state as JSON.
* *
* @param {string} guid The GUID identifying the network. * @param {!networkUI.StateProperties} state
* @param {!HTMLTableRowElement} baseRow The unexpanded row associated with * @param {!HTMLTableRowElement} baseRow The unexpanded row associated with
* the new row. * the new row.
* @return {!HTMLTableRowElement} The created tr element for the expanded row. * @return {!HTMLTableRowElement} The created tr element for the expanded row.
*/ */
var createExpandedRow = function(guid, baseRow) { var createExpandedRow = function(state, baseRow) {
var guid = state.GUID || '';
var expandedRow = createTableRowElement(); var expandedRow = createTableRowElement();
expandedRow.className = 'state-table-row'; expandedRow.className = 'state-table-row';
var emptyCell = createTableCellElement(); var emptyCell = createTableCellElement();
emptyCell.style.border = 'none'; emptyCell.style.border = 'none';
expandedRow.appendChild(emptyCell); expandedRow.appendChild(emptyCell);
var detailCell = createTableCellElement(); var detailCell = createTableCellElement();
detailCell.id = idFromGuid(guid); detailCell.id = guid ? idFromGuid(guid) : idFromType(state.Type);
detailCell.className = 'state-table-expanded-cell'; detailCell.className = 'state-table-expanded-cell';
detailCell.colSpan = baseRow.childNodes.length - 1; detailCell.colSpan = baseRow.childNodes.length - 1;
expandedRow.appendChild(detailCell); expandedRow.appendChild(detailCell);
var showDetail = function(state, error) {
if (error && error.message)
detailCell.textContent = error.message;
else
detailCell.textContent = JSON.stringify(state, null, '\t');
};
var selected = $('get-property-format').selectedIndex; var selected = $('get-property-format').selectedIndex;
var selectedId = $('get-property-format').options[selected].value; var selectedId = $('get-property-format').options[selected].value;
if (guid)
handleNetworkDetail(guid, selectedId, detailCell);
else
handleDeviceDetail(state, selectedId, detailCell);
return expandedRow;
};
/**
* Requests network details and calls showDetail with the result.
* @param {string} guid
* @param {string} selectedId
* @param {!HTMLTableCellElement} detailCell
*/
var handleNetworkDetail = function(guid, selectedId, detailCell) {
if (selectedId == 'shill') { if (selectedId == 'shill') {
chrome.send('getShillProperties', [guid]); chrome.send('getShillNetworkProperties', [guid]);
} else if (selectedId == 'state') { } else if (selectedId == 'state') {
chrome.networkingPrivate.getState(guid, function(properties) { chrome.networkingPrivate.getState(guid, function(properties) {
showDetail(properties, chrome.runtime.lastError); showDetail(detailCell, properties, chrome.runtime.lastError);
}); });
} else if (selectedId == 'managed') { } else if (selectedId == 'managed') {
chrome.networkingPrivate.getManagedProperties(guid, function(properties) { chrome.networkingPrivate.getManagedProperties(guid, function(properties) {
showDetail(properties, chrome.runtime.lastError); showDetail(detailCell, properties, chrome.runtime.lastError);
}); });
} else { } else {
chrome.networkingPrivate.getProperties(guid, function(properties) { chrome.networkingPrivate.getProperties(guid, function(properties) {
showDetail(properties, chrome.runtime.lastError); showDetail(detailCell, properties, chrome.runtime.lastError);
}); });
} }
return expandedRow;
}; };
/** /**
* Callback invoked by Chrome after a getShillProperties call. * Requests network details and calls showDetail with the result.
* @param {!networkUI.StateProperties} state
* @param {string} selectedId
* @param {!HTMLTableCellElement} detailCell
*/
var handleDeviceDetail = function(state, selectedId, detailCell) {
if (selectedId == 'shill') {
chrome.send('getShillDeviceProperties', [state.Type]);
} else {
showDetail(detailCell, state);
}
};
/**
* @param {!HTMLTableCellElement} detailCell
* @param {!CrOnc.NetworkStateProperties|!CrOnc.DeviceStateProperties|
* !chrome.networkingPrivate.ManagedProperties|
* !chrome.networkingPrivate.NetworkProperties} state
* @param {!Object=} error
*/
var showDetail = function(detailCell, state, error) {
if (error && error.message)
detailCell.textContent = error.message;
else
detailCell.textContent = JSON.stringify(state, null, '\t');
};
/**
* Callback invoked by Chrome after a getShillNetworkProperties call.
* *
* @param {Array} args The requested Shill properties. Will contain * @param {Array} args The requested Shill properties. Will contain
* just the 'GUID' and 'ShillError' properties if the call failed. * just the 'GUID' and 'ShillError' properties if the call failed.
*/ */
var getShillPropertiesResult = function(args) { var getShillNetworkPropertiesResult = function(args) {
var properties = args.shift(); var properties = args.shift();
var guid = properties['GUID']; var guid = properties['GUID'];
if (!guid) { if (!guid) {
console.error('No GUID in getShillPropertiesResult'); console.error('No GUID in getShillNetworkPropertiesResult');
return; return;
} }
...@@ -307,6 +365,33 @@ var NetworkUI = (function() { ...@@ -307,6 +365,33 @@ var NetworkUI = (function() {
}; };
/**
* Callback invoked by Chrome after a getShillDeviceProperties call.
*
* @param {Array} args The requested Shill properties. Will contain
* just the 'Type' and 'ShillError' properties if the call failed.
*/
var getShillDevicePropertiesResult = function(args) {
var properties = args.shift();
var type = properties['Type'];
if (!type) {
console.error('No Type in getShillDevicePropertiesResult');
return;
}
var detailCell = document.querySelector('td#' + idFromType(type));
if (!detailCell) {
console.error('No cell for Type: ' + type);
return;
}
if (properties['ShillError'])
detailCell.textContent = properties['ShillError'];
else
detailCell.textContent = JSON.stringify(properties, null, '\t');
};
/** /**
* Requests an update of all network info. * Requests an update of all network info.
*/ */
...@@ -323,6 +408,7 @@ var NetworkUI = (function() { ...@@ -323,6 +408,7 @@ var NetworkUI = (function() {
'configured': true 'configured': true
}, },
onFavoriteNetworksReceived); onFavoriteNetworksReceived);
chrome.networkingPrivate.getDeviceStates(onDeviceStatesReceived);
}; };
/** /**
...@@ -363,5 +449,8 @@ var NetworkUI = (function() { ...@@ -363,5 +449,8 @@ var NetworkUI = (function() {
chrome.send('addNetwork', [event.detail.customData]); chrome.send('addNetwork', [event.detail.customData]);
}); });
return {getShillPropertiesResult: getShillPropertiesResult}; return {
getShillNetworkPropertiesResult: getShillNetworkPropertiesResult,
getShillDevicePropertiesResult: getShillDevicePropertiesResult
};
})(); })();
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/strings/stringprintf.h"
#include "base/values.h" #include "base/values.h"
#include "chrome/browser/chromeos/options/network_config_view.h" #include "chrome/browser/chromeos/options/network_config_view.h"
#include "chrome/browser/extensions/tab_helper.h" #include "chrome/browser/extensions/tab_helper.h"
...@@ -19,8 +20,10 @@ ...@@ -19,8 +20,10 @@
#include "chrome/grit/generated_resources.h" #include "chrome/grit/generated_resources.h"
#include "chromeos/network/device_state.h" #include "chromeos/network/device_state.h"
#include "chromeos/network/network_configuration_handler.h" #include "chromeos/network/network_configuration_handler.h"
#include "chromeos/network/network_device_handler.h"
#include "chromeos/network/network_state.h" #include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h" #include "chromeos/network/network_state_handler.h"
#include "chromeos/network/onc/onc_utils.h"
#include "components/device_event_log/device_event_log.h" #include "components/device_event_log/device_event_log.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui.h"
...@@ -33,6 +36,9 @@ namespace chromeos { ...@@ -33,6 +36,9 @@ namespace chromeos {
namespace { namespace {
constexpr char kGetNetworkProperties[] = "getShillNetworkProperties";
constexpr char kGetDeviceProperties[] = "getShillDeviceProperties";
bool GetServicePathFromGuid(const std::string& guid, bool GetServicePathFromGuid(const std::string& guid,
std::string* service_path) { std::string* service_path) {
const NetworkState* network = const NetworkState* network =
...@@ -77,65 +83,120 @@ class NetworkConfigMessageHandler : public content::WebUIMessageHandler { ...@@ -77,65 +83,120 @@ class NetworkConfigMessageHandler : public content::WebUIMessageHandler {
// WebUIMessageHandler implementation. // WebUIMessageHandler implementation.
void RegisterMessages() override { void RegisterMessages() override {
web_ui()->RegisterMessageCallback( web_ui()->RegisterMessageCallback(
"getShillProperties", kGetNetworkProperties,
base::Bind(&NetworkConfigMessageHandler::GetShillProperties, base::Bind(&NetworkConfigMessageHandler::GetShillNetworkProperties,
base::Unretained(this))); base::Unretained(this)));
web_ui()->RegisterMessageCallback( web_ui()->RegisterMessageCallback(
"addNetwork", kGetDeviceProperties,
base::Bind(&NetworkConfigMessageHandler::AddNetwork, base::Bind(&NetworkConfigMessageHandler::GetShillDeviceProperties,
base::Unretained(this))); base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"addNetwork", base::Bind(&NetworkConfigMessageHandler::AddNetwork,
base::Unretained(this)));
} }
private: private:
void GetShillProperties(const base::ListValue* arg_list) { void GetShillNetworkProperties(const base::ListValue* arg_list) {
std::string guid; std::string guid;
if (!arg_list->GetString(0, &guid)) { if (!arg_list->GetString(0, &guid)) {
NOTREACHED(); NOTREACHED();
ErrorCallback(guid, "Missing GUID in arg list", nullptr);
return; return;
} }
std::string service_path; std::string service_path;
if (!GetServicePathFromGuid(guid, &service_path)) { if (!GetServicePathFromGuid(guid, &service_path)) {
ErrorCallback(guid, "Error.InvalidNetworkGuid", nullptr); ErrorCallback(guid, kGetNetworkProperties, "Error.InvalidNetworkGuid",
nullptr);
return; return;
} }
NetworkHandler::Get()->network_configuration_handler()->GetShillProperties( NetworkHandler::Get()->network_configuration_handler()->GetShillProperties(
service_path, service_path,
base::Bind(&NetworkConfigMessageHandler::GetShillPropertiesSuccess, base::Bind(
weak_ptr_factory_.GetWeakPtr()), &NetworkConfigMessageHandler::GetShillNetworkPropertiesSuccess,
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&NetworkConfigMessageHandler::ErrorCallback, base::Bind(&NetworkConfigMessageHandler::ErrorCallback,
weak_ptr_factory_.GetWeakPtr(), guid)); weak_ptr_factory_.GetWeakPtr(), guid,
kGetNetworkProperties));
} }
void GetShillPropertiesSuccess( void GetShillNetworkPropertiesSuccess(
const std::string& service_path, const std::string& service_path,
const base::DictionaryValue& dictionary) const { const base::DictionaryValue& dictionary) {
std::unique_ptr<base::DictionaryValue> dictionary_copy( std::unique_ptr<base::DictionaryValue> dictionary_copy(
dictionary.DeepCopy()); dictionary.DeepCopy());
// Set the 'ServicePath' property for debugging. // Set the 'service_path' property for debugging.
dictionary_copy->SetKey("ServicePath", base::Value(service_path)); dictionary_copy->SetKey("service_path", base::Value(service_path));
// Set the device properties for debugging. // Set the device properties for debugging.
SetDeviceProperties(dictionary_copy.get()); SetDeviceProperties(dictionary_copy.get());
base::ListValue return_arg_list; base::ListValue return_arg_list;
return_arg_list.Append(std::move(dictionary_copy)); return_arg_list.Append(std::move(dictionary_copy));
web_ui()->CallJavascriptFunctionUnsafe("NetworkUI.getShillPropertiesResult",
return_arg_list); AllowJavascript();
CallJavascriptFunction(
base::StringPrintf("NetworkUI.%sResult", kGetNetworkProperties),
return_arg_list);
}
void GetShillDeviceProperties(const base::ListValue* arg_list) {
std::string type;
if (!arg_list->GetString(0, &type)) {
NOTREACHED();
return;
}
const DeviceState* device =
NetworkHandler::Get()->network_state_handler()->GetDeviceStateByType(
onc::NetworkTypePatternFromOncType(type));
if (!device) {
ErrorCallback(type, kGetDeviceProperties, "Error.InvalidDeviceType",
nullptr);
return;
}
NetworkHandler::Get()->network_device_handler()->GetDeviceProperties(
device->path(),
base::Bind(
&NetworkConfigMessageHandler::GetShillDevicePropertiesSuccess,
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&NetworkConfigMessageHandler::ErrorCallback,
weak_ptr_factory_.GetWeakPtr(), type, kGetDeviceProperties));
}
void GetShillDevicePropertiesSuccess(
const std::string& device_path,
const base::DictionaryValue& dictionary) {
std::unique_ptr<base::DictionaryValue> dictionary_copy(
dictionary.DeepCopy());
// Set the 'device_path' property for debugging.
dictionary_copy->SetKey("device_path", base::Value(device_path));
base::ListValue return_arg_list;
return_arg_list.Append(std::move(dictionary_copy));
AllowJavascript();
CallJavascriptFunction(
base::StringPrintf("NetworkUI.%sResult", kGetDeviceProperties),
return_arg_list);
} }
void ErrorCallback( void ErrorCallback(const std::string& guid_or_type,
const std::string& guid, const std::string& function_name,
const std::string& error_name, const std::string& error_name,
std::unique_ptr<base::DictionaryValue> /* error_data */) const { std::unique_ptr<base::DictionaryValue> /* error_data */) {
NET_LOG(ERROR) << "Shill Error: " << error_name << " guid=" << guid; NET_LOG(ERROR) << "Shill Error: " << error_name << " id=" << guid_or_type;
base::ListValue return_arg_list; base::ListValue return_arg_list;
std::unique_ptr<base::DictionaryValue> dictionary; std::unique_ptr<base::DictionaryValue> dictionary;
dictionary->SetKey(shill::kGuidProperty, base::Value(guid)); std::string key = function_name == kGetDeviceProperties
? shill::kTypeProperty
: shill::kGuidProperty;
dictionary->SetKey(key, base::Value(guid_or_type));
dictionary->SetKey("ShillError", base::Value(error_name)); dictionary->SetKey("ShillError", base::Value(error_name));
return_arg_list.Append(std::move(dictionary)); return_arg_list.Append(std::move(dictionary));
web_ui()->CallJavascriptFunctionUnsafe("NetworkUI.getShillPropertiesResult",
return_arg_list); AllowJavascript();
CallJavascriptFunction(
base::StringPrintf("NetworkUI.%sResult", function_name.c_str()),
return_arg_list);
} }
void AddNetwork(const base::ListValue* args) { void AddNetwork(const base::ListValue* args) {
...@@ -190,12 +251,17 @@ void NetworkUI::GetLocalizedStrings(base::DictionaryValue* localized_strings) { ...@@ -190,12 +251,17 @@ void NetworkUI::GetLocalizedStrings(base::DictionaryValue* localized_strings) {
localized_strings->SetString( localized_strings->SetString(
"globalPolicyLabel", "globalPolicyLabel",
l10n_util::GetStringUTF16(IDS_NETWORK_UI_GLOBAL_POLICY)); l10n_util::GetStringUTF16(IDS_NETWORK_UI_GLOBAL_POLICY));
localized_strings->SetString(
"networkListsLabel",
l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LISTS));
localized_strings->SetString( localized_strings->SetString(
"visibleNetworksLabel", "visibleNetworksLabel",
l10n_util::GetStringUTF16(IDS_NETWORK_UI_VISIBLE_NETWORKS)); l10n_util::GetStringUTF16(IDS_NETWORK_UI_VISIBLE_NETWORKS));
localized_strings->SetString( localized_strings->SetString(
"favoriteNetworksLabel", "favoriteNetworksLabel",
l10n_util::GetStringUTF16(IDS_NETWORK_UI_FAVORITE_NETWORKS)); l10n_util::GetStringUTF16(IDS_NETWORK_UI_FAVORITE_NETWORKS));
localized_strings->SetString(
"devicesLabel", l10n_util::GetStringUTF16(IDS_NETWORK_UI_DEVICES));
} }
NetworkUI::NetworkUI(content::WebUI* web_ui) NetworkUI::NetworkUI(content::WebUI* web_ui)
...@@ -223,7 +289,6 @@ NetworkUI::NetworkUI(content::WebUI* web_ui) ...@@ -223,7 +289,6 @@ NetworkUI::NetworkUI(content::WebUI* web_ui)
html); html);
} }
NetworkUI::~NetworkUI() { NetworkUI::~NetworkUI() {}
}
} // namespace chromeos } // namespace chromeos
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment