Commit 7eec1c62 authored by Steven Bennetts's avatar Steven Bennetts Committed by Commit Bot

Add CrosNetworkConfig.SelectCellularMobileNetwork and convert UI to mojo

Bug: 853953
Change-Id: I00c177bdb0b1c40c23521871b94bea234cd81c4c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1758543
Commit-Queue: Steven Bennetts <stevenjb@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarKyle Horimoto <khorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#690122}
parent 4468e91a
......@@ -109,8 +109,8 @@
<template is="dom-if"
if="[[showCellularChooseNetwork_(managedProperties_)]]">
<div class="section single-column">
<network-choose-mobile networking-private="[[networkingPrivate]]"
network-properties="[[networkProperties]]">
<network-choose-mobile device-state="[[deviceState_]]"
managed-properties="[[managedProperties_]]">
</network-choose-mobile>
</div>
</template>
......
......@@ -295,9 +295,8 @@
<!-- Choose Mobile Network (Cellular only). -->
<template is="dom-if"
if="[[showCellularChooseNetwork_(managedProperties_)]]">
<network-choose-mobile
networking-private="[[networkingPrivate]]"
network-properties="[[networkProperties_]]">
<network-choose-mobile device-state="[[deviceState_]]"
managed-properties="[[managedProperties_]]">
</network-choose-mobile>
</template>
......
......@@ -1705,6 +1705,56 @@ void CrosNetworkConfig::SetCellularSimStateFailure(
set_cellular_sim_state_callbacks_.erase(iter);
}
void CrosNetworkConfig::SelectCellularMobileNetwork(
const std::string& guid,
const std::string& network_id,
SelectCellularMobileNetworkCallback callback) {
const DeviceState* device_state = nullptr;
const NetworkState* network_state =
network_state_handler_->GetNetworkStateFromGuid(guid);
if (network_state) {
device_state =
network_state_handler_->GetDeviceState(network_state->device_path());
}
if (!device_state) {
std::move(callback).Run(false);
return;
}
int callback_id = callback_id_++;
select_cellular_mobile_network_callbacks_[callback_id] = std::move(callback);
network_device_handler_->RegisterCellularNetwork(
device_state->path(), network_id,
base::Bind(&CrosNetworkConfig::SelectCellularMobileNetworkSuccess,
weak_factory_.GetWeakPtr(), callback_id),
base::Bind(&CrosNetworkConfig::SelectCellularMobileNetworkFailure,
weak_factory_.GetWeakPtr(), callback_id));
}
void CrosNetworkConfig::SelectCellularMobileNetworkSuccess(int callback_id) {
auto iter = select_cellular_mobile_network_callbacks_.find(callback_id);
if (iter == select_cellular_mobile_network_callbacks_.end()) {
LOG(ERROR) << "Unexpected callback id not found (success): " << callback_id;
return;
}
std::move(iter->second).Run(true);
select_cellular_mobile_network_callbacks_.erase(iter);
}
void CrosNetworkConfig::SelectCellularMobileNetworkFailure(
int callback_id,
const std::string& error_name,
std::unique_ptr<base::DictionaryValue> error_data) {
auto iter = select_cellular_mobile_network_callbacks_.find(callback_id);
if (iter == select_cellular_mobile_network_callbacks_.end()) {
LOG(ERROR) << "Unexpected callback id not found (failure): " << callback_id;
return;
}
std::move(iter->second).Run(false);
select_cellular_mobile_network_callbacks_.erase(iter);
}
void CrosNetworkConfig::RequestNetworkScan(mojom::NetworkType type) {
network_state_handler_->RequestScan(MojoTypeToPattern(type));
}
......
......@@ -59,6 +59,10 @@ class CrosNetworkConfig : public mojom::CrosNetworkConfig,
SetNetworkTypeEnabledStateCallback callback) override;
void SetCellularSimState(mojom::CellularSimStatePtr sim_state,
SetCellularSimStateCallback callback) override;
void SelectCellularMobileNetwork(
const std::string& guid,
const std::string& network_id,
SelectCellularMobileNetworkCallback callback) override;
void RequestNetworkScan(mojom::NetworkType type) override;
private:
......@@ -80,6 +84,11 @@ class CrosNetworkConfig : public mojom::CrosNetworkConfig,
int callback_id,
const std::string& error_name,
std::unique_ptr<base::DictionaryValue> error_data);
void SelectCellularMobileNetworkSuccess(int callback_id);
void SelectCellularMobileNetworkFailure(
int callback_id,
const std::string& error_name,
std::unique_ptr<base::DictionaryValue> error_data);
// NetworkStateHandlerObserver
void NetworkListChanged() override;
......@@ -102,6 +111,8 @@ class CrosNetworkConfig : public mojom::CrosNetworkConfig,
base::flat_map<int, SetPropertiesCallback> set_properties_callbacks_;
base::flat_map<int, SetCellularSimStateCallback>
set_cellular_sim_state_callbacks_;
base::flat_map<int, SelectCellularMobileNetworkCallback>
select_cellular_mobile_network_callbacks_;
base::WeakPtrFactory<CrosNetworkConfig> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(CrosNetworkConfig);
......
......@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/json/json_reader.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
......@@ -253,6 +254,22 @@ class CrosNetworkConfigTest : public testing::Test {
return success;
}
bool SelectCellularMobileNetwork(const std::string& guid,
const std::string& network_id) {
bool success = false;
base::RunLoop run_loop;
cros_network_config()->SelectCellularMobileNetwork(
guid, network_id,
base::BindOnce(
[](bool* successp, base::OnceClosure quit_closure, bool success) {
*successp = success;
std::move(quit_closure).Run();
},
&success, run_loop.QuitClosure()));
run_loop.Run();
return success;
}
NetworkStateTestHelper& helper() { return helper_; }
CrosNetworkConfigTestObserver* observer() { return observer_.get(); }
CrosNetworkConfig* cros_network_config() {
......@@ -663,6 +680,41 @@ TEST_F(CrosNetworkConfigTest, SetCellularSimState) {
EXPECT_TRUE(cellular->sim_lock_status->lock_type.empty());
}
TEST_F(CrosNetworkConfigTest, SelectCellularMobileNetwork) {
// Create fake list of found networks.
base::Optional<base::Value> found_networks_list =
base::JSONReader::Read(base::StringPrintf(
R"([{"network_id": "network1", "technology": "GSM",
"status": "current"},
{"network_id": "network2", "technology": "GSM",
"status": "available"}])"));
helper().device_test()->SetDeviceProperty(
kCellularDevicePath, shill::kFoundNetworksProperty, *found_networks_list,
/*notify_changed=*/true);
// Assert initial state
mojom::ManagedPropertiesPtr properties =
GetManagedProperties("cellular_guid");
ASSERT_TRUE(properties->cellular);
ASSERT_TRUE(properties->cellular->found_networks);
const std::vector<mojom::FoundNetworkPropertiesPtr>& found_networks1 =
*(properties->cellular->found_networks);
ASSERT_EQ(2u, found_networks1.size());
EXPECT_EQ("current", found_networks1[0]->status);
EXPECT_EQ("available", found_networks1[1]->status);
// Select "network2"
EXPECT_TRUE(SelectCellularMobileNetwork("cellular_guid", "network2"));
properties = GetManagedProperties("cellular_guid");
ASSERT_TRUE(properties->cellular);
ASSERT_TRUE(properties->cellular->found_networks);
const std::vector<mojom::FoundNetworkPropertiesPtr>& found_networks2 =
*(properties->cellular->found_networks);
ASSERT_EQ(2u, found_networks2.size());
EXPECT_EQ("available", found_networks2[0]->status);
EXPECT_EQ("current", found_networks2[1]->status);
}
TEST_F(CrosNetworkConfigTest, RequestNetworkScan) {
// Observe device state list changes and track when the wifi scanning state
// gets set to true. Note: In the test the scan will complete immediately and
......
......@@ -7,6 +7,9 @@
// (ONC) documentation for detailed descriptions of properties:
// components/onc/docs/onc_spec.md.
// Currently this service is implemented in the Chrome Browser process with
// clients in Chrome and WebUI.
module chromeos.network_config.mojom;
import "services/network/public/mojom/ip_address.mojom";
......@@ -518,7 +521,6 @@ struct ManagedCellularProperties {
string? network_technology;
PaymentPortalProperties? payment_portal;
string? roaming_state;
bool scanning = false;
CellularProviderProperties? serving_operator;
int32 signal_strength = 0;
bool support_network_scan = false;
......@@ -639,7 +641,8 @@ struct CellularSimState {
bool require_pin;
};
// Interface for fetching and setting network configuration properties.
// Interface for fetching and setting network configuration properties, e.g.
// from Settings WebUI or the SystemTray.
interface CrosNetworkConfig {
AddObserver(CrosNetworkConfigObserver observer);
......@@ -686,6 +689,12 @@ interface CrosNetworkConfig {
// * Returns true if the operation succeeded.
SetCellularSimState(CellularSimState state) => (bool success);
// Selects which Cellular mobile network to use. |network_id| must match a
// FoundNetworkProperties.network_id for an entry in the
// ManagedProperties.found_networks property for the specified Cellular
// network. Returns true if the operation succeeded.
SelectCellularMobileNetwork(string guid, string network_id) => (bool success);
// Requests a scan for new networks. If the list updates,
// CrosNetworkConfigObserver::OnNetworkStateListChanged() will be signaled.
RequestNetworkScan(NetworkType type);
......
......@@ -42,12 +42,10 @@ js_library("network_apnlist") {
js_library("network_choose_mobile") {
deps = [
"//ui/webui/resources/cr_elements/chromeos/network:cr_onc_types",
"//ui/webui/resources/cr_components/chromeos/network:network_config",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:i18n_behavior",
]
externs_list = [ "$externs_path/networking_private.js" ]
extra_sources = [ "$interfaces_path/networking_private_interface.js" ]
}
js_library("network_config") {
......
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/cr_elements/md_select_css.html">
......@@ -18,18 +17,21 @@
<div class="property-box first two-line">
<div class="flex layout vertical">
<div>[[i18n('networkChooseMobile')]]</div>
<div class="secondary">[[getSecondaryText_(networkProperties)]]</div>
<div class="secondary">
[[getSecondaryText_(managedProperties, deviceState)]]
</div>
</div>
<cr-button on-click="onScanTap_"
disabled="[[!getEnableScanButton_(networkProperties)]]">
disabled="[[!getEnableScanButton_(managedProperties, deviceState)]]">
[[i18n('networkCellularScan')]]
</cr-button>
<select class="md-select" on-change="onChange_"
value="[[selectedMobileNetworkId_]]"
disabled="[[!getEnableSelectNetwork_(networkProperties)]]"
disabled="[[!getEnableSelectNetwork_(managedProperties,
deviceState)]]"
aria-label="[[i18n('networkChooseMobile')]]">
<template is="dom-repeat" items="[[mobileNetworkList_]]">
<option value="[[item.NetworkId]]"
<option value="[[item.networkId]]"
disabled="[[getMobileNetworkIsDisabled_(item)]]">
[[getName_(item)]]
</option>
......
......@@ -6,33 +6,30 @@
* @fileoverview Polymer element for displaying and modifying a list of cellular
* mobile networks.
*/
(function() {
'use strict';
Polymer({
is: 'network-choose-mobile',
behaviors: [I18nBehavior],
properties: {
/**
* The current set of properties for the network.
* @type {!CrOnc.NetworkProperties|undefined}
*/
networkProperties: {
/** @private {!chromeos.networkConfig.mojom.ManagedProperties|undefined} */
managedProperties: {
type: Object,
observer: 'networkPropertiesChanged_',
observer: 'managedPropertiesChanged_',
},
/**
* Interface for networkingPrivate calls.
* @type {NetworkingPrivate}
*/
networkingPrivate: {
/** @type {?OncMojo.DeviceStateProperties} */
deviceState: {
type: Object,
value: chrome.networkingPrivate,
value: null,
},
/**
* The networkingPrivate.FoundNetworkProperties.NetworkId of the selected
* mobile network.
* The mojom.FoundNetworkProperties.networkId of the selected mobile
* network.
* @private
*/
selectedMobileNetworkId_: {
......@@ -41,8 +38,8 @@ Polymer({
},
/**
* Selectable list of FoundNetwork dictionaries for the UI.
* @private {!Array<!chrome.networkingPrivate.FoundNetworkProperties>}
* Selectable list of mojom.FoundNetworkProperties dictionaries for the UI.
* @private {!Array<!chromeos.networkConfig.mojom.FoundNetworkProperties>}
*/
mobileNetworkList_: {
type: Array,
......@@ -55,106 +52,129 @@ Polymer({
/** @private {boolean} */
scanRequested_: false,
/** @private {?chromeos.networkConfig.mojom.CrosNetworkConfigRemote} */
networkConfig_: null,
/** @override */
attached: function() {
this.scanRequested_ = false;
},
/**
* Polymer networkProperties changed method.
* @return {?chromeos.networkConfig.mojom.CrosNetworkConfigRemote}
* @private
*/
networkPropertiesChanged_: function() {
if (!this.networkProperties || !this.networkProperties.Cellular) {
return;
getNetworkConfig_() {
if (!this.networkConfig_) {
this.networkConfig_ =
network_config.MojoInterfaceProviderImpl.getInstance()
.getMojoServiceRemote();
}
const cellular = this.networkProperties.Cellular;
this.mobileNetworkList_ = cellular.FoundNetworks ||
[{NetworkId: 'none', LongName: this.i18n('networkCellularNoNetworks')}];
return this.networkConfig_;
},
/**
* Polymer managedProperties changed method.
* @private
*/
managedPropertiesChanged_: function() {
const cellular = this.managedProperties.cellular;
this.mobileNetworkList_ = cellular.foundNetworks || [];
if (!this.mobileNetworkList_.length) {
this.mobileNetworkList_ = [
{networkId: 'none', longName: this.i18n('networkCellularNoNetworks')}
];
}
// Set selectedMobileNetworkId_ after the dom-repeat has been stamped.
this.async(() => {
let selected = this.mobileNetworkList_.find(function(mobileNetwork) {
return mobileNetwork.Status == 'current';
return mobileNetwork.status == 'current';
});
if (!selected) {
selected = this.mobileNetworkList_[0];
}
this.selectedMobileNetworkId_ = selected.NetworkId;
this.selectedMobileNetworkId_ = selected.networkId;
});
},
/**
* @param {!chrome.networkingPrivate.FoundNetworkProperties} network
* @param {!chromeos.networkConfig.mojom.FoundNetworkProperties} foundNetwork
* @return {boolean}
* @private
*/
getMobileNetworkIsDisabled_: function(network) {
return network.Status != 'available' && network.Status != 'current';
getMobileNetworkIsDisabled_: function(foundNetwork) {
return foundNetwork.status != 'available' &&
foundNetwork.status != 'current';
},
/**
* @param {!chrome.networkingPrivate.NetworkProperties} properties
* @param {!chromeos.networkConfig.mojom.ManagedProperties} properties
* @return {boolean}
* @private
*/
getEnableScanButton_: function(properties) {
return properties.ConnectionState == CrOnc.ConnectionState.NOT_CONNECTED &&
!this.get('Cellular.Scanning', properties);
return properties.connectionState ==
chromeos.networkConfig.mojom.ConnectionStateType.kNotConnected &&
!!this.deviceState && !this.deviceState.scanning;
},
/**
* @param {!chrome.networkingPrivate.NetworkProperties} properties
* @param {!chromeos.networkConfig.mojom.ManagedProperties} properties
* @return {boolean}
* @private
*/
getEnableSelectNetwork_: function(properties) {
if (this.get('Cellular.Scanning', properties) ||
properties.ConnectionState != CrOnc.ConnectionState.NOT_CONNECTED) {
return false;
}
const found = this.get('Cellular.FoundNetworks', properties);
return !!found && found.length > 0;
return (
!!this.deviceState && !this.deviceState.scanning &&
properties.connectionState ==
chromeos.networkConfig.mojom.ConnectionStateType.kNotConnected &&
!!properties.cellular.foundNetworks &&
properties.cellular.foundNetworks.length > 0);
},
/**
* @param {!chrome.networkingPrivate.NetworkProperties} properties
* @param {!chromeos.networkConfig.mojom.ManagedProperties} properties
* @return {string}
* @private
*/
getSecondaryText_: function(properties) {
if (!properties || !properties.Cellular) {
if (!properties) {
return '';
}
const cellular = properties.Cellular;
if (cellular.Scanning) {
if (!!this.deviceState && this.deviceState.scanning) {
return this.i18n('networkCellularScanning');
} else if (this.scanRequested_) {
}
if (this.scanRequested_) {
return this.i18n('networkCellularScanCompleted');
} else if (
properties.ConnectionState != CrOnc.ConnectionState.NOT_CONNECTED) {
}
if (properties.connectionState !=
chromeos.networkConfig.mojom.ConnectionStateType.kNotConnected) {
return this.i18n('networkCellularScanConnectedHelp');
}
return '';
},
/**
* @param {!chrome.networkingPrivate.FoundNetworkProperties} network
* @param {!chromeos.networkConfig.mojom.FoundNetworkProperties} foundNetwork
* @return {string}
* @private
*/
getName_: function(network) {
return network.LongName || network.ShortName || network.NetworkId;
getName_: function(foundNetwork) {
return foundNetwork.longName || foundNetwork.shortName ||
foundNetwork.networkId;
},
/**
* Request a Cellular scan to populate the list of networks. This will
* triger a change to networkProperties when completed (if
* triger a change to managedProperties when completed (if
* Cellular.FoundNetworks changes).
* @private
*/
onScanTap_: function() {
this.scanRequested_ = true;
this.networkingPrivate.requestNetworkScan(CrOnc.Type.CELLULAR);
this.getNetworkConfig_().requestNetworkScan(
chromeos.networkConfig.mojom.NetworkType.kCellular);
},
/**
......@@ -166,7 +186,9 @@ Polymer({
if (!target.value || target.value == 'none') {
return;
}
this.networkingPrivate.selectCellularMobileNetwork(
this.networkProperties.GUID, target.value);
this.getNetworkConfig_().selectCellularMobileNetwork(
this.managedProperties.guid, target.value);
},
});
})();
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