OXY NOTES

Chromeの機能拡張を作成して、ブラウザで読み込み、デバックする方法

公式ドキュメントの勘どころさえ掴めば機能拡張も簡単です

Chrome機能拡張の解説」第2弾。

このページでは実際に機能拡張を作成します。作成した機能拡張をブラウザに取り込み、動作確認のためにデバックをする方法を解説します。

自分で機能拡張を作成するときに困らないように、公式ドキュメントを読み方も合わせて解説していきます。


目次


機能拡張の作成に必要なファイル

機能拡張の作成には以下のファイルが必要になります。

manifest file

manifest file(マニフェストファイル)とは、機能拡張のバージョンや名前などを記述するメタ情報ファイルで、JSON形式で記述します。

必須項目はmanifest_versionnameversionの3点のみです。必要に応じて情報を追加していきます。

HTMLファイル

ポップアップ表示する際に開いたり、オプションページを作る際にも使います。

JavaScriptファイル

DOM要素を操作したり、AJAXで外部と通信したりする際に使います。外部のコードを取り込んで実行することはできないので、必要ならjQueryなどのライブラリも機能拡張に含めます。

その他のファイル

CSSや、アイコンなどの画像ファイルなど。

以上のように基本的にはWebページを作る技術があれば機能拡張を作成することができます。


機能拡張を作りながらドキュメントを読み解く

機能拡張は複数のAPIを組み合わせて実装する必要があります。
Googleの公式ドキュメントには実装する上での決まり事や、ヒント用例が掲載されているので、ざっと1読することをおすすめします。

今回作成するツールバーにアイコンを表示して、クリックするとポップアップが表示されるという機能を追加するにはchrome.browserActionというAPIを利用します。

chrome.browserActionの公式ドキュメント

まずAPI名の後にDescription(解説)Availability(有効になったバージョン)Manifest(manifest.jsonへの記述方法)が解説されています。

Descriptionでは、アドレスバーの横にあるツールバーにアイコンが追加される。tooltip、badge、popupという機能が用意されている、とあります。

AvailabilityではChromeのバージョン5から有効になったことがわかります。

ManifestではJSON形式で"browser_action": {…}と追加すれば良いことがわかります。

Manifest

マニフェストファイルであるmanifest.jsonへの記述例です。
黄色でマーカーされている部分がchrome.browserAction用の記述です。

アイコンの指定方法、マウスオーバー時に表示されるツールチップの指定、ポップアップされるHTMLファイルの指定方法などが解説されています。

Parts of the UI

Iconの推奨サイズ利用可能なファイル形式canvas要素を利用したアニメーションも可能とあります。

Tooltipはマウスオーバー時の文字列の表示で、APIを利用すればJavaScript内で変更できることがわかります。

Badge(バッジ)には4文字までの情報を掲載でき、色やテキストを指定するAPIについて紹介されています。

Popupは好きなHTMLファイルを指定でき、サイズに合わせて自動でウィンドウサイズが変わることがわかります。

Tips

いわゆるヒント。画像の推奨サイズやシャギーをなくすにはアルファチャンネルを使うといった細かなテクニックを紹介しています。

Examples

さすがGoogle。APIを利用したサンプルの機能拡張がアップされています。「簡単な使い方は理解できたけど、実践的な利用方法が分からない」といったときに大助かりです。

Sample Extensionsページ

Summary

メソッド一覧です。個別のメソッドの使い方については実際に使用するときに解説します。

以上、ざっとですが公式ドキュメントの読み解き方を紹介しました。

はじめは読むのが面倒ですが、使い慣れると勘どころがすぐに理解できる、利用しやすいドキュメントです。


機能拡張の構成ファイルを作成

長々と解説しましたが、とうとう実際のファイルを作成しますw

まずは機能拡張用のディレクトリを作成します。
一応当サイトではデスクトップに「Test Extention」というディレクトリを作成しました。これから作成するファイルはこのディレクトリに保存してください。

manifest.json

ボタンをクリックすると何かのアクションが実行されるのはブラウザアクションです。

公式ドキュメントにサンプルが載っているので参考に以下のようにしました。

{
	"manifest_version": 2,
	"name": "Test Extention",
	"version": "0.1",
	"browser_action": {
		"default_popup": "popup.html",
		"default_icon": "19px.png",
		"default_title": "Hello Worldを表示するよ"
	}
}

manifest_versionは2015年現在だと2を指定します。

name機能拡張自体の名前です。

versionは、この機能拡張のバージョンです。更新するごとにバージョンの数字を上げていきます。

browser_actionで、ポップアップ時に表示するhtmlファイル、アイコン、マウスオーバー時に表示されるテキストを指定します。

マニフェストファイルの形式になれないうちはコメントを付けたくなりますが、JSONはコメントを付けることはできないので注意してください。

また、最後の項目の後にカンマは入れません。新しい要素を追加したり、順序を変えた際に間違えやすいので注意してください。

popup.html

これは普通のHTMLファイルです。テスト用なので簡易的に以下のようにしました。
ちなみにHTMLやJavaScriptファイルは、文字化け対策のためUTF-8で保存してください。

<!DOCTYPE html>
<html>
<head>
<title></title>
</head>

<body>

<p>Hello World!</p>

</body>
</html>

19px.png

上記のmanifest.jsonで指定したブラウザアクション用の画像です。
ちなみにアイコンのサイズは19pxです。今回は分かりやすくするためTestの頭文字からTと入ったアイコンを作成しました。

これでポップアップでHello Worldを表示する機能拡張は完成です。

とても簡単ですが、一応サンプルをアップロードしておきます。必要な方はダウンロードして利用してください。

Test Extentionをダウンロード


作成した機能拡張をChromeに読み込む

Google Chromeの設定ボタンから「その他のツール > 機能拡張」を選択します。もしくはアドレスバーに「chrome://extensions/」と入力します。

右上の「デベロッパーモード」にチェックを入ると「パッケージ化されていない機能拡張を読み込む…」というボタンが表示されるので先ほど作成した「Test Extention」ディレクトリを読み込みます。

すると以下のように「Test Extention」と書かれた機能拡張が表示されます。

manifest.jsonに記述したようにバージョンは0.1となっていることがわかると思います。
機能拡張に変更を加えた場合はタイトルの下にあるリロードボタンで読み込み直すことで変更を有効にします
(ブラウザアクションによって毎回読み込み直すファイルはリロードをクリックしなくても反映されますが、変更したらリロードと覚えておくと間違いが少ないと思います)

先ほど作成したTの入ったアイコンがアドレスバーの横に表示されたと思うのでマウスオーバーしてみます。
するとmanifest.jsonで指定した「Hello Worldを表示するよ」が表示されます。

またクリックすると「Hello World!」が表示されます。

Chromeの機能拡張がいかに簡単に作成できるか理解していただけたと思います。


外部のJavaScriptファイルを読み込む

続いて表示されたHello World!のテキストをクリックするとアラートが表示されるJavaScriptを追加します。
Chromeアプリではセキュリティの関係でポップアップで表示されたHTMLに直接JavaScriptを記述することは禁止しています。
ではどうするのか?答えは簡単外部ファイルとして読みこめば良いだけです。

先ほど作成したTest Extentionを複製してTest Extention2とします。

manifest.json

バージョンを0.2にします。

{
	"manifest_version": 2,
	"name": "Test Extention",
	"version": "0.2",
	"browser_action": {
		"default_popup": "popup.html",
		"default_icon": "19px.png",
		"default_title": "Hello Worldを表示するよ"
	}
}

popup.html

アラートで日本語を表示したいのでcharsetでUTF-8を指定
myscript.jsを読み込み、Hello Worldにidを追加。idはhelloとしました。

<!DOCTYPE html>
<meta charset="UTF-8" />
<html>
<head>
<title></title>
<script type="text/javascript" src="myscript.js"></script>
</head>

<body>

<p id="hello">Hello World!</p>

</body>
</html>

myscript.js

scriptタグで外部JavaScriptファイルを読み込むと、popup.htmlのDOM要素が読み込まれる前に解釈されます。
そのためドキュメントを読み込んだ後に実行されるようにwindow.onloadのイベントハンドラとしてdocument.getElementByIdを記述します。

後は普通にイベントリスナーでクリックイベントのコールバックとしてアラートを実行しています。

window.onload = function() {
	var el = document.getElementById("hello");
	el.addEventListener("click", function(){
		alert("外部JavaScriptファイル");
	}, false);
};

機能拡張を読み込み直す

機能拡張画面を開き、先ほどインストールした機能拡張の右上にあるゴミ箱アイコンをクリックして削除。新しく作成した「Test Extention2」を読み込みます。

manifest.jsonで指定したようにバージョンが0.2になっています。

読み込んだらアイコンをクリックしてポップアップを表示して「Hello World!」の文字をクリックします。
すると以下のようにアラートが表示れます。

このように外部ファイルにすればJavaScriptファイルを取り込むことができます。CSSも同じようにpopup.htmlに記述すれば読み込めるので試してみてください。


ChromeのAPIを利用する

外部のJavaScriptファイルを使えることは理解していただけたと思います。ではブラウザのタブに関する情報を取得してみます。

そのために利用するのがAPI(アプリケーションプログラミングインタフェース )です。何だか長い名前でややこしそうですが、特定のコードで呼び出せば、指定した情報が返ってくるという単純な仕組みです。

では今回は応用としてchrome.browserAction APIsetTitleメソッドを利用します。
今度は「Test Extention3」を作ります。

manifest.json

バージョンを0.3にします。

{
	"manifest_version": 2,
	"name": "Test Extention",
	"version": "0.3",
	"browser_action": {
		"default_popup": "popup.html",
		"default_icon": "19px.png",
		"default_title": "Hello Worldを表示するよ"
	}
}

myscript.js

先ほど開いたブラウザアクションの公式ドキュメントを開きます。

Summary(概要)Methods(メソッド)という項目があります。今回は一番上にあるsetTitleを例にドキュメントを読み進めます。

setTitleの次にある以下のコードが書式です。

chrome.browserAction.setTitle(object details)

続く「Sets the title…」が解説です。「ブラウザアクションのタイトルを変更する。タイトルはボタンにマウスオーバーすると表示される。」とあります。

その下の表にはParameters(パラメーターズ)とあり、どんな引数を取るかが解説してあります。

objectとあるのでオブジェクトを指定する事がわかります。
詳細は右にある通り、titleには文字列を入力する。オプションでtabId整数を指定する。指定したtabIdでは変更を制限する。とあります。

今回は以下のようにします。

chrome.browserAction.setTitle({title: "タイトルを変更したよ"});

ここまで作成できたら機能拡張画面で0.2を削除して0.3を読み込みます。

タイトルが変更されるかテストします。まずは何もせずにアイコンにマウスオーバーします。

myscript.jsに記述したように「Hello Worldを表示するよ」と表示されています。

続いてツールバーのアイコンをクリックしてpopup.htmlを読み込みます。するとmyscript.jsも読み込まれ、タイトルが変更されます。クリック後にもう一度マウスオーバーしてみてください。

タイトルを変更したよ」に変わりました。
このように各種APIを利用すれば要素を変更したり、情報を取得することができます。


chrome.browserAction APIと、chrome.tabs APIを組み合わせて利用する

今回は複数のAPIを組み合わせて現在表示しているタブのタイトルをアラート表示します。

chrome.tabs APIは名前の通り、Chromeのtabから情報を取得したり、開いたり閉じたりといった動作を制御する際に利用します。

chrome.tabs APIの公式ドキュメント

ドキュメントに先ほどのAPIには無かったPermissionsという項目があります。このAPIを利用するにはmanifest.jsonに指定する必要があります。
サンプルがあるので簡単ですね。

manifest.json

バージョン0.3.1にしてpermissionsにtabsを追加します。

{
	"manifest_version": 2,
	"name": "Test Extention",
	"version": "0.3.1",
	"browser_action": {
		"default_popup": "popup.html",
		"default_icon": "19px.png",
		"default_title": "Hello Worldを表示するよ"
	},
	"permissions": [
		"tabs"
	]
}

myscript.js

今回はgetメソッドを利用してtabの情報を取得します。

書式

chrome.tabs.get(integer tabId, function callback)

ドキュメントにはtabIdが必要とあるので、ドキュメントを検索して現在開いているタブのIDを取得する方法を探します。
するとgetSelectedというメソッドで取得できそうだということがわかります。

しかしDeprecated since Chrome 33. Please use tabs.query {active: true}.となっており、Chromeの33以降ではtabs.queryを利用してくださいとなっています。

tabs.queryの書式は以下の通り

chrome.tabs.query(object queryInfo, function callback)

tabs.queryで情報を取得するために様々なオブジェクト「queryInfo」を指定することがわかります。

今回は現在表示しているタブのIDを取得したいので一番上のactiveを指定します。booleanとあるので真偽値で指定することがわかります。
オブジェクトなので「{}(波括弧)」で囲んで、{active: true}とします。複数のウィンドウが開いていると別のウィンドウのタブの情報を取得するためlastFocusedWindowも追加します。

複数ある場合はカンマで区切って{active: true, lastFocusedWindow: true}といった感じです。この指定はよく使うので覚えておくと便利です。

またfunction callbackの解説にはarray of Tab resultとあります。つまり配列でTabオブジェクトを取得できることがわかります。

ではmyscript.jsに以下のコードを追加してタブのIDを取得します。

chrome.tabs.query({active: true}, function(tabs) {
	var tab = tabs[0]; // 配列なので1番目の要素を指定する
	alert(tab.id);
});

再びツールバーのアイコンをクリックしてみてください。タブのIDがアラートで表示されるはずです。

このときのtabオブジェクトに何が入っているか気になると思います。そんな時はconsole.log(tab)で出力してChromeのデベロッパーツールで表示します。

ボタンを右クリックして「ポップアップを検証」をクリックします。

デベロッパーツールのウィンドウが表示されるので「Console」タブを選択、Objectという表示をクリックして展開します。

以下の様な情報が取得できることがわかります。

active: true
favIconUrl: "https://www.google.com/images/icons/product/chrome-32.png"
height: 768
highlighted: true
id: 568
incognito: false
index: 4
pinned: false
selected: true
status: "complete"
title: "chrome.tabs - Google Chrome"
url: "https://developer.chrome.com/extensions/tabs#method-query"
width: 1407
windowId: 1

公式ドキュメントにもありましたが、固定されたタブかどうかを調べるpinned、ページが読み込み中であるかどうかを調べるstatus、タブが左から何番目かを調べるindexなど、機能拡張に使えそうな面白い値があることがわかります。

では目的で合ったchrome.tabs.getIDを追加してタイトルを取得してみます。
単純に以下のように入れ子にするだけです。

chrome.tabs.query({active: true, lastFocusedWindow: true}, function(tabs) {
	var tab = tabs[0];
	chrome.tabs.get(tab.id, function(tab) {
		alert(tab.title);
	});
});

サンプルを用意したので必要な方はダウンロードしてください。
Test Extention 3をダウンロード

再びツールバーのアイコンをクリックして動作確認をします。
無事にタイトルを取得できていることがわかると思います。

ちなみにペンディングになっていたchrome.tabs.getで取得したtabオブジェクトは以下のようになっています。

active: true
favIconUrl: "https://www.google.com/images/icons/product/chrome-32.png"
height: 768
highlighted: true
id: 568
incognito: false
index: 4
pinned: false
selected: true
status: "complete"
title: "chrome.tabs - Google Chrome"
url: "https://developer.chrome.com/extensions/tabs#method-query"
width: 1407
windowId: 1

chrome.tabs.queryで取得したtabオブジェクトと同じですね。


これでmanifest.jsonpermissionsを指定するタイプのAPIの紹介。
合わせて複数のAPIの組み合わせ、デバックの方法も紹介しました。

これで機能拡張の作り方について大体の流れを理解していただけたと思います。

次の投稿では「コンテンツセキュリティポリシー」について解説します。