// 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.io;
using fuchsia.mem;

const uint32 KEY_ID_SIZE = 16;

// Encryption modes as defined by ISO 23001-7: Common encryption in ISO base
// media file format files. These are defined as strings rather than enums so as
// to not limit the types of encryption formats to just the set as defined by
// the current Common Encryption standard.
const string ENCRYPTION_MODE_CENC = "cenc";
const string ENCRYPTION_MODE_CBC1 = "cbc1";
const string ENCRYPTION_MODE_CENS = "cens";
const string ENCRYPTION_MODE_CBCS = "cbcs";

enum KeyStatus {
    USABLE = 0;
    EXPIRED = 1;
    RELEASED = 2;
    OUTPUT_RESTRICTED = 3;
    OUTPUT_DOWNSCALED = 4;
    STATUS_PENDING = 5;
    INTERNAL_ERROR = 6;
};

/// ProvisioningRequest is for messages originating from the CDM that the caller
/// must route to the provisioning server.
struct ProvisioningRequest {
    fuchsia.mem.Buffer message;
};

/// ProvisioningResponse is for messages originating from the provisioning
/// server that the caller must provide to the CDM via
/// `ProcessProvisioningResponse`.
struct ProvisioningResponse {
    fuchsia.mem.Buffer message;
};

struct KeyId {
    array<uint8>:KEY_ID_SIZE data;
};

[FragileBase]
protocol ContentDecryptionModule {
    /// Set the certificate to be used for encrypting outgoing messages.
    SetServerCertificate(bytes certificate);

    /// Create a new session for the given type. The |session_id| will be
    /// generated by the CDM and can be used to reload the session after
    /// closing.
    CreateLicenseSession(LicenseSessionType session_type,
                         request<LicenseSession> license_session)
        -> (string session_id);

    /// Load an existing session from persistent storage using the given
    /// |session_id|. If the session is not found, then the |license_session|
    /// will be closed.
    LoadLicenseSession(string session_id,
                       request<LicenseSession> license_session);

    /// If the underlying CDM system requires provisioning for individual
    /// providers (the owner of the CDM instance), then this method can be used
    /// to generate ProvisioningRequests. This message must be routed to the
    /// provisioning server by the client and the server's response provided to
    /// the CDM by calling `ProcessProvisioningResponse`.
    GenerateProvisioningRequest() -> (ProvisioningRequest request);

    /// Update the CDM with a message from the provisioning server. Not all
    /// underlying CDM systems will require provisioning for individual
    /// providers. If they do, this method will carry the provisioning message
    /// to the CDM instance so that it may persistently store the provider
    /// certificate.
    ProcessProvisioningResponse(ProvisioningResponse response);

    /// Remove the persistent session data associated with the session without
    /// waiting for server acknowledgement. No LicenseMessage will be generated.
    /// If there is an active LicenseSession for this |session_id|, it will be
    /// closed.
    RemoveLicenseSessionData(string session_id);

    /// Check whether the device has been provisioned. Some CDM systems will be
    /// entirely provisioned at the time of device manufacturing, while others
    /// might require additional provisioning for a given content provider. This
    /// provisioning status will indicate whether the CDM is capable of
    /// generating license requests.
    IsProvisioned() -> (bool is_provisioned);

    /// Removes all provider based provisioning for this CDM instance. This does
    /// not impact any factory provisioning.
    RemoveProvisioning();

    /// Remove all persistent usage records for this CDM instance. Any
    /// associated license sessions will no longer be usable.
    RemoveUsageRecords();

    /// Query the status of a hypothetical key associated with an HDCP policy
    /// without setting up a license session. This aids clients in determining
    /// which content type to fetch prior to establishing. For example, if the
    /// device would restrict output for HDCP 1.x, then the client can choose to
    /// fetch SD content rather than HD.
    GetKeyStatusForHdcpVersion(string hdcp_version) -> (KeyStatus key_status);

    /// Query the CDM for the list of supported encryption modes, such as
    /// 'cenc', 'cbc1', 'cens', or 'cbcs'.
    GetSupportedEncryptionModes() -> (vector<string> encryption_modes);
};

// There are two ways to create the desired ContentDecryptionModule. Which
// method to use is dependent on how persistent storage should be provided to
// the CDM. The preferred method to use is the per key system discoverable
// interface. This method will rely on the componentmgr to create the CDM
// instance's persistent storage for it. This provides isolation of the storage
// location from the client.
//
// The second method is to use the discoverable ContentDecryptionModuleFactory
// and request that it creates the CDM on the client's behalf. Using this method
// requires the client to provide the storage to be used. This storage should be
// isolated to distinct origins/providers.

[Discoverable]
protocol ClearKeyContentDecryptionModule {
    compose ContentDecryptionModule;
};

[Discoverable]
protocol WidevineContentDecryptionModule {
    compose ContentDecryptionModule;
};

[Discoverable]
protocol PlayReadyContentDecryptionModule {
    compose ContentDecryptionModule;
};

[Discoverable]
protocol ContentDecryptionModuleFactory {
    /// The Factory interface should only be used if the client needs to inject
    /// the storage to be used by the CDM. The storage must be a unique location
    /// per origin/ provider.
    CreateClearKeyContentDecryptionModule(
        fuchsia.io.Directory data_directory,
        request<ClearKeyContentDecryptionModule> cdm);

    CreateWidevineContentDecryptionModule(
        fuchsia.io.Directory data_directory,
        request<WidevineContentDecryptionModule> cdm);

    CreatePlayReadyContentDecryptionModule(
        fuchsia.io.Directory data_directory,
        request<PlayReadyContentDecryptionModule> cdm);
};
