content-script-spec.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. const { expect } = require('chai')
  2. const { remote } = require('electron')
  3. const path = require('path')
  4. const { closeWindow } = require('./window-helpers')
  5. const { emittedNTimes } = require('./events-helpers')
  6. const { BrowserWindow, ipcMain } = remote
  7. describe('chrome extension content scripts', () => {
  8. const fixtures = path.resolve(__dirname, 'fixtures')
  9. const extensionPath = path.resolve(fixtures, 'extensions')
  10. const addExtension = (name) => BrowserWindow.addExtension(path.resolve(extensionPath, name))
  11. const removeAllExtensions = () => {
  12. Object.keys(BrowserWindow.getExtensions()).map(extName => {
  13. BrowserWindow.removeExtension(extName)
  14. })
  15. }
  16. let responseIdCounter = 0
  17. const executeJavaScriptInFrame = (webContents, frameRoutingId, code) => {
  18. return new Promise(resolve => {
  19. const responseId = responseIdCounter++
  20. ipcMain.once(`executeJavaScriptInFrame_${responseId}`, (event, result) => {
  21. resolve(result)
  22. })
  23. webContents.send('executeJavaScriptInFrame', frameRoutingId, code, responseId)
  24. })
  25. }
  26. const generateTests = (sandboxEnabled, contextIsolationEnabled) => {
  27. describe(`with sandbox ${sandboxEnabled ? 'enabled' : 'disabled'} and context isolation ${contextIsolationEnabled ? 'enabled' : 'disabled'}`, () => {
  28. let w
  29. describe('supports "run_at" option', () => {
  30. beforeEach(async () => {
  31. await closeWindow(w)
  32. w = new BrowserWindow({
  33. show: false,
  34. width: 400,
  35. height: 400,
  36. webPreferences: {
  37. contextIsolation: contextIsolationEnabled,
  38. sandbox: sandboxEnabled
  39. }
  40. })
  41. })
  42. afterEach(() => {
  43. removeAllExtensions()
  44. return closeWindow(w).then(() => { w = null })
  45. })
  46. it('should run content script at document_start', (done) => {
  47. addExtension('content-script-document-start')
  48. w.webContents.once('dom-ready', () => {
  49. w.webContents.executeJavaScript('document.documentElement.style.backgroundColor', (result) => {
  50. expect(result).to.equal('red')
  51. done()
  52. })
  53. })
  54. w.loadURL('about:blank')
  55. })
  56. it('should run content script at document_idle', (done) => {
  57. addExtension('content-script-document-idle')
  58. w.loadURL('about:blank')
  59. w.webContents.executeJavaScript('document.body.style.backgroundColor', (result) => {
  60. expect(result).to.equal('red')
  61. done()
  62. })
  63. })
  64. it('should run content script at document_end', (done) => {
  65. addExtension('content-script-document-end')
  66. w.webContents.once('did-finish-load', () => {
  67. w.webContents.executeJavaScript('document.documentElement.style.backgroundColor', (result) => {
  68. expect(result).to.equal('red')
  69. done()
  70. })
  71. })
  72. w.loadURL('about:blank')
  73. })
  74. })
  75. describe('supports "all_frames" option', () => {
  76. const contentScript = path.resolve(fixtures, 'extensions/content-script')
  77. // Computed style values
  78. const COLOR_RED = `rgb(255, 0, 0)`
  79. const COLOR_BLUE = `rgb(0, 0, 255)`
  80. const COLOR_TRANSPARENT = `rgba(0, 0, 0, 0)`
  81. before(() => {
  82. BrowserWindow.addExtension(contentScript)
  83. })
  84. after(() => {
  85. BrowserWindow.removeExtension('content-script-test')
  86. })
  87. beforeEach(() => {
  88. w = new BrowserWindow({
  89. show: false,
  90. webPreferences: {
  91. // enable content script injection in subframes
  92. nodeIntegrationInSubFrames: true,
  93. preload: path.join(contentScript, 'all_frames-preload.js')
  94. }
  95. })
  96. })
  97. afterEach(() =>
  98. closeWindow(w).then(() => {
  99. w = null
  100. })
  101. )
  102. it('applies matching rules in subframes', async () => {
  103. const detailsPromise = emittedNTimes(w.webContents, 'did-frame-finish-load', 2)
  104. w.loadFile(path.join(contentScript, 'frame-with-frame.html'))
  105. const frameEvents = await detailsPromise
  106. await Promise.all(
  107. frameEvents.map(async frameEvent => {
  108. const [, isMainFrame, , frameRoutingId] = frameEvent
  109. const result = await executeJavaScriptInFrame(
  110. w.webContents,
  111. frameRoutingId,
  112. `(() => {
  113. const a = document.getElementById('all_frames_enabled')
  114. const b = document.getElementById('all_frames_disabled')
  115. return {
  116. enabledColor: getComputedStyle(a).backgroundColor,
  117. disabledColor: getComputedStyle(b).backgroundColor
  118. }
  119. })()`
  120. )
  121. expect(result.enabledColor).to.equal(COLOR_RED)
  122. if (isMainFrame) {
  123. expect(result.disabledColor).to.equal(COLOR_BLUE)
  124. } else {
  125. expect(result.disabledColor).to.equal(COLOR_TRANSPARENT) // null color
  126. }
  127. })
  128. )
  129. })
  130. })
  131. })
  132. }
  133. generateTests(false, false)
  134. generateTests(false, true)
  135. generateTests(true, false)
  136. generateTests(true, true)
  137. })