| // Copyright 2019 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/management/management_ui_handler_chromeos.h" |
| |
| #include "ash/constants/ash_features.h" |
| #include "base/check_is_test.h" |
| #include "base/strings/string_util.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "chrome/browser/ash/crostini/crostini_features.h" |
| #include "chrome/browser/ash/crostini/crostini_pref_names.h" |
| #include "chrome/browser/ash/floating_sso/floating_sso_service.h" |
| #include "chrome/browser/ash/floating_sso/floating_sso_service_factory.h" |
| #include "chrome/browser/ash/floating_workspace/floating_workspace_util.h" |
| #include "chrome/browser/ash/net/secure_dns_manager.h" |
| #include "chrome/browser/ash/plugin_vm/plugin_vm_pref_names.h" |
| #include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h" |
| #include "chrome/browser/ash/policy/core/device_cloud_policy_manager_ash.h" |
| #include "chrome/browser/ash/policy/handlers/minimum_version_policy_handler.h" |
| #include "chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_prefs.h" |
| #include "chrome/browser/ash/policy/skyvault/policy_utils.h" |
| #include "chrome/browser/ash/policy/status_collector/device_status_collector.h" |
| #include "chrome/browser/ash/policy/status_collector/status_collector.h" |
| #include "chrome/browser/ash/policy/uploading/status_uploader.h" |
| #include "chrome/browser/ash/policy/uploading/system_log_uploader.h" |
| #include "chrome/browser/ash/profiles/profile_helper.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/browser_process_platform_part_ash.h" |
| #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h" |
| #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_factory.h" |
| #include "chrome/browser/chromeos/reporting/metric_reporting_prefs.h" |
| #include "chrome/browser/enterprise/browser_management/management_service_factory.h" |
| #include "chrome/browser/enterprise/reporting/prefs.h" |
| #include "chrome/browser/net/stub_resolver_config_reader.h" |
| #include "chrome/browser/net/system_network_context_manager.h" |
| #include "chrome/browser/policy/networking/policy_cert_service.h" |
| #include "chrome/browser/policy/networking/policy_cert_service_factory.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/managed_ui.h" |
| #include "chrome/browser/ui/webui/management/management_ui_constants.h" |
| #include "chrome/browser/ui/webui/management/management_ui_handler_chromeos.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/grit/branded_strings.h" |
| #include "chromeos/ash/components/browser_context_helper/browser_context_helper.h" |
| #include "chromeos/ash/components/network/network_state_handler.h" |
| #include "chromeos/ash/components/network/proxy/proxy_config_handler.h" |
| #include "chromeos/ash/components/network/proxy/ui_proxy_config_service.h" |
| #include "chromeos/ash/components/settings/cros_settings.h" |
| #include "chromeos/ash/components/settings/cros_settings_names.h" |
| #include "components/enterprise/browser/reporting/common_pref_names.h" |
| #include "components/policy/core/common/cloud/user_cloud_policy_manager.h" |
| #include "components/policy/core/common/management/management_service.h" |
| #include "components/policy/policy_constants.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/strings/grit/components_strings.h" |
| #include "components/user_manager/user_manager.h" |
| #include "content/public/browser/storage_partition.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/chromeos/devicetype_utils.h" |
| #include "ui/webui/webui_util.h" |
| |
| namespace { |
| |
| const char kAccountManagedInfo[] = "accountManagedInfo"; |
| const char kDeviceManagedInfo[] = "deviceManagedInfo"; |
| const char kOverview[] = "overview"; |
| |
| enum class DeviceReportingType { |
| kSupervisedUser, |
| kDeviceActivity, |
| kDeviceStatistics, |
| kDevice, |
| kCrashReport, |
| kAppInfoAndActivity, |
| kLogs, |
| kPrint, |
| kPrintJobs, |
| kCrostini, |
| kUsername, |
| kExtensions, |
| kAndroidApplication, |
| kDlpEvents, |
| kLoginLogout, |
| kCRDSessions, |
| kPeripherals, |
| kLegacyTech, |
| kWebsiteInfoAndActivity, |
| kFileEvents, |
| }; |
| |
| const char kCustomerLogo[] = "customerLogo"; |
| |
| net::NetworkTrafficAnnotationTag GetManagementUICustomerLogoAnnotation() { |
| return net::DefineNetworkTrafficAnnotation("management_ui_customer_logo", R"( |
| semantics { |
| sender: "Management UI Handler" |
| description: |
| "Download organization logo for visualization on the " |
| "chrome://management page." |
| trigger: |
| "The user managed by organization that provides a company logo " |
| "in their GSuites account loads the chrome://management page." |
| data: |
| "Organization uploaded image URL." |
| destination: GOOGLE_OWNED_SERVICE |
| } |
| policy { |
| cookies_allowed: NO |
| setting: |
| "This feature cannot be disabled by settings, but it is only " |
| "triggered by a user action." |
| policy_exception_justification: "Not implemented." |
| })"); |
| } |
| |
| // Corresponds to DeviceReportingType in management_browser_proxy.js |
| std::string ToJSDeviceReportingType(const DeviceReportingType& type) { |
| switch (type) { |
| case DeviceReportingType::kSupervisedUser: |
| return "supervised user"; |
| case DeviceReportingType::kDeviceActivity: |
| return "device activity"; |
| case DeviceReportingType::kDeviceStatistics: |
| return "device statistics"; |
| case DeviceReportingType::kDevice: |
| return "device"; |
| case DeviceReportingType::kCrashReport: |
| return "crash report"; |
| case DeviceReportingType::kAppInfoAndActivity: |
| return "app info and activity"; |
| case DeviceReportingType::kLogs: |
| return "logs"; |
| case DeviceReportingType::kPrint: |
| return "print"; |
| case DeviceReportingType::kPrintJobs: |
| return "print jobs"; |
| case DeviceReportingType::kCrostini: |
| return "crostini"; |
| case DeviceReportingType::kUsername: |
| return "username"; |
| case DeviceReportingType::kExtensions: |
| return "extension"; |
| case DeviceReportingType::kAndroidApplication: |
| return "android application"; |
| case DeviceReportingType::kDlpEvents: |
| return "dlp events"; |
| case DeviceReportingType::kLoginLogout: |
| return "login-logout"; |
| case DeviceReportingType::kCRDSessions: |
| return "crd sessions"; |
| case DeviceReportingType::kPeripherals: |
| return "peripherals"; |
| case DeviceReportingType::kLegacyTech: |
| return kReportingTypeLegacyTech; |
| case DeviceReportingType::kWebsiteInfoAndActivity: |
| return "website info and activity"; |
| case DeviceReportingType::kFileEvents: |
| return "file events"; |
| default: |
| NOTREACHED() << "Unknown device reporting type"; |
| } |
| } |
| |
| std::string GetWebsiteReportingAllowlistMessageParam( |
| const base::Value::List& url_allowlist) { |
| std::vector<std::string> url_patterns; |
| for (const base::Value& pattern_value : url_allowlist) { |
| url_patterns.push_back(pattern_value.GetString()); |
| } |
| |
| return base::JoinString(url_patterns, ", "); |
| } |
| |
| void AddDeviceReportingElement( |
| base::Value::List* report_sources, |
| const std::string& message_id, |
| const DeviceReportingType& type, |
| base::Value::List message_params = base::Value::List()) { |
| base::Value::Dict data; |
| data.Set("messageId", message_id); |
| data.Set("reportingType", ToJSDeviceReportingType(type)); |
| data.Set("messageParams", std::move(message_params)); |
| |
| report_sources->Append(std::move(data)); |
| } |
| |
| const policy::DlpRulesManager* GetDlpRulesManager() { |
| return policy::DlpRulesManagerFactory::GetForPrimaryProfile(); |
| } |
| |
| // If you are adding a privacy note, please also add it to |
| // go/chrome-policy-privacy-note-mappings. |
| void AddDeviceReportingInfo(base::Value::List* report_sources, |
| const policy::StatusCollector* collector, |
| const policy::SystemLogUploader* uploader, |
| Profile* profile) { |
| if (!collector || !profile || !uploader) { |
| return; |
| } |
| |
| // Elements appear on the page in the order they are added. |
| bool report_device_peripherals = false; |
| ash::CrosSettings::Get()->GetBoolean(ash::kReportDevicePeripherals, |
| &report_device_peripherals); |
| bool report_audio_status = false; |
| ash::CrosSettings::Get()->GetBoolean(ash::kReportDeviceAudioStatus, |
| &report_audio_status); |
| // TODO(b/262295601): Add/refine management strings corresponding to XDR |
| // reporting policy. |
| bool device_report_xdr_events = false; |
| ash::CrosSettings::Get()->GetBoolean(ash::kDeviceReportXDREvents, |
| &device_report_xdr_events); |
| if (collector->IsReportingActivityTimes() || report_device_peripherals || |
| report_audio_status || device_report_xdr_events || |
| profile->GetPrefs()->GetBoolean(::prefs::kInsightsExtensionEnabled)) { |
| AddDeviceReportingElement(report_sources, kManagementReportActivityTimes, |
| DeviceReportingType::kDeviceActivity); |
| } else { |
| if (collector->IsReportingUsers()) { |
| AddDeviceReportingElement(report_sources, kManagementReportUsers, |
| DeviceReportingType::kSupervisedUser); |
| } |
| } |
| if (collector->IsReportingNetworkData() || |
| profile->GetPrefs()->GetBoolean(::prefs::kInsightsExtensionEnabled)) { |
| AddDeviceReportingElement(report_sources, kManagementReportNetworkData, |
| DeviceReportingType::kDevice); |
| } |
| if (collector->IsReportingHardwareData()) { |
| AddDeviceReportingElement(report_sources, kManagementReportHardwareData, |
| DeviceReportingType::kDeviceStatistics); |
| } |
| if (collector->IsReportingCrashReportInfo()) { |
| AddDeviceReportingElement(report_sources, kManagementReportCrashReports, |
| DeviceReportingType::kCrashReport); |
| } |
| |
| const auto& app_inventory_app_types = |
| profile->GetPrefs()->GetList(::ash::reporting::kReportAppInventory); |
| const auto& app_usage_app_types = |
| profile->GetPrefs()->GetList(::ash::reporting::kReportAppUsage); |
| if (collector->IsReportingAppInfoAndActivity() || device_report_xdr_events || |
| !app_inventory_app_types.empty() || !app_usage_app_types.empty()) { |
| AddDeviceReportingElement(report_sources, |
| kManagementReportAppInfoAndActivity, |
| DeviceReportingType::kAppInfoAndActivity); |
| } |
| if (uploader->upload_enabled()) { |
| AddDeviceReportingElement(report_sources, kManagementLogUploadEnabled, |
| DeviceReportingType::kLogs); |
| } |
| |
| if (report_audio_status) { |
| AddDeviceReportingElement(report_sources, |
| kManagementReportDeviceAudioStatus, |
| DeviceReportingType::kDevice); |
| } |
| |
| bool report_graphics_status = false; |
| ash::CrosSettings::Get()->GetBoolean(ash::kReportDeviceGraphicsStatus, |
| &report_graphics_status); |
| if (report_graphics_status) { |
| AddDeviceReportingElement(report_sources, |
| kManagementReportDeviceGraphicsStatus, |
| DeviceReportingType::kDevice); |
| } |
| |
| if (report_device_peripherals) { |
| AddDeviceReportingElement(report_sources, |
| kManagementReportDevicePeripherals, |
| DeviceReportingType::kPeripherals); |
| } |
| |
| bool report_print_jobs = false; |
| ash::CrosSettings::Get()->GetBoolean(ash::kReportDevicePrintJobs, |
| &report_print_jobs); |
| if (report_print_jobs) { |
| AddDeviceReportingElement(report_sources, kManagementReportPrintJobs, |
| DeviceReportingType::kPrintJobs); |
| } |
| |
| bool report_print_username = profile->GetPrefs()->GetBoolean( |
| prefs::kPrintingSendUsernameAndFilenameEnabled); |
| if (report_print_username && !report_print_jobs) { |
| AddDeviceReportingElement(report_sources, kManagementPrinting, |
| DeviceReportingType::kPrint); |
| } |
| |
| if (GetDlpRulesManager() && GetDlpRulesManager()->IsReportingEnabled()) { |
| AddDeviceReportingElement(report_sources, kManagementReportDlpEvents, |
| DeviceReportingType::kDlpEvents); |
| } |
| |
| if (crostini::CrostiniFeatures::Get()->IsAllowedNow(profile)) { |
| if (!profile->GetPrefs() |
| ->GetFilePath(crostini::prefs::kCrostiniAnsiblePlaybookFilePath) |
| .empty()) { |
| AddDeviceReportingElement(report_sources, |
| kManagementCrostiniContainerConfiguration, |
| DeviceReportingType::kCrostini); |
| } else if (profile->GetPrefs()->GetBoolean( |
| crostini::prefs::kReportCrostiniUsageEnabled)) { |
| AddDeviceReportingElement(report_sources, kManagementCrostini, |
| DeviceReportingType::kCrostini); |
| } |
| } |
| |
| if (g_browser_process->local_state()->GetBoolean( |
| enterprise_reporting::kCloudReportingEnabled)) { |
| AddDeviceReportingElement(report_sources, |
| kManagementExtensionReportUsername, |
| DeviceReportingType::kUsername); |
| AddDeviceReportingElement(report_sources, kManagementReportExtensions, |
| DeviceReportingType::kExtensions); |
| AddDeviceReportingElement(report_sources, |
| kManagementReportAndroidApplications, |
| DeviceReportingType::kAndroidApplication); |
| } |
| |
| if (!profile->GetPrefs() |
| ->GetList(enterprise_reporting::kCloudLegacyTechReportAllowlist) |
| .empty()) { |
| AddDeviceReportingElement(report_sources, kManagementLegacyTechReport, |
| DeviceReportingType::kLegacyTech); |
| } |
| |
| bool report_login_logout = false; |
| ash::CrosSettings::Get()->GetBoolean(ash::kReportDeviceLoginLogout, |
| &report_login_logout); |
| bool report_xdr_events = false; |
| ash::CrosSettings::Get()->GetBoolean(ash::kDeviceReportXDREvents, |
| &report_xdr_events); |
| if (report_login_logout || report_xdr_events) { |
| AddDeviceReportingElement(report_sources, kManagementReportLoginLogout, |
| DeviceReportingType::kLoginLogout); |
| } |
| |
| if (report_xdr_events) { |
| AddDeviceReportingElement(report_sources, kManagementReportFileEvents, |
| DeviceReportingType::kFileEvents); |
| } |
| |
| bool report_crd_sessions = false; |
| ash::CrosSettings::Get()->GetBoolean(ash::kReportCRDSessions, |
| &report_crd_sessions); |
| if (report_crd_sessions) { |
| AddDeviceReportingElement(report_sources, kManagementReportCRDSessions, |
| DeviceReportingType::kCRDSessions); |
| } |
| |
| const auto wildcard_pattern_string = |
| ContentSettingsPattern::Wildcard().ToString(); |
| const auto& website_telemetry_types = |
| profile->GetPrefs()->GetList(::reporting::kReportWebsiteTelemetry); |
| const auto& website_telemetry_allowlist = profile->GetPrefs()->GetList( |
| ::reporting::kReportWebsiteTelemetryAllowlist); |
| const auto& website_activity_allowlist = profile->GetPrefs()->GetList( |
| ::reporting::kReportWebsiteActivityAllowlist); |
| if (base::Contains(website_activity_allowlist, wildcard_pattern_string) || |
| (!website_telemetry_types.empty() && |
| base::Contains(website_telemetry_allowlist, wildcard_pattern_string))) { |
| // One or more website metrics reporting policies allowlists all website |
| // URLs. |
| AddDeviceReportingElement(report_sources, |
| kManagementReportAllWebsiteInfoAndActivity, |
| DeviceReportingType::kWebsiteInfoAndActivity); |
| } else if (!website_activity_allowlist.empty()) { |
| // Admin defined subset of URLs allowlisted for website activity reporting. |
| base::Value::List message_params; |
| message_params.Append( |
| GetWebsiteReportingAllowlistMessageParam(website_activity_allowlist)); |
| AddDeviceReportingElement(report_sources, |
| kManagementReportWebsiteInfoAndActivity, |
| DeviceReportingType::kWebsiteInfoAndActivity, |
| std::move(message_params)); |
| } else if (!website_telemetry_types.empty() && |
| !website_telemetry_allowlist.empty()) { |
| // Admin defined subset of URLs allowlisted for website telemetry reporting. |
| base::Value::List message_params; |
| message_params.Append( |
| GetWebsiteReportingAllowlistMessageParam(website_telemetry_allowlist)); |
| AddDeviceReportingElement(report_sources, |
| kManagementReportWebsiteInfoAndActivity, |
| DeviceReportingType::kWebsiteInfoAndActivity, |
| std::move(message_params)); |
| } |
| } |
| |
| void AddStatusOverviewManagedDeviceAndAccount( |
| base::Value::Dict* status, |
| bool device_managed, |
| bool account_managed, |
| const std::string& device_manager, |
| const std::string& account_manager) { |
| if (device_managed && account_managed && |
| (account_manager.empty() || account_manager == device_manager)) { |
| status->Set(kOverview, base::Value(l10n_util::GetStringFUTF16( |
| IDS_MANAGEMENT_DEVICE_AND_ACCOUNT_MANAGED_BY, |
| base::UTF8ToUTF16(device_manager)))); |
| |
| return; |
| } |
| |
| if (account_managed && !account_manager.empty()) { |
| status->Set(kOverview, base::Value(l10n_util::GetStringFUTF16( |
| IDS_MANAGEMENT_ACCOUNT_MANAGED_BY, |
| base::UTF8ToUTF16(account_manager)))); |
| } |
| |
| if (account_managed && device_managed && !account_manager.empty() && |
| account_manager != device_manager) { |
| status->Set(kOverview, |
| base::Value(l10n_util::GetStringFUTF16( |
| IDS_MANAGEMENT_DEVICE_MANAGED_BY_ACCOUNT_MANAGED_BY, |
| base::UTF8ToUTF16(device_manager), |
| base::UTF8ToUTF16(account_manager)))); |
| } |
| } |
| |
| bool IsCloudDestination(policy::local_user_files::FileSaveDestination dest) { |
| return dest == policy::local_user_files::FileSaveDestination::kGoogleDrive || |
| dest == policy::local_user_files::FileSaveDestination::kOneDrive; |
| } |
| |
| bool IsActiveProfile(const Profile* profile) { |
| const auto* active_user = user_manager::UserManager::Get()->GetActiveUser(); |
| if (!active_user) { |
| return false; |
| } |
| auto* active_browser_context = |
| ash::BrowserContextHelper::Get()->GetBrowserContextByUser(active_user); |
| if (!active_browser_context) { |
| return false; |
| } |
| return profile == Profile::FromBrowserContext(active_browser_context); |
| } |
| |
| bool IsFloatingSsoEnabled(Profile* profile) { |
| if (!ash::features::IsFloatingSsoAllowed()) { |
| return false; |
| } |
| ash::floating_sso::FloatingSsoService* floating_sso_service = |
| ash::floating_sso::FloatingSsoServiceFactory::GetForProfile(profile); |
| if (!floating_sso_service) { |
| return false; |
| } |
| return floating_sso_service->IsFloatingSsoEnabled(); |
| } |
| |
| } // namespace |
| |
| ManagementUIHandlerChromeOS::ManagementUIHandlerChromeOS(Profile* profile) |
| : ManagementUIHandler(profile) { |
| // profile is unset during unittest, in which case, we can initial device |
| // managed state in ctor either. Hence skip the process. |
| if (!profile) { |
| CHECK_IS_TEST(); |
| return; |
| } |
| UpdateDeviceManagedState(); |
| } |
| |
| ManagementUIHandlerChromeOS::~ManagementUIHandlerChromeOS() = default; |
| |
| void ManagementUIHandlerChromeOS::RegisterMessages() { |
| ManagementUIHandler::RegisterMessages(); |
| web_ui()->RegisterMessageCallback( |
| "getLocalTrustRootsInfo", |
| base::BindRepeating( |
| &ManagementUIHandlerChromeOS::HandleGetLocalTrustRootsInfo, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| "getDeviceReportingInfo", |
| base::BindRepeating( |
| &ManagementUIHandlerChromeOS::HandleGetDeviceReportingInfo, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| "getPluginVmDataCollectionStatus", |
| base::BindRepeating( |
| &ManagementUIHandlerChromeOS::HandleGetPluginVmDataCollectionStatus, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| "getFilesUploadToCloudInfo", |
| base::BindRepeating( |
| &ManagementUIHandlerChromeOS::HandleGetFilesUploadToCloudInfo, |
| base::Unretained(this))); |
| |
| if (IsJavascriptAllowed()) { |
| NotifyThreatProtectionInfoUpdated(); |
| } |
| } |
| |
| // static |
| base::Value::List ManagementUIHandlerChromeOS::GetDeviceReportingInfo( |
| const policy::DeviceCloudPolicyManagerAsh* manager, |
| Profile* profile) { |
| base::Value::List report_sources; |
| policy::StatusUploader* uploader = nullptr; |
| policy::SystemLogUploader* syslog_uploader = nullptr; |
| policy::StatusCollector* collector = nullptr; |
| if (manager) { |
| uploader = manager->GetStatusUploader(); |
| syslog_uploader = manager->GetSystemLogUploader(); |
| if (uploader) { |
| collector = uploader->status_collector(); |
| } |
| } |
| AddDeviceReportingInfo(&report_sources, collector, syslog_uploader, profile); |
| return report_sources; |
| } |
| |
| // static |
| void ManagementUIHandlerChromeOS::AddDlpDeviceReportingElementForTesting( |
| base::Value::List* report_sources, |
| const std::string& message_id) { |
| AddDeviceReportingElement(report_sources, message_id, |
| DeviceReportingType::kDlpEvents); |
| } |
| |
| // static |
| void ManagementUIHandlerChromeOS::AddDeviceReportingInfoForTesting( |
| base::Value::List* report_sources, |
| const policy::StatusCollector* collector, |
| const policy::SystemLogUploader* uploader, |
| Profile* profile) { |
| AddDeviceReportingInfo(report_sources, collector, uploader, profile); |
| } |
| |
| const policy::DeviceCloudPolicyManagerAsh* |
| ManagementUIHandlerChromeOS::GetDeviceCloudPolicyManager() const { |
| // Only check for report status in managed environment. |
| if (!device_managed_) { |
| return nullptr; |
| } |
| |
| const policy::BrowserPolicyConnectorAsh* connector = |
| g_browser_process->platform_part()->browser_policy_connector_ash(); |
| return connector->GetDeviceCloudPolicyManager(); |
| } |
| |
| const std::string ManagementUIHandlerChromeOS::GetDeviceManager() const { |
| std::string device_domain; |
| policy::BrowserPolicyConnectorAsh* connector = |
| g_browser_process->platform_part()->browser_policy_connector_ash(); |
| if (device_managed_) { |
| device_domain = connector->GetEnterpriseDomainManager(); |
| } |
| return device_domain; |
| } |
| |
| bool ManagementUIHandlerChromeOS::IsUpdateRequiredEol() const { |
| const policy::BrowserPolicyConnectorAsh* connector = |
| g_browser_process->platform_part()->browser_policy_connector_ash(); |
| policy::MinimumVersionPolicyHandler* handler = |
| connector->GetMinimumVersionPolicyHandler(); |
| return handler && handler->ShouldShowUpdateRequiredEolBanner(); |
| } |
| |
| void ManagementUIHandlerChromeOS::AddUpdateRequiredEolInfo( |
| base::Value::Dict* response) const { |
| if (!device_managed_ || !IsUpdateRequiredEol()) { |
| response->Set("eolMessage", std::string()); |
| return; |
| } |
| |
| response->Set("eolMessage", l10n_util::GetStringFUTF16( |
| IDS_MANAGEMENT_UPDATE_REQUIRED_EOL_MESSAGE, |
| base::UTF8ToUTF16(GetDeviceManager()), |
| ui::GetChromeOSDeviceName())); |
| std::string eol_admin_message; |
| ash::CrosSettings::Get()->GetString(ash::kDeviceMinimumVersionAueMessage, |
| &eol_admin_message); |
| response->Set("eolAdminMessage", eol_admin_message); |
| } |
| |
| void ManagementUIHandlerChromeOS::AddMonitoredNetworkPrivacyDisclosure( |
| base::Value::Dict* response) { |
| bool showMonitoredNetworkDisclosure = false; |
| |
| // Check for secure DNS templates with identifiers. |
| std::optional<std::string> doh_with_identifiers_servers_for_display; |
| |
| doh_with_identifiers_servers_for_display = |
| GetSecureDnsManager()->GetDohWithIdentifiersDisplayServers(); |
| |
| showMonitoredNetworkDisclosure = |
| doh_with_identifiers_servers_for_display.has_value(); |
| if (showMonitoredNetworkDisclosure) { |
| response->Set("showMonitoredNetworkPrivacyDisclosure", |
| showMonitoredNetworkDisclosure); |
| return; |
| } |
| |
| // Check if DeviceReportXDREvents is enabled. |
| auto* report_xdr_events_policy_value = |
| GetPolicyService() |
| ->GetPolicies(policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, |
| std::string())) |
| .GetValue(policy::key::kDeviceReportXDREvents, |
| base::Value::Type::BOOLEAN); |
| bool report_xdr_events_policy_enabled = |
| report_xdr_events_policy_value && |
| report_xdr_events_policy_value->GetBool(); |
| |
| if (report_xdr_events_policy_enabled) { |
| response->Set("showMonitoredNetworkPrivacyDisclosure", |
| report_xdr_events_policy_enabled); |
| return; |
| } |
| |
| // Check for proxy config. |
| ash::NetworkHandler* network_handler = ash::NetworkHandler::Get(); |
| base::Value::Dict proxy_settings; |
| // |ui_proxy_config_service| may be missing in tests. If the device is offline |
| // (no network connected) the |DefaultNetwork| is null. |
| if (ash::NetworkHandler::HasUiProxyConfigService() && |
| network_handler->network_state_handler()->DefaultNetwork()) { |
| // Check if proxy is enforced by user policy, a forced install extension or |
| // ONC policies. This will only read managed settings. |
| ash::NetworkHandler::GetUiProxyConfigService()->MergeEnforcedProxyConfig( |
| network_handler->network_state_handler()->DefaultNetwork()->guid(), |
| &proxy_settings); |
| } |
| if (!proxy_settings.empty()) { |
| // Proxies can be specified by web server url, via a PAC script or via the |
| // web proxy auto-discovery protocol. Chrome also supports the "direct" |
| // mode, in which no proxy is used. |
| std::string* proxy_specification_mode = |
| proxy_settings.FindStringByDottedPath(base::JoinString( |
| {::onc::network_config::kType, ::onc::kAugmentationActiveSetting}, |
| ".")); |
| showMonitoredNetworkDisclosure = |
| proxy_specification_mode && |
| *proxy_specification_mode != ::onc::proxy::kDirect; |
| } |
| response->Set("showMonitoredNetworkPrivacyDisclosure", |
| showMonitoredNetworkDisclosure); |
| } |
| |
| void ManagementUIHandlerChromeOS::AddDeskSyncNotice( |
| Profile* profile, |
| base::Value::Dict* response) { |
| const bool are_windows_synced = |
| IsActiveProfile(profile) && |
| ash::floating_workspace_util::IsFloatingWorkspaceV2Enabled(); |
| response->Set("showWindowsNoticeForDeskSync", are_windows_synced); |
| response->Set("showCookiesNoticeForDeskSync", IsFloatingSsoEnabled(profile)); |
| } |
| |
| void ManagementUIHandlerChromeOS::RegisterPrefChange( |
| PrefChangeRegistrar& pref_registrar) { |
| ManagementUIHandler::RegisterPrefChange(pref_registrar); |
| pref_registrar.Add( |
| plugin_vm::prefs::kPluginVmDataCollectionAllowed, |
| base::BindRepeating( |
| &ManagementUIHandlerChromeOS::NotifyPluginVmDataCollectionUpdated, |
| base::Unretained(this))); |
| } |
| |
| base::Value::Dict ManagementUIHandlerChromeOS::GetContextualManagedData( |
| Profile* profile) { |
| std::string enterprise_manager = GetDeviceManager(); |
| if (enterprise_manager.empty()) { |
| enterprise_manager = GetAccountManager(profile); |
| } |
| base::Value::Dict response; |
| AddUpdateRequiredEolInfo(&response); |
| AddMonitoredNetworkPrivacyDisclosure(&response); |
| AddDeskSyncNotice(profile, &response); |
| |
| if (enterprise_manager.empty()) { |
| response.Set( |
| "extensionReportingSubtitle", |
| l10n_util::GetStringUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED)); |
| response.Set( |
| "applicationReportingSubtitle", |
| l10n_util::GetStringUTF16(IDS_MANAGEMENT_APPLICATIONS_INSTALLED)); |
| response.Set( |
| "managedWebsitesSubtitle", |
| l10n_util::GetStringUTF16(IDS_MANAGEMENT_MANAGED_WEBSITES_EXPLANATION)); |
| const auto device_type = ui::GetChromeOSDeviceTypeResourceId(); |
| response.Set("pageSubtitle", |
| managed() ? l10n_util::GetStringFUTF16( |
| IDS_MANAGEMENT_SUBTITLE_MANAGED, |
| l10n_util::GetStringUTF16(device_type)) |
| : l10n_util::GetStringFUTF16( |
| IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE, |
| l10n_util::GetStringUTF16(device_type))); |
| } else { |
| response.Set( |
| "extensionReportingSubtitle", |
| l10n_util::GetStringFUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED_BY, |
| base::UTF8ToUTF16(enterprise_manager))); |
| response.Set( |
| "applicationReportingSubtitle", |
| l10n_util::GetStringFUTF16(IDS_MANAGEMENT_APPLICATIONS_INSTALLED_BY, |
| base::UTF8ToUTF16(enterprise_manager))); |
| response.Set("managedWebsitesSubtitle", |
| l10n_util::GetStringFUTF16( |
| IDS_MANAGEMENT_MANAGED_WEBSITES_BY_EXPLANATION, |
| base::UTF8ToUTF16(enterprise_manager))); |
| const auto device_type = ui::GetChromeOSDeviceTypeResourceId(); |
| response.Set("pageSubtitle", |
| managed() ? l10n_util::GetStringFUTF16( |
| IDS_MANAGEMENT_SUBTITLE_MANAGED_BY, |
| l10n_util::GetStringUTF16(device_type), |
| base::UTF8ToUTF16(enterprise_manager)) |
| : l10n_util::GetStringFUTF16( |
| IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE, |
| l10n_util::GetStringUTF16(device_type))); |
| } |
| response.Set("managed", managed()); |
| GetManagementStatus(profile, &response); |
| |
| AsyncUpdateLogo(); |
| if (!fetched_image_.empty()) { |
| response.Set(kCustomerLogo, base::Value(fetched_image_)); |
| } |
| |
| return response; |
| } |
| |
| bool ManagementUIHandlerChromeOS::managed() const { |
| return account_managed() || device_managed_; |
| } |
| |
| void ManagementUIHandlerChromeOS::UpdateManagedState() { |
| bool is_account_updated = |
| UpdateAccountManagedState(Profile::FromWebUI(web_ui())); |
| bool is_device_updated = UpdateDeviceManagedState(); |
| if (is_account_updated || is_device_updated) { |
| FireWebUIListener("managed_data_changed"); |
| } |
| } |
| |
| bool ManagementUIHandlerChromeOS::UpdateDeviceManagedState() { |
| bool new_managed = |
| policy::ManagementServiceFactory::GetForPlatform()->IsManaged(); |
| bool is_updated = (device_managed_ != new_managed); |
| device_managed_ = new_managed; |
| return is_updated; |
| } |
| |
| void ManagementUIHandlerChromeOS::AsyncUpdateLogo() { |
| policy::BrowserPolicyConnectorAsh* connector = |
| g_browser_process->platform_part()->browser_policy_connector_ash(); |
| const auto url = connector->GetCustomerLogoURL(); |
| if (!url.empty() && GURL(url) != logo_url_) { |
| icon_fetcher_ = std::make_unique<BitmapFetcher>( |
| GURL(url), this, GetManagementUICustomerLogoAnnotation()); |
| icon_fetcher_->Init(net::ReferrerPolicy::NEVER_CLEAR, |
| network::mojom::CredentialsMode::kOmit); |
| auto* profile = Profile::FromWebUI(web_ui()); |
| icon_fetcher_->Start(profile->GetDefaultStoragePartition() |
| ->GetURLLoaderFactoryForBrowserProcess() |
| .get()); |
| } |
| } |
| |
| void ManagementUIHandlerChromeOS::OnFetchComplete(const GURL& url, |
| const SkBitmap* bitmap) { |
| if (!bitmap) { |
| return; |
| } |
| fetched_image_ = webui::GetBitmapDataUrl(*bitmap); |
| logo_url_ = url; |
| // Fire listener to reload managed data. |
| FireWebUIListener("managed_data_changed"); |
| } |
| |
| void ManagementUIHandlerChromeOS::NotifyPluginVmDataCollectionUpdated() { |
| FireWebUIListener( |
| "plugin-vm-data-collection-updated", |
| base::Value(Profile::FromWebUI(web_ui())->GetPrefs()->GetBoolean( |
| plugin_vm::prefs::kPluginVmDataCollectionAllowed))); |
| } |
| |
| void ManagementUIHandlerChromeOS::GetManagementStatus( |
| Profile* profile, |
| base::Value::Dict* status) const { |
| status->Set(kDeviceManagedInfo, base::Value()); |
| status->Set(kAccountManagedInfo, base::Value()); |
| status->Set(kOverview, base::Value()); |
| if (!managed()) { |
| status->Set(kOverview, base::Value(l10n_util::GetStringUTF16( |
| IDS_MANAGEMENT_DEVICE_NOT_MANAGED))); |
| return; |
| } |
| std::string account_manager = GetAccountManager(profile); |
| auto* primary_user = user_manager::UserManager::Get()->GetPrimaryUser(); |
| auto* primary_profile = |
| primary_user ? ash::ProfileHelper::Get()->GetProfileByUser(primary_user) |
| : nullptr; |
| const bool primary_user_managed = |
| primary_profile ? IsProfileManaged(primary_profile) : false; |
| |
| if (primary_user_managed) { |
| account_manager = GetAccountManager(primary_profile); |
| } |
| |
| std::string device_manager = GetDeviceManager(); |
| |
| AddStatusOverviewManagedDeviceAndAccount( |
| status, device_managed_, account_managed() || primary_user_managed, |
| device_manager, account_manager); |
| } |
| |
| void ManagementUIHandlerChromeOS::HandleGetLocalTrustRootsInfo( |
| const base::Value::List& args) { |
| CHECK_EQ(1U, args.size()); |
| base::Value trust_roots_configured(false); |
| AllowJavascript(); |
| |
| policy::PolicyCertService* policy_service = |
| policy::PolicyCertServiceFactory::GetForProfile( |
| Profile::FromWebUI(web_ui())); |
| if (policy_service && policy_service->IsObservingCertChanges() && |
| policy_service->has_policy_certificates()) { |
| trust_roots_configured = base::Value(true); |
| } |
| |
| ResolveJavascriptCallback(args[0] /* callback_id */, trust_roots_configured); |
| } |
| |
| std::u16string ManagementUIHandlerChromeOS::GetFilesUploadToCloudInfo( |
| Profile* profile) { |
| policy::local_user_files::FileSaveDestination download_destination = |
| policy::local_user_files::GetDownloadsDestination(profile); |
| policy::local_user_files::FileSaveDestination screenshot_destination = |
| policy::local_user_files::GetScreenCaptureDestination(profile); |
| int uploads_id = -1; |
| int destination_id = -1; |
| if (IsCloudDestination(download_destination) && |
| IsCloudDestination(screenshot_destination)) { |
| uploads_id = IDS_MANAGEMENT_FILES_CLOUD_UPLOAD_DOWNLOADS_AND_SCREENSHOTS; |
| if (download_destination == |
| policy::local_user_files::FileSaveDestination::kGoogleDrive && |
| screenshot_destination == |
| policy::local_user_files::FileSaveDestination::kGoogleDrive) { |
| destination_id = IDS_MANAGEMENT_FILES_CLOUD_UPLOAD_GOOGLE_DRIVE; |
| } else if (download_destination == |
| policy::local_user_files::FileSaveDestination::kOneDrive && |
| screenshot_destination == |
| policy::local_user_files::FileSaveDestination::kOneDrive) { |
| destination_id = IDS_MANAGEMENT_FILES_CLOUD_UPLOAD_ONEDRIVE; |
| } else { |
| destination_id = |
| IDS_MANAGEMENT_FILES_CLOUD_UPLOAD_GOOGLE_DRIVE_AND_ONEDRIVE; |
| } |
| } else if (IsCloudDestination(download_destination)) { |
| uploads_id = IDS_MANAGEMENT_FILES_CLOUD_UPLOAD_DOWNLOADS; |
| if (download_destination == |
| policy::local_user_files::FileSaveDestination::kGoogleDrive) { |
| destination_id = IDS_MANAGEMENT_FILES_CLOUD_UPLOAD_GOOGLE_DRIVE; |
| } else { |
| destination_id = IDS_MANAGEMENT_FILES_CLOUD_UPLOAD_ONEDRIVE; |
| } |
| } else if (IsCloudDestination(screenshot_destination)) { |
| uploads_id = IDS_MANAGEMENT_FILES_CLOUD_UPLOAD_SCREENSHOTS; |
| if (screenshot_destination == |
| policy::local_user_files::FileSaveDestination::kGoogleDrive) { |
| destination_id = IDS_MANAGEMENT_FILES_CLOUD_UPLOAD_GOOGLE_DRIVE; |
| } else { |
| destination_id = IDS_MANAGEMENT_FILES_CLOUD_UPLOAD_ONEDRIVE; |
| } |
| } |
| |
| if (uploads_id == -1) { |
| return std::u16string(); |
| } |
| |
| return l10n_util::GetStringFUTF16( |
| IDS_MANAGEMENT_FILES_CLOUD_UPLOAD_CONFIGURATION, |
| l10n_util::GetStringUTF16(uploads_id), |
| l10n_util::GetStringUTF16(destination_id)); |
| } |
| |
| const ash::SecureDnsManager* ManagementUIHandlerChromeOS::GetSecureDnsManager() |
| const { |
| return g_browser_process->platform_part()->secure_dns_manager(); |
| } |
| |
| void ManagementUIHandlerChromeOS::HandleGetFilesUploadToCloudInfo( |
| const base::Value::List& args) { |
| CHECK_EQ(1U, args.size()); |
| |
| AllowJavascript(); |
| |
| ResolveJavascriptCallback( |
| args[0] /* callback_id */, |
| base::Value(GetFilesUploadToCloudInfo(Profile::FromWebUI(web_ui())))); |
| } |
| |
| void ManagementUIHandlerChromeOS::HandleGetDeviceReportingInfo( |
| const base::Value::List& args) { |
| AllowJavascript(); |
| base::Value::List report_sources = GetDeviceReportingInfo( |
| GetDeviceCloudPolicyManager(), Profile::FromWebUI(web_ui())); |
| ResolveJavascriptCallback(args[0] /* callback_id */, report_sources); |
| } |
| |
| void ManagementUIHandlerChromeOS::HandleGetPluginVmDataCollectionStatus( |
| const base::Value::List& args) { |
| CHECK_EQ(1U, args.size()); |
| base::Value plugin_vm_data_collection_enabled( |
| Profile::FromWebUI(web_ui())->GetPrefs()->GetBoolean( |
| plugin_vm::prefs::kPluginVmDataCollectionAllowed)); |
| AllowJavascript(); |
| ResolveJavascriptCallback(args[0] /* callback_id */, |
| plugin_vm_data_collection_enabled); |
| } |
| |
| std::unique_ptr<ManagementUIHandler> ManagementUIHandler::Create( |
| Profile* profile) { |
| return std::make_unique<ManagementUIHandlerChromeOS>(profile); |
| } |