Chrome拡張　備忘録　１から１０まで

# はじめに
自分はChromeにマイ拡張機能を搭載して使っているのですが、ときどき機能追加しようとしたときにどうすれば良いのかわからなくなるので備忘録を書いておきます。
間違っていたりしたらコメントいただけるとうれしいです。

eventPageとかbrowserActionとかどれ使えばええねんって方は[まとめ](#まとめ)を御覧ください。

#必要なファイル・フォルダ構成
- manifest.json（必須）
- html（ブラウザアクションなどを実行したときに表示されるHTML）
- javascript（プログラム本体）

## manifest.json
[公式](https://developer.chrome.com/extensions/manifest)

必須

- manifest_version 現在有効なのは2(数値)
- name 拡張機能名　45文字まで
- version 1~4つまでの数字をドット区切り　更新時は必ずバージョンが上がっていなければならない
    * "1.0.0.1"や"3.4567"など
    
推奨

- default_locale
- description
- icons
    - `{ "16": "icon16.png", "48": "icon48.png" }`など アイコンは一つあればよい

一つ選択または無し

- browser_action
- page_action

オプション 使う機能だけ書けば良い

- author
- background　バックグラウンドページ／イベントページ（後述）
    - `"presistent" : false`が推奨（バックグラウンドページからイベントページへの移行（後述））
- chrome_settings_override ホーム画面、検索画面、スタートアップ画面の変更機能
- chrome_ui_override UIの変更　ブックマークとか
- chrome_url_override ブックマークマネージャ、履歴、新しいタブを変更できる
- commands キーボードショートカット
- content_scripts 配列　コンテントスクリプト（後述）
- homepage_url 拡張機能のホームページ
- incognito シークレットモードでの動作　spanning / split / not_allowedのいずれか
- offline_enabled オフライン時に動作するか否か
- optional_permissions オプションページでの[パーミッション](#パーミッション)
- options_page オプションページのHTML
- options_ui　オプションページの詳しい設定
    - chrome_style : true 　推奨
    - page : HTML。options_pageと同じ
- permissions 配列　[パーミッション](#パーミッション)
- update_url Chromeストア以外で自動更新したい場合設定する。ただし現在のWindows版およびベータ版はChromeストア以外で配信されている拡張機能はダウンロードできないらしい


# パーミッション
[公式](https://developer.chrome.com/extensions/permissions)
そのスクリプトが使えるChromeの機能
例えばタブ関連を使いたければTabs、ダウンロード機能を使いたければdownloadsなどをpermissionsに書く

# プログラム(javascript)を書ける場所
どのような種類の拡張があるか、というより、どこにプログラムを記載できるかで分類分けしてみます。

- ブラウザアクション/ページアクション(ポップアップのHTML上)
- イベントページ（旧バックグラウンドページから移行）
- コンテントスクリプト
- executeScriptで渡したスクリプト

## それぞれの解説
###ブラウザアクション／ページアクション
[Chrome公式解説ページ](https://developer.chrome.com/extensions/browserAction)
URL・検索バー右側にアイコンが出るタイプの拡張機能
2つの大まかな違いは、ブラウザアクションがブラウザ全体に作用する拡張機能（常時表示される）で、ページアクションがある特定のページに作用する拡張機能　という風に使い分ける
公式では「たくさんのページに作用するならブラウザアクション」「幾つかのページのみに作用するならページアクションを使って」とある
#### マニフェスト例
``` json
{ 
  "name": "My extension",
  "browser_action":{
    "default_icon":{
      "32": "images/icon.png"
    },
    "default_title": "拡張のボタン上ででるツールチップ",
    "default_popup": "popup.html"
  }
}
```
#### プログラムの書き方
上記の例である*popup.html*で、通常のHTMLのように`<script>`タグでスクリプトを読み込む。
当然ながら、**このスクリプトが操作できるのはポップアップのHTML(*popup.html*)**である。
jqueryなどを使うときは注意。
開いているページの中身などを操作したいときは後述の[コンテントスクリプト](#コンテントスクリプト)を使う。

### イベントページ
[Chrome公式](https://developer.chrome.com/extensions/event_pages)
バックグラウンドページ・イベントページと呼ばれる目に見えないページ上で動作するスクリプト達。
バックグラウンドページは常時ページが保持されるが、イベントページは必要なときだけ動作し、自動で廃棄されるようだ。
イベントページが実行されるタイミングは公式の方にも書いてあるが、だいたいは
- リッスンしていたイベントがディスパッチされた時
- [コンテントスクリプト](#コンテントスクリプト)などがメッセージを送信した時
- ポップアップなどが`runtime.getBackgroundPage`を呼び出した時

バックグラウンドページはページが保持され続けてしまうので、できるかぎりイベントページを使うように推奨されている。

####マニフェスト
``` json
{
  ...
  "background": {
    "scripts": ["eventPage.js"],
    "persistent": false
  }
  ...
}
```
####イベントページとバックグラウンドページの違い
マニフェストでpersistentをtrueにするとバックグラウンドページ、falseにするとイベントページ

#### プログラムの書き方
マニフェストのscriptsで記載したスクリプトが動作する。
**イベントページ（見えない）の内容を操作する**ので注意（jqueryなど）
`chrome.*`の機能（`chrome.tabs.*`など）が使えるので、`chrome.runtime.onMessage.addListener`でexecuteScriptのスクリプトからメッセージを受け取り、Chromeの機能を使って返してやることに使われることが多い気がする。


### コンテントスクリプト
[公式](https://developer.chrome.com/extensions/content_scripts)
指定されたページで自動的に実行されるスクリプト
matchesでURLを指定する
CSSも読めるので、特定のサイトのURLだけを変えたいような場合はスクリプトを組まなくてもできる（！）

#### マニフェスト
``` json
{
  ...
  "content_scripts":[
    {
      "matches": ["http://www.google.com/*"],
      "css": ["mycss.css"],
      "js": ["jquery.js","myscript.js"]
    }
  ]
}
```

#### プログラムの書き方
**そのサイトに対して動作する。**つまりjqueryなどでそのページを操作できる。
chromeの機能で使用できないものは[メッセージパッシング](#メッセージパッシング)でイベントページにやってもらおう。


### executeScript
[公式](https://developer.chrome.com/extensions/tabs#method-executeScript)
popupのスクリプトなどから、`chrome.tabs.executeScript`で渡すとそのスクリプトが実行される。
また、一部の`chrome.*`,`runtime.*`の機能が使えないので、それらを使う時は[メッセージパッシング](#メッセージパッシング)でイベントページにやってもらう
tabsのパーミッションが必要

#### コード例
``` js:popup.js
// jqueryを読み込んでから自分のスクリプトを動作させる
chrome.tabs.getSelected(null, function(selectedTab){
  chrome.tabs.executeScript( selectedTab.id, {
    file: "jquery.min.js"
  },function() {
    chrome.tabs.executeScript( selectedTab.id, {
      file: "myscript.js" 
    }, function(result){ ... });
  });
}
```
#### プログラムの書き方
任意のタイミングでそのページにスクリプトを挿入できる。**操作するのもそのページ。**
ただし、予め使うサイトが決まっているならコンテントスクリプトのほうが良いと思われる。

# メッセージパッシング
Message Passingってどう訳すんだろう　メッセージ渡し？
[公式](https://developer.chrome.com/extensions/messaging)
その拡張で動作中のスクリプト間でオブジェクトを渡したり出来る機能です。
たとえばExecuteScriptで実行したスクリプトがchrome.tabsを使おうとした時、そのままでは使えないので、メッセージパッシングでイベントページのスクリプトにメッセージを依頼して実行してもらうなどの使い方ができます。
送る方は

```js
chrome.runtime.sendMessage({atai:"値"},function(response){
  // 相手のメッセージリッスンが終わった後される処理
  var res = response.returnAtai;
});
```

受ける方は

```js
chrome.runtime.onMessage.addListener(
  function(request,sender,sendResponse){
    var atai = request.atai;
    sendResponse({returnAtai: "値その２"});
  }
);
```

# まとめ
- 特定のサイトの時そのサイトに対してスクリプト・CSSを与えたい　
    - →　[コンテントスクリプト](https://developer.chrome.com/extensions/content_scripts)
- ボタンを表示して色々したい　↓
    - ある特定のサイト　→　[ページアクション](https://developer.chrome.com/extensions/pageAction)
    - 全般的に　→　[ブラウザアクション](https://developer.chrome.com/extensions/browserAction)
     
- ボタンを押したらポップアップを表示しないでスクリプトを実行したい
    - → [バックグラウンド/イベントページ](https://developer.chrome.com/extensions/event_pages)のjsで`chrome.browserAction.onClicked.addListener(function callback)`
- ボタンを押したらポップアップしてそこでいろいろしたい
    - → [ポップアップのHTML](https://developer.chrome.com/extensions/browserAction#popups)を設定し、そこでjsを読み込む
- スクリプト間で連携するときはsendMessage

# 忘れたくないテクニックなど

- オプションページを開く
    - `chrome.runtime.openOptionsPage()`