index.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. "use strict";
  2. /**
  3. * Copyright 2021 Google LLC.
  4. * Copyright (c) Microsoft Corporation.
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. var __importDefault = (this && this.__importDefault) || function (mod) {
  19. return (mod && mod.__esModule) ? mod : { "default": mod };
  20. };
  21. Object.defineProperty(exports, "__esModule", { value: true });
  22. const path_1 = __importDefault(require("path"));
  23. const os_1 = __importDefault(require("os"));
  24. const promises_1 = require("fs/promises");
  25. const argparse_1 = __importDefault(require("argparse"));
  26. const browsers_1 = require("@puppeteer/browsers");
  27. const bidiServerRunner_js_1 = require("./bidiServerRunner.js");
  28. const mapperServer_js_1 = require("./mapperServer.js");
  29. const mapperReader_js_1 = __importDefault(require("./mapperReader.js"));
  30. function parseArguments() {
  31. const parser = new argparse_1.default.ArgumentParser({
  32. add_help: true,
  33. exit_on_error: true,
  34. });
  35. parser.add_argument('-p', '--port', {
  36. help: 'Port that BiDi server should listen to. Default is 8080.',
  37. type: 'int',
  38. default: process.env['PORT'] ?? 8080,
  39. });
  40. parser.add_argument('-c', '--channel', {
  41. help: 'If set, the given installed Chrome Release Channel will be used ' +
  42. 'instead of one pointed by Puppeteer version',
  43. choices: Object.values(browsers_1.ChromeReleaseChannel),
  44. default: browsers_1.ChromeReleaseChannel.DEV,
  45. });
  46. parser.add_argument('-hl', '--headless', {
  47. help: 'Sets if browser should run in headless or headful mode. Default is true.',
  48. default: true,
  49. });
  50. parser.add_argument('-v', '--verbose', {
  51. help: 'If present, the Mapper debug log, including CDP commands and events will be logged into the server output.',
  52. action: 'store_true',
  53. default: process.env['VERBOSE'] === 'true' || false,
  54. });
  55. const args = parser.parse_known_args();
  56. return args[0];
  57. }
  58. (() => {
  59. try {
  60. (0, bidiServerRunner_js_1.debugInfo)('Launching BiDi server');
  61. const args = parseArguments();
  62. const bidiPort = args.port;
  63. const headless = args.headless !== 'false';
  64. const verbose = args.verbose === true;
  65. const chromeChannel = args.channel;
  66. new bidiServerRunner_js_1.BidiServerRunner().run(bidiPort, (bidiServer) => {
  67. return onNewBidiConnectionOpen(headless, chromeChannel, bidiServer, verbose);
  68. });
  69. (0, bidiServerRunner_js_1.debugInfo)('BiDi server launched');
  70. }
  71. catch (e) {
  72. (0, bidiServerRunner_js_1.debugInfo)('Error', e);
  73. }
  74. })();
  75. /**
  76. * On each new BiDi connection:
  77. * 1. Launch Chromium (using Puppeteer for now).
  78. * 2. Get `BiDi-CDP` mapper JS binaries using `mapperReader`.
  79. * 3. Run `BiDi-CDP` mapper in launched browser.
  80. * 4. Bind `BiDi-CDP` mapper to the `BiDi server`.
  81. *
  82. * @return delegate to be called when the connection is closed
  83. */
  84. async function onNewBidiConnectionOpen(headless, chromeChannel, bidiTransport, verbose) {
  85. // 1. Launch the browser using @puppeteer/browsers.
  86. const profileDir = await (0, promises_1.mkdtemp)(path_1.default.join(os_1.default.tmpdir(), 'web-driver-bidi-server-'));
  87. // See https://github.com/GoogleChrome/chrome-launcher/blob/main/docs/chrome-flags-for-tools.md
  88. const chromeArguments = [
  89. ...(headless ? ['--headless', '--hide-scrollbars', '--mute-audio'] : []),
  90. // keep-sorted start
  91. '--disable-component-update',
  92. '--disable-popup-blocking',
  93. '--enable-automation',
  94. '--no-default-browser-check',
  95. '--no-first-run',
  96. '--password-store=basic',
  97. '--remote-debugging-port=9222',
  98. '--use-mock-keychain',
  99. `--user-data-dir=${profileDir}`,
  100. // keep-sorted end
  101. 'about:blank',
  102. ];
  103. const executablePath = process.env['BROWSER_BIN'] ??
  104. (0, browsers_1.computeSystemExecutablePath)({
  105. browser: browsers_1.Browser.CHROME,
  106. channel: chromeChannel,
  107. });
  108. if (!executablePath) {
  109. throw new Error('Could not find Chrome binary');
  110. }
  111. const browser = (0, browsers_1.launch)({
  112. executablePath,
  113. args: chromeArguments,
  114. });
  115. const wsEndpoint = await browser.waitForLineOutput(browsers_1.CDP_WEBSOCKET_ENDPOINT_REGEX);
  116. // 2. Get `BiDi-CDP` mapper JS binaries using `mapperReader`.
  117. const bidiMapperScript = await (0, mapperReader_js_1.default)();
  118. // 3. Run `BiDi-CDP` mapper in launched browser.
  119. const mapperServer = await mapperServer_js_1.MapperServer.create(wsEndpoint, bidiMapperScript, verbose);
  120. // 4. Bind `BiDi-CDP` mapper to the `BiDi server`.
  121. // Forward messages from BiDi Mapper to the client.
  122. mapperServer.setOnMessage(async (message) => {
  123. await bidiTransport.sendMessage(message);
  124. });
  125. // Forward messages from the client to BiDi Mapper.
  126. bidiTransport.setOnMessage(async (message) => {
  127. await mapperServer.sendMessage(message);
  128. });
  129. // Return delegate to be called when the connection is closed.
  130. return async () => {
  131. // Close the mapper server.
  132. mapperServer.close();
  133. // Close browser.
  134. await browser.close();
  135. };
  136. }
  137. //# sourceMappingURL=index.js.map