-->

How to debug javascript in an iOS app WkWebView?

2019-05-25 05:28发布

问题:

I have a website that a 3rd party has iframed into their iOS app inside a WkWebView. There is a bug on my site that manifests only when viewed in this app; I cannot replicate it either via a browser or a separate iOS app that I built specifically to check for the bug. In order to proceed with resolving the bug, I need to be able to debug the javascript running in real time in the app. If I had a debug build of the app, this would be trivially easy: just hook it up to Safari's remote debugger, but due to security constraints, the app developer cannot release a debug build to me.

What options exist to debug javascript under these conditions?

  • cannot change app code
  • must work with a release build of an app
  • at a minimum, view logs or, preferably, expose capabilities comparable to a browser developer console:
    • add breakpoints
    • step through code
    • view DOM
    • view console outputs
  • importing a javascript library into my website to enable this is acceptable, but I would prefer a tool-based solution over a code-based one

回答1:

You can connect Safari's developer tools, from a Mac, to the iOS app. From there, you can debug the javascript within your web view and see anything you could see if you're testing any website in Safari on your Mac.

High-level steps are:

  • Reproduce issue in your app.
  • Connect device to Mac.
  • Follow steps in Apple documentation: https://developer.apple.com/library/content/documentation/AppleApplications/Conceptual/Safari_Developer_Guide/GettingStarted/GettingStarted.html#//apple_ref/doc/uid/TP40007874-CH2-SW8
  • After connecting the remote debugger from safari on your mac to the iOS app, click the refresh button. It'll force the in-app web view to refresh, so you'll see what went wrong on-load.


回答2:

You can get the data you want by sending an HTTP request to your server with the relevant debug information. It's a bit nasty because it's running for all your users on your production site and comes nowhere near the capabilities you would have if you could attach Safari to debug, but might work for this particular situation.

Some basic JS gives the general idea of how you might send events around page load and/or user triggered events:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
<button>Click Me</button>
  <script>
    var sendDebug = function(simpleObject) {
      var serializedObject = JSON.stringify(simpleObject);
      var iPhone = navigator.userAgent.indexOf('iPhone') > 0;
      var xhr = new XMLHttpRequest();
      xhr.open('GET', `https://null.jsbin.com?iphone=${iPhone}&info=${serializedObject}`);
      xhr.send(null);
    }
    document.querySelector('button').addEventListener('click', function() {
      sendDebug('clicked the button');
    })
    sendDebug('page loaded');
  </script>
</body>
</html>

I included a crude iPhone boolean based on the navigator.userAgent; you could consider send the data only for iPhones so you don't clutter your logs with non-iPhone requests (be aware that the userAgent can be modified from the app, so you'll want to double check what they are sending). Although, depending on the volume of traffic you handle, this might not be enough throttling.

This creates HTTP requests with the debug data appended to the query string. These should be visible in your access log on the server:

https://null.jsbin.com/?iphone=false&info=%22clicked%20the%20button%22

http://jsbin.com/novowoduka/edit?html,output