| // Copyright (c) 2012 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. |
| |
| #ifndef CHROME_BROWSER_CHROMEOS_POLICY_STATUS_COLLECTOR_DEVICE_STATUS_COLLECTOR_H_ |
| #define CHROME_BROWSER_CHROMEOS_POLICY_STATUS_COLLECTOR_DEVICE_STATUS_COLLECTOR_H_ |
| |
| #include <stdint.h> |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/callback_forward.h" |
| #include "base/callback_list.h" |
| #include "base/compiler_specific.h" |
| #include "base/containers/circular_deque.h" |
| #include "base/time/default_clock.h" |
| #include "base/macros.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/sequenced_task_runner.h" |
| #include "base/task/cancelable_task_tracker.h" |
| #include "base/time/time.h" |
| #include "base/timer/timer.h" |
| #include "chrome/browser/chromeos/policy/status_collector/app_info_generator.h" |
| #include "chrome/browser/chromeos/policy/status_collector/status_collector.h" |
| #include "chrome/browser/chromeos/settings/cros_settings.h" |
| #include "chromeos/dbus/cryptohome/cryptohome_client.h" |
| #include "chromeos/dbus/power/power_manager_client.h" |
| #include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h" |
| #include "components/policy/proto/device_management_backend.pb.h" |
| #include "components/prefs/pref_member.h" |
| #include "ui/base/idle/idle.h" |
| |
| namespace chromeos { |
| class CrosSettings; |
| namespace system { |
| class StatisticsProvider; |
| } |
| } // namespace chromeos |
| |
| namespace cryptohome { |
| struct TpmStatusInfo; |
| } |
| |
| namespace power_manager { |
| class PowerSupplyProperties; |
| } |
| |
| namespace user_manager { |
| class User; |
| } |
| |
| class PrefChangeRegistrar; |
| class PrefRegistrySimple; |
| class PrefService; |
| class Profile; |
| |
| namespace policy { |
| |
| class EnterpriseActivityStorage; |
| struct DeviceLocalAccount; |
| class DeviceStatusCollectorState; |
| |
| // Enum used to define which data the CrosHealthdDataFetcher should collect. |
| enum class CrosHealthdCollectionMode { kFull, kBattery }; |
| |
| // Holds TPM status info. Cf. TpmStatusInfo in device_management_backend.proto. |
| struct TpmStatusInfo { |
| TpmStatusInfo(); |
| TpmStatusInfo(const TpmStatusInfo&); |
| TpmStatusInfo(bool enabled, |
| bool owned, |
| bool initialized, |
| bool attestation_prepared, |
| bool attestation_enrolled, |
| int32_t dictionary_attack_counter, |
| int32_t dictionary_attack_threshold, |
| bool dictionary_attack_lockout_in_effect, |
| int32_t dictionary_attack_lockout_seconds_remaining, |
| bool boot_lockbox_finalized); |
| ~TpmStatusInfo(); |
| |
| bool enabled = false; |
| bool owned = false; |
| bool initialized = false; |
| bool attestation_prepared = false; |
| bool attestation_enrolled = false; |
| int32_t dictionary_attack_counter = 0; |
| int32_t dictionary_attack_threshold = 0; |
| bool dictionary_attack_lockout_in_effect = false; |
| int32_t dictionary_attack_lockout_seconds_remaining = 0; |
| bool boot_lockbox_finalized = false; |
| }; |
| |
| // Sampled hardware measurement data for single time point. |
| class SampledData { |
| public: |
| SampledData(); |
| ~SampledData(); |
| |
| // Sampling timestamp. |
| base::Time timestamp; |
| // Battery samples for each battery. |
| std::map<std::string, enterprise_management::BatterySample> battery_samples; |
| // Thermal samples for each thermal point. |
| std::map<std::string, enterprise_management::ThermalSample> thermal_samples; |
| // CPU thermal samples. |
| std::map<std::string, enterprise_management::CPUTempInfo> cpu_samples; |
| |
| DISALLOW_COPY_AND_ASSIGN(SampledData); |
| }; |
| |
| // Collects and summarizes the status of an enterprise-managed ChromeOS device. |
| class DeviceStatusCollector : public StatusCollector, |
| public chromeos::PowerManagerClient::Observer { |
| public: |
| using VolumeInfoFetcher = |
| base::Callback<std::vector<enterprise_management::VolumeInfo>( |
| const std::vector<std::string>& mount_points)>; |
| |
| // Reads the first CPU line from /proc/stat. Returns an empty string if |
| // the cpu data could not be read. Broken out into a callback to enable |
| // mocking for tests. |
| // |
| // The format of this line from /proc/stat is: |
| // cpu user_time nice_time system_time idle_time |
| using CPUStatisticsFetcher = base::Callback<std::string(void)>; |
| |
| // Reads CPU temperatures from /sys/class/hwmon/hwmon*/temp*_input and |
| // appropriate labels from /sys/class/hwmon/hwmon*/temp*_label. |
| using CPUTempFetcher = |
| base::Callback<std::vector<enterprise_management::CPUTempInfo>()>; |
| |
| // Format of the function that asynchronously receives TpmStatusInfo. |
| using TpmStatusReceiver = base::OnceCallback<void(const TpmStatusInfo&)>; |
| // Gets the TpmStatusInfo and passes it to TpmStatusReceiver. |
| using TpmStatusFetcher = base::RepeatingCallback<void(TpmStatusReceiver)>; |
| |
| // Format of the function that asynchronously receives data from cros_healthd. |
| using CrosHealthdDataReceiver = base::OnceCallback<void( |
| chromeos::cros_healthd::mojom::TelemetryInfoPtr, |
| const base::circular_deque<std::unique_ptr<SampledData>>&)>; |
| // Gets the data from cros_healthd and passes it to CrosHealthdDataReceiver. |
| using CrosHealthdDataFetcher = |
| base::RepeatingCallback<void(CrosHealthdCollectionMode, |
| CrosHealthdDataReceiver)>; |
| |
| // Asynchronously receives the graphics status. |
| using GraphicsStatusReceiver = |
| base::OnceCallback<void(const enterprise_management::GraphicsStatus&)>; |
| |
| // Gets the display and graphics adapter information reported to the browser |
| // by the GPU process. |
| using GraphicsStatusFetcher = |
| base::RepeatingCallback<void(GraphicsStatusReceiver)>; |
| |
| // Format of the function that asynchronously receives CrashReportInfo. |
| using CrashReportInfoReceiver = base::OnceCallback<void( |
| const std::vector<enterprise_management::CrashReportInfo>&)>; |
| |
| // Gets the crash report information stored on the local device. |
| using CrashReportInfoFetcher = |
| base::RepeatingCallback<void(CrashReportInfoReceiver)>; |
| |
| // Reads EMMC usage lifetime from /var/log/storage_info.txt |
| using EMMCLifetimeFetcher = |
| base::RepeatingCallback<enterprise_management::DiskLifetimeEstimation( |
| void)>; |
| // Reads the stateful partition info from /home/.shadow |
| using StatefulPartitionInfoFetcher = |
| base::Callback<enterprise_management::StatefulPartitionInfo()>; |
| |
| // Constructor. Callers can inject their own *Fetcher callbacks, e.g. for unit |
| // testing. A null callback can be passed for any *Fetcher parameter, to use |
| // the default implementation. These callbacks are always executed on Blocking |
| // Pool. Caller is responsible for passing already initialized |pref_service|. |
| DeviceStatusCollector( |
| PrefService* pref_service, |
| chromeos::system::StatisticsProvider* provider, |
| const VolumeInfoFetcher& volume_info_fetcher, |
| const CPUStatisticsFetcher& cpu_statistics_fetcher, |
| const CPUTempFetcher& cpu_temp_fetcher, |
| const AndroidStatusFetcher& android_status_fetcher, |
| const TpmStatusFetcher& tpm_status_fetcher, |
| const EMMCLifetimeFetcher& emmc_lifetime_fetcher, |
| const StatefulPartitionInfoFetcher& stateful_partition_info_fetcher, |
| const CrosHealthdDataFetcher& cros_healthd_data_fetcher, |
| const GraphicsStatusFetcher& graphics_status_fetcher, |
| const CrashReportInfoFetcher& crash_report_info_fetcher, |
| base::Clock* clock = base::DefaultClock::GetInstance()); |
| |
| // Constructor with default callbacks. These callbacks are always executed on |
| // Blocking Pool. Caller is responsible for passing already initialized |
| // |pref_service|. |
| DeviceStatusCollector(PrefService* pref_service, |
| chromeos::system::StatisticsProvider* provider); |
| |
| ~DeviceStatusCollector() override; |
| |
| // StatusCollector: |
| void GetStatusAsync(const StatusCollectorCallback& response) override; |
| void OnSubmittedSuccessfully() override; |
| bool ShouldReportActivityTimes() const override; |
| bool ShouldReportNetworkInterfaces() const override; |
| bool ShouldReportUsers() const override; |
| bool ShouldReportHardwareStatus() const override; |
| bool ShouldReportCrashReportInfo() const override; |
| bool ShouldReportAppInfoAndActivity() const override; |
| |
| static void RegisterPrefs(PrefRegistrySimple* registry); |
| |
| AffiliatedSessionService* GetAffiliatedSessionServiceForTesting() { |
| return &affiliated_session_service_; |
| } |
| |
| // How often to poll to see if the user is idle. |
| static constexpr base::TimeDelta kIdlePollInterval = |
| base::TimeDelta::FromSeconds(30); |
| |
| // The total number of hardware resource usage samples cached internally. |
| static const unsigned int kMaxResourceUsageSamples = 10; |
| |
| protected: |
| using PowerStatusCallback = base::OnceCallback<void( |
| const power_manager::PowerSupplyProperties& prop)>; |
| |
| // Check whether the user has been idle for a certain period of time. |
| virtual void CheckIdleState(); |
| |
| // Handles the results of the idle state check. |
| void ProcessIdleState(ui::IdleState state); |
| |
| // Gets the version of the passed app. Virtual to allow mocking. |
| virtual std::string GetAppVersion(const std::string& app_id); |
| |
| // Samples the current hardware resource usage to be sent up with the |
| // next device status update. |
| void SampleResourceUsage(); |
| |
| // power_manager::PowerManagerClient::Observer: |
| void PowerChanged(const power_manager::PowerSupplyProperties& prop) override; |
| |
| private: |
| // Callbacks used during sampling data collection, that allows to pass |
| // additional data using partial function application. |
| using SamplingProbeResultCallback = |
| base::OnceCallback<void(chromeos::cros_healthd::mojom::TelemetryInfoPtr)>; |
| using SamplingCallback = base::OnceCallback<void()>; |
| |
| // Clears the cached hardware resource usage. |
| void ClearCachedResourceUsage(); |
| |
| // Callbacks from chromeos::VersionLoader. |
| void OnOSVersion(const std::string& version); |
| void OnOSFirmware(std::pair<const std::string&, const std::string&> version); |
| void OnTpmVersion( |
| const chromeos::CryptohomeClient::TpmVersionInfo& tpm_version_info); |
| |
| void GetDeviceStatus(scoped_refptr<DeviceStatusCollectorState> state); |
| void GetSessionStatus(scoped_refptr<DeviceStatusCollectorState> state); |
| |
| bool GetSessionStatusForUser( |
| scoped_refptr<DeviceStatusCollectorState> state, |
| enterprise_management::SessionStatusReportRequest* status, |
| const user_manager::User* user); |
| // Helpers for the various portions of DEVICE STATUS. Return true if they |
| // actually report any status. Functions that queue async queries take |
| // a |DeviceStatusCollectorState| instance. |
| bool GetActivityTimes( |
| enterprise_management::DeviceStatusReportRequest* status); |
| bool GetVersionInfo(enterprise_management::DeviceStatusReportRequest* status); |
| bool GetWriteProtectSwitch( |
| enterprise_management::DeviceStatusReportRequest* status); |
| bool GetNetworkInterfaces( |
| enterprise_management::DeviceStatusReportRequest* status); |
| bool GetUsers(enterprise_management::DeviceStatusReportRequest* status); |
| bool GetHardwareStatus(scoped_refptr<DeviceStatusCollectorState> |
| state); // Queues async queries! |
| bool GetOsUpdateStatus( |
| enterprise_management::DeviceStatusReportRequest* status); |
| bool GetRunningKioskApp( |
| enterprise_management::DeviceStatusReportRequest* status); |
| bool GetGraphicsStatus(scoped_refptr<DeviceStatusCollectorState> |
| state); // Queues async queries! |
| bool GetCrashReportInfo(scoped_refptr<DeviceStatusCollectorState> |
| state); // Queues async queries! |
| |
| // Helpers for the various portions of SESSION STATUS. Return true if they |
| // actually report any status. Functions that queue async queries take |
| // a |DeviceStatusCollectorState| instance. |
| bool GetKioskSessionStatus( |
| enterprise_management::SessionStatusReportRequest* status); |
| bool GetAndroidStatus( |
| enterprise_management::SessionStatusReportRequest* status, |
| const scoped_refptr<DeviceStatusCollectorState>& |
| state); // Queues async queries! |
| bool GetCrostiniUsage( |
| enterprise_management::SessionStatusReportRequest* status, |
| Profile* profile); |
| |
| // Update the cached values of the reporting settings. |
| void UpdateReportingSettings(); |
| |
| // Callback invoked to update our cpu usage information. |
| void ReceiveCPUStatistics(const std::string& statistics); |
| |
| // Callback for CrosHealthd that samples probe live data. |callback| will |
| // be called once all sampling is finished. |
| void SampleProbeData(std::unique_ptr<SampledData> sample, |
| SamplingProbeResultCallback callback, |
| chromeos::cros_healthd::mojom::TelemetryInfoPtr result); |
| |
| // Callback triggered from PowerManagedClient that samples battery discharge |
| // rate. |callback| will be called once all sampling is finished. |
| void SampleDischargeRate(std::unique_ptr<SampledData> sample, |
| SamplingCallback callback, |
| const power_manager::PowerSupplyProperties& prop); |
| |
| // Callback invoked to update our cpu temperature information. |
| void ReceiveCPUTemperature(std::unique_ptr<SampledData> sample, |
| SamplingCallback callback, |
| std::vector<enterprise_management::CPUTempInfo>); |
| |
| // Final sampling step that records data sample, invokes |callback|. |
| void AddDataSample(std::unique_ptr<SampledData> sample, |
| SamplingCallback callback); |
| |
| // CrosHealthdDataReceiver interface implementation, fetches data from |
| // cros_healthd and passes it to |callback|. The data collected depends on the |
| // collection |mode|. |
| void FetchCrosHealthdData(CrosHealthdCollectionMode mode, |
| CrosHealthdDataReceiver callback); |
| |
| // Callback for CrosHealthd that performs final sampling and |
| // actually invokes |callback|. |
| void OnProbeDataFetched( |
| CrosHealthdDataReceiver callback, |
| chromeos::cros_healthd::mojom::TelemetryInfoPtr reply); |
| |
| // Returns true if data (e.g. CPU info, power status, etc.) should be fetched |
| // from cros_healthd. |
| bool ShouldFetchCrosHealthdData() const; |
| |
| // Callback invoked when reporting users pref is changed. |
| void ReportingUsersChanged(); |
| |
| // Returns user's email if it should be included in the activity reports or |
| // empty string otherwise. Primary user is used as unique identifier of a |
| // single session, even for multi-user sessions. |
| std::string GetUserForActivityReporting() const; |
| |
| // Returns whether users' email addresses should be included in activity |
| // reports. |
| bool IncludeEmailsInActivityReports() const; |
| |
| // Pref service that is mainly used to store activity periods for reporting. |
| PrefService* const pref_service_; |
| |
| // The last time an idle state check was performed. |
| base::Time last_idle_check_; |
| |
| // End timestamp of the latest activity that went into the last report |
| // generated by GetStatusAsync(). Used to trim the stored data in |
| // OnSubmittedSuccessfully(). Trimming is delayed so unsuccessful uploads |
| // don't result in dropped data. |
| int64_t last_reported_end_timestamp_ = 0; |
| |
| // Time when GetStatusAsync() is called. Used to close open app |
| // activity just prior to reporting so the report can include the most |
| // up-to-date activity. |
| base::Time last_requested_; |
| |
| base::RepeatingTimer idle_poll_timer_; |
| base::RepeatingTimer resource_usage_sampling_timer_; |
| |
| std::string os_version_; |
| std::string firmware_version_; |
| std::string firmware_fetch_error_; |
| chromeos::CryptohomeClient::TpmVersionInfo tpm_version_info_; |
| |
| struct ResourceUsage { |
| // Sample of percentage-of-CPU-used. |
| int cpu_usage_percent; |
| |
| // Amount of free RAM (measures raw memory used by processes, not internal |
| // memory waiting to be reclaimed by GC). |
| int64_t bytes_of_ram_free; |
| |
| // Sampling timestamp. |
| base::Time timestamp; |
| }; |
| |
| // Samples of resource usage (contains multiple samples taken |
| // periodically every kHardwareStatusSampleIntervalSeconds). |
| base::circular_deque<ResourceUsage> resource_usage_; |
| |
| // Samples of probe data (contains multiple samples taken |
| // periodically every kHardwareStatusSampleIntervalSeconds) |
| base::circular_deque<std::unique_ptr<SampledData>> sampled_data_; |
| |
| // Callback invoked to fetch information about the mounted disk volumes. |
| VolumeInfoFetcher volume_info_fetcher_; |
| |
| // Callback invoked to fetch information about cpu usage. |
| CPUStatisticsFetcher cpu_statistics_fetcher_; |
| |
| // Callback invoked to fetch information about cpu temperature. |
| CPUTempFetcher cpu_temp_fetcher_; |
| |
| AndroidStatusFetcher android_status_fetcher_; |
| |
| TpmStatusFetcher tpm_status_fetcher_; |
| |
| EMMCLifetimeFetcher emmc_lifetime_fetcher_; |
| |
| StatefulPartitionInfoFetcher stateful_partition_info_fetcher_; |
| |
| CrosHealthdDataFetcher cros_healthd_data_fetcher_; |
| |
| GraphicsStatusFetcher graphics_status_fetcher_; |
| |
| CrashReportInfoFetcher crash_report_info_fetcher_; |
| |
| PowerStatusCallback power_status_callback_; |
| |
| // Power manager client. Used to listen to power changed events. |
| chromeos::PowerManagerClient* const power_manager_; |
| |
| // The most recent CPU readings. |
| uint64_t last_cpu_active_ = 0; |
| uint64_t last_cpu_idle_ = 0; |
| |
| // Cached values of the reporting settings. These are enterprise only. There |
| // are common ones in StatusCollector interface. |
| bool report_network_interfaces_ = false; |
| bool report_users_ = false; |
| bool report_hardware_status_ = false; |
| bool report_kiosk_session_status_ = false; |
| bool report_os_update_status_ = false; |
| bool report_running_kiosk_app_ = false; |
| bool report_power_status_ = false; |
| bool report_storage_status_ = false; |
| bool report_board_status_ = false; |
| bool report_cpu_info_ = false; |
| bool report_graphics_status_ = false; |
| bool report_timezone_info_ = false; |
| bool report_memory_info_ = false; |
| bool report_backlight_info_ = false; |
| bool report_crash_report_info_ = false; |
| bool report_bluetooth_info_ = false; |
| bool report_fan_info_ = false; |
| bool report_vpd_info_ = false; |
| bool report_app_info_ = false; |
| bool stat_reporting_pref_ = false; |
| |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| activity_times_subscription_; |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| network_interfaces_subscription_; |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| users_subscription_; |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| hardware_status_subscription_; |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| session_status_subscription_; |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| os_update_status_subscription_; |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| running_kiosk_app_subscription_; |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| power_status_subscription_; |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| storage_status_subscription_; |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| board_status_subscription_; |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| cpu_info_subscription_; |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| graphics_status_subscription_; |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| timezone_info_subscription_; |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| memory_info_subscription_; |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| backlight_info_subscription_; |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| crash_report_info_subscription_; |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| bluetooth_info_subscription_; |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| fan_info_subscription_; |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| vpd_info_subscription_; |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| app_info_subscription_; |
| std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> |
| stats_reporting_pref_subscription_; |
| |
| AffiliatedSessionService affiliated_session_service_; |
| |
| AppInfoGenerator app_info_generator_; |
| |
| std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_; |
| |
| // Stores and filters activity periods used for reporting. |
| std::unique_ptr<EnterpriseActivityStorage> activity_storage_; |
| |
| base::WeakPtrFactory<DeviceStatusCollector> weak_factory_{this}; |
| |
| DISALLOW_COPY_AND_ASSIGN(DeviceStatusCollector); |
| }; |
| |
| } // namespace policy |
| |
| #endif // CHROME_BROWSER_CHROMEOS_POLICY_STATUS_COLLECTOR_DEVICE_STATUS_COLLECTOR_H_ |