Add Scratch.fetch, Scratch.openWindow, and Scratch.redirect stubs in sandboxed extensions
Also includes the appropriate can[Fetch|OpenWindow|Redirect] methods. Fetching is always allowed. The other methods are always rejected. The Worker-based sandbox does not have a window.open method and the iframe-based sandbox has a feature policy that should prevent them from opening windows already.
This commit is contained in:
1 parent
c0a1c3db83
commit
47adea8107
2 files changed
+66
-1
No files matched your search
@@ -69,7 +69,14 @@ class ExtensionWorker {
|
||||
}
|
||||
|
||||
global.Scratch = global.Scratch || {};
|
||||
Object.assign(global.Scratch, ScratchCommon);
|
||||
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'))
|
||||
});
|
||||
|
||||
/**
|
||||
* Expose only specific parts of the worker to extensions.
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
const {test} = require('tap');
|
||||
|
||||
/* globals Request */
|
||||
global.Request = class {
|
||||
constructor (url) {
|
||||
this.url = url;
|
||||
}
|
||||
};
|
||||
global.fetch = (url, options = {}) => (
|
||||
Promise.resolve(`[Response ${url instanceof Request ? url.url : url} options=${JSON.stringify(options)}]`)
|
||||
);
|
||||
|
||||
// Need to trick the extension API to think it's running in a worker
|
||||
// It will not actually use this object ever.
|
||||
global.self = {};
|
||||
// This will install extension worker APIs onto `global`
|
||||
require('../../src/extension-support/extension-worker');
|
||||
|
||||
test('basic API', t => {
|
||||
t.type(global.Scratch.extensions.register, 'function');
|
||||
t.equal(global.Scratch.ArgumentType.BOOLEAN, 'Boolean');
|
||||
t.equal(global.Scratch.BlockType.REPORTER, 'reporter');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('not unsandboxed', t => {
|
||||
t.not(global.Scratch.extensions.unsandboxed, true);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('Cast', t => {
|
||||
// Cast is thoroughly tested elsewhere
|
||||
t.equal(global.Scratch.Cast.toString(5), '5');
|
||||
t.equal(global.Scratch.Cast.toNumber(' 5'), 5);
|
||||
t.equal(global.Scratch.Cast.toBoolean('true'), true);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('fetch', async t => {
|
||||
t.equal(await global.Scratch.canFetch('https://untrusted.example/'), true);
|
||||
t.equal(await global.Scratch.fetch('https://untrusted.example/'), '[Response https://untrusted.example/ options={}]');
|
||||
t.equal(await global.Scratch.fetch('https://untrusted.example/', {
|
||||
method: 'POST'
|
||||
}), `[Response https://untrusted.example/ options={"method":"POST"}]`);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('openWindow', async t => {
|
||||
t.equal(await global.Scratch.canOpenWindow('https://example.com/'), false);
|
||||
await t.rejects(global.Scratch.openWindow('https://example.com/'), /^Scratch\.openWindow not supported in sandboxed extensions$/);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('redirect', async t => {
|
||||
t.equal(await global.Scratch.canRedirect('https://example.com/'), false);
|
||||
await t.rejects(global.Scratch.redirect('https://example.com/'), /^Scratch\.redirect not supported in sandboxed extensions$/);
|
||||
t.end();
|
||||
});
|
||||
Reference in new issue
Block a user