blob: f8bd2f5846416c37433e95ade29e3dce5fe6a53f [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_SETTINGS_DEVICE_SETTINGS_SERVICE_H_
#define CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_SETTINGS_SERVICE_H_
#include <memory>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/containers/circular_deque.h"
#include "base/macros.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
#include "chromeos/dbus/session_manager_client.h"
#include "components/ownership/owner_settings_service.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "components/policy/core/common/cloud/cloud_policy_validator.h"
#include "components/policy/proto/chrome_device_policy.pb.h"
#include "components/policy/proto/device_management_backend.pb.h"
#include "crypto/scoped_nss_types.h"
namespace ownership {
class OwnerKeyUtil;
class PublicKey;
}
namespace policy {
namespace off_hours {
class DeviceOffHoursController;
} // namespace off_hours
} // namespace policy
namespace chromeos {
class SessionManagerOperation;
// Deals with the low-level interface to Chrome OS device settings. Device
// settings are stored in a protobuf that's protected by a cryptographic
// signature generated by a key in the device owner's possession. Key and
// settings are brokered by the session_manager daemon.
//
// The purpose of DeviceSettingsService is to keep track of the current key and
// settings blob. For reading and writing device settings, use CrosSettings
// instead, which provides a high-level interface that allows for manipulation
// of individual settings.
//
// DeviceSettingsService generates notifications for key and policy update
// events so interested parties can reload state as appropriate.
class DeviceSettingsService : public SessionManagerClient::Observer {
public:
// Indicates ownership status of the device (listed in upgrade order).
enum OwnershipStatus {
OWNERSHIP_UNKNOWN = 0,
// Not yet owned.
OWNERSHIP_NONE,
// Either consumer ownership, cloud management or Active Directory
// management.
OWNERSHIP_TAKEN
};
typedef base::Callback<void(OwnershipStatus)> OwnershipStatusCallback;
// Status codes for Load() and Store().
enum Status {
STORE_SUCCESS,
STORE_KEY_UNAVAILABLE, // Owner key not yet configured.
STORE_OPERATION_FAILED, // IPC to session_manager daemon failed.
STORE_NO_POLICY, // No settings blob present.
STORE_INVALID_POLICY, // Invalid settings blob (proto parse failed).
STORE_VALIDATION_ERROR, // Policy validation failure.
};
// Observer interface.
class Observer {
public:
virtual ~Observer();
// Indicates device ownership status changes. This is triggered upon every
// browser start since the transition from uninitialized (OWNERSHIP_UNKNOWN)
// to initialized (either of OWNERSHIP_{NONE,TAKEN}) also counts as an
// ownership change.
virtual void OwnershipStatusChanged();
// Gets called after updates to the device settings.
virtual void DeviceSettingsUpdated();
virtual void OnDeviceSettingsServiceShutdown();
};
// Manage singleton instance.
static void Initialize();
static bool IsInitialized();
static void Shutdown();
static DeviceSettingsService* Get();
// Creates a device settings service instance. This is meant for unit tests,
// production code uses the singleton returned by Get() above.
DeviceSettingsService();
~DeviceSettingsService() override;
// To be called on startup once threads are initialized and D-Bus is ready.
void SetSessionManager(SessionManagerClient* session_manager_client,
scoped_refptr<ownership::OwnerKeyUtil> owner_key_util);
// Prevents the service from making further calls to session_manager_client
// and stops any pending operations.
void UnsetSessionManager();
// Must only be used with a |device_mode| that has been read and verified by
// the InstallAttributes class.
void SetDeviceMode(policy::DeviceMode device_mode);
const enterprise_management::PolicyData* policy_data() const {
return policy_data_.get();
}
// Returns the currently active device settings. Returns nullptr if the device
// settings have not been retrieved from session_manager yet.
const enterprise_management::ChromeDeviceSettingsProto*
device_settings() const {
return device_settings_.get();
}
// Returns the currently used owner key.
scoped_refptr<ownership::PublicKey> GetPublicKey();
// Returns the status generated by the *last operation*.
// WARNING: It is not correct to take this method as an indication of whether
// DeviceSettingsService contains valid device settings. In order to answer
// that question, simply check whether device_settings() is different from
// nullptr.
Status status() const { return store_status_; }
// Returns the currently device off hours controller. The returned pointer is
// guaranteed to be non-null.
policy::off_hours::DeviceOffHoursController* device_off_hours_controller()
const {
return device_off_hours_controller_.get();
}
void SetDeviceOffHoursControllerForTesting(
std::unique_ptr<policy::off_hours::DeviceOffHoursController> controller);
// Triggers an attempt to pull the public half of the owner key from disk and
// load the device settings.
void Load();
// Synchronously pulls the public key and loads the device settings.
void LoadImmediately();
// Stores a policy blob to session_manager. The result of the operation is
// reported through |callback|. If successful, the updated device settings are
// present in policy_data() and device_settings() when the callback runs.
void Store(std::unique_ptr<enterprise_management::PolicyFetchResponse> policy,
const base::Closure& callback);
// Returns the ownership status. May return OWNERSHIP_UNKNOWN if the disk
// hasn't been checked yet.
OwnershipStatus GetOwnershipStatus();
// Determines the ownership status and reports the result to |callback|. This
// is guaranteed to never return OWNERSHIP_UNKNOWN.
void GetOwnershipStatusAsync(const OwnershipStatusCallback& callback);
// Checks whether we have the private owner key.
//
// DEPRECATED (ygorshenin@, crbug.com/433840): this method should
// not be used since private key is a profile-specific resource and
// should be checked and used in a profile-aware manner, through
// OwnerSettingsService.
bool HasPrivateOwnerKey();
// Sets the identity of the user that's interacting with the service. This is
// relevant only for writing settings through SignAndStore().
//
// TODO (ygorshenin@, crbug.com/433840): get rid of the method when
// write path for device settings will be removed from
// DeviceSettingsProvider and all existing clients will be switched
// to OwnerSettingsServiceChromeOS.
void InitOwner(const std::string& username,
const base::WeakPtr<ownership::OwnerSettingsService>&
owner_settings_service);
const std::string& GetUsername() const;
ownership::OwnerSettingsService* GetOwnerSettingsService() const;
// Mark that the device will establish consumer ownership. If the flag is set
// and ownership is not taken, policy reload will be deferred until InitOwner
// is called. So that the ownership status is flipped after the private part
// of owner is fully loaded.
void MarkWillEstablishConsumerOwnership();
// Adds an observer.
void AddObserver(Observer* observer);
// Removes an observer.
void RemoveObserver(Observer* observer);
// SessionManagerClient::Observer:
void OwnerKeySet(bool success) override;
void PropertyChangeComplete(bool success) override;
private:
friend class OwnerSettingsServiceChromeOS;
// Enqueues a new operation. Takes ownership of |operation| and starts it
// right away if there is no active operation currently.
void Enqueue(const linked_ptr<SessionManagerOperation>& operation);
// Enqueues a load operation.
void EnqueueLoad(bool request_key_load);
// Makes sure there's a reload operation so changes to the settings (and key,
// in case |request_key_load| is set) are getting picked up.
void EnsureReload(bool request_key_load);
// Runs the next pending operation.
void StartNextOperation();
// Updates status, policy data and owner key from a finished operation.
void HandleCompletedOperation(const base::Closure& callback,
SessionManagerOperation* operation,
Status status);
// Same as HandleCompletedOperation(), but also starts the next pending
// operation if available.
void HandleCompletedAsyncOperation(const base::Closure& callback,
SessionManagerOperation* operation,
Status status);
// Run OwnershipStatusChanged() for observers.
void NotifyOwnershipStatusChanged() const;
// Run DeviceSettingsUpdated() for observers.
void NotifyDeviceSettingsUpdated() const;
// Processes pending callbacks from GetOwnershipStatusAsync().
void RunPendingOwnershipStatusCallbacks();
SessionManagerClient* session_manager_client_ = nullptr;
scoped_refptr<ownership::OwnerKeyUtil> owner_key_util_;
Status store_status_ = STORE_SUCCESS;
std::vector<OwnershipStatusCallback> pending_ownership_status_callbacks_;
std::string username_;
scoped_refptr<ownership::PublicKey> public_key_;
base::WeakPtr<ownership::OwnerSettingsService> owner_settings_service_;
// Ownership status before the current session manager operation.
OwnershipStatus previous_ownership_status_ = OWNERSHIP_UNKNOWN;
std::unique_ptr<enterprise_management::PolicyData> policy_data_;
std::unique_ptr<enterprise_management::ChromeDeviceSettingsProto>
device_settings_;
policy::DeviceMode device_mode_ = policy::DEVICE_MODE_PENDING;
// The queue of pending operations. The first operation on the queue is
// currently active; it gets removed and destroyed once it completes.
base::circular_deque<linked_ptr<SessionManagerOperation>> pending_operations_;
base::ObserverList<Observer> observers_;
// Whether the device will be establishing consumer ownership.
bool will_establish_consumer_ownership_ = false;
std::unique_ptr<policy::off_hours::DeviceOffHoursController>
device_off_hours_controller_;
base::WeakPtrFactory<DeviceSettingsService> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(DeviceSettingsService);
};
// Helper class for tests. Initializes the DeviceSettingsService singleton on
// construction and tears it down again on destruction.
class ScopedTestDeviceSettingsService {
public:
ScopedTestDeviceSettingsService();
~ScopedTestDeviceSettingsService();
private:
DISALLOW_COPY_AND_ASSIGN(ScopedTestDeviceSettingsService);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_SETTINGS_SERVICE_H_