scripts.js 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /*
  2. * Copyright 2010-2020 Gildas Lormeau
  3. * contact : gildas.lormeau <at> gmail.com
  4. *
  5. * This file is part of SingleFile.
  6. *
  7. * The code in this file is free software: you can redistribute it and/or
  8. * modify it under the terms of the GNU Affero General Public License
  9. * (GNU AGPL) as published by the Free Software Foundation, either version 3
  10. * of the License, or (at your option) any later version.
  11. *
  12. * The code in this file is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
  15. * General Public License for more details.
  16. *
  17. * As additional permission under GNU AGPL version 3 section 7, you may
  18. * distribute UNMODIFIED VERSIONS OF THIS file without the copy of the GNU
  19. * AGPL normally required by section 4, provided you include this license
  20. * notice and a URL through which recipients can access the Corresponding
  21. * Source.
  22. */
  23. /* global browser, fetch, TextDecoder */
  24. let contentScript, frameScript;
  25. const contentScriptFiles = [
  26. "dist/chrome-browser-polyfill.js",
  27. "dist/single-file.js"
  28. ];
  29. const frameScriptFiles = [
  30. "dist/chrome-browser-polyfill.js",
  31. "dist/single-file-frames.js"
  32. ];
  33. const basePath = "../../../";
  34. export {
  35. inject
  36. };
  37. async function inject(tabId, options) {
  38. await initScripts(options);
  39. let scriptsInjected;
  40. if (!options.removeFrames) {
  41. try {
  42. await browser.tabs.executeScript(tabId, { code: frameScript, allFrames: true, matchAboutBlank: true, runAt: "document_start" });
  43. } catch (error) {
  44. // ignored
  45. }
  46. }
  47. try {
  48. await browser.tabs.executeScript(tabId, { code: contentScript, allFrames: false, runAt: "document_idle" });
  49. scriptsInjected = true;
  50. } catch (error) {
  51. // ignored
  52. }
  53. if (scriptsInjected) {
  54. if (options.frameId) {
  55. await browser.tabs.executeScript(tabId, { code: "document.documentElement.dataset.requestedFrameId = true", frameId: options.frameId, matchAboutBlank: true, runAt: "document_start" });
  56. }
  57. }
  58. return scriptsInjected;
  59. }
  60. async function initScripts(options) {
  61. const extensionScriptFiles = options.extensionScriptFiles || [];
  62. if (!contentScript && !frameScript) {
  63. [contentScript, frameScript] = await Promise.all([
  64. getScript(contentScriptFiles.concat(extensionScriptFiles)),
  65. getScript(frameScriptFiles)
  66. ]);
  67. }
  68. }
  69. async function getScript(scriptFiles) {
  70. const scriptsPromises = scriptFiles.map(async scriptFile => {
  71. if (typeof scriptFile == "function") {
  72. return "(" + scriptFile.toString() + ")();";
  73. } else {
  74. const scriptResource = await fetch(browser.runtime.getURL(basePath + scriptFile));
  75. return new TextDecoder().decode(await scriptResource.arrayBuffer());
  76. }
  77. });
  78. let content = "";
  79. for (const scriptPromise of scriptsPromises) {
  80. content += await scriptPromise;
  81. }
  82. return content;
  83. }