api-web-frame-spec.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. const assert = require('assert')
  2. const chai = require('chai')
  3. const dirtyChai = require('dirty-chai')
  4. const path = require('path')
  5. const { closeWindow } = require('./window-helpers')
  6. const { remote, webFrame } = require('electron')
  7. const { BrowserWindow, protocol, ipcMain } = remote
  8. const { emittedOnce } = require('./events-helpers')
  9. const { expect } = chai
  10. chai.use(dirtyChai)
  11. /* Most of the APIs here don't use standard callbacks */
  12. /* eslint-disable standard/no-callback-literal */
  13. describe('webFrame module', function () {
  14. const fixtures = path.resolve(__dirname, 'fixtures')
  15. let w = null
  16. afterEach(function () {
  17. return closeWindow(w).then(function () { w = null })
  18. })
  19. describe('webFrame.registerURLSchemeAsPrivileged', function () {
  20. it('supports fetch api by default', function (done) {
  21. const url = 'file://' + fixtures + '/assets/logo.png'
  22. window.fetch(url).then(function (response) {
  23. assert(response.ok)
  24. done()
  25. }).catch(function (err) {
  26. done('unexpected error : ' + err)
  27. })
  28. })
  29. it('allows CORS requests by default', function (done) {
  30. allowsCORSRequests(200, `<html>
  31. <script>
  32. const {ipcRenderer, webFrame} = require('electron')
  33. webFrame.registerURLSchemeAsPrivileged('cors1')
  34. fetch('cors1://myhost').then(function (response) {
  35. ipcRenderer.send('response', response.status)
  36. }).catch(function (response) {
  37. ipcRenderer.send('response', 'failed')
  38. })
  39. </script>
  40. </html>`, done)
  41. })
  42. it('allows CORS and fetch requests when specified', function (done) {
  43. allowsCORSRequests(200, `<html>
  44. <script>
  45. const {ipcRenderer, webFrame} = require('electron')
  46. webFrame.registerURLSchemeAsPrivileged('cors2', { supportFetchAPI: true, corsEnabled: true })
  47. fetch('cors2://myhost').then(function (response) {
  48. ipcRenderer.send('response', response.status)
  49. }).catch(function (response) {
  50. ipcRenderer.send('response', 'failed')
  51. })
  52. </script>
  53. </html>`, done)
  54. })
  55. it('allows CORS and fetch requests when half-specified', function (done) {
  56. allowsCORSRequests(200, `<html>
  57. <script>
  58. const {ipcRenderer, webFrame} = require('electron')
  59. webFrame.registerURLSchemeAsPrivileged('cors3', { supportFetchAPI: true })
  60. fetch('cors3://myhost').then(function (response) {
  61. ipcRenderer.send('response', response.status)
  62. }).catch(function (response) {
  63. ipcRenderer.send('response', 'failed')
  64. })
  65. </script>
  66. </html>`, done)
  67. })
  68. it('disallows CORS, but allows fetch requests, when specified', function (done) {
  69. allowsCORSRequests('failed', `<html>
  70. <script>
  71. const {ipcRenderer, webFrame} = require('electron')
  72. webFrame.registerURLSchemeAsPrivileged('cors4', { supportFetchAPI: true, corsEnabled: false })
  73. fetch('cors4://myhost').then(function (response) {
  74. ipcRenderer.send('response', response.status)
  75. }).catch(function (response) {
  76. ipcRenderer.send('response', 'failed')
  77. })
  78. </script>
  79. </html>`, done)
  80. })
  81. it('allows CORS, but disallows fetch requests, when specified', function (done) {
  82. allowsCORSRequests('failed', `<html>
  83. <script>
  84. const {ipcRenderer, webFrame} = require('electron')
  85. webFrame.registerURLSchemeAsPrivileged('cors5', { supportFetchAPI: false, corsEnabled: true })
  86. fetch('cors5://myhost').then(function (response) {
  87. ipcRenderer.send('response', response.status)
  88. }).catch(function (response) {
  89. ipcRenderer.send('response', 'failed')
  90. })
  91. </script>
  92. </html>`, done)
  93. })
  94. let runNumber = 1
  95. function allowsCORSRequests (expected, content, done) {
  96. const standardScheme = remote.getGlobal('standardScheme') + runNumber
  97. const corsScheme = 'cors' + runNumber
  98. runNumber++
  99. const url = standardScheme + '://fake-host'
  100. w = new BrowserWindow({ show: false })
  101. after(function (done) {
  102. protocol.unregisterProtocol(corsScheme, function () {
  103. protocol.unregisterProtocol(standardScheme, function () {
  104. done()
  105. })
  106. })
  107. })
  108. const handler = function (request, callback) {
  109. callback({ data: content, mimeType: 'text/html' })
  110. }
  111. protocol.registerStringProtocol(standardScheme, handler, function (error) {
  112. if (error) return done(error)
  113. })
  114. protocol.registerStringProtocol(corsScheme, function (request, callback) {
  115. callback('')
  116. }, function (error) {
  117. if (error) return done(error)
  118. ipcMain.once('response', function (event, status) {
  119. assert.strictEqual(status, expected)
  120. done()
  121. })
  122. w.loadURL(url)
  123. })
  124. }
  125. })
  126. it('supports setting the visual and layout zoom level limits', function () {
  127. assert.doesNotThrow(function () {
  128. webFrame.setVisualZoomLevelLimits(1, 50)
  129. webFrame.setLayoutZoomLevelLimits(0, 25)
  130. })
  131. })
  132. it('calls a spellcheck provider', async () => {
  133. w = new BrowserWindow({ show: false })
  134. w.loadFile(path.join(fixtures, 'pages', 'webframe-spell-check.html'))
  135. await emittedOnce(w.webContents, 'did-finish-load')
  136. w.focus()
  137. await w.webContents.executeJavaScript('document.querySelector("input").focus()', true)
  138. const spellCheckerFeedback = emittedOnce(ipcMain, 'spec-spell-check')
  139. const misspelledWord = 'spleling'
  140. for (const keyCode of [...misspelledWord, ' ']) {
  141. w.webContents.sendInputEvent({ type: 'char', keyCode })
  142. }
  143. const [, text] = await spellCheckerFeedback
  144. expect(text).to.equal(misspelledWord)
  145. })
  146. it('top is self for top frame', () => {
  147. expect(webFrame.top.context).to.equal(webFrame.context)
  148. })
  149. it('opener is null for top frame', () => {
  150. expect(webFrame.opener).to.be.null()
  151. })
  152. it('firstChild is null for top frame', () => {
  153. expect(webFrame.firstChild).to.be.null()
  154. })
  155. it('getFrameForSelector() does not crash when not found', () => {
  156. expect(webFrame.getFrameForSelector('unexist-selector')).to.be.null()
  157. })
  158. it('findFrameByName() does not crash when not found', () => {
  159. expect(webFrame.findFrameByName('unexist-name')).to.be.null()
  160. })
  161. it('findFrameByRoutingId() does not crash when not found', () => {
  162. expect(webFrame.findFrameByRoutingId(-1)).to.be.null()
  163. })
  164. })