Debugging WebKit

Processes

The WebKit system framework exports two public APIs on both Mac and iOS: a modern, multi-process API (WKWebView) and a legacy single-process API (WebView on Mac and UIWebView on iOS). Unlike the legacy API that executes within a single-process the modern WebKit API functionality is segregated between the UIProcess (e.g. Safari) and the following auxiliary processes:

Colloquial name Process name Purpose
WebProcess com.apple.WebKit.WebContent.Development Core engine
NetworkProcess com.apple.WebKit.Networking.Development Networking
StorageProcess com.apple.WebKit.Storage.Development IndexedDB/Service Worker Storage

The code base is organized around these process boundaries. You will need to attach to the appropriate process(es) to debug an issue.

Logging

WebKit emits a lot of logging by default. You can change the verbosity of this logging by setting the environment variable OS_ACTIVITY_MODE to one of the following values:

Value Description
disable Disables all logging and activity tracing (cannot be overridden)
off Turn all logging and activity tracing on process launch (may be overridden by tools)
info Info level logging
debug Debug level logging

iOS Simulator

In Terminal, run the following command to attach to the currently running MobileSafari:

xcrun --sdk iphonesimulator lldb --attach-name MobileSafari

Use the --wait-for option to wait for MobileSafari to be launched and attach to it as early as possible.

xcrun --sdk iphonesimulator lldb --attach-name MobileSafari --wait-for

Substitute com.apple.WebKit.WebContent.Development for the value of --attach-name to debug the WebProcess.

macOS

Internal Debug Menu

There is a Debug menu that can be enabled in Safari, and it exposes many useful options to help with debugging. To enable it, run the following in Terminal:

defaults write com.apple.Safari IncludeInternalDebugMenu 1

Debugging UIProcess from Terminal

Run script debug-safari or debug-minibrowser. It will start the debugger with Safari or MiniBrowser as the target, respectively. At the debugger prompt, enter run to start the process.

Debugging using Xcode

To debug from within Xcode, you can use the WebKit workspace. Ensure that the Products, Intermediates, and Index Datastore locations for the workspace match those used by build-webkit by choosing File > Workspace Settings and clicking the Advanced button, selecting Custom, Relative to Workspace, and entering WebKitBuild for Products, Intermediates and Index Datastore. Note that if you have specified a custom build location in Xcode preferences, then you don’t need to do this.

Debugging UIProcess

  1. Open the WebKit Xcode workspace
Note: The Xcode project file depends on the build location specified in the project itself. To interchange between building WebKit from the command line and Xcode you must ensure both use the same build directory. See remark above.
  1. Set the project’s build products location

    To find the WebKit you built, Xcode needs to know the build products location that build-webkit used. You can set the build products location in the project’s build settings editor.

  2. Set the project’s active scheme

    Xcode also needs to know the build configuration you used. You can set the active scheme from the workspace window.

  3. Add Safari to the project’s active scheme

    Choose Edit Scheme from scheme pop-up menu. In the leftmost pane of the window, choose Run. In the Info pane, choose Other from the Executable pop-up menu. Then select /Applications/Safari.app.

  4. Launch the debugger

    In the workspace window, click the Run button.

  5. See Debugging Tools for more information on using Xcode to debug software on macOS.

Debugging WebProcess

Current versions of Safari use a process for each tab, so it is easy to end up with a new WebProcess and have to reattach. If you enable the Internal Debug Menu as outlined above, you can have Safari display the Process ID of the WebProcess for each tab. Simply go to Debug > Miscellaneous Flags and select Show Web Process IDs In Page Titles. You should now see something like [WP 60737] in the title of every web page you navigate to, and 60737 is the Process ID of the WebProcess backing that tab.

Open the WebKit workspace and choose “All Source (target WebProcess)” from the Scheme pop-up menu in the toolbar, then choose Product > Run. If WebKit is already built, it is quicker to choose Product > Perform Action > Run Without Building