Chrome Extensions - Content Script
ATNDのイベント情報をGoogleカレンダーに登録するChrome Extensionsを作ってみました。
atnd2GCal
その時のメモです。
Content Script
Webページ内でJavaScriptを実行して、そのページを拡張したりする様な場合はContent Script APIを使う。(FirefoxのGreasemonkey的な感じ)
Content Scriptが出来ないこと
Content Scriptを作るに当たっては、以下の制約がある。
- クロスドメインでのXMLHttpRequestは生成出来ない
- chrome.extensionの一部を除く、chrome.* APIは仕様出来ない
- エクステンションのページで定義されている変数・関数へのアクセス
- Webページ、他のエクステンション内で定義されている変数・関数へのアクセス
Content Script本体では、ATNDのAPIからイベント情報を取得出来ないので、本体とは別にエクステンションの裏で動作するBackground Pageを作って、この中でAPIを操作する。Background Pageで取得したデータをContent Scriptに渡せばOK。
この場合、manifest.jsonの"permissions"に接続先を指定する必要がある。
manifest.json
{ ・ ・ ・ ・ "content_scripts": [ { "matches": ["http://atnd.org/*"], "css": ["style.css"], "js": ["contentscript.js"] } ], "permissions": [ "http://api.atnd.org/*" ] }
Content Script本体とBackground Pageを連携する
Content Script本体(contentscript.js)では、ATND APIからデータを取得出来ないので、Background Page(background.html)と連携する必要がある。
Background Pageと連携するには、chrome.extension APIのconnect()を呼び出す。
contentscript.js
//connectionの作成 var connection = chrome.extension.connect(); connection.onMessage.addListener(function(info, con) { console.log(info, con); }); //background pageにメッセージを送る:イベントのURL connection.postMessage({url:location.href}); //background pageからイベント情報を取得 connection.onMessage.addListener(function(info) { //Content Script本体でのデータ処理 });
background.html
/* ** Content Scriptから送信されたメッセージを受け取る */ chrome.self.onConnect.addListener(function(port, name) { port.onMessage.addListener(function(info, con) { //ATND APIからイベント情報を取得する処理 }); });
参考)第3回 Chrome Extensionsの作り方#2
contentscript.jsとbackground.htmlでメッセージの送受信の準備ができたら、background.htmlでデータを取得し、contentscript.jsへ取得したデータを渡す。
contentscript.js
/* ** バックグラウンドでイベント情報を取得する ** イベント情報を取得したらContent Script側へ渡す */ function getEventInfo(url, con) { //イベントIDを取得する var eventId = url.split('/').slice(-1).toString(); //イベント情報を取得するURLを整形する var url = 'http://api.atnd.org/events/?event_id=' + eventId + '&format=json'; var xhr = new XMLHttpRequest(); xhr.open('GET', url, false); xhr.onload = function() { console.log(xhr, xhr.responseText); var res = JSON.parse(xhr.responseText); //Content Script本体にデータを渡す con.postMessage(res); }; xhr.onerror = function() { console.log(xhr); }; xhr.send(null); }
送信したデータはcontentscript.jsの
//background pageからイベント情報を取得 connection.onMessage.addListener(function(info) { //Content Script本体でのデータ処理 });
で、受け取ることができるので、あとはContent Script本体でATNDのページを拡張していけば良い。
ハマリどころ
まず、Content Scriptでは、クロスドメインでのXMLHttpRequestが使えないこと、
manifest.jsonに"permission"を指定しなければいけないことに気付かず、大分はまりました。
色々参考にしたページ
TODO
- Autoupdating
- Googleカレンダーに遷移しっぱなしなので、なんとかする
【追記】
@matsuuさんからのアドバイス
atndはiCal出力できるので、マイページからカレンダーへ送るボタンもあるといいかも RT @MiCHiLU: RT @daigo3: atndのイベントをGoogleカレンダーに登録するchrome extensionを作りました。 >> http://ow.ly/Tlti