How Chromium's Protocol Monitor Exposes Raw CDP Messages

This article provides a technical overview of how the Protocol Monitor in the Chromium web browser intercepts, processes, and displays raw JSON-RPC 2.0 messages transmitted over the Chrome DevTools Protocol (CDP). By examining the DevTools frontend architecture, internal message routing hooks, and UI rendering pipelines, you will understand how browser instrumentation traffic is exposed in real-time for debugging and development.

The DevTools Frontend Architecture

Chrome DevTools is a web application written in TypeScript that runs in its own renderer process. To inspect and debug a web page, the DevTools frontend communicates with the Chromium browser backend and its various processes using the Chrome DevTools Protocol (CDP).

Every action taken in the DevTools UI—such as inspecting a DOM node, pausing on a JavaScript breakpoint, or recording network activity—is translated into a raw JSON-RPC 2.0 message. The Protocol Monitor is a built-in experimental panel within DevTools designed to tap directly into this communication channel and reveal these underlying payloads.

Message Interception via InspectorBackend

The core mechanism that exposes raw CDP messages lies within the protocol_client module of the DevTools frontend source code. All CDP traffic is routed through a central management class known as InspectorBackend.

Rather than parsing traffic at the network socket level, the Protocol Monitor hooks directly into the InspectorBackend message dispatcher. When the Protocol Monitor panel is opened by the user, it registers callback functions onto internal instrumentation hooks: onMessageSent and onMessageReceived. Because these hooks sit at the boundary between the DevTools application logic and the transport layer, they have access to the exact JSON payloads moving in both directions.

Capturing Outgoing Requests

When a DevTools panel requests data from the browser, it invokes a CDP command. The frontend serializes this command into a JSON-RPC request object containing three primary properties:

  • id: A sequentially generated integer used to track the request.
  • method: The CDP domain and command name (e.g., Page.navigate or DOM.getDocument).
  • params: An object containing the arguments required by the method.

Right before this serialized JSON string is passed to the underlying transport layer (which is either a WebSocket connection for remote debugging or Chromium's internal InspectorFrontendHost C++ bindings for local debugging), the onMessageSent hook fires. It passes a clone of the raw JSON object and the target metadata directly to the Protocol Monitor controller, which logs the outgoing request immediately.

Capturing Incoming Responses and Events

Traffic flowing from the Chromium backend to the DevTools frontend consists of two types of JSON-RPC messages: command responses and asynchronous events. When the transport layer receives a raw JSON string from the browser, it parses the string into a JavaScript object and immediately triggers the onMessageReceived hook before routing the data to the rest of the DevTools UI.

The Protocol Monitor inspects the incoming object to determine its type:

  • Responses: If the JSON object contains an id property, the Protocol Monitor identifies it as a response to a previously sent command. It extracts the result object (or the error object if the command failed) and pairs it with the matching outgoing request id. This pairing allows the monitor to calculate the exact round-trip execution time in milliseconds.
  • Events: If the JSON object lacks an id but contains a method and params, it is classified as an asynchronous event (e.g., Network.requestWillBeSent). The Protocol Monitor logs this as a standalone incoming message.

Handling Multiplexed Sessions

Modern Chromium architecture uses a flat session hierarchy to debug multiple targets—such as iframes, web workers, and service workers—over a single shared connection. To route messages to the correct target, CDP appends a sessionId field to the root of the JSON-RPC payload.

The Protocol Monitor extracts this sessionId directly from the raw message and cross-references it with the active Target Manager in DevTools. This allows the monitor to expose not just the raw JSON payload, but also the specific execution context or target that generated or received the message.

Rendering and Injecting Raw Payloads

Once the ProtocolMonitor module intercepts the raw objects, it appends them to an internal array and renders them inside a virtualized data grid. To ensure performance does not degrade during heavy browser activity, the UI only renders the text for visible rows.

When a user selects a specific message in the grid, the Protocol Monitor passes the unmutated JavaScript object representation of the JSON-RPC payload into a read-only object tree viewer. Furthermore, the Protocol Monitor exposes a command input bar at the bottom of the panel. When a developer types a raw JSON string into this input, the monitor bypasses the standard DevTools UI modules and injects the payload directly into the MainConnection.sendRawMessage method, sending the custom JSON-RPC command straight to the Chromium backend.