MapperCdpConnection.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  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. exports.MapperServerCdpConnection = void 0;
  23. const debug_1 = __importDefault(require("debug"));
  24. const SimpleTransport_js_1 = require("./SimpleTransport.js");
  25. const debugInternal = (0, debug_1.default)('bidi:mapper:internal');
  26. const debugInfo = (0, debug_1.default)('bidi:mapper:info');
  27. const debugOthers = (0, debug_1.default)('bidi:mapper:debug:others');
  28. // Memorizes a debug creation
  29. const loggers = new Map();
  30. const getLogger = (type) => {
  31. const prefix = `bidi:mapper:${type}`;
  32. let logger = loggers.get(prefix);
  33. if (!logger) {
  34. logger = (0, debug_1.default)(prefix);
  35. loggers.set(prefix, logger);
  36. }
  37. return logger;
  38. };
  39. class MapperServerCdpConnection {
  40. #cdpConnection;
  41. #bidiSession;
  42. static async create(cdpConnection, mapperTabSource, verbose, mapperOptions) {
  43. try {
  44. const bidiSession = await this.#initMapper(cdpConnection, mapperTabSource, verbose, mapperOptions);
  45. return new MapperServerCdpConnection(cdpConnection, bidiSession);
  46. }
  47. catch (e) {
  48. cdpConnection.close();
  49. throw e;
  50. }
  51. }
  52. constructor(cdpConnection, bidiSession) {
  53. this.#cdpConnection = cdpConnection;
  54. this.#bidiSession = bidiSession;
  55. }
  56. static async #sendMessage(mapperCdpClient, message) {
  57. try {
  58. await mapperCdpClient.sendCommand('Runtime.evaluate', {
  59. expression: `onBidiMessage(${JSON.stringify(message)})`,
  60. });
  61. }
  62. catch (error) {
  63. debugInternal('Call to onBidiMessage failed', error);
  64. }
  65. }
  66. close() {
  67. this.#cdpConnection.close();
  68. }
  69. bidiSession() {
  70. return this.#bidiSession;
  71. }
  72. static #onBindingCalled = (params, bidiSession) => {
  73. if (params.name === 'sendBidiResponse') {
  74. bidiSession.emit('message', params.payload);
  75. }
  76. else if (params.name === 'sendDebugMessage') {
  77. this.#onDebugMessage(params.payload);
  78. }
  79. };
  80. static #onDebugMessage = (json) => {
  81. try {
  82. const log = JSON.parse(json);
  83. if (log.logType !== undefined && log.messages !== undefined) {
  84. const logger = getLogger(log.logType);
  85. logger(log.messages);
  86. }
  87. }
  88. catch {
  89. // Fall back to raw log in case of unknown
  90. debugOthers(json);
  91. }
  92. };
  93. static #onConsoleAPICalled = (params) => {
  94. debugInfo('consoleAPICalled: %s %O', params.type, params.args.map((arg) => arg.value));
  95. };
  96. static #onRuntimeExceptionThrown = (params) => {
  97. debugInfo('exceptionThrown:', params);
  98. };
  99. static async #initMapper(cdpConnection, mapperTabSource, verbose, mapperOptions) {
  100. debugInternal('Initializing Mapper.', mapperOptions);
  101. const browserClient = await cdpConnection.createBrowserSession();
  102. const { targetId: mapperTabTargetId } = await browserClient.sendCommand('Target.createTarget', {
  103. url: 'about:blank',
  104. });
  105. const { sessionId: mapperSessionId } = await browserClient.sendCommand('Target.attachToTarget', { targetId: mapperTabTargetId, flatten: true });
  106. const mapperCdpClient = cdpConnection.getCdpClient(mapperSessionId);
  107. const bidiSession = new SimpleTransport_js_1.SimpleTransport(async (message) => await this.#sendMessage(mapperCdpClient, message));
  108. // Process responses from the mapper tab.
  109. mapperCdpClient.on('Runtime.bindingCalled', (params) => this.#onBindingCalled(params, bidiSession));
  110. // Forward console messages from the mapper tab.
  111. mapperCdpClient.on('Runtime.consoleAPICalled', this.#onConsoleAPICalled);
  112. // Catch unhandled exceptions in the mapper.
  113. mapperCdpClient.on('Runtime.exceptionThrown', this.#onRuntimeExceptionThrown);
  114. await mapperCdpClient.sendCommand('Runtime.enable');
  115. await browserClient.sendCommand('Target.exposeDevToolsProtocol', {
  116. bindingName: 'cdp',
  117. targetId: mapperTabTargetId,
  118. });
  119. await mapperCdpClient.sendCommand('Runtime.addBinding', {
  120. name: 'sendBidiResponse',
  121. });
  122. if (verbose) {
  123. // Needed to request verbose logs from Mapper.
  124. await mapperCdpClient.sendCommand('Runtime.addBinding', {
  125. name: 'sendDebugMessage',
  126. });
  127. }
  128. // Evaluate Mapper Tab sources in the tab.
  129. await mapperCdpClient.sendCommand('Runtime.evaluate', {
  130. expression: mapperTabSource,
  131. });
  132. await mapperCdpClient.sendCommand('Runtime.evaluate', {
  133. expression: `window.runMapperInstance('${mapperTabTargetId}', ${JSON.stringify(mapperOptions)})`,
  134. awaitPromise: true,
  135. });
  136. debugInternal('Mapper is launched!');
  137. return bidiSession;
  138. }
  139. }
  140. exports.MapperServerCdpConnection = MapperServerCdpConnection;
  141. //# sourceMappingURL=MapperCdpConnection.js.map