Подтвердить что ты не робот

Обнаружение, если страница загружена внутри WKWebView в JavaScript

Как я могу надежно обнаружить с помощью javascript, что страница загружается внутри WKWebView? Я хотел бы иметь возможность обнаруживать эти сценарии:

  • iOS и WKWebView
  • iOS и Safari
  • не iOS

Здесь есть аналогичный вопрос об UIWebView . Но он довольно старый, и я не уверен, что он применим и к WKWebView.

4b9b3361

Ответ 1

Вы можете проверить наличие window.webkit.messageHandlers, которое WKWebKit использует для приема сообщений с JavaScript. Если он существует, вы находитесь внутри WKWebView.

Это в сочетании с простой проверкой агента пользователя должно сделать трюк:

var iOS = (navigator.userAgent.match(/(iPad|iPhone|iPod)/g) ? true : false);
var isWKWebView = false;
if (window.webkit && window.webkit.messageHandlers) {
    isWKWebView = true;
}

Ответ 2

Принятый ответ не работает как проверенный с помощью WKWebView vs UIWebView app

Как упоминается в статье, единственным отличием особенностей HTML5 является поддержка IndexedDB. Поэтому я бы пошел на более надежный шаблон с помощью:

    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
      }
    }

Вы можете спросить: почему бы не использовать UserAgent? Это потому, что браузеры Android используют его в качестве настроек! Таким образом, мы никогда не должны доверять UA. Доступны только функции и свойства браузера.

Также я заметил, что плагин QuickTime всегда был загружен как часть Старого Safari и других браузеров в UIWebView. Но плагин больше не присутствует в WKWebView. Таким образом, вы можете использовать присутствие плагина QuickTime в качестве дополнительной проверки.

9/23/16 Редактирование: я скорректировал код для Safari 10, который больше не допускал, чтобы единственная проверка idb была надежной, как упоминалось @xmnboy. Чтобы отказаться от Safari 10, он проверяет наличие старой ошибки веб-кита, которая применяется только до Safari 9.2; и я использую резерв window.statusbar.visible, который кажется надежным сигналом индикатора после нескольких сравнительных тестов между iOS 9 и 10. (пожалуйста, проверьте, хотя)

Ответ 3

Учитывая изменение поведения в UIWebView, которое было представлено Apple в iOS 10, вот новый ответ, который объединяет исходный ответ от @Justin-Michael и последующего фаворита от @hexalys.

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

Оказывается, что ответ Justin был действительно лучшим механизмом обнаружения функции, потому что он работает как для iOS 9, так и для iOS 10.

Не сообщая, что произойдет, когда мы перейдем к iOS 11.: -)


Квалификация: этот тест будет работать, если вы используете официальный плагин Cordova WKWebView для создания своего веб-приложения, потому что этот плагин инициализирует метод addScriptMessageHandler, как отметил @hexalys в комментариях к этому сообщению. Этот механизм используется Кордовой для определения нового JS для родного моста, когда присутствует плагин WKWebView.

Найти addScriptMessageHandler в что плагин репо и увидеть самый конец файл ios-wkwebview-exec.js в этом репо для некоторых деталей реализации (или найдите строку window.webkit.messageHandlers в этом файле).

Ответ 4

Похоже, что из-за последнего iOS Chrome, использующего WKWebView в качестве механизма рендеринга, Chrome обнаруживается как WKWebView. ua.indexOf('CriOS')! == -1 поможет отличить Chrome от WKWebView в приложении.

Ответ 5

В iOS вы можете добавить этот код для установления связи между javascript и objective-c:

WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
WKUserContentController *controller = [[WKUserContentController alloc] init];
[controller addScriptMessageHandler:self name:@"javascript_observer"];
configuration.userContentController = controller;

...

webview = [[WKWebView alloc] initWithFrame:... configuration: configuration];

В javascript вы можете проверить соединение следующим образом:

if ( window.webkit != undefined ){
//javascript is running in webview
}