content-script-spec.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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', () => {
  47. addExtension('content-script-document-start');
  48. w.webContents.once('dom-ready', async () => {
  49. const result = await w.webContents.executeJavaScript('document.documentElement.style.backgroundColor');
  50. expect(result).to.equal('red');
  51. });
  52. w.loadURL('about:blank');
  53. });
  54. it('should run content script at document_idle', async () => {
  55. addExtension('content-script-document-idle');
  56. w.loadURL('about:blank');
  57. const result = await w.webContents.executeJavaScript('document.body.style.backgroundColor');
  58. expect(result).to.equal('red');
  59. });
  60. it('should run content script at document_end', () => {
  61. addExtension('content-script-document-end');
  62. w.webContents.once('did-finish-load', async () => {
  63. const result = await w.webContents.executeJavaScript('document.documentElement.style.backgroundColor');
  64. expect(result).to.equal('red');
  65. });
  66. w.loadURL('about:blank');
  67. });
  68. });
  69. describe('supports "all_frames" option', () => {
  70. const contentScript = path.resolve(fixtures, 'extensions/content-script');
  71. // Computed style values
  72. const COLOR_RED = `rgb(255, 0, 0)`;
  73. const COLOR_BLUE = `rgb(0, 0, 255)`;
  74. const COLOR_TRANSPARENT = `rgba(0, 0, 0, 0)`;
  75. before(() => {
  76. BrowserWindow.addExtension(contentScript);
  77. });
  78. after(() => {
  79. BrowserWindow.removeExtension('content-script-test');
  80. });
  81. beforeEach(() => {
  82. w = new BrowserWindow({
  83. show: false,
  84. webPreferences: {
  85. // enable content script injection in subframes
  86. nodeIntegrationInSubFrames: true,
  87. preload: path.join(contentScript, 'all_frames-preload.js')
  88. }
  89. });
  90. });
  91. afterEach(() =>
  92. closeWindow(w).then(() => {
  93. w = null;
  94. })
  95. );
  96. it('applies matching rules in subframes', async () => {
  97. const detailsPromise = emittedNTimes(w.webContents, 'did-frame-finish-load', 2);
  98. w.loadFile(path.join(contentScript, 'frame-with-frame.html'));
  99. const frameEvents = await detailsPromise;
  100. await Promise.all(
  101. frameEvents.map(async frameEvent => {
  102. const [, isMainFrame, , frameRoutingId] = frameEvent;
  103. const result = await executeJavaScriptInFrame(
  104. w.webContents,
  105. frameRoutingId,
  106. `(() => {
  107. const a = document.getElementById('all_frames_enabled')
  108. const b = document.getElementById('all_frames_disabled')
  109. return {
  110. enabledColor: getComputedStyle(a).backgroundColor,
  111. disabledColor: getComputedStyle(b).backgroundColor
  112. }
  113. })()`
  114. );
  115. expect(result.enabledColor).to.equal(COLOR_RED);
  116. if (isMainFrame) {
  117. expect(result.disabledColor).to.equal(COLOR_BLUE);
  118. } else {
  119. expect(result.disabledColor).to.equal(COLOR_TRANSPARENT); // null color
  120. }
  121. })
  122. );
  123. });
  124. });
  125. });
  126. };
  127. generateTests(false, false);
  128. generateTests(false, true);
  129. generateTests(true, false);
  130. generateTests(true, true);
  131. });