虎の穴開発室ブログ

虎の穴ラボ株式会社所属のエンジニアが書く技術ブログです

MENU

Chromeの拡張機能を自作する

こんにちは。虎の穴ラボのH.Hです。
突然ですが、皆さんは普段使っているブラウザは何でしょうか?
私は普段からChromeを使っており、このブログもChromeを使って書いています。

先日ある拡張機能をChromeに入れるにため機能の説明を読んでいました。 説明の中にGithubのURLが記載され拡張機能のソースコードが公開されており、JavaScriptなどの知識があれば作成可能とわかりました。
またGoogleから簡単な拡張機能を作成するチュートリアルも公開されていました。

そこで、チュートリアルで公開されている拡張機能の実際に作ってみることにしました。

今回は拡張機能の作成した時の手順とデバッグの方法を説明していきます。

Chromeの拡張機能とは

Chrome機能はChromeウェブストアなどからChromeに追加することで、標準には無い機能の追加を行うものです。

chrome.google.com

どのような拡張機能がChromeに入っているかの確認は、以下の方法で確認ができます。
・「chrome://extensions/」とブラウザのアドレスバーに入れる
・Chromeの設定から拡張機能を選ぶ

公開されている拡張機能には、Google製のものはもちろんGoogle以外の企業や個人が開発した拡張機能も多く公開されています。

Chromeの拡張機能は jsonファイル、HTMLファイル、JavaScriptファイル、CSSファイルで構成されます。

json・・・manifest.jsonという名前で作成する。拡張機能の設定など記述する
HTML・・・ブラウザ上で拡張機能を動作させるメニューや設定変更用のページを記述する
JavaScript・・・拡張機能の動作を記述する
CSS・・・拡張機能が適用するCSSの内容を記述する


拡張機能の作り方を説明した日本語のページもいくつかありましたが、断片的な情報が多かったです。今回は、Googleが公開しているチュートリアルの内容に倣って、実際に開発の流れを説明したいと思います。

拡張機能を作るために必要なもの

拡張機能を作って動作させるために必要なものは以下の二つです。

・ChromeがインストールされたPC
・HTMLなどを編集するためのテキストエディタ

今回はmacOS Calalina 10.15.3とChromeのバージョン81を使用します。

Googleが公開している拡張機能のチュートリアルについて

拡張機能の作り方についてはGoogleがサイトで公開しています。

developer.chrome.com

紹介されているのは特定のサイト(developer.chrome.com)の背景色を変更するボタンを持つ拡張機能になります。
実際に動かすとこのような表示に変わります。
f:id:toranoana-lab:20200421171459j:plain:w300

拡張機能の作り方

1.作業ディレクトリの作成

拡張機能を構成するファイルをまとめるためのディレクトリを作成します。
拡張機能をブラウザに追加する時は、関連ファイルをまとめたディレクトリを指定することになります。
ディレクトリの名前は拡張機能の名前などには反映されないので、わかりやすい名前で作成して問題ありません。


2.manifest.jsonファイルの作成

拡張機能に関する設定はこのファイルに記述する事になります。
最低限必要な内容は、拡張機能の名前(name)・バージョン(version)・拡張機能の詳細な説明(discription)・マニフェストバージョン(manifest_version)になります。
(2020/4/20現在、マニフェストファイルのバージョンは2が有効になります。)

最低限必要なmanifest.jsonの内容は以下のようになります。

{
    "name": "Getting Started Example",
    "version": "1.0",
    "description": "Build an Extension!",
    "manifest_version": 2
}

以降はmanifest.jsonに必要な内容を追記していく事になります。


3.拡張機能の初期処理

拡張機能を動かすにあたり初期設定として必要な内容がある場合は、backgroundという要素をmanifest.jsonに追記します。
またGoogleのサンプルではローカルストレージに値の読み書きする権限(storage)と、ブラウザに実際に表示されている内容の読み込みを行うための権限(declarativeContent)をつけるために、permissionsという要素を追加します。
backgroundの中で指定されているJavaScriptが実行されます。今回はbackground.jsとしています。

manifest.json

{
    "name": "Getting Started Example",
    "version": "1.0",
    "description": "Build an Extension!",
    "permissions": ["declarativeContent", "storage"],
    "background": {
      "scripts": ["background.js"],
      "persistent": false
    },
    "manifest_version": 2
}

background.js

chrome.runtime.onInstalled.addListener(function() {
    chrome.storage.sync.set({color: '#3aa757'}, function() {
      console.log('The color is green.');
    });
    chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
      chrome.declarativeContent.onPageChanged.addRules([{
        conditions: [new chrome.declarativeContent.PageStateMatcher({
          pageUrl: {hostEquals: 'developer.chrome.com'},
        })
        ],
            actions: [new chrome.declarativeContent.ShowPageAction()]
      }]);
    });
});

background.jsはmanifest.jsonと同じディレクトリに配置します。

background.jsは以下の二つをことを行っています。
・ローカルストレージにKey-Value形式の値を保存(colorという名称に対して、#3aa757を保存しています)
・今回の拡張機能を有効にするかどうかの判定(表示されているブラウザのホストがdeveloper.chrome.comと一致している場合のみ有効)


4.拡張機能の操作を行うHTMLの追加

次に背景色を変更するボタンを表示する部分を作成します。

拡張機能操作をするためのパーツはHTMLで記述します。
今回は単純なボタンが一つだけのHTMLを作成します。名前はpopup.htmlとします。

popup.html

<!DOCTYPE html>
  <html>
    <head>
      <style>
        button {
          height: 30px;
          width: 30px;
          outline: none;
        }
      </style>
    </head>
    <body>
      <button id="changeColor"></button>
    </body>
</html>

backgroud.jsと同様にmanifest.jsonにpage_actionという、popup.htmlを呼び出す定義を追加します。
また、page_actionのdefault_iconにアイコン画像を定義します。さらに表示されている画面を操作するため、permissionsにactiveTabを追加します。

manifest.json

 {
    "name": "Getting Started Example",
    "version": "1.0",
    "description": "Build an Extension!",
    "permissions": ["activeTab","declarativeContent", "storage"],
    "background": {
      "scripts": ["background.js"],
      "persistent": false
    },
    "page_action": {
      "default_popup": "popup.html",
      "default_icon": {
        "32": "images/get_started32.png"
      }
    },
    "manifest_version": 2
}

アイコンの定義に書かれている数値の"32"は画像を表示する場所の指定となります。
実際に動かすとアドレスバーの横の拡張機能のアイコンに、この画像は使用されます。
チュートリアルでは4つ定義されていますが、今回作成した拡張機能では32が定義されていれば問題ありません。


5.拡張機能の処理の追加

今回の拡張機能の根幹となる背景色を変更する処理を追加します。
機能の呼び出しはpopup.htmlにJavaScriptの呼び出しを追記します。
JavaScriptの名前はpopup.jsとします。

popup.html

<!DOCTYPE html>
  <html>
    <head>
      <style>
        button {
          height: 30px;
          width: 30px;
          outline: none;
        }
      </style>
    </head>
    <body>
      <button id="changeColor"></button>
      <script src="popup.js"></script>
    </body>
</html>

popup.js

  let changeColor = document.getElementById('changeColor');

  chrome.storage.sync.get('color', function(data) {
    changeColor.style.backgroundColor = data.color;
    changeColor.setAttribute('value', data.color);
  });
  changeColor.onclick = function(element) {
    let color = element.target.value;
    chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
      chrome.tabs.executeScript(
          tabs[0].id,
          {code: 'document.body.style.backgroundColor = "' + color + '";'});
    });
};

popup.jsの中では、以下の4つのことを行っています。
1)popup.htmlの中のボタンの要素を取得
2)backgroud.jsの中で定義したcolorの値を取得して1)で取得したボタンの背景色に設定
3)ボタンの要素に1)で取得した値をvalueの値として定義
4)ボタンを押した場合に実行する処理(onClickの処理)の定義

この部分で注意点が1点あります。それは上記の処理の4つ目のonClickの処理の追加です。
page_actionで定義したHTMLにはonClickなどのon~で始まる定義を記述できないという制約があるため、JavaScriptの中で処理を追加する必要があります。
仮にHTMLに直接記述した場合、Chromeに登録する際にエラーとなります。


6.オプションページの追加

細かな設定ができる拡張機能を作成した場合、設定用の画面があった方が良い場合があります。
その場合に使用するのがオプションページです。
HTMLファイルとJavaScriptファイルで記述し、その読み込みをmanifest.jsonに記述します。
今回は名前をoptions.html,options.jsとし、背景色の定義を切り替える機能をつけます。

option.html

 <!DOCTYPE html>
  <html>
    <head>
      <style>
        button {
          height: 30px;
          width: 30px;
          outline: none;
          margin: 10px;
        }
      </style>
    </head>
    <body>
      <div id="buttonDiv">
      </div>
      <div>
        <p>Choose a different background color!</p>
      </div>
    </body>
    <script src="options.js"></script>
  </html>

options.js

 let page = document.getElementById('buttonDiv');
  const kButtonColors = ['#3aa757', '#e8453c', '#f9bb2d', '#4688f1'];
  function constructOptions(kButtonColors) {
    for (let item of kButtonColors) {
      let button = document.createElement('button');
      button.style.backgroundColor = item;
      button.addEventListener('click', function() {
        chrome.storage.sync.set({color: item}, function() {
          console.log('color is ' + item);
        })
      });
      page.appendChild(button);
    }
  }
  constructOptions(kButtonColors);

manifest.json

{
    "name": "Getting Started Example",
    "version": "1.0",
    "description": "Build an Extension!",
    "permissions": ["activeTab","declarativeContent", "storage"],
    "background": {
      "scripts": ["background.js"],
      "persistent": false
    },
    "page_action": {
      "default_popup": "popup.html",
      "default_icon": {
        "32": "images/get_started32.png"
      }
    },
    "options_page":"option.html",
    "manifest_version": 2
  }


7.拡張機能の一覧画面に表示するアイコンの設定

最後に拡張機能の一覧画面に表示する際のアイコンを定義します。
定義を記述する場所はmanifest.jsonです。

manifest.json

{
    "name": "Getting Started Example",
    "version": "1.0",
    "description": "Build an Extension!",
    "permissions": ["activeTab","declarativeContent", "storage"],
    "background": {
      "scripts": ["background.js"],
      "persistent": false
    },
    "page_action": {
      "default_popup": "popup.html",
      "default_icon": {
        "32": "images/get_started32.png"
      }
    },
   "icons": {
      "48": "images/get_started48.png"
    },
    "options_page":"option.html",
    "manifest_version": 2
  }

アイコンの定義に書かれている数値の"48"は画像を表示する場所の指定となります。
この画像は、拡張機能の一覧画面や詳細ページで使用されます。
チュートリアルでは4つ定義が書かれていますが、48だけを定義すれば今回の場合問題ありません。



実際に動かしてみる

実際に動かすには、拡張機能の一覧が表示されている画面(chrome://extensions)に移り作成したファイルが入ったディレクトリを読み込ませます。
読み込むにはデベロッパーモードを有効にしておく必要があります。
下の画像のように画面の右側のデベロッパーモードが青くなっていれば問題ありません。
f:id:toranoana-lab:20200421171904j:plain:w300

アップロードは画面右側の「パッケージ化されていない拡張機能を読み込む」から作成したディレクトリを読み込みます。

f:id:toranoana-lab:20200421172631j:plain:w400

成功するとGetting Started Exampleという名前の拡張機能が追加され、ブラウザのアドレスバーの横に新しく拡張機能のアイコンが表示されます。
今回アイコンは虎の穴ラボで配布しているメイドちゃんにしました。拡張機能の一覧ページに表示される画像はiconsの48の画像、アドレスバーの横に表示される画像がpage_actionのdefault_iconの32の画像が使用されます。

f:id:toranoana-lab:20200421173027j:plain:w300

f:id:toranoana-lab:20200421173426j:plain:w300

小さいですが、アドレスバーの隣にメイドちゃんのアイコンが表示されます。
グレーアウトしているのは、ブラウザで「developer.chrome.com」を表示していないためです。画面を移動して、ホスト名がbackground.jsの内容と一致するとアイコンがカラーになり機能が有効になります。

f:id:toranoana-lab:20200421173656j:plain:w300

アイコンを押すと、アイコンの下にpopup.htmlの内容が表示されます。

f:id:toranoana-lab:20200421174447j:plain:w300

この緑色のボタンを押すと、「developer.chrome.com」の白色の背景が緑色に変わります。

f:id:toranoana-lab:20200421174708j:plain:w300f:id:toranoana-lab:20200421180043j:plain:w300
背景色の変更前後

またアイコンを右クリックした時に表示されるメニューの中のオプションを選択するとoptions.htmlで記述した内容が表示されます。

f:id:toranoana-lab:20200421175309j:plain:w300
オプション画面

オプションページで別の色を選択して、もう一度拡張機能のアイコンのボタンを押すと指定した色に変わります。

f:id:toranoana-lab:20200421180043j:plain:w300 f:id:toranoana-lab:20200421180235j:plain:w300
緑から赤に変える



デバッグ方法

拡張機能のデバッグ方法は初期処理のbackground.jsと実際の機能のpopup.jsで異なります。

1.background.jsのデバッグ方法

background.jsは拡張機能の詳細ページに移動して、ビューの検証というところで確認します。
バックグラウンドページのリンクを押すとディベロッパーツールが表示されて、ソースを確認することができます。

f:id:toranoana-lab:20200421183724j:plain:w300 f:id:toranoana-lab:20200421183735j:plain:w300
background.jsの検証

注意点はブレイクポイントが効かないので、コンソールへの出力などで動作の確認を行う必要がある点です。
上の画像でブレイクポイントを設定していますが、止まることなく処理が進みます。

2.popup.jsのデバッグ方法

popup.jsは下の画像のようにpopup.htmlが表示されている領域で右クリックを押して、表示された検証からディベロッパーツールを表示することで、動作確認が可能です。

f:id:toranoana-lab:20200421184624j:plain:w200
popup.jsのデバッグ

こちらはブレイクポイントが動作するので、通常のJavaScriptのように動作確認することが可能です。



まとめ
Chromeの拡張機能のチュートリアルではこの後様々なサンプルの紹介などがあります。時間を見つけてこれらにも取り組みたいと思います。
また、今回はJavaScriptで画面の背景色を変える処理を行いましたが、CSSで切り替える方法もあります。
実際に作ってみて、画面の表示をブラウザ内だけで変更できるので、画面表示の変更のテストを本番環境に影響を与えずに動作確認するなど様々な活用方法があると感じました。

P.S

虎の穴ラボでの開発に少しでも興味を持っていただけた方は、採用説明会やカジュアル面談という場でもっと深くお話しすることもできます。ぜひお気軽に申し込みいただければ幸いです。 虎の穴ラボのエンジニアが、開発プロセスの内容であったり、「今季何見ました?」といったオタクトークであったり、何でもお応えします。
※現在はオンラインカジュアル面談のみ受け付けております。(2020/4/20時点)

WantedlyLAPLASでの採用も行っております)

yumenosora.co.jp

news.toranoana.jp

とらのあなラボでは、ツイッターで情報発信しています。ぜひフォローしてください! twitter.com

5月14日に「とらのあな採用説明会 5/14 オタク企業で働くエンジニアの魅力について」オンライン会社説明会を開催します。

yumenosora.connpass.com