とりゅふの森

GCPデータエンジニアとして生きる

Chrome拡張機能開発に入門する①ポップアップアプリケーションを作成しよう

f:id:true-fly:20220110002728p:plain

こんにちは、最近暇なときにツール作成にはまってます、とりゅふです。
PCとにらめっこしてるとき、一番開くアプリケーションってなんでしょう?
VSCode?エクスプローラー?いえ、ブラウザ、Google Chromeです!
つまり、Google Chromeで動くツールこそ至高、Chrome拡張機能こそが至高なのです!

ということで、本日のテーマはこちら!

HTML + JavaScriptで、Chrome拡張機能開発に入門してみよう!

ブラウザでGoogle Chromeをメインに利用している方であれば、誰もが一度は使ったことがあるであろう、Chrome拡張機能、実は自作して自分で利用することだってできるのです。
今回は拡張機能開発入門ということで、簡単なポップアップアプリケーションを作成したいと思います。

今回作るもの

今回作る拡張機能は以下のようなポップアップアプリケーションです。

f:id:true-fly:20220107000512g:plain:w480

拡張機能のアイコンをクリックすると、ポップアップで画面が開き、必要な情報を入力すると、Atlassian Trelloにカードを作成する、といった簡単な機能です。

私自身、メモだったりブログや学習のやることリストをこのTrelloで管理しているので、ブラウザを開いていて、なにか思いついたときにすぐTrelloのカードにメモできるようにしたいと思い作りました。
Trelloについて、Trello APIを用いた開発については、過去にも紹介しているのでご覧ください。

www.true-fly.com

www.true-fly.com

Chrome拡張機能開発のキホン

Chrome拡張機能は、ざっくりいうと、manifest.jsonファイルと、画面を構成するHTML、CSSファイル、処理を記述するJavaScriptファイルなどから構成されます。

今回のディレクトリ構成は以下の通りです。

.
├── css
│   ├── bootstrap.min.css
│   └── style.css
├── js
│   ├── app.js
│   ├── bootstrap.bundle.min.js
│   ├── jquery-3.6.0.min.js
│   └── vue.js
├── manifest.json
└── popup.html

これらをローカルPCに作成し、それをブラウザで読み込むことで拡張機能を利用していこうと思います。
※今回はchromeウェブストアへの公開までは行いません

manifest.jsonを作成する

manifest.jsonファイルは拡張機能の設定を記述したJSONファイルです。今回はポップアップでHTMLを標準して処理はすべてJavaScriptで処理します。manifest.jsonファイルはブログ紹介用のため、必要最小限の情報を記載します。

{
    "name": "Trello Memo",
    "version": "1",
    "manifest_version": 2,
    "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self';",
    "browser_action": {
        "default_popup": "popup.html"
    }
}

nameは拡張機能の名前を書きます。
versionはこの拡張機能のバージョンを指定します。今回は新規作成なのでver1です。リリースして改修したらここを変更していきましょう。
manifest_versionは、このmanifest.jsonファイルの形式のバージョンです。2022年1月現在、3が最新バージョンですが、情報が少なかったのと、今回は外部公開をしないので2を選択しています。
content_security_policyはコンテンツセキュリティポリシーです。JavaScriptで通信するために、unsafe-evalを有効化します。
browser_action内のdefault_popupが、ブラウザの拡張機能のアイコンをクリックしたときに表示するHTMLファイルです。

CSS/JavaScriptライブラリファイルのダウンロード

Bootstrap、JQuery、Vue.jsをダウンロードしてローカルディレクトリに配置しましょう。

Bootstrap

  • css/bootstrap.min.css
  • js/bootstrap.bundle.min.js

の2ファイルは以下のページの「コンパイルされた CSS と JS」の方をダウンロードしましょう。

ダウンロード - Bootstrap 4.1 日本語リファレンス

jQuery

  • js/jquery-3.6.0.min.js

は以下から最新バージョンをダウンロードしましょう。

jQuery

Vue.js

  • js/vue.js

は以下のページの「<script> 直接組み込み」の下の、「開発バージョン」ボタンからダウンロードしましょう。

インストール — Vue.js

HTML/CSS/JavaScriptファイルの作成

次に拡張機能のメインとなるHTML/CSS/JavaScriptファイルを作成していきます。
今回は技術的な解説は省略します。実際に動作した各ファイルのソースを紹介します。

popup.html

<html>
<head>
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <link rel="stylesheet" href="css/style.css">
    <title>Trello Memo</title>
</head>
<body>
    <div id="app">
        <div class="container-fluid">
            <div class="row bg-info">
                <div class="col-sm-12"><h2>Trello Memo</h2></div>
            </div>
            <div class="form-group">
                <div class="row"><div class="col-sm-5">Title</div></div>
                <div class="row">
                    <div class="col-sm-5">
                        <input id="input-title" type="text" class="form-control" v-model="title">
                    </div>
                </div>
                <div class="row"><div class="col-sm-5">Desc</div></div>
                <div class="row">
                    <div class="col-sm-5">
                        <textarea id="input-desc" class="form-control" v-model="desc"></textarea>
                    </div>
                </div>
                <br>
                <div class="row">
                    <div class="form-check form-check-inline">
                        <div class="col-sm-10">
                            <button id="button" class="form-control btn-info" v-on:click="create">Create</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Modal -->
        <div class="modal fade" id="message-modal" tabindex="-1" role="dialog" aria-hidden="true">
            <div class="modal-dialog" role="document">            
                <div class="modal-content">
                    <div v-if ="isFailed()">
                        <div class="modal-header" id="error-modal">
                            {{ errorMessage }}
                            <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                                <span aria-hidden="true">&times;</span>
                            </button>
                        </div>
                    </div>
                    <div v-else>
                        <div class="modal-header" id="info-modal">
                            {{ modalMessage }}
                            <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                                <span aria-hidden="true">&times;</span>
                            </button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <script type="text/javascript" src="js/jquery-3.6.0.min.js"></script>
    <script type="text/javascript" src="js/bootstrap.bundle.min.js"></script>   
    <script type="text/javascript" src="js/vue.js"></script>   
    <script type="text/javascript" src="js/app.js"></script>
    <script type="text/javascript" src="js/popup.js"></script>
</body>
</html>

css/style.css

body {
    min-width: 480px;
}
h2 {
    color: #FFFFFF;
}
#info-modal {
    background-color: #17A2B8;
    color: #FFFFFF;
}
#error-modal {
    background-color: #DC3545;
    color: #FFFFFF;
}

js.app.js

****の箇所は以下を参考に必要な情報を取得し、変更してください。

www.true-fly.com

let app = new Vue({
    el: '#app',
    data: {
        title: '',
        desc: '',
        modalMessage: '',
        errorMessage: '',
        TRELLO_KEY: '****',
        TRELLO_TOKEN: '****',
        TRELLO_LIST_ID: '****'

    },
    methods: {
        isFailed() {
            if (this.errorMessage != '') {
                return true;
            }
            return false;
        },
        create() {
            let self = this;
            self.modalMessage = '';
            self.errorMessage = '';
            if (self.title == '') {
                self.errorMessage = 'Please enter a title!'
                $('#message-modal').modal();
                return
            }
            $.ajax({
                type:'POST',
                url: 'https://api.trello.com/1/cards?idList=' + self.TRELLO_LIST_ID
                    + '&key=' + self.TRELLO_KEY
                    + '&token=' + self.TRELLO_TOKEN,
                success: function(data) {
                    self.modalMessage = 'Succeeded in creating a new card!'
                    $('#message-modal').modal();
                },
                data: { 
                    'name': self.title,
                    'desc': self.desc
                },
                dataType : 'json',
                error: function(jqXHR) {
                    console.log(jqXHR)
                    self.errorMessage = 'Failed to create a new card!'
                    $('#message-modal').modal();
                }
            });
        }
    }
});

作成した拡張機能をブラウザで読み込む

Google Chromeで、「chrome://extensions/」にアクセスします。

拡張機能の設定画面が開いたら、画面上部の「パッケージ化されていない拡張機能を読み込む」をクリックします。
フォルダ選択のウインドウが開くので、作成したファイルがあるフォルダを選択肢します。

f:id:true-fly:20220109235845p:plain:w480

以下のように拡張機能一覧に自作の拡張機能が表示されれば無事読み込み成功です!

f:id:true-fly:20220110000110p:plain:w480

ブラウザ上の拡張機能をクリックして、画面が表示されることを確認しましょう。
試しにカードを1つ作成してみます。

f:id:true-fly:20220110000326p:plain:w480

作成先のTrelloのボードを確認します。
入力した情報がTrelloのカードとして作成されていれば完成です!

f:id:true-fly:20220110000512p:plain:w480

まとめ

以上、Google Chromeの拡張機能の開発方法について簡単に紹介しました。
今回はTrello APIを利用したメモだけの拡張機能ですが、HTML/CSS/JavaScriptで構成されるアプリケーションなので、様々なサービスのAPIを使って、普段の作業を簡易化できると思います。

今回は構成がシンプルで、Webアプリケーション作成と変わらない、ポップアップアプリケーションを紹介しましたが、Chrome拡張機能は今回のポップアップアプリケーション以外にも作れる機能はたくさんあります。

次回はChrome拡張機能のchrome.storage APIを使って、ローカルにデータを保存する方法を紹介しようと思います。
これによって、設定画面を作り、API KEYなどのJavaScriptにベタ書きの情報を外持ちできるようになります。