blob: ac45e11aba90b14bc6cdcec225b219855a855373 [file] [log] [blame]
// 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_DEVICE_STATUS_COLLECTOR_H_
#define CHROME_BROWSER_CHROMEOS_POLICY_DEVICE_STATUS_COLLECTOR_H_
#include <stdint.h>
#include <deque>
#include <string>
#include <vector>
#include "base/callback_forward.h"
#include "base/callback_list.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/cancelable_task_tracker.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chromeos/system/version_loader.h"
#include "content/public/browser/geolocation_provider.h"
#include "content/public/common/geoposition.h"
#include "policy/proto/device_management_backend.pb.h"
#include "ui/base/idle/idle.h"
namespace chromeos {
class CrosSettings;
namespace system {
class StatisticsProvider;
}
}
namespace content {
class NotificationDetails;
class NotificationSource;
}
class PrefRegistrySimple;
class PrefService;
namespace policy {
struct DeviceLocalAccount;
// Collects and summarizes the status of an enterprised-managed ChromeOS device.
class DeviceStatusCollector {
public:
// TODO(bartfab): Remove this once crbug.com/125931 is addressed and a proper
// way to mock geolocation exists.
typedef base::Callback<void(
const content::GeolocationProvider::LocationUpdateCallback& callback)>
LocationUpdateRequester;
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>()>;
// Constructor. Callers can inject their own VolumeInfoFetcher,
// CPUStatisticsFetcher and CPUTempFetcher. These callbacks are executed on
// Blocking Pool. A null callback can be passed for either parameter, to use
// the default implementation.
DeviceStatusCollector(
PrefService* local_state,
chromeos::system::StatisticsProvider* provider,
const LocationUpdateRequester& location_update_requester,
const VolumeInfoFetcher& volume_info_fetcher,
const CPUStatisticsFetcher& cpu_statistics_fetcher,
const CPUTempFetcher& cpu_temp_fetcher);
virtual ~DeviceStatusCollector();
// Fills in the passed proto with device status information. Will return
// false if no status information is filled in (because status reporting
// is disabled).
virtual bool GetDeviceStatus(
enterprise_management::DeviceStatusReportRequest* status);
// Fills in the passed proto with session status information. Will return
// false if no status information is filled in (because status reporting
// is disabled, or because the active session is not a kiosk session).
virtual bool GetDeviceSessionStatus(
enterprise_management::SessionStatusReportRequest* status);
// Called after the status information has successfully been submitted to
// the server.
void OnSubmittedSuccessfully();
static void RegisterPrefs(PrefRegistrySimple* registry);
// Returns the DeviceLocalAccount associated with the currently active
// kiosk session, if the session was auto-launched with zero delay
// (this enables functionality such as network reporting).
// Virtual to allow mocking.
virtual scoped_ptr<DeviceLocalAccount> GetAutoLaunchedKioskSessionInfo();
// How often, in seconds, to poll to see if the user is idle.
static const unsigned int kIdlePollIntervalSeconds = 30;
// The total number of hardware resource usage samples cached internally.
static const unsigned int kMaxResourceUsageSamples = 10;
protected:
// Check whether the user has been idle for a certain period of time.
virtual void CheckIdleState();
// Used instead of base::Time::Now(), to make testing possible.
virtual base::Time GetCurrentTime();
// Callback which receives the results of the idle state check.
void IdleStateCallback(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 status to be sent up with the next device
// status update.
void SampleHardwareStatus();
// The number of days in the past to store device activity.
// This is kept in case device status uploads fail for a number of days.
unsigned int max_stored_past_activity_days_;
// The number of days in the future to store device activity.
// When changing the system time and/or timezones, it's possible to record
// activity time that is slightly in the future.
unsigned int max_stored_future_activity_days_;
private:
// Prevents the local store of activity periods from growing too large by
// removing entries that are outside the reporting window.
void PruneStoredActivityPeriods(base::Time base_time);
// Trims the store activity periods to only retain data within the
// [|min_day_key|, |max_day_key|). The record for |min_day_key| will be
// adjusted by subtracting |min_day_trim_duration|.
void TrimStoredActivityPeriods(int64_t min_day_key,
int min_day_trim_duration,
int64_t max_day_key);
void AddActivePeriod(base::Time start, base::Time end);
// Clears the cached hardware status.
void ClearCachedHardwareStatus();
// Callbacks from chromeos::VersionLoader.
void OnOSVersion(const std::string& version);
void OnOSFirmware(const std::string& version);
// Helpers for the various portions of the status.
void GetActivityTimes(
enterprise_management::DeviceStatusReportRequest* request);
void GetVersionInfo(
enterprise_management::DeviceStatusReportRequest* request);
void GetBootMode(
enterprise_management::DeviceStatusReportRequest* request);
void GetLocation(
enterprise_management::DeviceStatusReportRequest* request);
void GetNetworkInterfaces(
enterprise_management::DeviceStatusReportRequest* request);
void GetUsers(
enterprise_management::DeviceStatusReportRequest* request);
void GetHardwareStatus(
enterprise_management::DeviceStatusReportRequest* request);
// Update the cached values of the reporting settings.
void UpdateReportingSettings();
void ScheduleGeolocationUpdateRequest();
// content::GeolocationUpdateCallback implementation.
void ReceiveGeolocationUpdate(const content::Geoposition&);
// Callback invoked to update our cached disk information.
void ReceiveVolumeInfo(
const std::vector<enterprise_management::VolumeInfo>& info);
// Callback invoked to update our cpu usage information.
void ReceiveCPUStatistics(const std::string& statistics);
// Callback invoked to update our CPU temp information.
void StoreCPUTempInfo(
const std::vector<enterprise_management::CPUTempInfo>& info);
// Helper routine to convert from Shill-provided signal strength (percent)
// to dBm units expected by server.
int ConvertWifiSignalStrength(int signal_strength);
PrefService* local_state_;
// The last time an idle state check was performed.
base::Time last_idle_check_;
// The maximum key that went into the last report generated by
// GetDeviceStatus(), and the duration for it. This is used to trim the
// stored data in OnSubmittedSuccessfully(). Trimming is delayed so
// unsuccessful uploads don't result in dropped data.
int64_t last_reported_day_;
int duration_for_last_reported_day_;
// Whether a geolocation update is currently in progress.
bool geolocation_update_in_progress_;
base::RepeatingTimer idle_poll_timer_;
base::RepeatingTimer hardware_status_sampling_timer_;
base::OneShotTimer geolocation_update_timer_;
std::string os_version_;
std::string firmware_version_;
content::Geoposition position_;
// Cached disk volume information.
std::vector<enterprise_management::VolumeInfo> volume_info_;
// Cached CPU temp information.
std::vector<enterprise_management::CPUTempInfo> cpu_temp_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;
};
// Samples of resource usage (contains multiple samples taken
// periodically every kHardwareStatusSampleIntervalSeconds).
std::deque<ResourceUsage> resource_usage_;
// 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_;
chromeos::system::StatisticsProvider* statistics_provider_;
chromeos::CrosSettings* cros_settings_;
// The most recent CPU readings.
uint64_t last_cpu_active_;
uint64_t last_cpu_idle_;
// TODO(bartfab): Remove this once crbug.com/125931 is addressed and a proper
// way to mock geolocation exists.
LocationUpdateRequester location_update_requester_;
scoped_ptr<content::GeolocationProvider::Subscription>
geolocation_subscription_;
// Cached values of the reporting settings from the device policy.
bool report_version_info_;
bool report_activity_times_;
bool report_boot_mode_;
bool report_location_;
bool report_network_interfaces_;
bool report_users_;
bool report_hardware_status_;
bool report_session_status_;
scoped_ptr<chromeos::CrosSettings::ObserverSubscription>
version_info_subscription_;
scoped_ptr<chromeos::CrosSettings::ObserverSubscription>
activity_times_subscription_;
scoped_ptr<chromeos::CrosSettings::ObserverSubscription>
boot_mode_subscription_;
scoped_ptr<chromeos::CrosSettings::ObserverSubscription>
location_subscription_;
scoped_ptr<chromeos::CrosSettings::ObserverSubscription>
network_interfaces_subscription_;
scoped_ptr<chromeos::CrosSettings::ObserverSubscription>
users_subscription_;
scoped_ptr<chromeos::CrosSettings::ObserverSubscription>
hardware_status_subscription_;
scoped_ptr<chromeos::CrosSettings::ObserverSubscription>
session_status_subscription_;
base::WeakPtrFactory<DeviceStatusCollector> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(DeviceStatusCollector);
};
} // namespace policy
#endif // CHROME_BROWSER_CHROMEOS_POLICY_DEVICE_STATUS_COLLECTOR_H_