// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library fuchsia.media.drm;

using fuchsia.media;

type DecryptorParams = table {
    /// Requires the decryptor [`fuchsia.media/StreamProcessor`] to only output
    /// to secure buffers.
    1: require_secure_mode bool;

    /// Initial format details for the [`fuchsia.media/StreamProcessor`].
    2: input_details fuchsia.media.FormatDetails;
};

/// A protocol for managing content license sessions and providing decryption of
/// media content. There may be zero to many active [`LicenseSession`]s
/// associated with a `ContentDecryptionModule`, each with their own sets of
/// keys.
///
/// From an EME client's perspective, this protocol has a 1:1 relationship with
/// the MediaKeys object.
closed protocol ContentDecryptionModule {
    /// Indicates that the `ContentDecryptionModule` is provisioned.
    ///
    /// In order to create `LicenseSession`s, a `ContentDecryptionModule` must
    /// be provisioned. A `ContentDecryptionModule` is not considered
    /// provisioned until it meets the requirements for the underlying DRM
    /// system. The DRM system may not require provisioning, may only require
    /// factory provisioning or may require both factory provisioning and
    /// service instance provisioning.
    ///
    /// If the `ContentDecryptionModule` has already has sufficient
    /// provisioning, this event will be sent immediately upon creation. If the
    /// `ContentDecryptionModule` has its provisioning removed, then the server
    /// will close the channel and also close any active `LicenseSession`s or
    /// Decryptors.
    ///
    /// If the DRM system does not require provisioning at all, this
    /// event should still be sent to notify the client that it can create
    /// `LicenseSession`s.
    strict -> OnProvisioned();

    /// Sets the certificate to be used for encrypting outgoing messages.
    ///
    /// + request `certificate` a buffer containing the certificate to be used.
    /// * error an [`Error`] indicating the reason for failure.
    strict SetServerCertificate(struct {
        certificate vector<uint8>:MAX;
    }) -> () error Error;

    /// Creates a new session for the given type.
    ///
    /// The `session_id` will be generated by the [`ContentDecryptionModule`]
    /// and can be used to reload the session after closing. If the
    /// `session_type` is not supported by the underlying DRM system, it will
    /// immediately close the `license_session`.
    ///
    /// + request `session_type` a field containing either
    ///   [`LicenseSessionType.TEMPORARY`] or
    ///   [`LicenseSessionType.PERSISTENT_LICENSE`]
    /// + request `license_session` the server endpoint of the
    ///   [`LicenseSession`]
    /// - response `session_id` an identifier that can be used to reload the
    ///   session later (if persistent).
    strict CreateLicenseSession(resource struct {
        session_type LicenseSessionType;
        license_session server_end:LicenseSession;
    }) -> (struct {
        session_id SessionId;
    });

    /// Loads an existing session from storage using the given `session_id`.
    ///
    /// If the session is not found, then the `license_session` will be closed.
    ///
    /// + request `session_id` contains an identifier of which session should be
    ///   loaded from storage.
    /// + request `license_session` the server endpoint of the
    ///   [`LicenseSession`].
    strict LoadLicenseSession(resource struct {
        session_id SessionId;
        license_session server_end:LicenseSession;
    });

    /// Creates a Decryptor [`fuchsia.media/StreamProcessor`] to be used to
    /// decrypt content.
    ///
    /// This `decryptor` would have access to the union of keys created by all
    /// the active sessions for this [`ContentDecryptionModule`].
    ///
    /// + request `params` the parameters with which to create the `decryptor`.
    /// + request `decryptor` the server endpoint of the
    ///   `fuchsia.media/StreamProcessor`.
    strict CreateDecryptor(resource struct {
        params DecryptorParams;
        decryptor server_end:fuchsia.media.StreamProcessor;
    });

    /// Queries the status of a hypothetical key associated with an HDCP policy.
    ///
    /// This aids clients in determining which content type to fetch prior to
    /// establishing a [`LicenseSession`]. For example, if the device would
    /// restrict output for HDCP 1.x, then the client can choose to fetch SD
    /// content rather than HD.
    ///
    /// + request `hdcp_version` a field containing the HDCP version to check,
    ///   such as "1.2" or "2.0".
    /// - response `key_status` a field indicating what the status of a
    ///   hypothetical key would be for this device if one could be licensed.
    strict GetKeyStatusForHdcpVersion(struct {
        hdcp_version HdcpVersion;
    }) -> (struct {
        key_status KeyStatus;
    });

    /// Queries for the list of supported encryption schemes.
    ///
    /// This returns a list of the supported encryption schemes that the
    /// `ContentDecryptionModule` supports, such as 'cenc' or 'cbcs'. If the
    /// implementation supports passing unencrypted frames through decryption
    /// prior to license arrival, it should also report
    /// `fuchsia.media.UNENCRYPTED` as a supported scheme.
    ///
    /// - response `encryption_schemes` a list of the supported encryption
    ///   schemes.
    strict GetSupportedEncryptionSchemes() -> (struct {
        encryption_schemes vector<EncryptionScheme>:MAX;
    });
};
