Search code examples
iosgeolocationwebkitwkwebview

How to prevent WKWebView to repeatedly ask for permission to access location?


I have a WKWebView in my app and when I start browsing www.google.com or any other website that requires location service, a pop up window appears, asking for the permission to access the location of the device even if I have already accepted to share my location.

The only thing I did to manage this location stuff is that I added the NSLocationWhenInUseUsageDescription attribute in my info.plist.

I couldn't find any answers on the web so any idea would be really appreciated.


Solution

  • Turns out it's quite hard, but possible to do. You have to inject JavaScript code which intercepts requests to navigator.geolocation and transfer them to your app, then get the location with CLLocationManager, then inject location back to the JavaScript.

    Here is the brief scheme:

    1. Add WKUserScript to your WKWebView configuration which overrides methods of navigator.geolocation. Injected JavaScript should look like this:

      navigator.geolocation.getCurrentPosition = function(success, error, options) { ... };
      navigator.geolocation.watchPosition = function(success, error, options) { ... };
      navigator.geolocation.clearWatch = function(id) { ... };
      
    2. With WKUserContentController.add(_:name:) add script message handler to your WKWebView. Injected JavaScript should call your handler, like this:

      window.webkit.messageHandlers.locationHandler.postMessage('getCurrentPosition');
      
    3. When a web page will request a location, this method will fire userContentController(_:didReceive:) so your app would know web page is requesting location. Find your location with the help of CLLocationManager as usual.

    4. Now it's time to inject the location back to the requesting JavaScript with webView.evaluateJavaScript("didUpdateLocation({coords: {latitude:55.0, longitude:0.0}, timestamp: 1494481126215.0})"). Of course your injected JavaScript should have didUpdateLocation function ready to launch saved success handler.

    Quite a long algorithm, but it works!