Skip to content

Commit

Permalink
fix: Don't use copyStyleSheets with documentPIP (videojs#8314)
Browse files Browse the repository at this point in the history
* Don't use copyStyleSheets

* Move to dom.js

* Add tests

* Address feedback
  • Loading branch information
beaufortfrancois authored Jul 7, 2023
1 parent c11d213 commit 8dd98f6
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/js/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -3095,9 +3095,9 @@ class Player extends Component {
return window.documentPictureInPicture.requestWindow({
// The aspect ratio won't be correct, Chrome bug https://crbug.com/1407629
width: this.videoWidth(),
height: this.videoHeight(),
copyStyleSheets: true
height: this.videoHeight()
}).then(pipWindow => {
Dom.copyStyleSheetsToWindow(pipWindow);
this.el_.parentNode.insertBefore(pipContainer, this.el_);

pipWindow.document.body.append(this.el_);
Expand Down
27 changes: 27 additions & 0 deletions src/js/utils/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -857,3 +857,30 @@ export function computedStyle(el, prop) {

return '';
}

/**
* Copy document style sheets to another window.
*
* @param {Window} win
* The window element you want to copy the document style sheets to.
*
*/
export function copyStyleSheetsToWindow(win) {
[...document.styleSheets].forEach((styleSheet) => {
try {
const cssRules = [...styleSheet.cssRules].map((rule) => rule.cssText).join('');
const style = document.createElement('style');

style.textContent = cssRules;
win.document.head.appendChild(style);
} catch (e) {
const link = document.createElement('link');

link.rel = 'stylesheet';
link.type = styleSheet.type;
link.media = styleSheet.media;
link.href = styleSheet.href;
win.document.head.appendChild(link);
}
});
}
1 change: 1 addition & 0 deletions test/unit/player.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2919,6 +2919,7 @@ QUnit.test('docPiP moves player and triggers events', function(assert) {
const fakePiPWindow = document.createElement('div');

fakePiPWindow.document = {
head: document.createElement('div'),
body: document.createElement('div')
};
fakePiPWindow.querySelector = function(sel) {
Expand Down
49 changes: 49 additions & 0 deletions test/unit/utils/dom.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -686,3 +686,52 @@ QUnit.test('isSingleLeftClick() checks return values for mousedown event', funct

assert.ok(Dom.isSingleLeftClick(mouseEvent), 'a touch event on simulated mobiles is a single left click');
});

QUnit.test('Dom.copyStyleSheetsToWindow() copies all style sheets to a window', function(assert) {
const fakeWindow = document.createElement('div');
const done = assert.async();

assert.expect(7);

fakeWindow.document = {
head: document.createElement('div')
};

const style1 = document.createElement('style');

style1.textContent = 'body { background: white; }';
document.head.appendChild(style1);

const style2 = document.createElement('style');

style2.textContent = 'body { margin: 0px; }';
document.head.appendChild(style2);

const link = document.createElement('link');

link.rel = 'stylesheet';
link.type = 'text/css';
link.media = 'print';
link.href = 'http://asdf.com/styles.css';

const containsRulesFromStyle = (el) => {
return Boolean([...fakeWindow.document.head.querySelectorAll('style')].find(s => {
return s.textContent.includes(el.textContent);
}));
};

link.onload = link.onerror = () => {
Dom.copyStyleSheetsToWindow(fakeWindow);
assert.strictEqual(fakeWindow.document.head.querySelectorAll('style, link').length, document.styleSheets.length, 'the fake window has as many <style> or <link> elements as document.styleSheets');
assert.true(containsRulesFromStyle(style1), 'a <style> in the fake window contains content from first <style> element');
assert.true(containsRulesFromStyle(style2), 'a <style> in the fake window contains content from second <style> element');
assert.strictEqual(fakeWindow.document.head.querySelectorAll('link[rel=stylesheet]').length, 1, 'the fake window has one <link> stylesheet element');
const fakeWindowLink = fakeWindow.document.head.querySelectorAll('link[rel=stylesheet]')[0];

assert.strictEqual(fakeWindowLink.type, link.type, 'the <style> type attribute in the fake window is the one from <link> element');
assert.strictEqual(fakeWindowLink.href, link.href, 'the <style> href attribute in the fake window is the one from <link> element');
assert.strictEqual(fakeWindowLink.media, link.media, 'the <style> media attribute in the fake window is the one from <link> element');
done();
};
document.head.appendChild(link);
});

0 comments on commit 8dd98f6

Please sign in to comment.