UNPKG

rx-player

Version:
141 lines (134 loc) 5.31 kB
/** * Copyright 2015 CANAL+ Group * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import type { IMediaKeys } from "../../../compat/browser_compatibility_types"; import hashBuffer from "../../../utils/hash_buffer"; /** * Keep track of server certificate which have been set for a MediaKeys. * As it is impossible for a MediaKeys to have his server certificate reset * or updated, we consider that once it has been set, it will remain set until * the MediaKeys instance is killed. * * So, a WeakMap helps keeping a trace of which server certificate (identified * with a unique hash) is set on a MediaKeys. * `null` indicate that we don't know (and not `undefined`, because this is the * default value for when a WeakMap has no value for a key) which server * certificate is attached to a MediaKeys instance (most likely because related * EME APIs failed or had an unexpected behavior). */ const serverCertificateHashesMap = new WeakMap< IMediaKeys, { hash: number; serverCertificate: Uint8Array } | null >(); /** ServerCertificateStore */ export default { /** * Tells the ServerCertificateStore that you begin to call the APIs to set a * ServerCertificate on `mediaKeys`. * * Calling this function is necessary due to how server certificate work * currently in EME APIs: * Because right now, it is impossible to tell if a MediaKeys instance has an * attached ServerCertificate or not when the corresponding API fails or if it * never answers, we prefer to announce through this function that the current * server certificate attached to this MediaKeys is for now invalid. * @param {MediaKeys | Object} mediaKeys */ prepare(mediaKeys: IMediaKeys): void { serverCertificateHashesMap.set(mediaKeys, null); }, /** * Attach a new server certificate to a MediaKeys in the * ServerCertificateStore. * * Only one server certificate should ever be attached to a MediaKeys * instance and the `prepare` function should have been called before any * action to update the server certificate took place (this function does not * enforce either of those behaviors). * @param {MediaKeys | Object} mediaKeys * @param {ArrayBufferView | BufferSource} serverCertificate */ set(mediaKeys: IMediaKeys, serverCertificate: ArrayBufferView | BufferSource): void { const formattedServerCertificate: Uint8Array = serverCertificate instanceof Uint8Array ? serverCertificate : new Uint8Array( serverCertificate instanceof ArrayBuffer ? serverCertificate : serverCertificate.buffer, ); const hash = hashBuffer(formattedServerCertificate); serverCertificateHashesMap.set(mediaKeys, { hash, serverCertificate: formattedServerCertificate, }); }, /** * Returns `true` if the MediaKeys instance has an attached ServerCertificate. * Returns `false` if it doesn't. * * Returns `undefined` if we cannot know, most likely because related EME APIs * failed or had an unexpected behavior. * @param {MediaKeys} mediaKeys * @returns {Boolean|undefined} */ hasOne(mediaKeys: IMediaKeys): boolean | undefined { const currentServerCertificate = serverCertificateHashesMap.get(mediaKeys); if (currentServerCertificate === undefined) { return false; } if (currentServerCertificate === null) { return undefined; } return true; }, /** * Returns `true` if the given `mediaKeys` has `serverCertificate` attached to * it. * Returns `false` either if it doesn't of if we doesn't know if it does. * @param {MediaKeys | Object} mediaKeys * @param {ArrayBufferView | BufferSource} serverCertificate * @returns {boolean} */ has(mediaKeys: IMediaKeys, serverCertificate: ArrayBufferView | BufferSource): boolean { const serverCertificateHash = serverCertificateHashesMap.get(mediaKeys); if (serverCertificateHash === undefined || serverCertificateHash === null) { return false; } const { hash: oldHash, serverCertificate: oldServerCertificate } = serverCertificateHash; const newServerCertificate: Uint8Array = serverCertificate instanceof Uint8Array ? serverCertificate : new Uint8Array( serverCertificate instanceof ArrayBuffer ? serverCertificate : serverCertificate.buffer, ); const newHash = hashBuffer(newServerCertificate); if ( newHash !== oldHash || oldServerCertificate.length !== newServerCertificate.length ) { return false; } for (let i = 0; i < oldServerCertificate.length; i++) { if (oldServerCertificate[i] !== newServerCertificate[i]) { return false; } } return true; }, };