blob: a5b72db4744b1dd214b755c5245a69bdc131df2a [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'chrome://resources/cr_components/chromeos/network/network_select.m.js';
import 'chrome://resources/cr_components/chromeos/network_health/network_diagnostics.js';
import 'chrome://resources/cr_components/chromeos/network_health/network_health_summary.js';
import 'chrome://resources/cr_components/chromeos/traffic_counters/traffic_counters.js';
import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
import 'chrome://resources/cr_elements/cr_tabs/cr_tabs.js';
import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.m.js';
import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
import 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-lite.js';
import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
import 'chrome://resources/polymer/v3_0/iron-pages/iron-pages.js';
import './strings.m.js';
import './network_state_ui.js';
import './network_logs_ui.js';
import './network_metrics_ui.js';
import {OncMojo} from 'chrome://resources/cr_components/chromeos/network/onc_mojo.m.js';
import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {NetworkUIBrowserProxy, NetworkUIBrowserProxyImpl} from './network_ui_browser_proxy.js';
/**
* @fileoverview
* Polymer element network debugging UI.
*/
Polymer({
is: 'network-ui',
_template: html`{__html_template__}`,
behaviors: [I18nBehavior],
properties: {
/**
* Names of the top level page tabs.
* @type {!Array<String>}
* @private
*/
tabNames_: {
type: Array,
value: function() {
return [
this.i18n('generalTab'),
this.i18n('networkHealthTab'),
this.i18n('networkLogsTab'),
this.i18n('networkStateTab'),
this.i18n('networkSelectTab'),
this.i18n('TrafficCountersTrafficCounters'),
this.i18n('networkHotspotTab'),
this.i18n('networkMetricsTab'),
];
},
},
/**
* Index of the selected top level page tab.
* @private
*/
selectedTab_: {
type: Number,
value: 0,
},
/** @private */
hostname_: {
type: String,
value: '',
},
/** @private */
tetheringConfigToSet_: {
type: String,
value: '',
},
/** @private */
isGuestModeActive_: {
type: Boolean,
value() {
return loadTimeData.valueExists('isGuestModeActive') &&
loadTimeData.getBoolean('isGuestModeActive');
},
},
/**@private */
isTetheringEnabled_: {
type: Boolean,
value: false,
},
/**
* Set to true while an tethering state change is requested and the
* callback hasn't been fired yet.
* @private
*/
tetheringChangeInProgress_: {
type: Boolean,
value: false,
},
/** @private */
isHotspotEnabled_: {
type: Boolean,
value() {
return loadTimeData.valueExists('isHotspotEnabled') &&
loadTimeData.getBoolean('isHotspotEnabled');
},
},
/** @private */
invalidJSON_: {
type: Boolean,
value: false,
},
},
/** @type {?chromeos.networkConfig.mojom.CrosNetworkConfigRemote} */
networkConfig_: null,
/** @type {!NetworkUIBrowserProxy} */
browserProxy_: NetworkUIBrowserProxyImpl.getInstance(),
/** @override */
attached() {
this.networkConfig_ =
chromeos.networkConfig.mojom.CrosNetworkConfig.getRemote();
const select = this.$$('network-select');
select.customItems = [
{
customItemName: 'addWiFiListItemName',
polymerIcon: 'cr:add',
customData: 'WiFi',
},
];
this.$$('#import-onc').value = '';
this.requestGlobalPolicy_();
this.getTetheringCapabilities_();
this.getTetheringConfig_();
this.getTetheringStatus_();
this.getHostname_();
this.selectTabFromHash_();
window.addEventListener('hashchange', () => {
this.selectTabFromHash_();
});
},
/**
* @param {*} result that need to stringify to JSON
* @return {string}
* @private
*/
stringifyJSON_(result) {
return JSON.stringify(result, null, '\t');
},
/** @private */
selectTabFromHash_() {
const selectedTab = window.location.hash.substring(1);
if (!selectedTab) {
return;
}
const tabpanels = this.$$('iron-pages').querySelectorAll('.tabpanel');
for (let idx = 0; idx < tabpanels.length; ++idx) {
if (tabpanels[idx].id == selectedTab) {
this.selectedTab_ = idx;
}
}
},
/** @private */
openCellularActivationUi_() {
this.browserProxy_.openCellularActivationUi().then((response) => {
const didOpenActivationUi = response.shift();
this.$$('#cellular-error-text').hidden = didOpenActivationUi;
});
},
/** @private */
onResetESimCacheClick_() {
this.browserProxy_.resetESimCache();
},
/** @private */
onDisableActiveESimProfileClick_() {
this.browserProxy_.disableActiveESimProfile();
},
/** @private */
onResetEuiccClick_() {
this.browserProxy_.resetEuicc();
},
/** @private */
showAddNewWifi_() {
this.browserProxy_.showAddNewWifi();
},
/**
* Handles the ONC file input change event.
* @param {!Event} event
* @private
*/
onImportOncChange_(event) {
const file = event.target.files[0];
event.stopPropagation();
if (!file) {
return;
}
const reader = new FileReader();
reader.onloadend = (e) => {
const content = reader.result;
if (!content || typeof (content) != 'string') {
console.error('File not read' + file);
return;
}
this.browserProxy_.importONC(content).then((response) => {
this.importONCResponse_(response);
});
};
reader.readAsText(file);
},
/**
* Handles the chrome 'importONC' response.
* @param {Array} args
* @private
*/
importONCResponse_(args) {
const result = args.shift();
const isError = args.shift();
const resultDiv = this.$$('#onc-import-result');
resultDiv.innerText = result;
resultDiv.classList.toggle('error', isError);
this.$$('#import-onc').value = '';
},
/**
* Requests the global policy dictionary and updates the page.
* @private
*/
requestGlobalPolicy_() {
this.networkConfig_.getGlobalPolicy().then(result => {
this.$$('#global-policy').textContent =
this.stringifyJSON_(result.result);
});
},
/** @private */
getTetheringCapabilities_() {
this.browserProxy_.getTetheringCapabilities().then(result => {
this.$$('#tethering-capabilities-div').textContent =
this.stringifyJSON_(result);
});
},
/** @private */
getTetheringStatus_() {
this.browserProxy_.getTetheringStatus().then(result => {
this.$$('#tethering-status-div').textContent =
this.stringifyJSON_(result);
const state = result['state'];
const startingState = loadTimeData.getString('tetheringStateStarting');
const activeState = loadTimeData.getString('tetheringStateActive');
if (!!state && (state === startingState || state === activeState)) {
this.isTetheringEnabled_ = true;
return;
}
this.isTetheringEnabled_ = false;
});
},
/** @private */
getTetheringConfig_() {
this.browserProxy_.getTetheringConfig().then(result => {
this.$$('#tethering-config-div').textContent =
this.stringifyJSON_(result);
});
},
/** @private */
setTetheringConfig_() {
this.browserProxy_.setTetheringConfig(this.tetheringConfigToSet_)
.then((result) => {
const success = result === 'success';
const resultDiv = this.$$('#set-tethering-config-result');
resultDiv.innerText = result;
resultDiv.classList.toggle('error', !success);
if (success) {
this.getTetheringConfig_();
}
});
},
/** @private */
checkTetheringReadiness_() {
this.browserProxy_.checkTetheringReadiness().then(result => {
const resultDiv = this.$$('#check-tethering-readiness-result');
resultDiv.innerText = result;
resultDiv.classList.toggle('error', result !== 'ready');
});
},
/**
* Check if the input tethering config string is a valid JSON object.
* @private
*/
validateJSON_() {
if (this.tetheringConfigToSet_ === '') {
this.invalidJSON_ = false;
return;
}
try {
const parsed = JSON.parse(this.tetheringConfigToSet_);
// Check if the parsed JSON is object type by its constructor
if (parsed.constructor === ({}).constructor) {
this.invalidJSON_ = false;
return;
}
this.invalidJSON_ = true;
} catch (e) {
this.invalidJSON_ = true;
}
},
/** @private */
onTetheringToggleChanged_() {
this.tetheringChangeInProgress_ = true;
this.browserProxy_.setTetheringEnabled(this.isTetheringEnabled_)
.then(result => {
const resultDiv = this.$$('#set-tethering-enabled-result');
resultDiv.innerText = result;
resultDiv.classList.toggle('error', result !== 'success');
this.getTetheringStatus_();
this.tetheringChangeInProgress_ = false;
});
},
/**
* @param {!Event} event
* @private
*/
onHostnameChanged_(event) {
this.browserProxy_.setHostname(this.hostname_);
},
/** @private */
getHostname_() {
this.browserProxy_.getHostname().then(result => this.hostname_ = result);
},
/**
* Handles clicks on network items in the <network-select> element by
* attempting a connection to the selected network or requesting a password
* if the network requires a password.
* @param {!Event<!OncMojo.NetworkStateProperties>} event
* @private
*/
onNetworkItemSelected_(event) {
const networkState = event.detail;
// If the network is already connected, show network details.
if (OncMojo.connectionStateIsConnected(networkState.connectionState)) {
this.browserProxy_.showNetworkDetails(networkState.guid);
return;
}
// If the network is not connectable, show a configuration dialog.
if (networkState.connectable === false || networkState.errorState) {
this.browserProxy_.showNetworkConfig(networkState.guid);
return;
}
// Otherwise, connect.
this.networkConfig_.startConnect(networkState.guid).then(response => {
if (response.result ==
chromeos.networkConfig.mojom.StartConnectResult.kSuccess) {
return;
}
console.error(
'startConnect error for: ' + networkState.guid + ' Result: ' +
response.result.toString() + ' Message: ' + response.message);
this.browserProxy_.showNetworkConfig(networkState.guid);
});
},
/**
* Returns and typecasts the network diagnostics element
* @returns {!NetworkDiagnosticsElement}
* @private
*/
getNetworkDiagnosticsElement_() {
return /** @type {!NetworkDiagnosticsElement} */ (
this.$$('#network-diagnostics'));
},
/**
* Handles requests to open the feedback report dialog. The provided string
* in the event will be sent as a part of the feedback report.
* @param {!Event<string>} event
* @private
*/
onSendFeedbackReportClick_(event) {
chrome.send('OpenFeedbackDialog');
},
/**
* Handles requests to open the feedback report dialog. The provided string
* in the event will be sent as a part of the feedback report.
* @param {!Event<string>} event
* @private
*/
onRunAllRoutinesClick_(event) {
this.getNetworkDiagnosticsElement_().runAllRoutines();
},
/**
* @param {!Event<!{detail:{customData: string}}>} event
* @private
*/
onCustomItemSelected_(event) {
this.browserProxy_.addNetwork(event.detail.customData);
},
});