Chrome拡張機能を作ってみた！

# はじめに
chrome拡張機能について使いやすく、便利なものが多く愛用している著者であるが、自分で作ったことがなかったので作り方も含めて記事にしてみた！ほぼ初心者が作成したので、至らない点もあると思いますが修正点等があれば教えてください。
(注意)この記事で作成するこの拡張機能はchromeのHPだけで使える設定になっているので注意してください

# chrome拡張機能の作り方
## 拡張機能を有効化する
有効化する手順は意外と簡単！
まず、目的としては拡張機能を有効化させることなので、公式のチュートリアルから完成された拡張機能をダウンロードして試してみる。
https://developer.chrome.com/extensions/examples/tutorials/get_started_complete.zip 
1.chromeのタブを閉じる「×」ボタンの下にあるボタン(Google Chromeの設定）をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474340/0074b5d0-97b8-0566-2b7d-2a20b23bd8a6.png)

2.「その他のツール」→「拡張機能」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474340/d9af89f4-7077-742a-c84c-0e808f01561d.png)

3.右上にあるデベロッパーモードをオンにして、「パッケージ化されていない拡張機能を読み込む」をクリック → 拡張機能として作成したフォルダ(試すだけなら、上でダウンロードしたフォルダ）を選択して完成　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474340/9f62df3a-2481-9cf1-8e01-229acdd45147.png)

このように、拡張機能を完成させてから有効化する方法について実践した。次は、実際に拡張機能の中身について書いていく

## Chrome拡張機能の作り方(コード)
### Manifestを作る
Chrome拡張機能の根幹となるもので、manifest.jsを作る必要がある。これだけでも、Chrome拡張機能として有効化させることはできる。(機能は何もないが）
必要最低限なコードは以下の通り

```json:manifest.json
  {
    "name": "Getting Started Example",
    "version": "1.0",
    "description": "Build an Extension!",
    "manifest_version": 2
  }
```
name : chrome拡張の名称
version : つくりはじめなので、「1.0」に設定
description : 拡張機能の説明

### Instruction を追加
上記の通りだと、拡張機能はインストールできるが、中身の指示については何もない状態であるので、それを追加していく。

1. background.jsを追加
ここで覚えておかないといけない大事なことであるが、background.jsなど新たに作成したものは、manifest.jsに登録しなければならない。

1. manifest.jsにbackground.jsを登録
background.jsの場合の登録方法は以下の通りである。

```js:manifest.json
  {
    "name": "Getting Started Example",
    "version": "1.0",
    "description": "Build an Extension!",
//追加部分(ここから)
    "background": {
     "scripts": ["background.js"],
     "persistent": false
      },
//追加部分(ここまで)
    "manifest_version": 2
  }
```
(追記)ちなみに"background"の中の"persistent"の説明は[こちら](https://www.eisbahn.jp/yoichiro/2013/02/chrome-extension-event-page.html)

2.background.jsのコードを書く
manifest.jsと同じ階層にbackground.jsを作成。
コードは以下のように書く

```js:background.js
  chrome.runtime.onInstalled.addListener(function() {
    chrome.storage.sync.set({color: '#3aa757'}, function() {
      console.log("The color is green.");
    });
  });
```
 上のコードでは、コンソールログに"The color is green"と表示するようにしている。
 また、値をセットするために、storageAPIを使用しているので、manifest.jsonに登録する必要がある。

3.APIをmanifest.jsに追加

```js:manifest.js
  {
    "name": "Getting Started Example",
    "version": "1.0",
    "description": "Build an Extension!",
//追加部分(ここから)
    "permissions": ["storage"],
//追加部分(ここまで)
    "background": {
     "scripts": ["background.js"],
     "persistent": false
      },
    "manifest_version": 2
  }
```
このようにして、拡張機能の管理画面でリロードボタン(右下の〇＋→のボタン）を押すと、以下のように、「ビューを検証　バックグラウンドページ」というのが追加される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474340/6479ab01-164e-d160-c54b-543ddb0def55.png)

ちなみにこの「バックグラウンド ぺージ」をクリックして、画面上部の"Console"タブをクリックすると、以下のように、"The color is green"と表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474340/bbc1e888-1f03-b54f-12d7-579a96622f87.png)

## UIの導入
Chrome拡張にはたくさんのUIがあるが、今回はpopupのみを試してみたいと思う。popupも含むUIについてのドキュメントは[こちら](https://developer.chrome.com/user_interface)

ここでは、***ボタンによって背景色を変える***ものを作ってみる！

1.popup.htmlを作成

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

2.manifest.jsに追加
恒例のあたらしいものをつ作ったら、manifest.jsに登録という工程。今回は、"page_action", "icons"を以下のように追加する。

```json:manifest.js
・・・略
    "page_action": {
      "default_popup": "popup.html",
      "default_icon": {
        "16": "images/get_started16.png",
        "32": "images/get_started32.png",
        "48": "images/get_started48.png",
        "128": "images/get_started128.png"
      }
    },
    "icons": {
      "16": "images/get_started16.png",
      "32": "images/get_started32.png",
      "48": "images/get_started48.png",
      "128": "images/get_started128.png"
    },
・・・略
```
 popup.htmlの設定と、表示させる画像のインポートを行っている。
 今回は[こちらの画像](https://developer.chrome.com/extensions/examples/tutorials/get_started/images.zip)をダウンロードして解凍した後、imageディレクトリをmanifest.jsと同じ階層に保存。

3.declarativeContent APIを導入
これは、ページのコンテンツを読み取る権限を必要とせずに、ページのコンテンツに応じてアクションを実行するためのもの。[原文のドキュメント](https://developer.chrome.com/declarativeContent)

■background.jsに以下のコードを追加

```js
: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()]
      }]);
    });
//ここまで追加
  });
```

4.manifest.jsにAPIを追加
permissionsに関しては、前に宣言してあるので、"declarativeContent"の部分を追加

```js:manifest.js
  {
    "name": "Getting Started Example",
  ...略
    "permissions": ["declarativeContent", "storage"],
  ...略
  }
```

1~4の手順を踏むと、右上のアイコンがフルカラーになり、クリックするとの下の枠が現れればここまでの手順は成功！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474340/172c98c5-9824-28a0-3796-46ba3417fcc2.png)


5.popup.jsを作成(色がつくようにする)

```js:popup.js
  let changeColor = document.getElementById('changeColor');

  chrome.storage.sync.get('color', function(data) {
    changeColor.style.backgroundColor = data.color;
    changeColor.setAttribute('value', data.color);
  });
```
このコードを追加して、popup.htmlに``` <script src="popup.js"></script>```を追加したら、下の画像のように緑色になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474340/fb775e8d-f2ee-8b61-dfa0-346b9f7f43f9.png)

```html:popup.html
<!DOCTYPE html>
<html>
...
  <body>
    <button id="changeColor"></button>
    <script src="popup.js"></script>//この行を追加
  </body>
</html>
```

ここまで作成すると、緑のボタンを押すことで、chromeの背景が緑色にすることができるchrome拡張機能を作れた！

##レイヤーロジック
現在は、ユーザーがポップアップを使用できることを認識し、色付きのボタンを表示しますが、ユーザーとの対話をさらに進めるためのロジックが必要です。そのため、popup.jsに以下のコードを追加する。
コードは以下の通り。

```js:popup.js
  let changeColor = document.getElementById('changeColor');
  ...
  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の更新が完了したら、今回使用したactiveTabの許可を行う。ちなみに、このAPIは、ユーザーが拡張機能を呼び出すときに、たとえばブラウザーのアクションをクリックすることにより、現在アクティブなタブに一時的に拡張機能をアクセスできるようにするものである。

##User Optionsの追加
今までのものだと、背景を緑色にしか変更することができない。しかし、他の色へも変更できる拡張機能を追加することができるので、その実装をここでは行う。
1.options.htmlを作成

```html:options.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>
```

2.manifest.jsにoptions.htmlを登録

```js:manifest.js
  {
    "name": "Getting Started Example",
    ...
    "options_page": "options.html",
    ...
    "manifest_version": 2
  }
```
3.拡張機能の管理画面での操作
更新を行い、詳細ボタンを選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474340/f8d3c88c-6be2-d52d-182e-9176e705ab03.png)

その後、「拡張機能のオプション」ボタンを押すと、色の選択画面(オプション)に遷移できるようにする。実行内容については次のステップで説明。

5.options.jsを作成
2行目のコードで変えられる色のコードを指定し、緑、赤、黄、青色に変更できるようにしている。この画面で色を設定すると、アイコンをクリックしたときに表示される色も変更される。

```js: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);
```

##完成！
今回は、ひとまずchromeの公式チュートリアルをなぞるように、背景色を変える拡張機能を実装してみた。一通り試してみて、中の構造が漠然とではあるがわかるようになってきたので、自分の作りたいものが拡張機能として実装できるように頑張りたい！(この拡張機能はchromeのHPだけで使える設定になっているので注意してください)

(ちなみに著者のチュートリアルに要した時間は、3時間半くらい。Qiitaを書きながらだったり、メモでまとめてたり、途中話してたりとしていたので、実装だけするなら1/3~1/2でできると思うと考えると、意外に簡単に実装できると知って驚いた)
# 参考記事
[公式のチュートリアル](https://developer.chrome.com/extensions/getstarted) ← 鉄板かと