こいつ…(とりあえず)動くぞっ!

あわよくばハッカーになりたい。あと3000年生きたい。ふふふーふ.jpで打製石器を作りまくっています。バールプログラミングを提唱しています。

「技術レベル:花粉」でもわかるChrome拡張機能の作り方

世間には「圧倒的簡単さで〇〇を作る方法」とか、「爆速で××作ってみた」とかそういうtipsが山ほどあるわけですが、正直そういうやつって、もうイオナズン覚えちゃってる人が、とりあえずこうすればイオラ出せるよみたいに書いてるやつじゃないですか。こちとらメラもライター程度のがやっとで、物理で殴り合ってスライムやドラキーとかなりきわどい勝負して、何なら10回以上コンティニューしてるわけですよ。もうね、勘弁してくれと。分らんと。最初の2行をなるほどと思って読み進めていると、早々に「とりあえずメラミの要領でサクッと魔力を集中させます」みたいなこと書いてあるんですよ。おい、ちょっと待てと。さくっとメラミ出せるならこんなに苦労してへんわと。

前置きが長くなりましたが、本ページでは私のような永遠のscript "kitten"に向け、この度習得した「真」圧倒的分かりやすさでchromeのアドオンを作る方法をご紹介したいと思います。 子猫ちゃんがネット上を放浪しまくって継ぎはぎで得た知識を開陳しているので、解説が間違ってたらごめんね(テヘペロ

あとなんかすげーほったらかしにしていたんですが、月間100PVとかいってて、一日3人くらいの人が見てくれてるわけで、とっても嬉しいです。皆様ありがとうございます。

chromeのアドオンといってもいろいろあるわけですが、今回は、右上にアドオンのアイコン出してクリックするとなんか出るやつと、右クリックメニュー(正しくはContext Menuっていうらしいよ)にオリジナルメニュー入れていい感じの機能つけるやつを実現するにはどうすればええねんということをご紹介したいと思います。ちなみに、browser action(いろんなURLで使う)とpage action(特定のURLに対して使う)と2種類あるらしいんですが、今回はbrowser actionの方です。

さて、chromeのアドオンの概略構造みたいなのはググれば詳しい人の記事がたくさん出てくるのでざっくりとしか書きませんが、今回の場合は

  • manifest.json(必須の設定ファイル)
  • background.js(右クリックメニューの処理)
  • main.html(右上のアイコンクリックしたときに出すやつ)
  • haahaaDisplay.js(onclick使うためのやつ)

この4つがあればOKです。これらを駆使して

  • 右上にアドオンのアイコンを出し、それをクリックするとウィンドウが出て、入力欄に文字列を入れてボタンを押すと文字列がウィンドウ内に表示される。
  • どっかのウェブページに表示されている文字列をドラッグで反転選択し、右クリメニューを選択するとalertで文字列が表示される。

という全く使いどころのないアドオンを作成してまいります。

manifest.jsonのポイント

基本的にはググって出てくる通りにやっとけば間違いないのですが、はまりポイントは、backgroundのところだと思います。ググるとバージョンアップ前の?結構古い記事が出てきてここにhtmlファイルが設定されているようなものが散見されます。昔は、「常に不可視なページをバックグラウンドで開いておいて、作業発生したらそいつにやらせとけばええやん?」みたいな発想(background page)だったらしいですが、閉じれもしない常時開かれているページが拡張機能の数だけ存在してたらメモリめっちゃ食うやん!というわけで、現在は、「作業が発生したときのみjsかなんか動かせば良くね?」(event page)というのが推奨されているようです。ここで右クリで動かしたいスクリプトを指定するとともに、event pageでの動作にするためには"persistent": falseが必要らしいので忘れないようにしましょう。また、permissionscontextMenu(右クリメニューのこと)を入れないとアドオンが右クリメニュー使えないっぽいのでここもお気を付けください。めんどくさかったらallにしとけばいい気がします(危険思想)。 また、右上のアドオンアイコン周りはbrowser_actionのところで設定します。クリックすると出てくるウィンドウ用のhtmlはdefault_popupのところに設定しておきます。

//manifest.json
{
    "manifest_version": 2,
    "name": "ハァハァアドオン",
    "description": "あなたのchromeをヤバいやつにするアドオンです。",
    "version": "0.1",
    "background": { 
        "scripts": ["background.js"],
        "persistent": false
    },
    "permissions": ["tabs","contextMenus"],
    "icons": {
        //"48": "icon.png"
      },
    "browser_action": {
        //"default_icon": "icon.png",
        "default_title": "haahaaExtension",
        "default_popup": "main.html"
    }
}

各項目はググればちゃんとした人の解説結構出てくるので割愛します。バージョンアップの件があるので、なるべく新しい記事見た方がいいです。default_iconとiconsの48サイズはディレクトリにアイコンの画像を用意しとかないと 拡張機能読み込んだ時にエラーが出るのでコメントアウトしてます。適当なアイコン入れるときはコメントアウト解除して設定してください。

main.htmlのポイント

要するにただのhtmlです。サイズは一番外側の要素の縦横サイズで決まるので、いい感じにするといいと思います。 でも、ただのhtmlと言いつつ、しれっと、onClick=function()(例えば<input type="button" onClick=function()>)が使えないというトラップが待ち構えています。ここで僕含め読者の85%の村人AはGoogleの我々のデキなさに対する無理解に怒りを隠しきれないと思いますが、その怒りのパワーで乗り越えましょう。 そこで、以下のようなJSをhtmlに持たせてあげてイベントを追加する必要があり、haahaaDisplay.jsが必要になってくるわけです。

//haahaaDisplay.js
'use strict';
document.addEventListener('DOMContentLoaded', function () {
    document.getElementById('kinkyButton').addEventListener('click', function () {
        let displayTarget = document.getElementById('kinkyDisplay');
        const targetName = document.forms.targetNameInputForm.targetName.value;
        const displayText ='chrome→(*´Д`)<'+ targetName + 'タン……ハァハァ……';
        displayTarget.innerText = displayText;

    });
}, false);

簡単に日本語でイメージを示すと以下の通りです。

ページの読み込みが終わったら右記の指示書確認よろ→
kinkyButtonっていう名前の要素がクリックされたらこの処理やっといて→
ページのtargetNameInputFormのtargetNameっていう部分に入力されてる値に
「タン ハァハァ……」をつなげてkinkyDisplayっていう要素に表示されるテキストとして入れる

main.html自体の全体像はこんな感じです。

<!--main.html-->
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link href="./main.css" rel="stylesheet" type="text/css" />
    <script type="text/javascript" src="./haahaaDisplay.js"></script>
</head>
<body>
    <table>
        <tbody>
            <tr>
                <td>
                    <form id="targetNameInputForm" action="">
                        <input type="text" id="targetName" size="20" maxlength="10" minlength="10" autofocus=true>
                        <input type="button" id="kinkyButton" value="ハァハァする">
                    </form>
                </td>
            </tr>
        </tbody>
        <table>
            <div id='kinkyDisplay'></div>
</body>
</html>

background.jsのポイント

ここが一番の肝かと思います。右クリメニューを出すにはchrome.contextMenus.createというchromeAPIを使いますが、ただ単にこいつを使うだけだと、アドオンを呼びだす度にメニューに登録されてしまうらしい?ので、 chrome.runtime.onInstalled.addListenerと組み合わせることでインストール時に一度だけ右クリックメニューへの追加が行われるようにします。 右クリメニューは階層を作れるので、親メニューと同じ感じで子メニューも淡々と登録します。異なる点としては、子メニューは、親メニューのidをparentIdに設定する必要があります。 そして、chrome.contextMenus.onClicked.addListenerで右クリックメニューを選択した後の動作を設定します。 infoというオブジェクトに右クリメニューが選択された時のデータがいろいろ入っているので、今回は、反転選択したテキストをselectionTextで取得しています。 infoに何が入ってるかは、公式のリファレンスをご参照のこと。 そして、選択されたメニューのidによって処理を振り分けます。今回は大した処理じゃないので引数に入れた関数内で処理が完結していますが、複雑な処理の場合は、普通のJS感覚でかっこの外に別で関数作っても引数内の関数で使えます。

//background.js
'use strict';

//親メニュー登録
chrome.runtime.onInstalled.addListener(function () {
    chrome.contextMenus.create({
        id: "fromSelectionToHaahaaExtension",
        title: "ハァハァさせる",
        contexts: ["all"],
        type: "normal",
    }, function () {
        alert("chromeは ハァハァすることを おぼえた");
    });
});

//サブメニュー登録
chrome.runtime.onInstalled.addListener(function () {
    chrome.contextMenus.create({
        id: "soft",
        parentId: "fromSelectionToHaahaaExtension",
        title: "優しく",
        contexts: ["all"],
        type: "normal",
    });
    chrome.contextMenus.create({
        id: "hard",
        parentId: "fromSelectionToHaahaaExtension",
        title: "激しく",
        contexts: ["all"],
        type: "normal",
    });
});

//ここからメニューに割り当てる処理
chrome.contextMenus.onClicked.addListener(function (info,tab) {
    const selectedMenu = info.menuItemId;
    let haahaa;
    const targetName = info.selectionText;

    switch (selectedMenu) { //呼び出されたメニューによりハァハァする回数を変える

        case 'soft':
            haahaa = 'ハァハァ……';
            break;

        case 'hard':
            haahaa = 'ハァハァハァハァハァッハァッハァハァハァハァハァハァ……';
            break;
    }
    alert(targetName +'タン……'+ haahaa);

});

以上で簡単なchrome拡張機能が作れました! 紹介した4つのファイルを同じディレクトリにいれてchromeに読み込ませるとあなたのchromeがハァハァしだすぞ!やってみよう! パッケージングしていない拡張機能chromeに読み込ませる方法は

naokixtechnology.net

が、 chromeのパッケージングは

pineplanter.moo.jp

が分かりやすかったです。Naokixさん?(著者名がわからなくて違ったらすいません)、Uematsu Satoshiさん、ありがとうございます。