rx-player
Version:
Canal+ HTML5 Video Player
134 lines (128 loc) • 4.85 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,
IMediaKeySystemAccess,
} from "../../compat/browser_compatibility_types";
import { EncryptedMediaError, isKnownError } from "../../errors";
import log from "../../log";
import type { IPlayerError } from "../../public_types";
import ServerCertificateStore from "./utils/server_certificate_store";
/**
* Call the setServerCertificate API with the given certificate.
* Resolves on success, rejects on failure.
*
* TODO Handle returned value?
* From the spec:
* - setServerCertificate resolves with true if everything worked
* - it resolves with false if the CDM does not support server
* certificates.
*
* @param {MediaKeys} mediaKeys
* @param {ArrayBuffer} serverCertificate
* @param {MediaKeySystemAccess} mediaKeySystemAccess - The
* `MediaKeySystemAccess` that produced the `MediaKeys` instance provided.
* This parameter is mainly useful for error generation.
* @returns {Promise}
*/
async function setServerCertificate(
mediaKeys: IMediaKeys,
serverCertificate: BufferSource,
mediaKeySystemAccess: IMediaKeySystemAccess,
): Promise<unknown> {
try {
const res = await mediaKeys.setServerCertificate(serverCertificate);
// Note: Even if `setServerCertificate` technically should return a
// Promise.<boolean>, this is not technically always true.
// Thus we prefer to return unknown here.
return res;
} catch (error) {
log.warn(
"DRM",
"mediaKeys.setServerCertificate returned an error",
error instanceof Error ? error : "",
);
const reason =
error instanceof Error ? error.toString() : "`setServerCertificate` error";
throw new EncryptedMediaError("LICENSE_SERVER_CERTIFICATE_ERROR", reason, {
keyStatuses: undefined,
keySystemConfiguration: mediaKeySystemAccess.getConfiguration(),
keySystem: mediaKeySystemAccess.keySystem,
});
}
}
/**
* Call the setCertificate API. If it fails just emit the error as warning
* and complete.
* @param {MediaKeys} mediaKeys
* @param {ArrayBuffer} serverCertificate
* @param {MediaKeySystemAccess} mediaKeySystemAccess - The
* `MediaKeySystemAccess` that produced the `MediaKeys` instance provided.
* This parameter is mainly useful for error generation.
* @returns {Promise.<Object>}
*/
export default async function trySettingServerCertificate(
mediaKeys: IMediaKeys,
serverCertificate: BufferSource,
mediaKeySystemAccess: IMediaKeySystemAccess,
): Promise<
| { type: "success"; value: unknown }
| { type: "already-has-one" }
| { type: "method-not-implemented" }
| { type: "error"; value: IPlayerError }
> {
if (ServerCertificateStore.hasOne(mediaKeys) === true) {
log.info("DRM", "The MediaKeys already has a server certificate, skipping...");
return { type: "already-has-one" };
}
if (typeof mediaKeys.setServerCertificate !== "function") {
log.warn(
"DRM",
"Could not set the server certificate." +
" mediaKeys.setServerCertificate is not a function",
);
return { type: "method-not-implemented" };
}
log.info("DRM", "Setting server certificate on the MediaKeys");
// Because of browser errors, or a user action that can lead to interrupting
// server certificate setting, we might be left in a status where we don't
// know if we attached the server certificate or not.
// Calling `prepare` allow to invalidate temporarily that status.
ServerCertificateStore.prepare(mediaKeys);
try {
const result = await setServerCertificate(
mediaKeys,
serverCertificate,
mediaKeySystemAccess,
);
ServerCertificateStore.set(mediaKeys, serverCertificate);
return { type: "success", value: result };
} catch (error) {
const formattedErr = isKnownError(error)
? error
: new EncryptedMediaError(
"LICENSE_SERVER_CERTIFICATE_ERROR",
"Unknown error when setting the server certificate.",
{
keyStatuses: undefined,
keySystemConfiguration: mediaKeySystemAccess.getConfiguration(),
keySystem: mediaKeySystemAccess.keySystem,
},
);
return { type: "error" as const, value: formattedErr };
}
}
export { trySettingServerCertificate, setServerCertificate };