| # Chrome DevTools Protocol | |
| ## Definitions | |
| ### Domain | |
| A group of CDP methods and events, which can usually be individually enabled or | |
| disabled and individually supported by different types of targets. | |
| *Source: [Chrome DevTools Walkthrough](https://docs.google.com/document/d/1QG7P18wDIhB_twNbkvEAbgJfNoTkyTRXf-6Nk2TTYPI/edit#)* | |
| ### Agent (in blink) or Handler (in browser) | |
| TLDR: Backend implementation of a domain that syncs with the frontend. | |
| Agents and Handlers are backend classes that implement individual protocol | |
| domains. Some domains are implemented as agents in the renderer process (either | |
| in Blink or v8; no agents are currently present in the content/renderer so far) | |
| and some as handlers in the browser process (implemented either by the content | |
| layer or by the embedder). A domain may be implemented by multiple agents or | |
| handlers spanning several layers and processes, e.g. have instances in | |
| `chrome/`, `content/` and `blink/renderer/` . A single command may be handled by | |
| multiple layers in the following sequence: | |
| embedder, content browser, blink, V8. An agent may indicate that it has | |
| completed handling the command or let the command fall-through to the | |
| next layer. | |
| *Source: | |
| - [Chrome DevTools Contribution Guide](https://docs.google.com/document/d/1WNF-KqRSzPLUUfZqQG5AFeU_Ll8TfWYcJasa_XGf7ro/edit#) | |
| - [third_party/blink/public/devtools_protocol - chromium/src - Git at Google](https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/public/devtools_protocol/) | |
| ## Background | |
| ### browser_protocol.pdl | |
| The `browser_protocol.pdl` file is the source of truth that is used to generate | |
| the `browser_protocol.json` file and the `.ts`, `.h` and `.cc` files. | |
| However, there are multiple `browser_protocol.pdl` files across the codebase. | |
| The main one is located at (in your chromium repo): | |
| `third_party/blink/public/devtools_protocol/browser_protocol.pdl` | |
| This is the one you should modify and the other ones will be synced using | |
| different commands explained later. | |
| There’s also a separate `js_protocol.pdl` that has only V8-specific domains. | |
| ## Create a new Protocol | |
| ### 1- Create your domain on the Chromium repository | |
| #### 1.1- Add your domain to the main browser_protocol.pdl file in your | |
| chromium repository To create a new domain, you should add your new domain to | |
| `third_party/blink/public/devtools_protocol/browser_protocol.pdl` | |
| #### 1.2- Modify headless/BUILD.gn | |
| Open the file `headless/BUILD.gn` in your chromium repository and the name of | |
| your new domain under the devtools_domain section. | |
| #### 1.3- Modify third_party/blink/renderer/core/inspector/BUILD.gn | |
| Open the file `third_party/blink/renderer/core/inspector/BUILD.gn` in your | |
| chromium repository and add the new protocol files to be generated under the | |
| outputs section. The convention is to use the domain name converting it from | |
| camel case to snake case. | |
| The protocol files generated will list the methods that your Agent will need to | |
| implement to enable the communication between the Chrome DevTools and Chromium. | |
| #### 1.4- Modify inspector_protocol_config.json | |
| Open the file | |
| `third_party/blink/renderer/core/inspector/inspector_protocol_config.json` and | |
| under `protocol.options`, add your new domain: | |
| ```json | |
| { | |
| "domain": "YourNewDomain" | |
| } | |
| ``` | |
| #### 1.5- Build chromium | |
| Build chromium as you normally would. | |
| #### 1.6- See the newly generated protocol C++ files | |
| Your new domain files should be generated in this folder: | |
| ```bash | |
| src/out/Default/gen/third_party/blink/renderer/core/inspector/protocol/your_new_domain.cc | |
| src/out/Default/gen/third_party/blink/renderer/core/inspector/protocol/your_new_domain.h | |
| ``` | |
| #### 1.7- Add the agent to the devtools-frontend/front_end/core/protocol_client/InspectorBackend.ts | |
| Open the file `devtools-frontend/front_end/core/protocol_client/InspectorBackend.ts` and add a new method to expose your Agent. | |
| ```ts | |
| youNewDomainAgent(): ProtocolProxyApi.YourNewAgentApi { | |
| return this.getAgent('YourNewAgent'); | |
| } | |
| ``` | |
| #### 1.8- Add the newly generated protocol files to the BUILD.gn | |
| In your chromium repository, open the file | |
| `third_party/blink/renderer/core/inspector/BUILD.gn` and add the newly generated | |
| protocol files. This will make them available to be used later in the Agent | |
| class. | |
| ``` | |
| outputs = [ | |
| ... | |
| "inspector/protocol/your_new_domain.cc", | |
| "inspector/protocol/your_new_domain.h", | |
| ] | |
| ``` | |
| ### 2- Sync the browser_protocol files and generate the protocol resources | |
| As mentioned before, there are many browser_protocol files. To synchronize the | |
| modifications, run this command from your Chrome DevTools repository: | |
| ```bash | |
| scripts/deps/roll_deps.py ~/chromium/src . | |
| ``` | |
| The first parameter is the path from your Chrome DevTools repository to the | |
| chromium repository. The second parameter is the root of the | |
| Chrome DevTools repository. | |
| ### 3- Create the Agent on the Chromium repository | |
| #### 3.1- Create the Agent class | |
| The Agent class should inherit the newly created protocol | |
| `protocol::YourNewDomainAgent::Metainfo` | |
| ```cpp | |
| class MODULES_EXPORT YourNewDomainAgent final : public InspectorBaseAgent<protocol::YourNewDomainAgent::Metainfo> { | |
| ``` | |
| #### 3.2- Register the Agent | |
| The Agent must be registered with the Session. To do so, go to the file | |
| `third_party/blink/renderer/modules/modules_initializer.cc` and append it to the | |
| session in this method: | |
| ```cpp | |
| void ModulesInitializer::InitInspectorAgentSession { | |
| … | |
| session->CreateAndAppend<YourNewAgent>... | |
| ``` | |
| ### 4- Setup the communication from the Chrome DevTools repository | |
| In the TypeScript class, your agent can now be accessible directly from the | |
| target. With the target, you can simply access your agent like this: | |
| ```ts | |
| initialize(target: SDK.Target.Target) { | |
| target.yourNewDomainAgent(); | |
| } | |
| ``` |