soiz1's picture
Upload 811 files
30c32c8 verified
raw
history blame
3.64 kB
/* eslint-env worker */
const ScratchCommon = require('./tw-extension-api-common');
const createScratchX = require('./tw-scratchx-compatibility-layer');
const dispatch = require('../dispatch/worker-dispatch');
const log = require('../util/log');
const {isWorker} = require('./tw-extension-worker-context');
const createTranslate = require('./tw-l10n');
const translate = createTranslate(null);
const loadScripts = url => {
if (isWorker) {
importScripts(url);
} else {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.onload = () => resolve();
script.onerror = () => {
reject(new Error(`Error in sandboxed script: ${url}. Check the console for more information.`));
};
script.src = url;
document.body.appendChild(script);
});
}
};
class ExtensionWorker {
constructor () {
this.nextExtensionId = 0;
this.initialRegistrations = [];
this.firstRegistrationPromise = new Promise(resolve => {
this.firstRegistrationCallback = resolve;
});
dispatch.waitForConnection.then(() => {
dispatch.call('extensions', 'allocateWorker').then(async x => {
const [id, extension] = x;
this.workerId = id;
try {
await loadScripts(extension);
await this.firstRegistrationPromise;
const initialRegistrations = this.initialRegistrations;
this.initialRegistrations = null;
Promise.all(initialRegistrations).then(() => dispatch.call('extensions', 'onWorkerInit', id));
} catch (e) {
log.error(e);
dispatch.call('extensions', 'onWorkerInit', id, `${e}`);
}
});
});
this.extensions = [];
}
register (extensionObject) {
const extensionId = this.nextExtensionId++;
this.extensions.push(extensionObject);
const serviceName = `extension.${this.workerId}.${extensionId}`;
const promise = dispatch.setService(serviceName, extensionObject)
.then(() => dispatch.call('extensions', 'registerExtensionService', serviceName));
if (this.initialRegistrations) {
this.firstRegistrationCallback();
this.initialRegistrations.push(promise);
}
return promise;
}
}
global.Scratch = global.Scratch || {};
Object.assign(global.Scratch, ScratchCommon, {
canFetch: () => Promise.resolve(true),
fetch: (url, options) => fetch(url, options),
canOpenWindow: () => Promise.resolve(false),
openWindow: () => Promise.reject(new Error('Scratch.openWindow not supported in sandboxed extensions')),
canRedirect: () => Promise.resolve(false),
redirect: () => Promise.reject(new Error('Scratch.redirect not supported in sandboxed extensions')),
canRecordAudio: () => Promise.resolve(false),
canRecordVideo: () => Promise.resolve(false),
canReadClipboard: () => Promise.resolve(false),
canNotify: () => Promise.resolve(false),
canGeolocate: () => Promise.resolve(false),
canEmbed: () => Promise.resolve(false),
canUnsandbox: () => Promise.resolve(false),
translate
});
/**
* Expose only specific parts of the worker to extensions.
*/
const extensionWorker = new ExtensionWorker();
global.Scratch.extensions = {
register: extensionWorker.register.bind(extensionWorker)
};
global.ScratchExtensions = createScratchX(global.Scratch);