playwright-chromium.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  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, common, 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, context;
  33. try {
  34. context = await browser.newContext({
  35. bypassCSP: options.browserBypassCSP === undefined || options.browserBypassCSP
  36. });
  37. await setContextOptions(context, options);
  38. page = await context.newPage();
  39. await setPageOptions(page, options);
  40. return await getPageData(page, options);
  41. } finally {
  42. if (page) {
  43. await page.close();
  44. }
  45. }
  46. };
  47. exports.closeBrowser = () => {
  48. if (browser) {
  49. return browser.close();
  50. }
  51. };
  52. function getBrowserOptions(options) {
  53. const browserOptions = {};
  54. if (options.browserHeadless !== undefined) {
  55. browserOptions.headless = options.browserHeadless && !options.browserDebug;
  56. }
  57. browserOptions.args = options.browserArgs ? JSON.parse(options.browserArgs) : [];
  58. if (options.browserExecutablePath) {
  59. browserOptions.executablePath = options.browserExecutablePath || "chrome";
  60. }
  61. return browserOptions;
  62. }
  63. async function setContextOptions(context, options) {
  64. if (options.browserCookies && options.browserCookies.length) {
  65. await context.addCookies(options.browserCookies);
  66. }
  67. }
  68. async function setPageOptions(page, options) {
  69. if (options.browserWidth && options.browserHeight) {
  70. await page.setViewportSize({
  71. width: options.browserWidth,
  72. height: options.browserHeight
  73. });
  74. }
  75. if (options.httpHeaders) {
  76. page.setExtraHTTPHeaders(options.httpHeaders);
  77. }
  78. }
  79. async function getPageData(page, options) {
  80. const injectedScript = await scripts.get(options);
  81. await page.addInitScript(injectedScript);
  82. if (options.browserDebug) {
  83. await page.waitForTimeout(3000);
  84. }
  85. await page.goto(options.url, {
  86. timeout: options.browserLoadMaxTime || 0,
  87. waitUntil: options.browserWaitUntil && options.browserWaitUntil.startsWith("networkidle") ? NETWORK_IDLE_STATE : options.browserWaitUntil || NETWORK_IDLE_STATE
  88. });
  89. if (options.browserWaitDelay) {
  90. await page.waitForTimeout(options.browserWaitDelay);
  91. }
  92. return await page.evaluate(async options => {
  93. const pageData = await singlefile.getPageData(options);
  94. if (options.includeInfobar) {
  95. await common.ui.content.infobar.includeScript(pageData);
  96. }
  97. return pageData;
  98. }, options);
  99. }