Runs in the background and handles incoming messages. Dispatches responses to commands and events to listeners.
(self)
| 444 | return session |
| 445 | |
| 446 | async def _reader_task(self): |
| 447 | """Runs in the background and handles incoming messages. |
| 448 | |
| 449 | Dispatches responses to commands and events to listeners. |
| 450 | """ |
| 451 | global devtools |
| 452 | if devtools is None: |
| 453 | raise RuntimeError("CDP devtools module not loaded. Call import_devtools() first.") |
| 454 | while True: |
| 455 | try: |
| 456 | message = await self.ws.get_message() |
| 457 | except WsConnectionClosed: |
| 458 | # If the WebSocket is closed, we don't want to throw an |
| 459 | # exception from the reader task. Instead we will throw |
| 460 | # exceptions from the public API methods, and we can quietly |
| 461 | # exit the reader task here. |
| 462 | break |
| 463 | try: |
| 464 | data = json.loads(message) |
| 465 | except json.JSONDecodeError: |
| 466 | raise BrowserError( |
| 467 | { |
| 468 | "code": -32700, |
| 469 | "message": "Client received invalid JSON", |
| 470 | "data": message, |
| 471 | } |
| 472 | ) |
| 473 | logger.debug("Received message %r", data) |
| 474 | if "sessionId" in data: |
| 475 | session_id = devtools.target.SessionID(data["sessionId"]) |
| 476 | try: |
| 477 | session = self.sessions[session_id] |
| 478 | except KeyError: |
| 479 | raise BrowserError( |
| 480 | { |
| 481 | "code": -32700, |
| 482 | "message": "Browser sent a message for an invalid session", |
| 483 | "data": f"{session_id!r}", |
| 484 | } |
| 485 | ) |
| 486 | session._handle_data(data) |
| 487 | else: |
| 488 | self._handle_data(data) |
| 489 | |
| 490 | for _, session in self.sessions.items(): |
| 491 | for _, senders in session.channels.items(): |
| 492 | for sender in senders: |
| 493 | sender.close() |
| 494 | |
| 495 | |
| 496 | @asynccontextmanager |
nothing calls this directly
no test coverage detected