api-subframe-spec.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. const { expect } = require('chai')
  2. const { remote } = require('electron')
  3. const path = require('path')
  4. const { emittedNTimes, emittedOnce } = require('./events-helpers')
  5. const { closeWindow } = require('./window-helpers')
  6. const { BrowserWindow, ipcMain } = remote
  7. describe('renderer nodeIntegrationInSubFrames', () => {
  8. const generateTests = (description, webPreferences) => {
  9. describe(description, () => {
  10. const fixtureSuffix = webPreferences.webviewTag ? '-webview' : ''
  11. let w
  12. beforeEach(async () => {
  13. await closeWindow(w)
  14. w = new BrowserWindow({
  15. show: false,
  16. width: 400,
  17. height: 400,
  18. webPreferences
  19. })
  20. })
  21. afterEach(() => {
  22. return closeWindow(w).then(() => {
  23. w = null
  24. })
  25. })
  26. it('should load preload scripts in top level iframes', async () => {
  27. const detailsPromise = emittedNTimes(ipcMain, 'preload-ran', 2)
  28. w.loadFile(path.resolve(__dirname, `fixtures/sub-frames/frame-container${fixtureSuffix}.html`))
  29. const [event1, event2] = await detailsPromise
  30. expect(event1[0].frameId).to.not.equal(event2[0].frameId)
  31. expect(event1[0].frameId).to.equal(event1[2])
  32. expect(event2[0].frameId).to.equal(event2[2])
  33. })
  34. it('should load preload scripts in nested iframes', async () => {
  35. const detailsPromise = emittedNTimes(ipcMain, 'preload-ran', 3)
  36. w.loadFile(path.resolve(__dirname, `fixtures/sub-frames/frame-with-frame-container${fixtureSuffix}.html`))
  37. const [event1, event2, event3] = await detailsPromise
  38. expect(event1[0].frameId).to.not.equal(event2[0].frameId)
  39. expect(event1[0].frameId).to.not.equal(event3[0].frameId)
  40. expect(event2[0].frameId).to.not.equal(event3[0].frameId)
  41. expect(event1[0].frameId).to.equal(event1[2])
  42. expect(event2[0].frameId).to.equal(event2[2])
  43. expect(event3[0].frameId).to.equal(event3[2])
  44. })
  45. it('should correctly reply to the main frame with using event.reply', async () => {
  46. const detailsPromise = emittedNTimes(ipcMain, 'preload-ran', 2)
  47. w.loadFile(path.resolve(__dirname, `fixtures/sub-frames/frame-container${fixtureSuffix}.html`))
  48. const [event1] = await detailsPromise
  49. const pongPromise = emittedOnce(ipcMain, 'preload-pong')
  50. event1[0].reply('preload-ping')
  51. const details = await pongPromise
  52. expect(details[1]).to.equal(event1[0].frameId)
  53. })
  54. it('should correctly reply to the sub-frames with using event.reply', async () => {
  55. const detailsPromise = emittedNTimes(ipcMain, 'preload-ran', 2)
  56. w.loadFile(path.resolve(__dirname, `fixtures/sub-frames/frame-container${fixtureSuffix}.html`))
  57. const [, event2] = await detailsPromise
  58. const pongPromise = emittedOnce(ipcMain, 'preload-pong')
  59. event2[0].reply('preload-ping')
  60. const details = await pongPromise
  61. expect(details[1]).to.equal(event2[0].frameId)
  62. })
  63. it('should correctly reply to the nested sub-frames with using event.reply', async () => {
  64. const detailsPromise = emittedNTimes(ipcMain, 'preload-ran', 3)
  65. w.loadFile(path.resolve(__dirname, `fixtures/sub-frames/frame-with-frame-container${fixtureSuffix}.html`))
  66. const [, , event3] = await detailsPromise
  67. const pongPromise = emittedOnce(ipcMain, 'preload-pong')
  68. event3[0].reply('preload-ping')
  69. const details = await pongPromise
  70. expect(details[1]).to.equal(event3[0].frameId)
  71. })
  72. it('should not expose globals in main world', async () => {
  73. const detailsPromise = emittedNTimes(ipcMain, 'preload-ran', 2)
  74. w.loadFile(path.resolve(__dirname, `fixtures/sub-frames/frame-container${fixtureSuffix}.html`))
  75. const details = await detailsPromise
  76. const senders = details.map(event => event[0].sender)
  77. await new Promise((resolve) => {
  78. let resultCount = 0
  79. senders.forEach(sender => {
  80. sender.webContents.executeJavaScript('window.isolatedGlobal', result => {
  81. if (webPreferences.contextIsolation) {
  82. expect(result).to.be.null()
  83. } else {
  84. expect(result).to.equal(true)
  85. }
  86. resultCount++
  87. if (resultCount === senders.length) {
  88. resolve()
  89. }
  90. })
  91. })
  92. })
  93. })
  94. })
  95. }
  96. const generateConfigs = (webPreferences, ...permutations) => {
  97. const configs = [{ webPreferences, names: [] }]
  98. for (let i = 0; i < permutations.length; i++) {
  99. const length = configs.length
  100. for (let j = 0; j < length; j++) {
  101. const newConfig = Object.assign({}, configs[j])
  102. newConfig.webPreferences = Object.assign({},
  103. newConfig.webPreferences, permutations[i].webPreferences)
  104. newConfig.names = newConfig.names.slice(0)
  105. newConfig.names.push(permutations[i].name)
  106. configs.push(newConfig)
  107. }
  108. }
  109. return configs.map(config => {
  110. if (config.names.length > 0) {
  111. config.title = `with ${config.names.join(', ')} on`
  112. } else {
  113. config.title = `without anything special turned on`
  114. }
  115. delete config.names
  116. return config
  117. })
  118. }
  119. generateConfigs(
  120. {
  121. preload: path.resolve(__dirname, 'fixtures/sub-frames/preload.js'),
  122. nodeIntegrationInSubFrames: true
  123. },
  124. {
  125. name: 'sandbox',
  126. webPreferences: { sandbox: true }
  127. },
  128. {
  129. name: 'context isolation',
  130. webPreferences: { contextIsolation: true }
  131. },
  132. {
  133. name: 'webview',
  134. webPreferences: { webviewTag: true, preload: false }
  135. }
  136. ).forEach(config => {
  137. generateTests(config.title, config.webPreferences)
  138. })
  139. describe('internal <iframe> inside of <webview>', () => {
  140. let w
  141. beforeEach(async () => {
  142. await closeWindow(w)
  143. w = new BrowserWindow({
  144. show: false,
  145. width: 400,
  146. height: 400,
  147. webPreferences: {
  148. preload: path.resolve(__dirname, 'fixtures/sub-frames/webview-iframe-preload.js'),
  149. nodeIntegrationInSubFrames: true,
  150. webviewTag: true
  151. }
  152. })
  153. })
  154. afterEach(() => {
  155. return closeWindow(w).then(() => {
  156. w = null
  157. })
  158. })
  159. it('should not load preload scripts', async () => {
  160. const promisePass = emittedOnce(ipcMain, 'webview-loaded')
  161. const promiseFail = emittedOnce(ipcMain, 'preload-in-frame').then(() => {
  162. throw new Error('preload loaded in internal frame')
  163. })
  164. await w.loadURL('about:blank')
  165. return Promise.race([promisePass, promiseFail])
  166. })
  167. })
  168. })