origin-csp.js 8.8 KB

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