| // Copyright 2006 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef COMPONENTS_SESSIONS_CORE_SESSION_COMMAND_H_ |
| #define COMPONENTS_SESSIONS_CORE_SESSION_COMMAND_H_ |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include <memory> |
| #include <optional> |
| #include <string> |
| #include <string_view> |
| #include <type_traits> |
| #include <vector> |
| |
| #include "base/containers/span.h" |
| #include "components/os_crypt/async/common/encryptor.h" |
| #include "components/sessions/core/sessions_export.h" |
| |
| namespace base { |
| class Pickle; |
| class PickleIterator; |
| } // namespace base |
| |
| namespace sessions { |
| |
| // SessionCommand stores information used for restoring a session. |
| // It contains an identifier ("id") and arbitrary chunk of data ("contents"). |
| // |
| // The meaning of the identifier and the contents are specific to the service |
| // creating them. |
| // |
| // Both TabRestoreService and SessionService use SessionCommands to store data |
| // on disk using the CommandStorageManager. |
| // |
| // There are two ways to create a SessionCommand: |
| // . Specify the size of the data block to create. This is useful for |
| // commands that have a fixed size. |
| // . From a pickle, this is useful for commands whose length varies. |
| class SESSIONS_EXPORT SessionCommand { |
| public: |
| // The type of the identifier. |
| using id_type = uint8_t; |
| |
| // The type of the size of the contents. |
| using size_type = uint16_t; |
| |
| // Creates a session command with the specified id. This allocates a buffer |
| // of size |size| that must be filled via contents(). |
| SessionCommand(id_type id, size_type size); |
| |
| // Convenience constructor that creates a session command with the specified |
| // id whose contents is populated from the contents of pickle. |
| SessionCommand(id_type id, const base::Pickle& pickle); |
| |
| SessionCommand(const SessionCommand&) = delete; |
| SessionCommand& operator=(const SessionCommand&) = delete; |
| bool operator==(const SessionCommand& command) const; |
| |
| std::unique_ptr<SessionCommand> Clone() const; |
| |
| // An identifier for the command. The meaning of the identifier is specific |
| // to the service that creates the command. |
| id_type id() const { return id_; } |
| |
| // The maximum size of the |contents|. |
| // Note that this is less than UINT16_MAX. |
| // If this size is exceeded, the contents will be truncated in Serialize(). |
| static constexpr size_t kMaxContentSize = |
| std::numeric_limits<size_type>::max() - sizeof(id_type); |
| |
| // The contents of the command. This is an arbitrary chunk of data whose |
| // meaning is specific to the service that creates the command. |
| base::span<const uint8_t> contents() const { |
| return base::as_byte_span(contents_); |
| } |
| base::span<uint8_t> contents() { |
| return base::as_writable_byte_span(contents_); |
| } |
| |
| // Convenience for extracting the data to a target. Returns false if |
| // the destination span's size is not equal to the size of data this |
| // command contains. |
| bool GetContents(base::span<uint8_t> dest) const; |
| |
| // Convenience for extracting the data to a target struct. Returns false if |
| // the destination's size is not equal to the size of data this command |
| // contains. |
| template <typename T> |
| bool GetContents(T& dest) const { |
| if constexpr (std::has_unique_object_representations_v<T>) { |
| return GetContents(base::byte_span_from_ref(dest)); |
| } else { |
| return GetContents( |
| base::byte_span_from_ref(base::allow_nonunique_obj, dest)); |
| } |
| } |
| |
| // Returns an iterator for reading the contents. |
| base::PickleIterator ContentsAsPickle() const; |
| |
| // Serializes the SessionCommand (e.g., so that it can be written to a file). |
| // The serialized form includes the size of the command, the id, and the |
| // contents. |
| // If the size of the contents is greater than kMaxContentSize, the contents |
| // will be truncated. |
| // If encryptor is nullptr, the contents will be cleartext. |
| // If an encryptor is provided, the contents will be encrypted. |
| // If an error occurs, an empty vector will be returned. |
| std::vector<uint8_t> Serialize(os_crypt_async::Encryptor* encryptor) const; |
| |
| // Deserializes the data into a SessionCommand (e.g., for reading from a |
| // file). It is expected that the data was serialized using Serialize(). |
| // Returns the total serialized size of the command if there is enough data |
| // to determine it, or std::nullopt otherwise. |
| // encrypted: whether the data was encrypted during serialization. |
| static std::optional<size_t> GetSerializedSize(base::span<const uint8_t> data, |
| bool encrypted); |
| |
| // Deserializes a SessionCommand that was serialized using Serialize() |
| // E.g., for reading from a file. |
| // If encryptor is nullptr, the data is assumed to be cleartext. |
| // If an encryptor is provided, the contents will be decrypted. |
| // If an error occurs, nullptr will be returned. |
| static std::unique_ptr<SessionCommand> Deserialize( |
| base::span<const uint8_t> data, |
| os_crypt_async::Encryptor* encryptor); |
| |
| private: |
| std::vector<uint8_t> SerializeAsCleartext() const; |
| std::vector<uint8_t> SerializeWithEncryption( |
| const os_crypt_async::Encryptor& encryptor) const; |
| |
| static std::unique_ptr<SessionCommand> DeserializeCleartext( |
| base::span<const uint8_t> data); |
| static std::unique_ptr<SessionCommand> DeserializeEncrypted( |
| base::span<const uint8_t> data, |
| const os_crypt_async::Encryptor& encryptor); |
| |
| const id_type id_; |
| std::string contents_; |
| }; |
| |
| } // namespace sessions |
| |
| #endif // COMPONENTS_SESSIONS_CORE_SESSION_COMMAND_H_ |