Google Chrome 拡張でページ内リンク変更イベントを取得する

追記

onhashchange をとれば以下のものは必要ありません。

動機

URL が http://hoge.com/index.html#a から http://hoge.com/index.html#b に変わったことを知りたい。この URL 変更では onload イベントは発生しない。

ポイント

  • background.html で chrome.tabs.onUpdated.addListener してタブの onUpdated イベントを受け取る
  • Content Script から sendRequest でイベントを受け取りたいとリクエス
  • background.html は sendRequest をしたタブの id を取得してそれをキーに callback を登録
  • onTabUpdated で callback を呼び出して Content Script 側に通知

意外と面倒。

コード

background.html
<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
    <script>

      function onTabUpdated(tabId, changeInfo, tab) {
          if (tabCallbacks[tabId] &&
              changeInfo.url &&
              changeInfo.url.match(/^http:\/\/localhost\//)) {
              tabCallbacks[tabId]({param : "hoge"});
          }
      }

      var tabCallbacks = {};

      function onRequest(request, sender, callback) {
        if (request.action == 'notifyTabUpdated') {
            chrome.tabs.getSelected(null,
                                    function(tab) {
                                        tabCallbacks[tab.id] = callback;
                                    });
        }
      };

      function init() {
          chrome.extension.onRequest.addListener(onRequest);
          chrome.tabs.onUpdated.addListener(onTabUpdated);
          chrome.extension.onRequest.addListener(onRequest);
      }

      window.addEventListener('load', init, false);


    </script>
  </body>
</html>
tab.js
function registerCallback() {
    chrome.extension.sendRequest({'action' : 'notifyTabUpdated'}, onTabUpdated);
}

function onTabUpdated(param) {
    alert('hage' + (param ? param.param : 'null'));

    // we have to re-register the callback, after it is called.
    registerCallback();
}

registerCallback();

注意

  • sendRequest を介して送られた callback を background.html から2回呼ぶことは出来ないようだ。
  • manifest.json に permissions で tabs を書くのを忘れない