rx-player
Version:
Canal+ HTML5 Video Player
141 lines (134 loc) • 5.31 kB
text/typescript
/**
* 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;
},
};