Chrome拡張に関する覚書


個人用です

manifest.jsonについて

基本構文

manifest.json
{
    "name": "Wikidot日本語化拡張",
    "version": "1.0.0",
    "manifest_version": 2,
    "description": "Wikidotに日本語を覚え直させる拡張機能です。",
    "author": "Yuuki Watanabe / ukwhatn",
    "permissions": ["storage", "*://*.scp-wiki.net/*", "*://*.wikidot.com/*"],
    "web_accessible_resources": ["js/ozone-script.js"],
    "content_scripts": [
        {
            "matches": ["*://*.scp-wiki.net/*", "*://*.wikidot.com/*"],
            "js": ["js/main.js", "js/ozone-loader.js"],
            "run_at": "document_start"
        },
        {
            "matches": ["*://*.wikidot.com/account/*"],
            "js": ["js/account.js"],
            "run_at": "document_start"
        },
        {
            "matches": ["*://*.wikidot.com/account/settings", "*://*.wikidot.com/account/settings#/*"],
            "js": ["js/account-settings.js"],
            "run_at": "document_start"
        }
    ]
}

manifest_version : 2以外ないので固定
permissions : storageでアドオンの設定をstorageに格納・読み出し/URL指定でページ読み込み時に自動実行
web_accessible_resources : 後述
content_scripts : ページ読み込み時に読み込むJSとCSSを指定

content_scriptsについて

matches

必須。ここで指定したURLにアクセスしたときにスクリプトを読み込む。
permissionsでURL指定してないと拡張機能アイコンのクリック時にしか起動しないっぽい。

exclude_matches

matchesにヒットするURLの中で除外したいものを定義

js

読み込むJavaScriptファイルを指定

css

読み込むCSSファイルを指定

run_at

document_start
DOMを読み込む前に起動 : これ+後述の待機ループをかけたほうがよさそう
document_end
DOMを読み込んだあと、その他のリソースを読み込む前に起動 : なんか発火しない時がある
document_idle
DOMもリソースも読み込み終わった後に起動(デフォルト): 罠
window.onloadなどで読み込んだJSを発火させたい場合、document_idleだと発火点を過ぎたあとで読み込んでいる可能性がある。

all_flames

iframeなど、全てのフレームを対象にするならtrue
デフォルトはfalse

待機ループ

DOM待ち
(function () {
    if (document.getElementsByTagName("body")[0]) {
        wikidot_main();
    } else {
        return setTimeout(arguments.callee, 1000);
    }
})();
JavaScript待ち
(function () {
    if (typeof OZONE == "function") {
        wikidot_main()
    } else {
        return setTimeout(arguments.callee, 1000);
    }
})();

document_startだと全てのリソース、つまりDOMや他のJavaScript等に先んじて読み込まれるため、回線速度が遅いと「定義されてへんねんけど」って言われる。
かといってdocument_endだとなぜか発火しない時が結構ある。
なので、発火点として「bodyが定義されたら」or「任意の関数が定義されたら」を指定する。
開発時はconsole.logつかうと見やすくて良さげ

content_scriptsの罠

拡張機能で実行されるスクリプトはページ本体とは別のwindowで実行されるが、documentだけは本体に干渉できる。
つまり、拡張機能側からページ本体のスクリプト(JQueryなども)を参照することは出来ない。
よって、scriptを挿入することで動作させる。

loader.js
(function () {
    if (document.getElementsByTagName("body")[0]) {
        console.log("bodyの読み込みが完了しました。")
        var s, th;
        th = document.getElementsByTagName("body")[0];
        s = document.createElement('script');
        s.setAttribute('type', 'text/javascript');
        s.setAttribute('src', chrome.extension.getURL('/script.js'));
        return th.appendChild(s);
    } else {
        console.log("bodyの読み込みを待っています。")
        return setTimeout(arguments.callee, 1000);
    }
})();
script.js
(function () {
    if (typeof OZONE == "function") {
        スクリプト
    } else {
        console.log("OZONEが読み込まれていません。")
        return setTimeout(arguments.callee, 1000);
    }
})();

これをやるとき、manifest.jsonの"web_accessible_resources"に挿入するscriptを書いておかなければならない。