The WebKit Web Inspector in Safari & Chrome is part of every decent web developer’s toolkit, but unfortunately it’s unavailable in Mobile Safari.
Or is it?
While I was researching my previous article on enabling WebGL on iOS via private WebKit APIs, another API caught my eye while I was class-dump
ing the private WebKit.framework
.
Private WebView API1 2 3 | @interface WebView (WebPrivate) + (void)_enableRemoteInspector; @end
|
I did a little bit of research and found an article by Pavel Feldman (@repenaxa) on the Surfin’ Safari blog about WebKit’s remote debugging feature. This private +[WebView _enableRemoteInspector]
API enables those same features in mobile WebKit.
Note: This API is available as of iOS 5.0. To use it, you’ll need a copy of Xcode with the iOS 5.0 SDK. You’ll also need to make sure that if you’ve got the iOS 4.0 SDK installed alongside the iOS 5.0 SDK, that you’ve selected iOS 5.0 in the iPhone Simulator via the Hardware → Version
menu. Hat tip to Phil Oye (@philoye) for pointing that out.
Enabling remote debugging in a UIWebView
To see if I could get it working, I checked out a copy of my UIWebViewWebGL project, and called the private API in application:didFinishLaunchingWithOptions
:
Enabling the remote inspector on launch1 2 3 4 5 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // ...Snipped... [NSClassFromString(@"WebView") _enableRemoteInspector]; // ...Snipped... }
|
The Surfin’ Safari article said the remote debugger runs on port 9222
, but connecting to http://localhost:9222
while the app was running in the simulator didn’t seem to work.
Using lsof
showed that UIWebViewWebGL.app
was actually listening on port 9999
:
$ sudo lsof -i TCP -a -p $(pidof UIWebViewWebGL) -P COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME UIWebView 3748 nathan 9u IPv6 0xffffff800fa25d80 0t0 TCP localhost:9999 (LISTEN) UIWebView 3748 nathan 13u IPv6 0xffffff80111ba340 0t0 TCP localhost:9999->localhost:52483 (ESTABLISHED)
Now when I pointed my browser at http://localhost:9999
, it worked!
Logging document.location.href
in the web inspector console shows I’m successfully inspecting the web content from UIWebViewWebGL.app
running in the iPhone Simulator.
Huzzah!
Enabling remote debugging in Mobile Safari
Enabling the web inspector in an embedded UIWebView
is handy, but what about content running in Mobile Safari?
To do that, we need to call the +[WebView _enableRemoteInspector]
API from within the Mobile Safari app. The easiest way to do that is by launching Mobile Safari in the iPhone Simulator, and then use gdb
to attach to it and call the private API.
Script to enable the remote inspector in Mobile Safari1 2 3 4 5 6 7 8 9 10 11 12 13 | MobileSafari_PID=$(ps x | grep "MobileSafari" | grep -v grep | awk '{ print $1 }') if [ "$MobileSafari_PID" == "" ]; then echo "Mobile Safari.app must be running in the Simulator to enable the remote inspector." else cat <<EOM | gdb -quiet > /dev/null attach $MobileSafari_PID p (void *)[WebView _enableRemoteInspector] detach EOM fi
|
Browsing to http://localhost:9999
will show an index page listing the URL of each tab open in Mobile Safari. This allows you to have a remote inspector open for each tab in Mobile Safari.
Summing Up
I haven’t used the remote inspector in anger yet, but so far it’s been incredibly useful.
Note that you can’t use gdb
to inject code on a device, so enabling remote debugging in Mobile Safari is limited to the Simulator. Hopefully Apple will provide the option to enable it, much like the debug console in Settings → Safari → Advanced → Debug Console
.
In the meantime, you can load your web content in an embedded UIWebView. Enabling the remote inspector on a UIWebView
in an app running on the device doesn’t seem to work. Using nmap
shows that my iPhone only has port 62078
open for OTA syncing, so it’s likely there’s a firewall preventing connections to the remote inspector port.