Chrome Extensionで社内メールを「いいね~」したい(第2回)
前口上
1ヶ月振り3回目の稲村です。前回のエントリ『Chrome Extensionで社内メールを「いいね~」したい(第1回)』の続きです。
今回のエントリの部分を作ったのは1ヶ月近く前で、注意点などはだいたい忘れてしまいました。心より恥じる。
なお、せっかく社内用の自作ツールで好きに作るのだからという事で、JavaScriptの代わりにCoffeeScriptで書いています。と言っても、書こうとするコードが単純な事と、私のCoffeeScriptレベルが相まって、JavaScriptが読める人なら見て分かるレベルになっています。
Gmailの画面に「いいね~」ボタンを埋め込む
Chrome Extensionにおける表示中ページの操作
Chrome Extensionで「表示中のページの内容を操作する」のは、Content Scriptsという技術を使います。
簡単に言うと、extensionで用意したJavaScrriptを表示中のページで動かす技術です。無条件に動かせる訳ではなく、上記ページに書いてある通り何点か制約もありますが、今回実現したい「メールを表示している画面をパースして、特定部分にボタンとJSを埋め込む」という処理は、つまりHTMLの走査+DOMの挿入だけなので、この制約に引っかからずストレートに書けます。
なおストレートに書く以外に何があるかというと、extension内の他のページとメッセージングによってやり取りする事で、Content Scriptでは制限されているchromeのAPIを使う、といった手法があります。
Gmailのメールスレッド画面にボタンを埋め込む
「いいね~」ボタンは各メールについて表示する必要があります。具体的には、Gmailはメールをスレッドにまとめて表示するので、その中の各メールのヘッダ部分(差出人、件名などが表示されている部分)に表示します。
まずは、メールスレッドを開いた時に処理を起動する必要があります。前回一言書いたように、jQueryを使います。
最初は$(window).load()や$(window).ready()を使ってみたのですが、無念な事に希望したタイミングで起動する事が出来ませんでした(具体的にどうNGだったかは忘れました…)。GmailはAjaxが流行る発端になっただけあって(?)Ajax処理が激しいので「読み込み終わった」とか言ってもそう単純にいかないようです。
早速暗礁に乗り上げかと思いきや、次に試したhashchangeイベントで無事動作させる事が出来ました。
// Coffee Script
$(window).bind 'hashchange', (event) =>
URLを見たところ、メールスレッドを開いた際は"#mbox"(受信箱)→"#mbox/123456789xxxxxx"(メールスレッド)のように、間に"/"が入るようですので、その存在をもってメールスレッド画面とみなす事にします(社内ツールは気楽ですね)。
if location.hash.indexOf '/' > -1
次に、「いいね~」ボタンに必要な以下の情報を取得します。
frame = $('#canvas_frame').contents()
from = frame.find('.gD')
from_email = from.email()
subject = frame.find('.hP').text()
sent_at = frame.find('.g3').attr 'title'
また自分(Gmailの画面を開いているユーザ)のメアドを取得する必要があります。これは本来認証して取得しないと簡単に詐称できちゃったりしますが、社内用かつ試作中という事で、画面から取る事にしました。危険ですので、良い子のみんなは真似しないで下さい。
me = frame.find('a[href="//google.com/profiles"]').text()
あとはボタンを埋め込むだけです。見栄えは置いておいて、とりあえず★マークを「いいね~ボタン」として埋め込みます。
like_button = $('<a href="#">★</a>')
like_button.on 'click mousedown', (event) =>
# ここでAjaxリクエスト送信
false
from.after like_button
まとめると以下です(ログ出力を追加しています)
$(window).bind 'hashchange', (event) =>
if location.hash.indexOf '/' > -1
frame = $('#canvas_frame').contents()
from = frame.find('.gD')
from_email = from.attr 'email'
subject = frame.find('.hP').text()
sent_at = frame.find('.g3').attr 'title'
me = frame.find('a[href="//google.com/profiles"]').text()
console.log "me: #{me}"
console.log "subject: #{subject}"
console.log "from: #{from_email}"
console.log "sent_at: #{sent_at}"
like_button = $('<a href="#">★</a>')
like_button.on 'click mousedown', (event) =>
# ここでAjaxリクエスト送信
false
from.after like_button
さて、これをcoffeeコマンドでコンパイルした後、Chrome Extensionを動かしてみます。
…ただし、これはスレッド内にメールが1通ならば良いですが、2通以上になると当然ながら全て先頭のメールの情報となってしまう為、修正が必要です。
が、今回は時間の関係上ここまでとして、次回続きを書きたいと思います。

