blob: 391ba056e87ff8c3625d91eb9ba6fba2da10ac76 [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 <deque>
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "chromeos/dbus/session_manager_client.h"
#include "components/policy/core/common/cloud/cloud_policy_validator.h"
#include "crypto/scoped_nss_types.h"
#include "policy/proto/device_management_backend.pb.h"
namespace crypto {
class RSAPrivateKey;
}
namespace enterprise_management {
class ChromeDeviceSettingsProto;
}
namespace chromeos {
class OwnerKeyUtil;
class PublicKey;
class SessionManagerOperation;
// Deals with the low-level interface to Chromium 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.
enum OwnershipStatus {
// Listed in upgrade order.
OWNERSHIP_UNKNOWN = 0,
OWNERSHIP_NONE,
OWNERSHIP_TAKEN
};
typedef base::Callback<void(OwnershipStatus)> OwnershipStatusCallback;
// Status codes for Store().
enum Status {
STORE_SUCCESS,
STORE_KEY_UNAVAILABLE, // Owner key not yet configured.
STORE_POLICY_ERROR, // Failure constructing the settings blob.
STORE_OPERATION_FAILED, // IPC to session_manager daemon failed.
STORE_NO_POLICY, // No settings blob present.
STORE_INVALID_POLICY, // Invalid settings blob.
STORE_VALIDATION_ERROR, // Unrecoverable policy validation failure.
STORE_TEMP_VALIDATION_ERROR, // Temporary policy validation failure.
};
// Observer interface.
class Observer {
public:
virtual ~Observer();
// Indicates device ownership status changes.
virtual void OwnershipStatusChanged() = 0;
// Gets call after updates to the device settings.
virtual void DeviceSettingsUpdated() = 0;
};
class PrivateKeyDelegate {
public:
typedef base::Callback<void(bool is_owner)> IsOwnerCallback;
typedef base::Callback<void(std::string policy_blob)>
AssembleAndSignPolicyCallback;
virtual ~PrivateKeyDelegate() {}
// Returns whether current user is owner or not. When this method
// is called too early, incorrect result can be returned because
// private key loading may be in progress.
virtual bool IsOwner() = 0;
// Determines whether current user is owner or not, responds via
// |callback|.
virtual void IsOwnerAsync(const IsOwnerCallback& callback) = 0;
// Assembles and signs |policy|, responds via |callback|.
virtual bool AssembleAndSignPolicyAsync(
scoped_ptr<enterprise_management::PolicyData> policy,
const AssembleAndSignPolicyCallback& callback) = 0;
};
// 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();
virtual ~DeviceSettingsService();
// To be called on startup once threads are initialized and DBus is ready.
void SetSessionManager(SessionManagerClient* session_manager_client,
scoped_refptr<OwnerKeyUtil> owner_key_util);
// Prevents the service from making further calls to session_manager_client
// and stops any pending operations.
void UnsetSessionManager();
// Returns the currently active device settings. Returns NULL if the device
// settings have not been retrieved from session_manager yet.
const enterprise_management::PolicyData* policy_data() {
return policy_data_.get();
}
const enterprise_management::ChromeDeviceSettingsProto*
device_settings() const {
return device_settings_.get();
}
// Returns the currently used owner key.
scoped_refptr<PublicKey> GetPublicKey();
// Returns the status generated by the last operation.
Status status() {
return store_status_;
}
// Triggers an attempt to pull the public half of the owner key from disk and
// load the device settings.
void Load();
// Signs |settings| with the private half of the owner key and sends the
// resulting policy blob to session manager for storage. 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 SignAndStore(
scoped_ptr<enterprise_management::ChromeDeviceSettingsProto> new_settings,
const base::Closure& callback);
// Sets the management related settings in PolicyData. Note that if
// |management_mode| is NOT_MANAGED, |request_token| and |device_id| should be
// empty strings.
void SetManagementSettings(
enterprise_management::PolicyData::ManagementMode management_mode,
const std::string& request_token,
const std::string& device_id,
const base::Closure& callback);
// 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(scoped_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.
bool HasPrivateOwnerKey();
// Sets the identity of the user that's interacting with the service. This is
// relevant only for writing settings through SignAndStore().
void InitOwner(const std::string& username,
const base::WeakPtr<PrivateKeyDelegate>& delegate);
const std::string& GetUsername() const;
// Adds an observer.
void AddObserver(Observer* observer);
// Removes an observer.
void RemoveObserver(Observer* observer);
// SessionManagerClient::Observer:
virtual void OwnerKeySet(bool success) OVERRIDE;
virtual void PropertyChangeComplete(bool success) OVERRIDE;
private:
// Enqueues a new operation. Takes ownership of |operation| and starts it
// right away if there is no active operation currently.
void Enqueue(SessionManagerOperation* operation);
// Enqueues a load operation.
void EnqueueLoad(bool force_key_load);
void EnqueueSignAndStore(scoped_ptr<enterprise_management::PolicyData> policy,
const base::Closure& callback);
// Makes sure there's a reload operation so changes to the settings (and key,
// in case force_key_load is set) are getting picked up.
void EnsureReload(bool force_key_load);
// Runs the next pending operation.
void StartNextOperation();
// Updates status, policy data and owner key from a finished operation.
// Starts the next pending operation if available.
void HandleCompletedOperation(const base::Closure& callback,
SessionManagerOperation* operation,
Status status);
// Updates status and invokes the callback immediately.
void HandleError(Status status, const base::Closure& callback);
// Assembles PolicyData based on |settings| and the current |policy_data_|
// and |username_|.
scoped_ptr<enterprise_management::PolicyData> AssemblePolicy(
const enterprise_management::ChromeDeviceSettingsProto& settings) const;
// Returns the current management mode.
enterprise_management::PolicyData::ManagementMode GetManagementMode() const;
// Returns true if it is okay to transfer from the current mode to the new
// mode. This function should be called in SetManagementMode().
bool CheckManagementModeTransition(
enterprise_management::PolicyData::ManagementMode new_mode) const;
SessionManagerClient* session_manager_client_;
scoped_refptr<OwnerKeyUtil> owner_key_util_;
Status store_status_;
std::vector<OwnershipStatusCallback> pending_ownership_status_callbacks_;
std::string username_;
scoped_refptr<PublicKey> public_key_;
base::WeakPtr<PrivateKeyDelegate> delegate_;
scoped_ptr<enterprise_management::PolicyData> policy_data_;
scoped_ptr<enterprise_management::ChromeDeviceSettingsProto> device_settings_;
// The queue of pending operations. The first operation on the queue is
// currently active; it gets removed and destroyed once it completes.
std::deque<SessionManagerOperation*> pending_operations_;
ObserverList<Observer, true> observers_;
// For recoverable load errors how many retries are left before we give up.
int load_retries_left_;
base::WeakPtrFactory<DeviceSettingsService> weak_factory_;
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_