| // Copyright 2013 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ui/webui/ash/network_ui.h" |
| |
| #include <memory> |
| #include <string> |
| #include <utility> |
| |
| #include "ash/constants/ash_features.h" |
| #include "ash/constants/ash_pref_names.h" |
| #include "ash/public/cpp/connectivity_services.h" |
| #include "ash/public/cpp/esim_manager.h" |
| #include "ash/public/cpp/network_config_service.h" |
| #include "ash/webui/common/trusted_types_util.h" |
| #include "ash/webui/network_ui/network_diagnostics_resource_provider.h" |
| #include "ash/webui/network_ui/network_health_resource_provider.h" |
| #include "ash/webui/network_ui/traffic_counters_resource_provider.h" |
| #include "base/functional/bind.h" |
| #include "base/json/json_reader.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/values.h" |
| #include "chrome/browser/ash/net/network_health/network_health_manager.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/extensions/tab_helper.h" |
| #include "chrome/browser/ui/ash/system_tray_client_impl.h" |
| #include "chrome/browser/ui/chrome_pages.h" |
| #include "chrome/browser/ui/webui/ash/cellular_setup/cellular_setup_localized_strings_provider.h" |
| #include "chrome/browser/ui/webui/ash/internet_config_dialog.h" |
| #include "chrome/browser/ui/webui/ash/internet_detail_dialog.h" |
| #include "chrome/browser/ui/webui/ash/network_logs_message_handler.h" |
| #include "chrome/browser/ui/webui/ash/onc_import_message_handler.h" |
| #include "chrome/browser/ui/webui/webui_util.h" |
| #include "chrome/common/url_constants.h" |
| #include "chrome/grit/browser_resources.h" |
| #include "chrome/grit/generated_resources.h" |
| #include "chrome/grit/network_ui_resources.h" |
| #include "chrome/grit/network_ui_resources_map.h" |
| #include "chromeos/ash/components/dbus/shill/shill_manager_client.h" |
| #include "chromeos/ash/components/network/cellular_esim_profile_handler.h" |
| #include "chromeos/ash/components/network/cellular_esim_profile_handler_impl.h" |
| #include "chromeos/ash/components/network/cellular_esim_uninstall_handler.h" |
| #include "chromeos/ash/components/network/cellular_utils.h" |
| #include "chromeos/ash/components/network/device_state.h" |
| #include "chromeos/ash/components/network/managed_network_configuration_handler.h" |
| #include "chromeos/ash/components/network/network_configuration_handler.h" |
| #include "chromeos/ash/components/network/network_device_handler.h" |
| #include "chromeos/ash/components/network/network_state.h" |
| #include "chromeos/ash/components/network/network_state_handler.h" |
| #include "chromeos/ash/components/network/onc/network_onc_utils.h" |
| #include "chromeos/ash/services/cellular_setup/public/mojom/esim_manager.mojom.h" |
| #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h" |
| #include "chromeos/services/network_health/public/mojom/network_diagnostics.mojom.h" |
| #include "chromeos/services/network_health/public/mojom/network_health.mojom.h" |
| #include "chromeos/strings/grit/chromeos_strings.h" |
| #include "components/device_event_log/device_event_log.h" |
| #include "components/user_manager/user_manager.h" |
| #include "content/public/browser/browser_context.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/browser/web_ui.h" |
| #include "content/public/browser/web_ui_data_source.h" |
| #include "content/public/browser/web_ui_message_handler.h" |
| #include "mojo/public/cpp/bindings/remote.h" |
| #include "third_party/cros_system_api/dbus/service_constants.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/chromeos/strings/network/network_element_localized_strings_provider.h" |
| |
| namespace ash { |
| |
| namespace { |
| |
| constexpr char kAddNetwork[] = "addNetwork"; |
| constexpr char kDisableESimProfile[] = "disableActiveESimProfile"; |
| constexpr char kGetNetworkProperties[] = "getShillNetworkProperties"; |
| constexpr char kGetFirstWifiNetworkProperties[] = |
| "getFirstWifiNetworkProperties"; |
| constexpr char kGetDeviceProperties[] = "getShillDeviceProperties"; |
| constexpr char kGetEthernetEAP[] = "getShillEthernetEAP"; |
| constexpr char kOpenCellularActivationUi[] = "openCellularActivationUi"; |
| constexpr char kResetESimCache[] = "resetESimCache"; |
| constexpr char kResetEuicc[] = "resetEuicc"; |
| constexpr char kResetApnMigrator[] = "resetApnMigrator"; |
| constexpr char kShowNetworkDetails[] = "showNetworkDetails"; |
| constexpr char kShowNetworkConfig[] = "showNetworkConfig"; |
| constexpr char kShowAddNewWifiNetworkDialog[] = "showAddNewWifi"; |
| constexpr char kGetHostname[] = "getHostname"; |
| constexpr char kSetHostname[] = "setHostname"; |
| constexpr char kGetTetheringCapabilities[] = "getTetheringCapabilities"; |
| constexpr char kGetTetheringStatus[] = "getTetheringStatus"; |
| constexpr char kGetTetheringConfig[] = "getTetheringConfig"; |
| constexpr char kSetTetheringConfig[] = "setTetheringConfig"; |
| constexpr char kCheckTetheringReadiness[] = "checkTetheringReadiness"; |
| constexpr char kSetTetheringEnabled[] = "setTetheringEnabled"; |
| |
| bool GetServicePathFromGuid(const std::string& guid, |
| std::string* service_path) { |
| const NetworkState* network = |
| NetworkHandler::Get()->network_state_handler()->GetNetworkStateFromGuid( |
| guid); |
| if (!network) |
| return false; |
| *service_path = network->path(); |
| return true; |
| } |
| |
| void SetDeviceProperties(base::Value::Dict* dictionary) { |
| DCHECK(dictionary); |
| const std::string* device = dictionary->FindString(shill::kDeviceProperty); |
| if (!device) |
| return; |
| const DeviceState* device_state = |
| NetworkHandler::Get()->network_state_handler()->GetDeviceState(*device); |
| if (!device_state) |
| return; |
| |
| base::Value::Dict device_dictionary = device_state->properties().Clone(); |
| if (!device_state->ip_configs().empty()) { |
| // Convert IPConfig dictionary to a ListValue. |
| base::Value::List ip_configs; |
| for (auto iter : device_state->ip_configs()) { |
| ip_configs.Append(iter.second.Clone()); |
| } |
| device_dictionary.Set(shill::kIPConfigsProperty, std::move(ip_configs)); |
| } |
| if (!device_dictionary.empty()) |
| dictionary->Set(shill::kDeviceProperty, std::move(device_dictionary)); |
| } |
| |
| bool IsGuestModeActive() { |
| return user_manager::UserManager::Get()->IsLoggedInAsGuest() || |
| user_manager::UserManager::Get()->IsLoggedInAsManagedGuestSession(); |
| } |
| |
| // Get the euicc path for reset euicc operation. Return std::nullopt if the |
| // reset euicc is not allowed, i.e: the user is in guest mode, admin enables |
| // restrict cellular network policy or a managed eSIM profile already installed. |
| std::optional<dbus::ObjectPath> GetEuiccResetPath() { |
| if (IsGuestModeActive()) { |
| NET_LOG(ERROR) << "Couldn't reset EUICC in guest mode."; |
| return std::nullopt; |
| } |
| std::optional<dbus::ObjectPath> euicc_path = |
| cellular_utils::GetCurrentEuiccPath(); |
| if (!euicc_path) { |
| NET_LOG(ERROR) << "No current EUICC. Unable to reset EUICC"; |
| return std::nullopt; |
| } |
| const ManagedNetworkConfigurationHandler* |
| managed_network_configuration_handler = |
| NetworkHandler::Get()->managed_network_configuration_handler(); |
| if (!managed_network_configuration_handler) |
| return std::nullopt; |
| if (managed_network_configuration_handler |
| ->AllowOnlyPolicyCellularNetworks()) { |
| NET_LOG(ERROR) |
| << "Couldn't reset EUICC if admin restricts cellular networks."; |
| return std::nullopt; |
| } |
| NetworkStateHandler* network_state_handler = |
| NetworkHandler::Get()->network_state_handler(); |
| if (!network_state_handler) |
| return std::nullopt; |
| NetworkStateHandler::NetworkStateList state_list; |
| network_state_handler->GetNetworkListByType(NetworkTypePattern::Cellular(), |
| /*configured_only=*/false, |
| /*visible_only=*/false, |
| /*limit=*/0, &state_list); |
| |
| HermesEuiccClient::Properties* euicc_properties = |
| HermesEuiccClient::Get()->GetProperties(*euicc_path); |
| const std::string& eid = euicc_properties->eid().value(); |
| for (const NetworkState* network : state_list) { |
| if (network->eid() == eid && network->IsManagedByPolicy()) { |
| NET_LOG(ERROR) |
| << "Couldn't reset EUICC if a managed eSIM profile is installed."; |
| return std::nullopt; |
| } |
| } |
| |
| return euicc_path; |
| } |
| |
| std::string HexDecode(const std::string& hex_ssid) { |
| std::string ssid; |
| if (!base::HexStringToString(hex_ssid, &ssid)) { |
| NET_LOG(ERROR) << "Error decoding HexSSID: " << hex_ssid; |
| } |
| |
| return ssid; |
| } |
| |
| class NetworkDiagnosticsMessageHandler : public content::WebUIMessageHandler { |
| public: |
| NetworkDiagnosticsMessageHandler() = default; |
| ~NetworkDiagnosticsMessageHandler() override = default; |
| |
| void RegisterMessages() override { |
| web_ui()->RegisterMessageCallback( |
| "OpenFeedbackDialog", |
| base::BindRepeating( |
| &NetworkDiagnosticsMessageHandler::OpenFeedbackDialog, |
| base::Unretained(this))); |
| } |
| |
| private: |
| void OpenFeedbackDialog(const base::Value::List& value) { |
| chrome::ShowFeedbackPage(nullptr, chrome::kFeedbackSourceNetworkHealthPage, |
| "" /*description_template*/, |
| "" /*description_template_placeholder*/, |
| "network-health", "" /*extra_diagnostics*/); |
| } |
| }; |
| |
| } // namespace |
| |
| namespace network_ui { |
| |
| class NetworkConfigMessageHandler : public content::WebUIMessageHandler { |
| public: |
| NetworkConfigMessageHandler() {} |
| |
| NetworkConfigMessageHandler(const NetworkConfigMessageHandler&) = delete; |
| NetworkConfigMessageHandler& operator=(const NetworkConfigMessageHandler&) = |
| delete; |
| |
| ~NetworkConfigMessageHandler() override {} |
| |
| // WebUIMessageHandler implementation. |
| void RegisterMessages() override { |
| web_ui()->RegisterMessageCallback( |
| kAddNetwork, |
| base::BindRepeating(&NetworkConfigMessageHandler::AddNetwork, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| kGetNetworkProperties, |
| base::BindRepeating( |
| &NetworkConfigMessageHandler::GetShillNetworkProperties, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| kGetFirstWifiNetworkProperties, |
| base::BindRepeating( |
| &NetworkConfigMessageHandler::GetFirstWifiNetworkProperties, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| kGetDeviceProperties, |
| base::BindRepeating( |
| &NetworkConfigMessageHandler::GetShillDeviceProperties, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| kGetEthernetEAP, |
| base::BindRepeating(&NetworkConfigMessageHandler::GetShillEthernetEAP, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| kOpenCellularActivationUi, |
| base::BindRepeating( |
| &NetworkConfigMessageHandler::OpenCellularActivationUi, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| kResetESimCache, |
| base::BindRepeating(&NetworkConfigMessageHandler::ResetESimCache, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| kDisableESimProfile, |
| base::BindRepeating( |
| &NetworkConfigMessageHandler::DisableActiveESimProfile, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| kResetEuicc, |
| base::BindRepeating(&NetworkConfigMessageHandler::ResetEuicc, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| kResetApnMigrator, |
| base::BindRepeating(&NetworkConfigMessageHandler::ResetApnMigrator, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| kShowNetworkDetails, |
| base::BindRepeating(&NetworkConfigMessageHandler::ShowNetworkDetails, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| kShowNetworkConfig, |
| base::BindRepeating(&NetworkConfigMessageHandler::ShowNetworkConfig, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| kShowAddNewWifiNetworkDialog, |
| base::BindRepeating(&NetworkConfigMessageHandler::ShowAddNewWifi, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| kGetHostname, |
| base::BindRepeating(&NetworkConfigMessageHandler::GetHostname, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| kSetHostname, |
| base::BindRepeating(&NetworkConfigMessageHandler::SetHostname, |
| base::Unretained(this))); |
| } |
| |
| private: |
| void Respond(const std::string& callback_id, const base::ValueView response) { |
| AllowJavascript(); |
| ResolveJavascriptCallback(base::Value(callback_id), response); |
| } |
| |
| void GetShillNetworkProperties(const base::Value::List& arg_list) { |
| CHECK_EQ(2u, arg_list.size()); |
| std::string callback_id = arg_list[0].GetString(); |
| std::string guid = arg_list[1].GetString(); |
| ProvideNetworkProperties(callback_id, guid); |
| } |
| |
| void GetFirstWifiNetworkProperties(const base::Value::List& arg_list) { |
| std::string callback_id = arg_list[0].GetString(); |
| const NetworkState* wifi_network = |
| NetworkHandler::Get()->network_state_handler()->FirstNetworkByType( |
| NetworkTypePattern::WiFi()); |
| if (wifi_network) { |
| ProvideNetworkProperties(callback_id, wifi_network->guid()); |
| return; |
| } |
| Respond(callback_id, base::Value::List()); |
| } |
| |
| void ProvideNetworkProperties(const std::string& callback_id, |
| const std::string& guid) { |
| std::string service_path; |
| if (!GetServicePathFromGuid(guid, &service_path)) { |
| RunErrorCallback(callback_id, guid, kGetNetworkProperties, |
| "Error.InvalidNetworkGuid"); |
| return; |
| } |
| NetworkHandler::Get()->network_configuration_handler()->GetShillProperties( |
| service_path, |
| base::BindOnce( |
| &NetworkConfigMessageHandler::OnGetShillNetworkProperties, |
| weak_ptr_factory_.GetWeakPtr(), callback_id, guid)); |
| } |
| |
| void OnGetShillNetworkProperties(const std::string& callback_id, |
| const std::string& guid, |
| const std::string& service_path, |
| std::optional<base::Value::Dict> result) { |
| if (!result) { |
| RunErrorCallback(callback_id, guid, kGetNetworkProperties, "Error.DBus"); |
| return; |
| } |
| // Set the 'service_path' property for debugging. |
| result->Set("service_path", service_path); |
| // Set the device properties for debugging. |
| SetDeviceProperties(&result.value()); |
| base::Value::List return_arg_list; |
| return_arg_list.Append(std::move(*result)); |
| Respond(callback_id, return_arg_list); |
| } |
| |
| void GetShillDeviceProperties(const base::Value::List& arg_list) { |
| CHECK_EQ(2u, arg_list.size()); |
| std::string callback_id = arg_list[0].GetString(); |
| std::string type = arg_list[1].GetString(); |
| |
| const DeviceState* device = |
| NetworkHandler::Get()->network_state_handler()->GetDeviceStateByType( |
| onc::NetworkTypePatternFromOncType(type)); |
| if (!device) { |
| RunErrorCallback(callback_id, type, kGetDeviceProperties, |
| "Error.InvalidDeviceType"); |
| return; |
| } |
| NetworkHandler::Get()->network_device_handler()->GetDeviceProperties( |
| device->path(), |
| base::BindOnce(&NetworkConfigMessageHandler::OnGetShillDeviceProperties, |
| weak_ptr_factory_.GetWeakPtr(), callback_id, type)); |
| } |
| |
| void GetShillEthernetEAP(const base::Value::List& arg_list) { |
| CHECK_EQ(1u, arg_list.size()); |
| std::string callback_id = arg_list[0].GetString(); |
| |
| NetworkStateHandler::NetworkStateList list; |
| NetworkHandler::Get()->network_state_handler()->GetNetworkListByType( |
| NetworkTypePattern::Primitive(shill::kTypeEthernetEap), |
| true /* configured_only */, false /* visible_only */, 1 /* limit */, |
| &list); |
| |
| if (list.empty()) { |
| Respond(callback_id, base::Value::List()); |
| return; |
| } |
| const NetworkState* eap = list.front(); |
| |
| Respond(callback_id, |
| base::Value::List().Append(base::Value::Dict() |
| .Set("guid", eap->guid()) |
| .Set("name", eap->name()) |
| .Set("type", eap->type()))); |
| } |
| |
| void OpenCellularActivationUi(const base::Value::List& arg_list) { |
| CHECK_EQ(1u, arg_list.size()); |
| std::string callback_id = arg_list[0].GetString(); |
| |
| const NetworkState* cellular_network = |
| NetworkHandler::Get()->network_state_handler()->FirstNetworkByType( |
| NetworkTypePattern::Cellular()); |
| if (cellular_network) { |
| SystemTrayClientImpl::Get()->ShowSettingsCellularSetup( |
| /*show_psim_flow=*/true); |
| } |
| base::Value::List response; |
| response.Append(base::Value(cellular_network != nullptr)); |
| Respond(callback_id, response); |
| } |
| |
| void ResetESimCache(const base::Value::List& arg_list) { |
| CellularESimProfileHandler* handler = |
| NetworkHandler::Get()->cellular_esim_profile_handler(); |
| if (!handler) |
| return; |
| |
| CellularESimProfileHandlerImpl* handler_impl = |
| static_cast<CellularESimProfileHandlerImpl*>(handler); |
| handler_impl->ResetESimProfileCache(); |
| } |
| |
| void DisableActiveESimProfile(const base::Value::List& arg_list) { |
| CellularESimProfileHandler* handler = |
| NetworkHandler::Get()->cellular_esim_profile_handler(); |
| if (!handler) |
| return; |
| |
| CellularESimProfileHandlerImpl* handler_impl = |
| static_cast<CellularESimProfileHandlerImpl*>(handler); |
| handler_impl->DisableActiveESimProfile(); |
| } |
| |
| void ResetEuicc(const base::Value::List& arg_list) { |
| std::optional<dbus::ObjectPath> euicc_path = GetEuiccResetPath(); |
| if (!euicc_path) |
| return; |
| |
| CellularESimUninstallHandler* handler = |
| NetworkHandler::Get()->cellular_esim_uninstall_handler(); |
| if (!handler) |
| return; |
| NET_LOG(EVENT) << "Executing reset EUICC on " << euicc_path->value(); |
| handler->ResetEuiccMemory( |
| *euicc_path, base::BindOnce(&NetworkConfigMessageHandler::OnEuiccReset, |
| base::Unretained(this))); |
| } |
| |
| void ResetApnMigrator(const base::Value::List& arg_list) { |
| NET_LOG(EVENT) << "Executing reset ApnMigrator"; |
| PrefService* local_state = g_browser_process->local_state(); |
| |
| // Clear set of migrated ICCIDs. |
| local_state->ClearPref(prefs::kApnMigratedIccids); |
| |
| // Clear all revamp APN lists in all network. |
| const std::string network_metadata_pref = "network_metadata"; |
| base::Value::Dict device_dict = |
| local_state->GetDict(network_metadata_pref).Clone(); |
| for (auto const [guid, val] : device_dict) { |
| base::Value::Dict* network_dict = device_dict.FindDict(guid.c_str()); |
| network_dict->Remove("custom_apn_list_v2"); |
| } |
| local_state->SetDict(network_metadata_pref, std::move(device_dict)); |
| } |
| |
| void OnEuiccReset(bool success) { |
| if (!success) { |
| NET_LOG(ERROR) << "Error occurred when resetting EUICC."; |
| } |
| } |
| |
| void ShowNetworkDetails(const base::Value::List& arg_list) { |
| CHECK_EQ(1u, arg_list.size()); |
| std::string guid = arg_list[0].GetString(); |
| |
| InternetDetailDialog::ShowDialog(guid); |
| } |
| |
| void ShowNetworkConfig(const base::Value::List& arg_list) { |
| CHECK_EQ(1u, arg_list.size()); |
| std::string guid = arg_list[0].GetString(); |
| |
| InternetConfigDialog::ShowDialogForNetworkId(guid); |
| } |
| |
| void ShowAddNewWifi(const base::Value::List& arg_list) { |
| InternetConfigDialog::ShowDialogForNetworkType(::onc::network_type::kWiFi); |
| } |
| |
| void OnGetShillDeviceProperties(const std::string& callback_id, |
| const std::string& type, |
| const std::string& device_path, |
| std::optional<base::Value::Dict> result) { |
| if (!result) { |
| RunErrorCallback(callback_id, type, kGetDeviceProperties, |
| "GetDeviceProperties failed"); |
| return; |
| } |
| |
| // Set the 'device_path' property for debugging. |
| result->Set("device_path", device_path); |
| |
| base::Value::List return_arg_list; |
| return_arg_list.Append(std::move(*result)); |
| Respond(callback_id, return_arg_list); |
| } |
| |
| void GetHostname(const base::Value::List& arg_list) { |
| CHECK_EQ(1u, arg_list.size()); |
| std::string callback_id = arg_list[0].GetString(); |
| std::string hostname = |
| NetworkHandler::Get()->network_state_handler()->hostname(); |
| Respond(callback_id, base::Value(hostname)); |
| } |
| |
| void SetHostname(const base::Value::List& arg_list) { |
| CHECK_EQ(1u, arg_list.size()); |
| std::string hostname = arg_list[0].GetString(); |
| NET_LOG(USER) << "SET HOSTNAME: " << hostname; |
| NetworkHandler::Get()->network_state_handler()->SetHostname(hostname); |
| } |
| |
| void RunErrorCallback(const std::string& callback_id, |
| const std::string& guid_or_type, |
| const std::string& function_name, |
| const std::string& error_name) { |
| NET_LOG(ERROR) << "Shill Error: " << error_name << " id=" << guid_or_type; |
| std::string key = function_name == kGetDeviceProperties |
| ? shill::kTypeProperty |
| : shill::kGuidProperty; |
| |
| Respond(callback_id, base::Value::List().Append( |
| base::Value::Dict() |
| .Set(key, base::Value(guid_or_type)) |
| .Set("ShillError", base::Value(error_name)))); |
| } |
| |
| void AddNetwork(const base::Value::List& args) { |
| DCHECK(!args.empty()); |
| std::string onc_type = args[0].GetString(); |
| InternetConfigDialog::ShowDialogForNetworkType(onc_type); |
| } |
| |
| base::WeakPtrFactory<NetworkConfigMessageHandler> weak_ptr_factory_{this}; |
| }; |
| |
| class HotspotConfigMessageHandler : public content::WebUIMessageHandler { |
| public: |
| HotspotConfigMessageHandler() = default; |
| ~HotspotConfigMessageHandler() override = default; |
| |
| // WebUIMessageHandler implementation. |
| void RegisterMessages() override { |
| web_ui()->RegisterMessageCallback( |
| kGetTetheringCapabilities, |
| base::BindRepeating( |
| &HotspotConfigMessageHandler::GetTetheringCapabilities, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| kGetTetheringStatus, |
| base::BindRepeating(&HotspotConfigMessageHandler::GetTetheringStatus, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| kGetTetheringConfig, |
| base::BindRepeating(&HotspotConfigMessageHandler::GetTetheringConfig, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| kSetTetheringConfig, |
| base::BindRepeating(&HotspotConfigMessageHandler::SetTetheringConfig, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| kCheckTetheringReadiness, |
| base::BindRepeating( |
| &HotspotConfigMessageHandler::CheckTetheringReadiness, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| kSetTetheringEnabled, |
| base::BindRepeating(&HotspotConfigMessageHandler::SetTetheringEnabled, |
| base::Unretained(this))); |
| } |
| |
| private: |
| void Respond(const std::string& callback_id, const base::ValueView response) { |
| AllowJavascript(); |
| ResolveJavascriptCallback(base::Value(callback_id), response); |
| } |
| |
| void GetTetheringCapabilities(const base::Value::List& arg_list) { |
| CHECK_EQ(1u, arg_list.size()); |
| std::string callback_id = arg_list[0].GetString(); |
| |
| ShillManagerClient::Get()->GetProperties(base::BindOnce( |
| &HotspotConfigMessageHandler::OnGetShillManagerDictPropertiesByKey, |
| weak_ptr_factory_.GetWeakPtr(), callback_id, |
| shill::kTetheringCapabilitiesProperty)); |
| } |
| |
| void GetTetheringStatus(const base::Value::List& arg_list) { |
| CHECK_EQ(1u, arg_list.size()); |
| std::string callback_id = arg_list[0].GetString(); |
| |
| ShillManagerClient::Get()->GetProperties(base::BindOnce( |
| &HotspotConfigMessageHandler::OnGetShillManagerDictPropertiesByKey, |
| weak_ptr_factory_.GetWeakPtr(), callback_id, |
| shill::kTetheringStatusProperty)); |
| } |
| |
| void GetTetheringConfig(const base::Value::List& arg_list) { |
| CHECK_EQ(1u, arg_list.size()); |
| std::string callback_id = arg_list[0].GetString(); |
| |
| ShillManagerClient::Get()->GetProperties(base::BindOnce( |
| &HotspotConfigMessageHandler::OnGetShillManagerDictPropertiesByKey, |
| weak_ptr_factory_.GetWeakPtr(), callback_id, |
| shill::kTetheringConfigProperty)); |
| } |
| |
| void CheckTetheringReadiness(const base::Value::List& arg_list) { |
| CHECK_EQ(1u, arg_list.size()); |
| std::string callback_id = arg_list[0].GetString(); |
| |
| ShillManagerClient::Get()->CheckTetheringReadiness( |
| base::BindOnce(&HotspotConfigMessageHandler::RespondStringResult, |
| weak_ptr_factory_.GetWeakPtr(), callback_id), |
| base::BindOnce(&HotspotConfigMessageHandler::RespondError, |
| weak_ptr_factory_.GetWeakPtr(), callback_id, |
| kCheckTetheringReadiness)); |
| } |
| |
| void SetTetheringEnabled(const base::Value::List& arg_list) { |
| CHECK_EQ(2u, arg_list.size()); |
| std::string callback_id = arg_list[0].GetString(); |
| bool enabled = arg_list[1].GetBool(); |
| |
| // Enable TetheringAllowed flag in Shill manager before turning on/off |
| // tethering. |
| ShillManagerClient::Get()->SetProperty( |
| shill::kTetheringAllowedProperty, base::Value(true), |
| base::BindOnce(&HotspotConfigMessageHandler::PerformSetTetheringEnabled, |
| weak_ptr_factory_.GetWeakPtr(), callback_id, enabled), |
| base::BindOnce( |
| &HotspotConfigMessageHandler::SetManagerPropertiesErrorCallback, |
| weak_ptr_factory_.GetWeakPtr(), callback_id, |
| shill::kTetheringConfigProperty)); |
| } |
| |
| void PerformSetTetheringEnabled(const std::string& callback_id, |
| bool enabled) { |
| ShillManagerClient::Get()->SetTetheringEnabled( |
| enabled, |
| base::BindOnce(&HotspotConfigMessageHandler::RespondStringResult, |
| weak_ptr_factory_.GetWeakPtr(), callback_id), |
| base::BindOnce(&HotspotConfigMessageHandler::RespondError, |
| weak_ptr_factory_.GetWeakPtr(), callback_id, |
| kSetTetheringEnabled)); |
| } |
| |
| void SetTetheringConfig(const base::Value::List& arg_list) { |
| CHECK_EQ(2u, arg_list.size()); |
| std::string callback_id = arg_list[0].GetString(); |
| std::string tethering_config = arg_list[1].GetString(); |
| std::optional<base::Value> value = base::JSONReader::Read(tethering_config); |
| |
| if (!value || !value->is_dict()) { |
| NET_LOG(ERROR) << "Invalid tethering configuration: " << tethering_config; |
| Respond(callback_id, base::Value("Invalid tethering configuration")); |
| return; |
| } |
| NET_LOG(USER) << "SetManagerProperty: " << shill::kTetheringConfigProperty |
| << ": " << *value; |
| const std::string* ssid = |
| value->GetDict().FindString(shill::kTetheringConfSSIDProperty); |
| if (ssid) { |
| value->GetDict().Set(shill::kTetheringConfSSIDProperty, |
| base::Value(base::HexEncode(*ssid))); |
| } |
| |
| ShillManagerClient::Get()->SetProperty( |
| shill::kTetheringConfigProperty, *value, |
| base::BindOnce(&HotspotConfigMessageHandler::RespondStringResult, |
| weak_ptr_factory_.GetWeakPtr(), callback_id, "success"), |
| base::BindOnce( |
| &HotspotConfigMessageHandler::SetManagerPropertiesErrorCallback, |
| weak_ptr_factory_.GetWeakPtr(), callback_id, |
| shill::kTetheringConfigProperty)); |
| } |
| |
| void OnGetShillManagerDictPropertiesByKey( |
| const std::string& callback_id, |
| const std::string& dict_key, |
| std::optional<base::Value::Dict> properties) { |
| if (!properties) { |
| NET_LOG(ERROR) << "Error getting Shill manager properties."; |
| Respond(callback_id, |
| base::Value("Error getting Shill manager properties.")); |
| return; |
| } |
| |
| base::Value::Dict* value = properties->FindDict(dict_key); |
| if (value) { |
| const std::string* ssid = |
| value->FindString(shill::kTetheringConfSSIDProperty); |
| if (ssid) { |
| value->Set(shill::kTetheringConfSSIDProperty, HexDecode(*ssid)); |
| } |
| Respond(callback_id, *value); |
| return; |
| } |
| |
| Respond(callback_id, base::Value::Dict()); |
| } |
| |
| void SetManagerPropertiesErrorCallback( |
| const std::string& callback_id, |
| const std::string& property_name, |
| const std::string& dbus_error_name, |
| const std::string& dbus_error_message) { |
| NET_LOG(ERROR) << "Error setting Shill manager properties: " |
| << property_name << ", error: " << dbus_error_name |
| << ", message: " << dbus_error_message; |
| Respond(callback_id, base::Value(dbus_error_name)); |
| } |
| |
| void RespondError(const std::string& callback_id, |
| const std::string& operation, |
| const std::string& error_name, |
| const std::string& error_message) { |
| NET_LOG(ERROR) << "Error occured when " << operation << ": " << error_name |
| << ", error message: " << error_message; |
| Respond(callback_id, base::Value(error_name)); |
| } |
| |
| void RespondStringResult(const std::string& callback_id, |
| const std::string& result) { |
| Respond(callback_id, base::Value(result)); |
| } |
| |
| base::WeakPtrFactory<HotspotConfigMessageHandler> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace network_ui |
| |
| // static |
| base::Value::Dict NetworkUI::GetLocalizedStrings() { |
| return base::Value::Dict() |
| .Set("titleText", l10n_util::GetStringUTF16(IDS_NETWORK_UI_TITLE)) |
| .Set("generalTab", l10n_util::GetStringUTF16(IDS_NETWORK_UI_TAB_GENERAL)) |
| .Set("networkHealthTab", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_TAB_NETWORK_HEALTH)) |
| .Set("networkLogsTab", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_TAB_NETWORK_LOGS)) |
| .Set("networkStateTab", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_TAB_NETWORK_STATE)) |
| .Set("networkSelectTab", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_TAB_NETWORK_SELECT)) |
| .Set("networkHotspotTab", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_TAB_NETWORK_HOTSPOT)) |
| .Set("networkMetricsTab", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_TAB_NETWORK_METRICS)) |
| .Set("autoRefreshText", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_AUTO_REFRESH)) |
| .Set("deviceLogLinkText", |
| l10n_util::GetStringUTF16(IDS_DEVICE_LOG_LINK_TEXT)) |
| .Set("networkRefreshText", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_REFRESH)) |
| .Set("clickToExpandText", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_EXPAND)) |
| .Set("propertyFormatText", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_PROPERTY_FORMAT)) |
| .Set("normalFormatOption", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_FORMAT_NORMAL)) |
| .Set("managedFormatOption", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_FORMAT_MANAGED)) |
| .Set("stateFormatOption", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_FORMAT_STATE)) |
| .Set("shillFormatOption", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_FORMAT_SHILL)) |
| .Set("dhcpHostnameLabel", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_DHCP_HOSTNAME)) |
| .Set("globalPolicyLabel", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_GLOBAL_POLICY)) |
| .Set("networkListsLabel", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LISTS)) |
| .Set("networkHealthLabel", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_HEALTH)) |
| .Set("networkDiagnosticsLabel", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_DIAGNOSTICS)) |
| .Set("visibleNetworksLabel", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_VISIBLE_NETWORKS)) |
| .Set("favoriteNetworksLabel", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_FAVORITE_NETWORKS)) |
| .Set("ethernetEapNetworkLabel", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_ETHERNET_EAP)) |
| .Set("devicesLabel", l10n_util::GetStringUTF16(IDS_NETWORK_UI_DEVICES)) |
| .Set("cellularActivationLabel", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_NO_CELLULAR_ACTIVATION_LABEL)) |
| .Set("cellularActivationButtonText", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_OPEN_CELLULAR_ACTIVATION_BUTTON_TEXT)) |
| .Set("noCellularErrorText", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_NO_CELLULAR_ERROR_TEXT)) |
| .Set("resetESimCacheLabel", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_RESET_ESIM_PROFILES_BUTTON_TEXT)) |
| .Set("resetESimCacheButtonText", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_RESET_ESIM_PROFILES_BUTTON_TEXT)) |
| .Set( |
| "disableESimProfilesLabel", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_DISABLE_ESIM_PROFILES_LABEL)) |
| .Set("disableActiveESimProfileButtonText", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_DISABLE_ACTIVE_ESIM_PROFILE_BUTTON_TEXT)) |
| .Set("resetEuiccLabel", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_RESET_EUICC_LABEL)) |
| .Set("resetApnMigratorLabel", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_RESET_APN_MIGRATOR_LABEL)) |
| .Set("addNewWifiLabel", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_ADD_NEW_WIFI_LABEL)) |
| .Set("addNewWifiButtonText", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_ADD_NEW_WIFI_BUTTON_TEXT)) |
| .Set("importOncButtonText", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_IMPORT_ONC_BUTTON_TEXT)) |
| .Set("addWiFiListItemName", |
| l10n_util::GetStringUTF16(IDS_NETWORK_ADD_WI_FI_LIST_ITEM_NAME)) |
| |
| // Network logs |
| .Set("networkLogsDescription", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LOGS_DESCRIPTION)) |
| .Set("networkLogsSystemLogs", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LOGS_SYSTEM_LOGS)) |
| .Set("networkLogsFilterPii", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LOGS_FILTER_PII)) |
| .Set("networkLogsPolicies", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LOGS_POLICIES)) |
| .Set("networkLogsDebugLogs", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LOGS_DEBUG_LOGS)) |
| .Set("networkLogsChromeLogs", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LOGS_CHROME_LOGS)) |
| .Set("networkLogsStoreButton", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LOGS_STORE_BUTTON)) |
| .Set("networkLogsStatus", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LOGS_STATUS)) |
| .Set("networkLogsDebuggingTitle", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_NETWORK_LOGS_DEBUGGING_TITLE)) |
| .Set("networkLogsDebuggingDescription", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_NETWORK_LOGS_DEBUGGING_DESCRIPTION)) |
| .Set( |
| "networkLogsDebuggingNone", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LOGS_DEBUGGING_NONE)) |
| .Set("networkLogsDebuggingUnknown", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_NETWORK_LOGS_DEBUGGING_UNKNOWN)) |
| |
| // Network Diagnostics |
| .Set("NetworkDiagnosticsRunAll", |
| l10n_util::GetStringUTF16(IDS_NETWORK_DIAGNOSTICS_RUN_ALL)) |
| .Set("NetworkDiagnosticsSendFeedback", |
| l10n_util::GetStringUTF16(IDS_NETWORK_DIAGNOSTICS_SEND_FEEDBACK)) |
| .Set("renderNetworkSelectButtonText", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_RENDER_NETWORK_SELECT_BUTTON_TEXT)) |
| .Set("renderNetworkSelectButtonDescription", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_RENDER_NETWORK_SELECT_BUTTON_DESCRIPTION)) |
| |
| // Network Metrics |
| .Set("networkMetricsLabel", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_METRICS_LABEL)) |
| .Set("renderGraphButtonText", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_NETWORK_METRICS_RENDER_BUTTON)) |
| .Set("startPlotsButtonText", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_NETWORK_METRICS_START_BUTTON)) |
| .Set( |
| "stopPlotsButtonText", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_METRICS_STOP_BUTTON)) |
| .Set("increaseRateButtonText", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_NETWORK_METRICS_INCREASE_RATE_BUTTON)) |
| .Set("decreaseRateButtonText", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_NETWORK_METRICS_DECREASE_RATE_BUTTON)) |
| |
| // Network Hotspot |
| .Set("tetheringCapabilitiesLabel", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_TETHERING_CAPABILITIES_LABEL)) |
| .Set("refreshTetheringCapabilitiesButtonText", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_REFRESH_TETHERING_CAPABILITIES_BUTTON_TEXT)) |
| .Set("tetheringStatusLabel", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_TETHERING_STATUS_LABEL)) |
| .Set("refreshTetheringStatusButtonText", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_REFRESH_TETHERING_STATUS_BUTTON_TEXT)) |
| .Set("tetheringConfigLabel", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_TETHERING_CONFIG_LABEL)) |
| .Set("refreshTetheringConfigButtonText", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_REFRESH_TETHERING_CONFIG_BUTTON_TEXT)) |
| .Set("setTetheringConfigButtonText", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_SET_TETHERING_CONFIG_BUTTON_TEXT)) |
| .Set("tetheringReadinessLabel", |
| l10n_util::GetStringUTF16(IDS_NETWORK_UI_TETHERING_READINESS_LABEL)) |
| .Set("checkTetheringReadinessButtonText", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_CHECK_TETHERING_READINESS_BUTTON_TEXT)) |
| .Set("setTetheringEnabledLabel", |
| l10n_util::GetStringUTF16( |
| IDS_NETWORK_UI_SET_TETHERING_ENABLED_LABEL)); |
| } |
| |
| NetworkUI::NetworkUI(content::WebUI* web_ui) |
| : ui::MojoWebUIController(web_ui, /*enable_chrome_send=*/true) { |
| web_ui->AddMessageHandler( |
| std::make_unique<network_ui::NetworkConfigMessageHandler>()); |
| web_ui->AddMessageHandler(std::make_unique<OncImportMessageHandler>()); |
| web_ui->AddMessageHandler(std::make_unique<NetworkLogsMessageHandler>()); |
| web_ui->AddMessageHandler( |
| std::make_unique<NetworkDiagnosticsMessageHandler>()); |
| web_ui->AddMessageHandler( |
| std::make_unique<network_ui::HotspotConfigMessageHandler>()); |
| |
| // Enable extension API calls in the WebUI. |
| extensions::TabHelper::CreateForWebContents(web_ui->GetWebContents()); |
| |
| base::Value::Dict localized_strings = GetLocalizedStrings(); |
| |
| content::WebUIDataSource* html = content::WebUIDataSource::CreateAndAdd( |
| web_ui->GetWebContents()->GetBrowserContext(), |
| chrome::kChromeUINetworkHost); |
| |
| html->AddLocalizedStrings(localized_strings); |
| html->AddBoolean("isGuestModeActive", IsGuestModeActive()); |
| html->AddBoolean("isHotspotEnabled", features::IsHotspotEnabled()); |
| html->AddString("tetheringStateStarting", shill::kTetheringStateStarting); |
| html->AddString("tetheringStateActive", shill::kTetheringStateActive); |
| network_health::AddResources(html); |
| network_diagnostics::AddResources(html); |
| cellular_setup::AddLocalizedStrings(html); |
| cellular_setup::AddNonStringLoadTimeData(html); |
| ui::network_element::AddLocalizedStrings(html); |
| ui::network_element::AddOncLocalizedStrings(html); |
| traffic_counters::AddResources(html); |
| |
| webui::SetupWebUIDataSource( |
| html, base::make_span(kNetworkUiResources, kNetworkUiResourcesSize), |
| IDR_NETWORK_UI_NETWORK_HTML); |
| // Enabling trusted types via trusted_types_util must be done after |
| // webui::SetupWebUIDataSource to override the trusted type CSP with correct |
| // policies for JS WebUIs. |
| ash::EnableTrustedTypesCSP(html); |
| } |
| |
| NetworkUI::~NetworkUI() = default; |
| |
| void NetworkUI::BindInterface( |
| mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig> |
| receiver) { |
| GetNetworkConfigService(std::move(receiver)); |
| } |
| |
| void NetworkUI::BindInterface( |
| mojo::PendingReceiver<chromeos::network_health::mojom::NetworkHealthService> |
| receiver) { |
| network_health::NetworkHealthManager::GetInstance()->BindHealthReceiver( |
| std::move(receiver)); |
| } |
| |
| void NetworkUI::BindInterface( |
| mojo::PendingReceiver< |
| chromeos::network_diagnostics::mojom::NetworkDiagnosticsRoutines> |
| receiver) { |
| network_health::NetworkHealthManager::GetInstance()->BindDiagnosticsReceiver( |
| std::move(receiver)); |
| } |
| |
| void NetworkUI::BindInterface( |
| mojo::PendingReceiver<cellular_setup::mojom::ESimManager> receiver) { |
| GetESimManager(std::move(receiver)); |
| } |
| |
| void NetworkUI::BindInterface( |
| mojo::PendingReceiver<chromeos::connectivity::mojom::PasspointService> |
| receiver) { |
| GetPasspointService(std::move(receiver)); |
| } |
| |
| WEB_UI_CONTROLLER_TYPE_IMPL(NetworkUI) |
| |
| } // namespace ash |