From 846c0800b198d8d1b03e9edd54c9db6385885a04 Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Fri, 6 Apr 2018 13:17:55 -0700 Subject: [PATCH] feat(Page): Page.addScriptTag should throw when blocked by CSP (#2320) This patch teaches Page.addScriptTag and Page.addStyleTag to throw an error when blocked by CSP. References #1229. --- lib/FrameManager.js | 23 +++++++++++++++++------ test/page.spec.js | 28 ++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/lib/FrameManager.js b/lib/FrameManager.js index 147d02fe2760d..81491c5ed261f 100644 --- a/lib/FrameManager.js +++ b/lib/FrameManager.js @@ -470,11 +470,12 @@ class Frame { script.src = url; if (type) script.type = type; - document.head.appendChild(script); - await new Promise((res, rej) => { + const promise = new Promise((res, rej) => { script.onload = res; script.onerror = rej; }); + document.head.appendChild(script); + await promise; return script; } @@ -487,7 +488,11 @@ class Frame { const script = document.createElement('script'); script.type = type; script.text = content; + let error = null; + script.onerror = e => error = e; document.head.appendChild(script); + if (error) + throw error; return script; } } @@ -529,23 +534,29 @@ class Frame { const link = document.createElement('link'); link.rel = 'stylesheet'; link.href = url; - document.head.appendChild(link); - await new Promise((res, rej) => { + const promise = new Promise((res, rej) => { link.onload = res; link.onerror = rej; }); + document.head.appendChild(link); + await promise; return link; } /** * @param {string} content - * @return {!HTMLElement} + * @return {!Promise} */ - function addStyleContent(content) { + async function addStyleContent(content) { const style = document.createElement('style'); style.type = 'text/css'; style.appendChild(document.createTextNode(content)); + const promise = new Promise((res, rej) => { + style.onload = res; + style.onerror = rej; + }); document.head.appendChild(style); + await promise; return style; } } diff --git a/test/page.spec.js b/test/page.spec.js index 04b27c32777eb..69b5af531bb2f 100644 --- a/test/page.spec.js +++ b/test/page.spec.js @@ -1336,6 +1336,20 @@ module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, p expect(scriptHandle.asElement()).not.toBeNull(); expect(await page.evaluate(() => __injected)).toBe(35); }); + + it('should throw when added with content to the CSP page', async({page, server}) => { + await page.goto(server.PREFIX + '/csp.html'); + let error = null; + await page.addScriptTag({ content: 'window.__injected = 35;' }).catch(e => error = e); + expect(error).toBeTruthy(); + }); + + it('should throw when added with URL to the CSP page', async({page, server}) => { + await page.goto(server.PREFIX + '/csp.html'); + let error = null; + await page.addScriptTag({ url: server.CROSS_PROCESS_PREFIX + '/injectedfile.js' }).catch(e => error = e); + expect(error).toBeTruthy(); + }); }); describe('Page.addStyleTag', function() { @@ -1388,6 +1402,20 @@ module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, p expect(styleHandle.asElement()).not.toBeNull(); expect(await page.evaluate(`window.getComputedStyle(document.querySelector('body')).getPropertyValue('background-color')`)).toBe('rgb(0, 128, 0)'); }); + + it('should throw when added with content to the CSP page', async({page, server}) => { + await page.goto(server.PREFIX + '/csp.html'); + let error = null; + await page.addStyleTag({ content: 'body { background-color: green; }' }).catch(e => error = e); + expect(error).toBeTruthy(); + }); + + it('should throw when added with URL to the CSP page', async({page, server}) => { + await page.goto(server.PREFIX + '/csp.html'); + let error = null; + await page.addStyleTag({ url: server.CROSS_PROCESS_PREFIX + '/injectedstyle.css' }).catch(e => error = e); + expect(error).toBeTruthy(); + }); }); describe('Page.url', function() {