アーカイブ
chrome拡張の開発
1年ぶりぐらいにchrome拡張を作っているのだが、開発しやすくなっていた。ymrlとmyatsumotoに教わった。
chrome://extensions か chrome://settings/extensionSettingsを開く。

右上の「デベロッパーモード」を押して、「パッケージ化されていない拡張機能を読み込む」ボタンを押す。フォルダを拡張として読み込める。
拡張の名前に(開発中)とつく。再読み込みを押すとリロードできる。
アイコンの左側の三角をクリックすると、background.htmlへのリンクがでる。ここでjsコンソールが出せるので、console.logを使ったりしてdebugできる。
chrome extensionの作り方+クロスドメインXMLHTTPリクエストのやり方
こないだ箱根合宿で学んだ。
単にchrome拡張を作ってみたかったというのと、chromeではgreasemonkeyが実行できるけど、Firefoxと違ってGM_xmlhttpRequestが無いのでクロスドメイン通信ができないのでなんとなくやってみたかった。
自分の見ているページの履歴を全部自分のサーバーに送って保存したい。
まずos0xさんのChrome拡張入門のスライドが勉強になる。
とくに
拡張コンテキスト、コンテントコンテキスト、ページコンテキストの3つのコンテキストが存在し、それぞれは完全に分かれているので、お互いが干渉してしまうことはない。さらに、拡張同士も独立したコンテキストで実行される。
拡張コンテキストはタブ操作やクロスドメイン通信などの特権を実行でき、コンテントコンテキストと通信したり、スクリプトを実行したりといったことができます。
コンテントコンテキスト(Content Scripts)は特権を持っていませんが、読み込んだページのDOMを操作することができ、拡張コンテキストと相互に通信できます。
ページコンテキストは通常のウェブページで実行されるコンテキストで、コンテントコンテキストとはDOM経由でしかやり取りできませんし、拡張コンテキストとは完全に分断されています
のあたりが今回は重要。
で、とりあえずお勉強として、自分の見ているページのURLを http://localhost:8888/page にpostするchrome extensionを作った。ページロード時に実行される。
github.com/shokai/post_location_href_crxにソースが置いてある。
■chrome拡張のビルドのしかた
rubyを使う人にはcrxmakeというgemが便利だと思う。
chrome拡張をビルドするには、ソースのディレクトリをchromeにドラッグアンドドロップすると.crx形式に固めてくれるが、
crxmakeだとterminalからビルドできる。
post_location_href_crxの中に適当なRakefileを入れておいたので、rake一発でビルドできる。
gem install crxmakeで、packageディレクトリができてその中にビルドされた.crxファイルができる。
rake -T
rake
macだとそのまま
open package/post_location_href.crxすればchromeで開かれてインストールできるので楽だ。
■chrome拡張に必要なファイル
github.com/shokai/post_location_href_crx/tree/master/src/の中にある物が、クロスドメイン通信するのに最低限必要らしい。
src
|-- background.html
|-- icon.png
|-- icon128.png
|-- icon48.png
|-- main.css
|-- main.js
|-- manifest.json
`-- popup.html
iconを設定しておいたらchromeのツールバーに表示されるようになった

それぞれのファイル名はmanifest.jsonの中で決めている。
{
"name":"post location.href",
"description":"POST location href to http://localhost:8888/page",
"version": "0.0.2",
"background_page": "background.html",
"permissions": ["tabs" ,"http://*/*", "https://*/*"],
"browser_action": {
"default_icon": "icon.png",
"default_title": "post location.href",
"popup": "popup.html"
},
"icons": {
"128": "icon128.png",
"48": "icon48.png"
},
"content_scripts": [
{
"js": [
"main.js"
],
"css": [
"main.css"
],
"matches": [
"http://*/*",
"https://*/*",
"ftp://*/*"
],
"run_at": "document_start",
"all_frames":true
}]
}
■クロスドメイン通信のしかた
このmanifest.jsonの内容だと、main.jsがコンテントスクリプトとして最初に実行される。
main.js内の最初の方に、バックグラウンドページのコンテキストと通信するコードを書いておけば、新しいページをロードした時にコンテントスクリプト→バックグラウンドページと通信できる。バックグラウンドページではクロスドメインXMLHTTPRequestが使えるので、そこで http://localhost:8888/page に location.href を送れば自分の見た全てのサイトのURLを保存できる。
main.js
var connection = chrome.extension.connect();
connection.onMessage.addListener(function(info, con) {
console.log(info, con);
});
connection.postMessage({url:location.href});
background.html
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<title>test app</title>
<script>
var api_endpoint = "http://localhost:8888";
chrome.self.onConnect.addListener(function(port, name) {
port.onMessage.addListener(function(info, con) {
xhr = new XMLHttpRequest();
xhr.open("POST", api_endpoint+"/page", true);
xhr.setRequestHeader("Content-Type" , "application/x-www-form-urlencoded");
xhr.send("url="+encodeURIComponent(info.url));
port.postMessage({url:info.url});
});
});
</script>
</html>
受信は、sinatraとかだと適当にこうして受け取れる
require 'rubygems'
require 'sinatra'
require 'json'
post '/page' do
url = params['url']
unless url
status 403
@mes = {
:error => '"url" required'
}.to_json
else
# 適当に保存するコード
@mes = {
:url => url
}.to_json
end
end
エディタ保存したらブラウザリロードするsinatra/auto-reloadを作った
エディタを保存したらブラウザを自動リロードするsinatraプラグインを作った。
これでサブモニタにchromeとJavaScriptコンソール置いておくと幸せになれる。
ソースはgithubに。
Google ChromeもしくはFirefox+Greasemonkeyで動作する。エディタには依存しない。
sinatraアプリをローカルではなくサーバーで実行していてもリロードできる。
■インストール
sudo gem install sinatra-auto-reloadrubygems.orgに置いたので、gemコマンドでインストールできる
■使う
sinatraアプリ内で読み込む
require 'sinatra/auto-reloader' if development?if development? すると、shotgunか -e development オプションを付けて起動した時だけ有効になる。production環境には影響を与えない。
■ブラウザ拡張をインストール
localhost:4567 でアプリを起動しているとして、
http://localhost:4567/sinatra_auto_reload.user.js にgreasemonkeyスクリプトが生成される。
Firefox 3.5+Greasemonkey、もしくはChrome 5.0のuserscriptとしてインストールできる。
スクリーンショット

ホスト名ごとに違うuserscriptとしてインストールされるので、調べ物して同じブラウザで他のページを開いても大丈夫

■監視しないファイルを定義
sinatraアプリ内でauto_reload_ignoresという関数を定義しておく
def auto_reload_ignores配列内に正規表現で書いたファイルは、更新されてもリロードしない。logとかpidに反応しても困るので。
[/db.*/, /config.yaml/, /log.*/, /pid.*/]
end
ところでプラグインに変数を渡すのは、こういう方法でいいんですかね?もっとまともなやり方がある気がするんだけど。
■しくみ
sinatra/baseに新しくgetでアクセスできるページを追加し、 http://hostname:port/sinatra_auto_reload にファイルの最終更新日時が出るようにした。
これをuserscriptからsetIntervalで監視して、更新があればリロードする。
■参考
JavaScript部分はこれを参考にした
最速インターフェース研究会 :: Firefoxでの開発を高速化する自動リロードスクリプト
■オススメ
sinatra-reloader か shotgun と一緒に使うのをおすすめします
sinatraはサーバーを再起動しないとrubyのコードの変更を読み込んでくれないんだけど、こいつらを使うと毎回読み込み直してくれるようになる。
■今後
よく考えたらSub URIで動かしている場合に動かなそうだ。あとで修正する。
使ってるchrome extensions
LDRにいろいろ付ける系のgreasemonkeyはGM_系の関数がまだ実装されてないので、LDRだけはFirefoxで見ている。
テキストエリアを外部テキストエディタで開くIt’s all text相当の拡張もあったけど、server側のインストールやら起動が面倒なのでblog書くのはFirefox使う。
普段の調べ物とSBMへの投稿、twitterぐらいならこれらを入れてあれば十分。一番重要なのはTaberarelooでdeliciousとはてなブックマークとlivedoor clipにすばやくクロスポストができる事。
意外なことにchrome keyconfigにLDRizeが入っている。AdBlock+は要素の指定がなんか面倒くさい。
pbtweet、chrome FullFeed、fldr_show_fc2_images.user.jsはMacはdev版のchromeなら使える。
GM_系が一通り実装されるのと、URLバーの履歴検索がFirefoxみたいに一部一致でも利用頻度の高い順にソートされて表示されるようになればFirefoxから乗り換えられるな。
chromeのURLバーは前方一致が優先されるので、例えばりそな銀行のログインページに行きたい場合、Firefoxだと「res」まで打てば候補にすぐ出てくるが、chromeなら「ib.res」まで打ち込まないと https://ib.resonabank.co.jp/IB/0102/SC_N_0102_010.aspx が出てこない。ibとか思い出せない。「りそな→reso」なら連想できる。URLがおかしい気もするが、サービス毎にサブドメイン振っているケースはいっぱいあるし、サブドメインは覚えられない。 https://e-navi.rakuten-kc.co.jp/ava_top とか。


最近のコメント