diff options
19 files changed, 475 insertions, 206 deletions
diff --git a/chrome/browser/resources/options/chromeos/internet_detail.html b/chrome/browser/resources/options/chromeos/internet_detail.html index ec541b2..dd939e8 100644 --- a/chrome/browser/resources/options/chromeos/internet_detail.html +++ b/chrome/browser/resources/options/chromeos/internet_detail.html @@ -74,8 +74,8 @@ <label for="prefer-network-wifi" i18n-content="inetPreferredNetwork"> </label> - <span class="controlled-setting-indicator" data="preferred" - for="prefer-network-wifi"> + <span class="controlled-setting-indicator" + managed="Priority" for="prefer-network-wifi"> </span> </span> </span> @@ -224,7 +224,7 @@ <td> <input class="option-value" id="inet-server-hostname"></input> <span class="controlled-setting-indicator" - data="serverHostname" for="inet-server-hostname"></span> + managed="VPN.Host" for="inet-server-hostname"></span> </td> </tr> <tr> diff --git a/chrome/browser/resources/options/chromeos/internet_detail.js b/chrome/browser/resources/options/chromeos/internet_detail.js index 7447b52..431e7d2 100644 --- a/chrome/browser/resources/options/chromeos/internet_detail.js +++ b/chrome/browser/resources/options/chromeos/internet_detail.js @@ -15,23 +15,60 @@ cr.define('options.internet', function() { /** @const */ var ArrayDataModel = cr.ui.ArrayDataModel; /** @const */ var IPAddressField = options.internet.IPAddressField; + var GetManagedTypes = { + ACTIVE: 0, + TRANSLATED: 1, + RECOMMENDED: 2 + }; + /** - * Helper function to get the "Active" value of a property from a dictionary - * that includes ONC managed properties, e.g. getActiveValue(data, 'Name'). - * We use (data, key) instead of getActiveValue(data[key]) so that we can - * (possibly) add ONC key validation once all properties use ONC. + * Gets the value of a property from a dictionary |data| that includes ONC + * managed properties, e.g. getManagedValue(data, 'Name'). See notes for + * getManagedProperty. * @param {object} data The properties dictionary. * @param {string} key The property key. - * @return {*} the property value or undefined. + * @param {string} type (Optional) The type of property to get as defined in + * GetManagedTypes: + * 'ACTIVE' (default) - gets the active value + * 'TRANSLATED' - gets the traslated or active value + * 'RECOMMENDED' - gets the recommended value + * @return {*} The property value or undefined. */ - function getActiveValue(data, key) { - if (!(key in data)) - return undefined; - var property = data[key]; + function getManagedValue(data, key, type) { + var property = getManagedProperty(data, key); if (typeof property != 'object') return property; + if (type == GetManagedTypes.RECOMMENDED) + return getRecommendedValue(property); + if (type == GetManagedTypes.TRANSLATED && 'Translated' in property) + return property['Translated']; + // Otherwise get the Active value (defalt behavior). if ('Active' in property) return property['Active']; + // If no Active value is defined, return the effective value. + return getEffectiveValue(property); + } + + /** + * Get the recommended value from a Managed property ONC dictionary. + * @param {object} property The managed property ONC dictionary. + * @return {*} the effective value or undefined. + */ + function getRecommendedValue(property) { + if (property['UserEditable']) + return property['UserPolicy']; + if (property['DeviceEditable']) + return property['DevicePolicy']; + // No value recommended by policy. + return undefined; + } + + /** + * Get the effective value from a Managed property ONC dictionary. + * @param {object} property The managed property ONC dictionary. + * @return {*} The effective value or undefined. + */ + function getEffectiveValue(property) { if ('Effective' in property) { var effective = property.Effective; if (effective in property) @@ -41,15 +78,26 @@ cr.define('options.internet', function() { } /** - * Helper function for nested ONC properties, e.g. data[WiFi][Strength]. - * @param {object|string} property The property which must ether be - * a dictionary object or not be present. - * @return {*} the property value or undefined. + * Gets either a managed property dictionary or an unmanaged value from + * dictionary |data| that includes ONC managed properties. This supports + * nested dictionaries, e.g. getManagedProperty(data, 'VPN.Type'). + * @param {object} data The properties dictionary. + * @param {string} key The property key. + * @return {*} The property value or dictionary if it exists, otherwise + * undefined. */ - function getActiveDictionaryValue(data, dict, key) { - if (!(dict in data)) - return undefined; - return getActiveValue(data[dict], key); + function getManagedProperty(data, key) { + while (true) { + var index = key.indexOf('.'); + if (index < 0) + break; + var keyComponent = key.substr(0, index); + if (!(keyComponent in data)) + return undefined; + data = data[keyComponent]; + key = key.substr(index + 1); + } + return data[key]; } /** @@ -135,7 +183,7 @@ cr.define('options.internet', function() { function getNetworkName(data) { if (data.type == 'Ethernet') return loadTimeData.getString('ethernetName'); - return getActiveValue(data, 'Name'); + return getManagedValue(data, 'Name'); } ///////////////////////////////////////////////////////////////////////////// @@ -908,7 +956,7 @@ cr.define('options.internet', function() { return; } - var connectState = getActiveValue(data, 'ConnectionState'); + var connectState = getManagedValue(data, 'ConnectionState'); if (connectState == 'NotConnected') { $('details-internet-login').hidden = false; // Connecting to an unconfigured network might trigger certificate @@ -921,7 +969,7 @@ cr.define('options.internet', function() { $('details-internet-disconnect').hidden = false; } - var connectable = getActiveValue(data, 'Connectable'); + var connectable = getManagedValue(data, 'Connectable'); if (connectState != 'Connected' && (!connectable || this.hasSecurity || (data.type == 'Wimax' || data.type == 'VPN'))) { @@ -946,7 +994,7 @@ cr.define('options.internet', function() { // Update our cached data object. updateDataObject(data, update); - var connectionState = getActiveValue(data, 'ConnectionState'); + var connectionState = getManagedValue(data, 'ConnectionState'); var connectionStateString = networkOncStateString(connectionState); detailsPage.deviceConnected = data.deviceConnected; detailsPage.connected = connectionState == 'Connected'; @@ -982,11 +1030,11 @@ cr.define('options.internet', function() { DetailsInternetPage.showDetailedInfo = function(data) { var detailsPage = DetailsInternetPage.getInstance(); - data.type = getActiveValue(data, 'Type'); // Get Active Type value. + data.type = getManagedValue(data, 'Type'); // Get Active Type value. // Populate header $('network-details-title').textContent = getNetworkName(data); - var connectionState = getActiveValue(data, 'ConnectionState'); + var connectionState = getManagedValue(data, 'ConnectionState'); var connectionStateString = networkOncStateString(connectionState); detailsPage.connected = connectionState == 'Connected'; $('network-details-subtitle-status').textContent = connectionStateString; @@ -1130,7 +1178,7 @@ cr.define('options.internet', function() { DetailsInternetPage.updateNameServerDisplay(data.nameServerType); - var macAddress = getActiveValue(data, 'MacAddress'); + var macAddress = getManagedValue(data, 'MacAddress'); if (macAddress) { $('hardware-address').textContent = macAddress; $('hardware-address-row').style.display = 'table-row'; @@ -1153,8 +1201,7 @@ cr.define('options.internet', function() { // Signal strength as percentage (for WiFi and Wimax). var signalStrength; if (data.type == 'WiFi' || data.type == 'Wimax') { - signalStrength = - getActiveDictionaryValue(data, data.type, 'SignalStrength'); + signalStrength = getManagedValue(data, data.type + '.SignalStrength'); } if (!signalStrength) signalStrength = 0; @@ -1163,21 +1210,20 @@ cr.define('options.internet', function() { detailsPage.type = data.type; if (data.type == 'WiFi') { - assert(data.WiFi, 'WiFi network has no WiFi object' + networkName); + assert('WiFi' in data, 'WiFi network has no WiFi object' + networkName); OptionsPage.showTab($('wifi-network-nav-tab')); detailsPage.gsm = false; detailsPage.shared = data.shared; $('wifi-connection-state').textContent = connectionStateString; - var ssid = getActiveDictionaryValue(data, 'WiFi', 'SSID'); + var ssid = getManagedValue(data, 'WiFi.SSID'); $('wifi-ssid').textContent = ssid ? ssid : networkName; - setOrHideParent('wifi-bssid', - getActiveDictionaryValue(data, 'WiFi', 'BSSID')); - var security = getActiveDictionaryValue(data, 'WiFi', 'Security'); + setOrHideParent('wifi-bssid', getManagedValue(data, 'WiFi.BSSID')); + var security = getManagedValue(data, 'WiFi.Security'); if (security == 'None') security = undefined; setOrHideParent('wifi-security', security); // Frequency is in MHz. - var frequency = getActiveDictionaryValue(data, 'WiFi', 'Frequency'); + var frequency = getManagedValue(data, 'WiFi.Frequency'); if (!frequency) frequency = 0; var frequencyFormat = loadTimeData.getString('inetFrequencyFormat'); @@ -1185,31 +1231,33 @@ cr.define('options.internet', function() { $('wifi-frequency').textContent = frequencyFormat; $('wifi-signal-strength').textContent = strengthString; setOrHideParent('wifi-hardware-address', - getActiveValue(data, 'MacAddress')); + getManagedValue(data, 'MacAddress')); detailsPage.showPreferred = data.remembered; - $('prefer-network-wifi').checked = data.preferred.value; + var priority = getManagedValue(data, 'Priority'); + $('prefer-network-wifi').checked = priority > 0; $('prefer-network-wifi').disabled = !data.remembered; $('auto-connect-network-wifi').checked = - getActiveValue(data, 'AutoConnect'); + getManagedValue(data, 'AutoConnect'); $('auto-connect-network-wifi').disabled = !data.remembered; detailsPage.hasSecurity = security != undefined; } else if (data.type == 'Wimax') { - assert(data.Wimax, 'Wimax network has no Wimax object' + networkName); + assert('Wimax' in data, + 'Wimax network has no Wimax object' + networkName); OptionsPage.showTab($('wimax-network-nav-tab')); detailsPage.gsm = false; detailsPage.shared = data.shared; detailsPage.showPreferred = data.remembered; $('wimax-connection-state').textContent = connectionStateString; $('auto-connect-network-wimax').checked = - getActiveValue(data, 'AutoConnect'); + getManagedValue(data, 'AutoConnect'); $('auto-connect-network-wimax').disabled = !data.remembered; var identity; if (data.Wimax.EAP) - identity = getActiveValue(data.Wimax.EAP, 'Identity'); + identity = getManagedValue(data.Wimax.EAP, 'Identity'); setOrHideParent('wimax-eap-identity', identity); $('wimax-signal-strength').textContent = strengthString; } else if (data.type == 'Cellular') { - assert(data.Cellular, + assert('Cellular' in data, 'Cellular network has no Cellular object' + networkName); OptionsPage.showTab($('cellular-conn-nav-tab')); if (data.showCarrierSelect && data.currentCarrierIndex != -1) { @@ -1227,27 +1275,29 @@ cr.define('options.internet', function() { } $('network-technology').textContent = - getActiveDictionaryValue(data, 'Cellular', 'NetworkTechnology'); + getManagedValue(data, 'Cellular.NetworkTechnology'); $('activation-state').textContent = data.activationState; $('roaming-state').textContent = data.roamingState; $('restricted-pool').textContent = data.restrictedPool; $('error-state').textContent = data.errorMessage; $('manufacturer').textContent = - getActiveDictionaryValue(data, 'Cellular', 'Manufacturer'); - $('model-id').textContent = - getActiveDictionaryValue(data, 'Cellular', 'ModelID'); + getManagedValue(data, 'Cellular.Manufacturer'); + $('model-id').textContent = getManagedValue(data, 'Cellular.ModelID'); $('firmware-revision').textContent = - getActiveDictionaryValue(data, 'Cellular', 'FirmwareRevision'); + getManagedValue(data, 'Cellular.FirmwareRevision'); $('hardware-revision').textContent = - getActiveDictionaryValue(data, 'Cellular', 'HardwareRevision'); - $('mdn').textContent = getActiveDictionaryValue(data, 'Cellular', 'MDN'); + getManagedValue(data, 'Cellular.HardwareRevision'); + $('mdn').textContent = getManagedValue(data, 'Cellular.MDN'); // Show ServingOperator properties only if available. - if (data.Cellular.ServingOperator) { - $('operator-name').textContent = - getActiveValue(data.Cellular.ServingOperator, 'Name'); - $('operator-code').textContent = - getActiveValue(data.Cellular.ServingOperator, 'Code'); + var servingOperatorName = + getManagedValue(data, 'Cellular.ServingOperator.Name'); + var servingOperatorCode = + getManagedValue(data, 'Cellular.ServingOperator.Code'); + if (servingOperatorName != undefined && + servingOperatorCode != undefined) { + $('operator-name').textContent = servingOperatorName; + $('operator-code').textContent = servingOperatorCode; } else { $('operator-name').parentElement.hidden = true; $('operator-code').parentElement.hidden = true; @@ -1258,23 +1308,18 @@ cr.define('options.internet', function() { updateHidden('#details-internet-page .cdma-only', false); // Show IMEI/ESN/MEID/MIN/PRL only if they are available. - setOrHideParent('esn', getActiveDictionaryValue(data, 'Cellular', 'ESN')); - setOrHideParent( - 'imei', getActiveDictionaryValue(data, 'Cellular', 'IMEI')); - setOrHideParent( - 'meid', getActiveDictionaryValue(data, 'Cellular', 'MEID')); - setOrHideParent('min', getActiveDictionaryValue(data, 'Cellular', 'MIN')); - setOrHideParent( - 'prl-version', - getActiveDictionaryValue(data, 'Cellular', 'PRLVersion')); - - var family = getActiveDictionaryValue(data, 'Cellular', 'GSM'); + setOrHideParent('esn', getManagedValue(data, 'Cellular.ESN')); + setOrHideParent('imei', getManagedValue(data, 'Cellular.IMEI')); + setOrHideParent('meid', getManagedValue(data, 'Cellular.MEID')); + setOrHideParent('min', getManagedValue(data, 'Cellular.MIN')); + setOrHideParent('prl-version', + getManagedValue(data, 'Cellular.PRLVersion')); + + var family = getManagedValue(data, 'Cellular.GSM'); detailsPage.gsm = family == 'GSM'; if (detailsPage.gsm) { - $('iccid').textContent = - getActiveDictionaryValue(data, 'Cellular', 'ICCID'); - $('imsi').textContent = - getActiveDictionaryValue(data, 'Cellular', 'IMSI'); + $('iccid').textContent = getManagedValue(data, 'Cellular.ICCID'); + $('imsi').textContent = getManagedValue(data, 'Cellular.IMSI'); var apnSelector = $('select-apn'); // Clear APN lists, keep only last element that "other". @@ -1324,7 +1369,7 @@ cr.define('options.internet', function() { $('change-pin').hidden = !lockEnabled; } $('auto-connect-network-cellular').checked = - getActiveValue(data, 'AutoConnect'); + getManagedValue(data, 'AutoConnect'); $('auto-connect-network-cellular').disabled = false; $('buyplan-details').hidden = !data.showBuyButton; @@ -1337,16 +1382,24 @@ cr.define('options.internet', function() { OptionsPage.showTab($('vpn-nav-tab')); detailsPage.gsm = false; $('inet-service-name').textContent = networkName; - $('inet-provider-type').textContent = data.providerType; - $('inet-username').textContent = data.username; + $('inet-provider-type').textContent = + getManagedValue(data, 'VPN.Type', GetManagedTypes.TRANSLATED); + var providerType = + getManagedValue(data, 'VPN.Type', GetManagedTypes.ACTIVE); + var providerKey = 'VPN.' + providerType; + $('inet-username').textContent = + getManagedValue(data, providerKey + '.Username'); var inetServerHostname = $('inet-server-hostname'); - inetServerHostname.value = data.serverHostname.value; + inetServerHostname.value = getManagedValue(data, 'VPN.Host'); inetServerHostname.resetHandler = function() { PageManager.hideBubble(); - inetServerHostname.value = data.serverHostname.recommendedValue; + var recommended = + getManagedValue(data, 'VPN.Host', GetManagedTypes.RECOMMENDED); + if (recommended != undefined) + inetServerHostname.value = recommended; }; $('auto-connect-network-vpn').checked = - getActiveValue(data, 'AutoConnect'); + getManagedValue(data, 'AutoConnect'); $('auto-connect-network-vpn').disabled = false; } else { OptionsPage.showTab($('internet-nav-tab')); @@ -1356,16 +1409,20 @@ cr.define('options.internet', function() { var indicators = cr.doc.querySelectorAll( '#details-internet-page .controlled-setting-indicator'); for (var i = 0; i < indicators.length; i++) { - var attributeName = - indicators[i].hasAttribute('managed') ? 'managed' : 'data'; + var managed = indicators[i].hasAttribute('managed'); + var attributeName = managed ? 'managed' : 'data'; var propName = indicators[i].getAttribute(attributeName); - if (!propName || !data[propName]) + if (!propName) + continue; + var propValue = + managed ? getManagedProperty(data, propName) : data[propName]; + if (propValue == undefined) continue; var event; - if (attributeName == 'managed') - event = detailsPage.createManagedEvent_(propName, data[propName]); + if (managed) + event = detailsPage.createManagedEvent_(propName, propValue); else - event = detailsPage.createControlledEvent_(propName, data[propName]); + event = detailsPage.createControlledEvent_(propName, propValue); indicators[i].handlePrefChange(event); var forElement = $(indicators[i].getAttribute('for')); if (forElement) { diff --git a/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc index c4c8e95..f49f63e 100644 --- a/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc +++ b/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc @@ -43,6 +43,7 @@ #include "chromeos/network/network_state_handler.h" #include "chromeos/network/network_util.h" #include "chromeos/network/onc/onc_signature.h" +#include "chromeos/network/onc/onc_translation_tables.h" #include "chromeos/network/onc/onc_translator.h" #include "chromeos/network/onc/onc_utils.h" #include "components/onc/onc_constants.h" @@ -62,6 +63,10 @@ namespace options { namespace { +// The key in a Managed Value dictionary for translated values. +// TODO(stevenjb): Consider making this part of the ONC spec. +const char kTranslatedKey[] = "Translated"; + // Keys for the network description dictionary passed to the web ui. Make sure // to keep the strings in sync with what the JavaScript side uses. const char kNetworkInfoKeyIconURL[] = "iconURL"; @@ -149,8 +154,6 @@ const char kTagNetworkId[] = "networkId"; const char kTagOptions[] = "options"; const char kTagPassword[] = "password"; const char kTagPolicy[] = "policy"; -const char kTagPreferred[] = "preferred"; -const char kTagProviderType[] = "providerType"; const char kTagProviderApnList[] = "providerApnList"; const char kTagRecommended[] = "recommended"; const char kTagRecommendedValue[] = "recommendedValue"; @@ -158,7 +161,6 @@ const char kTagRemembered[] = "remembered"; const char kTagRememberedList[] = "rememberedList"; const char kTagRestrictedPool[] = "restrictedPool"; const char kTagRoamingState[] = "roamingState"; -const char kTagServerHostname[] = "serverHostname"; const char kTagCarriers[] = "carriers"; const char kTagCurrentCarrierIndex[] = "currentCarrierIndex"; const char kTagShared[] = "shared"; @@ -334,20 +336,20 @@ const char* GetOncSettingString(::onc::ONCSource onc_source) { // Creates a GetManagedProperties style dictionary and adds it to |settings|. // |default_value| represents either the recommended value if |recommended| -// is true, or the enforced value if |recommended| is false. +// is true, or the enforced value if |recommended| is false. |settings_dict_key| +// is expected to be an ONC key with no '.' in it. // Note(stevenjb): This is bridge code until we use GetManagedProperties to // retrieve Shill properties. -void SetManagedValueDictionary(const char* key, - const base::Value* value, - ::onc::ONCSource onc_source, - bool recommended, - const base::Value* default_value, - base::DictionaryValue* settings) { +void SetManagedValueDictionaryEx(const char* settings_dict_key, + const base::Value& value, + ::onc::ONCSource onc_source, + bool recommended, + const base::Value* default_value, + base::DictionaryValue* settings_dict) { base::DictionaryValue* dict = new base::DictionaryValue(); - settings->Set(key, dict); + settings_dict->SetWithoutPathExpansion(settings_dict_key, dict); - DCHECK(value); - dict->Set(::onc::kAugmentationActiveSetting, value->DeepCopy()); + dict->Set(::onc::kAugmentationActiveSetting, value.DeepCopy()); if (onc_source == ::onc::ONC_SOURCE_NONE) return; @@ -360,9 +362,9 @@ void SetManagedValueDictionary(const char* key, if (default_value) { std::string policy_source = GetOncPolicyString(onc_source); dict->Set(policy_source, default_value->DeepCopy()); - if (recommended && !value->Equals(default_value)) { + if (recommended && !value.Equals(default_value)) { std::string setting_source = GetOncSettingString(onc_source); - dict->Set(setting_source, value->DeepCopy()); + dict->Set(setting_source, value.DeepCopy()); dict->SetString(::onc::kAugmentationEffectiveSetting, setting_source); } else { dict->SetString(::onc::kAugmentationEffectiveSetting, policy_source); @@ -370,6 +372,48 @@ void SetManagedValueDictionary(const char* key, } } +// Wrapper for SetManagedValueDictionaryEx that does the policy lookup. +// Note: We have to pass |onc_key| separately from |settings_dict_key| since +// we might be populating a sub-dictionary in which case |onc_key| will be the +// complete path (e.g. 'VPN.Host') and |settings_dict_key| is the dictionary key +// (e.g. 'Host'). +void SetManagedValueDictionary(const std::string& guid, + const char* settings_dict_key, + const base::Value& value, + const std::string& onc_key, + base::DictionaryValue* settings_dict) { + ::onc::ONCSource onc_source = ::onc::ONC_SOURCE_NONE; + const base::DictionaryValue* onc = + onc::FindPolicyForActiveUser(guid, &onc_source); + DCHECK_EQ(onc == NULL, onc_source == ::onc::ONC_SOURCE_NONE); + const base::Value* default_value = NULL; + bool recommended = false; + if (onc) { + onc->Get(onc_key, &default_value); + recommended = onc::IsRecommendedValue(onc, onc_key); + } + SetManagedValueDictionaryEx(settings_dict_key, + value, + onc_source, + recommended, + default_value, + settings_dict); +} + +// Creates a GetManagedProperties style dictionary with an Active value and +// a Translated value, and adds it to |settings|. +// Note(stevenjb): This is bridge code until we use GetManagedProperties to +// retrieve Shill properties and include Translated values. +void SetTranslatedDictionary(const char* settings_dict_key, + const std::string& value, + const std::string& translated_value, + base::DictionaryValue* settings_dict) { + base::DictionaryValue* dict = new base::DictionaryValue(); + settings_dict->Set(settings_dict_key, dict); + dict->SetString(::onc::kAugmentationActiveSetting, value); + dict->SetString(kTranslatedKey, translated_value); +} + std::string CopyStringFromDictionary(const base::DictionaryValue& source, const std::string& src_key, const std::string& dest_key, @@ -387,46 +431,55 @@ void PopulateVPNDetails(const NetworkState* vpn, base::DictionaryValue* dictionary) { // Name and Remembered are set in PopulateConnectionDetails(). // Provider properties are stored in the "Provider" dictionary. - const base::DictionaryValue* provider_properties = NULL; + const base::DictionaryValue* shill_provider_properties = NULL; if (!shill_properties.GetDictionaryWithoutPathExpansion( - shill::kProviderProperty, &provider_properties)) { + shill::kProviderProperty, &shill_provider_properties)) { LOG(ERROR) << "No provider properties for VPN: " << vpn->path(); return; } - std::string provider_type; - provider_properties->GetStringWithoutPathExpansion( - shill::kTypeProperty, &provider_type); - dictionary->SetString(kTagProviderType, - internet_options_strings::ProviderTypeString( - provider_type, - *provider_properties)); + base::DictionaryValue* vpn_dictionary = new base::DictionaryValue; + dictionary->Set(::onc::network_config::kVPN, vpn_dictionary); + std::string shill_provider_type; + if (!shill_provider_properties->GetStringWithoutPathExpansion( + shill::kTypeProperty, &shill_provider_type)) { + LOG(ERROR) << "Shill VPN has no Provider.Type: " << vpn->path(); + return; + } + std::string onc_provider_type; + onc::TranslateStringToONC( + onc::kVPNTypeTable, shill_provider_type, &onc_provider_type); + SetTranslatedDictionary( + ::onc::vpn::kType, + onc_provider_type, + internet_options_strings::ProviderTypeString(shill_provider_type, + *shill_provider_properties), + vpn_dictionary); + + std::string provider_type_key; std::string username; - if (provider_type == shill::kProviderOpenVpn) { - provider_properties->GetStringWithoutPathExpansion( + if (shill_provider_type == shill::kProviderOpenVpn) { + provider_type_key = ::onc::vpn::kOpenVPN; + shill_provider_properties->GetStringWithoutPathExpansion( shill::kOpenVPNUserProperty, &username); } else { - provider_properties->GetStringWithoutPathExpansion( + provider_type_key = ::onc::vpn::kL2TP; + shill_provider_properties->GetStringWithoutPathExpansion( shill::kL2tpIpsecUserProperty, &username); } - dictionary->SetString(kTagUsername, username); + base::DictionaryValue* provider_type_dictionary = new base::DictionaryValue; + vpn_dictionary->Set(provider_type_key, provider_type_dictionary); + provider_type_dictionary->SetString(::onc::vpn::kUsername, username); - ::onc::ONCSource onc_source = ::onc::ONC_SOURCE_NONE; - const base::DictionaryValue* onc = - onc::FindPolicyForActiveUser(vpn->guid(), &onc_source); - - NetworkPropertyUIData hostname_ui_data; - hostname_ui_data.ParseOncProperty( - onc_source, - onc, - ::onc::network_config::VpnProperty(::onc::vpn::kHost)); std::string provider_host; - provider_properties->GetStringWithoutPathExpansion( + shill_provider_properties->GetStringWithoutPathExpansion( shill::kHostProperty, &provider_host); - SetValueDictionary(kTagServerHostname, - new base::StringValue(provider_host), - hostname_ui_data, - dictionary); + SetManagedValueDictionary( + vpn->guid(), + ::onc::vpn::kHost, + base::StringValue(provider_host), + ::onc::network_config::VpnProperty(::onc::vpn::kHost), + vpn_dictionary); } // Given a list of supported carrier's by the device, return the index of @@ -1332,11 +1385,11 @@ void InternetOptionsHandler::PopulateDictionaryDetailsCallback( int priority = 0; shill_properties.GetIntegerWithoutPathExpansion( shill::kPriorityProperty, &priority); - bool preferred = priority > 0; - SetValueDictionary(kTagPreferred, - new base::FundamentalValue(preferred), - property_ui_data, - dictionary.get()); + SetManagedValueDictionary(network->guid(), + ::onc::network_config::kPriority, + base::FundamentalValue(priority), + ::onc::network_config::kPriority, + dictionary.get()); std::string onc_path_to_auto_connect; if (network->Matches(NetworkTypePattern::WiFi())) { @@ -1371,8 +1424,7 @@ void InternetOptionsHandler::PopulateDictionaryDetailsCallback( shill_properties.GetBooleanWithoutPathExpansion( shill::kAutoConnectProperty, &auto_connect); - scoped_ptr<base::Value> auto_connect_value( - new base::FundamentalValue(auto_connect)); + base::FundamentalValue auto_connect_value(auto_connect); ::onc::ONCSource auto_connect_onc_source = onc_source; DCHECK_EQ(onc == NULL, onc_source == ::onc::ONC_SOURCE_NONE); @@ -1397,15 +1449,15 @@ void InternetOptionsHandler::PopulateDictionaryDetailsCallback( : ::onc::ONC_SOURCE_DEVICE_POLICY; if (auto_connect) { LOG(WARNING) << "Policy prevents autoconnect, but value is True."; - auto_connect_value.reset(new base::FundamentalValue(false)); + auto_connect_value = base::FundamentalValue(false); } } - SetManagedValueDictionary(shill::kAutoConnectProperty, - auto_connect_value.get(), - auto_connect_onc_source, - auto_connect_recommended, - auto_connect_default_value, - dictionary.get()); + SetManagedValueDictionaryEx(shill::kAutoConnectProperty, + auto_connect_value, + auto_connect_onc_source, + auto_connect_recommended, + auto_connect_default_value, + dictionary.get()); } // Show details dialog diff --git a/chromeos/network/onc/onc_signature.cc b/chromeos/network/onc/onc_signature.cc index 4e1bdeb..2b750fb 100644 --- a/chromeos/network/onc/onc_signature.cc +++ b/chromeos/network/onc/onc_signature.cc @@ -290,6 +290,7 @@ const OncFieldSignature network_configuration_fields[] = { { ::onc::network_config::kName, &kStringSignature}, // Not supported, yet. { ::onc::network_config::kNameServers, &kStringListSignature}, + { ::onc::network_config::kPriority, &kIntegerSignature}, { ::onc::network_config::kProxySettings, &kProxySettingsSignature}, { ::onc::kRemove, &kBoolSignature}, // Not supported, yet. diff --git a/chromeos/network/onc/onc_translation_tables.cc b/chromeos/network/onc/onc_translation_tables.cc index 119b62b..3cf512c 100644 --- a/chromeos/network/onc/onc_translation_tables.cc +++ b/chromeos/network/onc/onc_translation_tables.cc @@ -43,7 +43,8 @@ const FieldTranslationEntry ipsec_fields[] = { // Ignored by Shill, not necessary to synchronize. // { ::onc::ipsec::kIKEVersion, shill::kL2tpIpsecIkeVersion }, { ::onc::ipsec::kPSK, shill::kL2tpIpsecPskProperty}, - { ::onc::vpn::kSaveCredentials, shill::kSaveCredentialsProperty}, + // This field is converted during translation, see onc_translator_*. + // { ::onc::vpn::kSaveCredentials, shill::kSaveCredentialsProperty}, { ::onc::ipsec::kServerCAPEMs, shill::kL2tpIpsecCaCertPemProperty}, {NULL}}; @@ -55,8 +56,7 @@ const FieldTranslationEntry xauth_fields[] = { const FieldTranslationEntry l2tp_fields[] = { { ::onc::vpn::kPassword, shill::kL2tpIpsecPasswordProperty}, // We don't synchronize l2tp's SaveCredentials field for now, as Shill - // doesn't - // support separate settings for ipsec and l2tp. + // doesn't support separate settings for ipsec and l2tp. // { ::onc::vpn::kSaveCredentials, &kBoolSignature }, { ::onc::vpn::kUsername, shill::kL2tpIpsecUserProperty}, {NULL}}; @@ -80,7 +80,8 @@ const FieldTranslationEntry openvpn_fields[] = { // { ::onc::openvpn::kRemoteCertKU, shill::kOpenVPNRemoteCertKUProperty }, { ::onc::openvpn::kRemoteCertTLS, shill::kOpenVPNRemoteCertTLSProperty}, { ::onc::openvpn::kRenegSec, shill::kOpenVPNRenegSecProperty}, - { ::onc::vpn::kSaveCredentials, shill::kSaveCredentialsProperty}, + // This field is converted during translation, see onc_translator_*. + // { ::onc::vpn::kSaveCredentials, shill::kSaveCredentialsProperty}, { ::onc::openvpn::kServerCAPEMs, shill::kOpenVPNCaCertPemProperty}, { ::onc::openvpn::kServerPollTimeout, shill::kOpenVPNServerPollTimeoutProperty}, @@ -99,8 +100,8 @@ const FieldTranslationEntry verify_x509_fields[] = { const FieldTranslationEntry vpn_fields[] = { { ::onc::vpn::kAutoConnect, shill::kAutoConnectProperty}, - { ::onc::vpn::kHost, shill::kProviderHostProperty}, - // This field is converted during translation, see onc_translator_*. + // These fields are converted during translation, see onc_translator_*. + // { ::onc::vpn::kHost, shill::kProviderHostProperty}, // { ::onc::vpn::kType, shill::kProviderTypeProperty }, {NULL}}; @@ -159,6 +160,7 @@ const FieldTranslationEntry network_fields[] = { { ::onc::network_config::kGUID, shill::kGuidProperty}, { ::onc::network_config::kConnectable, shill::kConnectableProperty }, { ::onc::network_config::kErrorState, shill::kErrorProperty }, + { ::onc::network_config::kPriority, shill::kPriorityProperty }, // Shill doesn't allow setting the name for non-VPN networks. // Name is conditionally translated, see onc_translator_*. diff --git a/chromeos/network/onc/onc_translation_tables.h b/chromeos/network/onc/onc_translation_tables.h index 4563b66..1053f37 100644 --- a/chromeos/network/onc/onc_translation_tables.h +++ b/chromeos/network/onc/onc_translation_tables.h @@ -8,6 +8,7 @@ #include <string> #include <vector> +#include "chromeos/chromeos_export.h" #include "chromeos/network/onc/onc_signature.h" namespace chromeos { @@ -25,12 +26,12 @@ struct StringTranslationEntry { // These tables contain the mapping from ONC strings to Shill strings. // These are NULL-terminated arrays. -extern const StringTranslationEntry kNetworkTypeTable[]; -extern const StringTranslationEntry kVPNTypeTable[]; -extern const StringTranslationEntry kWiFiSecurityTable[]; -extern const StringTranslationEntry kEAPOuterTable[]; -extern const StringTranslationEntry kEAP_PEAP_InnerTable[]; -extern const StringTranslationEntry kEAP_TTLS_InnerTable[]; +CHROMEOS_EXPORT extern const StringTranslationEntry kNetworkTypeTable[]; +CHROMEOS_EXPORT extern const StringTranslationEntry kVPNTypeTable[]; +CHROMEOS_EXPORT extern const StringTranslationEntry kWiFiSecurityTable[]; +CHROMEOS_EXPORT extern const StringTranslationEntry kEAPOuterTable[]; +CHROMEOS_EXPORT extern const StringTranslationEntry kEAP_PEAP_InnerTable[]; +CHROMEOS_EXPORT extern const StringTranslationEntry kEAP_TTLS_InnerTable[]; // A separate translation table for cellular properties that are stored in a // Shill Device instead of a Service. The |shill_property_name| entries @@ -48,14 +49,15 @@ bool GetShillPropertyName(const std::string& onc_field_name, std::string* shill_property_name); // Translate individual strings to Shill using the above tables. -bool TranslateStringToShill(const StringTranslationEntry table[], - const std::string& onc_value, - std::string* shill_value); +CHROMEOS_EXPORT bool TranslateStringToShill( + const StringTranslationEntry table[], + const std::string& onc_value, + std::string* shill_value); // Translate individual strings to ONC using the above tables. -bool TranslateStringToONC(const StringTranslationEntry table[], - const std::string& shill_value, - std::string* onc_value); +CHROMEOS_EXPORT bool TranslateStringToONC(const StringTranslationEntry table[], + const std::string& shill_value, + std::string* onc_value); } // namespace onc } // namespace chromeos diff --git a/chromeos/network/onc/onc_translator_onc_to_shill.cc b/chromeos/network/onc/onc_translator_onc_to_shill.cc index 2fd411f..e7e7782 100644 --- a/chromeos/network/onc/onc_translator_onc_to_shill.cc +++ b/chromeos/network/onc/onc_translator_onc_to_shill.cc @@ -55,6 +55,7 @@ class LocalTranslator { private: void TranslateEthernet(); void TranslateOpenVPN(); + void TranslateIPsec(); void TranslateVPN(); void TranslateWiFi(); void TranslateEAP(); @@ -94,6 +95,8 @@ void LocalTranslator::TranslateFields() { TranslateVPN(); else if (onc_signature_ == &kOpenVPNSignature) TranslateOpenVPN(); + else if (onc_signature_ == &kIPsecSignature) + TranslateIPsec(); else if (onc_signature_ == &kWiFiSignature) TranslateWiFi(); else if (onc_signature_ == &kEAPSignature) @@ -117,6 +120,14 @@ void LocalTranslator::TranslateEthernet() { } void LocalTranslator::TranslateOpenVPN() { + // SaveCredentials needs special handling when translating from Shill -> ONC + // so handle it explicitly here. + bool save_credentials; + if (onc_object_->GetBooleanWithoutPathExpansion( + ::onc::vpn::kSaveCredentials, &save_credentials)) { + shill_dictionary_->SetBooleanWithoutPathExpansion( + shill::kSaveCredentialsProperty, save_credentials); + } // Shill supports only one RemoteCertKU but ONC a list. // Copy only the first entry if existing. const base::ListValue* certKUs = NULL; @@ -131,8 +142,7 @@ void LocalTranslator::TranslateOpenVPN() { for (base::DictionaryValue::Iterator it(*onc_object_); !it.IsAtEnd(); it.Advance()) { scoped_ptr<base::Value> translated; - if (it.key() == ::onc::vpn::kSaveCredentials || - it.key() == ::onc::openvpn::kRemoteCertKU || + if (it.key() == ::onc::openvpn::kRemoteCertKU || it.key() == ::onc::openvpn::kServerCAPEMs) { translated.reset(it.value().DeepCopy()); } else { @@ -143,7 +153,25 @@ void LocalTranslator::TranslateOpenVPN() { } } +void LocalTranslator::TranslateIPsec() { + CopyFieldsAccordingToSignature(); + + // SaveCredentials needs special handling when translating from Shill -> ONC + // so handle it explicitly here. + bool save_credentials; + if (onc_object_->GetBooleanWithoutPathExpansion( + ::onc::vpn::kSaveCredentials, &save_credentials)) { + shill_dictionary_->SetBooleanWithoutPathExpansion( + shill::kSaveCredentialsProperty, save_credentials); + } +} + void LocalTranslator::TranslateVPN() { + std::string host; + if (onc_object_->GetStringWithoutPathExpansion(::onc::vpn::kHost, &host)) { + shill_dictionary_->SetStringWithoutPathExpansion( + shill::kProviderHostProperty, host); + } std::string type; onc_object_->GetStringWithoutPathExpansion(::onc::vpn::kType, &type); TranslateWithTableAndSet(type, kVPNTypeTable, shill::kProviderTypeProperty); diff --git a/chromeos/network/onc/onc_translator_shill_to_onc.cc b/chromeos/network/onc/onc_translator_shill_to_onc.cc index 19e7eff..224e26c 100644 --- a/chromeos/network/onc/onc_translator_shill_to_onc.cc +++ b/chromeos/network/onc/onc_translator_shill_to_onc.cc @@ -89,6 +89,12 @@ class ShillToONCTranslator { // |onc_field_name|. void TranslateAndAddNestedObject(const std::string& onc_field_name); + // Sets |onc_field_name| in dictionary |onc_dictionary_name| in |onc_object_| + // to |value| if the dictionary exists. + void SetNestedOncValue(const std::string& onc_dictionary_name, + const std::string& onc_field_name, + const base::Value& value); + // Translates a list of nested objects and adds the list to |onc_object_| at // |onc_field_name|. If there are errors while parsing individual objects or // if the resulting list contains no entries, the result will not be added to @@ -117,6 +123,10 @@ class ShillToONCTranslator { const StringTranslationEntry table[], const std::string& onc_field_name); + // Returns the name of the Shill service provided in |shill_dictionary_| + // for debugging. + std::string GetName(); + const base::DictionaryValue* shill_dictionary_; const OncValueSignature* onc_signature_; const FieldTranslationEntry* field_translation_table_; @@ -182,8 +192,7 @@ void ShillToONCTranslator::TranslateOpenVPN() { for (const OncFieldSignature* field_signature = onc_signature_->fields; field_signature->onc_field_name != NULL; ++field_signature) { const std::string& onc_field_name = field_signature->onc_field_name; - if (onc_field_name == ::onc::vpn::kSaveCredentials || - onc_field_name == ::onc::openvpn::kRemoteCertKU || + if (onc_field_name == ::onc::openvpn::kRemoteCertKU || onc_field_name == ::onc::openvpn::kServerCAPEMs) { CopyProperty(field_signature); continue; @@ -213,7 +222,8 @@ void ShillToONCTranslator::TranslateOpenVPN() { LOG(ERROR) << "Shill property '" << shill_property_name << "' with value " << *shill_value << " couldn't be converted to base::Value::Type " - << field_signature->value_signature->onc_type; + << field_signature->value_signature->onc_type + << ": " << GetName(); } else { onc_object_->SetWithoutPathExpansion(onc_field_name, translated.release()); @@ -221,7 +231,7 @@ void ShillToONCTranslator::TranslateOpenVPN() { } else { LOG(ERROR) << "Shill property '" << shill_property_name << "' has value " << *shill_value - << ", but expected a string"; + << ", but expected a string: " << GetName(); } } } @@ -233,19 +243,48 @@ void ShillToONCTranslator::TranslateIPsec() { } void ShillToONCTranslator::TranslateVPN() { - TranslateWithTableAndSet( - shill::kProviderTypeProperty, kVPNTypeTable, ::onc::vpn::kType); CopyPropertiesAccordingToSignature(); - std::string vpn_type; - if (onc_object_->GetStringWithoutPathExpansion(::onc::vpn::kType, - &vpn_type)) { - if (vpn_type == ::onc::vpn::kTypeL2TP_IPsec) { - TranslateAndAddNestedObject(::onc::vpn::kIPsec); - TranslateAndAddNestedObject(::onc::vpn::kL2TP); - } else { - TranslateAndAddNestedObject(vpn_type); - } + // Parse Shill Provider dictionary. Note, this may not exist, e.g. if we are + // just translating network state in network_util::TranslateNetworkStateToONC. + const base::DictionaryValue* provider = NULL; + if (!shill_dictionary_->GetDictionaryWithoutPathExpansion( + shill::kProviderProperty, &provider)) { + return; + } + std::string shill_provider_type, onc_provider_type; + provider->GetStringWithoutPathExpansion(shill::kTypeProperty, + &shill_provider_type); + if (!TranslateStringToONC( + kVPNTypeTable, shill_provider_type, &onc_provider_type)) { + return; + } + onc_object_->SetStringWithoutPathExpansion(::onc::vpn::kType, + onc_provider_type); + std::string provider_host; + if (provider->GetStringWithoutPathExpansion(shill::kHostProperty, + &provider_host)) { + onc_object_->SetStringWithoutPathExpansion(::onc::vpn::kHost, + provider_host); + } + + // Translate the nested dictionary. + std::string provider_type_dictionary; + if (onc_provider_type == ::onc::vpn::kTypeL2TP_IPsec) { + TranslateAndAddNestedObject(::onc::vpn::kIPsec, *provider); + TranslateAndAddNestedObject(::onc::vpn::kL2TP, *provider); + provider_type_dictionary = ::onc::vpn::kIPsec; + } else { + TranslateAndAddNestedObject(onc_provider_type, *provider); + provider_type_dictionary = onc_provider_type; + } + + bool save_credentials; + if (shill_dictionary_->GetBooleanWithoutPathExpansion( + shill::kSaveCredentialsProperty, &save_credentials)) { + SetNestedOncValue(provider_type_dictionary, + ::onc::vpn::kSaveCredentials, + base::FundamentalValue(save_credentials)); } } @@ -411,6 +450,19 @@ void ShillToONCTranslator::TranslateAndAddNestedObject( onc_object_->SetWithoutPathExpansion(onc_field_name, nested_object.release()); } +void ShillToONCTranslator::SetNestedOncValue( + const std::string& onc_dictionary_name, + const std::string& onc_field_name, + const base::Value& value) { + base::DictionaryValue* nested; + if (!onc_object_->GetDictionaryWithoutPathExpansion( + onc_dictionary_name, &nested)) { + nested = new base::DictionaryValue; + onc_object_->SetWithoutPathExpansion(onc_dictionary_name, nested); + } + nested->SetWithoutPathExpansion(onc_field_name, value.DeepCopy()); +} + void ShillToONCTranslator::TranslateAndAddListOfObjects( const std::string& onc_field_name, const base::ListValue& list) { @@ -419,7 +471,7 @@ void ShillToONCTranslator::TranslateAndAddListOfObjects( if (field_signature->value_signature->onc_type != base::Value::TYPE_LIST) { LOG(ERROR) << "ONC Field name: '" << onc_field_name << "' has type '" << field_signature->value_signature->onc_type - << "', expected: base::Value::TYPE_LIST."; + << "', expected: base::Value::TYPE_LIST: " << GetName(); return; } DCHECK(field_signature->value_signature->onc_array_entry_signature); @@ -478,7 +530,8 @@ void ShillToONCTranslator::CopyProperty( << " has base::Value::Type " << shill_value->GetType() << " but ONC field '" << field_signature->onc_field_name << "' requires type " - << field_signature->value_signature->onc_type << "."; + << field_signature->value_signature->onc_type + << ": " << GetName(); return; } @@ -501,7 +554,14 @@ void ShillToONCTranslator::TranslateWithTableAndSet( return; } LOG(ERROR) << "Shill property '" << shill_property_name << "' with value " - << shill_value << " couldn't be translated to ONC"; + << shill_value << " couldn't be translated to ONC: " << GetName(); +} + +std::string ShillToONCTranslator::GetName() { + DCHECK(shill_dictionary_); + std::string name; + shill_dictionary_->GetStringWithoutPathExpansion(shill::kNameProperty, &name); + return name; } } // namespace diff --git a/chromeos/network/onc/onc_translator_unittest.cc b/chromeos/network/onc/onc_translator_unittest.cc index 29a77b9..bce14cb 100644 --- a/chromeos/network/onc/onc_translator_unittest.cc +++ b/chromeos/network/onc/onc_translator_unittest.cc @@ -98,11 +98,11 @@ INSTANTIATE_TEST_CASE_P( "translation_of_shill_wifi_clientcert.onc"), std::make_pair("shill_wifi_wpa1.json", "translation_of_shill_wifi_wpa1.onc"), - std::make_pair("shill_l2tpipsec.json", + std::make_pair("shill_output_l2tpipsec.json", "translation_of_shill_l2tpipsec.onc"), - std::make_pair("shill_openvpn.json", + std::make_pair("shill_output_openvpn.json", "translation_of_shill_openvpn.onc"), - std::make_pair("shill_openvpn_with_errors.json", + std::make_pair("shill_output_openvpn_with_errors.json", "translation_of_shill_openvpn_with_errors.onc"), std::make_pair("shill_wifi_with_state.json", "translation_of_shill_wifi_with_state.onc"), diff --git a/chromeos/test/data/network/shill_openvpn_with_errors.json b/chromeos/test/data/network/shill_openvpn_with_errors.json deleted file mode 100644 index 9ac9d53..0000000 --- a/chromeos/test/data/network/shill_openvpn_with_errors.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - // Missing GUID. - "Type": "vpn", - "Name": "my vpn", - // String instead of Int. - "SaveCredentials": "false", - "Provider.Type": "openvpn", - "Provider.Host": "vpn.my.domain.com", - "OpenVPN.AuthRetry": "interact", - "OpenVPN.User": "abc ${LOGIN_EMAIL} def", - "OpenVPN.Password": "some password", - "OpenVPN.StaticChallenge": "Please enter token OTP", - "OpenVPN.CompLZO": "true", - // Int instead of String. - "OpenVPN.ServerPollTimeout": 10, - "OpenVPN.RemoteCertKU": "e0", - "OpenVPN.RemoteCertTLS": "server", - "OpenVPN.Port": "443", - "OpenVPN.TLSRemote": "my.domain.com", - "OpenVPN.KeyDirection": "1", - "OpenVPN.RenegSec": "0", - "OpenVPN.RemoteCertEKU": "TLS Web Server Authentication", - "OpenVPN.Proto": "udp", - "OpenVPN.PushPeerInfo": "true", - "OpenVPN.TLSAuthContents": "-----BEGIN OpenVPN Static key V1-----\n83f8e7ccd99be189b4663e18615f9166\nd885cdea6c8accb0ebf5be304f0b8081\n5404f2a6574e029815d7a2fb65b83d0c\n676850714c6a56b23415a78e06aad6b1\n34900dd512049598382039e4816cb5ff\n1848532b71af47578c9b4a14b5bca49f\n99e0ae4dae2f4e5eadfea374aeb8fb1e\na6fdf02adc73ea778dfd43d64bf7bc75\n7779d629498f8c2fbfd32812bfdf6df7\n8cebafafef3e5496cb13202274f2768a\n1959bc53d67a70945c4c8c6f34b63327\nfb60dc84990ffec1243461e0b6310f61\ne90aee1f11fb6292d6f5fcd7cd508aab\n50d80f9963589c148cb4b933ec86128d\ned77d3fad6005b62f36369e2319f52bd\n09c6d2e52cce2362a05009dc29b6b39a\n-----END OpenVPN Static key V1-----\n" -} diff --git a/chromeos/test/data/network/shill_output_l2tpipsec.json b/chromeos/test/data/network/shill_output_l2tpipsec.json new file mode 100644 index 0000000..4848ab4 --- /dev/null +++ b/chromeos/test/data/network/shill_output_l2tpipsec.json @@ -0,0 +1,14 @@ +{ "GUID": "guid", + "Type": "vpn", + "Name": "MyL2TPVPN", + "Provider": { + "Host": "some.host.org", + "L2TPIPsec.PSK": "some_preshared_key", + "L2TPIPsec.User": "some username", + "L2TPIPsec.XauthPassword": "some xauth password", + "L2TPIPsec.XauthUser": "some xauth username", + "L2TPIPsec.Password": "some password", + "Type": "l2tpipsec", + }, + "SaveCredentials": true +} diff --git a/chromeos/test/data/network/shill_output_openvpn.json b/chromeos/test/data/network/shill_output_openvpn.json new file mode 100644 index 0000000..692834c --- /dev/null +++ b/chromeos/test/data/network/shill_output_openvpn.json @@ -0,0 +1,34 @@ +{ + "AutoConnect":true, + "GUID":"{a3860e83-f03d-4cb1-bafa-b22c9e746950}", + "Name":"my vpn", + "Provider": { + "Host":"vpn.my.domain.com", + "OpenVPN.AuthRetry":"interact", + "OpenVPN.CACertPEM":[ + "pem1", + "pem2" + ], + "OpenVPN.CompLZO":"true", + "OpenVPN.KeyDirection":"1", + "OpenVPN.Password":"some password", + "OpenVPN.Port":"443", + "OpenVPN.Proto":"udp", + "OpenVPN.PushPeerInfo":"true", + "OpenVPN.RemoteCertEKU":"TLS Web Server Authentication", + "OpenVPN.RemoteCertKU":"e0", + "OpenVPN.RemoteCertTLS":"server", + "OpenVPN.RenegSec":"0", + "OpenVPN.ServerPollTimeout":"10", + "OpenVPN.StaticChallenge":"Please enter token OTP", + "OpenVPN.TLSAuthContents":"-----BEGIN OpenVPN Static key V1-----\n83f8e7ccd99be189b4663e18615f9166\nd885cdea6c8accb0ebf5be304f0b8081\n5404f2a6574e029815d7a2fb65b83d0c\n676850714c6a56b23415a78e06aad6b1\n34900dd512049598382039e4816cb5ff\n1848532b71af47578c9b4a14b5bca49f\n99e0ae4dae2f4e5eadfea374aeb8fb1e\na6fdf02adc73ea778dfd43d64bf7bc75\n7779d629498f8c2fbfd32812bfdf6df7\n8cebafafef3e5496cb13202274f2768a\n1959bc53d67a70945c4c8c6f34b63327\nfb60dc84990ffec1243461e0b6310f61\ne90aee1f11fb6292d6f5fcd7cd508aab\n50d80f9963589c148cb4b933ec86128d\ned77d3fad6005b62f36369e2319f52bd\n09c6d2e52cce2362a05009dc29b6b39a\n-----END OpenVPN Static key V1-----\n", + "OpenVPN.TLSRemote":"my.domain.com", + "OpenVPN.User":"abc ${LOGIN_EMAIL} def", + "OpenVPN.VerifyHash":"some hash", + "OpenVPN.VerifyX509Name":"some x509 name", + "OpenVPN.VerifyX509Type":"name-prefix", + "Type":"openvpn", + }, + "SaveCredentials":false, + "Type":"vpn" +} diff --git a/chromeos/test/data/network/shill_output_openvpn_with_errors.json b/chromeos/test/data/network/shill_output_openvpn_with_errors.json new file mode 100644 index 0000000..3639283 --- /dev/null +++ b/chromeos/test/data/network/shill_output_openvpn_with_errors.json @@ -0,0 +1,28 @@ +{ + // Missing GUID. + "Type": "vpn", + "Name": "my vpn", + // String instead of Boolean. + "SaveCredentials": "false!", + "Provider": { + "Host": "vpn.my.domain.com", + "OpenVPN.AuthRetry": "interact", + "OpenVPN.User": "abc ${LOGIN_EMAIL} def", + "OpenVPN.Password": "some password", + "OpenVPN.StaticChallenge": "Please enter token OTP", + "OpenVPN.CompLZO": "true", + // Int instead of String. + "OpenVPN.ServerPollTimeout": 10, + "OpenVPN.RemoteCertKU": "e0", + "OpenVPN.RemoteCertTLS": "server", + "OpenVPN.Port": "443", + "OpenVPN.TLSRemote": "my.domain.com", + "OpenVPN.KeyDirection": "1", + "OpenVPN.RenegSec": "0", + "OpenVPN.RemoteCertEKU": "TLS Web Server Authentication", + "OpenVPN.Proto": "udp", + "OpenVPN.PushPeerInfo": "true", + "OpenVPN.TLSAuthContents": "-----BEGIN OpenVPN Static key V1-----\n83f8e7ccd99be189b4663e18615f9166\nd885cdea6c8accb0ebf5be304f0b8081\n5404f2a6574e029815d7a2fb65b83d0c\n676850714c6a56b23415a78e06aad6b1\n34900dd512049598382039e4816cb5ff\n1848532b71af47578c9b4a14b5bca49f\n99e0ae4dae2f4e5eadfea374aeb8fb1e\na6fdf02adc73ea778dfd43d64bf7bc75\n7779d629498f8c2fbfd32812bfdf6df7\n8cebafafef3e5496cb13202274f2768a\n1959bc53d67a70945c4c8c6f34b63327\nfb60dc84990ffec1243461e0b6310f61\ne90aee1f11fb6292d6f5fcd7cd508aab\n50d80f9963589c148cb4b933ec86128d\ned77d3fad6005b62f36369e2319f52bd\n09c6d2e52cce2362a05009dc29b6b39a\n-----END OpenVPN Static key V1-----\n", + "Type": "openvpn" + } +} diff --git a/chromeos/test/data/network/shill_wifi_with_state.json b/chromeos/test/data/network/shill_wifi_with_state.json index 865162b..8ae1dc5 100644 --- a/chromeos/test/data/network/shill_wifi_with_state.json +++ b/chromeos/test/data/network/shill_wifi_with_state.json @@ -1,9 +1,11 @@ { "AutoConnect": true, + "Connectable": true, "GUID": "{64c4f86b-cf6a-4e4a-8eff-456def}", "Mode": "managed", "Name": "OpenWrt", "Passphrase": "some passphrase", + "Priority": 1, "Security": "psk", "State": "idle", "Strength": 10, diff --git a/chromeos/test/data/network/translation_of_shill_l2tpipsec.onc b/chromeos/test/data/network/translation_of_shill_l2tpipsec.onc index 1e6d3da..271a7182 100644 --- a/chromeos/test/data/network/translation_of_shill_l2tpipsec.onc +++ b/chromeos/test/data/network/translation_of_shill_l2tpipsec.onc @@ -20,7 +20,7 @@ }, "L2TP": { "Username": "some username", - "Password": "some password" - } + "Password": "some password", + }, } } diff --git a/chromeos/test/data/network/translation_of_shill_wifi_with_state.onc b/chromeos/test/data/network/translation_of_shill_wifi_with_state.onc index c49bf16..d149a43 100644 --- a/chromeos/test/data/network/translation_of_shill_wifi_with_state.onc +++ b/chromeos/test/data/network/translation_of_shill_wifi_with_state.onc @@ -1,6 +1,8 @@ { + "Connectable": true, "GUID": "{64c4f86b-cf6a-4e4a-8eff-456def}", "Name": "OpenWrt", + "Priority": 1, "Type": "WiFi", "WiFi": { "AutoConnect": true, diff --git a/components/onc/docs/onc_spec.html b/components/onc/docs/onc_spec.html index 4b72a3e..6822117 100644 --- a/components/onc/docs/onc_spec.html +++ b/components/onc/docs/onc_spec.html @@ -400,6 +400,17 @@ networks. The format is 00:11:22:AA:BB:CC. </dd> + <dt class="field">Priority</dt> + <dd> + <span class="field_meta"> + (optional) + <span class="type">integer</span> + </span> + Provides a suggested priority value for this network. May be used by the + system to determine which network to connect to when multiple configured + networks are available (or may be ignored). + </dd> + </dl> <section> diff --git a/components/onc/onc_constants.cc b/components/onc/onc_constants.cc index 1c1dccda..4909aed 100644 --- a/components/onc/onc_constants.cc +++ b/components/onc/onc_constants.cc @@ -41,6 +41,7 @@ const char kIPConfigs[] = "IPConfigs"; const char kMacAddress[] = "MacAddress"; const char kName[] = "Name"; const char kNameServers[] = "NameServers"; +const char kPriority[] = "Priority"; const char kProxySettings[] = "ProxySettings"; const char kSearchDomains[] = "SearchDomains"; const char kConnectionState[] = "ConnectionState"; diff --git a/components/onc/onc_constants.h b/components/onc/onc_constants.h index 5db4c92..371570c 100644 --- a/components/onc/onc_constants.h +++ b/components/onc/onc_constants.h @@ -65,6 +65,7 @@ ONC_EXPORT extern const char kIPConfigs[]; ONC_EXPORT extern const char kMacAddress[]; ONC_EXPORT extern const char kName[]; ONC_EXPORT extern const char kNameServers[]; +ONC_EXPORT extern const char kPriority[]; ONC_EXPORT extern const char kProxySettings[]; ONC_EXPORT extern const char kSearchDomains[]; ONC_EXPORT extern const char kConnectionState[]; |