Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect if page is loaded inside WKWebView in JavaScript

How can I reliably detect using javascript that a page is loaded inside a WKWebView? I'd like to be able to detect these scenarios:

  • iOS & WKWebView
  • iOS & Safari
  • not iOS

There is a similar question about UIWebView here. But it's quite old and I'm not sure if same still applies to WKWebView.

like image 841
andr111 Avatar asked Mar 01 '15 15:03

andr111


2 Answers

The accepted answer doesn't work as tested using the WKWebView vs UIWebView app

As the article mentions, the only HTML5 feature difference is IndexedDB support. So I'd go for a more reliable pattern with:

    if (navigator.platform.substr(0,2) === 'iP'){       //iOS (iPhone, iPod or iPad)       var lte9 = /constructor/i.test(window.HTMLElement);       var nav = window.navigator, ua = nav.userAgent, idb = !!window.indexedDB;       if (ua.indexOf('Safari') !== -1 && ua.indexOf('Version') !== -1 && !nav.standalone){               //Safari (WKWebView/Nitro since 6+)       } else if ((!idb && lte9) || !window.statusbar.visible) {         //UIWebView       } else if ((window.webkit && window.webkit.messageHandlers) || !lte9 || idb){         //WKWebView       }     } 

You may ask: Why not using the UserAgent? That's because Android browsers use it as settings! So, we should never trust any UAs. Only browser features and property checks as such.

Also I noticed that the QuickTime plugin was always loaded as part of Older Safari and other Browsers in UIWebView. But the plugin is no longer present in WKWebView. So you can use the QuickTime plugin presence as an extra check.

9/23/16 Edit: I adjusted the code for Safari 10 which no longer allowed the sole idb check to be reliable, as mentioned by @xmnboy. To discard Safari 10, it checks for the old webkit engine bug, which only applied until Safari 9.2; and i use a window.statusbar.visible fallback which appears to be a reliable indicator signal after a few comparison tests between iOS 9 and 10. (please check though)

like image 124
hexalys Avatar answered Sep 18 '22 06:09

hexalys


Given the change in behavior to the UIWebView that was introduced by Apple in iOS 10, here's a new answer that combines the original response by @Justin-Michael and the follow-up favorite by @hexalys.

var isWKWebView = false ;
if( navigator.platform.substr(0,2) === 'iP' ) {    // iOS detected
    if( window.webkit && window.webkit.messageHandlers ) {
        isWKWebView = true ;
    }
}

It turns out that Justin's answer was really the better feature detection mechanism, because it works for both iOS 9 and iOS 10.

No telling what happens when we get to iOS 11. :-)


Qualification: this test will work if you are using the official Cordova WKWebView plugin to build your webview app, because that plugin does initialize the addScriptMessageHandler method, as noted by @hexalys in the comments to this post. That mechanism is being used by Cordova to define a new JS to native bridge when the WKWebView plugin is present.

Search for addScriptMessageHandler in that plugin repo and see the very end of the ios-wkwebview-exec.js file in that repo for some implementation details (or search for the string window.webkit.messageHandlers in that file).

like image 25
xmnboy Avatar answered Sep 20 '22 06:09

xmnboy