Runner in the High

技術のことをかくこころみ

loadstop イベントより細かい request.onCompleted を使う

 Chrome API の WebView にはページのロードが終了した時に発生する loadstop というイベントが存在する。これを用いたサンプルが公式のドキュメントにあるのだが、ここにひとつ注意したい点がある。

onload = function() {
var webview = document.getElementById("foo");
var indicator = document.querySelector(".indicator");

var loadstart = function() {
indicator.innerText = "loading...";
}
var loadstop = function() {
indicator.innerText = "";
}
webview.addEventListener("loadstart", loadstart);
webview.addEventListener("loadstop", loadstop);
}
 Googleの検索結果のページなどで起こりがちなことだが、実際にページのロードではなくJavaScriptによる動的なデータの書き換え?のような動作を行うページではこの loadstop の発生するタイミングがあまり芳しいものにはならない(webview 内で表示されているページのタイトルを取得したいと思った際に、Google検索では loadstop のタイミングでタイトルを取得してもうまくいかないなど)
 この公式のサンプルでは単にページがローディング中かどうかだけを判断するために loadstart と loadstop を使っているが、実際にはもっと細かい感覚でスクリプトなどの実行が行われているはずであり、より詳細なステータスを知る必要に迫られた際にはこれらのイベントでは不十分である。


→こうした問題を解決するために chrome.webRequest を使おうではないか。

{
...
"permissions": [
"https://*/",
"http://*/",
"webview",
"webRequest"
]
...
}

manifest.json の permission はこんな感じで書く。
また、前に書いた webview 内のページタイトル取得のコードと組み合わせるとこんな感じに。

var view = document.getElementById("web-view-test");
view.request.onCompleted.addListener(
function(details) {
view.executeScript({
code: "document.title"
}, function(r) {
console.log("Title: " + r[0]);
});
}, {
urls: [""]
}
);
 最初に触れた loadstop ではなく webRequest.onCompleted イベントのタイミングでタイトルを取得することで、Google検索のようにタイトルの取得が難しいページでも正確にタイトルを取得することができるようになる。これは、そもそも chrome.webRequest が低レイヤーなネットワーク処理の実装を提供するAPIであり、loadstop と比べるとかなり細かい感覚でイベントが発生するからである。(ちなみに、コード中で view.request.onCompleted という書き方をしているのは webview のプロパティである WebRequestEventInterface を直接呼んでいるため)
 ドキュメントそのものを全て詳しくは読んでいないので、全部は分からないけれど、この他にもリダイレクションやヘッダーの受信などで発生するイベントなどできることは盛り沢山なので、これは要チェックだと思う :D