Iframe inject (#406)

This commit is contained in:
Harvey Zack authored and GitHub committed 2022-10-20 16:46:26 +08:00
1 parent b5727b60a2
commit d055eb3e60
3 files changed
+227

No files matched your search

+115
View File
@@ -0,0 +1,115 @@
class IframeHelper {
static postMessage(type, data, id = 0) {
window.parent.postMessage(
{
type: type,
data: data,
id: id,
},
'*',
);
}
static async onMessage(event) {
const { type, data, id } = event.data;
switch (type) {
case 'commit':
try {
if (data.match(/resolve\((.*?)\)/)) {
const string = `return new Promise(function(resolve){\n${data}\n})`;
const result = await new Function(string)();
IframeHelper.postMessage('response', result, id);
} else {
IframeHelper.postMessage('response', new Function(data)(), id);
}
} catch (error) {
IframeHelper.postMessage('error', error.message, id);
}
break;
default:
break;
}
}
static inject() {
IframeHelper.postMessage('inject');
window.addEventListener('message', IframeHelper.onMessage);
}
static destroy() {
window.removeEventListener('message', IframeHelper.onMessage);
}
constructor({ iframe, url }) {
this.promises = {};
this.isInject = false;
this.isDestroy = false;
this.$iframe = iframe;
this.onMessage = this.onMessage.bind(this);
window.addEventListener('message', this.onMessage);
this.$iframe.src = url;
}
onMessage(event) {
const { type, data, id } = event.data;
switch (type) {
case 'inject':
this.isInject = true;
break;
case 'destroy':
this.isInject = false;
break;
default:
break;
}
if (this.promises[id]) {
if (type === 'error') {
this.promises[id].reject(new Error(data));
} else {
this.promises[id].resove(data);
}
delete this.promises[id];
}
}
postMessage(type, data) {
return new Promise((resove, reject) => {
(function loop() {
if (this.isInject) {
const id = Date.now();
this.promises[id] = { resove, reject };
this.$iframe.contentWindow.postMessage(
{
type: type,
data: data,
id: id,
},
'*',
);
} else {
if (!this.isDestroy) {
setTimeout(loop.bind(this), 200);
}
}
}.call(this));
});
}
commit(callback) {
const callbackString = callback.toString();
const bodyString = callbackString
.substring(callbackString.indexOf('{') + 1, callbackString.lastIndexOf('}'))
.trim();
return this.postMessage('commit', bodyString);
}
destroy() {
this.isDestroy = true;
window.removeEventListener('message', this.onMessage);
}
}
window['IframeHelper'] = IframeHelper;
+72
View File
@@ -0,0 +1,72 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Artplayer Iframe Inject</title>
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
.container {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
padding: 50px;
box-sizing: border-box;
}
</style>
</head>
<body>
<div class="container">
<iframe id="iframe" frameborder="0" width="100%" height="100%" allowfullscreen="true"></iframe>
</div>
<script src="./iframe.helper.js"></script>
<script>
(async function () {
// Init iframe helper
const helper = new IframeHelper({
iframe: document.getElementById('iframe'),
url: './inner.html',
});
// Instantiate the player and mount the instance in the window
await helper.commit(() => {
window.art = new Artplayer({
container: '.artplayer-app',
url: '../assets/sample/video.mp4',
});
});
// The value of the player can be returned through the resolve method
const currentTime = await helper.commit((resolve) => {
window.art.on('ready', () => {
window.art.seek = 5;
resolve(window.art.currentTime);
});
});
console.log(currentTime);
// The value of the player can be returned through the return
const currentTime2 = await helper.commit(() => {
return window.art.currentTime;
});
console.log(currentTime2);
})();
</script>
</body>
</html>
+40
View File
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Artplayer Iframe Inject</title>
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
.container {
width: 100%;
height: 100%;
}
.artplayer-app {
width: 100%;
height: 100%;
background-color: #000;
}
</style>
</head>
<body>
<div class="container">
<div class="artplayer-app"></div>
</div>
<script src="../uncompiled/artplayer/index.js"></script>
<script src="./iframe.helper.js"></script>
<script>IframeHelper.inject();</script>
</body>
</html>