Cobalt Web Debugging

Overview

Cobalt includes the Chrome DevTools frontend for debugging web apps. It's available in the 20.lts.1+ and newer branches of Cobalt.

Cobalt only supports a subset of what DevTools can do, but we make a point of hiding UI elements that don't work so everything you see in the UI should work. As we get more implemented in the backend the respective UI will be enabled in the frontend.

The following panels are supported:

  • Elements - view the DOM tree and CSS styles
  • Console - JavaScript “command line” and logging output
  • Sources - interactive JavaScript debugging
  • Performance - profile JavaScript execution

Cobalt DevTools relies heavily on V8 for its backend implementation. When Cobalt is built with MozJs only basic Elements and Console functionality is supported, but the UI remains the same as when building with V8 and some things don't work.

Using DevTools

The DevTools frontend is loaded in Chrome from a small HTTP server built into non-gold Cobalt. Even though it looks mostly the same as Chrome‘s inspector (it’s built from the same source code), Cobalt‘s DevTools is a separate app, and Cobalt is not a remote target that you can debug with Chrome’s built-in debugger.

After building and running Cobalt as usual, use Chrome on your desktop to load the start page from port 9222 on the target device where Cobalt is running. Click through to the only inspectable page shown on the start page.

If you have trouble connecting:

  • Ensure you have an IP route from your desktop to the target device that allows traffic on the debugging port (default 9222).
  • If you are running Cobalt locally on your desktop, then use http://localhost:9222 since the Linux build only listens to the loopback network interface by default.

If you‘re not sure what IP address to use, look in the terminal log output for a message telling you the URL of Cobalt’s DevTools (which you may be able to open with a ctrl-click in many terminal programs):

---------------------------------
 Connect to the web debugger at:
 http://192.168.1.1:9222
---------------------------------

Wait for web debugger

If you‘re debugging the initial page as it’s loading you need use the --wait_for_web_debugger switch to tell Cobalt to wait until you attach DevTools before actually loading the initial URL:

out/linux-x64x11_devel/cobalt --wait_for_web_debugger --url="http://test.example.com"

When this switch is specified, Cobalt will appear to hang with just a black window until you load DevTools. In the terminal log output you'll see that Cobalt is waiting with message like:

-------------------------------------
 Waiting for web debugger to connect
-------------------------------------

If you're debugging a page in a series of redirects, you can specify a number to make Cobalt wait before loading the Nth page. If no number is specified with the switch, the default value is 1 to wait before the initial page load. For example:

out/linux-x64x11_devel/cobalt --wait_for_web_debugger=2 --url="http://test.example.com"

Panels

Elements

The Elements panel displays the DOM as a tree with expandable nodes to dig into it. The right side bar shows the CSS styles affecting the selected node in the DOM. The Styles tab shows matching rules, inherited rules, and inline style. The Computed tab shows the computed style for the selected node. The box model properties are shown graphically in both the Styles and Computed tabs.

Cobalt currently only supports a read-only view of the DOM and CSS.

Chrome docs:

Console

Cobalt has two types of consoles:

  • Overlay Console: shown at runtime of Cobalt. It has multiple mode that it can cycle between as well:
    • HUD
    • HUD & Debug Console
    • Media Console
  • Remote Console: shown in a connected devtools session.

Both console UIs show messages logged from JavaScript (with console.log(), etc.), and have a command line to evaluate arbitrary JavaScript in the context of the page being debugged.

Overlay Console

The overlay console also shows non-JavaScript logging from Cobalt itself, which is mostly interesting to Cobalt developers rather than web app developers.

The various modes of the overlay console are accessed by repeatedly pressing “F1” or “Ctrl+O”. They cycle in order between: none, HUD, HUD & Debug, and Media. Alternatively, initial console state can be set with the --debug_console=off|hud|debug|media command-line switch (--debug_console=on is accepted as a legacy option and maps to “debug” setting).

Overlay Console mode switching

HUD overlay

This brings up an overlay panel which does not block sending input to the underlying Cobalt app. It serves to display real-time statistics (e.g. memory usage) and configuration values (e.g. disabled codecs) of the Cobalt app in a compact string.

Debug Console overlay

This overlay is interactive and it shows messages from Cobalt, along with logs from Javacript console.log(). While it is active, you cannot interact directly with the underlying page.

Additionally, it can act as a JS interpreter that will evaluate arbitrary expressions on the page being debugged. The output from these JS commands will also be printed to the Debug console.

Finally, it has some special debug commands which can be listed by calling d.help(). They are provided by a debug helper object and the list of functions are invoked by prepending either “debug” or “d”. For example, you can disable the vp9 codec manually for all future played videos in this session of Cobalt by sending debug.disable_media_codecs("vp9") to the console.

Note: you can clear the disabled media codecs by sending debug.disable_media_codecs(""). The command takes a semicolon separated list of codecs as the input list of codecs to disable.

Media Console overlay

The media console is a specialized console of the debug overlay system, for playback and media related tasks. The current list of implemented features are:

  • Reading the play/pause state of the primary video
  • Reading the current time and duration of the primary video
  • Reading the playback rate of the primary video
  • Reading the currently disabled codecs for the player
  • Toggling between playing and pausing the primary video
  • Setting the current playback rate between various presets for the primary video
  • Toggling the enabled/disabled state of the available codecs

While the media console is shown, it is not possible to interact with the page below it directly.

Additionally, the console does not show any meaningful information or interactions when no video is currently playing (all the readouts are blank or undefined). A status message of “No primary video.” indicates there is no valid player element on the current page.

In the case of multiple videos playing (such as picture in picture), only the primary (fullscreen) video’s information is shown and the controls are only enabled for the primary video.

The list of hotkeys and commands are dynamically generated as they are found to be available on app startup.

Basic always-enabled commands are (case-sensitive):

  • p” Toggle the play/pause state
  • ]” Increase the playback rate
  • [” Decrease the playback rate

The above commands will take effect instantly for the currently playing video. They have no effect if there is no video playing.

The following commands are dynamically loaded based on the capability of the system:

  • CTRL+NUM” Enable/disable specific video codec
  • ALT+NUM” Enable/disable specific audio codec

Important: Media Console cannot be used to directly select a specific codec for playback. See the section below for rough outline of steps to work around this.

The list of available codecs for any video is chosen based on the decoders on the platform, and what formats YouTube itself serves. As a result, the only way to get a particular codec to play is to disable all the options until the desired codec is the one that is picked. Simply do the following procedure:

  • Pick the video you want to play.
  • Enable “stats for nerds” (See help page for instructions).
  • Write down the codecs that are chosen when playing the video, without any codecs disabled (one for video, and one for audio).
  • Disable the default codecs.
  • Replay the same video from the browse screen.
  • Repeat until you identify all codecs that are available for the video, until the video is unable to be played.
  • Use the above knowledge to disable the codecs to force the player into choosing a particular codec, by process of elimination.

Important: Disabled codecs only take effect when a video starts playing. When you play a video, the current list of disabled codecs is used to select an arbitrary enabled format. When you seek in the video, the disabled codecs list does not take effect. Only when you exit the player and re-enter by playing a video will any toggled codecs be affected.

Important: Disabled codecs list is persistent for the app-run. If you disable “av01”, then until you re-enable it, “av01” formats will never be chosen.

Important: If you disable all the available codecs, no video codec can be selected and an error dialog will be shown. This means that YouTube does not have the video in any other formats, outside of the codecs that are disabled. The player reports that it cannot play the video in any of the available formats so playback will fail here, which is intended.

Remote Console

The console in DevTools is a richer UI that can show evaluated objects with an expander so you can dig in to their properties. Logging from JavaScript with console.log() can show objects and exceptions as well, in contrast to the text-only messages shown in the console overlay.

Chrome docs:

Sources

Source-level JavaScript debugging can be done on the Sources panel. You can inspect sources, set breakpoints, see call stacks and scoped variables, add watch expressions, and all that good stuff.

Source debugging only works when Cobalt is built with V8.

Chrome docs:

Performance

The Performance panel allows you to record a profile of sampled call stacks while Cobalt is running your JavaScript code. The recorded profile is displayed in a flame chart showing the relationship and timing of function calls.

Performance profiling only works when Cobalt is built with V8, and the platform implements the SbThreadSampler Starboard API.

The profiler can't currently identify which is the main thread, but you can easily see it as the one with the most events.

Chrome docs:

Tips

  • You can make Cobalt reload the current page by pressing F5 in the Cobalt window, or ctrl-R in the remote DevTools. This may be useful for debugging startup code in the web app. It may also help in case some source file is not appearing in the DevTools Sources panel.

  • The DevTools frontend remembers your breakpoints, so if you need to restart Cobalt completely you can just kill it with ctrl-C in the terminal where you launched it and re-run it. Then click the Reconnect DevTools button shown in the DevTools UI or refresh the page to reload the DevTools UI.

  • You can use the --remote_debugging_port command line switch to specify a remote debugging port other than the default 9222.

  • You can use the --dev_servers_listen_ip command line switch to change which network interface the remote debugging server is listening to.