JavaScriptでWebViewをハックする

 JavaScriptでWebViewをハックする

Bf8dccb5b8479c3a589004d3154b6f5f?s=128

Wataru Mizukami

April 12, 2019
Tweet

Transcript

  1. JavaScriptでWebViewをハックする Wataru Mizukami(水上 亘) Shibuya.apk #33

  2. 自己紹介 - Wataru Mizukami/水上 亘 -         / @tarumzu (たる)

    - Organization/ sikmi, inc. TOEICテストTEPPAN英単語、好評発売中! (付録のAndroidアプリがおすすめです!)
  3. WebViewを使った開発するときに JavaScriptに苦しめられたこと、 ありませんか?

  4. 初級編 SPAでページの変更を検知する① 通常、WebViewでページの変更を検出する場合は下記を使用す るがReactやVueで作成されたSPAではsubmitが走らないため UrlLoadingを検知できない。 WebViewClient#shouldOverrideUrlLoading

  5. 初級編 SPAでページの変更を検知する② webview.getSettings().setJavaScriptEnabled(true) webview.setWebViewClient(object : WebViewClient() { override fun doUpdateVisitedHistory(view: WebView,

    url: String, isReload: Boolean) { Log.d("MainActivity", "doUpdateVisitedHistory url = $url") } })
  6. 初級編 SPAでページの変更を検知する② webview.getSettings().setJavaScriptEnabled(true) webview.setWebViewClient(object : WebViewClient() { override fun doUpdateVisitedHistory(view: WebView,

    url: String, isReload: Boolean) { Log.d("MainActivity", "doUpdateVisitedHistory url = $url") } }) doUpdateVisitedHistoryは訪問済みリンクのデータ ベースを更新した際に呼ばれる
  7. 今回の例は専用のメソッドが用意されれ てたけど、なかった場合どうする? もっと自由にイベントをフックしたくない?

  8. 上級編 自在にイベントをフックする① webview.setWebViewClient(object : WebViewClient() { override fun onPageFinished(view: WebView, url:

    String) { webview.loadUrl("javascript:window.addEventListener('popState', function (event) { injectedObj.testFunction(‘test') }, false)") } })
  9. 上級編 自在にイベントをフックする① webview.setWebViewClient(object : WebViewClient() { override fun onPageFinished(view: WebView, url:

    String) { webview.loadUrl("javascript:window.addEventListener('popState', function (event) { injectedObj.testFunction(‘test') }, false)") } }) popStateとは JavaScriptのHTML5 HistoryAPIで、 history.back()、history.forward()が実行された 際に呼び出されるイベント
  10. 上級編 自在にイベントをフックする① webview.setWebViewClient(object : WebViewClient() { override fun onPageFinished(view: WebView, url:

    String) { webview.loadUrl("javascript:window.addEventListener('popState', function (event) { injectedObj.testFunction(‘test') }, false)") } }) 例えば、JavaScriptのaddEventListenerを使 えばpopStateイベントのリスナーにfunctionを 登録させることが出来る。という事は…
  11. 上級編 自在にイベントをフックする② class JSObject(private val webview: WebView) { @JavascriptInterface fun testFunction(str:

    String): String { Log.d("xxx", "hook $str") return "false" } } JSObjectというクラスを用意して…
  12. 上級編 自在にイベントをフックする③ webview.addJavascriptInterface(JSObject(webview), "injectedObj") webview.setWebViewClient(object : WebViewClient() { override fun onPageFinished(view:

    WebView, url: String) { webview.loadUrl("javascript:window.addEventListener('popState', function (event) { injectedObj.testFunction(‘test') }, false)") } }) JSObjectクラスをaddJavascriptInterfaceで登録して あげることでpopStateイベントが走った際に自前のメ ソッドが呼ばれるようになる!
  13. つまり、WebView側だけの対応で、 Webページを自由自在に操作できる!

  14. まとめ - SPAのページ変更検知はdoUpdateVisitedHistoryを使う。 - メソッドが用意されてなくてもJavaScriptを知ることで何でも出 来る。

  15. 宣伝 4/14開催の技術書典6でSwift/Kotlin愛好会合同執筆本として、 日本で唯一!のRealm Cloud入門書書くのでぜひ買いに来てくだ さい!他にも内容盛りだくさんです。 場所は「け18」よろしくおねがいします! https://techbookfest.org/event/tbf06/circle/71750003

  16. ご清聴、ありがとうございました!