blob: 7d6174eccefa1d301bcb9b9fcf3fcbd25d110550 [file] [log] [blame]
// Copyright 2018 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_LOGIN_DEMO_MODE_DEMO_MODE_RESOURCES_REMOVER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_MODE_RESOURCES_REMOVER_H_
#include <memory>
#include <string>
#include <vector>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/scoped_observer.h"
#include "chromeos/dbus/cryptohome/cryptohome_client.h"
#include "components/user_manager/user_manager.h"
#include "ui/base/user_activity/user_activity_observer.h"
class PrefRegistrySimple;
class PrefService;
namespace base {
class TickClock;
class TimeDelta;
class TimeTicks;
} // namespace base
namespace ui {
class Event;
class UserActivityDetector;
} // namespace ui
namespace chromeos {
// Handles removal of pre-installed demo mode resources.
// Observes system state to detect when pre-installed demo mode resources are
// not needed anymore, and schedules their deletion from the disk.
//
// Only single instance is expected to be created per process.
//
// Demo mode resources are deleted if the device is not in demo mode, and any
// of the following conditions are satisfied:
// * device is running low on disk space
// * device is enrolled in a non-demo-mode domain
// * enough user activity has been detected on the device
class DemoModeResourcesRemover
: public CryptohomeClient::Observer,
public user_manager::UserManager::UserSessionStateObserver,
public ui::UserActivityObserver {
public:
// The reason a removal was requested.
// DO NOT REORDER - used to report metrics.
enum class RemovalReason {
kLowDiskSpace = 0,
kEnterpriseEnrolled = 1,
kRegularUsage = 2,
kMaxValue = kRegularUsage
};
// The result of a removal attempt.
// DO NOT REORDER - used to report metrics.
enum class RemovalResult {
// Pre-installed resources were removed.
kSuccess = 0,
// Pre-installed resources were not found.
kNotFound = 1,
// Pre-installed resources cannot be removed in this session.
// Not expected to be reported in UMA.
kNotAllowed = 2,
// The resources have been previously removed.
// Not expected to be reported in UMA.
kAlreadyRemoved = 3,
// Attempt to remove pre-installed resources failed.
kFailed = 4,
kMaxValue = kFailed
};
// Callback for a request to remove demo mode resources from the stateful
// partition.
using RemovalCallback = base::OnceCallback<void(RemovalResult result)>;
// Configures how DemoModeResourcesRemover tracks the amount of active
// device usage in order to determine when demo mode resources are not needed
// anymore.
struct UsageAccumulationConfig {
// Creates the config with default params used in production.
UsageAccumulationConfig();
UsageAccumulationConfig(const base::TimeDelta& resources_removal_threshold,
const base::TimeDelta& update_interval,
const base::TimeDelta& idle_threshold);
// Amount of accumulated device usage time that warrants demo mode resources
// removal. When this threshold is reached, demo mode resources removal will
// be attempted.
base::TimeDelta resources_removal_threshold;
// The interval in which accumulated usage time is updated in prefs (during
// active device usage).
base::TimeDelta update_interval;
// The amount of time without user activity after which the device is
// considered idle.
base::TimeDelta idle_threshold;
};
static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
// Gets the demo mode resources remover instance for this process - at most
// one instance can be created per process.
static DemoModeResourcesRemover* Get();
// Creates a demo mode resources remover instance if it's required.
// It will return nullptr if a DemoModeResourcesRemover is not needed at the
// time - for example if the resources have previously been removed, or if the
// device is in demo mode.
//
// It should be called at most once per process - creating more than one
// DemoModeResourcesRemover instances will hit a CHECK.
static std::unique_ptr<DemoModeResourcesRemover> CreateIfNeeded(
PrefService* local_state);
// Method used to determine whether a domain is associated with legacy demo
// retail mode, where demo mode sessions are implemented as public sessions.
// Exposed so the matching can be tested.
// TODO(crbug.com/874778): Remove after legacy retail mode domains have been
// disabled.
static bool IsLegacyDemoRetailModeDomain(const std::string& domain);
~DemoModeResourcesRemover() override;
// CryptohomeClient::Observer:
void LowDiskSpace(uint64_t free_disk_space) override;
// user_manager::UserManager::UserSessionStateObserver:
void ActiveUserChanged(const user_manager::User* user) override;
// ui::UserActivityObserver:
void OnUserActivity(const ui::Event* event) override;
// Requests demo mode resources removal from the disk. If a removal operation
// is already in progress, this method will schedule the callback to be run
// with the result of the operation in progress.
void AttemptRemoval(RemovalReason reason, RemovalCallback callback);
// Allows tests to override the tick clock and configuration for accumulating
// the amount of active device usage.
void OverrideTimeForTesting(base::TickClock* tick_clock,
const UsageAccumulationConfig& config);
private:
// Defined here so it can be overridden in tests.
UsageAccumulationConfig usage_accumulation_config_;
// Use CreateIfNeeded() to create an instance.
explicit DemoModeResourcesRemover(PrefService* local_state);
// Updates the accumulated information about the amount of active device
// usage, which is used to detect when the device owned by a real user, and
// thus does not require demo mode resources.
void UpdateDeviceUsage(const base::TimeDelta& duration);
// If the amount of detected device usage is above the threshold for removing
// demo mode resources, attempts the resources removal. If resoruces removal
// is requested, stops observing device usage.
// Returns whether the resources removal was requested.
bool AttemptRemovalIfUsageOverThreshold();
// Passes as the callback to directory removal file operations.
void OnRemovalDone(RemovalReason reason, RemovalResult result);
PrefService* const local_state_;
// Whether a resources removal operation is currently in progress.
bool removal_in_progress_ = false;
// Callbacks for the resources removal operation, if one is in progress.
std::vector<RemovalCallback> removal_callbacks_;
const base::TickClock* tick_clock_;
// Used to track the duration of last unrecorded interval of user activity.
base::Optional<base::TimeTicks> usage_start_;
base::Optional<base::TimeTicks> usage_end_;
ScopedObserver<CryptohomeClient, DemoModeResourcesRemover>
cryptohome_observer_;
ScopedObserver<ui::UserActivityDetector, DemoModeResourcesRemover>
user_activity_observer_;
base::WeakPtrFactory<DemoModeResourcesRemover> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(DemoModeResourcesRemover);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_MODE_RESOURCES_REMOVER_H_