Skip to content

Commit

Permalink
feat: enable uninstalling PatchedMediaKeysApple (shaka-project#4471)
Browse files Browse the repository at this point in the history
  • Loading branch information
martinstark authored Sep 23, 2022
1 parent 83a420f commit 7166f0c
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 1 deletion.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Jun Hong Chong <[email protected]>
Jürgen Kartnaller <[email protected]>
JW Player <*@jwplayer.com>
Lucas Gabriel Sánchez <[email protected]>
Martin Stark <[email protected]>
Matthias Van Parijs <[email protected]>
Mattias Wadman <[email protected]>
Mohamed Rashid <[email protected]>
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTORS
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ Jun Hong Chong <[email protected]>
Jürgen Kartnaller <[email protected]>
Leandro Ribeiro Moreira <[email protected]>
Lucas Gabriel Sánchez <[email protected]>
Martin Stark <[email protected]>
Matias Russitto <[email protected]>
Matthias Van Parijs <[email protected]>
Mattias Wadman <[email protected]>
Expand Down
7 changes: 7 additions & 0 deletions docs/tutorials/fairplay.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ Modern EME yet, you can use legacy Apple Media Keys with:
shaka.polyfill.PatchedMediaKeysApple.install();
```

If you need to use both legacy and Modern EME, for example if you have to support
multiple DRM providers, it is possible to enable uninstalling the polyfill:
```js
shaka.polyfill.PatchedMediaKeysApple.install(/* enableUninstall= */ true);
shaka.polyfill.PatchedMediaKeysApple.uninstall();
```

The support in each case would be the following:

| |Modern EME |legacy Apple Media Keys|
Expand Down
56 changes: 55 additions & 1 deletion lib/polyfill/patchedmediakeys_apple.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,33 @@ goog.require('shaka.util.StringUtils');
shaka.polyfill.PatchedMediaKeysApple = class {
/**
* Installs the polyfill if needed.
* @param {boolean} enableUninstall enables uninstalling the polyfill
* @export
*/
static install() {
static install(enableUninstall = false) {
if (!window.HTMLVideoElement || !window.WebKitMediaKeys) {
// No HTML5 video or no prefixed EME.
return;
}

if (enableUninstall) {
this.enableUninstall = true;
this.originalHTMLMediaElementPrototypeMediaKeys =
/** @type {!Object} */ (
Object.getOwnPropertyDescriptor(
// eslint-disable-next-line no-restricted-syntax
HTMLMediaElement.prototype, 'mediaKeys',
)
);
// eslint-disable-next-line no-restricted-syntax
this.originalHTMLMediaElementPrototypeSetMediaKeys = HTMLMediaElement
.prototype.setMediaKeys;
this.originalWindowMediaKeys = window.MediaKeys;
this.originalWindowMediaKeySystemAccess = window.MediaKeySystemAccess;
this.originalNavigatorRequestMediaKeySystemAccess = navigator
.requestMediaKeySystemAccess;
}

shaka.log.info('Using Apple-prefixed EME');

// Alias
Expand All @@ -59,6 +78,41 @@ shaka.polyfill.PatchedMediaKeysApple = class {
window.shakaMediaKeysPolyfill = true;
}

/**
* Uninstalls the polyfill if needed and enabled.
* @export
*/
static uninstall() {
if (!this.enableUninstall) {
return;
}

shaka.log.info('Un-installing Apple-prefixed EME');

this.enableUninstall = false;
Object.defineProperty(
// eslint-disable-next-line no-restricted-syntax
HTMLMediaElement.prototype,
'mediaKeys',
this.originalHTMLMediaElementPrototypeMediaKeys,
);
// eslint-disable-next-line no-restricted-syntax
HTMLMediaElement.prototype.setMediaKeys = this
.originalHTMLMediaElementPrototypeSetMediaKeys;
window.MediaKeys = this.originalWindowMediaKeys;
window.MediaKeySystemAccess = this.originalWindowMediaKeySystemAccess;
navigator.requestMediaKeySystemAccess = this
.originalNavigatorRequestMediaKeySystemAccess;

this.originalWindowMediaKeys = null;
this.originalWindowMediaKeySystemAccess = null;
this.originalHTMLMediaElementPrototypeSetMediaKeys = null;
this.originalNavigatorRequestMediaKeySystemAccess = null;
this.originalHTMLMediaElementPrototypeMediaKeys = null;

window.shakaMediaKeysPolyfill = false;
}

/**
* An implementation of navigator.requestMediaKeySystemAccess.
* Retrieves a MediaKeySystemAccess object.
Expand Down
124 changes: 124 additions & 0 deletions test/polyfill/patchedmediakeys_apple_unit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
describe('PatchedMediaKeys_Apple', () => {
const PatchedMediaKeysApple = shaka.polyfill.PatchedMediaKeysApple;
let originalMediaKeys;
let originalHTMLMediaElementPrototypeSetMediaKeys;
let originalWindowMediaKeys;
let originalWindowMediaKeySystemAccess;
let originalNavigatorRequestMediaKeySystemAccess;
let originalHTMLSVideoElement;
let originalWebKitMediaKeys;

beforeEach(() => {
originalHTMLSVideoElement = window.HTMLVideoElement;
originalWebKitMediaKeys = window.WebKitMediaKeys;

Object.defineProperty(window,
'HTMLVideoElement', {value: {}, configurable: true, writable: true});
Object.defineProperty(window,
'WebKitMediaKeys', {value: {}, configurable: true, writable: true});

originalMediaKeys = /** @type {!Object} */ (
Object.getOwnPropertyDescriptor(
// eslint-disable-next-line no-restricted-syntax
HTMLMediaElement.prototype, 'mediaKeys',
)
);

// eslint-disable-next-line no-restricted-syntax
originalHTMLMediaElementPrototypeSetMediaKeys = HTMLMediaElement
.prototype.setMediaKeys;
originalWindowMediaKeys = window.MediaKeys;
originalWindowMediaKeySystemAccess = window.MediaKeySystemAccess;
originalNavigatorRequestMediaKeySystemAccess = navigator
.requestMediaKeySystemAccess;

delete window.shakaMediaKeysPolyfill;
});

afterEach(() => {
window.HTMLVideoElement = originalHTMLSVideoElement;
window.WebKitMediaKeys = originalWebKitMediaKeys;

Object.defineProperty(
// eslint-disable-next-line no-restricted-syntax
HTMLMediaElement.prototype,
'mediaKeys',
originalMediaKeys,
);

// eslint-disable-next-line no-restricted-syntax
HTMLMediaElement
.prototype.setMediaKeys =
originalHTMLMediaElementPrototypeSetMediaKeys;
window.MediaKeys = originalWindowMediaKeys;
window.MediaKeySystemAccess = originalWindowMediaKeySystemAccess;
navigator
.requestMediaKeySystemAccess =
originalNavigatorRequestMediaKeySystemAccess;

delete window.shakaMediaKeysPolyfill;
});

describe('install', () => {
it('should override browser globals', () => {
shaka.polyfill.PatchedMediaKeysApple.install();

expect(shaka.polyfill.PatchedMediaKeysApple.enableUninstall)
.toBe(undefined);

expect(
originalHTMLMediaElementPrototypeSetMediaKeys,
).not.toEqual(
// eslint-disable-next-line no-restricted-syntax
HTMLMediaElement.prototype.setMediaKeys,
);

expect(
Object.getOwnPropertyDescriptor(
// eslint-disable-next-line no-restricted-syntax
HTMLMediaElement.prototype, 'mediaKeys',
).value,
).toBeNull();

// eslint-disable-next-line no-restricted-syntax
expect(HTMLMediaElement.prototype.setMediaKeys)
.toEqual(PatchedMediaKeysApple.setMediaKeys);

expect(window.MediaKeys).toEqual(PatchedMediaKeysApple.MediaKeys);
expect(window.MediaKeySystemAccess)
.toEqual(PatchedMediaKeysApple.MediaKeySystemAccess);
expect(navigator.requestMediaKeySystemAccess)
.toEqual(PatchedMediaKeysApple.requestMediaKeySystemAccess);
expect(window.shakaMediaKeysPolyfill).toBe(true);
});
});

describe('uninstall', () => {
it('should restore browser globals', () => {
shaka.polyfill.PatchedMediaKeysApple.install(true);

expect(shaka.polyfill.PatchedMediaKeysApple.enableUninstall)
.toBe(true);

shaka.polyfill.PatchedMediaKeysApple.uninstall();

expect(
Object.getOwnPropertyDescriptor(
// eslint-disable-next-line no-restricted-syntax
HTMLMediaElement.prototype, 'mediaKeys',
).value,
).not.toBeNull();

// eslint-disable-next-line no-restricted-syntax
expect(HTMLMediaElement.prototype.setMediaKeys)
.toEqual(originalHTMLMediaElementPrototypeSetMediaKeys);

expect(window.MediaKeys).toEqual(originalWindowMediaKeys);
expect(window.MediaKeySystemAccess)
.toEqual(originalWindowMediaKeySystemAccess);
expect(navigator.requestMediaKeySystemAccess)
.toEqual(originalNavigatorRequestMediaKeySystemAccess);
expect(window.shakaMediaKeysPolyfill).toBe(false);
});
});
});

0 comments on commit 7166f0c

Please sign in to comment.