Chrome Extensions - Content Script

ATNDのイベント情報をGoogleカレンダーに登録するChrome Extensionsを作ってみました。
atnd2GCal
20100107103236
その時のメモです。

Content Script

Webページ内でJavaScriptを実行して、そのページを拡張したりする様な場合はContent Script APIを使う。(FirefoxGreasemonkey的な感じ)

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

【追記】
@matsuuさんからのアドバイス

atndはiCal出力できるので、マイページからカレンダーへ送るボタンもあるといいかも RT @MiCHiLU: RT @daigo3: atndのイベントをGoogleカレンダーに登録するchrome extensionを作りました。 >> http://ow.ly/Tlti