Add chords to the DevTools

This CL adds the ability to bind actions to a sequence of two
keypresses, rather than just one (e.g. Ctrl+K Ctrl+O). VS Code refers to
these as chords [1]. As we move forward with custom keyboard shortcuts,
it's necessary to implement chords in the DevTools so that users
can match their shortcuts to editor shortcuts that use chords or assign
custom chords. This CL also adds a Ctrl+K Ctrl+S shortcut to open the
shortcuts settings for testing purposes, but I plan to remove that
shortcut before landing this change. It will return later as part of the
VS Code editor preset.

My implementation of chords here is focused on two-keypress
shortcuts, e.g. Ctrl+K Ctrl+Shift+Q would be a valid chord but Ctrl+K
Ctrl+K Ctrl+O would not be because it has three parts. Limiting chords
to two parts simplifies the implementation and matches a similar
restriction in VS Code. Although other editors like vim and Atom allow
shortcuts of arbitrary length, that's not really a feature that users
have asked for and it would introduce extra complexity into
ShortcutRegistry for questionable gain. However, the new structure of
ShortcutRegistry leaves open the possibility of enabling
arbitrary-length shortcuts in the future.

ShortcutRegistry's approach to handling a key has been changed as
follows:

If a keypress comprises only modifiers (e.g Ctrl+Shift), then it's
ignored. The DevTools already disallow modifier-only shortcuts, so this
change just prevents modifiers from clearing the chord timeout.

If the first half of a chord has been pressed within the timeout
(currently 1000ms), then clear the timeout and try to execute the
current key as the second half of a chord. If that isn't a valid chord,
then try to execute both keys as separate shortcuts in sequence.

If there isn't an active timeout and the keypress is potentially the
first part of a chord, then set _activePrefixKey and
_activePrefixTimeout. If the timeout expires without a second key being
pressed, attempt to handle the keypress as an individual shortcut.

If the keypress isn't potentialy the first part of a chord and there
isn't an active timeout, then it will be handled as normal.


There were a few shortcuts handled outside of ShortcutRegistry (e.g.
sources.rename, debugger.toggle-breakpoint) that made the assumption
that checking the key of a single event was enough to determine whether
it matched a shortcut, so that flow has been reworked to centralize all
shortcut-matching in
ShortcutRegistry.handleKey().


Custom shortcuts design doc: https://docs.google.com/document/d/1oOPSWPxCHvMoBZ0Fw9jwFZt6gP4lrsrsl8DEAp-Hy7o/edit
[1] https://code.visualstudio.com/docs/getstarted/keybindings#_keyboard-rules

Bug: 174309
Change-Id: I1b3f384d7c65e41d0dbc5e32854fb331e052823f
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2125620
Commit-Queue: Jack Lynch <jalyn@microsoft.com>
Reviewed-by: Robert Paveza <Rob.Paveza@microsoft.com>
5 files changed
tree: eea91464c6005e6b9df88934e1dd11f7b4c80202
  1. build_overrides/
  2. docs/
  3. front_end/
  4. node_modules/
  5. scripts/
  6. test/
  7. third_party/
  8. v8/
  9. .clang-format
  10. .editorconfig
  11. .eslintignore
  12. .eslintrc.js
  13. .gitattributes
  14. .gitignore
  15. .gn
  16. .npmignore
  17. .style.yapf
  18. AUTHORS
  19. BUILD.gn
  20. DEPS
  21. DESIGN_GUIDELINES.md
  22. ENG_REVIEW_OWNERS
  23. htaccess
  24. INFRA_OWNERS
  25. karma.conf.js
  26. LICENSE
  27. LIGHTHOUSE_OWNERS
  28. OWNERS
  29. package-lock.json
  30. package.json
  31. PRESUBMIT.py
  32. protocol.json
  33. README.md
  34. tsconfig.base.json
  35. tsconfig.json
  36. WATCHLISTS
README.md

Chrome DevTools frontend

NPM package

The client-side of the Chrome DevTools, including all JS & CSS to run the DevTools webapp.

Source code

The frontend is available on chromium.googlesource.com.

Design Guidelines

Please be aware that DevTools follows additional development guidelines.

Workflows

In order to make changes to DevTools frontend, build, run, test, and submit changes, several workflows exist. Having depot_tools set up is a common prerequisite.

Integrate standalone checkout into Chromium (strongly recommended)

This workflow will ensure that your local setup is equivalent to how Chromium infrastructure tests your change. It also allows you to develop DevTools independently of the version in your Chromium checkout. This means that you don't need to update Chromium often, in order to work on DevTools.

In chromium/src, run gclient sync to make sure you have installed all required submodules.

gclient sync

Then, disable gclient sync for DevTools frontend inside of Chromium by editing .gclient config. From chromium/src/, simply run

vim $(gclient root)/.gclient

In the custom_deps section, insert this line:

"src/third_party/devtools-frontend/src": None,

Then run

gclient sync -D

This removes the DevTools frontend dependency. We now create a symlink to refer to the standalone checkout (execute in chromium/src and make sure that third_party/devtools-frontend exists):

(Note that the folder names do NOT include the trailing slash)

ln -s path/to/standalone/devtools-frontend third_party/devtools-frontend/src

Running gclient sync in chromium/src/ will update dependencies for the Chromium checkout. Running gclient sync in chromium/src/third_party/devtools-frontend/src will update dependencies for the standalone checkout.

Standalone workflow

As a standalone project, Chrome DevTools frontend can be checked out and built independently from Chromium. The main advantage is not having to check out and build Chromium. However, there is also no way to run layout tests in this workflow.

Checking out source

To check out the source for DevTools frontend only, follow these steps:

mkdir devtools
cd devtools
fetch devtools-frontend
Build

To build, follow these steps:

cd devtools-frontend
gn gen out/Default
autoninja -C out/Default

The resulting build artifacts can be found in out/Default/resources/inspector.

Update to latest

To update to latest tip of tree version:

git fetch origin
git checkout origin/master
gclient sync
Run in Chromium

These steps work with Chromium 79 or later. To run the production build, use

(Requires brew install coreutils on Mac.)

<path-to-chrome>/chrome --custom-devtools-frontend=file://$(realpath out/Default/resources/inspector)

To run the debug build (directly symlinked to the original unminified source files), build both Chromium and DevTools frontend with the GN flag debug_devtools=true, and use

<path-to-chrome>/chrome --custom-devtools-frontend=file://$(realpath out/Default/resources/inspector/debug)

You can inspect DevTools with DevTools by undocking DevTools and then open the developers tools (F12 on Windows/Linux, Cmd+Option+I on Mac).

Test

Test are available by running scripts in scripts/test/.

Create a change

Usual steps for creating a change work out of the box.

Managing dependencies
  • To sync dependencies from Chromium to DevTools frontend, use scripts/deps/roll_deps.py && npm run generate-protocol-resources.

The following scripts run as AutoRollers, but can be manually invoked if desired:

  • To roll the HEAD commit of DevTools frontend into Chromium, use scripts/deps/roll_to_chromium.py.
  • To update DevTools frontend's DEPS, use roll-dep.

Chromium workflow (discouraged)

DevTools frontend can also be developed as part of the full Chromium checkout. This workflow can be used to make small patches to DevTools as a Chromium engineer. However, it is different to our infrastructure setup and how to execute general maintenance work.

Checking out source

Follow instructions to check out Chromium. DevTools frontend can be found under third_party/devtools-frontend/src/.

Build

Refer to instructions to build Chromium. To only build DevTools frontend, use devtools_frontend_resources as build target. The resulting build artifacts for DevTools frontend can be found in out/Default/resources/inspector.

Consider building with the GN flag debug_devtools=true to symlink to the original unminified source.

Run

Run Chrome with DevTools frontend bundled:

out/Default/chrome
Test

Test are available by running scripts in third_party/devtools-frontend/src/scripts/test/. After building content shell, we can also run layout tests that are relevant for DevTools frontend:

autoninja -C out/Default content_shell
third_party/blink/tools/run_web_tests.py http/tests/devtools
Create a change

Usual steps for creating a change work out of the box, when executed in third_party/devtools-frontend/src/.

Testing

Please refer to the overview document. The current test status can be seen at the test waterfall.

Additional references

Merges and Cherry-Picks

Merge request/approval is handled by Chromium Release Managers. DevTools follows The Zen of Merge Requests. In exceptional cases please get in touch with hablich@chromium.org.

Step-by-step guide on how to merge:

  1. Request and receive approval to merge
  2. Backmerges are done to the chromium/xxxx (e.g. chromium/3979) branch respectively on the DevTools frontend repo
  3. Use Omahaproxy to find out what branch a major Chromium version has (column true_branch). Open the to-be-merged commit in Gerrit e.g. Example
  4. Click hamburger menu on the top right and select Cherry Pick
  5. Select branch to merge to e.g. chromium/3968
  6. Cherry Pick CL is created e.g. Example
  7. Get it reviewed if necessary
  8. Click hamburger menu on the cherry pick CL and select Submit
  9. Done

Useful Commands

git cl format --js

Formats all code using clang-format.

npm run check

Runs all static analysis checks on DevTools code.

Source mirrors

DevTools frontend repository is mirrored on GitHub.

DevTools frontend is also available on NPM as the chrome-devtools-frontend package. It's not currently available via CJS or ES2015 modules, so consuming this package in other tools may require some effort.

The version number of the npm package (e.g. 1.0.373466) refers to the Chromium commit position of latest frontend git commit. It's incremented with every Chromium commit, however the package is updated roughly daily.

Getting in touch