| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_BROWSER_ASH_SETTINGS_DEVICE_SETTINGS_SERVICE_H_ |
| #define CHROME_BROWSER_ASH_SETTINGS_DEVICE_SETTINGS_SERVICE_H_ |
| |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "base/containers/circular_deque.h" |
| #include "base/functional/callback.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/observer_list.h" |
| #include "chromeos/ash/components/dbus/session_manager/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" |
| |
| class PrefService; |
| |
| namespace ownership { |
| class OwnerKeyUtil; |
| class PublicKey; |
| } // namespace ownership |
| |
| namespace policy { |
| namespace off_hours { |
| class DeviceOffHoursController; |
| } // namespace off_hours |
| } // namespace policy |
| |
| namespace ash { |
| |
| 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 class OwnershipStatus { |
| // These values are persisted to logs. Entries should not be renumbered and |
| // numeric values should never be reused. |
| kOwnershipUnknown = 0, |
| // Not yet owned. |
| kOwnershipNone = 1, |
| // Either consumer ownership or cloud management. |
| kOwnershipTaken = 2, |
| kMaxValue = kOwnershipTaken |
| }; |
| |
| using OwnershipStatusCallback = base::OnceCallback<void(OwnershipStatus)>; |
| using PolicyDataCallback = |
| base::OnceCallback<void(enterprise_management::PolicyData*)>; |
| |
| // Status codes for Load() and Store(). |
| // These values are logged to UMA. Entries should not be renumbered and |
| // numeric values should never be reused. Please keep in sync with |
| // "DeviceSettingsStatus2" in |
| // tools/metrics/histograms/metadata/enterprise/enums.xml. |
| 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. |
| STORE_KEY_UNAVAILABLE_NOT_INITIALIZED, // Early in boot process. |
| STORE_KEY_UNAVAILABLE_NOT_LOCKED, // Owner key not present, ownership |
| // not taken. Not an error. |
| STORE_KEY_UNAVAILABLE_MANAGED, // Owner key not present for managed device. |
| kMaxValue = STORE_KEY_UNAVAILABLE_MANAGED, |
| }; |
| |
| // 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(); |
| |
| // Returns a human-readable string describing |status|. |
| static const char* StatusToString(Status status); |
| |
| // Creates a device settings service instance. This is meant for unit tests, |
| // production code uses the singleton returned by Get() above. |
| DeviceSettingsService(); |
| |
| DeviceSettingsService(const DeviceSettingsService&) = delete; |
| DeviceSettingsService& operator=(const DeviceSettingsService&) = delete; |
| |
| ~DeviceSettingsService() override; |
| |
| // To be called on startup once threads are initialized and D-Bus is ready. |
| // `local_state` must be valid until `StopProcessing()`. `local_state` may be |
| // null only in tests. |
| void StartProcessing(PrefService* local_state, |
| 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 StopProcessing(); |
| |
| // 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(); |
| } |
| |
| const enterprise_management::PolicyFetchResponse* policy_fetch_response() |
| const { |
| return policy_fetch_response_.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(); |
| |
| // Attempts to load asynchronously the settings if they haven't been loaded |
| // already and no request is in the queue. The aim is to avoid additional |
| // request when not needed. Should NOT be used when the settings need to be |
| // renewed, like in invalidations flow or when an explicit request from user |
| // to reload is received. |
| void LoadIfNotPresent(); |
| |
| // 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, |
| base::OnceClosure 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. |
| virtual void GetOwnershipStatusAsync(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 OwnerSettingsServiceAsh. |
| 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(); |
| |
| // Returns whether the current user should take ownership of the device |
| // (effectively whether the user is the first consumer user on the device). |
| bool GetWillEstablishConsumerOwnership() const { |
| return will_establish_consumer_ownership_; |
| } |
| |
| // Returns if the device is managed according to the device settings. |
| bool IsDeviceManaged() const; |
| |
| // Returns if the device policy is loaded and contains the DM token. |
| bool HasDmToken() const; |
| |
| // 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; |
| void SessionStopping() override; |
| |
| private: |
| friend class OwnerSettingsServiceAsh; |
| |
| // Enqueues a new operation. Takes ownership of |operation| and starts it |
| // right away if there is no active operation currently. |
| void Enqueue(std::unique_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(base::OnceClosure callback, |
| SessionManagerOperation* operation, |
| Status status); |
| |
| // Same as HandleCompletedOperation(), but also starts the next pending |
| // operation if available. |
| void HandleCompletedAsyncOperation(base::OnceClosure callback, |
| SessionManagerOperation* operation, |
| Status status); |
| |
| // Helper method for GetOwnershipStatusAsync to avoid data race upon |
| // user sign-in. |
| void ValidateOwnershipStatusAndNotify(OwnershipStatusCallback callback); |
| |
| // Run OwnershipStatusChanged() for observers. |
| void NotifyOwnershipStatusChanged() const; |
| |
| // Run DeviceSettingsUpdated() for observers. |
| void NotifyDeviceSettingsUpdated() const; |
| |
| // Processes pending callbacks from GetOwnershipStatusAsync(). |
| void RunPendingOwnershipStatusCallbacks(); |
| |
| raw_ptr<PrefService> local_state_ = nullptr; |
| |
| raw_ptr<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_ = |
| OwnershipStatus::kOwnershipUnknown; |
| |
| std::unique_ptr<enterprise_management::PolicyFetchResponse> |
| policy_fetch_response_; |
| 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<std::unique_ptr<SessionManagerOperation>> |
| pending_operations_; |
| |
| base::ObserverList<Observer>::Unchecked observers_; |
| |
| // Whether the device will be establishing consumer ownership. |
| bool will_establish_consumer_ownership_ = false; |
| |
| // Whether we received the signal that the session is stopping. |
| bool session_stopping_ = false; |
| |
| std::unique_ptr<policy::off_hours::DeviceOffHoursController> |
| device_off_hours_controller_; |
| |
| base::WeakPtrFactory<DeviceSettingsService> weak_factory_{this}; |
| }; |
| |
| std::ostream& operator<<(std::ostream&, DeviceSettingsService::OwnershipStatus); |
| |
| } // namespace ash |
| |
| #endif // CHROME_BROWSER_ASH_SETTINGS_DEVICE_SETTINGS_SERVICE_H_ |