Google Chrome Extensionの作り方 第1回 ~Hello World編~
Google Chrome Extensionの作り方 第2回 ~概要編~
Google Chrome Extensionの作り方 第3回 ~実践編~
今回は前々回でのHello World、前回の概要を踏まえて、
もう少し凝ったものを作ってみます。
Google Chrome Extensionの作り方 ~実践編~
実践
今回作成するもの
現在開いているウィンドウと、ウィンドウが持っているタブを一覧で表示する拡張機能です。
完成イメージ
URL横にアイコンが表示されます。
ページに関係なく表示されてほしいので、ブラウザアクションです。
アイコンをクリックすると現在開いているウィンドウの一覧と、
ウィンドウが持っているタブの一覧が表示されます。
構成ファイル
・manifest.json
・background.js
・main.html
・main.js
main.htmlに、ウィンドウとタブを表示します。
Hello Worldではポップアップに表示しましたが、今回はページに表示します。
では、manifest.jsonから作成していきます。
manifest.json
{ "manifest_version": 2, "name": "TabViewer", "version": "0.1", "description": "This extension will display all Window and all Tab.", "icons": { "16": "icons/icon_16.png", "128": "icons/icon_128.png" }, "browser_action": { "default_title": "Tab Viewer" }, "background": { "scripts": [ "jquery-2.1.3.min.js", "background.js" ], "persistent": false }, "permissions":[ "tabs" ] }
“permissions”はchrome.* APIを使用するときにほぼ必ず必要な設定です。
この拡張機能がユーザに対してアクセス権を求める項目です。
拡張機能をインストールするとき、
こんなメッセージが表示されることがあると思いますが、
“permissions”に指定した内容から、拡張機能がアクセスする権限を表示し、
ユーザに確認を促すわけです。
APIを使うときどの”permissions”を指定しなければいけないかは、
公式のAPIページに記載されています。
必要な”permissions”を指定していないと、APIを実行できないので注意です。
今回はタブに対してアクセスするので、”permissions”に”tabs”を指定します。
main.html
<!DOCTYPE html> <html> <head> <title>Tab Viewer</title> <link rel='stylesheet' type='text/css' href='main.css' media='all'> </head> <script src='jquery-2.1.3.min.js'></script> <script src='main.js'></script> <body> <div> <ul id='window_list'> <!-- テンプレート --> <li id='template' class='window_list'> <div class='window_name'> </div> <ul id='tab_list' class='tab_list'> <li id='tab-template'> <img class='favicon' /> <span class='tab_title'></span> <br /> <span class='tab_url'></span> </li> </ul> </li> </ul> </div> </body> </html>
今回のメインとなるページです。
動的に生成する要素は予めテンプレートとして配置しておき”display:none;”にしておきます。
(今回はCSSで”display:none;”にしてあります。)
こうすることで、JavaScriptで動的な要素の生成が楽になります。
main.css
#template, #tab-template { display: none; } ul { list-style: none; } /* Window一覧 */ .window_list { margin-bottom: 30px; } .window_name { margin-top: 10px; margin-bottom: 10px; padding-left: 10px; height: 30px; border-bottom: 1px solid gray; font-size: 14pt; } /* Tab一覧 */ .tab_list { padding-left: 10px; } #tab_list li { margin-bottom: 10px; } .tab_url { margin-left: 3px; color: gray; } .favicon { margin-right: 3px; width: 18px; vertical-align: middle; }
main.js
var cnt = 1; $(function (){ // テンプレート var template = document.getElementById('template'); var tabTemplate = document.getElementById('tab-template'); // Window取得 chrome.windows.getAll(null, function(windows){ for (var i=0; i<windows.length; i++) { var winId = windows[i].id; // Window.idからWindowのタブを取得 chrome.tabs.getAllInWindow(winId, function(tabs){ var winInfo = template.cloneNode(true); winInfo.removeAttribute('id'); // id削除 // タイトル部分 $(winInfo).find('.window_name').text('Window' + cnt); // Window名 cnt++; // タブ一覧 for (var j=0; j<tabs.length; j++) { var tab = tabTemplate.cloneNode(true); tab.removeAttribute('id'); // id削除 // ファビコン $(tab).find('img').attr('src', tabs[j].favIconUrl); // タブタイトル $(tab).find('.tab_title').text(tabs[j].title); // タブURL $(tab).find('.tab_url').text(tabs[j].url); // リストに追加 $(winInfo).find('#tab_list').append(tab); } $('#window_list').append(winInfo); }); } }); });
メインページのJavaScriptです。
chrome.* APIを使っています。
// テンプレート var template = document.getElementById('template'); var tabTemplate = document.getElementById('tab-template');
最初にテンプレートの要素を取得しておきます。
chrome.windows.getAll(null, function(windows){
chrome.* APIを使って全てのWindowを取得します。
取得したWindowを使って処理を行いたいので、パラメータにfunctionをセットします。
functionのパラメータの’windows’にchrome.windows.getAllの実行結果が格納されます。
for (var i=0; i<windows.length; i++) { var winId = windows[i].id; // Window.idからWindowのタブを取得 chrome.tabs.getAllInWindow(winId, function(tabs){ var winInfo = template.cloneNode(true); winInfo.removeAttribute('id'); // id削除 // タイトル部分 $(winInfo).find('.window_name').text('Window' + cnt); // Window名 cnt++; // タブ一覧 for (var j=0; j<tabs.length; j++) { var tab = tabTemplate.cloneNode(true); tab.removeAttribute('id'); // id削除 // ファビコン $(tab).find('img').attr('src', tabs[j].faviconUrl); // タブタイトル $(tab).find('.tab_title').text(tabs[j].title); // タブURL $(tab).find('.tab_url').text(tabs[j].url); // リストに追加 $(winInfo).find('#tab_list').append(tab); } $('#window_list').append(winInfo); }); }
パラメータの”windows”はWindowの配列です。
(Windowが1つしかない場合は配列ではなくただのWindowです。)
Windowは、
・id
・focused
などのプロパティがあります。
詳しくは公式を参照してください。
『chrome.windows』
https://developer.chrome.com/extensions/windows
Windowのidを
chrome.tabs.getAllInWindow(winId, function(tabs){
このように”chrome.tabs.getAllInWindow”のパラメータにセットすることで
idに一致するWindowが持つタブをfunctionの”tabs”に格納してくれます。
Tabsは
・id
・index
・active
・url
・title
・faviconUrl
などのプロパティがあります。
詳しくは公式を参照してください。
『chrome.tabs』
https://developer.chrome.com/extensions/tabs
取得したタブのタイトルやURLを要素にセットすれば、
一覧が完成します。
ここで注意すべきなのは、JavaScriptを使っている方なら意識しなくてもいいかもしれませんが、
chrome.* APIのパラメータにセットしたfunciton内の処理は全て「非同期処理」です。
これを忘れていると、エラーになったり、意図した動作と違う動作をするので注意です。
background.js
// main.htmlを新しいタブで開く var showMainPage = function() { chrome.tabs.create({ url:'main.html' }); }; (function() { chrome.browserAction.onClicked.addListener(showMainPage); }) ();
background.jsでブラウザアクションをクリックしたときのイベントを設定します。
これで準備が整いました。
作ったファイルをフォルダに格納します。
(ここでは”TabViewer”というフォルダ名にしました。)
iconを”icons”フォルダにまとめる作業もお忘れなく。
Chromeに拡張機能を登録
Hello Worldのおさらいです。
Chromeから「設定」⇒「その他ツール」⇒「拡張機能」を選択して拡張機能のページを開き、
拡張機能フォルダを読み込みます。
拡張機能を動かす
URL横にアイコンが表示されています。
クリックすると、main.htmlが開きました。
現在開いているウィンドウと、ウィンドウが持っているタブの一覧が表示されています。
以上で実践編は終了です。
お疲れ様でした。
※ソースコードは記事を参照していただくとして、アイコンのファイルだけ置いておきます⇒icons.zip
豆情報
Chromeにインストールした拡張機能のソースを見る方法です。
どのOSでもソースを見ることができると思いますが、Windows以外は自力で場所を探してください。。。
まず、拡張機能が格納されているフォルダを開きます。
Windows7:
C:\Users\[ユーザ]\AppData\Local\Google\Chrome\User Data\Default\Extensions
ランダムな文字列のフォルダが並んでいるはずです。
このフォルダ1つ1つが、インストールしている拡張機能のソースです。
次にChromeから拡張機能ページを開き、ソースを見たい拡張機能の”ID”を確認します。
(“詳細”や”オプション”のテキストリンクの下にあります。)
このIDと同じ名前のフォルダの中身が、目的の拡張機能のソースです。
Chrome ウェブストアには多くの拡張機能が公開されているので、
勉強がてらにソースを見てみるのもありです。
ただ、ソースを見ることを前提に公開しているわけではないので、
JavaScriptやCSSは圧縮されている可能性があります。
そんなときは「javascript 圧縮」などで検索して、
ソースコードに整形するツールを使いましょう。