advanced-csp.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. var t = require('assert')
  2. module.exports = ({extensions, advanced, content}) => {
  3. before(async () => {
  4. await advanced.bringToFront()
  5. // remove origin
  6. if (await advanced.evaluate(() => Object.keys(state.origins).length > 1)) {
  7. // expand origin
  8. if (!await advanced.evaluate(() =>
  9. document.querySelector('.m-list li:nth-of-type(2)')
  10. .classList.contains('m-expanded'))) {
  11. await advanced.click('.m-list li:nth-of-type(2)')
  12. }
  13. await advanced.click('.m-list li:nth-of-type(2) .m-footer .m-button:nth-of-type(2)')
  14. }
  15. // add origin
  16. await advanced.select('.m-select', 'http')
  17. await advanced.type('[type=text]', 'localhost:3000')
  18. await advanced.click('button')
  19. await advanced.waitFor(200)
  20. // expand origin
  21. if (!await advanced.evaluate(() =>
  22. document.querySelector('.m-list li:nth-of-type(2)')
  23. .classList.contains('m-expanded'))) {
  24. await advanced.click('.m-list li:nth-of-type(2)')
  25. }
  26. // enable path matching
  27. await advanced.evaluate(() => {
  28. document.querySelector('.m-list li:nth-of-type(2) input')
  29. .value = 'csp-match-path'
  30. document.querySelector('.m-list li:nth-of-type(2) input')
  31. .dispatchEvent(new Event('keyup'))
  32. })
  33. // there is debounce timeout of 750ms in the options UI
  34. await advanced.waitFor(800)
  35. })
  36. describe('preserve state', () => {
  37. it('enable csp', async () => {
  38. await advanced.bringToFront()
  39. // enable csp
  40. if (!await advanced.evaluate(() => state.origins['http://localhost:3000'].csp)) {
  41. await advanced.click('.m-list li:nth-of-type(2) .m-switch')
  42. }
  43. await advanced.reload()
  44. await advanced.waitFor(200)
  45. // expand origin
  46. await advanced.click('.m-list li:nth-of-type(2)')
  47. t.strictEqual(
  48. await advanced.evaluate(() =>
  49. document.querySelector('.m-list li:nth-of-type(2) .m-switch')
  50. .classList.contains('is-checked')
  51. ),
  52. true,
  53. 'csp checkbox should be enabled'
  54. )
  55. })
  56. it('disable csp', async () => {
  57. await advanced.bringToFront()
  58. // disable csp
  59. if (await advanced.evaluate(() => state.origins['http://localhost:3000'].csp)) {
  60. await advanced.click('.m-list li:nth-of-type(2) .m-switch')
  61. }
  62. await advanced.reload()
  63. await advanced.waitFor(200)
  64. // expand origin
  65. await advanced.click('.m-list li:nth-of-type(2)')
  66. t.strictEqual(
  67. await advanced.evaluate(() =>
  68. document.querySelector('.m-list li:nth-of-type(2) .m-switch')
  69. .classList.contains('is-checked')
  70. ),
  71. false,
  72. 'csp checkbox should be disabled'
  73. )
  74. })
  75. })
  76. describe('strip csp header only on matching content type or url', () => {
  77. before(async () => {
  78. await advanced.bringToFront()
  79. // expand origin
  80. if (!await advanced.evaluate(() =>
  81. document.querySelector('.m-list li:nth-of-type(2)')
  82. .classList.contains('m-expanded'))) {
  83. await advanced.click('.m-list li:nth-of-type(2)')
  84. }
  85. // enable csp
  86. if (!await advanced.evaluate(() => state.origins['http://localhost:3000'].csp)) {
  87. await advanced.click('.m-list li:nth-of-type(2) .m-switch')
  88. }
  89. // go to page serving content with strict csp
  90. await content.goto('http://localhost:3000/csp-wrong-path')
  91. await content.bringToFront()
  92. await content.waitFor(200)
  93. })
  94. it('non matching urls should be skipped', async () => {
  95. t.strictEqual(
  96. await content.evaluate(() => {
  97. try {
  98. window.localStorage
  99. }
  100. catch (err) {
  101. return err.message.split(':')[1].trim()
  102. }
  103. }),
  104. `The document is sandboxed and lacks the 'allow-same-origin' flag.`,
  105. 'localStorage should not be accessible'
  106. )
  107. })
  108. })
  109. describe('enable csp', () => {
  110. before(async () => {
  111. await advanced.bringToFront()
  112. // expand origin
  113. if (!await advanced.evaluate(() =>
  114. document.querySelector('.m-list li:nth-of-type(2)')
  115. .classList.contains('m-expanded'))) {
  116. await advanced.click('.m-list li:nth-of-type(2)')
  117. }
  118. // enable csp
  119. if (!await advanced.evaluate(() => state.origins['http://localhost:3000'].csp)) {
  120. await advanced.click('.m-list li:nth-of-type(2) .m-switch')
  121. }
  122. // go to page serving content with strict csp
  123. await content.goto('http://localhost:3000/csp-match-path')
  124. await content.bringToFront()
  125. await content.waitFor(200)
  126. })
  127. it('webRequest.onHeadersReceived event is enabled', async () => {
  128. t.strictEqual(
  129. await content.evaluate(() =>
  130. window.localStorage.toString()
  131. ),
  132. '[object Storage]',
  133. 'localStorage should be accessible'
  134. )
  135. })
  136. })
  137. describe('disable csp', () => {
  138. before(async () => {
  139. await advanced.bringToFront()
  140. // expand origin
  141. if (!await advanced.evaluate(() =>
  142. document.querySelector('.m-list li:nth-of-type(2)')
  143. .classList.contains('m-expanded'))) {
  144. await advanced.click('.m-list li:nth-of-type(2)')
  145. }
  146. // disable csp
  147. if (await advanced.evaluate(() => state.origins['http://localhost:3000'].csp)) {
  148. await advanced.click('.m-list li:nth-of-type(2) .m-switch')
  149. }
  150. // go to page serving content with strict csp
  151. await content.goto('http://localhost:3000/csp-match-path')
  152. await content.bringToFront()
  153. await content.waitFor(200)
  154. })
  155. it('webRequest.onHeadersReceived event is disabled', async () => {
  156. t.strictEqual(
  157. await content.evaluate(() => {
  158. try {
  159. window.localStorage
  160. }
  161. catch (err) {
  162. return err.message.split(':')[1].trim()
  163. }
  164. }),
  165. `The document is sandboxed and lacks the 'allow-same-origin' flag.`,
  166. 'localStorage should not be accessible'
  167. )
  168. })
  169. })
  170. describe('enable csp + suspend the event page', () => {
  171. before(async () => {
  172. await advanced.bringToFront()
  173. // expand origin
  174. if (!await advanced.evaluate(() =>
  175. document.querySelector('.m-list li:nth-of-type(2)')
  176. .classList.contains('m-expanded'))) {
  177. await advanced.click('.m-list li:nth-of-type(2)')
  178. }
  179. // enable csp
  180. if (!await advanced.evaluate(() => state.origins['http://localhost:3000'].csp)) {
  181. await advanced.click('.m-list li:nth-of-type(2) .m-switch')
  182. }
  183. // chrome://extensions
  184. await extensions.bringToFront()
  185. // enable developer mode
  186. await extensions.evaluate(() => {
  187. Array.from(
  188. document.querySelector('extensions-manager').shadowRoot
  189. .querySelector('extensions-item-list').shadowRoot
  190. .querySelectorAll('extensions-item'))[0].shadowRoot
  191. .querySelector('#enable-toggle').click()
  192. })
  193. // disable the extension
  194. await extensions.evaluate(() => {
  195. Array.from(
  196. document.querySelector('extensions-manager').shadowRoot
  197. .querySelector('extensions-item-list').shadowRoot
  198. .querySelectorAll('extensions-item'))[0].shadowRoot
  199. .querySelector('#enable-toggle').click()
  200. })
  201. await extensions.waitFor(200)
  202. // check
  203. t.equal(
  204. await extensions.evaluate(() =>
  205. Array.from(
  206. document.querySelector('extensions-manager').shadowRoot
  207. .querySelector('extensions-item-list').shadowRoot
  208. .querySelectorAll('extensions-item'))[0].shadowRoot
  209. .querySelector('#inspect-views a').innerText
  210. ),
  211. 'background page (Inactive)',
  212. 'background page should be inactive'
  213. )
  214. // go to page serving content with strict csp
  215. await content.goto('http://localhost:3000/csp-match-path')
  216. await content.bringToFront()
  217. await content.waitFor(200)
  218. })
  219. it('the tab is reloaded on event page wakeup', async () => {
  220. t.strictEqual(
  221. await content.evaluate(() =>
  222. window.localStorage.toString()
  223. ),
  224. '[object Storage]',
  225. 'localStorage should be accessible'
  226. )
  227. })
  228. })
  229. }