CommandProcessor.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  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. Object.defineProperty(exports, "__esModule", { value: true });
  19. exports.CommandProcessor = void 0;
  20. const protocol_js_1 = require("../protocol/protocol.js");
  21. const EventEmitter_js_1 = require("../utils/EventEmitter.js");
  22. const log_js_1 = require("../utils/log.js");
  23. const BidiNoOpParser_js_1 = require("./BidiNoOpParser.js");
  24. const BrowserProcessor_js_1 = require("./modules/browser/BrowserProcessor.js");
  25. const CdpProcessor_js_1 = require("./modules/cdp/CdpProcessor.js");
  26. const BrowsingContextProcessor_js_1 = require("./modules/context/BrowsingContextProcessor.js");
  27. const InputProcessor_js_1 = require("./modules/input/InputProcessor.js");
  28. const NetworkProcessor_js_1 = require("./modules/network/NetworkProcessor.js");
  29. const PermissionsProcessor_js_1 = require("./modules/permissions/PermissionsProcessor.js");
  30. const ScriptProcessor_js_1 = require("./modules/script/ScriptProcessor.js");
  31. const SessionProcessor_js_1 = require("./modules/session/SessionProcessor.js");
  32. const StorageProcessor_js_1 = require("./modules/storage/StorageProcessor.js");
  33. const OutgoingMessage_js_1 = require("./OutgoingMessage.js");
  34. class CommandProcessor extends EventEmitter_js_1.EventEmitter {
  35. // keep-sorted start
  36. #browserProcessor;
  37. #browsingContextProcessor;
  38. #cdpProcessor;
  39. #inputProcessor;
  40. #networkProcessor;
  41. #permissionsProcessor;
  42. #scriptProcessor;
  43. #sessionProcessor;
  44. #storageProcessor;
  45. // keep-sorted end
  46. #parser;
  47. #logger;
  48. constructor(cdpConnection, browserCdpClient, eventManager, browsingContextStorage, realmStorage, preloadScriptStorage, networkStorage, parser = new BidiNoOpParser_js_1.BidiNoOpParser(), logger) {
  49. super();
  50. this.#parser = parser;
  51. this.#logger = logger;
  52. // keep-sorted start block=yes
  53. this.#browserProcessor = new BrowserProcessor_js_1.BrowserProcessor(browserCdpClient);
  54. this.#browsingContextProcessor = new BrowsingContextProcessor_js_1.BrowsingContextProcessor(browserCdpClient, browsingContextStorage);
  55. this.#cdpProcessor = new CdpProcessor_js_1.CdpProcessor(browsingContextStorage, realmStorage, cdpConnection, browserCdpClient);
  56. this.#inputProcessor = new InputProcessor_js_1.InputProcessor(browsingContextStorage, realmStorage);
  57. this.#networkProcessor = new NetworkProcessor_js_1.NetworkProcessor(browsingContextStorage, networkStorage);
  58. this.#permissionsProcessor = new PermissionsProcessor_js_1.PermissionsProcessor(browserCdpClient);
  59. this.#scriptProcessor = new ScriptProcessor_js_1.ScriptProcessor(browsingContextStorage, realmStorage, preloadScriptStorage, logger);
  60. this.#sessionProcessor = new SessionProcessor_js_1.SessionProcessor(eventManager, browserCdpClient);
  61. this.#storageProcessor = new StorageProcessor_js_1.StorageProcessor(browserCdpClient, browsingContextStorage, logger);
  62. // keep-sorted end
  63. }
  64. async #processCommand(command) {
  65. switch (command.method) {
  66. case 'session.end':
  67. // TODO: Implement.
  68. break;
  69. // Browser domain
  70. // keep-sorted start block=yes
  71. case 'browser.close':
  72. return this.#browserProcessor.close();
  73. case 'browser.createUserContext':
  74. return await this.#browserProcessor.createUserContext(command.params);
  75. case 'browser.getUserContexts':
  76. return await this.#browserProcessor.getUserContexts();
  77. case 'browser.removeUserContext':
  78. return await this.#browserProcessor.removeUserContext(this.#parser.parseRemoveUserContextParams(command.params));
  79. // keep-sorted end
  80. // Browsing Context domain
  81. // keep-sorted start block=yes
  82. case 'browsingContext.activate':
  83. return await this.#browsingContextProcessor.activate(this.#parser.parseActivateParams(command.params));
  84. case 'browsingContext.captureScreenshot':
  85. return await this.#browsingContextProcessor.captureScreenshot(this.#parser.parseCaptureScreenshotParams(command.params));
  86. case 'browsingContext.close':
  87. return await this.#browsingContextProcessor.close(this.#parser.parseCloseParams(command.params));
  88. case 'browsingContext.create':
  89. return await this.#browsingContextProcessor.create(this.#parser.parseCreateParams(command.params));
  90. case 'browsingContext.getTree':
  91. return this.#browsingContextProcessor.getTree(this.#parser.parseGetTreeParams(command.params));
  92. case 'browsingContext.handleUserPrompt':
  93. return await this.#browsingContextProcessor.handleUserPrompt(this.#parser.parseHandleUserPromptParams(command.params));
  94. case 'browsingContext.locateNodes':
  95. return await this.#browsingContextProcessor.locateNodes(this.#parser.parseLocateNodesParams(command.params));
  96. case 'browsingContext.navigate':
  97. return await this.#browsingContextProcessor.navigate(this.#parser.parseNavigateParams(command.params));
  98. case 'browsingContext.print':
  99. return await this.#browsingContextProcessor.print(this.#parser.parsePrintParams(command.params));
  100. case 'browsingContext.reload':
  101. return await this.#browsingContextProcessor.reload(this.#parser.parseReloadParams(command.params));
  102. case 'browsingContext.setViewport':
  103. return await this.#browsingContextProcessor.setViewport(this.#parser.parseSetViewportParams(command.params));
  104. case 'browsingContext.traverseHistory':
  105. return await this.#browsingContextProcessor.traverseHistory(this.#parser.parseTraverseHistoryParams(command.params));
  106. // keep-sorted end
  107. // CDP domain
  108. // keep-sorted start block=yes
  109. case 'cdp.getSession':
  110. return this.#cdpProcessor.getSession(this.#parser.parseGetSessionParams(command.params));
  111. case 'cdp.resolveRealm':
  112. return this.#cdpProcessor.resolveRealm(this.#parser.parseResolveRealmParams(command.params));
  113. case 'cdp.sendCommand':
  114. return await this.#cdpProcessor.sendCommand(this.#parser.parseSendCommandParams(command.params));
  115. // keep-sorted end
  116. // Input domain
  117. // keep-sorted start block=yes
  118. case 'input.performActions':
  119. return await this.#inputProcessor.performActions(this.#parser.parsePerformActionsParams(command.params));
  120. case 'input.releaseActions':
  121. return await this.#inputProcessor.releaseActions(this.#parser.parseReleaseActionsParams(command.params));
  122. case 'input.setFiles':
  123. return await this.#inputProcessor.setFiles(this.#parser.parseSetFilesParams(command.params));
  124. // keep-sorted end
  125. // Network domain
  126. // keep-sorted start block=yes
  127. case 'network.addIntercept':
  128. return await this.#networkProcessor.addIntercept(this.#parser.parseAddInterceptParams(command.params));
  129. case 'network.continueRequest':
  130. return await this.#networkProcessor.continueRequest(this.#parser.parseContinueRequestParams(command.params));
  131. case 'network.continueResponse':
  132. return await this.#networkProcessor.continueResponse(this.#parser.parseContinueResponseParams(command.params));
  133. case 'network.continueWithAuth':
  134. return await this.#networkProcessor.continueWithAuth(this.#parser.parseContinueWithAuthParams(command.params));
  135. case 'network.failRequest':
  136. return await this.#networkProcessor.failRequest(this.#parser.parseFailRequestParams(command.params));
  137. case 'network.provideResponse':
  138. return await this.#networkProcessor.provideResponse(this.#parser.parseProvideResponseParams(command.params));
  139. case 'network.removeIntercept':
  140. return await this.#networkProcessor.removeIntercept(this.#parser.parseRemoveInterceptParams(command.params));
  141. // keep-sorted end
  142. // Permissions domain
  143. // keep-sorted start block=yes
  144. case 'permissions.setPermission':
  145. return await this.#permissionsProcessor.setPermissions(this.#parser.parseSetPermissionsParams(command.params));
  146. // keep-sorted end
  147. // Script domain
  148. // keep-sorted start block=yes
  149. case 'script.addPreloadScript':
  150. return await this.#scriptProcessor.addPreloadScript(this.#parser.parseAddPreloadScriptParams(command.params));
  151. case 'script.callFunction':
  152. return await this.#scriptProcessor.callFunction(this.#parser.parseCallFunctionParams(this.#processTargetParams(command.params)));
  153. case 'script.disown':
  154. return await this.#scriptProcessor.disown(this.#parser.parseDisownParams(this.#processTargetParams(command.params)));
  155. case 'script.evaluate':
  156. return await this.#scriptProcessor.evaluate(this.#parser.parseEvaluateParams(this.#processTargetParams(command.params)));
  157. case 'script.getRealms':
  158. return this.#scriptProcessor.getRealms(this.#parser.parseGetRealmsParams(command.params));
  159. case 'script.removePreloadScript':
  160. return await this.#scriptProcessor.removePreloadScript(this.#parser.parseRemovePreloadScriptParams(command.params));
  161. // keep-sorted end
  162. // Session domain
  163. // keep-sorted start block=yes
  164. case 'session.new':
  165. return await this.#sessionProcessor.create(command.params);
  166. case 'session.status':
  167. return this.#sessionProcessor.status();
  168. case 'session.subscribe':
  169. return await this.#sessionProcessor.subscribe(this.#parser.parseSubscribeParams(command.params), command.channel);
  170. case 'session.unsubscribe':
  171. return await this.#sessionProcessor.unsubscribe(this.#parser.parseSubscribeParams(command.params), command.channel);
  172. // keep-sorted end
  173. // Storage domain
  174. // keep-sorted start block=yes
  175. case 'storage.deleteCookies':
  176. return await this.#storageProcessor.deleteCookies(this.#parser.parseDeleteCookiesParams(command.params));
  177. case 'storage.getCookies':
  178. return await this.#storageProcessor.getCookies(this.#parser.parseGetCookiesParams(command.params));
  179. case 'storage.setCookie':
  180. return await this.#storageProcessor.setCookie(this.#parser.parseSetCookieParams(command.params));
  181. // keep-sorted end
  182. }
  183. // Intentionally kept outside the switch statement to ensure that
  184. // ESLint @typescript-eslint/switch-exhaustiveness-check triggers if a new
  185. // command is added.
  186. throw new protocol_js_1.UnknownCommandException(`Unknown command '${command.method}'.`);
  187. }
  188. // Workaround for as zod.union always take the first schema
  189. // https://github.com/w3c/webdriver-bidi/issues/635
  190. #processTargetParams(params) {
  191. if (typeof params === 'object' &&
  192. params &&
  193. 'target' in params &&
  194. typeof params.target === 'object' &&
  195. params.target &&
  196. 'context' in params.target) {
  197. delete params.target['realm'];
  198. }
  199. return params;
  200. }
  201. async processCommand(command) {
  202. try {
  203. const result = await this.#processCommand(command);
  204. const response = {
  205. type: 'success',
  206. id: command.id,
  207. result,
  208. };
  209. this.emit("response" /* CommandProcessorEvents.Response */, {
  210. message: OutgoingMessage_js_1.OutgoingMessage.createResolved(response, command.channel),
  211. event: command.method,
  212. });
  213. }
  214. catch (e) {
  215. if (e instanceof protocol_js_1.Exception) {
  216. this.emit("response" /* CommandProcessorEvents.Response */, {
  217. message: OutgoingMessage_js_1.OutgoingMessage.createResolved(e.toErrorResponse(command.id), command.channel),
  218. event: command.method,
  219. });
  220. }
  221. else {
  222. const error = e;
  223. this.#logger?.(log_js_1.LogType.bidi, error);
  224. this.emit("response" /* CommandProcessorEvents.Response */, {
  225. message: OutgoingMessage_js_1.OutgoingMessage.createResolved(new protocol_js_1.UnknownErrorException(error.message, error.stack).toErrorResponse(command.id), command.channel),
  226. event: command.method,
  227. });
  228. }
  229. }
  230. }
  231. }
  232. exports.CommandProcessor = CommandProcessor;
  233. //# sourceMappingURL=CommandProcessor.js.map