読者です 読者をやめる 読者になる 読者になる

あんパン

こしあん以外は認めない

FirefoxOSでTwitterのStreamingAPIを扱ってみる

はじめに

こんにちはこんにちは。 FirefoxOSでTwitterができるようになって機嫌がすごく良いので記事にしちゃいます。

XHRのCrossOrigin制限について

普通、XMLHttpRequestはSameOriginじゃないとアクセスできません。TwitterAPIはcallbackがあるエンドポイントのみCORS(Cross-Origin Resource Sharing)できるようになっているのでそれについてはJavaScriptからアクセスできるのですが*1、StreamingAPIについてはこれがないためアクセスすることができません。

ですが、FirefoxOSのPrivilegedApp(権限付きアプリケーション)の場合、この制限を回避することができます。

PrivilegedAppとは?

権限付きのアプリケーションのこと。普通の(Plain)アプリケーションであればそのままFirefoxMarketplaceに並べることができますが、権限付きの場合はコードレビューの後に掲載されます。つまり、権限を与えられる代わりに審査が厳しくなるという感じです。Host型アプリケーションでは作ることができません。(もちろんSimulatorで使う分にはそんなもの関係ありません。)

manifest.webappに一行書き加えるだけでアプリケーションをprivileged appにすることができます。

"type": "privileged"

systemXHRについて

SameOrigin制限を回避するのにsystemXHRというものを使います。この権限もmanifest.webappに更に数行書き加えるだけで得ることができます。

"permissions": {
  "systemXHR": {}
}

実際にStreamingAPIにアクセスしてTimelineを取得してみる

これについてはコードを見たほうが早いかと思います。

masawada/firefoxos-streaming-test

にアクセスして右のSelect one of your Appsから自分のアプリケーションを選択します。Generate OAuth signatureをクリックして遷移した先のページ下部にあるSee OAuth signature for this requestをクリックしてAuthorization Headerのサンプルを取得します。

Authorization HeaderのOAuth oauth_consumer_key=...以降をコピーしてxhr.jsvar authorization = ''に代入します。

FirefoxOSシミュレータからmanifest.webappを指定して起動、get timelineと書いてあるリンクを押すことで自分のTimelineを読むことができるようになったかと思います。

f:id:masawada:20130624192845p:plain

コードの説明

ほぼ普通にXMLHttpRequestをまわしている感じです。二ヶ所だけ説明を入れておきます。

mozSystem

XMLHttpRequestをnewするときに少しだけ工夫が要ります。

var req = new XMLHttpRequest({mozSystem: true});

を見てもわかるとおり、mozSystem: trueを入れて初期化してあげます。

StremingAPIのデータ受け取り

StremingAPIはHTTPのコネクションをはりっぱなしにして、新規ツイートなどをそのつど送ってくるという形になります。つまり、コネクションに終わりがないのでreq.onreadystatechangereq.readyState === 3のときをみます。詳しくはコードを読んでみてください。

まとめ

ということで、少々駆け足になってしまいましたがこんな感じにStreamingAPIを読むことができます。Twitterのdiscussionに「JavaScriptじゃStreamingAPI使えないぜHAHAHA」って書いてあったのでTCP APIを使って実装しなきゃいけないのかと少し身構えましたがXHRでもちゃんと使えるということがわかりました。

これは試しにやってみただけなので考慮していませんが、StreamingAPIを使うとずっとコネクションをはりっぱなしにしてデータも保持したままになると思うので、ある程度の時間で繋ぎ直すなどの工夫は必要になるかと思います。

これを使ってTwitterクライアントでも作ってみようかと思います。

*1:試していません。要出典。