続・先取り! Google Chrome Extensions

第5回 Chrome ExtensionのAPI#2

この記事を読むのに必要な時間:およそ 5.5 分

リスト作成関数

function list_creater(datas, parent, callback){
  datas.forEach(function(data){
    if (data.url && data.title &&
        data.url.indexOf('javascript:') !== 0) {
      var li = tmpl.cloneNode(true);
      var a = li.firstChild;
      a.href = data.url;
      a.textContent = data.title;
      var icon = document.createElement('img');
      icon.src = data.favIconUrl || FAVICON + a.host;
      a.insertBefore(icon, a.firstChild);
      parent.appendChild(li);
      if (callback) {
        callback(data, a);
      }
    }
  });
}

この関数を使って,ブックマークからリストを作成します。

ブックマークの走査とリストの作成

chrome.bookmarks.getTree(function(roots){
  var bookmarks = [];
  roots.forEach(parser);
  function parser(node){
    if (node.children) {
      node.children.forEach(parser);
    } else if(node.url) {
      bookmarks.push(node);
    }
  }
  list_creater(bookmarks, bookmark_list);
});

続いて,Tabs APIで開いているタブを取得し,それもリストにしてみます。

ブックマークの走査とリストの作成

function TabUpdate(){
  chrome.tabs.getAllInWindow(null,function(tabs){
    while (tab_list.firstChild) {
      tab_list.removeChild(tab_list.firstChild);
    }
    list_creater(tabs, tab_list, function(tab, link){
      link.addEventListener('click',function(evt){
        evt.preventDefault();
        evt.stopPropagation();
        chrome.tabs.update(tab.id,{selected:true});
      }, false);
    });
  });
}
TabUpdate();

タブの場合,クリックした際はそのタブに移動したいので,デフォルトのアクションをキャンセルしてchrome.tabs.updateでタブ移動するようにしました。list_createrでcallbackをするようにしていた点がポイントです。また,タブを閉じたり開いたりした際の変化を反映する必要があるので,TabUpdateという関数にして何度も呼び出せるようにしています。

タブの監視

chrome.tabs.onUpdated.addListener(function(tabid, info){
  if (info.status === 'complete') {
    TabUpdate();
  }
});
chrome.tabs.onRemoved.addListener(function(tabid){
  TabUpdate();
});
chrome.tabs.onDetached.addListener(function(tabid){
  TabUpdate();
});
chrome.tabs.onAttached.addListener(function(tabid){
  TabUpdate();
});
chrome.tabs.onMoved.addListener(function(tabid){
  TabUpdate();
});

タブのイベントAPIをフルに使用してタブの変更を監視し,都度TabUpdateを呼び出しています。あまり効率的な方法ではありませんが,ブラッシュアップは今後の課題とします。

最後に,chrome://extensions/ などの特殊なページは通常のaタグによるリンクでは無効なリンクとして処理されてします。そこで,chrome.tabs.updateで処理する必要があります。この時,リンクひとつひとつに処理を入れる方法とページ全体のクリックを監視してhttpで始まらないリンクがクリックされたときに処理をする方法があります。今回は後者を選択しました。

クリックの監視

const LEFT_CLICK = 0;
const CENTER_CLICK = 1;
document.addEventListener('click',function(evt){
  var target = evt.target;
  if (target instanceof HTMLAnchorElement &&
      target.href &&
      target.href.indexOf('http') !== 0) {
    evt.preventDefault();
    chrome.tabs.getSelected(null,function(tab){
      switch (evt.button) {
        case LEFT_CLICK :
          chrome.tabs.update(tab.id,{url:target.href});
          break;
        case CENTER_CLICK:
          chrome.tabs.create({
            url:target.href,
            selected:false
          });
          break;
      }
    });
  }
},false);

左クリックの場合,現在のタブを更新,センタークリックの場合は新規タブにバックグラウンドで開くようにしています。

今回作成したExtensionはこちらからインストールできます。

まとめ

今回はBookmark APIやOverride Pagesの使い方を解説しました。

次回は今回作成したExtensionをブラッシュアップしながら拡張の開発ノウハウなどを紹介したいと思います。

著者プロフィール

太田昌吾(おおたしょうご,ハンドルネーム:os0x)

1983年生まれ。JavaScriptをメインに,HTML/CSSにFlashなどのクライアントサイドを得意とするウェブエンジニア。2009年12月より、Google Chrome ExtensionsのAPI Expertとして活動を開始。

URLhttp://d.hatena.ne.jp/os0x/