BrowserInstance.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. "use strict";
  2. /*
  3. * Copyright 2023 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. */
  19. var __importDefault = (this && this.__importDefault) || function (mod) {
  20. return (mod && mod.__esModule) ? mod : { "default": mod };
  21. };
  22. Object.defineProperty(exports, "__esModule", { value: true });
  23. exports.BrowserInstance = void 0;
  24. const promises_1 = require("fs/promises");
  25. const os_1 = __importDefault(require("os"));
  26. const path_1 = __importDefault(require("path"));
  27. const browsers_1 = require("@puppeteer/browsers");
  28. const debug_1 = __importDefault(require("debug"));
  29. const ws_1 = __importDefault(require("ws"));
  30. const CdpConnection_js_1 = require("../cdp/CdpConnection.js");
  31. const WebsocketTransport_js_1 = require("../utils/WebsocketTransport.js");
  32. const MapperCdpConnection_js_1 = require("./MapperCdpConnection.js");
  33. const reader_js_1 = require("./reader.js");
  34. const debugInternal = (0, debug_1.default)('bidi:mapper:internal');
  35. /**
  36. * BrowserProcess is responsible for running the browser and BiDi Mapper within
  37. * it.
  38. * 1. Launch Chromium (using Puppeteer for now).
  39. * 2. Get `BiDi-CDP` mapper JS binaries using `MapperReader`.
  40. * 3. Run `BiDi-CDP` mapper in launched browser using `MapperRunner`.
  41. * 4. Bind `BiDi-CDP` mapper to the `BiDi server` to forward messages from BiDi
  42. * Mapper to the client.
  43. */
  44. class BrowserInstance {
  45. #mapperCdpConnection;
  46. #browserProcess;
  47. static async run(chromeOptions, mapperOptions, verbose) {
  48. const profileDir = await (0, promises_1.mkdtemp)(path_1.default.join(os_1.default.tmpdir(), 'web-driver-bidi-server-'));
  49. // See https://github.com/GoogleChrome/chrome-launcher/blob/main/docs/chrome-flags-for-tools.md
  50. const chromeArguments = [
  51. // keep-sorted start
  52. '--allow-browser-signin=false',
  53. '--disable-component-update',
  54. '--disable-default-apps',
  55. '--disable-features=DialMediaRouteProvider,TrackingProtection3pcd',
  56. '--disable-infobars',
  57. '--disable-notifications',
  58. '--disable-popup-blocking',
  59. '--disable-search-engine-choice-screen',
  60. '--enable-automation',
  61. '--no-default-browser-check',
  62. '--no-first-run',
  63. '--password-store=basic',
  64. '--remote-debugging-port=9222',
  65. '--use-mock-keychain',
  66. `--user-data-dir=${profileDir}`,
  67. // keep-sorted end
  68. ...chromeOptions.chromeArgs,
  69. 'about:blank',
  70. ];
  71. const executablePath = chromeOptions.chromeBinary ?? process.env['BROWSER_BIN'];
  72. if (!executablePath) {
  73. throw new Error('Could not find Chrome binary');
  74. }
  75. const launchArguments = {
  76. executablePath,
  77. args: chromeArguments,
  78. env: process.env,
  79. };
  80. debugInternal(`Launching browser`, launchArguments);
  81. const browserProcess = (0, browsers_1.launch)(launchArguments);
  82. const cdpEndpoint = await browserProcess.waitForLineOutput(browsers_1.CDP_WEBSOCKET_ENDPOINT_REGEX);
  83. // There is a conflict between prettier and eslint here.
  84. // prettier-ignore
  85. const cdpConnection = await this.#establishCdpConnection(cdpEndpoint);
  86. // 2. Get `BiDi-CDP` mapper JS binaries.
  87. const mapperTabSource = await (0, reader_js_1.getMapperTabSource)();
  88. // 3. Run `BiDi-CDP` mapper in launched browser using `MapperRunner`.
  89. const mapperCdpConnection = await MapperCdpConnection_js_1.MapperServerCdpConnection.create(cdpConnection, mapperTabSource, verbose, mapperOptions);
  90. return new BrowserInstance(mapperCdpConnection, browserProcess);
  91. }
  92. constructor(mapperCdpConnection, browserProcess) {
  93. this.#mapperCdpConnection = mapperCdpConnection;
  94. this.#browserProcess = browserProcess;
  95. }
  96. async close() {
  97. // Close the mapper tab.
  98. this.#mapperCdpConnection.close();
  99. // Close browser.
  100. await this.#browserProcess.close();
  101. }
  102. bidiSession() {
  103. return this.#mapperCdpConnection.bidiSession();
  104. }
  105. static #establishCdpConnection(cdpUrl) {
  106. return new Promise((resolve, reject) => {
  107. debugInternal('Establishing session with cdpUrl: ', cdpUrl);
  108. const ws = new ws_1.default(cdpUrl);
  109. ws.once('error', reject);
  110. ws.on('open', () => {
  111. debugInternal('Session established.');
  112. const transport = new WebsocketTransport_js_1.WebSocketTransport(ws);
  113. const connection = new CdpConnection_js_1.MapperCdpConnection(transport);
  114. resolve(connection);
  115. });
  116. });
  117. }
  118. }
  119. exports.BrowserInstance = BrowserInstance;
  120. //# sourceMappingURL=BrowserInstance.js.map