altair-graphql-core
Version:
Several of the core logic for altair graphql client
108 lines • 4.03 kB
JavaScript
import { EvaluatorWorker } from '../../evaluator/worker';
import { urlWithParams } from '../../utils/url';
import { instanceTypes } from './frame-worker';
export class PluginParentWorker extends EvaluatorWorker {
constructor(opts) {
super();
this.opts = opts;
this.messageListeners = [];
this.iframe = this.createIframe();
this.frameReadyPromise = new Promise((resolve) => {
this.iframe.addEventListener('load', () => {
resolve();
});
});
}
createIframe() {
const iframe = document.createElement('iframe');
iframe.id = this.opts.id;
if (this.opts.instanceType === instanceTypes.PANEL) {
iframe.style.width = '100%';
iframe.style.height = '100%';
iframe.style.border = 'none';
iframe.style.display = 'block'; // fixes issue with vertical scrollbar appearing https://stackoverflow.com/a/9131632/3929126
if ('width' in this.opts && this.opts.width) {
iframe.style.minWidth = `${this.opts.width}px`;
}
}
else {
iframe.style.display = 'none';
}
const params = {
...this.opts.additionalParams,
sc: window.location.origin,
id: this.opts.id,
instanceType: this.getInstanceType(),
};
// NOTE: Don't add allow-same-origin to the sandbox attribute!
iframe.sandbox.add('allow-scripts');
if (this.opts.additionalSandboxAttributes) {
this.opts.additionalSandboxAttributes.forEach((attr) => {
iframe.sandbox.add(attr);
});
}
iframe.referrerPolicy = 'no-referrer';
if (this.opts.type === 'scripts') {
const url = urlWithParams(this.opts.sandboxUrl, {
...params,
sandbox_type: 'plugin',
plugin_sandbox_opts: JSON.stringify(this.opts),
});
iframe.src = url;
}
else if (this.opts.type === 'url') {
const url = urlWithParams(this.opts.pluginEntrypointUrl, params);
iframe.src = url;
}
if (!this.opts.disableAppend) {
document.body.appendChild(iframe);
}
return iframe;
}
async frameReady() {
await this.frameReadyPromise;
}
getIframe() {
return this.iframe;
}
getInstanceType() {
return this.opts.instanceType ?? instanceTypes.MAIN;
}
onMessage(handler) {
const listener = (e) => {
if (e.origin !== 'null' || e.source !== this.iframe.contentWindow) {
return;
}
if (e.data.frameId !== this.opts.id) {
// eslint-disable-next-line no-console
console.error('Invalid frameId in data', e.data.frameId, this.opts.id);
return;
}
handler(e.data);
};
window.addEventListener('message', listener, false);
this.messageListeners.push(listener);
}
send(type, payload) {
this.frameReady().then(() => {
this.iframe.contentWindow?.postMessage({ type, payload },
// https://web.dev/articles/sandboxed-iframes#safely_sandboxing_eval
// Note that we're sending the message to "*", rather than some specific
// origin. Sandboxed iframes which lack the 'allow-same-origin' header
// don't have an origin which you can target: you'll have to send to any
// origin, which might alow some esoteric attacks. Validate your output!
'*');
});
}
onError(handler) {
this.iframe.addEventListener('error', handler);
}
destroy() {
// cleanup resources
this.messageListeners.forEach((listener) => {
window.removeEventListener('message', listener);
});
this.iframe.remove();
}
}
//# sourceMappingURL=parent-worker.js.map