Firefox OS Bluetooth API の翻訳(と試行錯誤)

このエントリは MDNやFirefox OSのドキュメントをみんなで翻訳! Advent Calendar 2015 の 21 日目 です。

Bluetoothマネージャと設定操作に必要な Setting API あたりを翻訳してみました。
初めての翻訳作業でしたが、初日のUemmra3さんの投稿などを参考にさせていただきながら、色々悩みつつも楽しんで作業しました。

訳したのはこのあたり↓です。
BluetoothManager (Firefox OS)
デバイス設定の利用

基本自分は締め切りに終われないと動かない(動けない)人なので、ウィキペディアとか自主的に書いてる人本当にすごいなあと思います。

今回もそうなんですが、作業開始からある地点を超えると、どんどん作業速度が増してくるんですよ。で、そのスピードに乗れると、今度は作業そのものが楽しくなってきて、気がつくと時間を忘れて没頭してたりするんです。
(ただしその地点をいつ越えられるかが分からないので、それまでは終わりの見えない悶絶タイムが続くわけですが)

今回 Firefox OS の bluetooth まわりを翻訳してみようと思ったきっかけは、Firefox OSで bluetooth がらみのアプリを作りたいなとのほほんと思いついたからなんですが、名乗りを上げてからよくよく調べてみると、bluetooth 関連のAPIは認定アプリ(内部アプリとか公認アプリとか呼ばれていたりもします)に属するAPIで、セキュリティの観点から通信事業者やOEM事業者、つまりプリインストールされるアプリにのみその利用を限定されてたんですね。

どおりでテストプログラム書いて BluetoothManager オブジェクトとか取得しても null 返ってくるわけですよ・・・

ドキュメントちゃんと読めって感じです。訳して下さった方ごめんなさい。というか翻訳作業者が何やってるんだって感じですが。

で、そもそも触れないAPI翻訳したって仕方ないじゃないの、とやさぐれてたんですが、久しぶりに引っ張り出してきた Firefox Flame の開発者メニューを眺めてたらこんな項目を見つけて釘付けに。

flame_unlock_privilages

何この危険そうな感じの素敵なスイッチ。押してみよう。

2015-12-22-02-37-14

セキュリティを解除した上にデータまで削除。
たぶんよい子は押しちゃいけないやつです。でも押す。

2015-12-22-02-37-23

この画面のあとボタンを10回押すとFASTBOOTの画面が表示され、本当に真っ新な状態でデバイスが起動しました。

期待をこめて、Bluetooth Managerを取得してコンソールに出力するだけの簡単なコードを実行してみます。

// Bluetooth Manager 取得
bluetooth = window.navigator.mozBluetooth;
console.info("mozBluetooth", bluetooth);
console.info("BluetoothManager.enabled", bluetooth.enabled);

すると・・・

console_log

ちゃんとオブジェクト返ってきてます!成功です!!

・・・と、思ったんですが、よく見るとたった一つしかない .enabled プロパティが取れていません。(涙)
.getAdapters() メソッドも叩いて見たのですが、やはりこちらも空っぽの配列が返ってくるだけ。
つまりオブジェクトが取れただけで、あとは何もできないんです。

Firefox WebIDE は認定アプリのデバッグは正式にサポートしていないし、そもそもコンソールのデバッグにも限界を感じ始めました。そこでない知恵を絞って色々考えてながら調べてゆくと、Android SDK にバンドルされている Android Monitor が使えそうだということに。

Android Monitor | Android Developers

ええもう翻訳時間よりデバッグ時間の方が長くなってます。

実は BluetoothManager は、マネージャーと言いつつも Bluetooth アダプタの取得と bluetooth の有効/無効の監視くらいしかできなかったりします。割と守備範囲の狭い子なんです。

そこで Settings API を使って Bluetooth の状態変更を任意に発生させ、イベント発生を拾えないかテストしてみました。

新たに追記した Setting API はこれだけです。

// Setting API の取得と lock オブジェクト作成
var settings = window.navigator.mozSettings;
var lock    = settings.createLock();

// 設定取得
var setting = lock.get('bluetooth.enabled');
setting.onsuccess = function () {
    console.log('setting.result', setting.result);
};
setting.onerror = function () {
    console.warn('setting.error', setting.error);
};
// 設定変更
var result = lock.set({
    'bluetooth.enabled': true
});
result.onsuccess = function () {
    console.log("bluetooth settings has been changed");
};
result.onerror = function () {
    console.log("An error occure, the bluetooth settings remain unchanged");
};
console.info("result", result);

その実行結果がこちら。
(読みにくくてすみません)

12-22 00:17:01.346: I/BlueToothTest(5221): Content JS INFO: mozBluetooth [object BluetoothManager] 
12-22 00:17:01.356: I/BlueToothTest(5221): Content JS INFO: BluetoothManager.enabled  
12-22 00:17:01.676: I/BlueToothTest(5221): Content JS LOG: bluetooth settings has been changed 
12-22 00:17:01.746: I/GeckoDump(2449): [system] [SettingsCore][2851.691] observing settings bluetooth.enabled changed to true
12-22 00:17:01.746: I/GeckoDump(2449): [system] [AirplaneModeServiceHelper][2851.694] observing bluetooth.enabled : true
12-22 00:17:01.746: I/GeckoDump(2449): [system] [AirplaneModeServiceHelper][2851.695] observer for bluetooth.enabled found, invoking.
12-22 00:17:01.746: I/GeckoDump(2449): [system] [AirplaneModeServiceHelper][2851.696] unsuspending: bluetooth.suspended
12-22 00:17:01.746: I/GeckoDump(2449): [system] [AirplaneModeServiceHelper][2851.696] writing {"bluetooth.suspended":false} to settings db
12-22 00:17:01.746: I/GeckoDump(2449): [system] [SettingsCore][2851.697] writing {"bluetooth.suspended":false} to settings db.
12-22 00:17:01.796: I/GeckoDump(2449): [system] [SettingsCore][2851.741] observing settings bluetooth.suspended changed to false
12-22 00:17:01.796: I/GeckoDump(2449): [system] [AirplaneModeServiceHelper][2851.741] observing bluetooth.suspended : false

ログを見る限りでは Setting API で Bluetooth の有効に成功しているし、実際 Setting API の .onsuccess() コールバック関数では設定変更のイベントも取得できているんですが、肝心の BluetoothManager が設定の変更を検知してくれないんです。

そもそも .enabled プロパティは相変わらず null だし、そもそもあるはずの Bluetooth アダプタが返ってこないのもおかしい。

もはやソースコードを確認するしかない。
他のプラットフォームなら多分諦めてますが、こんな時ソースコードがJavascriptで書かれているのが有難いです。

githubを彷徨って、多分これが BluetoothManager のソースコードだと思われる箇所を発見。

gaia/apps/bluetooth/js/modules/bluetooth/bluetooth_adapter_manager.js

しかし .enable プロパティが定義されていない。あれ?間違えた?
ここで初期化された後どこかで追加されるとか。いや、そんな追いにくいコード書くかなぁ。
システム構造の基本知識がないから判断に迷うところです。こんな事なら Firefox OSのコードリーディングに参加しておくんだった・・・

gaia/apps/system/js/bluetooth_v2.js

あれ、bluetooth_v2.js なんてソースコードがあるぞ?
こっちには .enabled が定義されてる。ひょっとして flame に入れた OS のバージョンが古い?いやいや Latest master builds なんですけど・・・。

と、色々試行錯誤しているうちに時間切れになってしまいました。
ここまで読んで下さった人、本当に申し訳ない。でもありがとうございます。

今回の経験を通じて問題解決のための手数が増えたので、一応得るものはあったのですが、やっぱり解決にたどり着けなかったのは悔しいです・・・というか気になって仕方がないです。

あと後半は脱線気味でしたが、自分はやはり bluetooth まわりを習得したいです。
でも頑張って作っても自分の開発端末でしか動かせない、配布できないというのは寂しいです。

なのでもし将来的にはマーケットのレビュープロセスで配布可能になったり、カメラAPIのように低い権限レベルでも利用可能になると嬉しいです。Mozillaの偉いひと、お願いします。そんな未来がやってくるならデバッグにも身が入ります(笑)