This is a breaking change. Replaces logic that was previously in our scratch-gui fork. Upstream does the opposite; they disable cloud variables when video sensing is used. We can't do the same because of custom extensions. Disabling all custom extensions when video sensing is used would be too limiting. The concern with custom extensions is not that they will steal private skins, but that a project could use their blocks to fetch() color information to a remote server similar to cloud variables. The end result is not dissimilar: Cloud variables and video sensing shouldn't be used together.
117 lines
3.3 KiB
JavaScript
117 lines
3.3 KiB
JavaScript
const {test} = require('tap');
|
|
const Runtime = require('../../src/engine/runtime');
|
|
const VM = require('../../src/virtual-machine');
|
|
|
|
const mockRenderer = () => ({
|
|
setLayerGroupOrdering: () => {
|
|
// not relevant to this test
|
|
},
|
|
|
|
privateSkinAccess: true,
|
|
setPrivateSkinAccess (enabled) {
|
|
this.privateSkinAccess = enabled;
|
|
}
|
|
});
|
|
|
|
test('baseline: no external communication methods', t => {
|
|
const rt = new Runtime();
|
|
rt.attachRenderer(mockRenderer());
|
|
t.equal(rt.renderer.privateSkinAccess, true);
|
|
t.end();
|
|
});
|
|
|
|
test('throws errors for unknown method', t => {
|
|
t.plan(1);
|
|
const rt = new Runtime();
|
|
try {
|
|
rt.setExternalCommunicationMethod('something fake', true);
|
|
} catch (e) {
|
|
t.equal(e.message, 'Unknown method: something fake');
|
|
}
|
|
t.end();
|
|
});
|
|
|
|
test('communication method enabled after attaching renderer', t => {
|
|
const rt = new Runtime();
|
|
rt.attachRenderer(mockRenderer());
|
|
rt.setExternalCommunicationMethod('cloudVariables', true);
|
|
t.equal(rt.renderer.privateSkinAccess, false);
|
|
t.end();
|
|
});
|
|
|
|
test('communication method enabled before attaching renderer', t => {
|
|
const rt = new Runtime();
|
|
rt.setExternalCommunicationMethod('cloudVariables', true);
|
|
rt.attachRenderer(mockRenderer());
|
|
t.equal(rt.renderer.privateSkinAccess, false);
|
|
t.end();
|
|
});
|
|
|
|
test('disable enforcement', t => {
|
|
const rt = new Runtime();
|
|
rt.attachRenderer(mockRenderer());
|
|
rt.setEnforcePrivacy(false);
|
|
rt.setExternalCommunicationMethod('cloudVariables', true);
|
|
t.equal(rt.renderer.privateSkinAccess, true);
|
|
t.end();
|
|
});
|
|
|
|
test('multiple features toggled', t => {
|
|
const rt = new Runtime();
|
|
rt.attachRenderer(mockRenderer());
|
|
rt.setExternalCommunicationMethod('cloudVariables', true);
|
|
t.equal(rt.renderer.privateSkinAccess, false);
|
|
rt.setExternalCommunicationMethod('customExtensions', true);
|
|
t.equal(rt.renderer.privateSkinAccess, false);
|
|
rt.setExternalCommunicationMethod('cloudVariables', false);
|
|
t.equal(rt.renderer.privateSkinAccess, false);
|
|
rt.setExternalCommunicationMethod('customExtensions', false);
|
|
t.equal(rt.renderer.privateSkinAccess, true);
|
|
t.end();
|
|
});
|
|
|
|
test('cloud variables', t => {
|
|
const rt = new Runtime();
|
|
rt.attachRenderer(mockRenderer());
|
|
|
|
rt.addCloudVariable();
|
|
t.equal(rt.renderer.privateSkinAccess, false);
|
|
|
|
rt.addCloudVariable();
|
|
t.equal(rt.renderer.privateSkinAccess, false);
|
|
|
|
rt.removeCloudVariable();
|
|
t.equal(rt.renderer.privateSkinAccess, false);
|
|
|
|
rt.removeCloudVariable();
|
|
t.equal(rt.renderer.privateSkinAccess, true);
|
|
|
|
t.end();
|
|
});
|
|
|
|
test('custom extensions', async t => {
|
|
const vm = new VM();
|
|
vm.attachRenderer(mockRenderer());
|
|
|
|
vm.extensionManager.securityManager.getSandboxMode = () => 'unsandboxed';
|
|
global.document = {
|
|
createElement: () => {
|
|
const element = {};
|
|
setTimeout(() => {
|
|
global.Scratch.extensions.register({
|
|
getInfo: () => ({})
|
|
});
|
|
});
|
|
return element;
|
|
},
|
|
body: {
|
|
appendChild: () => {}
|
|
}
|
|
};
|
|
|
|
t.equal(vm.renderer.privateSkinAccess, true);
|
|
await vm.extensionManager.loadExtensionURL('data:application/javascript;,');
|
|
t.equal(vm.renderer.privateSkinAccess, false);
|
|
t.end();
|
|
});
|