diff --git a/docs/api.md b/docs/api.md index 67f7d6d8..7744d3ac 100644 --- a/docs/api.md +++ b/docs/api.md @@ -90,6 +90,7 @@ * [page.reload(options)](#pagereloadoptions) * [page.screenshot([options])](#pagescreenshotoptions) * [page.select(selector, ...values)](#pageselectselector-values) + * [page.setBypassCSP(enabled)](#pagesetbypasscspenabled) * [page.setCacheEnabled(enabled)](#pagesetcacheenabledenabled) * [page.setContent(html)](#pagesetcontenthtml) * [page.setCookie(...cookies)](#pagesetcookiecookies) @@ -1176,6 +1177,15 @@ page.select('select#colors', 'red', 'green', 'blue'); // multiple selections Shortcut for [page.mainFrame().select()](#frameselectselector-values) +#### page.setBypassCSP(enabled) +- `enabled` <[boolean]> sets bypassing of page's Content-Security-Policy. +- returns: <[Promise]> + +Toggles bypassing page's Content-Security-Policy. + +> **NOTE** CSP bypassing happens at the moment of CSP initialization rather then evaluation. Usually this means +that `page.setBypassCSP` should be called before navigating to the domain. + #### page.setCacheEnabled(enabled) - `enabled` <[boolean]> sets the `enabled` state of the cache. - returns: <[Promise]> diff --git a/lib/Page.js b/lib/Page.js index bb5fb3f4..6f9ed28b 100644 --- a/lib/Page.js +++ b/lib/Page.js @@ -610,6 +610,13 @@ class Page extends EventEmitter { await this._client.send('Emulation.setScriptExecutionDisabled', { value: !enabled }); } + /** + * @param {boolean} enabled + */ + async setBypassCSP(enabled) { + await this._client.send('Page.setBypassCSP', { enabled }); + } + /** * @param {?string} mediaType */ diff --git a/test/page.spec.js b/test/page.spec.js index 69b5af53..8193107a 100644 --- a/test/page.spec.js +++ b/test/page.spec.js @@ -1267,6 +1267,46 @@ module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, p }); }); + describe('Page.setBypassCSP', function() { + it('should bypass CSP meta tag', async({page, server}) => { + // Make sure CSP prohibits addScriptTag. + await page.goto(server.PREFIX + '/csp.html'); + await page.addScriptTag({content: 'window.__injected = 42;'}).catch(e => void e); + expect(await page.evaluate(() => window.__injected)).toBe(undefined); + + // By-pass CSP and try one more time. + await page.setBypassCSP(true); + await page.reload(); + await page.addScriptTag({content: 'window.__injected = 42;'}); + expect(await page.evaluate(() => window.__injected)).toBe(42); + }); + + it('should bypass CSP header', async({page, server}) => { + // Make sure CSP prohibits addScriptTag. + server.setCSP('/empty.html', 'default-src "self"'); + await page.goto(server.EMPTY_PAGE); + await page.addScriptTag({content: 'window.__injected = 42;'}).catch(e => void e); + expect(await page.evaluate(() => window.__injected)).toBe(undefined); + + // By-pass CSP and try one more time. + await page.setBypassCSP(true); + await page.reload(); + await page.addScriptTag({content: 'window.__injected = 42;'}); + expect(await page.evaluate(() => window.__injected)).toBe(42); + }); + + it('should bypass after cross-process navigation', async({page, server}) => { + await page.setBypassCSP(true); + await page.goto(server.PREFIX + '/csp.html'); + await page.addScriptTag({content: 'window.__injected = 42;'}); + expect(await page.evaluate(() => window.__injected)).toBe(42); + + await page.goto(server.CROSS_PROCESS_PREFIX + '/csp.html'); + await page.addScriptTag({content: 'window.__injected = 42;'}); + expect(await page.evaluate(() => window.__injected)).toBe(42); + }); + }); + describe('Page.addScriptTag', function() { it('should throw an error if no options are provided', async({page, server}) => { let error = null;