Copyright © 2025 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
이 명세서는 HTMLMediaElement
[HTML]
를 확장하여 암호화된 콘텐츠의 재생을 제어하는 API를 제공합니다.
이 API는 단순한 Clear Key 복호화부터(적절한 사용자 에이전트 구현이 주어질 경우) 고가치 비디오까지 다양한 사용 사례를 지원합니다. 라이선스/키 교환은 애플리케이션이 제어하므로 다양한 콘텐츠 복호화 및 보호 기술을 지원하는 견고한 재생 애플리케이션 개발을 용이하게 합니다.
이 명세서는 콘텐츠 보호나 디지털 권리 관리(Digital Rights Management) 시스템을 정의하지 않습니다. 대신, 그러한 시스템들뿐만 아니라 더 단순한 콘텐츠 암호화 시스템과 발견, 선택 및 상호작용하는 데 사용될 수 있는 공통 API를 정의합니다. 디지털 권리 관리의 구현은 이 명세서 준수를 위해 필수는 아닙니다: 공통 기준선으로 구현이 요구되는 것은 오직 Clear Key 시스템뿐입니다.
공통 API는 간단한 콘텐츠 암호화 기능 집합을 지원하며, 인증 및 권한 부여와 같은 애플리케이션 기능은 페이지 작성자에게 맡깁니다. 이는 암호화 시스템과 라이선스 또는 다른 서버 간의 별도 채널 통신을 가정하기보다, 콘텐츠 보호 시스템 특정 메시징이 페이지를 통해 중재되도록 요구함으로써 실현됩니다.
이 절은 문서가 공개될 당시의 상태를 설명합니다. 현재 W3C 출판물 목록과 이 기술 보고서의 최신 개정판은 W3C 표준 및 초안 색인에서 확인할 수 있습니다.
2017년 9월의 Recommendation 공개 이후 두 가지 새로운 기능이 추가되었습니다:
encryptionScheme
을
통한 암호화 방식 능력 감지.
getStatusForPolicy
()
메서드를 통해 HDCP 정책과 연관된 키의 상태를 조회하는 기능.
다른 기능의 포함은 Media 작업 그룹의 범위를 벗어납니다. 편집상 업데이트 외에도, 이 명세서에 이루어진 다른 실질적 변경 사항들은 이 명세서의 유지보수 문제를 다룹니다:
encrypted-media
식별자를 추가.
usable-in-future
를 아직 복호화에 사용할 수
없는 키를 위해 MediaKeyStatus
에 추가.
QuotaExceededError
를 반환하도록
변경.
MediaKeySessionClosedReason
를 세션 종료의
가능한 이유를 설명하기 위해 추가하고,
알고리즘을 그에 맞게 조정.
이전 버전 이후의 전체 변경 목록은 커밋을 참조하세요.
이 문서는 Media Working Group에 의해 권고 트랙을 사용한 Working Draft로 발행되었습니다.
Working Draft로의 게시가 W3C 및 그 구성원들의 승인이나 지지를 의미하지는 않습니다.
이 문서는 초안 문서이며 언제든지 업데이트, 교체 또는 다른 문서로 대체될 수 있습니다. 진행 중인 작업 외의 다른 목적으로 이 문서를 인용하는 것은 적절하지 않습니다.
이 문서는 다음을 따르는 그룹에 의해 작성되었습니다. W3C 특허 정책.
W3C는 그룹의 산출물과 관련하여 이루어진 모든 특허 공개에 대한 공개 목록을 유지하고 있으며; 해당 페이지에는 특허 공개를 위한 지침도 포함되어 있습니다. 개인이 해당 특허가 핵심 청구(essential claim)을 포함한다고 실제로 알고 있다고 믿는 경우, 해당 정보는 W3C 특허 정책의 섹션 6에 따라 공개되어야 합니다.
이 문서는 2025년 8월 18일 W3C 프로세스 문서의 적용을 받습니다.
이 절은 비규범적입니다.
이 명세서는 스크립트가 콘텐츠 보호 메커니즘을 선택하고, 라이선스/키 교환을 제어하며, 맞춤형 라이선스 관리 알고리즘을 실행할 수 있도록 합니다. 각 사용 사례마다 사용자 에이전트 측의 변경을 요구하지 않고도 광범위한 사용 사례를 지원합니다. 이를 통해 콘텐츠 제공자는 모든 장치에서 동작하는 단일 애플리케이션 솔루션을 개발할 수 있습니다.
지원되는 콘텐츠는 컨테이너별 "공통 암호화(common encryption)" 명세에 따라 암호화되며, 이는 여러 키 시스템에서 사용 가능하게 합니다. 지원되는 콘텐츠는 암호화되지 않은
컨테이너를 가지므로 메타데이터를 애플리케이션에 제공할 수 있고 다른 HTMLMediaElement
기능과의 호환성을 유지합니다.
구현자들은 이 명세서에서 설명하는 보안 및 개인정보 위협과 우려사항에 대한 완화책을 주의 깊게 살펴야 합니다. 특히, 보안 및 개인정보 요구사항은 Key System 및 그 구현의 보안·개인정보 특성을 아는 것 없이는 충족될 수 없습니다. 8. Implementation Requirements에는 기저의 Key System 구현의 통합 및 사용과 관련된 보안 및 개인정보 규정이 포함되어 있습니다. 10. Security는 입력 데이터나 네트워크 공격과 같은 외부 위협에 중점을 둡니다. 11. Privacy는 사용자별 정보의 처리와 사용자에게 자신의 개인정보에 대한 적절한 통제권을 제공하는 것에 중점을 둡니다.
이 명세서는 미디어 데이터의 출처와 독립적이지만, 많은 구현체가 Media Source Extensions를 통해 제공되는 미디어 데이터만 복호화하는 것을 지원한다는 점을 저자들이 인지해야 합니다 [MEDIA-SOURCE].
이 API를 사용해 구현한 일반적인 스택은 아래에 나와 있습니다. 이 다이어그램은 예시 흐름을 보여주며; 다른 API 호출과 이벤트 조합도 가능합니다.
Content Decryption Module (CDM)은 하나 이상의 Key Systems에 대해 복호화를 포함한 기능을 제공하는 클라이언트 구성 요소입니다.
구현체는 CDM의 구현을 분리하거나 사용자 에이전트와 별도로 처리할 수도 있고 그렇지 않을 수도 있습니다. 이는 API와 애플리케이션에 투명합니다.
Key System은 복호화 메커니즘 및/또는 콘텐츠 보호 제공자를 지칭하는 일반적인 용어입니다. Key System 문자열은 Key System을 고유하게 식별합니다. 이 문자열들은 사용자 에이전트가 CDM을 선택하고 키 관련 이벤트의 출처를 식별하는 데 사용됩니다. 사용자 에이전트는 MUST 공통 Common Key Systems를 지원해야 합니다. 사용자 에이전트는 또한 대응하는 Key System 문자열을 가진 추가 CDMs를 제공할 수 있습니다.
Key System 문자열은 항상 역도메인(reverse domain name) 형식입니다. Key System 문자열은 대소문자 구분 매칭으로 비교됩니다. RECOMMENDED로서 CDMs는 단순한 소문자 ASCII 키 시스템 문자열을 사용하는 것이 좋습니다.
예: "com.example.somesystem".
주어진 시스템(예시의 "somesystem") 내에서 하위 시스템이 키 시스템 공급자에 의해 정의될 수 있습니다. 예: "com.example.somesystem.1" 및 "com.example.somesystem.1_5". 키 시스템 공급자는 이러한 문자열들이 비교 및 검색에 사용되므로 비교하기 쉽고 구조가 합리적으로 단순하게 유지되도록 고려해야 합니다.
Key Session(또는 간단히 Session)은 CDM과의 메시지 교환을 위한 컨텍스트를 제공하며, 그 결과 키가 CDM에 제공됩니다. 세션은 MediaKeySession
객체로 구현됩니다. 각 Key Session은 Initialization Data의 단일 인스턴스와 연관되며, 이는 generateRequest
()
호출에서 제공됩니다.
각 Key Session은 단일 MediaKeys
객체와 연관되며, 해당 MediaKeys
객체와 연관된 미디어 요소만 세션과 연관된 키에 접근할 수 있습니다.
다른 MediaKeys
객체들, CDM 인스턴스들, 및 미디어 요소들은 세션이나 그 키들에
접근하거나 사용해서는 MUST NOT 합니다. 세션이 종료되면, Usable for decryption 상태가 아니게 되며, MediaKeySession
객체가 파괴되는 경우도 포함됩니다.
명시적으로 저장되지 않은 모든 라이선스 및 키는 Key Session이 닫힐 때 MUST 파기되어야 합니다.
Key IDs는 세션 내에서 고유해야 합니다.
Session ID는 CDM가 생성한 고유 문자열 식별자로, 애플리케이션이 MediaKeySession
객체를 식별하는 데 사용할 수 있습니다.
사용자 에이전트와 CDM이 새 세션을 성공적으로 생성할 때마다 새로운 Session ID가 생성됩니다.
각 Session ID는 그것이 생성된 브라우징 컨텍스트 내에서 SHALL 고유해야 합니다.
Is persistent session type? 알고리즘이 true
를 반환하는 세션 유형의 경우, Session ID는 브라우징 세션을 포함하여 시간에
걸쳐 해당 origin 내에서 MUST 고유해야 합니다.
기저의 콘텐츠 보호 프로토콜이 반드시 Session ID를 지원할 필요는 없습니다.
별도의 명시가 없는 한, key는 미디어 데이터 내의 블록을 복호화하는 데 사용될 수 있는 복호화 키를 가리킵니다. 각 키는 key ID로 고유하게 식별됩니다. 키는 세션과 연관되어 CDM에 제공됩니다. (동일한 키가 여러 세션에 존재할 수
있습니다.) 이러한 키는 update
()
호출을 통해서만 CDM에 제공되어야 합니다. (나중에 저장된 세션 데이터의 일부로 load
()
에 의해 로드될 수 있습니다.)
저자들은 의미있게 다른 정책을 적용해야 하는 각 스트림 집합을 서로 다른 키(및 key ID)로 암호화하는 것이 바람직합니다. 예를 들어, 정책이 두 비디오 해상도 간에 다를 수 있다면, 한 해상도를 포함하는 스트림은 다른 해상도를 포함하는 스트림을 암호화하는 데 사용된 키와 동일한 키로 암호화되어서는 안 됩니다. 암호화된 경우, 오디오 스트림은 어떤 비디오 스트림과도 동일한 키를 사용해서는 SHOULD NOT 합니다. 이는 클라이언트 간에 집행 및 호환성을 보장하는 유일한 방법입니다.
키는 CDM가 해당 키가 현재 하나 이상의 미디어 데이터 블록을 복호화하는 데 사용 가능하다고 확신할 때 복호화에 사용 가능하다고 간주됩니다.
예: 라이선스가 만료된 경우 해당 키는 복호화에 사용 가능하지 않습니다. 라이선스가 만료되지 않았더라도 출력 보호와 같은 다른 조건들이 현재 충족되지 않으면 키는 복호화에 사용 가능하지 않습니다.
key는 옥텟 시퀀스인 key ID와 연관되며, 이는 키를 고유하게 식별합니다. 컨테이너는 미디어 데이터 내의 블록 또는 블록 집합을 복호화할 수 있는 키의 ID를 지정합니다. Initialization Data는 미디어 데이터를 복호화하는 데 필요한 키들을 식별하기 위한 key ID들을 포함할 수 있습니다. 그러나 Initialization Data가 미디어 데이터나 미디어 리소스에서 사용되는 모든 key ID를 포함해야 한다는 요구는 없습니다. Licenses가 CDM에 제공될 때, 각 키는 key ID와 연관되어 CDM가 암호화된 미디어 블록을 복호화할 때 적절한 키를 선택할 수 있게 합니다.
키는 세션에 알려진 것으로 간주되는데, 이는 CDM의 세션 구현이 해당 키에 관한 어떤 정보(특히 key
ID)를 포함하고 있음을 의미합니다. 실제 키 값이 알려져 있거나 사용 가능 여부와는 무관합니다. 알려진 키는 keyStatuses
속성을 통해 노출됩니다.
키는 만료와 같이 사용 불가능해진 이후에도 알려진 것으로 간주됩니다. 키는 세션에서 명시적으로 제거되고 라이선스 해제 메시지가 확인될 때에만 알려지지 않게 됩니다.
예: update
()
호출이 이전에 포함된
키를 포함하지 않는 새 라이선스를 제공하고 이전 라이선스를 교체하라는 지시를 포함하는 경우 키는 알려지지 않게 될 수 있습니다.
라이선스는 하나 이상의 key(s)와(각각은 key ID와 연관됨) 키 사용에 관한 기타 정보를 포함할 수 있는 키 시스템 특정 상태 정보입니다.
Key Systems는 일반적으로 라이선스 요청 메시지를 구성하기 전에 스트림 복호화에 대한 정보를 포함하는 초기화 데이터 블록을 필요로 합니다. 이 블록은 단순한 키나 콘텐츠 ID일 수도 있고 더 복잡한 구조를 가질 수도 있습니다. 초기화 데이터는 복호화에 필요한 key(s)를 고유하게 식별할 수 있어야 합니다.
Initialization Data는 CDM이 라이선스 요청을 생성하는 데 사용하는 컨테이너별 데이터의 일반 용어입니다.
초기화 데이터의 형식은 컨테이너 유형에 따라 달라지며, 컨테이너는 여러 형식의 초기화 데이터를 지원할 수 있습니다. Initialization Data Type은 동반되는 Initialization Data의 형식을 나타내는 문자열입니다. Initialization Data Type 문자열은 항상 대소문자 구분 매칭됩니다. 초기화 데이터 유형 문자열은 소문자 ASCII 문자열로 하는 것이 RECOMMENDED됩니다.
Encrypted Media Extensions Initialization Data Format Registry는 각 형식에 대한 명세로 Initialization Data Type 문자열을 매핑하는 방법을 제공합니다.
사용자 에이전트가 미디어 데이터에서 Initialization Data를 만나면, 해당 Initialization Data를 initData
속성으로 애플리케이션에 제공하는데, 이는
이벤트의 일부입니다. 사용자 에이전트는
Initialization Data의 내용을 그 시점에 저장하거나 사용할 수 없습니다. 애플리케이션은 Initialization Data를 CDM에 encrypted
generateRequest
()
를
통해 제공합니다. 사용자 에이전트는 Initialization Data를 다른 방식으로 CDM에 제공해서는 안 됩니다.
Initialization Data는 주어진 스트림 집합 또는 미디어 데이터에 대해 고정된 값이어야 합니다. 또한 주어진 스트림 집합 또는 미디어 데이터를 재생하는 데 필요한 키와 관련된 정보만 포함해야 하며, 애플리케이션 데이터, 클라이언트 특정 데이터, 사용자 특정 데이터 또는 실행 가능한 코드를 포함해서는 안 됩니다.
Initialization Data는 Key System 특정 데이터나 값을 포함해서는 SHOULD NOT 합니다. 구현체는 자신이 지원하는 각 Initialization Data Type에 대해 [EME-INITDATA-REGISTRY]에 정의된 공통 형식을 지원해야 합니다.
독점 형식/콘텐츠의 사용은 권장되지 않으며, 오직 독점 형식만 지원하거나 사용하는 것은 강력히 권장되지 않습니다. 독점 형식은 기존 콘텐츠나 기존 클라이언트 장치에서만 사용되어야 합니다.
두 개 이상의 식별자 또는 다른 값은 동일하거나 합리적인 시간과 노력을 들여 상호 연관시키거나 연관할 수 있는 경우에 associable하다고 합니다. 그렇지 않으면 그 값들은 non-associable입니다.
예를 들어, 다음과 같은 방식으로 생성된 값들은 associable입니다:
쉽게 복원 가능한 해시 함수 사용.
접두사나 다른 부분 집합을 공유.
임의 값 N을 N+10으로 교체.
고정값과 XOR(역으로 쉽게 복원 가능하기 때문).
반대로, 완전히 관련이 없거나 암호학적으로 구분되는 값(예: 강력한 비가역 해시 함수 사용)은 non-associable입니다.
두 개 이상의 식별자 또는 다른 값은 associable by an entity라 불리려면, 참조된 엔티티(또는 엔티티 집합)가 추가 엔티티의 참여 없이 합리적인 시간과 노력으로 그것들을 연관시킬 수 있어야 합니다. 그렇지 않으면 그 값들은 non-associable by an entity입니다.
두 개 이상의 식별자 또는 값이 non-associable by the application이라면, 이는 해당 값들이 non-associable by an entity임을 의미하며, 그 엔티티는 애플리케이션, 다른 모든 애플리케이션, 그리고 애플리케이션이 사용하는 서버 또는 통신하는 엔티티들을 포함하는 집합입니다. 그렇지 않으면 그 값들은 associable by the application로 간주되며, 이는 금지됩니다.
Distinctive Value는 많은 사용자 또는 클라이언트 장치 집단에서 공유되지 않는 값, 데이터의 소유를 암시하는 정보, 또는 관찰 가능한 행동이나 타이밍으로, 메모리나 영속 저장소에 있을 수 있습니다.
Distinctive Value의 예는 다음과 같지만 이에 국한되지는 않습니다:
기타 식별자
기타 세션 데이터
Distinctive Value는 일반적으로 사용자나 클라이언트 장치에 대해 고유하지만, 반드시 엄밀히 고유할 필요는 없습니다. 예를 들어 소수의 사용자 간에 공유되는 값도 여전히 distinctive할 수 있습니다.
Permanent Identifier는 어떤 방식으로든 지울 수 없거나 사용자가 제거, 재설정 또는 변경하기 어려운 값, 데이터, 혹은 그 소유를 암시하는 정보 또는 관찰 가능한 행동/타이밍을 말합니다. 여기에는 다음이 포함되지만 이에 국한되지 않습니다:
하드웨어 또는 하드웨어 기반 식별자
공장 출하시 하드웨어에 프로비저닝된 값
운영체제 설치 인스턴스에서 파생되거나 연관된 값
사용자 에이전트 설치 인스턴스에서 파생되거나 연관된 값
CDM 또는 다른 소프트웨어 구성 요소와 연관되거나 그로부터 파생된 값
클라이언트에서 생성되었더라도 구성 파일 또는 유사한 준영구 데이터에 있는 값
클라이언트 또는 다른 사용자 계정 값
Distinctive Permanent Identifier는 Permanent Identifier 중에서 distinctive한 것을 말합니다.
클라이언트 외부로 노출될 때, Distinctive Permanent Identifiers 및 그로부터 파생되거나 관련된 값들은 MUST 암호화되어야 합니다. Distinctive Permanent Identifiers는 암호화된 형태라도 애플리케이션에 노출되어서는 MUST NOT 합니다.
Distinctive Permanent Identifier는 일반적으로 사용자나 클라이언트 장치에 대해 고유하지만, 엄밀히 고유할 필요는 없습니다. 예를 들어 소수의 사용자 간에 공유되는 Distinctive Permanent Identifier도 여전히 distinctive할 수 있습니다.
Distinctive Permanent Identifier는 이 명세서의 범위 내에서 파생되거나 생성되지 않으므로 Distinctive Identifier가 아닙니다.
distinctiveIdentifier
는 Distinctive Permanent Identifiers의 사용 여부를 제어합니다. 특히, Distinctive Permanent Identifiers는 distinctiveIdentifier
멤버의 값이
MediaKeySystemAccess
에서 "required
"로 설정된 경우에만 사용될 수
있습니다.
Distinctive Identifier는 암호화되거나 불투명한 형태를 포함한 값으로, 클라이언트 외부의 어떤 엔티티가 웹 플랫폼에서 사용자가 기대할 수 있는 수준을 초과하여 값들을 연관시키거나 결합할 수 있는 경우를 뜻합니다(예: 쿠키 및 기타 사이트 데이터). 예를 들어, 애플리케이션 이외의 엔티티에 의해 연관될 수 있는 값들(예: 개별화 요청에 공통 값이 포함되어 중앙 서버가 여러 오리진에 걸쳐 값을 연관할 수 있는 경우)은 Distinctive Identifier가 될 수 있습니다.
애플리케이션에 노출되는 Distinctive Identifiers는 암호화된 형태라도 MUST 식별자 요구사항을 준수해야 하며, 여기에는 암호화, 오리진 및 프로필별 고유성, 및 삭제 가능성이 포함됩니다.
Distinctive Identifier의 생성이나 사용은 애플리케이션의 이 명세서 정의된 API 사용에 의해 촉발되지만, 식별자가 애플리케이션에 제공될 필요는 없습니다. (Distinctive Permanent Identifier(s))는 암호화되었더라도 애플리케이션에 제공되어서는 MUST NOT 합니다.
distinctiveIdentifier
는 Distinctive Identifiers의 사용 여부를 제어합니다. 구체적으로, Distinctive Identifiers는 distinctiveIdentifier
멤버의 값이
MediaKeySystemAccess
에서 "required
"로 설정된 경우에만 사용될 수
있습니다.
Distinctive Identifier는 다음의 모든 기준을 만족하는 값, 데이터 조각, 데이터 소유의 암시, 또는 관찰 가능한 행동/타이밍입니다:
그것은 distinctive합니다.
Distinctive Identifier는 일반적으로 사용자나 클라이언트 장치에 대해 고유하지만, 엄밀히 고유할 필요는 없습니다. 예: 소수의 사용자 간에 공유되는 식별자도 여전히 distinctive할 수 있습니다.
그것 자체, 그것에 대한 정보, 또는 그것으로부터 파생되거나 관련된 값들이 암호화된 형태라도 클라이언트 외부로 노출됩니다(예: 애플리케이션, 라이선스, individualization 또는 기타 서버에 제공).
다음 중 하나 이상의 속성을 갖습니다:
하나 이상의 Distinctive Permanent Identifier(s)로부터 파생됩니다.
그 값을 생성한 과정(개별화, 프로비저닝 등)이 하나 이상의 Distinctive Permanent Identifier(s) 또는 다른 Distinctive Identifier를 사용하거나 포함했습니다.
그것은 clearable하지만 쿠키 및 기타 사이트 데이터와 함께 삭제되지 않을 수 있습니다.
예: OS 수준 메커니즘과 같은 사용자 에이전트 외부의 메커니즘을 통해.
애플리케이션에 노출되는 값에 대해 규범적으로 금지된 기타 속성들은 다음을 포함하지만 이에 국한되지 않습니다:
그것이 Distinctive Permanent Identifier인 경우.
그것이 not clearable인 경우.
식별자 삭제 후 생성된 값이 이전 값과 애플리케이션에 의해 연관 가능한 경우.
값들이 오리진 및 프로필별로 고유하지 않은 경우.
서로 다른 오리진의 값들이 애플리케이션에 의해 연관 가능한 경우.
규범적으로 금지된 값들의 예는 다음과 같지만 이에 한정되지 않습니다:
모든 오리진에 대해 사용되는 단일 하드웨어 기반 값.
모든 오리진에 대해 사용되는 단일 랜덤 기반 값.
모든 오리진에 대해 사용되는 단일 개별화 프로세스에서 얻은 값.
위 값들 중 일부 또는 전부를 포함하는 값.
여러 오리진에서 사용되지만 모든 오리진에서 사용되지는 않는 단일 값.
도메인의 모든 오리진에 대해 사용되는 단일 값(식별자는 오리진별이어야 함).
사전 프로비저닝된 오리진 특정 값.
역으로 쉽게 복원 가능한 수단으로 생성된 값들(예: XOR하거나 오리진의 일부를 고정값과 통합하는 등)으로, 이는 애플리케이션에 의해 연관 가능합니다.
Distinctive Identifier는 보통 생성한 엔티티에 의해 연관 가능하지만, 애플리케이션에 의해 연관 가능해서는 안 됩니다. 즉, 이러한 상호 연관은 원래 Distinctive Identifier 값을 생성한 엔티티(예: individualization 서버)만이 할 수 있어야 합니다. Distinctive Permanent Identifiers에 접근할 수 있는 엔티티는 이 능력을 애플리케이션에 노출해서는 MUST NOT 하며, 다른 엔티티나 제3자에게 이러한 상관관계를 노출하지 않도록 주의해야 합니다.
Distinctive Identifiers의 예는 다음과 같지만 이에 국한되지 않습니다:
키 요청에 포함되는 바이트 시퀀스가 다른 클라이언트 장치의 시퀀스와 다르며, Distinctive Permanent Identifier로부터 직접 또는 간접적으로 기반하거나 획득된 경우.
키 요청에 포함된 공개 키가 다른 클라이언트 장치에서 포함된 공개 키와 다르며 Distinctive Permanent Identifier로부터 직접 또는 간접적으로 기반하거나 획득된 경우.
다른 클라이언트 장치가 갖지 않은 개인 키의 소유 증명(예: 일부 데이터를 서명)으로, Distinctive Permanent Identifier로부터 직접 또는 간접적으로 기반하거나 획득된 경우.
그러한 키의 식별자.
첫 번째 값이 직접적으로 노출되지 않더라도 노출되는 다른 값을 도출하기 위해 사용되는 값.
다른 Distinctive Identifier로부터 도출된 값.
individualization 서버에 보고된 랜덤 값과 Distinctive Permanent Identifier와 함께 보고되었거나, 그런 서버가 Distinctive Permanent Identifier를 제공한 후 제공한 랜덤 값.
공장에서 하드웨어 장치에 프로비저닝된 고유 값에서 도출된 값.
공장에 내장된 고유 하드웨어 값(예: MAC 주소 또는 일련번호)이나 소프트웨어 값(예: 운영체제 설치 인스턴스 또는 운영체제 사용자 계정 이름)에서 도출된 값.
CDM 바이너리 또는 CDM이 사용하는 기타 파일에 포함된 고유 값에서 도출된 값.
Distinctive Identifier가 아닌 것들의 예:
설치 기반이 큰 경우 특정 CDM 버전의 모든 복사본에 공통으로 포함된 공개 키.
고유하지만 한 세션에서만 사용되는 nonce 또는 일시적 키.
개별화나 유사한 과정을 통해 외부로 노출되지 않는 값.
비디오 파이프라인과 CDM 간의 증명에 사용되는 장치 고유 키로, 해당 증명이 애플리케이션으로 유출되지 않고 대신 CDM 자체가 Distinctive Identifier가 되지 않는 키를 사용하여 새로운 증명을 만드는 경우.
쿠키 등의 브라우징 데이터를 포함한 데이터와 함께 완전히 삭제/삭제 가능하게 되고, 이후 중앙 서버(예: individualization 서버)조차도 다시 연관시킬 수 없는 방식으로 대체되는 값이며, 또한 다음 중 하나 이상에 해당하는 경우:
값 생성에 Distinctive Permanent Identifier나 Distinctive Identifier가 관여하지 않은 경우.
시스템 입력 없이 생성된 랜덤 값인 경우.
다른 Distinctive Identifier의 사용 또는 지식 없이 서버에서 제공된 값인 경우.
구현, 구성, 인스턴스 또는 객체가 uses Distinctive Identifier(s)라면, 그 수명 주기 동안 또는 관련 엔티티의 수명 주기 동안 하나 이상 Distinctive Identifier(s) 또는 그에 관한 정보, 또는 그로부터 파생되거나 관련된 값을 클라이언트 외부로(암호화된 형태라도) 노출합니다. 이는 애플리케이션 및/또는 라이선스, individualization 서버 등으로 값을 제공하는 것을 포함합니다.
구현, 구성, 인스턴스 또는 객체가 uses Distinctive Permanent Identifier(s)라면, 그 수명 주기 동안 하나 이상 Distinctive Permanent Identifier(s) 또는 그에 관한 정보, 또는 그로부터 파생되거나 관련된 값을 클라이언트 외부로(암호화된 형태라도) 노출합니다. 이는 개별화 서버로 값을 제공하는 것을 포함합니다. 이러한 값들은 애플리케이션에 제공되어서는 MUST NOT 합니다.
구현, 구성, 인스턴스 또는 객체가 uses Distinctive Identifier(s) or Distinctive Permanent Identifier(s)라면, 이는 uses Distinctive Identifier(s) 및/또는 uses Distinctive Permanent Identifier(s)를 포함합니다.
distinctiveIdentifier
는 Distinctive Identifiers 및 Distinctive Permanent Identifiers의 사용 여부를 제어합니다. 구체적으로, 이러한 식별자들은 distinctiveIdentifier
멤버의 값이
MediaKeySystemAccess
에서 "required
"로 설정된 경우에만 사용될 수
있습니다.
재생 중에 포함된 미디어 데이터는 임베딩된 origin의 스크립트에
노출됩니다. API가 Initialization Data를
이벤트에서 제공하려면, 미디어 데이터는 임베딩
페이지와 CORS-same-origin이어야
합니다. 미디어 데이터가 임베딩 문서와 교차 출처인 경우, 저자들은 encrypted
crossOrigin
속성을 HTMLMediaElement
에 사용하고
미디어 데이터 응답에 CORS 헤더를 포함시켜 CORS-same-origin으로
만들어야 합니다.
재생 중에 포함된 미디어 데이터는 임베딩된 origin의 스크립트에
노출됩니다. API가 Initialization Data를
이벤트에서 제공하려면, 미디어 데이터는 Mixed
Content가 아니어야 합니다 [MIXED-CONTENT].
encrypted
Time은 ECMAScript Time Values and Time Range에 표현된 것과 동등해야 합니다 [ECMA-262].
그러한 시간이 존재하지 않거나 불확정한 경우 Time은 NaN
이 됩니다. Infinity
값을 가져서는 안 됩니다.
Time은 일반적으로 밀리초 정확도로 시점을 나타내지만, 그것만으로 충분한 정의가 되지는 않습니다. 정의된 Time Values 및 Time Range 참조는 다른 중요한 요구사항을 추가합니다.
만료 시간은 키가 더 이상 usable for decryption하지 않게 되는 time입니다.
주어진 머신의 사용자 에이전트는 애플리케이션 가시적 상태와 데이터에 대해 독립적으로 동작하는 다양한 컨텍스트나 모드 또는 임시 상태에서 실행을 지원할 수 있습니다. 특히, 모든 저장된 데이터는 독립적인 것으로 기대됩니다. 이 명세서에서는 이러한 독립적인 컨텍스트나 모드를 "Browsing Profiles"라고 부릅니다.
이러한 독립적 컨텍스트의 예로는 사용자 에이전트가 다른 운영체제 사용자 계정에서 실행되거나 단일 계정에 대해 여러 독립 프로필을 정의하는 기능을 제공하는 경우가 있습니다.
이 절에서는 Key System에 대한 접근을 얻는 메커니즘을 정의합니다. 요청에 기능을 포함시키면 기능 탐지가 가능해집니다.
알고리즘의 단계는 약속(promise)이 거부될 때 항상 중단됩니다.
requestMediaKeySystemAccess
()
는 문자열
encrypted-media
로
식별되는
정책
제어 기능입니다.
그 기본
허용목록은 'self'
입니다 [PERMISSIONS-POLICY].
WebIDLenum MediaKeysRequirement
{
"required
",
"optional
",
"not-allowed
"
};
MediaKeysRequirement
열거형은 다음과 같이 정의됩니다:
열거형 설명 | |
---|---|
required
|
|
optional
|
|
not-allowed
|
|
WebIDLdictionary MediaKeySystemConfiguration
{
DOMString label
= "";
sequence<DOMString> initDataTypes
= [];
sequence<MediaKeySystemMediaCapability
> audioCapabilities
= [];
sequence<MediaKeySystemMediaCapability
> videoCapabilities
= [];
MediaKeysRequirement
distinctiveIdentifier
= "optional";
MediaKeysRequirement
persistentState
= "optional";
sequence<DOMString> sessionTypes
;
};
MediaKeySystemConfiguration
사전은 다음
멤버들을 포함합니다:
label
(DOMString
타입, 기본값
""
)
MediaKeySystemConfiguration
가 getConfiguration
()
메서드로 반환될 때 보존되는 선택적 라벨입니다.
MediaKeySystemAccess
.
initDataTypes
(sequence<DOMString
>
타입, 기본값 []
)
audioCapabilities
(sequence<MediaKeySystemMediaCapability
>
타입, 기본값 []
)
videoCapabilities
요소는 비어 있으면 안 됩니다.
videoCapabilities
(sequence<MediaKeySystemMediaCapability
>
타입, 기본값 []
)
audioCapabilities
요소는 비어 있으면 안 됩니다.
distinctiveIdentifier
(MediaKeysRequirement
타입, 기본값
"optional"
)
이 멤버가 "not-allowed
"일 경우, 구현은
Distinctive
Identifier(s) 또는 Distinctive Permanent Identifier(s) 사용을 이 구성에서 생성된 모든 객체의 연산에 대해 절대(MUST NOT) 사용해서는 안 됩니다.
persistentState
(MediaKeysRequirement
타입, 기본값
"optional"
)
이 멤버가 "not-allowed
"일 때, CDM은 이 객체의 Document의 애플리케이션이나 origin과 관련된
어떤 상태도 영구 저장해서는 절대(MUST NOT) 안 됩니다.
이 멤버의 목적상, 영구 상태는 Key System 구현에 의해 제어되는 영구 고유
식별자(Distinctive
Identifiers)를 포함하지 않습니다. distinctiveIdentifier
는
이 요구사항을 독립적으로 반영합니다.
영구 상태가 지원되지 않을 때는 "temporary
" 세션만 생성할 수 있습니다.
"temporary
" 세션의 경우, 상태
저장의 필요성과 가능성은 Key System 구현에 따라 다르며, 사용되는 기능에 따라 달라질 수 있습니다.
"temporary
"가 아닌 세션을
생성하려는 애플리케이션은 required
로 이 멤버를 설정하여
requestMediaKeySystemAccess
()
를
호출해야 합니다.
sessionTypes
(sequence<DOMString
>
타입)
MediaKeySessionType
들의 목록입니다. 모든 값은 지원되어야
합니다.
이 멤버가 사전에 존재하지 않을(not present) 경우, requestMediaKeySystemAccess
()
에
전달될 때, 이 사전은 이 멤버가
[ "
로 설정된 것처럼 처리됩니다.
temporary
"
]
구현체는 이 사전에 멤버를 추가해서는 권장되지 않음(SHOULD NOT)니다. 만약 멤버가 추가된다면, 반드시(MUST) MediaKeysRequirement
타입이어야 하며, "optional
"을 기본값으로 갖는 것이 권장됨(RECOMMENDED)니다. 이는 애플리케이션과 클라이언트 조합의 범위를 넓게 지원하기 위함입니다.
사용자 에이전트 구현이 인식하지 못하는 사전 멤버는 [WEBIDL]에 따라 무시되며 requestMediaKeySystemAccess
()
알고리즘에서 고려되지 않습니다. 애플리케이션이 비표준 사전 멤버를 사용할 경우, 해당 멤버가 포함된 구성에서 사용자 에이전트 구현이 구성을 거부할 것이라고 절대(MUST NOT) 기대해서는 안 됩니다.
이 사전은 CDM에 상태나 데이터를 전달하는 데 절대(MUST NOT) 사용해서는 안 됩니다.
WebIDLdictionary MediaKeySystemMediaCapability
{
DOMString contentType
= "";
DOMString? encryptionScheme
= null;
DOMString robustness
= "";
};
MediaKeySystemMediaCapability
멤버
contentType
타입 DOMString
, 기본값
""
애플리케이션은 권장됨(SHOULD)으로, MIME 타입이 반드시 코덱 및 코덱 제약을 명시하도록 해야 합니다(예: [RFC6381] 참조). 만약 컨테이너에 의해 규범적으로 암시되지 않는다면 반드시 명시해야 합니다.
encryptionScheme
타입 DOMString
, 기본값
null
content type에 연관된 암호화 방식. 값이 null이거나 존재하지 않으면, 애플리케이션에서 특정 암호화 방식이 필요하지 않으므로 모든 암호화 방식을 허용한다는 의미입니다.
이 필드를 인지하는 애플리케이션은 권장됨(SHOULD)으로, 필요한 암호화 방식을 명시해야 합니다. 서로 다른 암호화 방식은 일반적으로 서로 호환되지 않습니다. 애플리케이션이 "아무 암호화 방식이나" 허용하는 것은 비현실적이지만, 기본값인 null과 null의 해석("아무거나")은 인지하지 못하는 애플리케이션에 대한 하위 호환성 및 오래된 사용자 에이전트용 폴리필 경로를 제공합니다.
빈 문자열은 null 또는 미존재와 다르므로, 인식되지 않는 암호화 방식으로 처리됩니다.
robustness
타입 DOMString
, 기본값
""
content type에 연관된 견고성(robustness) 수준. 빈 문자열은 해당 content type을 복호화 및 디코딩할 수 있는 능력이 아무거나 허용됨을 의미합니다.
구현체는 반드시(MUST) CDM을 해당 MediaKeySystemAccess
객체의 구성에서 지정된 견고성 수준을 최소한 지원하도록 설정해야 합니다. MediaKeys
객체를 생성할 때 사용됨. CDM의 정확한 구성은 구현별이며, 구현체는 허용함(MAY)으로, 구성에서 가장 높은 견고성 수준을 사용할 수 있습니다(더 높은 수준이 있을지라도).
빈 문자열만 지정된 경우, 구현체는 구현에서 지원하는 가장 낮은 견고성 수준을 사용하도록 설정할 수 있습니다.
애플리케이션은 권장됨(SHOULD)으로, 예상치 못한 클라이언트 호환성 문제를 방지하기 위해 필요한 견고성 수준을 반드시 명시하는 것이 좋습니다.
이 객체가 나타내는 기능이 지원되는 것으로 간주되려면,
contentType
은 빈 문자열이 아니어야 하며(MUST NOT), 코덱 전체 값이 robustness
와 함께 반드시(MUST) 지원되어야 합니다.
여러 코덱 중 하나가 허용된다면, 각 코덱별로 이 사전의 별도 인스턴스를 사용하세요.
MediaKeySystemAccess
객체는 Key System에 대한 접근을 제공합니다.
WebIDL[Exposed=Window, SecureContext] interface MediaKeySystemAccess
{
readonly attribute DOMString keySystem
;
MediaKeySystemConfiguration
getConfiguration
();
Promise<MediaKeys
> createMediaKeys
();
};
keySystem
타입 DOMString
, 읽기전용
getConfiguration()
requestMediaKeySystemAccess
()
알고리즘에 의해 선택된 지원되는 구성 옵션 조합을 반환합니다.
반환된 객체는 약속을 이행한 해당 호출의 requestMediaKeySystemAccess
()
호출에 전달된 첫 번째 만족 가능한 MediaKeySystemConfiguration
구성의 비엄격 부분집합(암시적 기본값 포함)입니다. 해당 구성에 명시되지 않은 기능(암시적 기본값 외)을 위한 값은 포함하지 않으므로 Key System 구현의 모든 기능을 반영하지 않을 수 있습니다. 구성 내의 모든 값은 어떤
조합으로든 사용할 수 있습니다. MediaKeysRequirement
타입의 멤버는 해당 기능이
어떤 조합에서 필수인지 반영합니다. "optional
" 값은 가지지 않습니다.
이 메서드가 호출되면, 사용자 에이전트는 다음 단계를 반드시(MUST) 실행해야 합니다:
이 객체의 configuration 값을 반환합니다.
이 메서드가 호출될 때마다 configuration로부터 새로운 객체가 생성 및 초기화됩니다.
애플리케이션에서 encryptionScheme
를 제공하지 않은 경우에도, 누적된 configuration에는 encryptionScheme
필드가 반드시 null
값으로 포함되어야 하며, 이를 통해 polyfill에서 사용자 에이전트가 해당 필드를 지원하는지 특정
값을 지정하지 않고도 감지할 수 있습니다.
createMediaKeys()
keySystem에 대한 새로운 MediaKeys
객체를 생성합니다.
이 메서드가 호출되면, 사용자 에이전트는 다음 단계를 반드시(MUST) 실행해야 합니다:
promise를 새 약속으로 둡니다.
다음 단계를 병렬로 실행합니다:
configuration을 이 객체의 configuration 값으로 둡니다.
use distinctive identifier를 configuration의 distinctiveIdentifier
멤버 값이 "required
"이면
true
, 그 외에는 false
로 둡니다.
persistent state allowed를 configuration의 persistentState
멤버 값이 "required
"이면
true
, 그 외에는 false
로 둡니다.
필요하다면, 이 객체의 cdm implementation 값으로 표시되는 Key System 구현을 로드 및 초기화합니다.
instance를 이 객체의 cdm implementation 값으로 표시되는 Key System 구현의 새 인스턴스로 둡니다.
instance를 configuration을 사용해 Key System 기능을 활성화, 비활성화, 선택할 수 있도록 초기화합니다.
use distinctive identifier가 false
이면,
instance가 Distinctive
Identifier(s) 및 Distinctive Permanent Identifier(s) 사용을 하지 못하도록 합니다.
persistent state allowed가 false
이면,
instance가 이 객체의 origin이나
Document와 관련된
애플리케이션 상태를 영구 저장하지 못하도록 합니다.
앞선 단계 중 하나라도 실패하면, promise를 새로운 DOMException
으로
적절한 에러 이름을 포함하여 거부합니다.
media keys를 새 MediaKeys
객체로 만들고, 다음과 같이
초기화합니다:
use distinctive identifier 값을 use distinctive identifier로 둡니다.
persistent state allowed 값을 persistent state allowed로 둡니다.
supported session types 값을 configuration의 sessionTypes
멤버의 값으로 둡니다.
cdm implementation 값을 이 객체의 cdm implementation 값으로 둡니다.
cdm instance 값을 instance로 둡니다.
promise를 media keys로 이행(resolve)합니다.
promise를 반환합니다.
MediaKeys
객체는 연관된 HTMLMediaElement
가 재생 중에 media data를 복호화하는 데 사용할 수 있는 키
집합을 나타냅니다. 또한
CDM
인스턴스를 나타냅니다.
MediaKeys
객체는 더 이상 액세스할 수 없게 되면 사용자 에이전트에 의해 파괴될 수 있습니다.
예를 들어 스크립트 참조가 없고 연결된 미디어 요소가 없을 때입니다.
Promise를 반환하는 메서드의 경우, 모든 오류는 반환된 Promise를 거부(reject)하여 비동기적으로 보고됩니다. 여기에는 [WEBIDL] 타입 매핑 오류가 포함됩니다.
알고리즘의 단계는 Promise가 거부될 때 항상 중단됩니다.
WebIDLenum MediaKeySessionType
{
"temporary
",
"persistent-license
"
};
MediaKeySessionType
열거형은 다음과 같이 정의됩니다:
Enumeration description | |
---|---|
temporary
|
라이선스, 키 및 세션과 관련된 기록 또는 데이터가 영구 저장되지 않는 세션입니다. 애플리케이션은 그러한 저장소 관리를 신경 쓸 필요가 없습니다. 이 세션 타입에 대한 지원은 필수(REQUIRED)입니다. |
persistent-license
|
라이선스(및 잠재적으로 세션과 관련된 다른 데이터)가 영구적으로 저장되는 세션입니다. 라이선스와 그 안의 키들이 파기될 때 record of license destruction가 반드시 보존되어야 합니다. record of license destruction은 해당 라이선스와 포함된 키들이 더 이상 클라이언트에서 사용 불가능함을 나타내는 Key System 고유의 증빙입니다. 이 세션 타입에 대한 지원은 선택사항(OPTIONAL)입니다.
이 타입의 세션은 이 객체를 만든 애플리케이션은 이러한 세션을 위해 영구 저장된 데이터를 더 이상 필요로 하지 않게 되었을 때 해당 데이터를 제거할 책임이 있습니다. 자세한 내용은 Session Storage and Persistence를 참조하세요. |
WebIDL[Exposed=Window, SecureContext] interface MediaKeys
{
MediaKeySession
createSession
(optional MediaKeySessionType
sessionType = "temporary");
Promise<MediaKeyStatus
> getStatusForPolicy
(optional MediaKeysPolicy
policy = {});
Promise<boolean> setServerCertificate
(BufferSource serverCertificate);
};
createSession()
새로운 MediaKeySession
객체를 반환합니다.
sessionType 매개변수는 반환된 객체의 동작에 영향을 줍니다.
이 메서드가 호출되면, 사용자 에이전트는 다음 단계를 반드시(MUST) 실행해야 합니다:
이 객체의 supported session types 값이 sessionType을 포함하지 않으면, throw하여
[WEBIDL] 규정에 따라 NotSupportedError
를 발생시킵니다.
sessionType에 대해 Is persistent session type?
알고리즘이 true
를 반환하는 값들은 이 객체의 persistent state allowed 값이
false
이면 실패할 것입니다.
구현체가 현재 상태에서 MediaKeySession
연산을 지원하지 않으면, throw하여
[WEBIDL] 규정에 따라 InvalidStateError
를 발생시킵니다.
일부 구현체는 이 MediaKeys
객체가
setMediaKeys()
로
미디어 요소에 연결될 때까지 MediaKeySession
알고리즘을 실행할 수
없습니다. 이 단계는 애플리케이션이 그러한 드문 동작을 시도하기 전에 감지할 수 있도록 합니다.
session을 새 MediaKeySession
객체로 만들고, 다음과 같이
초기화합니다:
sessionId
속성의 값을 빈 문자열로 둡니다.
expiration
속성의 값을 NaN
으로 둡니다.
closed
속성의 값을 새
Promise로 둡니다.
key status를 새 빈 MediaKeyStatusMap
객체로
두고, 다음과 같이 초기화합니다:
size
속성의 값을 0으로 둡니다.
session type 값을 sessionType으로 둡니다.
uninitialized 값을 true로 둡니다.
callable 값을 false로 둡니다.
closing or closed 값을 false로 둡니다.
use distinctive identifier 값을 이 객체의 use distinctive identifier 값으로 둡니다.
cdm implementation 값을 이 객체의 cdm implementation으로 둡니다.
cdm instance 값을 이 객체의 cdm instance로 둡니다.
session을 반환합니다.
getStatusForPolicy()
주어진 MediaKeysPolicy
에 대한
MediaKeyStatus
를 반환합니다.
WebIDLdictionary MediaKeysPolicy
{
DOMString minHdcpVersion
;
};
MediaKeysPolicy
사전은 선택적 속성들로만 구성된 객체입니다. 각 속성은 정책 요구사항을 나타냅니다. 모든 요구사항을 기반으로 CDM이 암호 해제된 미디어 데이터를 재생하도록 허용하는
경우에만 정책이 충족된 것으로 간주됩니다.
HDCP 정책은 minHdcpVersion
으로
표현됩니다. 시스템이 지정된 HDCP 버전 이상을 활성화할 수 있다면, 그 정책은 "usable
"인 MediaKeyStatus
를
반환합니다. [EME-HDCP-VERSION-REGISTRY]는
minHdcpVersion
값과
HDCP 명세 간의 매핑을 제공합니다.
HDCP 상태의 판단은 재생 중 CDM이 그러한 제한을 집행하는 방식과 동일해야 합니다. 이렇게 하면 애플리케이션 개발자는 재생 시작을 위해 어떤 콘텐츠를 최적화하여 가져올지에 대한 합리적인 힌트를 얻을 수 있습니다.
이 메서드가 호출되면, 사용자 에이전트는 다음 단계를 반드시(MUST) 실행해야 합니다:
TypeError
로 거부된 Promise를 반환합니다.
promise를 새 Promise로 둡니다.
다음 단계를 수행하는 작업(task)을 큐에 넣습니다:
policy의 각 사전 멤버에 대해 다음 단계를 실행합니다:
키가 유효한 MediaKeysPolicy
멤버가 아니거나 값의 타입이 올바르지 않으면, promise를 TypeError
로 거부하고 이 단계를
중단합니다.
policy의 각 사전 멤버에 대해 다음 단계를 실행합니다:
만약 CDM이 해당 사전 멤버에 대한 MediaKeyStatus
를
결정할 수 없다면, promise를 NotSupportedError
로
거부하고 이 단계를 중단합니다.
policy의 각 사전 멤버에 대해 다음 단계를 실행합니다:
만약 CDM이 해당 사전 멤버에 대해 암호
해제된 미디어 데이터의 재생을 차단할 것이라면, promise를 "output-restricted
"로
이행(resolve)합니다.
promise를 "usable
"로
이행(resolve)합니다.
promise를 반환합니다.
setServerCertificate()
서버 인증서를 제공하여 라이선스 서버로 보내는 메시지의 암호화를 위해 사용합니다.
이러한 인증서를 사용하는 Key Systems는 또한 인증서를 서버에서 요청하는 기능을 Queue a "message" Event 알고리즘을 통해 지원해야 합니다.
이 메서드는 애플리케이션이 CDM이 요청할 경우 발생할 추가 왕복을 피하기 위해 서버 인증서를 미리 제공할 수 있도록 허용합니다. 이는 최적화를 위한 것이며, 애플리케이션이 반드시 사용해야 하는 것은 아닙니다.
서버 인증서의 내용은 Key System별입니다. 인증서에는 실행 가능한 코드가 포함되어서는 안 됩니다.
이 메서드가 호출되면, 사용자 에이전트는 다음 단계를 반드시(MUST) 실행해야 합니다:
이 객체의 cdm implementation 값으로 표시되는 Key
System 구현이 서버 인증서를 지원하지 않으면, false
로 이행된 Promise를 반환합니다.
serverCertificate가 빈 배열이면, 새로 생성된 TypeError
로 거부된 Promise를 반환합니다.
certificate를 serverCertificate 매개변수의 내용 복사본으로 둡니다.
promise를 새 Promise로 둡니다.
다음 단계를 병렬로 실행합니다:
sanitized certificate를 certificate의 검증 및/또는 정제된 버전으로 둡니다.
사용자 에이전트는 CDM에 전달하기 전에 인증서를 철저히 검증해야 합니다. 여기에는 값의 합리성 검사, 관련 없는 데이터나 필드 제거, 사전 파싱, 정제 또는 완전한 정제 버전 생성 등이 포함될 수 있습니다. 길이와 필드 값이 합리적인지 확인하고, 알 수 없는 필드는 거부하거나 제거해야 합니다.
이 객체의 cdm instance를 사용하여 sanitized certificate를 처리합니다.
앞 단계가 실패하면, 적절한 오류 이름을 가진 새 DOMException
로
promise를 거부합니다.
promise를 true
로 이행(resolve)합니다.
promise를 반환합니다.
"Is persistent session type?" 알고리즘은 지정된 세션 타입이 어떠한 형태의 영속성(persistence)을 지원하는지 판단하기 위해 실행됩니다. 이
알고리즘에 대한 요청은 MediaKeySessionType
값을 포함합니다.
다음 단계들이 실행됩니다:
session type을 지정된 MediaKeySessionType
값으로 둡니다.
다음 목록에서 session type 값에 해당하는 단계들을 수행합니다:
temporary
"
false
.
persistent-license
"
true
.
이 절은 저장소 및 영속성에 관련된 일반 요구사항을 설명합니다.
만약 어떤 MediaKeys
객체의 persistent state allowed 값이
false
라면, 그 객체의 cdm instance는 이 객체 또는 그것이 생성하는 어떤 세션의 연산 결과로 상태를 영구 저장하거나 이전에 영구
저장된 상태에 접근해서는 안 됩니다(SHALL NOT).
만약 어떤 MediaKeys
객체의 persistent state allowed 값이
true
라면, 그 객체의 cdm instance는 이 객체 또는 그것이 생성하는 어떤 세션의 연산 결과로 상태를 영구 저장하거나 이전에 영구
저장된 상태에 접근할 수 있습니다.
영구 저장된 데이터는 항상 이 객체의 origin만 접근할 수 있도록 저장되어야 합니다. 또한 그 데이터는 현재의 browsing profile에서만 접근 가능해야 하며, 다른 브라우징 프로필들, 사용자 에이전트들, 애플리케이션들은 저장된 데이터에 접근해서는 안 됩니다(MUST NOT). 저장된 정보에 대해서는 Information Stored on User Devices를 참조하세요.
영구 저장소를 지원할 때의 추가 고려사항은 10. Security 및 11. Privacy를 참조하세요.
MediaKeySession
객체는 key session을 나타냅니다.
MediaKeySession
객체는 그 객체의 closed
속성이 이행(resolved)된 경우에만 closed로 간주됩니다.
사용자 에이전트는 Monitor for CDM State Changes 알고리즘을
닫히지 않은 각 MediaKeySession
객체에 대해 지속적으로 실행해야(SHALL) 합니다.
Monitor for CDM State Changes 알고리즘은 메인 이벤트 루프와 병렬로
실행되어야(MUST) 하지만, 이 명세서에서 병렬로 실행되도록 정의된 다른 절차들과는 병렬로 실행되어서는 안 됩니다.
MediaKeySession
객체는 닫히지 않았고 그것을 생성한 MediaKeys
객체가
계속 접근 가능한 경우에는 파괴되어서는 안 되며(SHALL NOT) 이벤트를 계속 수신해야(SHALL)
합니다. 그렇지 않으면 더 이상 접근할 수 없는 MediaKeySession
객체는 추가 이벤트를
수신해서는 안 되며(SHALL NOT) 파괴될 수 있습니다(MAY).
위 규칙은 관련된 모든 MediaKeys
객체들과 그 MediaKeySession
객체들이 모두 파괴될 때까지 CDM
인스턴스를 파괴해서는 안 된다는 것을 의미합니다.
만약 MediaKeySession
객체가 페이지에서 접근 불가능하게 될 때 닫히지 않은
상태라면(closed 아닐 경우), CDM는 해당 객체와 연관된 key session을 닫아야(SHALL) 합니다.
key session을 닫으면 명시적으로 저장되지 않은 모든 라이선스와 키들이 파기됩니다.
key session이 정확히 언제 닫히는지는 구현에 따라 다르므로 애플리케이션은 특정 타이밍에 의존해서는 안 됩니다(SHOULD NOT).
세션이 닫힌 후에 어떤 다른 작업을 수행하기 전에 세션이 닫혔는지 확실히 하려는 애플리케이션은 close
()
를 호출하고 반환된 약속이 이행될 때까지
기다려야(SHOULD) 합니다.
Promise를 반환하는 메서드의 경우, 모든 오류는 반환된 Promise를 거부(reject)함으로써 비동기적으로 보고됩니다. 여기에는 [WEBIDL] 타입 매핑 오류가 포함됩니다.
알고리즘의 다음 단계들은 약속이 거부될 때 항상 중단됩니다.
WebIDLenum MediaKeySessionClosedReason
{
"internal-error
",
"closed-by-application
",
"release-acknowledged
",
"hardware-context-reset
",
"resource-evicted
"
};
MediaKeySessionClosedReason
열거형은 다음과 같이 정의됩니다:
Enumeration description | |
---|---|
internal-error
|
세션은 CDM의 복구 불가능한 오류로 인해 닫혔습니다. 이 경우 애플리케이션은 이 MediaKeys 인스턴스에 대해 새 세션을 생성해서는 안 됩니다(MUST NOT).
|
closed-by-application
|
세션은 애플리케이션이 세션의 close () 메서드를 명시적으로
호출하여 닫혔습니다.
|
release-acknowledged
|
세션은 CDM이 record of license destruction에 대한 확인을 받았기 때문에 닫혔습니다. |
hardware-context-reset
|
세션은 CDM의 원래 하드웨어 컨텍스트가 재설정되어 닫혔습니다. 이 경우 사용자 에이전트는 애플리케이션이 이 MediaKeys 인스턴스에 대해 새 세션을 생성할 수 있도록 허용해야
합니다(MUST).
Note
이는 장치의 절전, 모니터 구성 변경 등 여러 이유로 발생할 수 있습니다. 하드웨어 컨텍스트 재설정의 정확한 원인은 구현에 따라 다릅니다. |
resource-evicted
|
세션은 시스템이 다른 세션들을 생성할 수 있도록 자원을 확보해야 했기 때문에 닫혔습니다.
Note
이는 애플리케이션이 장치별 세션 자원 한계에 도달했음을 의미합니다. 닫힌 세션이 여전히 필요하다면, 애플리케이션 개발자는 필요 세션 수를 줄이거나 불필요한 세션을 사전에 닫는 전략을 고려해야 합니다. |
WebIDL[Exposed=Window, SecureContext] interface MediaKeySession
: EventTarget {
readonly attribute DOMString sessionId
;
readonly attribute unrestricted double expiration
;
readonly attribute Promise<MediaKeySessionClosedReason
> closed
;
readonly attribute MediaKeyStatusMap
keyStatuses
;
attribute EventHandler onkeystatuseschange
;
attribute EventHandler onmessage
;
Promise<undefined> generateRequest
(DOMString initDataType, BufferSource initData);
Promise<boolean> load
(DOMString sessionId);
Promise<undefined> update
(BufferSource response);
Promise<undefined> close
();
Promise<undefined> remove
();
};
sessionId
타입의 DOMString
, 읽기 전용
이 객체와 연관된 키 또는 라이선스에 대한 세션 ID입니다.
expiration
타입의 unrestricted double
,
읽기 전용
세션 내 모든 키의 만료 시간이며, 그러한 시간이 존재하지 않거나 CDM에 의해 라이선스가 명시적으로 만료되지 않는 것으로
결정된 경우에는 NaN
입니다.
이 값은 세션 수명 동안 변경될 수 있으며, 예를 들어 어떤 동작이 윈도우의 시작을 유발할 때 변경될 수 있습니다.
closed
타입의 Promise<MediaKeySessionClosedReason
>,
읽기 전용
닫힘이 발생할 때를 알리는 신호로, 이는 세션 닫힘 알고리즘이 실행된 결과입니다. 이 약속은 오직 이행될 수 있으며 거부되지는 않습니다.
keyStatuses
타입의 MediaKeyStatusMap
,
읽기 전용
세션에 키 ID로 알려진 항목들과 연관된 현재 키 상태를 나타내는 읽기 전용 맵에 대한 참조입니다. 각 항목은 고유한 키 ID를 가져야 합니다.
맵 항목들과 그 값들은 이벤트 루프가 한 바퀴 돌 때마다 갱신될 수 있습니다. 맵은 절대로 불일치하거나 부분적으로만 갱신되어서는 안 되지만, 접근들 사이에 이벤트
루프가 도는 경우 접근 간에 변경될 수 있습니다. 키 ID는 load
()
또는 update
()
호출의 결과로
추가될 수 있습니다. 기존 키에 대한 지식이 제거되거나 기존 키 집합이 새 집합으로 대체되는 update
()
호출의 결과로
키 ID가 제거될 수 있습니다. 키 ID는 만료와 같은 이유로 사용 불가능해졌다고 해서 제거되어서는 안 되며, 대신 그러한 키들은 "expired
"와 같은 적절한 상태를 가져야 합니다.
일부 오래된 플랫폼에는 키 ID를 노출하지 않는 Key System 구현체가 있어 준수하는 사용자 에이전트
구현을 제공하기 어렵습니다. 상호운용성을 최대화하기 위해, 그러한 CDM을 노출하는 사용자 에이전트 구현체는 이 멤버를 다음과 같이
구현하는 것이 권장됩니다: 비어있지 않은 목록이 적절한 경우(예: 이 객체로 표현되는 key
session이 키를 포함할 수 있는 경우), 맵을 단일 쌍으로 채우되 단일 바이트 키 ID 0
과 이 객체의 집계된 상태에 가장
적절한 MediaKeyStatus
를
사용하세요.
onkeystatuseschange
타입의 EventHandler
이벤트에 대한
이벤트 핸들러입니다.
keystatuseschange
onmessage
타입의 EventHandler
이벤트에 대한 이벤트 핸들러입니다.
message
generateRequest()
initData를 기반으로 라이선스 요청을 생성합니다. 알고리즘이 성공하여 약속이 이행되면 타입이
"license-request
" 또는
"individualization-request
"인
가 항상 큐에 추가됩니다.
message
이 메서드가 호출되면, 사용자 에이전트는 다음 단계들을 반드시(MUST) 실행해야 합니다:
만약 이 객체의 closing or closed 값이 true이면,
로
거부된 약속을 반환합니다.
InvalidStateError
만약 이 객체의 uninitialized 값이 false이면,
로
거부된 약속을 반환합니다.
InvalidStateError
이 객체의 uninitialized 값을 false로 둡니다.
만약 initDataType이 빈 문자열이면, 새로 생성된
로 거부된 약속을 반환합니다.
TypeError
만약 initData가 빈 배열이면, 새로 생성된
로 거부된 약속을 반환합니다.
TypeError
이 객체의 cdm implementation 값으로 표시되는 Key
System 구현이 initDataType를 Initialization Data Type으로 지원하지 않으면,
로
거부된 약속을 반환합니다. 문자열 비교는 대소문자 구분입니다.
NotSupportedError
init data를 initData 매개변수의 내용 복사본으로 둡니다.
session type을 이 객체의 session type으로 둡니다.
promise를 새 약속으로 둡니다.
다음 단계들을 병렬로 실행합니다:
만약 init data가 initDataType에 대해 유효하지 않으면, 새로 생성된
로
promise를 거부합니다.
TypeError
sanitized init data를 init data의 검증되고 정제된 버전으로 둡니다.
사용자 에이전트는 Initialization Data를 CDM에 전달하기 전에 철저히 검증해야 합니다. 여기에는 필드의 길이 및 값이 합리적인지 확인하고, 값이 합리적인 범위 내에 있는지 검증하며, 관련 없거나 지원되지 않거나 알 수 없는 데이터 또는 필드를 제거하는 것이 포함됩니다. 사용자 에이전트는 Initialization Data를 미리 파싱하고, 정제하며 완전한 정제 버전을 생성하는 것이 권장됨(RECOMMENDED)입니다. 만약 initDataType으로 지정된 Initialization Data 형식이 다중 항목을 지원하면, 사용자 에이전트는 CDM에 필요하지 않은 항목들을 제거해야(SHOULD) 합니다. 사용자 에이전트는 Initialization Data 내의 항목 순서를 변경해서는 안 됩니다(MUST NOT).
앞 단계가 실패하면, 새로 생성된
로
promise를 거부합니다.
TypeError
만약 sanitized init data가 비어있다면,
로
promise를 거부합니다.
NotSupportedError
session id를 빈 문자열로 둡니다.
message를 null로 둡니다.
message type를 null로 둡니다.
cdm를 이 객체의 cdm instance 값으로 표시되는 CDM 인스턴스로 둡니다.
다음 단계를 수행하기 위해 cdm을 사용합니다:
만약 sanitized init data가 cdm에서 지원되지 않으면,
로
promise를 거부합니다.
NotSupportedError
다음 목록에서 session type 값에 대한 단계를 따릅니다:
temporary
"
requested license type을 임시 비영구 라이선스로 둡니다.
반환되는 라이선스는 영구 저장 가능하거나 그것과 관련된 정보를 저장하도록 요구해서는 안 됩니다.
persistent-license
"
requested license type을 영구 저장 가능한 라이선스로 둡니다.
session id를 고유한 Session ID 문자열로 둡니다.
만약 session type에 대해 Is persistent session
type? 알고리즘을 실행한 결과가 true
이면, 해당 ID는 이 객체의 origin
내에서 시간이 지나도(다른 Document 및 브라우징 세션을 포함하여) 고유해야 합니다(MUST).
message를 sanitized init data를 initDataType에 따라 해석하여 생성된 requested license type에 대한 라이선스 요청으로 둡니다.
cdm은 sanitized init data로 제공되지 않은 스트림 관련 데이터(예: media data)를 사용해서는 안 됩니다(MUST NOT).
cdm은 이 시점에서 세션 ID를 포함한 세션 데이터를 저장해서는 안 되는 것이 권장됨(SHOULD NOT)입니다. 자세한 내용은 Session Storage and Persistence를 참조하세요.
message type을 "license-request
"로
둡니다.
message를 sanitized init data에 기반한 라이선스 요청을 생성하기 전에 처리해야 하는 요청으로 둡니다.
이후의 update()
호출에서, CDM은
initDataType에 따라 해석된 sanitized init
data에 기반한 requested license type에
대한 라이선스 요청을 반드시 생성해야(MUST) 합니다.
message type을 message의 타입을 반영하도록
설정합니다. 이는 "license-request
"이거나
"individualization-request
"입니다.
다음 단계들을 실행하는 작업(task)을 큐에 넣습니다:
만약 앞선 단계들 중 어떤 것이 자원 부족으로 실패했다면,
로
promise를 거부합니다.
QuotaExceededError
만약 앞선 단계들 중 어떤 것이 다른 이유로 실패했다면, 적절한 error
name을 가진 새 DOMException
로
promise를 거부합니다.
sessionId
속성을 session id로 설정합니다.
이 객체의 callable 값을 true로 설정합니다.
promise를 undefined
로 이행(resolve)합니다.
session에서 Queue a "message" Event 알고리즘을 실행하여 message type과 message를 제공합니다.
promise를 반환합니다.
load()
지정된 세션에 대해 저장된 데이터를 이 객체로 불러옵니다.
이 메서드가 호출되면, 사용자 에이전트는 다음 단계들을 반드시(MUST) 실행해야 합니다:
만약 이 객체의 closing or closed 값이 true이면,
로
거부된 약속을 반환합니다.
InvalidStateError
만약 이 객체의 uninitialized 값이 false이면,
로
거부된 약속을 반환합니다.
InvalidStateError
이 객체의 uninitialized 값을 false로 둡니다.
만약 sessionId가 빈 문자열이면, 새로 생성된
로 거부된 약속을
반환합니다.
TypeError
만약 이 객체의 session type에 대해 Is persistent session type? 알고리즘을
실행한 결과가 false
이면, 새로 생성된
로 거부된 약속을
반환합니다.
TypeError
origin을 이 객체의 origin으로 둡니다.
promise를 새 약속으로 둡니다.
다음 단계들을 병렬로 실행합니다:
sanitized session ID를 sessionId의 검증 및/또는 정제된 버전으로 둡니다.
사용자 에이전트는 sessionId 값을 CDM에 전달하기 전에 철저히 검증해야 합니다. 최소한 길이와 값이 합리적인지(예: 수십 문자보다 길지 않고 영숫자) 확인해야 합니다.
앞 단계가 실패했거나 sanitized session ID가 비어 있으면, 새로 생성된
로
promise를 거부합니다.
TypeError
만약 이 객체의 MediaKeySession
객체 중 이
객체의 Document에 닫히지 않은 것이
있고 그 객체의 sessionId
속성이
sanitized session ID이면,
로
promise를 거부합니다.
QuotaExceededError
다시 말해, 이 브라우징 컨텍스트에 대해 비-닫힘 세션(타입과 관계없이)이 이미 존재하면 세션을 생성하지 마십시오.
expiration time을 NaN
으로 둡니다.
message를 null로 둡니다.
message type를 null로 둡니다.
cdm를 이 객체의 cdm instance 값으로 표시되는 CDM 인스턴스로 둡니다.
다음 단계를 수행하기 위해 cdm을 사용합니다:
만약 origin에 대해 sanitized session ID에 저장된 데이터가 없다면,
promise를 false
로 이행하고 이 단계들을 중단합니다.
저장된 세션의 session type이 현재 이 MediaKeySession
의
session type과 다르면, 새로 생성된
로
promise를 거부합니다.
TypeError
session data를 origin에 sanitized session ID에 대해 저장된 데이터로 둡니다. 이 데이터는 다른 origin의 데이터나 origin과 연관되지 않은 데이터를 포함해서는 안 됩니다(MUST NOT).
만약 어떤 MediaKeySession
객체가 어떤 Document에서
닫히지 않았고 그 객체가 session data를 나타낸다면,
로
promise를 거부합니다.
QuotaExceededError
다시 말해, 어떤 브라우징 컨텍스트에 대해 비-닫힘 영구 세션이 이미 존재하면 세션을 생성하지 마십시오.
session data를 로드합니다.
만약 session data가 세션의 expiration time을 나타내면, expiration time을 그 만료 시간으로 둡니다.
만약 메시지를 전송할 필요가 있다면, 다음 단계를 실행합니다:
message를 session data에 기반해 생성된 메시지로 둡니다.
message type을 그 메시지에 적절한 MediaKeyMessageType
로
둡니다.
다음 단계들을 실행하는 작업(task)을 큐에 넣습니다:
만약 앞선 단계들 중 어떤 것이 실패했으면, 적절한 error name으로 promise를 거부합니다.
sessionId
속성을 sanitized session ID로 설정합니다.
이 객체의 callable 값을 true로 설정합니다.
만약 로드된 세션이 어떤 키들에 대한 정보를 포함한다면(알려진 키가 있는 경우), 각 키의 key ID와
적절한 MediaKeyStatus
를
제공하여 session에 대해 Update Key Statuses 알고리즘을
실행합니다.
키의 상태를 확실히 판단하기 위해 추가 처리가 필요하다면 "status-pending
"를
사용하세요. 하나 이상의 키에 대한 추가 처리가 완료되면, 실제 상태들로 다시 Update
Key Statuses 알고리즘을 실행합니다.
Update Expiration 알고리즘을 session에 대해 실행하여 expiration time을 제공합니다.
promise를 true
로 이행(resolve)합니다.
만약 message가 null이 아니면, session에서 Queue a "message" Event 알고리즘을 실행하여 message type과 message를 제공합니다.
promise를 반환합니다.
update()
CDM에 메시지(라이선스 포함)를 제공합니다.
response 매개변수는 CDM에 제공될 메시지를 포함합니다. 내용은 Key System별이며 실행 가능한 코드를 포함해서는 안 됩니다(MUST NOT).
이 메서드가 호출되면, 사용자 에이전트는 다음 단계들을 반드시(MUST) 실행해야 합니다:
만약 이 객체의 closing or closed 값이 true이면,
로
거부된 약속을 반환합니다.
InvalidStateError
만약 이 객체의 callable 값이 false이면,
로
거부된 약속을 반환합니다.
InvalidStateError
만약 response가 빈 배열이면, 새로 생성된
로 거부된 약속을
반환합니다.
TypeError
response copy를 response 매개변수의 내용 복사본으로 둡니다.
promise를 새 약속으로 둡니다.
다음 단계들을 병렬로 실행합니다:
sanitized response를 response copy의 검증 및/또는 정제된 버전으로 둡니다.
사용자 에이전트는 CDM에 전달하기 전에 응답을 철저히 검증해야 합니다. 여기에는 값들이 합리적인 범위 내에 있는지 확인하고, 관련 없는 데이터나 필드를 제거하거나, 미리 파싱하거나, 정제하거나, 완전한 정제 버전을 생성하는 것이 포함될 수 있습니다. 길이와 필드 값이 합리적인지 확인하고 알 수 없는 필드는 거부하거나 제거해야 합니다.
앞 단계가 실패했거나 sanitized response가 비어 있으면, 새로 생성된
로
promise를 거부합니다.
TypeError
message를 null로 둡니다.
message type를 null로 둡니다.
session closed를 false로 둡니다.
cdm를 이 객체의 cdm instance 값으로 표시되는 CDM 인스턴스로 둡니다.
다음 단계를 수행하기 위해 cdm을 사용합니다:
만약 sanitized response의 형식이 어떤 면에서든 유효하지 않으면, 새로 생성된
로
promise를 거부합니다.
TypeError
sanitized response를 처리하되, 다음 목록에서 첫 번째로 일치하는 조건의 규정을 따릅니다:
여기에는 초기 라이선스, 업데이트된 라이선스 및 라이선스 갱신 메시지가 포함됩니다.
다음 목록에서 첫 번째로 일치하는 조건의 규정을 따르며 sanitized response를 처리합니다:
temporary
"
이고 sanitized response가 포함된 어떤 세션 데이터(라이선스, 키 등)를
저장해야 한다고 명시하지 않으면
sanitized response를 처리하되 어떤 세션 데이터도 저장하지 않습니다.
persistent-license
"
이고 sanitized response가 영구 저장 가능한 라이선스를 포함하면
sanitized response를 처리하여 그 안에 포함된 라이선스/키 및 관련 세션 데이터를 저장합니다. 그러한 데이터는 이 객체의 origin만 접근할 수 있도록 저장되어야 합니다(MUST).
새로 생성된
로
promise를 거부합니다.
TypeError
또한 Session Storage and Persistence를 참조하세요.
각 세션의 상태 정보(키 포함)는 한 세션을 닫는 것이 다른 세션들의 관찰 가능한 상태에 영향을 주지 않도록 저장되어야 합니다. 이는 키 ID가 겹치더라도 적용됩니다(MUST).
sanitized response가 키 및/또는 관련 데이터를 포함하면, cdm은 아마 키와 관련 데이터를 키 ID로 인덱싱하여 (메모리에) 저장할 것입니다.
세션 내에서의 교체 알고리즘은 Key System에 따라 다릅니다.
CDM 구현체가
각 MediaKeySession
객체당 표준적이고 합리적으로 높은 최소 키 수, 표준 교체 알고리즘 및 표준적이고 합리적으로 높은 최소 MediaKeySession
객체 수를 지원하는 것이 권장됨(RECOMMENDED)입니다.
이는 다양한 스트림을 같은 요소에서 서로 다른 키로 사용하는 사용 사례(예: 적응형 스트림, 다양한 오디오
및 비디오 트랙)에서 재생 중단 가능성을 줄이는 데 도움이 됩니다.
persistent-license
"인
경우
다음 단계들을 실행합니다:
이 객체와 연관된 key session을 닫고,
이 객체와 연관된 모든 저장된 세션 데이터를 삭제합니다. 여기에는
sessionId
및 record
of license destruction이 포함됩니다.
Set session closed to true.
sanitized response를 처리하되 어떤 세션 데이터도 저장하지 않습니다.
예를 들어, sanitized response가 또 다른
이벤트를 생성하는 데 사용될 정보를 포함할 수 있습니다. 이 경우에는
sessionType에 대해 내용을 검증할 필요가 없습니다.
message
만약 메시지를 전송할 필요가 있으면, 다음 단계를 실행합니다:
message를 해당 메시지로 둡니다.
message type을 그 메시지에 적절한 MediaKeyMessageType
로
둡니다.
다음 단계들을 실행하는 작업(task)을 큐에 넣습니다:
이 객체에서 이유를 "release-acknowledged
"로
하여 Session Closed 알고리즘을
실행합니다.
다음 단계들을 실행합니다:
만약 이 객체에 대해 CDM가 알고 있는 키(known)가
변경되었거나 어떤 키의 상태가 변경되었다면, session에 대해 Update Key
Statuses 알고리즘을 실행하여 각 알려진 키의 key ID와 적절한
MediaKeyStatus
를
제공합니다.
키의 상태를 확정적으로 판단하기 위해 추가 처리가 필요하면 "status-pending
"를
사용합니다. 추가 처리가 완료되면 실제 상태로 다시 Update Key
Statuses 알고리즘을 실행합니다.
만약 세션의 expiration time이 변경되었으면, session에 대해 Update Expiration 알고리즘을 실행하여 새로운 만료 시간을 제공합니다.
앞선 단계들 중 어떤 것이 실패하면, 적절한 error
name을 가진 새 DOMException
로
promise를 거부합니다.
만약 message가 null이 아니면, session에서 Queue a "message" Event 알고리즘을 실행하여 message type과 message를 제공합니다.
promise를 undefined
로 이행(resolve)합니다.
promise를 반환합니다.
close()
애플리케이션이 더 이상 세션을 필요로 하지 않음을 나타내며, CDM가 세션과 관련된 자원을 해제하고 세션을 닫아야 함을 의미합니다. 영구 저장된 데이터는 해제되거나 삭제되어서는 안 됩니다.
반환된 약속은 요청이 처리되었을 때 이행되며, 세션이 닫힐 때 closed
속성의 약속이 "closed-by-application
"로
이행될 때 해결됩니다.
이 메서드가 호출되면, 사용자 에이전트는 다음 단계들을 반드시(MUST) 실행해야 합니다:
만약 이 객체의 closing or closed 값이 true이면, undefined
로 이행된 약속을 반환합니다.
만약 이 객체의 callable 값이 false이면,
로
거부된 약속을 반환합니다.
InvalidStateError
promise를 새 약속으로 둡니다.
이 객체의 closing or closed 값을 true로 설정합니다.
다음 단계들을 병렬로 실행합니다:
cdm를 이 객체의 cdm instance 값으로 표시되는 CDM 인스턴스로 둡니다.
cdm를 사용하여 이 객체와 연관된 key session을 닫습니다.
key session을 닫으면 명시적으로 저장되지 않은 모든 라이선스와 키들이 파기됩니다.
다음 단계들을 실행하는 작업(task)을 큐에 넣습니다:
promise를 undefined
로 이행(resolve)합니다.
이유를 "closed-by-application
"로
하여 이 객체에서 Session
Closed 알고리즘을 실행합니다.
promise를 반환합니다.
remove()
세션과 연관된 모든 라이선스와 키를 제거합니다. 영구 세션 타입의 경우, 릴리스 메시지 확인이
update()
에 의해
처리되면 각 세션 타입에 대해 정의된 대로 기타 세션 데이터가 삭제됩니다.
이 메서드가 호출되면, 사용자 에이전트는 다음 단계들을 반드시(MUST) 실행해야 합니다:
만약 이 객체의 closing or closed 값이 true이면,
로
거부된 약속을 반환합니다.
InvalidStateError
만약 이 객체의 callable 값이 false이면,
로
거부된 약속을 반환합니다.
InvalidStateError
promise를 새 약속으로 둡니다.
다음 단계들을 병렬로 실행합니다:
cdm를 이 객체의 cdm instance 값으로 표시되는 CDM 인스턴스로 둡니다.
message를 null로 둡니다.
message type를 null로 둡니다.
다음 단계를 수행하기 위해 cdm을 사용합니다:
만약 세션과 연관된 어떤 라이선스나 키가 있다면:
세션과 연관된 라이선스 및/또는 키를 파기합니다.
이는 메모리나 영구 저장소에 있든지 간에 해당 라이선스 및/또는 키를 파기하는 것을 의미합니다.
이 객체의 session type 값에 대한 다음 목록의 단계를 따릅니다:
temporary
"
다음 단계들을 계속 진행합니다.
persistent-license
"
record of license destruction를 이 객체가 나타내는 라이선스에 대한 record of license destruction으로 둡니다.
그 record of license destruction를 저장합니다.
message를 record of license destruction를 포함하거나 반영하는 메시지로 둡니다.
다음 단계들을 실행하는 작업(task)을 큐에 넣습니다:
Update
Key Statuses 알고리즘을 session에 대해 실행하여 세션 내 모든 key
ID들에 대해 각 키에 대해 "released
"
MediaKeyStatus
값을
제공합니다.
Update
Expiration 알고리즘을 session에 대해 실행하여 NaN
을
제공합니다.
앞선 단계들 중 어떤 것이 실패하면, 적절한 error name을 가진 새 DOMException
로
promise를 거부합니다.
message type을 "license-release
"로
둡니다.
promise를 undefined
로 이행(resolve)합니다.
만약 message가 null
이 아니면, session에서 Queue a
"message" Event 알고리즘을 실행하여 message type과
message를 제공합니다.
promise를 반환합니다.
MediaKeyStatusMap
객체는 key IDs에서 해당 키의 현재 상태로 가는 읽기 전용 맵입니다.
키의 상태는 해당 키가 현재 사용 중인지 여부나 미디어 데이터와는 독립적입니다.
예를 들어, 어떤 키가 현재 충족할 수 없는 출력 요구사항을 가지고 있다면, 그 키가 미디어 데이터를 복호화하는 데 필요했었는지 또는 현재 필요한지에 관계없이 해당 키의 상태는
적절하게 "output-downscaled
" 또는
"output-restricted
"이어야 합니다.
WebIDL[Exposed=Window, SecureContext] interface MediaKeyStatusMap
{
iterable<BufferSource,MediaKeyStatus
>;
readonly attribute unsigned long size
;
boolean has
(BufferSource keyId);
(MediaKeyStatus
or undefined) get
(BufferSource keyId);
};
size
타입의 unsigned long
,
읽기 전용
known keys의 개수입니다.
has()
keyId로 식별되는 키의 상태를 알고 있으면 true
를 반환합니다.
get()
MediaKeyStatus
를
keyId로 식별되는 키에 대해 반환하거나, 해당 키의 상태를 알 수 없으면 undefined
를 반환합니다.
이 인터페이스는 entries
, keys
, values
,
forEach
및 @@iterator
메서드를 iterable에서 제공합니다
[WebIDL].
반복할 값 쌍은 모든 key ID와 해당하는 MediaKeyStatus
값으로부터 형성된 쌍의 스냅샷이며, key ID 순으로 정렬됩니다. 키 ID는 다음과 같이 비교됩니다: 길이가
m인 키 ID A와 길이 n인 키 ID B에 대해 (m <=
n로 가정), A의 m 바이트가 B의 처음 m 바이트보다 사전식으로 작거나, 그
바이트들이 같고 m < n이면 A < B입니다.
WebIDLenum MediaKeyStatus
{
"usable
",
"expired
",
"released
",
"output-restricted
",
"output-downscaled
",
"usable-in-future
",
"status-pending
",
"internal-error
"
};
MediaKeyStatus
열거형은 다음과 같이 정의됩니다:
열거형 설명 | |
---|---|
usable
|
CDM이 해당 키가 현재 복호화에 사용 가능함을 확신하는 상태입니다. 현재 사용할 수 없을 가능성이 있는 키는 이 상태를 가져서는 안 됩니다(MUST NOT). |
expired
|
키는 그 복호화에 사용 가능함 상태가 더 이상
아니며, 그 이유는 만료 시간이 지났기 때문입니다.expiration 속성이 나타내는 시간은
반드시 현재 시간보다 이전이어야 합니다(MUST). 세션의 다른 모든 키는 이 상태여야 합니다(MUST).
|
released
|
키 자체는 더 이상 CDM에서 사용할 수 없지만, record of license destruction와 같은 키에 관한 정보는 이용 가능합니다. |
output-restricted
|
해당 키와 관련된 출력 제한이 현재 충족될 수 없습니다. 이 키로 복호화된 미디어 데이터는 출력 제한에 따라 필요할 경우 재생이 차단될 수 있습니다. 애플리케이션은 해당 키와 연결된 출력 제한을 유발할 스트림의 사용을 피해야 합니다. |
output-downscaled
|
해당 키와 관련된 출력 제한이 현재 충족될 수 없습니다. 이 키로 복호화된 미디어 데이터는 필요할 경우 출력 제한에 따라 더 낮은 품질(예: 해상도)로 표시될 수
있습니다. 애플리케이션은 해당 키와 연결된 출력 제한을 유발할 스트림의 사용을 피해야 합니다. 다운스케일링 지원은 선택 사항(OPTIONAL)입니다. 애플리케이션은 출력 요구사항을 충족할 수 없을 때 재생을 중단 없이 유지하기 위해 다운스케일링에 의존해서는 안 됩니다(SHOULD NOT). |
usable-in-future
|
해당 키는 시작 시간이 미래에 있기 때문에 아직 복호화에 사용 가능하지 않습니다. 시작 시간이 도달하면 키는 사용 가능해질 것입니다. |
status-pending
|
키의 상태가 아직 알려지지 않았고 결정 중입니다. 상태가 결정되면 실제 상태로 갱신될 것입니다. |
internal-error
|
해당 키는 다른 값들과 관련 없는 CDM의 오류로 인해 현재 복호화에 사용 가능하지 않습니다. 이 값은 애플리케이션이 조치할 수 있는 값이 아닙니다. |
MediaKeyMessageEvent
객체는
이벤트에 사용됩니다.
message
WebIDLenum MediaKeyMessageType
{
"license-request
",
"license-renewal
",
"license-release
",
"individualization-request
"
};
MediaKeyMessageType
는 다음과 같이 정의됩니다:
열거형 설명 | |
---|---|
license-request
|
메시지는 새 라이선스 요청을 포함합니다. |
license-renewal
|
메시지는 기존 라이선스 갱신 요청을 포함합니다. |
license-release
|
메시지는 record of license destruction를 포함합니다. |
individualization-request
|
메시지는 App-Assisted
Individualization (또는 재개인화) 요청을 포함합니다. 다른 모든 메시지와 마찬가지로, 메시지 내의 식별자는 반드시 origin 및 profile별로 고유해야 하며, 해당 식별자는 Distinctive Permanent Identifiers이어서는 안 됩니다. |
WebIDL[Exposed=Window, SecureContext]
interface MediaKeyMessageEvent
: Event {
constructor
(DOMString type, MediaKeyMessageEventInit
eventInitDict);
readonly attribute MediaKeyMessageType
messageType
;
readonly attribute ArrayBuffer message
;
};
messageType
타입의 MediaKeyMessageType
, 읽기 전용
구현체는 애플리케이션이 메시지 타입을 처리하도록 강제해서는 안 됩니다(MUST NOT). 구현체는 메시지를 구분하지 않는 애플리케이션을 지원해야 하며(MUST), 메시지 타입을 처리하도록 애플리케이션에 요구해서는 안 됩니다(MUST NOT). 구체적으로, Key Systems는 모든 타입의 메시지를 단일 URL로 전달하는 것을 지원해야 합니다(MUST).
이 속성은 애플리케이션이 메시지를 파싱하지 않고도 메시지를 구분할 수 있게 해줍니다. 이는 선택적인 애플리케이션 및/또는 서버 최적화를 가능하게 하기 위한 것이며, 애플리케이션이 반드시 사용할 필요는 없습니다.
message
타입의 ArrayBuffer
,
읽기 전용
CDM로부터의 메시지입니다. 메시지들은 Key System별 특유의 내용입니다.
WebIDLdictionary MediaKeyMessageEventInit
: EventInit {
required MediaKeyMessageType
messageType
;
required ArrayBuffer message
;
};
MediaKeyMessageEventInit
멤버
messageType
타입의 MediaKeyMessageType
message
타입의 ArrayBuffer
이 절은 비규범적입니다.
이벤트 이름 | 인터페이스 | 발생 시... |
---|---|---|
keystatuseschange
|
Event
|
세션 내의 키들이 변경되었거나 키들의 상태에 변경이 있을 때. |
message
|
MediaKeyMessageEvent
|
CDM이 세션을 위해 메시지를 생성했을 때. |
"Queue a "message" Event" 알고리즘은 MediaKeySession
객체에 대한 message 이벤트를 큐에
추가합니다. 이 알고리즘을 실행하기 위한 요청에는 대상 MediaKeySession
객체, message
type, 및 message가 포함됩니다.
message는 암호화된 형태든 아니든 Distinctive Permanent Identifier(s)을
포함해서는 안 됩니다. 만약 이 객체의 MediaKeySession
의 use distinctive
identifier 값이 false이면, message는 암호화된 형태이든 아니든 Distinctive Identifier(s)을 포함해서는 안 됩니다.
다음 단계들이 실행됩니다:
지정된 MediaKeySession
객체를 session이라고 합니다.
Queue a
task를 사용하여 버블되지 않고 취소할 수 없는 이름이
인 이벤트를 생성하도록 큐에 추가합니다. 이
이벤트는 message
MediaKeyMessageEvent
인터페이스를
사용하며, 해당 type 속성은 message
로 설정되고 isTrusted 속성은
true
로 초기화되며, 그 이벤트를 session에서 디스패치합니다.
이벤트 인터페이스 MediaKeyMessageEvent
는 다음을 가집니다:
messageType
=
지정된 message
typemessage
= 지정된
message
Update Key Statuses 알고리즘은 known 키들의 집합 또는 하나 이상의 키들의 상태를 MediaKeySession
에 대해 갱신합니다. 이 알고리즘을 실행하기 위한
요청에는 대상 MediaKeySession
객체와 키
ID 및 연관된 MediaKeyStatus
쌍들의 시퀀스가
포함됩니다.
이 알고리즘은 항상 태스크 내에서 실행됩니다.
다음 단계들이 실행됩니다:
관련된 MediaKeySession
객체를 session이라고 합니다.
input statuses를 키 ID와 연관된 MediaKeyStatus
쌍들의 시퀀스라고 합니다.
statuses를 session의 keyStatuses
속성이라고 합니다.
statuses의 내용을 교체하기 위해 다음 단계를 실행합니다:
statuses를 비웁니다.
input statuses의 각 쌍에 대해 다음을 수행합니다.
pair를 그 쌍으로 둡니다.
pair의 키 ID에 대한 항목을 statuses에 삽입하고 그 값으로
pair의 MediaKeyStatus
값을
설정합니다.
이 단계의 효과는 session의 keyStatuses
속성의 내용이
기존의 그 속성에 대한 참조를 무효화하지 않고 교체된다는 것입니다. 이 교체는 스크립트 관점에서 원자적입니다. 즉, 스크립트는 절대로 부분적으로 채워진
시퀀스를 보아서는 안 됩니다.
Queue a
task를 사용하여 fire an event 명령을 큐에 추가하고,
이름이
인
이벤트를 session에서 발생시킵니다.
keystatuseschange
Queue a
task를 사용하여 각 mediaKeys
속성이 이
session을 생성한 MediaKeys
객체인 미디어
요소들에서 Attempt to Resume Playback If
Necessary 알고리즘을 실행하도록 큐에 추가합니다.
Update Expiration 알고리즘은 expiration time을 갱신합니다. 대상은 MediaKeySession
객체이며, 요청에는 새 만료 시간이 포함되며 이는
NaN
일 수 있습니다.
이 알고리즘은 항상 태스크 내에서 실행됩니다.
다음 단계들이 실행됩니다:
관련된 MediaKeySession
객체를 session이라고 합니다.
expiration time을 일단 NaN
으로 둡니다.
새 만료 시간이 NaN
이 아니면, expiration time을 그 값으로 둡니다.
session의 expiration
속성을 time으로 표현된 expiration time으로 설정합니다.
Session Closed 알고리즘은 MediaKeySession
의 상태를
CDM에 의해 key session이 닫힌 이후에 갱신합니다. 이 알고리즘을 실행하기 위한 요청에는 대상 MediaKeySession
객체와 MediaKeySessionClosedReason
이
포함됩니다.
이 알고리즘은 항상 태스크 내에서 실행됩니다.
세션이 닫히면, 그와 연관된 라이선스와 키들은 더 이상 미디어 데이터를 복호화하는 데 사용할 수
없습니다. 이 알고리즘이 실행된 이후에는 해당 MediaKeySession
의 모든 메서드는 실패하며 더 이상의 이벤트는 이
객체에 대해 큐에 추가되지 않습니다.
CDM는 세션이 더 이상 필요하지 않게 되거나 시스템 자원이 손실되는 등 어떤 시점에서든 세션을 닫을 수 있습니다. 그 경우 Monitor for CDM State Changes 알고리즘이 변화를 감지하고 이 알고리즘을 실행합니다.
다른 세션의 키들은 겹치는 키 ID를 가지고 있더라도 영향을 받아서는 안 됩니다.
이 알고리즘이 실행된 후에는, 이 알고리즘이 큐에 추가한 이벤트 핸들러들이 실행되겠지만 더 이상의 이벤트는 큐에 추가될 수 없습니다. 결과적으로, 세션을 닫는 것의 결과로 CDM이 메시지를 보낼 수는 없습니다.
다음 단계들이 실행됩니다:
관련된 MediaKeySession
객체를 session이라고 합니다.
promise를 session의 closed
속성으로 둡니다.
만약 promise가 이행된 상태이면, 이 단계들을 중단합니다.
session의 closing or closed 값을 true로 설정합니다.
Update Key Statuses 알고리즘을 session에서 실행하되 빈 시퀀스를 제공합니다.
Update Expiration 알고리즘을 session에서
실행하되 NaN
을 제공합니다.
promise를 제공된 이유로 이행(resolve)합니다.
Monitor for CDM State Changes 알고리즘은 다양한 CDM 상태 변화 시 필요한 단계를 실행합니다.
이 알고리즘은 다른 알고리즘에서 다루지 않는 CDM 상태 변화에만 적용됩니다. 예를 들어, update
()
는 메시지, 키 상태
변경 및/또는 만료 시간 변경을 초래할 수 있지만, 이는 해당 알고리즘 내에서 처리됩니다.
이 알고리즘은 항상 메인 이벤트 루프와 병렬로 실행됩니다.
다음 단계들이 실행됩니다:
session을 MediaKeySession
객체로 둡니다.
cdm를 session의 cdm instance 값으로 표시되는 CDM 인스턴스로 둡니다.
만약 cdm가 아직 전송되지 않은 아웃고잉 메시지를 가지고 있으면, queue a task를 사용하여 다음 단계를 실행합니다:
message type과 message를 그 메시지 타입 및 메시지로 둡니다.
Queue a "message" Event 알고리즘을 실행하여 session, message type 및 message를 전달합니다.
만약 cdm가 session에 대해 알려진(known) 키들의 집합을 변경했거나 하나 이상의 키들의 상태를 변경했으면, queue a task를 사용하여 다음 단계를 실행합니다:
statuses를 session에 대해 알려진 각 키에 대한 키 ID와 MediaKeyStatus
값 쌍의 목록으로
둡니다.
Update Key Statuses 알고리즘을 실행하여 session과 statuses를 전달합니다.
만약 cdm가 session의 expiration time을 변경했으면, queue a task를 사용하여 다음 단계를 실행합니다:
expiration time을 session의 새 만료 시간으로 둡니다.
Update Expiration 알고리즘을 실행하여 session과 expiration time을 전달합니다.
만약 cdm가 session을 닫았다면, queue a
task를 사용하여 적절한 MediaKeySessionClosedReason
값을 사용하여 session에서 Session Closed 알고리즘을 실행합니다.
만약 cdm가 하드웨어 컨텍스트 재설정으로 인해 사용 불가능해졌다면, queue a
task를 사용하여 이유를 "hardware-context-reset
"로
하여 CDM Unavailable 알고리즘을 실행합니다.
만약 cdm가 다른 이유로 사용 불가능해졌다면, queue a
task를 사용하여 이유를 "internal-error
"로
하여 CDM Unavailable 알고리즘을 실행합니다.
메서드는 반환된 promise를 단순
예외
[WEBIDL] 또는 DOMException
으로
거부(reject)함으로써 오류를 보고합니다. 다음의
[WEBIDL]에 정의된 단순 예외 및 DOMException 이름이 알고리즘에서
사용됩니다. 알고리즘에서 명시된 원인들은 각 이름 옆에 나열되어 있지만, 이 이름들은 다른 이유로도 사용될 수 있습니다.
이름(Name) | 가능한 원인(비포괄적) |
---|---|
TypeError
|
매개변수가 비어 있음. 초기화 데이터가 잘못됨. 응답 형식이 잘못됨. " temporary "
세션에 대해 영구 라이선스가 제공됨.
|
NotSupportedError
|
기존 MediaKeys 객체를 제거할 수 없음.Key System이 지원되지 않음. 초기화 데이터 타입이 Key System에서 지원되지 않음. 세션 타입이 Key System에서 지원되지 않음. 초기화 데이터가 Key System에서 지원되지 않음. 연산이 Key System에서 지원되지 않음. |
InvalidStateError
|
기존 MediaKeys 객체를 현재 제거할 수 없음.세션이 이미 사용됨. 세션이 아직 초기화되지 않음. 세션이 닫힘. |
QuotaExceededError
|
MediaKeys 객체를 추가 HTMLMediaElement 와 함께 사용할 수 없음.해당 sessionId에 대해 닫히지 않은 세션이 이미 존재함. 새 세션 또는 라이선스 요청을 생성하기에 자원이 부족함. |
이 절은 알고리즘을 보완하는 세션 저장 및 영속성 개요를 제공합니다.
다음 요구사항은 Storage and Persistence에서의 요구사항 외에도 적용됩니다.
이 객체의 session type에 대해 Is persistent session type?
알고리즘을 실행한 결과가 false
이면, 사용자 에이전트 및 CDM은 어떠한 시점에서도 세션과 관련된 기록이나
데이터를 저장해서는 안 됩니다(MUST NOT). 여기에는 라이선스, 키, record(s) of license destruction 및 Session ID가 포함됩니다.
이 절의 나머지 부분은 Is persistent session type?
알고리즘이 true
를 반환하는 세션 타입에 적용됩니다.
CDM은
세션 데이터(세션 ID 포함)를 첫 update
()
호출 이전에 저장해서는 안
됩니다(SHOULD NOT). 즉, generateRequest
()
알고리즘 중 세션 데이터를 저장해서는 안 됩니다(SHOULD NOT). 이는 애플리케이션이 세션을 인지하고, 결국 세션을 제거해야 함을 알 수
있게 합니다.
세션과 관련된 모든 데이터는 세션이 삭제될 때 반드시 삭제되어야 합니다(MUST). 예를 들어 update
()
에서 record of license destruction 확인을 처리할 때가 이에
해당합니다. 자세한 내용은 Persistent Data를 참조하세요.
CDM은
특정 세션에 대한 데이터가 MediaKeySession
객체 중 닫히지 않은
객체에서
하나만 존재하도록 보장해야 합니다(MUST). 즉, load
()
는 해당 sessionId를 나타내는 MediaKeySession
가 이미 존재하면 반드시 실패해야 합니다(MUST). 이
객체는 generateRequest
()
로
생성되어 아직 활성 상태이거나, load
()
로 다른
객체에 로드된 상태일 수 있습니다. 세션은 해당 세션을 나타내는 모든 객체가 closed된 경우에만 다시 로드할 수 있습니다(MAY).
Is persistent session type? 알고리즘이
true
를 반환하는 타입으로 세션을 생성한 애플리케이션은 나중에 remove
()
를 사용해 제거 프로세스를 시작하고,
메시지 교환 등으로 제거 프로세스가 성공적으로 완료되었는지 확인하여 저장된 데이터를 제거해야 합니다(SHOULD). CDM도 필요에 따라 세션을 제거할 수 있지만, 애플리케이션은 이에 의존해서는 안
됩니다(SHOULD NOT).
영구 저장소 지원 시 추가 고려사항은 10. 보안(Security) 및 11. 개인정보(Privacy)를 참조하세요.
이 절은 암호화 미디어 확장(Encrypted Media Extensions)이 지원될 때 HTMLMediaElement
[HTML]에 대한 추가 및 수정을 명세합니다.
다음 내부 값들이 HTMLMediaElement
에 추가됩니다:
attaching media keys: 불리언 값을 가져야 합니다(SHALL).
encrypted block queue: 복호화를 기다리는 암호화된 블록들의 큐여야 합니다(SHALL).
decryption blocked waiting for key: 불리언 값을 가져야 합니다(SHALL).
playback blocked waiting for key: 불리언 값을 가져야 합니다(SHALL).
다음과 같이 HTMLMediaElement
의 동작이 수정됩니다:
HTMLMediaElement
가 생성될 때, attaching
media keys의 값은 false
로 초기화되어야 하며(SHALL),
encrypted block queue의 값은 비어 있어야 하며(SHALL), decryption
blocked waiting for key의 값은 false
로 초기화되어야 하며(SHALL),
playback blocked waiting for key의 값도 false
로 초기화되어야 합니다(SHALL).
현재 재생 위치(current
playback position)가 일반 재생의 일부로서 재생 방향(direction of playback)으로 진행되는 경우가 아닌 다른 방식으로 변경될 때,
encrypted block queue의 값은 비어 있어야 하며(SHALL), decryption
blocked waiting for key의 값은 false
로 초기화되어야 하며(SHALL),
playback blocked waiting for key의 값도 false
로 설정되어야 합니다(SHALL).
즉, 미디어 리소스 로딩이나 탐색(seeking) 시 이러한 값들은 리셋되어야 합니다.
[HTML]에 명시된 기준 외에도, HTMLMediaElement
는 playback blocked
waiting for key 값이 true
이면 차단된 미디어 요소(blocked media
element)로 간주되어야 합니다(SHALL).
사용자 에이전트가 재생을 시작할 준비가 되었고 미디어 데이터(media data)가 리소스 페치 알고리즘(resource fetch algorithm)에서 암호화된 블록을 포함할 수 있다는 표시를 발견하면, 사용자 에이전트는 Media Data May Contain Encrypted Blocks 알고리즘을 실행해야 합니다(SHALL).
일부 컨테이너 포맷의 경우, 이러한 표시는 Initialization Data와 별도로 존재할 수 있습니다.
이 알고리즘은 관련된 컨테이너 데이터를 파싱한 후(예: Initialization Data Encountered 알고리즘 실행 포함), 디코딩 시작 전에 실행되어야 합니다.
사용자 에이전트가 Initialization Data를 미디어 데이터 내에서 리소스 페치 알고리즘(resource fetch algorithm) 중에 발견하면, 사용자 에이전트는 Initialization Data Encountered 알고리즘을 실행해야 합니다(SHALL).
일부 컨테이너 포맷은 Initialization Data를 포함하지 않는 암호화된 미디어 데이터를 지원할 수 있으며, 이런 경우에는 이 알고리즘이 트리거되지 않는 미디어 데이터도 지원 가능함을 의미합니다.
미디어 데이터 내의 암호화된 각 블록을 리소스 페치 알고리즘(resource fetch algorithm) 중에 발견할 때마다, 사용자 에이전트는 암호화된 블록을 발견한 순서대로 Encrypted Block Encountered 알고리즘을 실행해야 합니다(SHALL).
위 단계는 사용자 에이전트 구현체가 암호화된 블록을 발견한 이후, 재생에 필요하기 전에 아무 때나 복호화를 수행할 수 있도록 유연성을 제공합니다.
decryption blocked waiting for key 값이 true
인 상태에서 다음 중 하나가 발생하면, 사용자 에이전트는 Wait for Key 알고리즘을 실행해야 합니다(SHALL).
사용자 에이전트가 현재 재생 위치(current playback position)를 재생 방향(direction of playback)으로 진행시킬 수 없는 경우.
사용자 에이전트가 현재 재생 위치(current playback position)에 데이터를 제공할 수 없는 경우.
예를 들어, 재생 시작 시 또는 탐색(seeking) 이후에 해당될 수 있습니다.
아래에 명시된 대로 추가 속성과 메서드가 추가됩니다.
Promise를 반환하는 메서드의 경우, 모든 오류는 반환된 Promise를 거부하여 비동기적으로 보고됩니다. 여기에는 [WEBIDL] 타입 매핑 오류가 포함됩니다.
알고리즘의 단계는 Promise가 거부될 때 항상 중단됩니다.
WebIDL[Exposed=Window] partial interface HTMLMediaElement
{
[SecureContext] readonly attribute MediaKeys
? mediaKeys
;
attribute EventHandler onencrypted
;
attribute EventHandler onwaitingforkey
;
[SecureContext] Promise<undefined> setMediaKeys
(MediaKeys
? mediaKeys);
};
mediaKeys
타입 MediaKeys
, 읽기 전용, nullable
onencrypted
타입 EventHandler
이벤트에 대한 이벤트 핸들러입니다. 모든
encrypted
HTMLMediaElement
에서
content attribute와 IDL attribute 모두로 반드시(MUST) 지원되어야 합니다.
onwaitingforkey
타입 EventHandler
이벤트에 대한 이벤트
핸들러입니다. 모든 waitingforkey
HTMLMediaElement
에서
content attribute와 IDL attribute 모두로 반드시(MUST) 지원되어야 합니다.
setMediaKeys()
재생 중 미디어 데이터를 복호화할 때 사용할 MediaKeys
를 제공합니다.
재생 중에 연관된 MediaKeys
객체를 지우거나
교체하는 것의 지원은 구현 품질에 따라 다릅니다. 많은 경우 나쁜 사용자 경험이나 promise 거부가 발생할 수 있습니다.
이 메서드를 호출하면, 사용자 에이전트는 다음 단계를 반드시(MUST) 실행해야 합니다:
이 객체의 attaching media keys 값이 true이면,
로
거부된 promise를 반환합니다.
InvalidStateError
mediaKeys와 mediaKeys
속성이 동일
객체라면, undefined
로 이행된 promise를 반환합니다.
이 객체의 attaching media keys 값을 true로 설정합니다.
promise를 새 promise로 둡니다.
다음 단계들을 병렬로 실행합니다:
다음 조건이 모두 참이면:
mediaKeys가 null이 아니고,
mediaKeys가 나타내는 CDM 인스턴스가 이미 다른 미디어 요소에서 사용 중이고,
사용자 에이전트가 해당 요소와 함께 사용할 수 없는 경우
이 객체의 attaching media keys 값을 false로 설정하고, promise를
로
거부합니다.
QuotaExceededError
mediaKeys
속성이 null이 아니면, 다음 단계들을 실행합니다:
사용자 에이전트 또는 CDM이 연관 제거를 지원하지
않으면, attaching media keys 값을 false로 하고, promise를
로
거부합니다.
NotSupportedError
현재 연관을 제거할 수 없으면, attaching media keys 값을 false로 하고,
promise를
로
거부합니다.
InvalidStateError
일부 구현체는 재생 중에 연관 제거를 허용하지 않을 수 있습니다.
CDM 인스턴스를 사용하여, mediaKeys
속성에 연관된 미디어 데이터 복호화를 중단하고, 미디어 요소와의 연관을 제거합니다.
앞 단계가 실패하면, attaching media keys 값을 false로 하고, promise를 적절한 error name으로 거부합니다.
mediaKeys가 null이 아니면, 다음 단계들을 실행합니다:
CDM 인스턴스를 미디어 요소에 연관시켜 미디어 데이터 복호화에 사용할 수 있도록 합니다.
앞 단계가 실패하면, 다음 단계들을 실행합니다:
mediaKeys
속성을 null로 설정합니다.
attaching media keys 값을 false로 설정합니다.
promise를 적절한 error name을
가진 새 DOMException
으로
거부합니다.
Queue a task를 사용하여 미디어 요소에서 Attempt to Resume Playback If Necessary 알고리즘을 실행합니다.
mediaKeys
속성을
mediaKeys로 설정합니다.
attaching media keys 값을 false로 설정합니다.
promise를 undefined
로 이행(resolve)합니다.
promise를 반환합니다.
MediaEncryptedEvent
객체는
이벤트에 사용됩니다.
encrypted
WebIDL[Exposed=Window]
interface MediaEncryptedEvent
: Event {
constructor
(DOMString type, optional MediaEncryptedEventInit
eventInitDict = {});
readonly attribute DOMString initDataType
;
readonly attribute ArrayBuffer? initData
;
};
initDataType
타입 DOMString
, 읽기 전용
initData
속성에 포함됩니다.
initData
타입 ArrayBuffer
,
읽기 전용, nullable
WebIDLdictionary MediaEncryptedEventInit
: EventInit {
DOMString initDataType
= "";
ArrayBuffer? initData
= null;
};
MediaEncryptedEventInit
멤버
initDataType
타입 DOMString
,
기본값은
""
initData
타입 ArrayBuffer
,
nullable, 기본값은
null
이 절은 비규범적입니다.
이벤트 이름 | 인터페이스 | 발생 시점 | 전제조건 |
---|---|---|---|
encrypted
|
MediaEncryptedEvent
|
사용자 에이전트가 Initialization Data를 미디어 데이터에서 발견했을 때. |
요소의 readyState
값이
HAVE_METADATA
이상일 때.
참고
요소가 이미 재생 중이거나 재생된 적이 있을 수도 있습니다. |
waitingforkey
|
Event
|
키를 기다리느라 재생이 차단될 때. |
readyState
값이
HAVE_CURRENT_DATA
이하일 때.
요소의 playback blocked waiting
for key 값이 새롭게 true 가 될 때.
|
Media Data May Contain Encrypted Blocks 알고리즘은 사용자 에이전트가 미디어 데이터를 재생하기 전에 MediaKeys
객체의 지정이 필요하다고 판단하면 재생을 일시중지합니다.
이 알고리즘을 실행하기 위한 요청에는 대상 HTMLMediaElement
객체가 포함됩니다.
다음 단계들이 실행됩니다:
지정된 HTMLMediaElement
객체를 media
element라고 합니다.
만약 media element의 mediaKeys
속성이 null이고,
구현체가 잠재적으로 암호화된 media data를
디코딩하기 전에 MediaKeys
객체의 지정을
요구한다면, 다음 단계들을 실행합니다:
이러한 단계는 애플리케이션이 media data를
제공한 후에 setMediaKeys
()
를
호출하여 MediaKeys
객체를
제공하기 전에 도달할 수 있습니다. CDM 선택은 파이프라인 및/또는 디코더에 영향을 줄 수
있으므로, 일부 구현체는 CDM이 MediaKeys
객체로 setMediaKeys
()
에
의해 지정될 때까지 암호화 블록을 포함할 수 있는 미디어 데이터의 재생을 지연시킬 수 있습니다.
Wait for Key 알고리즘을 media element에서 실행합니다.
재생을 재개하라는 신호를 기다립니다.
Initialization Data Encountered 알고리즘은 미디어 데이터에서 발견된
이벤트를 큐에 추가합니다. 이 알고리즘을 실행하기
위한 요청에는 대상 encrypted
HTMLMediaElement
객체가
포함됩니다.
다음 단계들이 실행됩니다:
지정된 HTMLMediaElement
객체를 media
element라고 합니다.
initDataType를 빈 문자열로 둡니다.
initData를 null로 둡니다.
만약 media data가 CORS-same-origin이고 mixed content가 아닐 경우, 다음 단계들을 실행합니다:
initDataType를 Initialization Data의 Initialization Data Type을 나타내는 문자열로 둡니다.
initData를 Initialization Data로 둡니다.
미디어 요소는 "Upgradeable Content"를 허용할 수 있지만, 사용자 에이전트는 그러한 미디어 데이터에서의 Initialization Data를 애플리케이션에 노출해서는 안 됩니다(MUST NOT).
Queue a
task를 사용하여 버블되지 않고 취소할 수 없는 이름의
이벤트를 생성하도록 큐에
추가합니다. 이 이벤트는 encrypted
MediaEncryptedEvent
인터페이스를 사용하며,
type 속성은 encrypted
로, isTrusted 속성은 true
로
초기화되어 media element에 디스패치됩니다.
이벤트 인터페이스 MediaEncryptedEvent
는 다음을 가집니다:
initDataType
=
initDataTypeinitData
=
initData
readyState
는
변경되지 않으며 어떤 알고리즘도 중단되지 않습니다. 이 이벤트는 단지 정보를 제공합니다.
만약 media data가 not CORS-same-origin이거나
mixed content인 경우, initData
속성은 null이
됩니다. 애플리케이션은 대체 경로에서 Initialization Data를 가져올 수 있습니다.
Encrypted Block Encountered 알고리즘은 복호화를 위해 암호화된 미디어 데이터 블록을 큐에 추가하고, 가능하면 복호화를 시도합니다. 이 알고리즘을 실행하기 위한
요청에는 대상 HTMLMediaElement
객체가
포함됩니다.
다음 단계들이 실행됩니다:
지정된 HTMLMediaElement
객체를 media
element라고 합니다.
block을 암호화된 미디어 데이터 블록으로 둡니다.
block을 media element의 encrypted block queue의 끝에 추가합니다.
만약 media element의 decryption blocked waiting for key 값이
false
이면, Attempt to Decrypt 알고리즘을
실행합니다.
Attempt to Decrypt 알고리즘은 복호화를 위해 큐에 쌓인 미디어 데이터를 복호화하려고 시도합니다. 이 알고리즘을 실행하기 위한 요청에는 대상 HTMLMediaElement
객체가 포함됩니다.
다음 단계들이 실행됩니다:
지정된 HTMLMediaElement
객체를 media
element라고 합니다.
만약 media element의 encrypted block queue가 비어 있으면, 이 단계들을 중단합니다.
만약 media element의 mediaKeys
속성이 null이 아니면,
다음 단계들을 실행합니다:
해당 속성이 참조하는 MediaKeys
객체를
media keys라 합니다.
media keys의 cdm instance 값으로 표현되는 CDM 인스턴스를 cdm라 합니다.
만약 cdm가 어떤 이유로 더 이상 사용 불가능하면, 다음 단계들을 실행합니다:
media data is corrupted 단계를 실행합니다(리소스 페치 알고리즘의 해당 부분).
CDM
Unavailable 알고리즘을 media keys에 대해 하드웨어 컨텍스트 재설정의 경우 "hardware-context-reset
"
이유로, 그 외의 경우에는 "internal-error
"
이유로 실행합니다.
이 단계들을 중단합니다.
만약 media keys로 생성된 MediaKeySession
중에서 닫히지 않은
것이 하나 이상 있으면, 다음 단계들을 실행합니다:
이 검사는 cdm이 로딩을 마쳤는지 확인하며, 일치하는 키가 사용 가능해지기 위한 전제 조건입니다.
block을 media element의 encrypted block queue의 첫 번째 항목으로 둡니다.
block key ID를 block의 키 ID로 둡니다.
키 ID는 일반적으로 컨테이너에 의해 지정됩니다.
cdm을 사용하여 다음 단계들을 실행합니다:
available keys를 media keys가 생성한 세션들에 있는 키들의 합집합으로 둡니다.
block key를 null로 둡니다.
만약 available keys 중 어떤 것이 block key ID에 대응하고
복호화에 사용 가능하면, 해당 키를
포함한 MediaKeySession
객체를 session으로 두고 block key를 그 키로 둡니다.
만약 여러 세션이 block key ID에 대해 복호화에 사용 가능한 키를 포함한다면, 어떤 세션과 키를 사용할지는 Key System에 따라 다릅니다.
만약 앞 단계 실행의 결과로 available keys의 상태 중 일부가 변경되었다면, 영향을 받은 각
session에 대해 queue
a task를 사용하여 Update Key Statuses
알고리즘을 실행하고, 해당 세션의 모든 key ID들과 각각에 적절한 MediaKeyStatus
값을 제공합니다.
만약 block key가 null이 아니면, 다음 단계들을 실행합니다:
cdm을 사용하여 block key로 block을 복호화합니다.
다음 목록에서 첫 번째로 일치하는 조건에 대한 단계를 따릅니다:
media data is corrupted 단계를 실행합니다(리소스 페치 알고리즘의 해당 부분).
만약 cdm가 더 이상 사용 불가능하면, CDM
Unavailable 알고리즘을 media
keys에 대해 하드웨어 컨텍스트 재설정의 경우 "hardware-context-reset
"
이유로, 그렇지 않으면 "internal-error
"
이유로 실행합니다.
이 단계들을 중단합니다.
block을 media element의 encrypted block queue의 앞에서 제거합니다.
복호된 블록을 정상적으로 처리합니다.
즉, 블록을 디코드합니다.
이 알고리즘의 시작으로 돌아갑니다.
모든 복호화 문제(예: 잘못된 키 사용)가 복호화 실패로 이어지는 것은 아닙니다. 그런 경우에는 여기서 오류가 발생하지 않을 수 있지만 디코드 과정에서 오류가 발생할 수 있습니다.
그렇지 않다면, 어떤 세션에도 block key ID에 해당하는 키가 없으므로 계속 진행합니다.
media element의 decryption blocked waiting for key 값을
true
로 설정합니다.
이 단계는 block에 대해 복호화에 사용 가능한 키가 없을 때 도달합니다.
사용자 에이전트가 복호화할 수 없는 블록 앞의 블록들을 렌더링한 후(가능한 한, 예: 완전한 비디오 프레임 전부), Wait for Key 알고리즘을 실행합니다.
이 알고리즘을 여기서 직접 실행하지 않는 이유는 구현체가 현재 재생 위치보다 앞선 미디어 데이터를 복호화하고 디코드하는 것을 허용하여 시각적 동작에 영향을 주지 않도록 하기 위해서입니다.
프레임 기반 암호화의 경우, 리소스 페치 알고리즘의 일부로 미디어 요소가 프레임을 디코드하려고 시도할 때 다음과 같이 구현할 수 있습니다:
encrypted을 false로 둡니다.
프레임이 암호화되었는지 감지합니다.
프레임을 디코드합니다.
렌더링을 위해 프레임을 제공합니다.
Wait for Key 알고리즘은
이벤트를 큐에 추가하고 waitingforkey
readyState
를
갱신합니다.
이 알고리즘은 HTMLMediaElement
객체가
potentially
playing 상태이고 readyState
가
HAVE_FUTURE_DATA
이상일 때만 호출되어야 합니다. 이 알고리즘을 실행하기 위한 요청에는 대상 HTMLMediaElement
객체가 포함됩니다.
다음 단계들이 실행됩니다:
지정된 HTMLMediaElement
객체를 media
element라고 합니다.
만약 media element의 playback blocked waiting for key 값이
true
이면, 이 단계들을 중단합니다.
media element의 playback blocked waiting for key 값을 true
로
설정합니다.
위 단계의 결과로, 미디어 요소는 아직 차단된 미디어 요소가 아니었다면 차단된 미디어 요소가 됩니다. 그런 경우 미디어 요소는 재생을 중지합니다.
다음 목록에서 첫 번째로 일치하는 조건에 대한 단계를 따릅니다:
media element의 readyState
를
HAVE_CURRENT_DATA
로
설정합니다.
media element의 readyState
를
HAVE_METADATA
로
설정합니다.
다시 말해, 현재 재생 위치의 비디오 프레임과 오디오 데이터가 암호화되어 있지 않거나/또는 성공적으로 복호화되어 디코드되었으면 readyState
를
HAVE_CURRENT_DATA
로
설정합니다. 그렇지 않거나 이전에 가능했지만 더 이상 데이터가 없으면 readyState
를
HAVE_METADATA
로
설정합니다.
Queue a
task를 사용하여 fire an event 이름이
인 이벤트를
media element에서 발생시키도록 큐에 추가합니다.
waitingforkey
재생을 정지합니다.
Attempt to Resume Playback If Necessary 알고리즘은 미디어 요소가 키를 기다리느라 차단되어 있고 필요한 키가 현재 복호화에 사용 가능한 경우 재생을 재개합니다. 이 알고리즘을 실행하기 위한 요청에는 대상
HTMLMediaElement
객체가 포함됩니다.
다음 단계들이 실행됩니다:
지정된 HTMLMediaElement
객체를 media
element라고 합니다.
만약 media element의 playback blocked waiting for key가
false
이면, 이 단계들을 중단합니다.
Attempt to Decrypt 알고리즘을 media element에서 실행합니다.
만약 사용자 에이전트가 current playback position을 재생 방향으로 진행시킬 수 있으면:
media element의 decryption blocked waiting for key 값을
false
로 설정합니다.
media element의 playback blocked waiting for key 값을
false
로 설정합니다.
위 단계의 결과로 미디어 요소가 더 이상 차단된 미디어 요소가 아닐 수 있으며, 이로 인해 재생이 재개될 수 있습니다.
media element의 readyState
값을 상황에 맞게 HAVE_CURRENT_DATA
,
HAVE_FUTURE_DATA
또는 HAVE_ENOUGH_DATA
로
설정합니다.
HAVE_CURRENT_DATA
를
넘어선 상태와 canplaythrough
이벤트는 현재 키 외의 키 가용성을 고려하지 않거나 고려하지 않을 가능성이 높습니다.
ready state의 변경은 HTMLMediaElement
이벤트들을 트리거할 수 있습니다(관련 문서 참조).
This section is non-normative.
CDM이
처리하는 미디어 데이터는 일반적인 방식(예: CanvasRenderingContext2D
의
drawImage
()
메서드나 AudioContext
의
MediaElementAudioSourceNode
등)을 통해 웹 플랫폼 API로 제공되지 않을 MAY 있습니다.
이 명세서는 그러한 미디어 데이터의 비가용성 조건을 정의하지 않지만, 만약 미디어 데이터가 해당 API들을 통해 사용 불가능하면, 해당 API들은 마치 미디어 데이터가 전혀 존재하지 않는
것처럼 동작할 수 있습니다(MAY).
미디어 렌더링이 사용자 에이전트가 아닌 경우(예: 하드웨어 기반 미디어 파이프라인)에는 CSS 변환과 같은 HTML 렌더링 기능 전체가 제공되지 않을 수 있습니다(MAY). 하나의 가능한 제약으로 비디오 미디어는 창의 가장자리와 평행한 변을 가진 직사각형 영역에서만 정상 방향으로 표시되도록 제한될 수 있습니다(MAY).
이 절은 알고리즘에서 명시적으로 다루어지지 않을 수 있는 구현 요구사항들을 정의합니다 — 사용자 에이전트와 Key Systems을 포함하여, CDM 및 서버들까지 포함됩니다. 이 명세서 전반의 요구사항은 CDM가 사용자 에이전트와 분리되어 있거나 그 일부인지에 관계없이 모든 구현에 적용됩니다.
사용자 에이전트 구현자는 CDMs가 이 명세서의 기능을 사용해 보호된 미디어 재생에 합리적으로 필요한 범위를 벗어나는 정보, 저장소 또는 시스템 기능에 접근하지 않도록 보장해야 합니다. 구체적으로, CDM은 다음을 SHALL NOT 합니다:
사용자 에이전트를 통해 명시적으로 허용된 경우를 제외하고, 로컬 또는 원격의 네트워크 자원에 접근하지 않습니다.
보호된 미디어 재생에 합리적으로 필요한 경우를 제외하고 저장소(예: 디스크나 메모리)에 접근하지 않습니다.
CDM 상태 및 persistent data 이외의 사용자 데이터에 접근하지 않습니다.
보호된 미디어 재생에 합리적으로 필요한 경우를 제외하고 하드웨어 구성 요소나 장치에 접근하지 않습니다.
사용자 에이전트 구현자는 위 요구사항을 충족하기 위해 다양한 기법을 사용할 수 있습니다. 예를 들어, 자체적으로 CDM를 구현하는 사용자 에이전트라면 해당 구성요소에 대한 설계 요구사항으로 위 조항을 포함할 수 있습니다. 서드파티 CDM를 사용하는 경우, 제약된 환경(예: "sandbox")에서 실행되도록 하여 금지된 정보와 구성요소에 접근하지 못하게 보장할 수 있습니다.
CDM와의 모든 메시지 및 통신(예: CDM과 라이선스 서버 간)은 반드시 사용자 에이전트를 통해 전달되어야 합니다. CDM은 직접적인 밴드 외 네트워크 요청을 해서는 안 됩니다(MUST NOT). Direct Individualization에서 설명된 경우를 제외한 모든 메시지와 통신은 애플리케이션을 통해 이 명세서에 정의된 API로 전달되어야 합니다(MUST). 특히 애플리케이션이 지정한 URL로 전송되거나 그 오리진에 기반한, 애플리케이션·오리진·컨텐츠 관련 정보를 포함하는 모든 통신은 API를 통해 전달되어야 합니다. 이는 모든 라이선스 교환 메시지를 포함합니다.
Persistent Data는 CDM 또는 사용자 에이전트가 CDM를 대신하여 저장한, MediaKeys
객체가 파기된 이후에도 존재하는 모든 데이터를 포함합니다. 구체적으로,
식별자(또는 Distinctive Identifier(s)를 포함), 라이선스, 키, 키 ID, 또는
record(s) of license destruction 등이 CDM
또는 사용자 에이전트에 의해 저장된 경우가 이에 해당합니다.
애플리케이션 또는 라이선스 서버에 보이는 방식으로 메시지나 동작에 영향을 줄 수 있는 Persistent Data는 반드시 origin-별 및 browsing profile-별로 저장되어야 하며 사생활 모드로부터 유출되거나 유입되어서는 안 됩니다(MUST NOT). 구체적이지만 비포괄적으로, 세션 데이터·라이선스·키·오리진별 식별자 등은 MUST 원-오리진(origin) 및 원-프로파일(per-profile) 단위로 저장되어야 합니다.
Session Storage and Persistence를 참조하세요.
Persistent Data를 사용하는 구현체는 사용자가 해당 데이터를 더 이상 이 명세서의 API를 통해서든 클라이언트 장치에서든 복원할 수 없도록 지울 수 있게 해야 합니다(MUST).
사용자 에이전트는 SHOULD 다음을 권장합니다:
Persistent Data를 쿠키와 같은 다른 사이트 데이터처럼 취급합니다([COOKIES]). 구체적으로:
사용자가 브라우징 기록을 지우는 기능의 일부로 Persistent Data를 지울 수 있도록 허용합니다.
"모든 데이터 삭제" 기능에 Persistent Data를 포함시킵니다.
Persistent Data를 다른 사이트 데이터와 동일한 UI 위치에 표시합니다.
사용자가 origin별 및 browsing profile별로 Persistent Data를 지울 수 있도록 허용합니다. 특히 특정 사이트와 연관된 쿠키·데이터 등을 지우는 "이 사이트에 대한 정보 잊기" 기능의 일부로 지원해야 합니다.
Persistent Data를 지우는 작업이 "쿠키 부활(cookie resurrection)" 유형의 재연결을 방지하도록 충분히 원자적으로 수행되도록 보장합니다. 예를 들어 동시에 지워지지 않은 다른 로컬 데이터에 의존해 새로운 식별자가 이전 식별자와 재연결되는 것을 방지해야 합니다. incomplete clearing of data를 참조하세요.
이러한 인터페이스를 사용자가 데이터의 불완전한 삭제 가능성(incomplete clearing of data)을 이해하고, 쿠키([COOKIES])와 웹 스토리지 등 지속 데이터를 동시에 삭제할 수 있도록 돕는 방식으로 제시합니다.
Key System을 비활성화/재활성화하는 인터페이스를 제공할 때, 데이터 불완전 삭제 가능성을 이해시키고 모든 영속 저장소 기능에서 해당 데이터를 동시에 삭제할 수 있도록 돕는 방식으로 제시합니다.
사용자가 origin별로 또는 모든 오리진에 대해 Persistent Data를 명시적으로 삭제할 수 있도록 허용합니다.
사용자 에이전트는 Persistent Data를 민감할 수 있는 데이터로 취급해야 합니다(SHOULD); 이 정보가 유출되면 사용자 프라이버시가 침해될 가능성이 큽니다. 따라서 Persistent Data를 안전하게 저장하고 삭제 시 기반 저장소에서 신속히 삭제되도록 보장해야 합니다(SHOULD).
애플리케이션에 노출되거나 CDM의 사용을 통해 추론 가능한 값들은, 설계 목적과 상관없이 클라이언트나 사용자를 식별하는 데 사용될 수 있습니다. 이 절은 그러한 우려를 피하거나 완화하기 위한 요구사항을 정의합니다. Identifiers에 대한 추가 요구사항도 존재합니다.
애플리케이션에 노출되거나 추론 가능한 모든 Distinctive Values는 origin별 및 browsing profile별로 고유해야 합니다(MUST). 즉, 이 명세서의 API를 사용하는 한 오리진에서 사용되는 값은 다른 오리진에서 사용되는 값과 달라야 하며, 한 브라우징 프로필에서 사용되는 값은 다른 프로필에서 사용되는 값과 달라야 합니다. 또한 이러한 값들은 사생활 모드로부터 유출되어서는 안 됩니다(MUST NOT).
오리진 및 프로필 간에 값들을 애플리케이션이 연관시킬 수 없어야 합니다(non-associable by applications, MUST). 즉, 여러 오리진 또는 프로필에서 나온 값들이 동일한 클라이언트나 사용자로부터 왔는지 상호 연관할 수 없어야 합니다. 오리진 독립적 또는 프로필 독립적인 값에서 파생된 오리진별 값을 생성하는 구현체는 비가역성 같은 적절한 성질을 가진 파생 함수를 사용하여 위의 비연관성 속성이 보장되도록 해야 합니다(MUST).
Allow Persistent Data to Be Cleared의 요구사항에 따라, 애플리케이션에 노출된 모든 영속화된 값들은 외부(API를 통한 접근 등)와 클라이언트 장치 양쪽에서 더 이상 복원되거나 관찰되거나 추론될 수 없도록 지울 수 있어야 합니다(MUST).
지워진 이후에는 값이 다시 필요할 때 새로운 애플리케이션 비연관(non-associable) 값들이 생성되어야 합니다(MUST).
구현체에서 식별자(특히 Distinctive Identifier(s) 또는 Distinctive Permanent Identifier(s))를 사용하는 것은 프라이버시 문제를 일으킬 수 있습니다. 이 절은 그러한 우려를 피하거나 완화하기 위한 요구사항을 정의합니다. Values Exposed to the Application의 요구사항은 애플리케이션에 노출되는 식별자에도 적용됩니다.
요약하면:
Distinctive Identifiers 및 Permanent Identifiers 사용을 제한하거나 피하세요.
MUST를 제외한 모든 식별자는 Permanent Identifiers를 제외하고 오리진 및 프로필별로 고유, 비연관(non-associable), 그리고 지울 수 있어야 합니다.
모든 식별자는 외부에 노출될 때(SHOULD) 암호화되어야 합니다.
Distinctive Identifiers는 클라이언트 외부에 노출될 때 암호화되어야 하며, 오리진 및 프로필별로 고유하고(per-origin per-profile) 지울 수 있어야 합니다.
Distinctive Permanent Identifiers는 클라이언트 외부로 노출될 때 암호화되어야 하며(암호화), 애플리케이션에 노출되어서는 안 됩니다(MUST NOT).
이 명세서의 API 사용 결과 생성되는 모든 잠재적 식별자 또는 Distinctive Values는 오리진 및 프로필별로 고유하고(per-origin per-profile) 지울 수 있어야 합니다(clearable). 여기에는 무작위 식별자·세션 데이터·기타 CDM 데이터가 포함됩니다.
구현체는 Distinctive Identifier(s) 또는 Distinctive Permanent Identifier(s)의 사용을 피하는 것이 좋습니다(SHOULD).
예: 개별 클라이언트 대신 클라이언트나 장치 그룹에 적용되는 식별자나 값을 사용하는 것이 바람직합니다.
구현체는 필요한 경우에만 Distinctive Identifier(s) 또는 Distinctive Permanent Identifier(s)를 사용해야 합니다(SHOULD). 이는 특정 CDM 인스턴스와 세션 관련 정책을 적용하기 위한 경우에 해당합니다.
예: "temporary
"와
"persistent-license
"
세션은 서로 다른 요구사항을 가질 수 있습니다.
Distinctive Identifier(s) 또는 Distinctive Permanent Identifier(s)를 사용하는 구현체는 이들을 사용하지 않는 옵션을 지원해야 합니다(SHOULD). 이러한 옵션을 지원하는 구현체는 사용자가 이를 선택할 수 있도록 기능을 제공하는 것이 바람직합니다(SHOULD).
지원되는 경우, 애플리케이션은 distinctiveIdentifier
=
"not-allowed
"를
사용하여 이 모드를 선택할 수 있습니다. 이러한 옵션을 선택하면 requestMediaKeySystemAccess
()
호출 결과나 이후 생성된 세션에서 생성되는 라이선스 요청에 영향을 줄 수 있습니다.
사용자가 이 구현 기능을 선택할 수 있게 하면, 사용자 프라이버시를 유지하면서 컨텐츠에 접근할 수 있는 가능성이 높아집니다.
Distinctive Identifiers와 Distinctive Permanent Identifiers는 클라이언트 외부로 노출될 때 메시지 교환 수준에서 반드시 암호화되어야 합니다(MUST). 그 외 모든 식별자는 클라이언트 외부로 노출될 때 암호화하는 것이 권장됩니다(SHOULD). 암호화는 동일한 식별자 암호문의 두 인스턴스가 복호화 키를 가진 엔티티만 연관시킬 수 있도록 보장해야 합니다(associable).
식별자는 다음과 같은 방식으로 노출될 수 있습니다:
애플리케이션에
이벤트를 통해.
message
서버에서 오는 메시지 내에서, 예를 들어 update
()
에
전달되는 경우.
individualization의 일부로.
CDM은 암호화 키가 해당 Key System에 대해 유효한 서버에 속하는지 검증해야 합니다(MUST). 애플리케이션에 노출되는 식별자에 대해서는, 이는 서버 인증서를 사용해 구현될 수 있습니다(MAY).
서버는 Distinctive Identifier를 그 값을 보낸 CDM 이외의 어떤 엔티티에게도 노출해서는 안 됩니다(MUST NOT).
구체적으로는, 해당 식별자를 애플리케이션에 제공하거나 암호화되지 않은 형태로 CDM에 포함된 메시지의 외부에 넣어서는 안 됩니다. 이는 식별자 또는 해당 식별자로 암호화하여 특정 CDM만 복호화할 수 있도록 함으로써 달성할 수 있습니다.
이는 다음을 의미합니다:
장치별 또는 사용자별 키로 만든 모든 서명은 동일한 평문이라도 서로 달라야 합니다(MUST).
장치별 또는 사용자별 키와 관련된 식별자, 키 또는 인증서는 라이선스나 individualization 서버를 위해 암호화되어야 합니다(MUST).
라이선스 서버가 CDM로 보내는 메시지는 수신자 고유의 식별자(예: 의도된 복호화 키의 ID)를 암호화 외피(envelope) 바깥에 노출해서는 안 됩니다(MUST NOT).
Distinctive Permanent Identifiers를 제외한 모든 식별자는 origin 및 browsing profile별로 고유해야 합니다(MUST). 8.4.1 Use Per-Origin Per-Profile Values를 참조하세요.
이는 Distinctive Identifiers를 포함하되 이에 국한되지 않습니다.
Distinctive Permanent Identifiers는 애플리케이션이나 오리진에 노출되어서는 안 됩니다(MUST NOT).
구현체가 애플리케이션에 노출하는 모든 식별자(암호화된 형태라도 포함), 특히 Distinctive Identifiers는 애플리케이션이 오리진·브라우징 프로필 및 식별자 삭제 상태에 걸쳐 이를 연관시킬 수 없어야 합니다(non-associable by application, MUST).
모든 해당 식별자들에 대해, 하나 이상의 애플리케이션(라이선스 또는 관련 서버 포함)이 이러한 연관이나 상관을 달성하는 것이 불가능해야 합니다(MUST NOT).
Allow Persistent Data to Be Cleared의 요구사항 결과로, Distinctive Values를 포함한 모든 잠재적 식별자는 Distinctive Permanent Identifiers를 제외하고 지워질 수 있어야 하며, 지워진 이후에는 외부(API 등)와 클라이언트 장치 양쪽에서 더 이상 복원되거나 관찰되거나 추론될 수 없어야 합니다(MUST).
Distinctive Identifier(s)를 사용하는 구현체는 사용자가 해당 Distinctive Identifier(s)를 지울 수 있게 해야 합니다(MUST). 또한 Distinctive Permanent Identifier(s)를 사용하는 구현체는 Distinctive Permanent Identifier(s)와 연관된 값을 지울 수 있게 해야 합니다(MUST).
지워진 이후에는, 예를 들어 Distinctive Identifiers 같은 값이 이후 필요할 때 새로운 애플리케이션 비연관(non-associable) 값들이 생성되어야 합니다(MUST).
식별자, 특히 Distinctive Identifiers는 때때로 개별화(individualization) 또는 프로비저닝(provisioning)이라고 불리는 과정을 통해 생성되거나 획득됩니다. 그 결과로 얻어진 식별자들은 MUST 애플리케이션에 의해 연관될 수 없어야(non-associable by applications) 하며, 이들의 사용은 MUST 단일 프로파일의 단일 오리진에만 노출되어야 합니다. 이 과정은 식별자가 지워진 후와 같이 여러 번 수행될 수 있습니다(MAY).
이 과정은 사용자 에이전트에 의해 직접 수행되거나 애플리케이션을 통해 수행되어야 합니다(MUST). 두 가지 유형의 개별화에 대한 메커니즘, 흐름 및 제약은 아래 섹션에 설명된 바와 같이 서로 다릅니다. 어떤 방법이 사용되는지는 CDM 구현과 이 명세의 요구사항, 특히 아래 요구사항의 적용에 따라 달라집니다.
distinctiveIdentifier
은 Distinctive Identifiers 및
Distinctive Permanent
Identifiers가 개별화에 포함되어 사용될 수 있는지를 제어합니다. 구체적으로, 그러한 식별자는
distinctiveIdentifier
멤버의 값이 MediaKeySystemAccess
에서 생성된
MediaKeys
객체의 사용 시 그 값이
"required
"일 때만 사용될 수 있습니다.
Direct Individualization은 CDM과 오리진 및 애플리케이션에 독립적인 서버 간에 수행됩니다. 서버는 오리진 독립적이지만, 개별화의 결과는 CDM이 이 명세의 다른 요구사항에 따라 오리진별 식별자를 제공할 수 있게 합니다. 이 과정은 사용자 에이전트에 의해 수행되어야 하며(MUST), 이 명세에 정의된 API를 사용해서는 안 됩니다(MUST NOT).
예를 들어, 이러한 과정은 사용자 에이전트나 CDM 공급업체가 운영하는 미리 결정된 서버와 통신하여 클라이언트 장치를 초기화하거나, 단일 오리진에 대한 지울 수 있는 식별자를 단일 브라우징 프로파일에 대해 얻을 수 있습니다. 이 과정에서 Distinctive Permanent Identifier(s) 또는 기타 Permanent Identifier(s)를 사용할 수 있습니다.
이러한 개별화를 위해 모든 메시지 교환은:
MUST 사용자 에이전트에 의해 처리되고 사용자 에이전트의 네트워크 스택을 통해 수행되어야 합니다.
MUST NOT CDM에 의해 직접 수행되어서는 안 됩니다.
MUST NOT 이 명세에 정의된 API를 통해 애플리케이션에 전달되거나 애플리케이션을 통해 전달되어서는 안 됩니다.
MUST 오리진 및 애플리케이션과 독립적으로 선택된 URL로 전송되어야 합니다.
MUST 모든 Distinctive Identifiers 및 Distinctive Permanent Identifiers을 암호화해야 합니다.
MUST TLS를 사용해야 합니다.
구현체는 오리진(들), 오리진 또는 애플리케이션별 정보, 또는 오리진과 연관될 수 있는 값을 중앙 서버에 암호화된 형태로라도 노출해서는 안 됩니다. 이는 사용자가 방문한 모든 오리진의 중앙 기록을 생성할 수 있기 때문입니다.
App-Assisted Individualization은 CDM과 애플리케이션(애플리케이션이 선택한 서버 포함) 간에 수행되며 오리진별 식별자를 생성합니다. 이 과정은 이 명세에 정의된 API를 통해 수행되어야 하며(MUST), 다른 통신 수단을 사용해서는 안 됩니다(MUST NOT). 다른 API 사용과 마찬가지로, 이 과정은 하나 이상의 Distinctive Identifier(s)를 사용할 수 있습니다(MAY), 하지만 Distinctive Permanent Identifier(s)나 비오리진 특정 값은 사용해서는 안 됩니다(MUST NOT)—암호화된 형태라도 마찬가지입니다. 만약 이 과정이 하나 이상의 Distinctive Identifier(s)를 사용한다면, 결과 식별자는 정의상 Distinctive Identifier가 됩니다.
이러한 개별화를 위해 모든 메시지 교환은:
MUST 이 명세에 정의된 API를 통해 애플리케이션으로 전달되거나 애플리케이션을 통해 전달되어야 합니다.
SHALL 모든 관련
이벤트에 대해 메시지 타입 "message
individualization-request
"를
사용해야 합니다.
MUST NOT 사용자 에이전트에 의해 수행되어서는 안 됩니다.
MUST NOT CDM에 의해 직접 수행되어서는 안 됩니다.
MUST NOT Distinctive Permanent Identifier(s)를 포함하거나 사용해서는 안 됩니다(사용 금지).
MUST NOT 오리진-비특정적인 클라이언트별 정보를 포함해서는 안 됩니다.
MUST 식별자 요구사항을 준수해야 합니다.
여기에는 오리진 및 프로파일별로 고유하고 지울 수 있는 값만 사용하고, 필요 시 암호화하는 것이 포함됩니다.
MUST NOT 실행 가능한 코드를 CDM에 제공해서는 안 됩니다.
연관 가능한(associable) 값들, 포함하여 Distinctive Identifier(s)가 과정에서 사용되는 경우, 구현체는 오리진(들), 오리진-또는-애플리케이션 특정 정보 또는 오리진과 연관될 수 있는 값을 중앙 서버에 암호화된 형태로라도 노출해서는 안 됩니다. 이는 사용자가 방문한 모든 오리진의 중앙 기록을 생성할 수 있기 때문입니다.
적절한 예방 조치를 취하면, 이러한 개별화는 Direct Individualization보다 더 나은 프라이버시를 제공할 수 있지만, Distinctive Identifier(s)를 사용하지 않는 모델만큼은 아닙니다. 이러한 디자인의 이점을 유지하고 다른 프라이버시 문제를 유발하지 않기 위해, 이러한 구현체와 이를 지원하는 애플리케이션은 개별화 메시지를 중앙 서버나 애플리케이션 작성자가 제어하지 않는 다른 서버로 연기하거나 전달하는 것을 피하는 것이 바람직합니다(SHOULD).
구현체는 각 MediaKeySession
객체에서 다중 키를 지원해야 합니다(MUST).
다중 키를 어떻게 지원하는지는 구현 세부사항이지만, 이는 애플리케이션과 이 명세에 정의된 API에 투명해야 합니다(MUST).
구현체는 재생 중 키 간의 원활한 전환을 지원해야 합니다(MUST). 여기에는 동일한 MediaKeySession
내의 키와 별도의 MediaKeySession
객체 간의 키 전환이 포함됩니다.
구현체는 지원하는 모든 Initialization Data Type으로 생성된 라이선스가 모든 콘텐츠 타입에서 사용될 수 있도록 허용하는 것이 바람직합니다(SHOULD).
그렇지 않으면, 예를 들어 requestMediaKeySystemAccess
()
알고리즘이 MediaKeySystemConfiguration
를
거부할 수 있습니다. 예를 들어, initDataTypes
중 하나가 videoCapabilities
중 하나와 지원되지 않을 때가 해당됩니다.
지원되는 컨테이너에 나타날 수 있는 모든 지원되는 Initialization Data Type에 대해, 사용자 에이전트는 해당 컨테이너에서 그 유형의 Initialization Data를 추출하는 것을 지원해야 합니다(MUST).
다시 말해, 어떤 Initialization Data Type을 지원한다고 표시하는 것은 CDM이 라이선스 요청을 생성하는 지원을 의미하고, 컨테이너 특정 타입의 경우 컨테이너에서 이를 추출하는 사용자 에이전트의 지원도 포함합니다. 이는 모든 지원되는 Initialization Data를 모든 지원되는 콘텐츠 타입에서 파싱해야 한다는 것을 의미하지는 않습니다.
이 절은 이 명세의 구현체가 지원하는 콘텐츠(미디어 리소스)의 속성을 정의합니다.
미디어 컨테이너는 암호화되어 있어서는 안 됩니다(MUST NOT). 이 명세는 사용자 에이전트가 미디어 데이터를 복호화하지 않고도
미디어 컨테이너를 파싱할 수 있다는 능력에 의존합니다. 이는 Encrypted Block Encountered 및 Initialization Data Encountered 알고리즘뿐만
아니라 HTMLMediaElement
의 표준
기능(예: seeking)을 지원하는 것을 포함합니다.
모든 트랙을 포함한 미디어 리소스는 컨테이너별 "common encryption" 명세에 따라 암호화되고 패키지되어야 하며(MUST), 키가 제공되면 완전히 규격화되고 호환 가능한 방식으로 복호화될 수 있어야 합니다.
Encrypted Media Extensions Stream Format Registry는 그러한 스트림 형식에 대한 참조를 제공합니다.
캡션, 설명 오디오(described audio), 전사(transcripts)와 같은 인밴드 지원 콘텐츠는 암호화되어서는 안 됩니다(SHOULD NOT).
이러한 트랙의 복호화 — 특히 사용자 에이전트에 다시 제공될 수 있도록 하는 복호화 — 는 일반적으로 구현체에서 지원되지 않습니다. 따라서 이러한 트랙을 암호화하면 접근성 기능과 함께 사용자 에이전트 구현에서 널리 사용 가능하지 않게 됩니다.
접근성 정보를 사용 가능한 형태로 보장하기 위해, 암호화된 인밴드 지원 콘텐츠를 지원하기로 선택한 구현체의 경우: a) CDM은 복호화된 데이터를 사용자 에이전트에 제공해야 하며(MUST) b) 사용자 에이전트는 이를 동등한 비암호화 지원 콘텐츠와 동일한 방식으로 처리해야 합니다(예: timed text tracks로 노출).
모든 사용자 에이전트는 이 절에 설명된 공통 Key Systems를 MUST 지원해야 합니다.
이는 완전히 오픈 소스인 사용자 에이전트를 포함하여 모든 사용자 에이전트에서 보장되는 공통 기본 기능 수준이 존재하도록 보장합니다. 따라서 단순 복호화만 필요한 콘텐츠 제공자는 별도의 콘텐츠 보호 제공자와 협력하지 않고도 모든 플랫폼에서 동작하는 간단한 애플리케이션을 만들 수 있습니다.
"org.w3.clearkey"
Key System은 평문 clear(암호화되지 않은) key들을 사용하여 소스를
복호화합니다. 추가적인 클라이언트 측 콘텐츠 보호는 필요하지 않습니다. 이 Key System은 아래에 설명되어 있습니다.
다음은 Clear Key가 Key System 특유의 기능을 어떻게 지원하는지를 설명합니다:
encryptionScheme
:
구현체는 MUST
스킴을 지원해야 하며, 다른 스킴을 지원할 수 있습니다(MAY).
"cenc"
robustness
:
빈 문자열만 지원됩니다.
distinctiveIdentifier
:
"required
"는
지원되지 않습니다.
persistentState
:
애플리케이션이 비-"temporary
"
세션을 생성하려는 경우(지원되는 경우)가 아니면 "required
"가
아닙니다.
"persistent-license
"
MediaKeySessionType
:
구현체는 이 타입을 지원할 수 있습니다(MAY).
setServerCertificate
()
메서드: 지원되지 않음.
getStatusForPolicy
()
메서드: 구현체는 항상 "usable
"로 약속을 이행(resolve)해야
합니다.
setMediaKeys
()
메서드: 구현체는 MediaKeys
객체를
둘 이상의 HTMLMediaElement
와 연결하는 것을 지원할 수
있습니다(MAY).
다음은 Clear Key가 Key System 특유의 동작을 어떻게 구현하는지를 설명합니다:
generateRequest
()
알고리즘에서:
생성된 message는 License Request Format에 설명된 바와 같이 UTF-8로 인코딩된 JSON 객체입니다.
요청은 sanitized init data에서 키 ID들을 추출하여 생성됩니다.
"type" 멤버 값은 sessionType 매개변수의 값입니다.
sessionId
속성은 32비트 정수로 표현
가능한 숫자 값입니다.
expiration
속성은 항상
NaN
입니다.
update
()
알고리즘에서:
response 매개변수는 License Format에 설명된 JWK Set이거나 License Release Acknowledgement Format에 설명된 바와 같이 UTF-8로 인코딩된 JSON 객체입니다.
첫 번째 경우, sanitized response는 오디오/비디오 타입에 대해 유효한 길이의 적어도 하나의 유효한 JWK 키를 포함한 유효한 JWK Set이 아니면 유효하지 않은 것으로 간주됩니다. 두 번째 경우에는 sanitized response가 유효한 JSON 객체가 아니면 유효하지 않은 것으로 간주됩니다.
"persistent-license
"
타입의 세션에 대해, remove
()
알고리즘에서는
record of license destruction를 반영하는 message가 License Release Format에 설명된 바와 같이 UTF-8로 인코딩된 JSON
객체입니다.
keyStatuses
속성은 초기에는 update
()
를 통해
제공된 모든 키 ID들을 포함하며, 상태는 "usable
"입니다. remove
()
알고리즘이
실행되면 keyStatuses
속성은 빈 목록으로
설정됩니다.
Initialization Data: 구현체는 등록된 Initialization
Data Types의 임의 조합을 지원할 수 있습니다([EME-INITDATA-REGISTRY]).
구현체는 사용자가 지원하는 콘텐츠 타입에 적합한 "keyids"
타입([EME-INITDATA-KEYIDS])과
다른 타입들을 지원하는 것이 바람직합니다(SHOULD).
이 절은
이벤트의 message 속성을 통해 애플리케이션에
제공되는 라이선스 요청의 형식을 설명합니다.
message
형식은 다음 멤버를 포함하는 JSON 객체입니다:
MediaKeySessionType
.
이 JSON이 message
속성으로 포함되어 MediaKeyMessageEvent
객체에 들어갈 경우, JSON
문자열은 Encoding 명세에 따라 UTF-8로 인코딩됩니다([ENCODING]). 애플리케이션은 TextDecoder
인터페이스를 사용하여
ArrayBuffer의 내용을 JSON 문자열로 디코드할 수 있습니다(MAY).
This section is non-normative.
다음 예제는 두 개의 키 ID에 대한 임시 라이선스 요청입니다. (줄바꿈은 가독성을 위한 것뿐입니다.)
{
"kids": [
"LwVHf8JLtPrv2GUXFW2v_A",
"0DdtU9od-Bh5L3xbv0Xf_A"
],
"type": "temporary"
}
이 절은 update
()
메서드의
response 매개변수로 제공될 라이선스의 형식을 설명합니다.
형식은 복호화에 사용될 대칭 키의 표현을 포함하는 JSON Web Key (JWK) Set입니다. 이는 JSON Web Key (JWK) 명세([RFC7517])에 정의된 바를 따릅니다.
세트의 각 JWK에 대해 매개변수 값은 다음과 같습니다:
JSON 객체는 선택적으로 "type" 멤버 값을 가질 수 있으며, 이 값은 MediaKeySessionType
값 중 하나여야 합니다(MUST). 명시되지 않으면 기본값 "temporary
"가 사용됩니다. update
()
알고리즘은 이 값을
sessionType과 비교합니다.
JSON 문자열이 update
()
메서드에
ArrayBuffer response 매개변수로 전달될 때, JSON 문자열은 Encoding 명세에 따라 반드시 UTF-8로 인코딩되어야
합니다([ENCODING]). 애플리케이션은 필요 시 TextEncoder
인터페이스를 사용하여
JSON 문자열을 인코드할 수 있습니다(MAY).
This section is non-normative.
다음 예제는 단일 대칭 키를 포함하는 JWK Set입니다. (줄바꿈은 가독성을 위한 것뿐입니다.)
{
"keys": [{
"kty": "oct",
"k": "tQ0bJVWb6b0KPL6KtZIy_A",
"kid": "LwVHf8JLtPrv2GUXFW2v_A"
}],
"type": "temporary"
}
이 절은
이벤트의 message 속성을 통해 제공될 라이선스
해제 메시지의 형식을 설명합니다.
message
형식은 JSON 객체입니다. "persistent-license
"
타입의 세션에 대해, 객체는 다음 멤버를 포함해야 합니다:
이 JSON이 message
속성으로 포함되어 MediaKeyMessageEvent
객체에 들어갈 경우, JSON
문자열은 Encoding 명세에 따라 UTF-8로 인코딩됩니다([ENCODING]). 애플리케이션은 TextDecoder
를 사용하여
ArrayBuffer의 내용을 JSON 문자열로 디코드할 수 있습니다(MAY).
This section is non-normative.
다음 예제는 두 개의 키를 포함한 "persistent-license
"
세션에 대한 라이선스 해제 예입니다. (줄바꿈은 가독성을 위한 것뿐입니다.)
{
"kids": [ "LwVHf8JLtPrv2GUXFW2v_A", "0DdtU9od-Bh5L3xbv0Xf_A" ]
}
이 절은 update
()
메서드의
response 매개변수로 제공될 라이선스 해제 확인(acknowledgement)의 형식을 설명합니다.
형식은 다음 멤버를 포함하는 JSON 객체입니다:
이 JSON이 update
()
메서드의
ArrayBuffer response 매개변수로 전달될 때, JSON 문자열은 Encoding 명세에 따라 반드시 UTF-8로 인코딩되어야
합니다([ENCODING]). 애플리케이션은 필요 시 TextEncoder
를 사용하여 JSON
문자열을 인코드할 수 있습니다(MAY).
This section is non-normative.
다음 예제는 두 개의 키 ID에 대한 임시 라이선스 요청 예입니다. (줄바꿈은 가독성을 위한 것뿐입니다.)
{
"kids": [
"LwVHf8JLtPrv2GUXFW2v_A",
"0DdtU9od-Bh5L3xbv0Xf_A"
]
}
This section is non-normative.
base64url 및 이를 다루는 방법에 대한 자세한 내용은 "Base64url Encoding" 용어 정의와 "Notes on implementing base64url encoding without padding"를 참조하세요([RFC7515]). 구체적으로 '=' 패딩이 없으며, 문자 '-' 및 '_'는 각각 '+' 및 '/' 대신에 반드시(MUST) 사용되어야 합니다.
User Agent 및 Key System 구현체는 MUST 미디어
데이터(media
data), Initialization Data, update
()
에 전달된 데이터,
라이선스, 키 데이터 및 애플리케이션이 제공하는 기타 모든 데이터를 신뢰할 수 없는 콘텐츠이자
잠재적 공격 벡터로 고려해야 합니다. 그들은 관련 위협을 완화하기 위해 적절한 보호조치를 사용하고
그러한 데이터를 안전하게 구문 분석하고 복호화하는 등의 주의를 기울여야 합니다. User Agent는 SHOULD 데이터를 CDM에 전달하기 전에 검증해야 합니다.
이러한 검증은 특히 CDM이 예를 들어 DOM과 같은 동일한(샌드박스된) 컨텍스트에서 실행되지 않는 경우에 특히 중요합니다.
구현체는 애플리케이션에 활성 콘텐츠나 프로그램 제어 흐름에 영향을 미치는 수동 콘텐츠를 반환해서는 안 됩니다(MUST NOT).
예를 들어, Initialization Data에서 온 것일 수 있는 URL이나 기타
정보를 노출하는 것은 안전하지 않습니다. 이는 generateRequest
()
에
전달된 Initialization Data의 경우와 같습니다. 애플리케이션은 사용할 URL을 결정해야 합니다.
messageType
속성은 관련이
있을 경우 애플리케이션이 URL 집합 중에서 선택하는 데 사용할 수 있습니다.
User Agent는 사용자가 웹을 안전하게 탐색할 수 있도록 제공할 책임이 있습니다. 이 책임은 서드파티의 기능을 포함하여 User Agent가 사용하는 모든 기능에 적용됩니다. User agent 구현자는 MUST Key System 구현자들로부터 통합의 보안 영향을 적절히 평가할 수 있는 충분한 정보를 얻어야 합니다. User agent 구현자는 MUST CDM 구현체가 사용자 에이전트를 위해 보안을 제공할 수 있도록 충분한 제어를 제공 및/또는 지원하는지 보장해야 합니다. 또한 User agent 구현자는 보안 취약점이 발견될 경우 CDM 구현체가 신속하고 능동적으로 업데이트될 수 있고 업데이트될 것임을 보장해야 합니다.
완전히 샌드박스되지 않았거나 플랫폼 기능을 사용하는 CDM 구현체를 악용하면 공격자가 OS나 플랫폼 기능에 접근하거나 권한을 상승시켜(예: 시스템 또는 root로 실행) 드라이버, 커널, 펌웨어, 하드웨어 등에 접근할 수 있습니다. 이러한 기능, 소프트웨어 및 하드웨어는 적대적인 소프트웨어나 웹 기반 공격에 대해 견고하게 작성되지 않았을 수 있으며, 특히 사용자 에이전트와 비교했을 때 보안 수정이 적용되지 않았을 수 있습니다. CDM 구현체의 보안 취약점에 대한 수정이 부족하거나 드물거나 느린 경우 위험이 증가합니다. 이러한 CDM 구현체 및 이를 노출하는 UA는 MUST 모든 보안 영역에서 특히 신중해야 하며, 모든 데이터의 구문 분석을 포함합니다.
User agent는 클라이언트 OS, 플랫폼 및/또는 하드웨어의 일부이거나 이를 제공하는 CDM 또는 기반 메커니즘을 사용할 때 특히 주의해야 합니다.
사용자가 충분히 샌드박스되지 않거나 다른 방식으로 보안이 확보될 수 없는 Key System 구현체를 지원하기로 선택하는 경우, user agent는 로드하거나 호출하기 전에 사용자가 완전히 정보 제공을 받거나 명시적 동의를 제공하도록 SHOULD 해야 합니다(보안 관련 이유로서).
인증되지 않은 출처에 권한을 부여하는 것은 네트워크 공격자가 있는 환경에서 모든 출처에 권한을 부여하는 것과 동일합니다. 퍼시스턴트 동의 남용를 참조하십시오.
이 섹션은 비규범적입니다.
잠재적인 네트워크 공격과 그 영향은 다음을 포함합니다:
DNS 스푸핑 공격: 특정 도메인(origin)에 속한다고 주장하는 호스트가 실제로 그 도메인에서 왔다는 것을 보장할 수 없습니다.
수동 네트워크 공격: 클라이언트와 서버 간에 전송되는 데이터(예: Distinctive Identifiers 및 Distinctive Permanent Identifiers) 를 다른 엔터티가 보지 못한다고 보장할 수 없습니다. 사용자 추적을 참조하십시오.
능동 네트워크 공격: 페이지에 추가 스크립트나 iframe이 주입되지 않는다고 보장할 수 없습니다(이 사양의 API를 합법적으로 사용하는 페이지와 사용하지 않는 페이지 모두). 결과는 다음과 같습니다:
이 사양에 정의된 API 호출이 어떤 페이지에든 주입될 수 있습니다.
합법적인 목적으로 이 사양을 사용하는 페이지에서의 API 호출이 요청된 기능을 변경하거나 호출을 수정 및 추가하거나 데이터를 수정 또는 주입하는 등으로 조작될 수 있습니다. 또한 입력 데이터 공격 및 취약점을 참고하십시오.
클라이언트와 서버 간에 전송되는 데이터(예: Distinctive Identifiers 및 Distinctive Permanent Identifiers) 를 다른 엔터티가 보거나 수정할 수 있습니다. 사용자 추적을 참조하십시오.
퍼시스턴트 동의 남용: 이 사양의 API 사용을 요청하는 호스트가 사용자가 이전에 동의를 제공한 호스트인지 보장할 수 없습니다. 결과적으로 인증되지 않은 출처에 권한을 부여하는 것은 네트워크 공격자가 있는 환경에서 모든 출처에 권한을 부여하는 것과 같습니다.
다음 기술들은 위험을 완화할 수 있습니다:
TLS를 사용하는 애플리케이션은 사용자와 사용자를 대신하여 동작하는 소프트웨어, 그리고 동일한 도메인으로 식별되는 인증서를 가진 다른 TLS 사용 페이지만 해당 애플리케이션과 상호작용할 수 있음을 확신할 수 있습니다. 또한 보안된 출처와 결합된 origin-특정 권한은 애플리케이션에 부여된 권한이 네트워크 공격자에 의해 악용되는 것을 방지합니다.
이 사양에 정의된 API는 보안 컨텍스트에서만 노출됩니다. 또한 보안 출처 및 전송을 참고하십시오.
User agent는 혼합 콘텐츠[MIXED-CONTENT]를 적절히 처리해야 하며(MUST) 잠재적 노출을 피하기 위해 "차단 가능한 콘텐츠"(MIXED-CONTENT)를 차단하는 것을 포함합니다. 이러한 노출은 TLS 사용과 같은 다른 완화책을 손상시킬 수 있습니다.
User agent는 보안을 더욱 강화하기 위해 모든 혼합 콘텐츠(선택적으로 차단 가능한 콘텐츠를 포함)를 차단할 것을 선택할 수 있습니다(MAY). 이는 신뢰할 수 없는 미디어 데이터가 CDM에 전달되는 것을 방지함으로써 보안을 높입니다(참조: CDM 공격 및 취약점).
User agent는 보안 및/또는 개인정보 보호 사유 등으로 인해 사용자에게 충분히 알리고/또는 명시적 동의를 요구해야 할 Key System 에 접근하기 전에 사용자가 충분히 정보 제공을 받고/또는 명시적 동의를 제공하도록 해야 합니다(SHOULD).
이러한 메커니즘은 유효한 사용이 이후 악의적인 접근을 허용하지 않도록 origin별로 적용되어야 하며(MUST), 또한 브라우징 프로필별로 적용되어야 합니다(MUST).
이 사양에 정의된 API를 보안 컨텍스트로 제한하는 것은 네트워크 공격자가 인증되지 않은 출처에 부여된 권한을 악용하지 못하도록 합니다. 퍼시스턴트 동의 남용을 참조하십시오.
이 섹션은 비규범적입니다.
악의적인 페이지는 합법적인 애플리케이션을 iframe에 호스팅하여 공격을 숨기거나 출처에 대해 사용자를 속일 수 있습니다. 예를 들어 사용을 합법적인 콘텐츠 제공자로 보이게 만드는 경우가 있습니다. 이는 특히 보안 및/또는 개인정보 보호 이유 등으로 사용자를 알리거나 동의를 요구하는 구현에 관련이 큽니다. 네트워크 공격에 더해, 공격자는 합법적인 이 사양의 API 사용을 iframe에서 호스팅함으로써 이를 악용하려고 할 수 있습니다. 합법적인 애플리케이션이 동작을 수행하게 함으로써 공격자는 기존에 부여된 권한(또는 화이트리스트)을 재사용하거나 합법적인 요청 또는 사용처럼 보이게 할 수 있습니다.
사용자에게 알리거나 동의를 요구하는 User agent는 보안 및/또는 개인정보 보호 이유를 포함하여 UI 및 동의의 영속성을 최상위 문서의 origin과 이 사양의 API를 사용하는 쪽의 origin의 조합에 기반해야 합니다(SHOULD). 이는 요청을 하는 주 문서가 무엇인지 사용자에게 알리고 하나의(합법적인) 조합에 대해 권한을 영구화하는 것이 악의적인 사용을 우연히 허용하지 않도록 보장합니다.
저자는 다른 엔터티가 자신의 애플리케이션을 iframe
에 호스팅하지 못하도록 해야
합니다(SHOULD). 합법적인 애플리케이션 설계 이유로 호스팅을 지원해야
하는 애플리케이션은 호스팅 문서가 CDM에 전달될 수 있는 어떠한
데이터를 제공하지 못하도록 해야 하며(이 사양의 API를 통해서든 미디어 데이터를 통해서든),
호스팅 프레임이 이 사양의 API를 호출하는 것을 허용해서는 안 됩니다(SHOULD
NOT).
이 섹션은 비규범적입니다.
예를 들어 사용자가 geocities.com
에 콘텐츠를 호스팅하는 등 서로 다른 저자가 하나의 호스트
이름을 공유하면 모두 하나의 origin을 공유하게
됩니다. User agent는 경로명에 의해 API 접근을 제한하는 기능을 제공하지 않습니다.
이 사양의 API를 공유 호스트에서 사용하면 User agent가 구현한 origin 기반의 보안 및 개인정보 보호 완화책이 손상됩니다. 예를 들어, 호스트 이름 하나에 대한 per-origin Distinctive Identifiers는 해당 호스트의 모든 저자가 공유하며, 영속화된 데이터는 호스트의 아무 저자에 의해서나 접근 및 조작될 수 있습니다. 후자는 예를 들어 그러한 데이터의 수정 또는 삭제가 사용자의 특정 콘텐츠에 대한 권리를 지울 수 있는 경우에 특히 중요합니다.
User agent가 경로 제한 기능을 제공하더라도 일반적인 DOM 스크립팅 보안 모델은 이 보호를 우회하여 어떤 경로에서든 데이터를 액세스하는 것을 쉽게 만들 것입니다.
따라서 공유 호스트의 저자들은 이 사양의 API 사용을 피하는 것이 권장됩니다(RECOMMENDED). 이는 User agent의 origin 기반 보안 및 개인정보 보호 완화책을 손상시키기 때문입니다.
사용자의 장치에서 Key System(s)의 존재 또는 사용은 여러 가지 개인정보 문제를 야기합니다. 이는 두 가지 범주로 나뉩니다: (a) EME 인터페이스 자체나 Key System 메시지 내에서 공개될 수 있는 사용자 특정 정보와 (b) 사용자의 장치에 영구적으로 저장될 수 있는 사용자 특정 정보입니다.
User Agents는 사용자 자신의 개인정보에 대해 적절한 통제권을 제공하는 책임을 MUST 져야 합니다. User Agents가 제3자 CDM 구현과 통합할 수 있으므로, CDM 구현자는 사용자 에이전트 구현자가 아래에 설명된 기술들을 포함하되 이에 국한되지 않는 적절한 기술을 구현하여 사용자가 자신의 개인정보를 통제할 수 있도록 충분한 정보와 제어 수단을 제공해야 합니다(MUST).
EME 및 Key Systems가 공개하는 정보에 대한 우려는 두 가지 범주로 나뉩니다: (a) 사용자 에이전트나 장치의 지문 추출 가능성에 기여할 수 있는 비특정적 정보에 대한 우려와 (b) 사용자 추적에 직접 사용될 수 있는 사용자 특정 정보입니다.
악의적인 애플리케이션은 지원되는 Key Systems의 목록과 관련 정보를 감지하거나 열거함으로써 사용자나 사용자 에이전트의 지문을 추출할 수 있습니다. 적절한 출처(origin) 보호가 제공되지 않으면 여기에는 방문한 사이트의 감지나 해당 사이트에 대해 저장된 정보의 식별이 포함될 수 있습니다. 특히, Key Systems는 origins 간에 키나 기타 데이터를 공유해서는 안 됩니다(MUST).
이 섹션은 비규범적입니다.
특히 사용자 에이전트 외부에 구현된 CDM은 웹 플랫폼과 동일한 기본적인 격리를 갖지 않을 수 있습니다. 정보 유출, 특히 출처 간의 유출을 방지하기 위한 조치를 취하는 것이 중요합니다. 여기에는 메모리상의 데이터와 저장된 데이터 모두가 포함됩니다. 이를 방치하면 개인 브라우징 세션으로부터의 정보 유출, 브라우징 프로필 간(운영체제 사용자 계정 간을 포함) 및 심지어 서로 다른 브라우저나 애플리케이션 간의 정보 유출로 이어질 수 있습니다.
이러한 문제를 피하기 위해, 사용자 에이전트 및 CDM 구현체는 다음을 보장해야 합니다(MUST):
CDMs는 CDM 인스턴스 개념을 가지고 있어야 하며,
이 인스턴스는 MediaKeys
객체와 일대일로
연관되어야 합니다.
키, 라이선스, 기타 세션 데이터 및 세션의 존재 여부는 세션을 생성한 MediaKeys
객체와 연관된 CDM 인스턴스에
제한되어야 합니다.
세션 데이터는 세션을 생성한 MediaKeys
객체와
연관되지 않은 미디어 요소와 공유되어서는 안 됩니다. 이는 예를 들어 세션의 키가 해당
mediaKeys
속성이 그
MediaKeys
객체가 아닌
미디어 요소에 의해 로드된 콘텐츠를 복호화하는 데 사용되어서는 안 됨을 의미합니다(MUST).
적용 가능한 경우, 영속화된 세션 데이터는 origin별로 저장되어야 합니다.
요청한 origin에 의해 저장된 데이터만 로드될 수 있어야 합니다.
사용자 허가 없이 이 사양에 명시적으로 설명되어 있지 않거나 페이지가 웹 플랫폼의 다른 API를 통해 접근할 수 없는 정보를 CDM으로부터 추출, 유도 또는 추론하는 것이 불가능해야 합니다. 이는 CDM 메시지에 노출되는 정보를 포함하여, 클라이언트 장치 외부나 애플리케이션으로 노출되는 모든 정보에 적용됩니다.
이 요구사항이 다루는 정보 유형에는 다음이 포함되지만 이에 국한되지 않습니다:
위치 정보(지오로케이션 포함)
Distinctive Identifiers 외의 자격 증명 또는 식별자
운영체제 계정 이름 및 기타 잠재적 개인 식별 정보(PII)
로컬 디렉터리 경로(유사한 정보가 포함될 수 있음)
로컬 네트워크 세부정보(예: 장치의 로컬 IP 주소)
Bluetooth, USB, 사용자 미디어를 포함하되 이에 국한되지 않는 로컬 장치들
이 사양에 정의된 API의 결과로 연관되거나 저장되지 않은 사용자 상태
이 섹션은 비규범적입니다.
제3자 호스트(또는 여러 사이트에 콘텐츠를 배포할 수 있는 광고주와 같은 어떤 엔터티)는 Distinctive Identifier나 라이선스, 키, 키 ID, 또는 records of license destruction와 같은 영속적 데이터를 CDM이 저장하거나 대리 저장한 것을 이용해 여러 세션에 걸쳐(또는 origins과 브라우징 프로필을 넘나들며) 사용자를 추적하고, 사용자의 활동이나 관심사에 대한 프로파일을 구축할 수 있습니다. 이러한 추적은 웹 플랫폼이 제공하는 개인정보 보호를 약화시키고, 예를 들어 기존에는 불가능했던 정교한 타깃 광고를 가능하게 할 수 있습니다. 사용자의 실명 신원을 알고 있는 사이트(예: 인증된 자격 증명을 요구하는 콘텐츠 제공자나 전자 상거래 사이트)와 결합될 경우, 이는 순수하게 익명인 웹 사용 환경보다 개인을 더 정확히 표적으로 삼는 데 이용될 수 있습니다.
이 사양의 API 구현을 통해 얻을 수 있는 사용자 또는 클라이언트 특정 정보는 다음을 포함합니다:
방문한 Origins(저장되거나 메모리에 있는 데이터, 권한 등으로부터)
본문으로 본 콘텐츠(저장되거나 메모리에 있는 라이선스, 키, 키 ID, records of license destruction 등으로부터)
이 사양이 특별히 우려되는 이유는 이러한 정보가 종종 사용자 에이전트 외부(그리고 연관된 브라우징 프로필 저장소와 별개로) 저장되는 경우가 많고, 종종 CDM에 저장되기 때문입니다.
라이선스의 내용 및 records of license destruction는 Key System별이며 키 ID는 임의의 값을 포함할 수 있으므로, 이러한 데이터 항목들은 사용자 식별 정보를 저장하는 데 악용될 수 있습니다.
Key Systems는 장치 또는 장치 사용자를 위해 영구적이거나 준영구적인 식별자(identifier)를 접근하거나 생성할 수 있습니다. 경우에 따라 이러한 식별자는 특정 장치에 보안 방식으로 바인딩될 수 있습니다. 이러한 식별자가 Key System 메시지에 포함되어 있다면 장치 및/또는 사용자가 추적될 수 있습니다. 아래의 완화책들이 적용되지 않으면, 이는 시간 경과에 따른 사용자/장치 추적과 특정 장치의 여러 사용자 연결을 모두 포함할 수 있습니다.
특히 삭제 불가능하거나 비-origin-특정이거나 permanent한 식별자들은 기존의 쿠키[COOKIES] 나 URL에 삽입된 세션 식별자보다 훨씬 큰 추적 영향을 미친다는 점을 유의해야 합니다.
완화되지 않으면, 이러한 추적은 Key System의 설계에 따라 세 가지 형태로 발생할 수 있습니다:
모든 경우에 이러한 식별자는 Key System을 완전히 지원하는 사이트 및/또는 서버가 이용할 수 있을 것으로 예상되며(따라서 Key System 메시지를 해석할 수 있음) 이러한 사이트들에 의해 추적이 가능해집니다.
Key Systems이 노출하는 식별자가 origin-특정이 아닐 경우, 해당 Key System을 완전히 지원하는 두 사이트 및/또는 서버가 공모하여 사용자를 추적할 수 있습니다.
Key System 메시지가 사용자 식별자로부터 일관된 방식으로 파생된 정보를 포함하는 경우(예: 특정 콘텐츠 항목에 대한 초기 Key System 메시지의 일부가 시간이 지나도 변하지 않고 사용자 식별자에 의존한다면), 이 정보는 어떤 애플리케이션이라도 장치나 사용자를 시간 경과에 따라 추적하는 데 사용될 수 있습니다.
또한, 만약 Key System이 키나 기타 데이터를 저장하고 origins 간에 재사용을 허용한다면, 두 origin이 공모하여 공통 키에 접근할 수 있는지를 기록함으로써 고유 사용자를 추적할 수 있게 될 수 있습니다.
마지막으로, Key Systems에 대한 사용자 제어 UI가 HTTP 세션 쿠키[COOKIES] 또는 영속 저장소의 데이터와 별도로 데이터를 표시한다면, 사용자는 사이트 권한을 변경하거나 한쪽의 데이터를 삭제하고 다른 쪽은 삭제하지 않을 가능성이 큽니다. 이는 사이트들이 서로의 다양한 기능을 상호 백업 수단으로 사용하게 하여 사용자가 자신의 개인정보를 보호하려는 시도를 무력화할 수 있습니다.
사이트나 다른 제3자가 사용자를 추적할 가능성 외에도, 사용자 에이전트 구현자, CDM 공급자 또는 장치 공급자가 사용자가 방문하는 이 사양의 API를 사용하는 사이트들처럼 사용자의 활동이나 관심사에 대한 프로파일을 구축할 수 있습니다. 이러한 추적은 특히 origin 분리에 관련된 웹 플랫폼의 개인정보 보호를 약화시킵니다.
Distinctive Identifiers와 같은 식별자들은 CDM 공급자가 운영하거나 제공하는 서버(예: individualization 과정)를 통해 얻어질 수 있습니다. 이 과정은 Distinctive Permanent Identifier(s)를 포함한 클라이언트 식별자들을 서버에 제공하는 것을 포함할 수 있습니다. per-origin 식별자를 생성하기 위해서는 origin을 나타내는 값도 제공될 수 있습니다.
이러한 구현에서 CDM 공급자는 방문한 origin의 수나 새 식별자가 필요한 횟수와 같은 사용자의 활동을 추적할 수 있습니다. 만약 요청에 origin이나 origin과 연관 가능한 값이 제공된다면, CDM 공급자는 사용자가 방문한 사이트들이나 장치의 사용자들을 추적할 수 있습니다.
다음 섹션은 사용자 동의 없이 발생할 수 있는 추적의 위험을 완화할 수 있는 기술들을 설명합니다.
Key System 구현체는 가능한 한 Distinctive Identifiers 및 Distinctive Permanent Identifiers의 사용을 피해야 하며, 구현의 강건성에 의미 있게 기여할 때에만 사용해야 합니다. 참조: Distinctive Identifiers 및 Permanent Identifiers의 사용 제한 또는 회피.
구현체는 Distinctive Permanent Identifiers를 애플리케이션이나 출처(origin)에 노출해서는 안 됩니다(MUST NOT).
Distinctive Identifiers는 Key System 메시지 내에서 타임스탬프 또는 nonce와 함께 암호화되어야 하며(MUST), 그 결과 Key System 메시지는 항상 달라야 합니다. 이는 Key System 메시지를 통한 추적을 Key System을 완전히 지원하는 서버만이 수행할 수 있게 하여 방지합니다. 참조: 식별자 암호화.
사용자 에이전트는 Distinctive Identifiers와 Key Systems가 저장한 데이터를 HTTP 세션 쿠키[COOKIES]와 강하게 연관시키는 방식으로 사용자에게 표시하고, "모든 데이터 삭제"에 포함시키며 동일한 UI 위치에 제시해야 합니다(SHOULD). 이는 사용자가 이러한 식별자를 경계하여 보게 하는 데 도움이 될 수 있습니다. 사용자 에이전트는 불완전한 데이터 삭제 방지를 통해 사용자를 도와야 합니다.
origin이나 출처와 연관 가능한 값을 개인화 서버(individualization servers)나 출처와 관련 없는 다른 엔터티에 제공하지 마십시오. 구현에서 해당 프로세스를 사용하는 경우 Individualization 섹션의 요구사항과 권고를 따르십시오.
애플리케이션에 노출되는 모든 Distinctive Values에 대해, 구현체는 각 origin과 browsing profile마다 서로 다른 어플리케이션에 의해 연관될 수 없는(non-associable by applications) 값을 사용해야 합니다(MUST). 참조: 8.4.1 Use Per-Origin Per-Profile Values.
이는 특히 Distinctive Identifier(s)를 사용하는 구현체에 중요합니다. 참조: 8.5.3 Use Per-Origin Per-Profile Identifiers.
애플리케이션이나 라이선스 서버에 보이는 방식으로 메시지나 동작에 영향을 미칠 수 있는 CDM에서 사용하는 모든 데이터는 origin 및 browsing profile별로 분할되어 저장되어야 하며, 사적 브라우징 세션으로부터 누출되거나 거기로부터 유입되어서는 안 됩니다(MUST). 이는 메모리상의 데이터와 영속화된 데이터 모두에 적용됩니다. 특히(그러나 이에 국한되지 않고) 세션 데이터, 라이선스, 키 및 출처별 식별자는 출처 및 브라우징 프로필별로 분할되어야 합니다(MUST). 참조: 8.3.1 Use origin-specific and browsing profile-specific Key System storage 및 8.4.1 Use Per-Origin Per-Profile Values.
사용자 에이전트는 Key Systems가 유지하는 모든 영속적 데이터(예: Distinctive Identifiers)를 사용자가 삭제할 수 있는 기능을 제공해야 합니다(MUST)。참조: Allow Persistent Data to Be Cleared.
사용자 에이전트는 사용자가 설정할 수 있는 방식으로 일정 기간 후에 Distinctive Identifiers 및/또는 기타 Key System 데이터를 자동으로 삭제할 수 있습니다(MAY).
예를 들어, 사용자 에이전트는 해당 데이터를 세션 전용 저장소로 구성하여 사용자가 해당 데이터에 접근할 수 있는 모든 브라우징 컨텍스트를 닫으면 데이터를 삭제하도록 할 수 있습니다.
이렇게 하면 사이트가 사용자를 추적할 수 있는 능력을 제한할 수 있습니다. 사이트는 사용자가 사이트 자체에 인증할 때(예: 구매하거나 서비스에 로그인할 때)에만 여러 세션에 걸쳐 사용자를 추적할 수 있게 됩니다.
그러나 이렇게 하면 사용자가 만료의 영향을 완전히 이해하지 못하는 경우 특히 구매 또는 대여한 콘텐츠에 대한 접근 권한이 위험에 처할 수도 있습니다.
사용자 에이전트는 Key Systems 및/또는 기능에 대한 접근을 브라우징 컨텍스트의 최상위 문서의 origin에서
기원한 스크립트로 제한할 수 있습니다(MAY)。
예를 들어, requestMediaKeySystemAccess
()
는
iframe
에서 실행되는 다른 출처의 페이지에 대해 특정 구성 요청을 거부할 수 있습니다.
사용자 에이전트는 Distinctive Identifier(s) 또는 Distinctive Permanent Identifier(s)의 사용 전에 사용자가 충분히 정보 제공을 받고/또는 명시적 동의를 제공하도록 보장해야 합니다(MUST)。
이러한 메커니즘은 유효한 사용이 이후 악의적인 접근을 가능하게 하지 않도록 출처(origin)별로 적용되어야 하며(MUST), 브라우징 프로필별로도 적용되어야 합니다(MUST)。
이 사양에 정의된 API를 보안 컨텍스트로 제한하면 네트워크 공격자가 인증되지 않은 출처에 부여된 권한을 악용하지 못하도록 합니다. 참조: 퍼시스턴트 동의 남용.
사용자 에이전트는 Key System이 활성화되어 있는지 또는 Key System의 Distinctive Identifier(s) 또는 Distinctive Permanent Identifier(s)의 사용이 활성화되어 있는지에 대한 전역 제어를 사용자에게 제공해야 합니다(해당 Key System에서 지원하는 경우)(SHOULD)。사용자 에이전트는 불완전한 데이터 삭제 방지를 통해 사용자를 도와야 합니다。
사용자 에이전트는 사이트가 Key System을 사용하기 전에 각 Key System 또는 특정 기능에 대한 접근을 사용자가 명시적으로 승인하도록 요구할 수 있습니다(MAY)。 사용자 에이전트는 사용자가 이 승인을 일시적 또는 영구적으로 철회할 수 있도록 해야 합니다(SHOULD)。
사용자 에이전트는 사용자가 origin 및/또는 Key Systems의 블랙리스트를 공유할 수 있게 허용할 수 있습니다(MAY)。 이는 커뮤니티가 함께 개인정보를 보호하는 데 도움이 될 수 있습니다。
이러한 제안들은 이 사양에 정의된 API를 사용자 추적에 자명하게 사용하는 것을 방지하지만, 완전히 차단하지는 못합니다. 단일 출처 내에서는 사이트가 세션 중에 사용자를 계속 추적할 수 있으며, 그런 다음 사이트가 수집한 모든 정보를(이름, 신용카드 번호, 주소 등 식별 정보와 함께) 제3자에게 전달할 수 있습니다. 제3자가 여러 사이트와 협력하여 그러한 정보를 수집하고, 식별자가 출처 및 프로필별로 고유하지 않다면, 여전히 프로파일이 생성될 수 있습니다.
이 섹션은 비규범적입니다.
Key Systems는 사용자의 장치에 정보를 저장할 수 있으며, 또는 사용자 에이전트가 Key Systems를 대신하여 정보를 저장할 수 있습니다. 잠재적으로 이는 동일한 장치의 다른 사용자에게 해당 사용자가 방문한 출처들이나 특정 Key System을 사용한 사실(즉, 방문한 사이트들) 또는 Key System으로 복호화된 콘텐츠에 관한 정보를 노출할 수 있습니다.
한 출처에 대해 저장된 정보가 다른 출처의 Key System의 동작에 영향을 미친다면, 한 사이트에서 사용자가 방문했거나 본 콘텐츠가 잠재적으로 악의적인 다른 사이트에 의해 드러날 수 있습니다.
클라이언트 장치에서 한 브라우징 프로필을 위해 저장된 정보가 다른 브라우징 프로필 또는 다른 브라우저의 Key System 동작에 영향을 미친다면, 서로 다른 운영체제 사용자 계정이나 브라우저를 포함하여 한 프로필에서 방문하거나 본 사이트 정보가 다른 프로필에서 노출되거나 상호 연관될 수 있습니다.
이러한 우려를 완화하는 요구사항은 8.3 Persistent Data에 정의되어 있습니다.
이 섹션은 비규범적입니다.
사용자가 Distinctive Identifiers와 저장된 데이터를 삭제하거나 Key System을 비활성화하여 개인정보를 보호하려는 시도가, 해당 데이터와 기능뿐만 아니라 쿠키[COOKIES] 및 기타 사이트 데이터가 동시에 삭제되거나 비활성화되지 않으면 무력화될 수 있습니다. 예를 들면:
사용자가 쿠키나 다른 영속 저장소를 삭제하지만 Distinctive Identifiers와 Key Systems가 저장한 데이터를 함께 삭제하지 않으면, 사이트는 이러한 여러 기능을 상호 보완적인 백업으로 사용하여 사용자의 삭제 시도를 무력화할 수 있습니다.
사용자가 Distinctive Identifiers만 삭제하고 Key Systems가 저장한 데이터(예: 영속 세션), 쿠키 및 기타 영속 저장소를 삭제하지 않으면, 사이트는 남아 있는 데이터를 사용해 이전 식별자와 새 식별자를 연관시켜 사용자의 삭제 시도를 무력화할 수 있습니다.
사용자가 특정 origin에 대해 Key System을 비활성화하되 쿠키나 다른 영속 저장소를 함께 삭제하지 않으면, 사이트는 남아 있는 기능을 이용해 사용자의 비활성화 시도를 무력화할 수 있습니다.
사용자가 어떤 Key System을 비활성화했다가 나중에 해당 Key System을 다시 활성화하되 쿠키나 다른 영속 저장소, Distinctive Identifiers, 그리고 Key Systems가 저장한 데이터를 삭제하지 않으면, 사이트는 비활성화 이전의 데이터와 비활성화 이후의 동작을 연관시킬 수 있습니다.
이러한 우려를 완화하는 권고사항은 8.3 Persistent Data에 정의되어 있습니다.
사용자 에이전트는 사용자 익명성을 유지하거나/또는 탐색 기록이 클라이언트에 영속되지 않도록 하기 위한 동작 모드(예: 개인 브라우징)를 지원할 수 있습니다. 이전 섹션에서 논의된 개인정보 우려는 이러한 모드를 사용하는 사용자에게 특히 중요할 수 있습니다.
이러한 모드들을 지원하는 사용자 에이전트 구현자는 SHOULD 해당 모드에서 Key Systems에 대한 접근을
비활성화해야 하는지 신중히 고려해야 합니다. 예를 들어, 이러한 모드는 MediaKeySystemAccess
객체의 생성 중에 persistentState
또는
distinctiveIdentifier
를
지원하거나 사용하는 MediaKeySystemAccess
객체의 생성을 금지할 수 있습니다(이는 CDM 구현의 일부이거나 애플리케이션이 이를 "required
"로 표시한 경우를 포함합니다). 구현이
이러한 생성을 금지하지 않는다면, 사용자가 해당 모드의 예상되는 개인정보 특성에 미치는 영향과 잠재적 결과를 이해하도록 정보를 제공한 후에만 사용을 허용해야 합니다(SHOULD).
이 사양에 정의된 API는 보안 출처에서만 지원되어 이전 섹션에서 논의된 정보를 보호합니다. 식별자는 또한 Encrypt Identifiers에 명시된 대로 암호화됩니다.
애플리케이션 및 이들이 사용하는 서버들은 CDM의 데이터나 메시지를 포함하거나 관련된 모든 트래픽에 대해, SHOULD 보안
전송을 사용해야 합니다. 여기에는
이벤트에서 전달되는 모든 데이터와 message
update
()
로 전달되는 데이터 등이 포함되며
이에 국한되지 않습니다.
모든 사용자 에이전트는 보안 출처 및 전송을 적용하려 할 때 불안전한 콘텐츠나 전송에 노출되는 것을 피하기 위해 혼합 콘텐츠[MIXED-CONTENT]를 적절히 처리해야 합니다(MUST).
비규범적이라고 표시된 섹션뿐만 아니라, 이 명세서의 모든 저작 지침, 다이어그램, 예제 및 주석은 비규범적입니다. 이 명세서의 나머지 모든 내용은 규범적입니다.
문서에서의 키워드 MAY, MUST, MUST NOT, OPTIONAL, RECOMMENDED, REQUIRED, SHALL, SHALL NOT, SHOULD, 및 SHOULD NOT 은 모두 대문자로 나타날 때에 한해 BCP 14 [RFC2119] [RFC8174] 에 설명된 대로 해석되어야 합니다.
이 섹션은 비규범적입니다.
이 섹션은 제안된 확장을 사용한 다양한 사용 사례에 대한 예시 솔루션을 포함합니다. 이들은 해당 사용 사례에 대한 유일한 해법이 아닙니다. 예제에서는 video 요소를 사용하지만 동일한 내용이 모든 미디어 요소에 적용됩니다. 동기 XHR 사용과 같은 몇몇 경우에는 확장에 집중하기 위해 예제가 단순화되어 있습니다.
이 단순한 예제에서는 소스 파일과 clear-text license가 페이지에 하드코딩되어 있습니다. 하나의 세션만 생성됩니다.
<script>
function onLoad() {
var video = document.getElementById('video');
if (!video.mediaKeys) {
navigator.requestMediaKeySystemAccess('org.w3.clearkey', [
{ initDataTypes: ['webm'],
videoCapabilities: [{ contentType: 'video/webm; codecs="vp8"' }] }
]).then(
function(keySystemAccess) {
var promise = keySystemAccess.createMediaKeys();
promise.catch(
console.error.bind(console, 'Unable to create MediaKeys')
);
promise.then(
function(createdMediaKeys) {
return video.setMediaKeys(createdMediaKeys);
}
).catch(
console.error.bind(console, 'Unable to set MediaKeys')
);
promise.then(
function(createdMediaKeys) {
var te = new TextEncoder();
var initData = te.encode( '{"kids":["LwVHf8JLtPrv2GUXFW2v_A"]}');
var keySession = createdMediaKeys.createSession();
keySession.addEventListener("message", handleMessage, false);
return keySession.generateRequest('keyids', initData);
}
).catch(
console.error.bind(console, 'Unable to create or initialize key session')
);
}
);
}
}
function handleMessage(event) {
var keySession = event.target;
var te = new TextEncoder();
var license = te.encode('{"keys":[{"kty":"oct","k":"tQ0bJVWb6b0KPL6KtZIy_A","kid":"LwVHf8JLtPrv2GUXFW2v_A"}],"type":"temporary"}');
keySession.update(license).catch(
console.error.bind(console, 'update() failed')
);
}
</script>
<body onload='onLoad()'>
<video src='foo.webm' autoplay id='video'></video>
</body>
이 예제는 Key System을 requestMediaKeySystemAccess
()
메서드를 사용해 선택한 다음, 미디어 데이터의 Initialization Data를 사용해 라이선스 요청을
생성하고 적절한 라이선스 서버로 전송합니다. 지원되는 키 시스템 중 하나는 serverCertificate를 사용하며, 그것은 사전에 제공됩니다.
<script>
var licenseUrl;
var serverCertificate;
// Returns a Promise<MediaKeys>.
function createSupportedKeySystem() {
someSystemOptions = [
{ initDataTypes: ['keyids', 'webm'],
audioCapabilities: [
{ contentType: 'audio/webm; codecs="opus"' },
{ contentType: 'audio/webm; codecs="vorbis"' }
],
videoCapabilities: [
{ contentType: 'video/webm; codecs="vp9"' },
{ contentType: 'video/webm; codecs="vp8"' }
]
}
];
clearKeyOptions = [
{ initDataTypes: ['keyids', 'webm'],
audioCapabilities: [
{ contentType: 'audio/webm; codecs="opus"' },
{ contentType: 'audio/webm; codecs="vorbis"' }
],
videoCapabilities: [
{ contentType: 'video/webm; codecs="vp9"',
robustness: 'foo' },
{ contentType: 'video/webm; codecs="vp9"',
robustness: 'bar' },
{ contentType: 'video/webm; codecs="vp8"',
robustness: 'bar' },
]
}
];
return navigator.requestMediaKeySystemAccess('com.example.somesystem', someSystemOptions).then(
function(keySystemAccess) {
// Not shown:
// 1. Use both attributes of keySystemAccess.getConfiguration().audioCapabilities[0]
// and both attributes of keySystemAccess.getConfiguration().videoCapabilities[0]
// to retrieve appropriate stream(s).
// 2. Set video.src.
licenseUrl = 'https://license.example.com/getkey';
serverCertificate = new Uint8Array([ ... ]);
return keySystemAccess.createMediaKeys();
}
).catch(
function(error) {
// Try the next key system.
navigator.requestMediaKeySystemAccess('org.w3.clearkey', clearKeyOptions).then(
function(keySystemAccess) {
// Not shown:
// 1. Use keySystemAccess.getConfiguration().audioCapabilities[0].contentType
// and keySystemAccess.getConfiguration().videoCapabilities[0].contentType
// to retrieve appropriate stream(s).
// 2. Set video.src.
licenseUrl = 'https://license.example.com/clearkey/request';
return keySystemAccess.createMediaKeys();
}
);
}
).catch(
console.error.bind(console, 'Unable to instantiate a key system supporting the required combinations')
);
}
function handleInitData(event) {
var video = event.target;
if (video.mediaKeysObject === undefined) {
video.mediaKeysObject = null; // Prevent entering this path again.
video.pendingSessionData = []; // Will store all initData until the MediaKeys is ready.
createSupportedKeySystem().then(
function(createdMediaKeys) {
video.mediaKeysObject = createdMediaKeys;
if (serverCertificate)
createdMediaKeys.setServerCertificate(serverCertificate);
for (var i = 0; i < video.pendingSessionData.length; i++) {
var data = video.pendingSessionData[i];
makeNewRequest(video.mediaKeysObject, data.initDataType, data.initData);
}
video.pendingSessionData = [];
return video.setMediaKeys(createdMediaKeys);
}
).catch(
console.error.bind(console, 'Failed to create and initialize a MediaKeys object')
);
}
addSession(video, event.initDataType, event.initData);
}
function addSession(video, initDataType, initData) {
if (video.mediaKeysObject) {
makeNewRequest(video.mediaKeysObject, initDataType, initData);
} else {
video.pendingSessionData.push({initDataType: initDataType, initData: initData});
}
}
function makeNewRequest(mediaKeys, initDataType, initData) {
var keySession = mediaKeys.createSession();
keySession.addEventListener("message", licenseRequestReady, false);
keySession.generateRequest(initDataType, initData).catch(
console.error.bind(console, 'Unable to create or initialize key session')
);
}
function licenseRequestReady(event) {
var request = event.message;
var xmlhttp = new XMLHttpRequest();
xmlhttp.keySession = event.target;
xmlhttp.open("POST", licenseUrl);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
var license = new Uint8Array(xmlhttp.response);
xmlhttp.keySession.update(license).catch(
console.error.bind(console, 'update() failed')
);
}
}
xmlhttp.send(request);
}
</script>
<video autoplay onencrypted='handleInitData(event)'></video>
암호화된 이벤트를 MediaKeys 초기화 동안 처리할 필요가 없다면 초기화가 훨씬 단순해집니다. 이는 다른 방식으로 Initialization Data를 제공하거나 MediaKeys
객체를 생성한 후에 소스를 설정함으로써 달성할 수 있습니다. 이 예제는 후자의
방법을 사용합니다.
<script>
var licenseUrl;
var serverCertificate;
var mediaKeys;
// See the previous example for implementations of these functions.
function createSupportedKeySystem() { ... }
function makeNewRequest(mediaKeys, initDataType, initData) { ... }
function licenseRequestReady(event) { ... }
function handleInitData(event) {
makeNewRequest(mediaKeys, event.initDataType, event.initData);
}
createSupportedKeySystem().then(
function(createdMediaKeys) {
mediaKeys = createdMediaKeys;
var video = document.getElementById("v");
video.src = 'foo.webm';
if (serverCertificate)
mediaKeys.setServerCertificate(serverCertificate);
return video.setMediaKeys(mediaKeys);
}
).catch(
console.error.bind(console, 'Failed to create and initialize a MediaKeys object')
);
</script>
<video id="v" autoplay onencrypted='handleInitData(event)'></video>
이것은 모든 이벤트를 사용하는 보다 완전한 예제입니다.
handleMessage()
는 여러 번 호출될 수 있음을 주의하십시오. 예를 들어 여러 왕복(round trips)이 필요한 경우 update
()
호출에 대한 응답으로 호출될 수
있으며, Key System이 메시지를 보낼 필요가 있는 기타 모든 경우에도 호출될 수 있습니다.
<script>
var licenseUrl;
var serverCertificate;
var mediaKeys;
// See previous examples for implementations of these functions.
// createSupportedKeySystem() additionally sets renewalUrl.
function createSupportedKeySystem() { ... }
function handleInitData(event) { ... }
// This replaces the implementation in the previous example.
function makeNewRequest(mediaKeys, initDataType, initData) {
var keySession = mediaKeys.createSession();
keySession.addEventListener('message', handleMessage, false);
keySession.addEventListener('keystatuseschange', handlekeyStatusesChange, false);
keySession.closed.then(
function(reason) {
console.log('Session', this.sessionId, 'closed, reason', reason);
}.bind(keySession)
);
keySession.generateRequest(initDataType, initData).catch(
console.error.bind(console, 'Unable to create or initialize key session')
);
}
function handleMessageResponse(keySession, response) {
var license = new Uint8Array(response);
keySession.update(license).catch(
function(err) {
console.error('update() failed: ' + err);
}
);
}
function sendMessage(type, message, keySession) {
var url = licenseUrl;
if (type == "license-renewal")
url = renewalUrl;
xmlhttp = new XMLHttpRequest();
xmlhttp.keySession = keySession;
xmlhttp.open('POST', url);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4)
handleMessageResponse(xmlhttp.keySession, xmlhttp.response);
}
xmlhttp.send(message);
}
function handleMessage(event) {
sendMessage(event.messageType, event.message, event.target);
}
function handlekeyStatusesChange(event) {
// Evaluate the current state using one of the map-like methods exposed by
// event.target.keyStatuses.
// For example:
event.target.keyStatuses.forEach(function(status, keyId) {
switch (status) {
case "usable":
break;
case "expired":
// Report an expired key.
break;
case "status-pending":
// The status is not yet known. Consider the key unusable until the status is updated.
break;
default:
// Do something with |keyId| and |status|.
}
})
}
createSupportedKeySystem().then(
function(createdMediaKeys) {
mediaKeys = createdMediaKeys;
var video = document.getElementById("v");
video.src = 'foo.webm';
if (serverCertificate)
mediaKeys.setServerCertificate(serverCertificate);
return video.setMediaKeys(mediaKeys);
}
).catch(
console.error.bind(console, 'Failed to create and initialize a MediaKeys object')
);
</script>
<video id='v' src='foo.webm' autoplay></video>
이 예제는 향후 사용을 위해 영구 라이선스를 요청하고 그것을 저장합니다. 또한 나중에 라이선스를 검색하고 파기(destroy)하기 위한 함수들을 제공합니다.
<script>
var licenseUrl;
var serverCertificate;
var mediaKeys;
// See the previous examples for implementations of these functions.
// createSupportedKeySystem() additionally sets persistentState: "required" in each options dictionary.
function createSupportedKeySystem() { ... }
function sendMessage(message, keySession) { ... }
function handleMessage(event) { ... }
// Called if the application does not have a stored sessionId for the media resource.
function makeNewRequest(mediaKeys, initDataType, initData) {
var keySession = mediaKeys.createSession("persistent-license");
keySession.addEventListener('message', handleMessage, false);
keySession.closed.then(
function(reason) {
console.log('Session', this.sessionId, 'closed, reason', reason);
}.bind(keySession)
);
keySession.generateRequest(initDataType, initData).then(
function() {
// Store this.sessionId in the application.
}.bind(keySession)
).catch(
console.error.bind(console, 'Unable to request a persistent license')
);
}
// Called if the application has a stored sessionId for the media resource.
function loadStoredSession(mediaKeys, sessionId) {
var keySession = mediaKeys.createSession("persistent-license");
keySession.addEventListener('message', handleMessage, false);
keySession.closed.then(
function(reason) {
console.log('Session', this.sessionId, 'closed, reason', reason);
}.bind(keySession)
);
keySession.load(sessionId).then(
function(loaded) {
if (!loaded) {
console.error('No stored session with the ID ' + sessionId + ' was found.');
// The application should remove its record of |sessionId|.
return;
}
}
).catch(
console.error.bind(console, 'Unable to load or initialize the stored session with the ID ' + sessionId)
);
}
// Called when the application wants to stop using the session without removing the stored license.
function closeSession(keySession) {
keySession.close();
}
// Called when the application wants to remove the stored license.
// The stored session data has not been completely removed until the promise returned by remove() is fulfilled.
// The remove() call may initiate a series of messages to/from the server that must be completed before this occurs.
function removeStoredSession(keySession) {
keySession.remove().then(
function() {
console.log('Session ' + this.sessionId + ' removed');
// The application should remove its record of this.sessionId.
}.bind(keySession)
).catch(
console.error.bind(console, 'Failed to remove the session')
);
}
// This replaces the implementation in the previous example.
function handleMessageResponse(keySession, response) {
var license = new Uint8Array(response);
keySession.update(license).then(
function() {
// If this was the last required message from the server, the license is
// now stored. Update the application state as appropriate.
}
).catch(
console.error.bind(console, 'update() failed')
);
}
createSupportedKeySystem().then(
function(createdMediaKeys) {
mediaKeys = createdMediaKeys;
var video = document.getElementById("v");
if (serverCertificate)
mediaKeys.setServerCertificate(serverCertificate);
return video.setMediaKeys(mediaKeys);
}
).catch(
console.error.bind(console, 'Failed to create and initialize a MediaKeys object')
);
</script>
<video id='v' src='foo.webm' autoplay></video>
라이선스에 HDCP 정책이 적용되는 미디어가 있는 경우, 애플리케이션은 사전 가져오기 전에 해당 버전을 확인할 수 있습니다.
const status = await video.mediaKeys.getStatusForPolicy({
minHdcpVersion: '1.4'
});
if (status === 'usable') {
// Pre-fetch HD content.
} else { // 'output-restricted'
// Pre-fetch SD content.
}
편집자들은 Aaron Colwell, Alex Russell, Anne van Kesteren, Bob Lund, Boris Zbarsky, Chris Needham, Chris Pearce, David Singer, Domenic Denicola, Frank Galligan, Glenn Adams, Henri Sivonen, Jer Noble, Joe Steele, Joey Parrish, John Simmons, Mark Vickers, Pavel Pergamenshchik, Philip Jägenstedt, Pierre Lemieux, Robert O'Callahan, Ryan Sleevi, Steve Heffernan, Steven Robertson, Theresa O'Connor, Thomás Inskip, Travis Leithead, 및 Xiaohan Wang의 이 명세서에 대한 기여에 대해 감사드립니다. 또한 메일링 리스트와 이슈 참여를 통해 명세서에 기여해 주신 많은 다른 분들께도 감사드립니다.
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: