2019年11月27日 星期三

[Go] 透過 Golang 操作系統內建 WebView @ macOS, WKWebView

最近在幫同事想想,到底有沒有什麼更方便的環境去協助同事分析網頁的組成。再加上自己想順便了解一下 golang 是如何跨平台的,就隨意找了這套:github.com/zserge/webview ,看了看,學到不少東西。

心得一:所謂的跨平台,是別人幫你做完所有苦力

在 webview.h 裡頭就定義清楚在 Windows / Linux / macOS 上所使用的 WebView 元件為何,超佛心的幫你串好常見的用法

心得二:macOS 的 WKWebView 就跟 iOS 內的沒啥兩樣

簡稱想要做到更細的東西,都得靠 hack ,黑來黑去好累啊。像是想要追蹤一個網頁形成過程到底用了哪些 resource ,於似乎想要追蹤所有 request ,接著又要想想該如何向 UIWebView 那麼方便查看,接著又要想想是不是要用 WKURLSchemeHandler ,又該怎樣把系統內定的 http/https 黑回來 NSURLProtocol 處理等等,還是要搞個 proxy mode 追蹤?

想著想著...啊不就換套 CEF 就好 XD

於是乎,我就放棄 zserge/webview 在 macOS 上操弄 WKWebView !不過也趁這個機會我練了一下怎樣從 C call ObjectiveC 或者說從 Go 怎樣操作 ObjectiveC,也是總緣份吧

這次操弄 zserge/webview 大概玩了:

- 欣賞 zserge/webview 大大怎樣提供跨平台呼叫瀏覽網頁的元件

- 從 C 操作 WKWebView 物件,接著再呼叫它的 methods 換掉 User-Agent 資訊

WEBVIEW_API void webview_set_user_agent(struct webview *w, const char *user_agent) {
  // https://developer.apple.com/documentation/webkit/wkwebview/1414950-customuseragent?language=objc
  objc_msgSend(w->priv.webview, sel_registerName("setCustomUserAgent:"), get_nsstring(user_agent));
}


- 從 C 操作 WKWebView 物件,接著再呼叫它的 methods 添加監聽 didStartProvisionalNavigation 和 didFinishNavigation

static void wk_webview_didStartProvisionalNavigation(id self, SEL cmd, id webView, id navigation) {
  // https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455621-webview?language=objc
  webview_print_log("at wk_webview_didStartProvisionalNavigation");
  //id absoluteString = objc_msgSend(objc_msgSend(webView, sel_registerName("URL")), sel_registerName("absoluteString"));
  webview_print_log( get_webview_current_url(webView) );
}

static void wk_webview_didFinishNavigation(id self, SEL cmd, id webView, id navigation) {
  // https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455629-webview?language=objc
  webview_print_log("at wk_webview_didFinishNavigation");
}

// ...

  Class __WKNavigationDelegate = objc_allocateClassPair(
      objc_getClass("NSObject"), "__WKNavigationDelegate", 0);
  class_addProtocol(__WKNavigationDelegate,
                    objc_getProtocol("WKNavigationDelegate"));

// ...

  class_addMethod(
      __WKNavigationDelegate,
      sel_registerName(
          "webView:didStartProvisionalNavigation:"),
      (IMP)wk_webview_didStartProvisionalNavigation, "v@:@@");
  class_addMethod(
      __WKNavigationDelegate,
      sel_registerName(
          "webView:didFinishNavigation:"),
      (IMP)wk_webview_didFinishNavigation, "v@:@@");


收工!

沒有留言:

張貼留言