Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DRM: Fix potential race condition issues on setMediaKeys and quick content switching #1594

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 0 additions & 125 deletions src/main_thread/decrypt/attach_media_keys.ts

This file was deleted.

6 changes: 3 additions & 3 deletions src/main_thread/decrypt/clear_on_stop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,22 @@ import type { IMediaElement } from "../../compat/browser_compatibility_types";
import shouldUnsetMediaKeys from "../../compat/should_unset_media_keys";
import log from "../../log";
import disposeDecryptionResources from "./dispose_decryption_resources";
import MediaKeysInfosStore from "./utils/media_keys_infos_store";
import MediaKeysAttacher from "./utils/media_keys_attacher";

/**
* Clear DRM-related resources that should be cleared when the current content
* stops its playback.
* @param {HTMLMediaElement} mediaElement
* @returns {Promise}
*/
export default function clearOnStop(mediaElement: IMediaElement): Promise<unknown> {
export default async function clearOnStop(mediaElement: IMediaElement): Promise<unknown> {
log.info("DRM: Clearing-up DRM session.");
if (shouldUnsetMediaKeys()) {
log.info("DRM: disposing current MediaKeys.");
return disposeDecryptionResources(mediaElement);
}

const currentState = MediaKeysInfosStore.getState(mediaElement);
const currentState = await MediaKeysAttacher.getAttachedMediaKeysState(mediaElement);
if (
currentState !== null &&
currentState.keySystemOptions.closeSessionsOnStop === true
Expand Down
8 changes: 6 additions & 2 deletions src/main_thread/decrypt/content_decryptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import isNullOrUndefined from "../../utils/is_null_or_undefined";
import { objectValues } from "../../utils/object_values";
import { bytesToHex } from "../../utils/string_parsing";
import TaskCanceller from "../../utils/task_canceller";
import attachMediaKeys from "./attach_media_keys";
import createOrLoadSession from "./create_or_load_session";
import type { ICodecSupportList } from "./find_key_system";
import type { IMediaKeysInfos } from "./get_media_keys";
Expand All @@ -57,6 +56,7 @@ import {
areSomeKeyIdsContainedIn,
} from "./utils/key_id_comparison";
import type KeySessionRecord from "./utils/key_session_record";
import MediaKeysAttacher from "./utils/media_keys_attacher";

/**
* Module communicating with the Content Decryption Module (or CDM) to be able
Expand Down Expand Up @@ -287,8 +287,12 @@ export default class ContentDecryptor extends EventEmitter<IContentDecryptorEven
};

log.debug("DRM: Attaching current MediaKeys");
attachMediaKeys(mediaElement, stateToAttach, this._canceller.signal)
MediaKeysAttacher.attach(mediaElement, stateToAttach)
.then(async () => {
if (this._isStopped()) {
// We might be stopped since then
return;
}
this._stateData.isMediaKeysAttached = MediaKeyAttachmentStatus.Attached;

const { serverCertificate } = options;
Expand Down
15 changes: 2 additions & 13 deletions src/main_thread/decrypt/dispose_decryption_resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
*/

import type { IMediaElement } from "../../compat/browser_compatibility_types";
import { setMediaKeys } from "../../compat/eme/set_media_keys";
import log from "../../log";
import MediaKeysInfosStore from "./utils/media_keys_infos_store";
import MediaKeysAttacher from "./utils/media_keys_attacher";

/**
* Free up all ressources taken by the content decryption logic.
Expand All @@ -27,14 +25,5 @@ import MediaKeysInfosStore from "./utils/media_keys_infos_store";
export default async function disposeDecryptionResources(
mediaElement: IMediaElement,
): Promise<unknown> {
const currentState = MediaKeysInfosStore.getState(mediaElement);
if (currentState === null) {
return undefined;
}

log.info("DRM: Disposing of the current MediaKeys");
const { loadedSessionsStore } = currentState;
MediaKeysInfosStore.clearState(mediaElement);
await loadedSessionsStore.closeAllSessions();
return setMediaKeys(currentState.emeImplementation, mediaElement, null);
return MediaKeysAttacher.clearMediaKeys(mediaElement);
}
4 changes: 2 additions & 2 deletions src/main_thread/decrypt/find_key_system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import arrayIncludes from "../../utils/array_includes";
import flatMap from "../../utils/flat_map";
import isNullOrUndefined from "../../utils/is_null_or_undefined";
import type { CancellationSignal } from "../../utils/task_canceller";
import MediaKeysInfosStore from "./utils/media_keys_infos_store";
import MediaKeysAttacher from "./utils/media_keys_attacher";

type MediaKeysRequirement = "optional" | "required" | "not-allowed";

Expand Down Expand Up @@ -445,7 +445,7 @@ export default function getMediaKeySystemAccess(

const chosenType = keySystemsType[index];

const currentState = MediaKeysInfosStore.getState(mediaElement);
const currentState = await MediaKeysAttacher.getAttachedMediaKeysState(mediaElement);
if (currentState !== null) {
if (eme.implementation === currentState.emeImplementation.implementation) {
// Fast way to find a compatible keySystem if the currently loaded
Expand Down
4 changes: 2 additions & 2 deletions src/main_thread/decrypt/get_key_system_configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

import type { IMediaElement } from "../../compat/browser_compatibility_types";
import MediaKeysInfosStore from "./utils/media_keys_infos_store";
import MediaKeysAttacher from "./utils/media_keys_attacher";

/**
* Returns the name of the current key system used as well as its configuration,
Expand All @@ -26,7 +26,7 @@ import MediaKeysInfosStore from "./utils/media_keys_infos_store";
export default function getKeySystemConfiguration(
mediaElement: IMediaElement,
): [string, MediaKeySystemConfiguration] | null {
const currentState = MediaKeysInfosStore.getState(mediaElement);
const currentState = MediaKeysAttacher.getAwaitedState(mediaElement);
if (currentState === null) {
return null;
}
Expand Down
4 changes: 2 additions & 2 deletions src/main_thread/decrypt/get_media_keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import getMediaKeySystemAccess from "./find_key_system";
import type { ICodecSupportList } from "./find_key_system";
import type { IMediaKeySessionStores } from "./types";
import LoadedSessionsStore from "./utils/loaded_sessions_store";
import MediaKeysInfosStore from "./utils/media_keys_infos_store";
import MediaKeysAttacher from "./utils/media_keys_attacher";
import PersistentSessionsStore from "./utils/persistent_sessions_store";
import ServerCertificateStore from "./utils/server_certificate_store";

Expand Down Expand Up @@ -94,7 +94,7 @@ export default async function getMediaKeysInfos(
}

const { options, mediaKeySystemAccess, askedConfiguration, codecSupport } = evt.value;
const currentState = MediaKeysInfosStore.getState(mediaElement);
const currentState = await MediaKeysAttacher.getAttachedMediaKeysState(mediaElement);
const persistentSessionsStore = createPersistentSessionsStorage(options);

if (
Expand Down
4 changes: 2 additions & 2 deletions src/main_thread/decrypt/init_media_keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ import type { IMediaElement } from "../../compat/browser_compatibility_types";
import log from "../../log";
import type { IKeySystemOption } from "../../public_types";
import type { CancellationSignal } from "../../utils/task_canceller";
import { disableMediaKeys } from "./attach_media_keys";
import type { IMediaKeysInfos } from "./get_media_keys";
import getMediaKeysInfos from "./get_media_keys";
import MediaKeysAttacher from "./utils/media_keys_attacher";

/**
* Get media keys infos from key system configs then attach media keys to media element.
Expand Down Expand Up @@ -48,7 +48,7 @@ export default async function initMediaKeys(

if (shouldDisableOldMediaKeys) {
log.debug("DRM: Disabling old MediaKeys");
await disableMediaKeys(mediaElement);
await MediaKeysAttacher.clearMediaKeys(mediaElement);
}
return mediaKeysInfo;
}
Loading
Loading