Google Chrome Extensions (拡張機能) を作ってみる

Linux版の Google Chrome で拡張機能を作ってみた際のメモ。

Google のサンプルコードとチュートリアル (Google Chrome Extensions – Google Code) や "特集:先取り! Google Chrome Extensions|gihyo.jp … 技術評論社" の記事を参考にして Fastladder の未読記事数を表示する拡張機能を作ってみる。

Manifest file

まず、Manifest file (manifest.json) を作成する。
これは、拡張機能の各種情報を記述した JSON 形式のファイルで、以下のように記述する。

{
    "name" : "Fastladder Notify",
    "version" : "1.0",
    "description" : "Notify unread Fastladder entry.",
    "background_page" : "background.html",
    "permissions" : [
        "tabs",
        "http://rpc.fastladder.com/"
    ],
    "browser_action" : {
        "default_title" : "Fastladder Notify",
        "default_icon" : "icon.png"
    },
    "options_page" : "options.html"
}
name
拡張機能名、必須パラメータ。
version
拡張機能バージョン番号,必須パラメータ。
description
拡張機能の説明文。
background_page
Google Chrome 起動中にバックグラウンドでスクリプトを実行させるためのファイル。
permissions
異るドメインとの通信やタブ・ウィンドウ・ブックマークなどの操作を許可するための指定をする。
ここでは、APIURI と、ツールバーのアイコンをクリックした際に新規タブで Fastladder のサイトを開くための "tabs" を指定している。
browser_action
Google Chrome のツールバーやアドレスバーの右端にアイコンを設置して、いろいろなアクションを行なわせるもの。
ここでは、ツールバーのアイコンの画像ファイル名とツールチップテキストを指定している。
拡張機能 ツールバーアイコン Screenshot
options_page
拡張機能の管理ページの『オプション』ボタンをクリックした際に表示されるページとその動作を記述したファイル。

Background Pages

次に、Background Pages のファイル background.html (manifest.json に記述した任意の名前のファイル) を作成する。
これは、バックグラウンドで動作するので外観の記述は不要。
API からのデータの取得とツールバーアイコンへの未読件数の表示ロジックを記述している。

<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<script type="text/javascript">
const API_URI = 'http://rpc.fastladder.com/notify?user=';
const fastladderURI = 'http://fastladder.com/';
const fastladderRe = /https?\:\/\/fastladder.com\//;
const MAX_COUNT_SIZE = 9999;
const INTERVAL_S = 1000 * 60; // 1 minute
const INTERVAL_E = 1000 * 60 * 60; // 1 hour
const COLOR_S = [050, 150, 050, 230];
const COLOR_E = [200, 050, 050, 230];

var update = function(count) {
    if (count > MAX_COUNT_SIZE) {
        count = MAX_COUNT_SIZE;
    }
    chrome.browserAction.setBadgeText({text : count});
};

var check = function() {
    if (/\W/.test(userName)) return;
    var xhr = new XMLHttpRequest();
    var uri = API_URI + userName;
    xhr.open('GET', uri, true);
    xhr.onload = function(){
        var count = parseInt(xhr.responseText.substring(1), 10);
        if (count >= 0) {
            chrome.browserAction.setBadgeBackgroundColor({color : COLOR_S});
            update(count.toString());
            setTimeout(check, INTERVAL_S);
        } else {
            error();
        }
    };
    xhr.onerror = function(){
        error();
    };
    xhr.send(null);
};

var error = function() {
    chrome.browserAction.setBadgeBackgroundColor({color : COLOR_E});
    update('!');
    setTimeout(check, INTERVAL_E);
};

var goToFastladder = function() {
    chrome.tabs.getAllInWindow(undefined, function(tabs) {
        for (var i = 0, tab; tab = tabs[i]; i++) {
            if (tab.url && fastladderRe.test(tab.url)) {
                chrome.tabs.update(tab.id, {selected: true});
                return;
            }
        }
        chrome.tabs.create({url: fastladderURI});
    });
};

var userName;

chrome.browserAction.setBadgeText({text : '?'});
chrome.browserAction.setBadgeBackgroundColor({color : COLOR_E});
chrome.browserAction.onClicked.addListener(function(tab) {
      goToFastladder();
});

init = function(){
    userName = localStorage["fldUserName"];
    check();
};

</script>
</head>
<body onload="init();">
</body>
</html>

Options Pages

続いて、Options Pages (manifest.json に記述した任意の名前のファイル) の作成を行う。
こちらは、HTML のフォームタグ等を使って設定パラメータの指定と localStorage への保存を行っている。

HTML, CSS, JavaScript を用いた普通の Web ページを作る感じ。

拡張機能 オプションページ Screenshot

<!doctype html>
<head>
<meta charset="utf-8" />
<title>Fastladder Notifier Options</title>
<style type="text/css">
h1 {
    color: #000;
    font: normal normal bold 120% "Verdana", sans-serif;
}
#wrapper {
    display: inline-block;
    border: 1px solid #333;
    border-radius: 10px;
    margin: 10px; padding: 10px;
}
#username {
    width: 100px;
    border: 1px solid #99f;
    background-color: #fff;
}
#username:focus {
    border: 1px solid #fbb;
    background-color: #ffe;
}
label {
    color: #666;
}
label:after {
    content : " : ";
}
</style>
<script type="text/javascript">
var saveOptions = function() {
    var BG = chrome.extension.getBackgroundPage();
    var userName = document.getElementById('username').value;
    localStorage["fldUserName"] = userName;
    BG.init();
    close();
};

var loadOptions = function() {
    var userName = localStorage["fldUserName"];
    if (userName) {
        document.getElementById('username').value = userName;
    }
};

</script>
</head>
<body onload="loadOptions();">

<div id="wrapper">
    <h1>Fastladder Notifier Options</h1>
    <div id="options">
        <label for="username">UserName</label><input type="text" placeholder="UserName" id="username" />
        <input type="button" id="set-username" value="Save" onclick="saveOptions();" />
    </div>
</div>

</body>
</html>

Google Chrome への読み込み

そして、ツールバーアイコン用の PNG 画像 (19×19) を作成して、フォルダ内に配置する。
そのフォルダを『拡張機能』ページの『パッケージ化されていない拡張機能を読み込みます…』 ボタンをクリックして表示されるファイル選択ダイアログから選択して『開く』とインストールされる。
フォルダ内のファイルに変更を加えて『再読み込み』リンクをクリックすると変更が反映されるので、Google Chrome の再起動をせずに開発してゆくことができる。

パッケージ化・インストール

完成したらパッケージ化して保存し、インストールする。

パッケージ化は『拡張機能』ページの『拡張機能のパッケージ化…』ボタンをクリックして表示されたダイアログの『拡張機能のルートディレクトリ』に作成したファイルの保存されているフォルダを指定する。
『秘密鍵ファイル』は空欄のまま『OK』ボタンをクリックするとルートディレクトリと同じレベルのディレクトリに フォルダ名.crxフォルダ名.pem の2つのファイルが生成される。

フォルダ名.crx ファイルを Google Chrome のウィンドウにドラッグ&ドロップするとインストールできる。

まとめ

Web ページを作る知識(HTML, CSS, JavaScript)だけで簡単に拡張機能を作ることができた。
Firefox の拡張機能というよりも JetPack に相当するものかも。

«
»