Chromeのブラウザ拡張(Extension)を作る
最近仕事関連でChrome Extensionを作ったので、ポイントとかを簡単にまとめてみる。
前提
作るもの
Extensionにはいくつかのタイプがあるが、今回は以下の様なものを作る。
- ブラウザに表示されている内容を取得
- 1で取得した内容をExtensionのJavaScriptがパース
- Extensionのポップアップを表示し、2の内容を表示
- ポップアップ上のボタンを押すと、内容がサーバーに送信される
イメージとしては、はてブとかEvernoteのブラウザ拡張を思い浮かべてもらえれば良いかと。
後述する専門用語で言うと、browser action (あるいは page action) + content script という構成。
アーキテクチャ
主な構成
まずは仕組みを理解しとくと後々楽だと思うので、簡単に説明。詳しくは、この辺をじっくり読めば大体わかるはず。
大雑把な構成要素は以下の通り。
- background page or background script: バックグラウンドでの処理とかを行う
- UI page: ポップアップとか
- content script: ブラウザに表示されているWebページの内容を扱うスクリプト
content scriptはちょっと特殊(?)なので少し説明。例えば、はてブのトップページにアクセスした時に、タイトルとはてブ数だけを一覧表示するブラウザ拡張を考える。Chromeで http://b.hatena.ne.jp/ のページを表示して、ブラウザ拡張からそのページのDOMにアクセスする必要があるが、それを行えるのはcontent scriptだけで、UI pageとbackground pageからはアクセス出来ない。
content scriptとその他のコンポーネントはメッセージをやりとりすることでデータの受け渡しを行う。
UI要素
色んなのがあるので、簡単に説明。
- Page Action: 特定のページ・サイトを開いた時だけボタンが表示されるタイプのもの。楽天サイトでのみ使えるブラウザ拡張とかはこれを使う事が多い。
- Browser Action: 基本的にどんなページでも、常にボタンが表示されるタイプ。Evernoteのブラウザ拡張みたいなのを使いたい場合はこれ。
- Context Menu: 右クリックした時に、独自のメニュー項目を追加する。
UIは色んなパターンがあるので、詳細はdeveloper guideを参照のこと。
実際の作り方
設計
上の方で書いたけど、上に書いたような専門用語を使って、もう一度簡単にまとめる。
- 特定のサイト・ページ (http://example.com/) を開いた時に、Page Action(のボタン)を有効にする。
- ページの読み込みが終わったら、Content Scriptを実行し、http://example.com/ のページの内容を読み込んでContent ScriptのJavaScriptで処理する。
- Content Script から Background Script にデータをメッセージとして送る
- Page Actionのボタンが押されたら、Popupを表示し、Background Script が保持しているデータを表示
- Popup内のボタンが押されたら、サーバーへデータを送信する
manifest.json
{ "manifest_version": 2, "name": "Example extension", "description": "", "version": "1.0", "permissions": [ ], "background": { "scripts": ["jquery-2.0.3.min.js", "background.js"] }, "page_action": { "default_icon": "icon-s.png", "default_popup": "popup.html" }, "content_scripts": [ { "matches": ["http://example.com/*"], "js": ["jquery-2.0.3.min.js", "contentscript.js"], "run_at": "document_end" } ] }
contentscript.js
ページの内容を取得して、background.jsにメッセージとしてデータを送る。
console.log('contentscript.js started'); var items = $.map($('li.some-item'), function(elem, i) { return elem.text; }); chrome.runtime.sendMessage({"items": items,}, function(response) { console.log('message sent'); });
background.js
メッセージを受け取って、データを保持するだけ。
function checkForValidUrl(tabId, changeInfo, tab) { if (tab.url.match(/http:\/\/example.com\/.*/)) { // ... show the page action. chrome.pageAction.show(tabId); } }; // URLをチェック chrome.tabs.onUpdated.addListener(checkForValidUrl); var parsedItems = []; // ここにデータを保持 function parseItem(item) { // .... parsedItems.push({'foo': bar, 'hobe': fuga}); } // メッセージを受け取った時に呼び出されるメソッドを登録 chrome.runtime.onMessage.addListener( function(request, sender, sendResponse) { parsedItems = []; for (var i in items) { parseItem(request.items[i]); } var res = 'finish'; sendResponse(res); });
popup.js
ここは、background.js からデータを受け取る以外は通常通りのプログラムでOK。
// background.js のデータを参照 var parsedItems = chrome.extension.getBackgroundPage().parsedItems; $(document).ready(function() { //... });
まとめ
HTML + JavaScriptに慣れていれば、Chrome Extensionは結構簡単に作れる。仕組みを理解することが重要。