advanced-csp.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. var t = require('assert')
  2. module.exports = ({browser, extensions, popup, advanced, content}) => {
  3. before(async () => {
  4. // add origin
  5. await advanced.bringToFront()
  6. await advanced.select('.m-select', 'http')
  7. await advanced.type('[type=text]', 'localhost:3000')
  8. await advanced.click('button')
  9. await advanced.waitFor(() => document.querySelectorAll('.m-list li').length === 2)
  10. // disable csp
  11. if (await advanced.evaluate(() => state.csp)) {
  12. await advanced.click('.m-switch:nth-of-type(2)')
  13. }
  14. // enable path matching
  15. await advanced.evaluate(() => {
  16. document.querySelector('.m-list li:nth-of-type(2) input')
  17. .value = 'csp-match-path'
  18. document.querySelector('.m-list li:nth-of-type(2) input')
  19. .dispatchEvent(new Event('keyup'))
  20. })
  21. // there is debounce timeout of 750ms in the options UI
  22. await advanced.waitFor(800)
  23. })
  24. describe('preserve state', () => {
  25. it('options page', async () => {
  26. await advanced.bringToFront()
  27. // enable csp
  28. if (!await advanced.evaluate(() => state.csp)) {
  29. await advanced.click('.m-switch:nth-of-type(2)')
  30. }
  31. await advanced.reload()
  32. await advanced.waitFor('#options')
  33. await advanced.waitFor(100)
  34. t.strictEqual(
  35. await advanced.evaluate(() =>
  36. document.querySelector('.m-switch:nth-of-type(2)')
  37. .classList.contains('is-checked')
  38. ),
  39. true,
  40. 'csp checkbox should be enabled'
  41. )
  42. // disable csp
  43. if (await advanced.evaluate(() => state.csp)) {
  44. await advanced.click('.m-switch:nth-of-type(2)')
  45. }
  46. await advanced.reload()
  47. await advanced.waitFor('#options')
  48. await advanced.waitFor(100)
  49. t.strictEqual(
  50. await advanced.evaluate(() =>
  51. document.querySelector('.m-switch:nth-of-type(2)')
  52. .classList.contains('is-checked')
  53. ),
  54. false,
  55. 'csp checkbox should be disabled'
  56. )
  57. })
  58. })
  59. describe('strip csp header only on matching content type or url', () => {
  60. it('non matching urls should be skipped', async () => {
  61. await advanced.bringToFront()
  62. // enable csp
  63. if (!await advanced.evaluate(() => state.csp)) {
  64. await advanced.click('.m-switch:nth-of-type(2)')
  65. }
  66. // go to page serving content with strict csp
  67. await content.goto('http://localhost:3000/csp-wrong-path')
  68. await content.bringToFront()
  69. await content.waitFor('pre')
  70. t.strictEqual(
  71. await content.evaluate(() => {
  72. try {
  73. window.localStorage
  74. }
  75. catch (err) {
  76. return err.message.split(':')[1].trim()
  77. }
  78. }),
  79. `The document is sandboxed and lacks the 'allow-same-origin' flag.`,
  80. 'localStorage should not be accessible'
  81. )
  82. })
  83. })
  84. describe('enable csp', () => {
  85. it('webRequest.onHeadersReceived event is enabled', async () => {
  86. await advanced.bringToFront()
  87. // enable csp
  88. if (!await advanced.evaluate(() => state.csp)) {
  89. await advanced.click('.m-switch:nth-of-type(2)')
  90. }
  91. // go to page serving content with strict csp
  92. await content.goto('http://localhost:3000/csp-match-path')
  93. await content.bringToFront()
  94. await content.waitFor('#_html')
  95. t.strictEqual(
  96. await content.evaluate(() =>
  97. window.localStorage.toString()
  98. ),
  99. '[object Storage]',
  100. 'localStorage should be accessible'
  101. )
  102. })
  103. })
  104. describe('disable csp', () => {
  105. it('webRequest.onHeadersReceived event is disabled', async () => {
  106. await advanced.bringToFront()
  107. // disable csp
  108. if (await advanced.evaluate(() => state.csp)) {
  109. await advanced.click('.m-switch:nth-of-type(2)')
  110. }
  111. // go to page serving content with strict csp
  112. await content.goto('http://localhost:3000/csp-match-path')
  113. await content.bringToFront()
  114. await content.waitFor('#_html')
  115. t.strictEqual(
  116. await content.evaluate(() => {
  117. try {
  118. window.localStorage
  119. }
  120. catch (err) {
  121. return err.message.split(':')[1].trim()
  122. }
  123. }),
  124. `The document is sandboxed and lacks the 'allow-same-origin' flag.`,
  125. 'localStorage should not be accessible'
  126. )
  127. })
  128. })
  129. describe('enable csp + suspend the event page', () => {
  130. it('the tab is reloaded on event page wakeup', async () => {
  131. await advanced.bringToFront()
  132. // enable csp
  133. if (!await advanced.evaluate(() => state.csp)) {
  134. await advanced.click('.m-switch:nth-of-type(2)')
  135. }
  136. await extensions.bringToFront()
  137. // enable developer mode
  138. await extensions.click('#dev-toggle label')
  139. // disable the extension
  140. await extensions.click('.enable-checkbox label')
  141. // enable the extension
  142. await extensions.click('.enable-checkbox label')
  143. // check
  144. t.equal(
  145. await extensions.evaluate(() =>
  146. document.querySelector('.active-views a').innerText
  147. ),
  148. 'background page (Inactive)',
  149. 'background page should be disabled'
  150. )
  151. // go to page serving content with strict csp
  152. await content.goto('http://localhost:3000/csp-match-path')
  153. await content.bringToFront()
  154. await content.waitFor('#_html')
  155. t.strictEqual(
  156. await content.evaluate(() =>
  157. window.localStorage.toString()
  158. ),
  159. '[object Storage]',
  160. 'localStorage should be accessible'
  161. )
  162. })
  163. })
  164. }