続・先取り! Google Chrome Extensions

第4回 ベータ版に向けたExtension総復習

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

Extensionsの開発手順

では実際にmanifest.jsonを記述し,それに対応するファイルを用意していきます。今回もSBMカウンタをサンプルとします(そろそろ別のサンプルを出すべきところですが,今回だけお付き合いください⁠⁠。

SBMカウンタのmanifest.json

{
  "name": "SBM Counter",
  "description": "Social Bookmark Counter Extension",
  "version": "4.2.1",
  "permissions": [
    "tabs",
    "http://*/",
    "https://*/"
  ],
  "update_url": "http://ss-o.net/chrome_extension/sbm_counter/updates.xml",
  "options_page": "options_page.html",
  "background_page": "background.html",
  "icons": {
    "128": "sbm_icon_128.png",
    "64": "sbm_icon_64.png",
    "32": "sbm_icon_32.png",
    "16": "sbm_icon.png"
  },
  "browser_action": {
    "default_icon": "sbm_icon.png",
    "default_title": "SBM Counter",
    "popup" : "popup.html"
  }
}

Tabs APIとexecuteScriptをすべてのサイトで使用するので,permissionsはほぼフルアクセスの権限を与えています。

このmanifestに対応したHTML,画像,CSSやJavaScriptファイルを用意していきます。なお,前回はpage_actionを使用しましたが,今回はbrowser_actionを使用しています。また,複数のサービスをカウントするためにExtensionsを複数用意する方法を取りましたが,BrowserActionにはブックマーク数の合計数を表示して,Tooltipに各サービスごとのブックマーク数を,popupにブックマーク数と詳細ページ,ブックマーク追加ページへのリンクを表示することにします。

Background Page

では,最初にBackground PageのHTMLを用意します。

Background PageのHTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript" src="Services.js"></script>
<script type="text/javascript" src="md5.js"></script>
<script type="text/javascript" src="background.js"></script>
</head>
<body>
</body>
</html>

DOCTYPEやhtml要素などを省略せずに書きましたが,JavaScriptを動かすだけなので,script要素だけに省略しても問題ありません。

scriptはサービスの定義を記述したServices.js,delicious用のMD5ライブラリ,Background Pageの本体となるbackground.jsの3つに分けました。

このbackground.jsはChromeが起動した際に一度だけ初期化されます。そこで,最初に起動時の初期化処理を記述します。

Background Pageでの設定の初期化

var SBMConf = {
  disable_sites:[
    "^http://localhost(:\\d+)?/",
    "^https://",
    "^http://b\\.hatena\\.ne\\.jp/entry"
  ],
  isInlineCount:true,
  usageServiceConfig:[
    {id:'hatena', enable:true},
    {id:'delicious', enable:true}
  ]
}
if (!localStorage.disable_sites) {
  localStorage.disable_sites = JSON.stringify(SBMConf.disable_sites);
} else {
  SBMConf.disable_sites = JSON.parse(localStorage.disable_sites);
}
if (!localStorage.isInlineCount) {
  localStorage.isInlineCount = Boolean(SBMConf.isInlineCount);
} else {
  SBMConf.isInlineCount = Boolean(localStorage.isInlineCount);
}
if (!localStorage.usageServiceConfig) {
  localStorage.usageServiceConfig = JSON.stringify(SBMConf.usageServiceConfig);
} else {
  SBMConf.usageServiceConfig = JSON.parse(localStorage.usageServiceConfig);
}
SBMConf.usageServiceConfig.forEach(function(opt){
  Services[opt.id].enable =  opt.enable;
});

最初のSBMConfはインストール直後用のデフォルトの設定です。localStorageに値が存在すればその値をJSON.parseで取り出してSBMConfに反映し,存在しなければ逆にJSON.stringifyでlocalStorageに値をセットしています。なお,isInlineCountは真偽値(プリミティブな値)なので,JSONを経由させていません。JSONを使ってもエラーにはならないようなのですが,本来JSONはプリミティブ値だけを取ることはできないので,念のため直接プリミティブ値として扱うようにしました。

最後のusageServiceConfigの処理は,サービスのON/OFFをServicesオブジェクトに反映させています。

SBMクラスの実装

function SBM(tab){
  if (tab) {
    this.init(tab);
  }
}
SBM.prototype = {
  init:function _sbm_init(tab){
    var tabid = tab.id, url = tab.url;
    this.count = 0;
    this.title = new Array(Services.length);
    this.tabid = tabid;
    this.title = tab.title;
    this.url = url.replace('#','%23');
    this.encoded_url = encodeURIComponent(url);
    Services.forEach(function(service, index){
      this.request(service, index);
    },this);
  },
  request:function _sbm_request(service, index){
    if (!service.enable) return;
    var self = this, xhr = new XMLHttpRequest();
    var api_url = fill(service.api_get, this);
    xhr.open('GET', api_url, true);
    xhr.onload = function(){
      var count = service.responceFilter(xhr.responseText);
      self.update(count,service,index);
    };
    xhr.send();
  },
  update:function _sbm_update(count, service, i){
    this.count += parseInt(count, 10) || 0;
    this.title[i] = count + ' count(' + service.name + ')';
    chrome.browserAction.setBadgeText({
      tabId:this.tabid,
      text:this.count
    });
    chrome.browserAction.setTitle({
      tabId:this.tabid,
      title:this.title.join('\n')
    });
  }
};

著者プロフィール

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

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

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