fxosコードリーディングミートアップ#16 contacts api読んでみた
TRANSCRIPT
![Page 1: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/1.jpg)
Contacts API読んでみた
株式会社グローバルサイバーグループ
マネージャ
藪下正美
![Page 2: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/2.jpg)
はじめに
![Page 3: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/3.jpg)
自己紹介
• 藪下正美
• 株式会社グローバルサイバーグループというところから来ました
• Firefox OSコミュニティから来ました
• Codezineに記事乗りました!
– http://codezine.jp/article/detail/8540
![Page 4: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/4.jpg)
今日のおはなし
• Contacts APIとは
• 手始めにfindメソッドを追ってみる
• getAllメソッドを見てみる
• まとめ
![Page 5: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/5.jpg)
Contacts APIとは
• 使い方のおはなしは#11でやったのでslideshareとか参照
– http://www.slideshare.net/aoitan/meetup11-contacts-api
![Page 6: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/6.jpg)
手始めにFINDメソッドを追ってみる
![Page 7: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/7.jpg)
まずざっとまとめ
• パーミッションチェック
• チェックがallowならsendAsyncMessageで 'Contacts:Find' メッセージを投げる
• Parentプロセスで動いているContactsServiceが 'Contacts:Find' メッセージを受信すると
• ContactDBを検索
• ContactDBの処理が終わったらChildプロセスに 'Contacts:Find:Return:OK' か'Contacts:Find:Return:KO' メッセージを送信
• ContactsManagerがメッセージを受信してDOMRequestのsuccessイベントかerrorイベントを発火
• 間にIPCとか挟まってるけど闇が深いので省略!
• 間にIndexedDBHelperとか挟まってるけどただのプロミスラッパーなので省略!
![Page 8: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/8.jpg)
具体的なコードを見てみる(1)
• パーミッションチェック
• チェックがallowならsendAsyncMessageで 'Contacts:Find' メッセージを投げる
find: function(aOptions) {if (DEBUG) debug("find! " + JSON.stringify(aOptions));let request = this.createRequest();let options = { findOptions: aOptions };let allowCallback = function() {
cpmm.sendAsyncMessage("Contacts:Find", {requestID: this.getRequestId({
request: request,reason: "find"
}), options: options });}.bind(this)this.askPermission("find", request, allowCallback);return request;
},
![Page 9: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/9.jpg)
具体的なコードを見てみる(2)
• Chromeプロセスで動いているContactsServiceが 'Contacts:Find' メッセージを受信すると
receiveMessage: function(aMessage) {if (DEBUG) debug("receiveMessage " + aMessage.name);let mm = aMessage.target;let msg = aMessage.data;let cursorList;
switch (aMessage.name) {case "Contacts:Find":
![Page 10: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/10.jpg)
具体的なコードを見てみる(3)
• ContactDBを検索
• ContactDBの処理が終わったらChildプロセスに 'Contacts:Find:Return:OK' か'Contacts:Find:Return:KO' メッセージを送信
this._db.find(function(contacts) {
for (let i in contacts) {result.push(contacts[i]);
}if (DEBUG) debug("result:" + JSON.stringify(result));mm.sendAsyncMessage("Contacts:Find:Return:OK",
{requestID: msg.requestID, contacts: result});}.bind(this),function(aErrorMsg) {
mm.sendAsyncMessage("Contacts:Find:Return:KO", {requestID: msg.requestID,errorMsg: aErrorMsg });
}.bind(this), msg.options.findOptions);
![Page 11: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/11.jpg)
具体的なコードを見てみる(4)
• ContactsManagerがメッセージを受信してDOMRequestのsuccessイベントかerrorイベントを発火
receiveMessage: function(aMessage) {if (DEBUG) debug("receiveMessage: " + aMessage.name);let msg = aMessage.json;let contacts = msg.contacts;
let req;switch (aMessage.name) {
case "Contacts:Find:Return:OK":req = this.getRequest(msg.requestID);if (req) {
let result = this._convertContacts(contacts);Services.DOMRequest.fireSuccess(req.request, result);
} else {if (DEBUG) debug("no request stored!" + msg.requestID);
}break;
![Page 12: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/12.jpg)
GETALLメソッドを見てみる
![Page 13: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/13.jpg)
まずざっとまとめ
• パーミッションチェック
• チェックがallowならsendAsyncMessageで 'Contacts:GetAll' メッセージを投げる
• Parentプロセスで動いているContactsServiceが 'Contacts:GetAll' メッセージを受信すると
• ContactDBを検索
• ContactDBのカーソルが回るたびにChildプロセスに 'Contacts:GetALl:Next' メッセージを送信する
• 処理失敗が起きたら 'Contacts:GetAll:Return:KO' メッセージを送信
• ContactsManagerがメッセージを受信してDOMCursorのsuccessイベントかerrorイベントを発火
![Page 14: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/14.jpg)
具体的なコードを見てみる(1)
• パーミッションチェック
• チェックがallowならsendAsyncMessageで 'Contacts:GetAll' メッセージを投げる
getAll: function CM_getAll(aOptions) {if (DEBUG) debug("getAll: " + JSON.stringify(aOptions));let [cursorId, cursor] = this.createCursor();let allowCallback = function() {
cpmm.sendAsyncMessage("Contacts:GetAll", {cursorId: cursorId, findOptions: aOptions});
}.bind(this);this.askPermission("find", cursor, allowCallback);return cursor;
},
![Page 15: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/15.jpg)
具体的なコードを見てみる(2)
• Parentプロセスで動いているContactsServiceが 'Contacts:GetAll' メッセージを受信すると
receiveMessage: function(aMessage) {if (DEBUG) debug("receiveMessage " + aMessage.name);let mm = aMessage.target;let msg = aMessage.data;let cursorList;
switch (aMessage.name) {(snip)
case "Contacts:GetAll":
![Page 16: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/16.jpg)
具体的なコードを見てみる(3)
• ContactDBを検索
• ContactDBのカーソルが回るたびにChildプロセスに 'Contacts:GetALl:Next' メッセージを送信する
this._db.getAll(function(aContacts) {
try {mm.sendAsyncMessage("Contacts:GetAll:Next",
{cursorId: msg.cursorId, contacts: aContacts});if (aContacts === null) {
let cursorList = this._cursors.get(mm);let index = cursorList.indexOf(msg.cursorId);cursorList.splice(index, 1);
}} catch (e) {
if (DEBUG) debug("Child is dead, DB should stop sending contacts");throw e;
}}.bind(this),
![Page 17: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/17.jpg)
具体的なコードを見てみる(4)
• 処理失敗が起きたら 'Contacts:GetAll:Return:KO' メッセージを送信
function(aErrorMsg) {mm.sendAsyncMessage("Contacts:GetAll:Return:KO",
{ requestID: msg.cursorId, errorMsg: aErrorMsg });},msg.findOptions, msg.cursorId);
break;
![Page 18: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/18.jpg)
具体的なコードを見てみる(5)
• ContactsManagerがメッセージを受信してDOMCursorのsuccessイベントかerrorイベントを発火
case "Contacts:GetAll:Next":(snip)
this.nextTick(this._fireSuccessOrDone.bind(this, data.cursor, contact));(snip)
break;
(snip)
_fireSuccessOrDone: function(aCursor, aResult) {if (aResult == null) {
Services.DOMRequest.fireDone(aCursor);} else {
Services.DOMRequest.fireSuccess(aCursor, aResult);}
},
![Page 19: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/19.jpg)
具体的なコードを見てみる(6)
• ContactsManagerがメッセージを受信してDOMCursorのsuccessイベントかerrorイベントを発火
case "Contacts:GetAll:Return:KO":req = this.getRequest(msg.requestID);if (req) {
Services.DOMRequest.fireError(req.cursor, msg.errorMsg);}break;
![Page 20: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/20.jpg)
他のメソッド
• どうやら基本は同じ
• 多少プロパティを詰め直したりとかしてるAPIはあるけどやることはfindと同じ
• getAllだけはDOMCursorを扱う都合で多少違った
![Page 21: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/21.jpg)
まとめ
![Page 22: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/22.jpg)
ちょっと寄り道
![Page 23: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/23.jpg)
なぜsendAsyncMessageが挟まっているのか(1)
• 簡単なプロセスの図
Chrome Content
Systemアプリ Contactsアプリ
ContacsServiceContactDB
ContactsManager
![Page 24: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/24.jpg)
なぜsendAsyncMessageが挟まっているのか(2)
• こんな感じでFxOSのアプリはアプリのプロセスとシステムのプロセスがわかれている
• なので基本的に子プロセスは権限の必要な作業は親プロセスに依頼しないといけない
–非同期に動くメソッドは大体プロセス境界をまたいでいる
• そこでpostなんとかMessageやsendなんとかMessageの出番
• Gaiaで閉じているものだとiframe間の通信なのでpostMessageが使われる
• Gecko側に実体のあるものだとsendAsyncMessage
• 基本的に同じ使い勝手のもので文字列とかJSONオブジェクトしか投げられないのでコマンド文字列とかこねこねしていることが多い
![Page 25: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/25.jpg)
全体像
• 全体図
Chrome Content
ContactsService ContactsManager
ContactDB
IndexedDB
sendAsyncMessage
![Page 26: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/26.jpg)
ContentsManager
• メソッドの呼び出しを受けたらパーミッションチェックして親プロセスへのメッセージ送信
• 戻りメッセージを待ち受けてDOMRequestやDOMCursorのイベントを発火
![Page 27: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/27.jpg)
ContactsService
• 子プロセスからのメッセージを待ち受けてDB処理
– find/save/remove/clearは成功時と失敗時のコールバックを与えてDBのメソッドを呼ぶ
• コールバックの中身は子プロセスに対するsendAsyncMessage
• 成功時は元のメッセージに 'Return:OK' を付けて投げる
• 失敗時は元のメッセージに 'Return:KO' を付けて投げる
– getAllはカーソルが返るのでカーソル一つ回すごとに 'Contacts:GetAll:Next' メッセージをsendAsyncMessageで飛ばす
• sim入れ替えの監視
![Page 28: FxOSコードリーディングミートアップ#16 Contacts API読んでみた](https://reader035.vdocuments.mx/reader035/viewer/2022062304/55abe8491a28abb5678b46aa/html5/thumbnails/28.jpg)
ContactDB
• 連絡帳用のDB処理をまとめている
• 単にIndexedDBラッパー