playwright-firefox.js 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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 singlefile, require, exports */
  24. const playwright = require("playwright").firefox;
  25. const scripts = require("./common/scripts.js");
  26. const NETWORK_IDLE_STATE = "networkidle0";
  27. let browser;
  28. exports.initialize = async options => {
  29. browser = await playwright.launch(getBrowserOptions(options));
  30. };
  31. exports.getPageData = async options => {
  32. let page;
  33. try {
  34. page = await browser.newPage({
  35. bypassCSP: options.browserBypassCSP === undefined || options.browserBypassCSP
  36. });
  37. await setPageOptions(page, options);
  38. return await getPageData(browser, page, options);
  39. } finally {
  40. if (page) {
  41. await page.close();
  42. }
  43. }
  44. };
  45. exports.closeBrowser = () => {
  46. if (browser) {
  47. return browser.close();
  48. }
  49. };
  50. function getBrowserOptions(options) {
  51. const browserOptions = {};
  52. if (options.browserHeadless !== undefined) {
  53. browserOptions.headless = options.browserHeadless && !options.browserDebug;
  54. }
  55. browserOptions.args = options.browserArgs ? JSON.parse(options.browserArgs) : [];
  56. if (options.browserExecutablePath) {
  57. browserOptions.executablePath = options.browserExecutablePath || "firefox";
  58. }
  59. browserOptions.product = "firefox";
  60. return browserOptions;
  61. }
  62. async function setPageOptions(page, options) {
  63. if (options.browserWidth && options.browserHeight) {
  64. await page.setViewportSize({
  65. width: options.browserWidth,
  66. height: options.browserHeight
  67. });
  68. }
  69. }
  70. async function getPageData(browser, page, options) {
  71. const injectedScript = await scripts.get(options);
  72. await page.addInitScript(injectedScript);
  73. if (options.browserDebug) {
  74. await page.waitForTimeout(3000);
  75. }
  76. await page.goto(options.url, {
  77. timeout: options.browserLoadMaxTime || 0,
  78. waitUntil: options.browserWaitUntil || NETWORK_IDLE_STATE
  79. });
  80. return await page.evaluate(async options => {
  81. const pageData = await singlefile.lib.getPageData(options);
  82. if (options.includeInfobar) {
  83. await singlefile.common.ui.content.infobar.includeScript(pageData);
  84. }
  85. return pageData;
  86. }, options);
  87. }