playwright-chromium.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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").chromium;
  25. const scripts = require("./common/scripts.js");
  26. const NETWORK_IDLE_STATE = "networkidle";
  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(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 || "chrome";
  58. }
  59. return browserOptions;
  60. }
  61. async function setPageOptions(page, options) {
  62. if (options.browserWidth && options.browserHeight) {
  63. await page.setViewportSize({
  64. width: options.browserWidth,
  65. height: options.browserHeight
  66. });
  67. }
  68. if (options.httpHeaders) {
  69. page.setExtraHTTPHeaders(options.httpHeaders);
  70. }
  71. }
  72. async function getPageData(page, options) {
  73. const injectedScript = await scripts.get(options);
  74. await page.addInitScript(injectedScript);
  75. if (options.browserDebug) {
  76. await page.waitForTimeout(3000);
  77. }
  78. await page.goto(options.url, {
  79. timeout: options.browserLoadMaxTime || 0,
  80. waitUntil: options.browserWaitUntil && options.browserWaitUntil.startsWith("networkidle") ? NETWORK_IDLE_STATE : options.browserWaitUntil || NETWORK_IDLE_STATE
  81. });
  82. return await page.evaluate(async options => {
  83. const pageData = await singlefile.lib.getPageData(options);
  84. if (options.includeInfobar) {
  85. await singlefile.common.ui.content.infobar.includeScript(pageData);
  86. }
  87. return pageData;
  88. }, options);
  89. }