Google ChromeのExtension作成メモ
基本的に自分がつくったextensionに必要な箇所のメモ
Manifest V2について
Content Security Policy (CSP) などをセキュリティの向上のため新しい拡張機能の実装ルールとしてManifest V2が定義されている。
Tutorial: Migrate to Manifest V2
この方式は拡張機能内のmanifestファイルに記載するバージョン ( "manifest_version": 2
) を記述すると有効になる。この方式にそっていない拡張機能は新しくインストールできなくなり、すでにインストール済みの拡張機能もChromeのバージョンアップによって実行できなくなる見込み。従って新規に実装する場合はManifest V2にそって実装しないといけないし、既存の拡張機能もバージョンアップしないといけない。
Content Security Policy (CSP)
Content Security Policy (CSP) 自体はChromeの仕様でもChrome Extensionの仕様でもなくウェブサイトの仕様なのでChromeにウェブで検索すると情報が見つかる。 細かいルールはるが、大まかな対応としてはhtml内にcss,jsをインラインで記述せずに別のファイルにすること、外部ファイルのjs,cssを読み込む場合はそのurlを使うことを予め宣言する(manifestファイルに記載する)といったことになる。
Overview
http://developer.chrome.com/extensions/docs.html
- HTML, CSS, JavaScript, 画像をzipでバンドルするという非常にWidgetに近いアーキテクチャーで
- XMLHttpRequestやHTML5 local storageなどを使って機能を作成でき
- さらにChromeからは browser actionsやpage actions、bookmarks、tabsなどの機能が提供される
ブラウザアクション
- ブラウザに常駐するextensionは基本的にbackgroundページ(html)というのを持つ
- さらにpopupを表示するなど別のページ(html)を持つことができ、別ページからbackgoundページの関数を実行したりできる
- popupで表示するページはmanifestにてブラウザアクション(browser_action > default_popup)を定義することで呼び出せる
{
"name": "My extension",
...
"browser_action": {
"default_icon": "images/icon19.png", // required
"default_title": "Google Mail", // optional; shown in tooltip
"default_popup": "popup.html" // optional
},
...
}
つまりbackgounrd.htmlでアイコンで状態だけを表示しておいて、ユーザの呼び出し(クリック)によって詳細な情報だけをpopupで表示するということがextensionのひとつのやり方となる。
ページでの連携
popup, option -> background
- extensionにとってbackgroundは親玉でありで以下で取れる
var background = chrome.extension.getBackgroundPage();
- これでとれるのはbackground.htmlのwindowオブジェクトなので例えばbackground.htmlにあるグローバルな関数にアクセスするには以下のようにできる
// background.js
function foo() { alert("bar"); }
// popup.js
var background = chrome.extension.getBackgroundPage();
background.foo();
- Google Calendar for Todayでは機能を別のオブジェクトにまとめており面倒くさいので以下のようにしてアクセスさせている
// background.js
(function($){
$(document).ready(function() {
var w = Blz.Widget,
gcal = Blz.Google.Calendar,
app = MyGoogleCal.Application;
// ....
window.Blz = Blz;
window.MyGoogleCal = app;
});
})(jQuery);
// popup.js
var background = chrome.extension.getBackgroundPage(),
Blz = background.Blz,
w = Blz.Widget,
app = background.MyGoogleCal
background > others
- 他のページはbackgoundのように
getPopupPage()
とかは用意されていないのでsendRequest()
を使う、sendRequest()
は拡張機能内でメッセージのやり取りを行うメソッド。Today’s Schedule (https://chrome.google.com/webstore/detail/todays-schedule-in-google/mkaaneppndljkmpgdcglnpfagfhjhipc) ではbackgoundにて予定を取得した時にpopupへ更新を指示するために以下のようにしている
// background.js
function update() {
chrome.extension.sendRequest({update:true});
}
// popup.js
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.update) update();
});
function update() {
...
}
sendRequest()
だと特定の宛先にメッセージを送れないのでメッセージを受け取った人が自分宛てのものかを判別しないといけない。ここではupdateというプロパティの有無でそれを判断している。
ページアクション
- Chromeが開いているページに対して機能を提供する場合は、background.htmlを持たないでページアクションをつかって機能を提供できる
- なおmanifestにはブラウザアクションとページアクションの両方を指定することはできない
Content Scripts
- manifestに
content_scripts
を設定することで既存のHTMLにスクリプトをつっこんで操作することができる
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://www.google.com/*"],
"css": ["mystyles.css"],
"js": ["jquery.js", "myscript.js"]
}
],
...
}
- matchesにどのURLのページにつっこむか、css,jsにextensionのどのファイルを突っ込むかを指定する
- さらにrun_atにはいつスクリプトを実行するかを指定できる、指定できる値には以下のようなものがある
- document_start: DOMが作成される前
- document_end: DOMが作成されたあと
- document_idle(デフォルト): window.loadの後
manifest
XMLHttpRequest
XMLHttpRequest
で別ドメインにアクセスする場合はそのURLを予めmanifest.jsonのpermission
へ書いておく必要がある
{
"name": "My extension",
...
"permissions": [
"http://www.google.com/"
],
...
}
設定について
- Extensionは設定ページを持つことができてmanifest.jsonに
options_page
というのを指定してhtmlをつくればいい
{
...
"options_page": "options.html",
...
}
- デザインについてはhtmlなので単純にinput要素などつくればよい
- データの読み書きについてはHTML5のlocalStorageで行うとよい
- localStorage(Storage interface)は
getItem
やsetItem
もあるが属性でのアクセスもできるので以下のようにも書ける
localStorage["favorite_color"] = color;
var favorite = localStorage["favorite_color"];
- window.loadや保存ボタンのclickイベントをハンドリングするなどしてlocalStoragに読み書きするのがよいだろう
国際化について
_locales/localeCode/messages.json
というファイルを作成すれば良い- 開発中のunpackageなextensionの場合、messages.jsonがおかしいと容赦なくChromeから削除されてしまう。再度起動するためにいちいちディレクトリを選択しないといけないのであらけじめjsonの検証ツールでチェックしておくのがよいと思われる
- 日英なら
_locales/en/messages.json
,_locales/ja/messages.json
を準備する - 文言はkey-valueの形で設定するらしいが文言自体は
value["message"]
に設定する - パラメータを埋め込みたい場合は、パラメータに名前をつけて文言の中に$で囲い埋め込む、で
value["placeholders"][key]["content"]
へ変数の何番目に指定してもらうかを$1
とかで入れる
"hello": {
"message": "Hello, $USER$",
"description": "Greet the user",
"placeholders": {
"user": {
"content": "$1",
"example": "Cira"
}
}
},
- message.jsonで指定した文言をつかう場合、manifestなどでは
__MSG_messagename__
で指定する、javascriptからはchrome.i18n.getMessage
を使う
chrome.i18n.getMessage("messagename")
- パラメータを渡す場合は第二引数に配列で渡す
var message = chrome.i18n.getMessage("click_here", ["string1", "string2"]);
開発方法
- 適当なフォルダにファイル一式を置く
- Chromeの拡張機能を選択し、 デベロッパーモード を有効にする
- パッケージ化されていない拡張機能を読み込みます… からフォルダを選択
- 実行中は アクティブな閲覧数を確認: からDeveloper Toolsを起動する
- Consoleよりログが確認できる
- Consoleにログを出すにはjavascriptで
console.log()
を使う - Storageから保存したデータを参照できる
トラブルメモ
messages.jsonがおかしいとextensionが読み込めない
- messages.jsonというファイルがちゃんとないと読み込めない
- default_localeをmaniest.jsonに指定していないと読み込めない。
- http://www.jsonlint.com/ でjsonpのチェックをするのが吉
ポップアップでaタグのリンクが開けない
どうやらtarget=_blankがいるらしい。
公開されているextensionのソースを読む技
インストールするとローカルのユーザデータに展開されているのでそれをテキストエディタで読むだけでいい
- Windows
C:\Users\makoto_kw\AppData\Local\Google\Chrome\User Data\Default\Extensions
- Mac OS X
/Users/makoto_kw/Library/Application Support/Google/Chrome/Default/Extensions