’e’の重要性

この記事はSeeed UG Advent Calendar 2018の22日目の記事です。 明らかにネタですが、いろいろとすみません。

Seeed社さんの商品を使ったブログのエントリーを書いていると、気をつけていないとついtypoしてしまい「e」が足りないことが結構あります。

そのまま誤記したエントリーをアップすると「Seeed警察*1」というパトロールが見回りを行っていて「e」が足りないという指摘を受けて、自分のTypoを実感してしまいます。

過去にはこんなエントリーを書いていましたが、これらの何件かはポリスの御用になっていました。

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

そこで今回のエントリーではAdvent Calendar 2018の後半の箸休めとして、エントリー内にSeeedをSeedとするような誤記があるか調べるChrome拡張を作ってみることにしました。 これで安心してSeeed製品関連のエントリーを書くことができるでしょう。

あーえっとネタがちょっとなかったのですみません。

とりあえず

Chromeの拡張なのでバーにアイコンを表示してそれをクリックし、ページ内のコンテンツにseedがあるかないかを判定する機能を作ってみることにします。名前はSeeedポリス拡張機能としました。

Chrome拡張の開発に関しては以下のリンクのチュートリアルを参考にすれば比較的かんたんに実装することができます。

f:id:ueponx:20181209175437p:plain

Chrome拡張はHTMLとCSSJavascriptで作成し一つのフォルダ(ディレクトリ)の中に格納して管理します。

アイコンの作成

とはいっても、アイコン表示を行うのでアイコンも必要になります。Seeedさんということで以下のサイトで種と芽の形のアイコンを作ってみました。

icooon-mono.com

大きさはアイコンサイズではありますが48pixelあたりにしています。

f:id:ueponx:20181221164903p:plain

Manifestファイルを作成する

Chrome拡張にはManifestファイルが必要になります。Manifestでは、拡張機能に関する情報をjsonファイルで記述していきます。 内容としては拡張の名前やバックグラウンドで動作するJavascriptファイル(background.js)、拡張が動作可能な名前空間、アイコンクリック時に動作するJavascriptファイル(content.js)などの名前が記載されています。

今回のManifestファイルは以下のようにしました。

manifest.json

{
    "manifest_version": 2,
    "name": "Seeedポリス拡張機能",
    "description": "表示しているタブ内にSeedという単語が含まれているかチェックする拡張機能",
    "version": "1.0",
    "permissions": [
        "tabs",
        "notifications"
    ],
    "background": {
        "scripts": [
            "background.js"
        ]
    },
    "content_scripts": [
        {
            "matches": [
                "<all_urls>"
            ],
            "js": [
                "content.js"
            ]
        }
    ],
    "icons": {
        "48": "Extension48.png"
    },
    "browser_action": {
        "default_icon": "Extension48.png",
        "default_title": "Seeedポリス拡張機能"
    }
}

Content Scriptの記述

Chromeの拡張バーに表示されたアイコンをクリックすると動作する処理になります。

Manifestファイルのcontent_scriptsで指定したJavascriptファイル(今回はcontent.js)がこれに当たります。

このファイルは実行環境の制限が特殊でisolated worldと呼ばれています。制限事項は以下のようになっているようです。

という制限があります。今回はブラウザで開いているページのコンテンツを対象とするのでDOMを使用して、コンテンツのbodyタグを取得しました。ただこれだけでは、完了できなかったのでChromeの拡張のランタイムにbodyタグの内容をメッセージとして送信し、送信した内容をバックグラウンド側の処理で対応してもらうことにしました。

content.js

chrome.runtime.sendMessage({
    value: document.getElementsByTagName('body')[0].outerText
});

短いですがこんな感じになりました。

Background Pageの記述

先程のContent Scriptで機能制限がかかるのでその際に対応する手段としてBackground Pageがあります。Chrome拡張はバックグラウンドで動くページを持っていて、そちら側で処理を行うことができます。

今回はManifestファイルの"background"に指定したbackground.jsを編集します。 先程のcontent.jsで表示しているページのBodyタグの内容をMessageとして送信したので、 こちらのファイルでそのメッセージを受信し、seedという文字列が入っていたらChromeの通知(トースト?)を表示することにします。

  • 通知を受け取る場合には → chrome.runtime.onMessage.addListener()
  • アイコンのクリックを検知するには → chrome.browserAction.onClicked.addListener()

というイベントのリスナにfunctionを記述します。

background.js

let textContents = '';

chrome.runtime.onMessage.addListener(
    function (request, sender, sendResponse) {
        textContents = request.value;
        if (textContents.toLowerCase().search(/seed/) !== -1) {
            textContents = "含む";
        } else {
            textContents = "含まない";
        }
    }
);

chrome.browserAction.onClicked.addListener(
    function (request, sender, sendResponse) {
        let options = {
            type: "basic",
            title: "Seeed ポリス出動します!",
            message: "",
            iconUrl: "Extension48.png"
        };
        console.log("debug", options);
        if (textContents.indexOf("含む") !== -1) {
            options.message = "ページ内に”Seed”が含まれています、\n念の為確認してください!";
        } else {
            options.message = "ページ内にSeedは含まれていません、\nご安心ください!";
        }
        chrome.notifications.create(options);
        console.log("debug", options);
    }
);

chrome.runtime.onMessage.addListener()の処理では受け取ったメッセージのテキストの中にseedが 含まれるかチェックしています。

chrome.browserAction.onClicked.addListener()の処理ではseedが含まれていたら通知(chrome.notifications.create())を発生する処理を行っています。

ディレクトリの中がこんなふうになっていればいいかなと思います。

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2018/12/09     14:32           1076 background.js
-a----       2018/12/09     13:16             96 content.js
-a----       2018/12/09     12:08           2226 Extension48.png
-a----       2018/12/09     14:20            770 manifest.json

ローカル環境で配置

では、Chromeに拡張を配置します。Chromeで以下のURLを開きます

chrome://extensions/

すると、このような画面になります。

f:id:ueponx:20181209173718j:plain

(メニューから【その他ツール】→【拡張機能】でも同じ画面になります。)

画面の左上方にある【デベロッパーモード】を有効にするとメニューが追加されます。

デベロッパーモードの無効】 f:id:ueponx:20181222091503p:plain

デベロッパーモードの有効】 f:id:ueponx:20181222091731p:plain

この中から【パッケージ化されていない拡張機能を読み込む】をクリックします。 クリックするとディレクトリの選択のダイアログが開きます。

f:id:ueponx:20181209173805j:plain

ここで、先程保存しておいた拡張機能のフォルダを選択します。 うまく読み込むことができれば行けばこのように作成した拡張機能が表示されます。

f:id:ueponx:20181209174349p:plain

拡張機能のバーにアイコンの表示されているのも確認できます。

f:id:ueponx:20181209173858j:plain

アイコンをクリックすれば、Chromeの通知機能でseedが含まれているか否かを教えてくれます。

f:id:ueponx:20181222101234p:plain

f:id:ueponx:20181222102240p:plain

終わりに

いろいろネタがなくてすみません… eが大切なGReeeeNにも使えそうです。

*1:なぜか組織されているらしい