39
# Contacts API 読んでみた 株式会社グローバルサイバーグループ マネージャ 藪下 正美

Meetup11 contacts api読んでみた

Embed Size (px)

Citation preview

Page 1: Meetup11 contacts api読んでみた

# Contacts API読んでみた

株式会社グローバルサイバーグループ

マネージャ

藪下 正美

Page 2: Meetup11 contacts api読んでみた

# はじめに

Page 3: Meetup11 contacts api読んでみた

## 自己紹介

• 藪下 正美

• 組み込み系の会社でスマホ作ってる人

• OSとかコンパイラとかの理屈が好きでいつの間にか数学基礎論とか形式言語とか形式手法とか論理学とかに足を踏み入れてしまった人

• 最近アカデミック分が足りてなくてモヤモヤしてるのでTaPLとかSICPとかそこらへんの読書会をやりたがっている

Page 4: Meetup11 contacts api読んでみた

## 会社紹介

• 株式会社グローバルサイバーグループ– http://www.gcg.bz

• 関西出身の組み込み系ソフトハウス• 勉強会支援やってます。会議室借りたい、プロジェクタ借り

たい、登壇してほしいなど気軽にご相談ください。– http://www.gcg.bz/labo_blog/?page_id=943

• 質問受け付けてます。ブログネタください。– http://www.gcg.bz/labo_blog/?page_id=945

• 本日の懇親会は株式会社グローバルサイバーグループの支援を受けています。

Page 5: Meetup11 contacts api読んでみた

## 今日のアジェンダ

• Contacts APIとは• Firefox OSの連絡帳アプリから使い方を見てみる

– 連絡先の保存– 連絡先の検索– 連絡先の全件取得– 連絡先の削除

• Contacts APIの実装のお話– Contacts APIの概要図– Contacts APIの流れ– Contacts APIのDBエントリデータ構造

• 資料書いてみたら前半がすごい長くなっちゃったのでAPIの実装の話は後日やります

Page 6: Meetup11 contacts api読んでみた

## 今日のコードリーディングに使ったソースコード

• 今回のコードリーディングはちょっと古いソースですが以下のURLのを使ってます

– http://reading.fxos.org/source/

Page 7: Meetup11 contacts api読んでみた

# Contacts APIとは

• Contacts APIは連絡先情報を扱うAPIです

• Gaiaでは連絡帳アプリやSMSアプリで使われます

– ざっくりと保存、読み込み、更新、削除のインターフェイスを備えています

Page 8: Meetup11 contacts api読んでみた

# Firefox OSの連絡帳アプリから使い方を見てみる

• もともと自作のアプリで使うための調べものですがせっかくなのでコードリーディングしてみましょう

• 今回のターゲットはContacts APIなので連絡帳アプリから読んでみます

– B2G/apps/communications/contacts

Page 9: Meetup11 contacts api読んでみた

## パーミッション

• まずはパーミッションです

• パーミッションのリストはMDNで見てください

– https://developer.mozilla.org/ja/Apps/App_permissions

Page 10: Meetup11 contacts api読んでみた

### Gaiaの連絡帳アプリのパーミッション

• B2G/gaia/apps/communications/manifest.webapp

"name": "Communications","description": "Gaia Communications","type": "certified","launch_path": "/",

:(snip)

:"permissions": {

:(snip)

:"contacts":{ "access": "readwrite" },

:(snip)

:},

Page 11: Meetup11 contacts api読んでみた

## Contacts APIのパーミッション

• apps/communications配下はいくつかのアプリを含んでいるので沢山パーミッションがありますがキモはここです

• B2G/gaia/apps/communications/manifest.webapp"contacts":{ "access": "readwrite" },

• 見たままContacts APIのパーミッションです• 連絡帳アプリでは読み書きどちらも要求しています

– SMSアプリなどでは読み込みだけ要求しています– 他にも初期設定アプリが読み書き、メールや電話アプリは読み込み

のみで使ってます

"contacts":{ "access": "readwrite" },

Page 12: Meetup11 contacts api読んでみた

### Gaiaの連絡帳アプリの特権

• もうひとつここも勘所です

• B2G/gaia/apps/communications/manifest.webapp

"type": "certified",

• これはアプリ特権の設定です• Gaiaで定義されているプリインアプリなのでcertifiedが設定

されています• ユーザ定義のアプリだとここはprivilegedを使うことになり

ます

Page 13: Meetup11 contacts api読んでみた

### パーミッションまとめ

• Contacts APIを使用する際はpermissions属性にcontacts属性の設定が必要です

– contacts属性にはaccess属性を設定します

– access属性にはreadonlyあるいはreadwriteを設定します

• 特権が必要なのでtype属性にprivilegedかcertifiedの設定が必要です

– privilegedの場合プロンプトが出ます

Page 14: Meetup11 contacts api読んでみた

## 連絡先の保存

• 連絡先の保存を見ていきます

• MDNの解説は以下を見てください

– https://developer.mozilla.org/en-US/docs/Web/API/Contacts_API#Adding_a_contact

Page 15: Meetup11 contacts api読んでみた

### 保存処理

• B2G/gaia/apps/communications/contacts/js/export/sim.js

var _updateContactSimSource = function _updateContactSimSource(theContact,iccContact, cb, errorCb) {

if (!iccContact) {window.console.warn('No Icc Contact provided');cb();return;

}

theContact.url = theContact.url || [];theContact.url.push(_generateIccContactUrl(iccContact.id, _getIccId()));var req = navigator.mozContacts.save(theContact);req.onsuccess = cb;req.onerror = function() {

errorCb(req.error);};

};

Page 16: Meetup11 contacts api読んでみた

### 保存APIの呼び出し

• Contacts APIを使ってるのはここですね

• B2G/gaia/apps/communications/contacts/js/export/sim.js

theContact.url = theContact.url || [];theContact.url.push(_generateIccContactUrl(iccContact.id, _getIccId()));var req = navigator.mozContacts.save(theContact);req.onsuccess = cb;req.onerror = function() {

errorCb(req.error);};

• 連絡先情報を渡してDOMRequestを受け取っているだけのシンプルな呼び出しですね• reqという変数に返り値を受けてonsuccessとonerrorを設定しているこの形はWebAPIの基本形の

一つです– 処理に時間のかかるAPIやchromeプロセスに処理を要求するAPIにはDOMRequestやその派生オブジェクトを返す

ものがたくさんあります– DOMRequestは非同期に動作するAPIの処理終了イベントを表すオブジェクトです

Page 17: Meetup11 contacts api読んでみた

### 保存APIの引数

• 保存APIに渡されているオブジェクトがどんな値を持っているか見ていきます

Page 18: Meetup11 contacts api読んでみた

#### mozContacts.saveの使用個所からさかのぼる1

• まず_updateContactSimSourceのtheContact出所を確認します• 結論から言うとここから追うのははずれだったので細かくソースコードは見せませ

ContactsSIMExport._updateContactSimSourct (theContact)->ContactsSIMExport._doExport (contacts[step]、contactsはContactsSIMExportのプロパティ)->ContactsSIMExport.setContactsToExport (引数のctsがcontactsに設定さ

れる)->ContactsExporter._start (contacts、ContactsExporterのプロパティ)->ContactsExporter._init (theContacts、連絡先IDの配列)

• ここで引数の連絡先IDを持つ連絡先データを配列にしています• ですが連絡先データの出所がmozContacts.find()で取ってきた値なので使ってい

るシーンがなくて残念な感じですね

Page 19: Meetup11 contacts api読んでみた

#### mozContacts.saveの使用個所からさかのぼる2

• 別の使用個所から追います

• B2G/gaia/apps/communications/contacts/js/views/details.js

var request =navigator.mozContacts.save(utils.misc.toMozContact(contact));

• utils.misc.toMozContactで連絡先情報を作っているようなので中身を見てみると

• B2G/gaia/shared/js/contacts/import/utilities/misc.js

utils.misc.toMozContact = function(contact) {var outContact = contact;if (!(contact instanceof mozContact)) {outContact = new mozContact(contact);outContact.id = contact.id || outContact.id;

}return outContact;

};

• new mozContactが連絡先情報みたいですね

Page 20: Meetup11 contacts api読んでみた

#### 連絡先情報オブジェクト

• mozContact何者? と思ったらwebidlを探しに行くのがお作法ですよね!

• B2G/gecko/dom/webidl/Contacts.webidl

[Constructor(optional ContactProperties properties),JSImplementation="@mozilla.org/contact;1"]interface mozContact {

attribute DOMString id;readonly attribute Date? published;readonly attribute Date? updated;

attribute Date? bday;attribute Date? anniversary;

attribute DOMString? sex;attribute DOMString? genderIdentity;

Page 21: Meetup11 contacts api読んでみた

[Cached, Pure] attribute sequence<Blob>? photo;

[Cached, Pure] attribute sequence<ContactAddress>? adr;

[Cached, Pure] attribute sequence<ContactField>? email;[Cached, Pure] attribute sequence<ContactField>? url;[Cached, Pure] attribute sequence<ContactField>? impp;

[Cached, Pure] attribute sequence<ContactTelField>? tel;

Page 22: Meetup11 contacts api読んでみた

[Cached, Pure] attribute sequence<DOMString>? name;[Cached, Pure] attribute sequence<DOMString>? honorificPrefix;[Cached, Pure] attribute sequence<DOMString>? givenName;[Cached, Pure] attribute sequence<DOMString>? phoneticGivenName;[Cached, Pure] attribute sequence<DOMString>? additionalName;[Cached, Pure] attribute sequence<DOMString>? familyName;[Cached, Pure] attribute sequence<DOMString>? phoneticFamilyName;[Cached, Pure] attribute sequence<DOMString>? honorificSuffix;[Cached, Pure] attribute sequence<DOMString>? nickname;[Cached, Pure] attribute sequence<DOMString>? category;[Cached, Pure] attribute sequence<DOMString>? org;[Cached, Pure] attribute sequence<DOMString>? jobTitle;[Cached, Pure] attribute sequence<DOMString>? note;[Cached, Pure] attribute sequence<DOMString>? key;

Page 23: Meetup11 contacts api読んでみた

void init(optional ContactProperties properties);

[ChromeOnly]void setMetadata(DOMString id, Date? published, Date? updated);

jsonifier;};

Page 24: Meetup11 contacts api読んでみた

• メンバが多くておぢさんびっくりなんじゃよ。。。

• プロパティ全部説明するの大変なのでMDNペタリ– https://developer.mozilla.org/en-US/docs/Web/API/mozContact

• ざっくり言うと名前とか読み仮名とか電番とかメアドとかURLとかまあもろもろの配列が持てます

• 性別とは別にセクシャルアイデンティティが設定できて地味に細やかで面白いですね

• idがreadonlyではないのは既存の連絡先を更新する際に使うからです– 既存のIDを設定したmozContactオブジェクトを保存すると置き換えら

れます

Page 25: Meetup11 contacts api読んでみた

### 連絡先の保存まとめ

• 連絡先の保存はnavigator.mozContacts.save()で行います

– mozContacts.save()の引数はmozContactオブジェクトです

– mozContacts.save()の返り値はDOMRequestオブジェクトです

• mozContactオブジェクトプロパティ多い。。。

– webidl見慣れてない人はMDNの以下のページを参照してください

– https://developer.mozilla.org/en-US/docs/Mozilla/WebIDL_bindings

– webidlは変更多いので英語版をこまめに追いかけたほうがいいです(翻訳サボってサーセンw)

Page 26: Meetup11 contacts api読んでみた

## 連絡先の検索

• 次は連絡先の検索を見てみます

• 連絡先を探すのに使えるメソッドは二つあるのでそれぞれ見ていきます

Page 27: Meetup11 contacts api読んでみた

• まずは条件を指定する場合を見ていきます

• B2G/gaia/apps/communications/contacts/js/views/list.jsvar getContactById = function(contactID, successCb, errorCb) {(snip)var options = {

filterBy: ['id'],filterOp: 'equals',filterValue: contactID

};var request = navigator.mozContacts.find(options);request.onsuccess = function findCallback(e) {

var result = e.target.result[0];

if (!fb.isFbContact(result)) {successCb(result);return;

}

var fbContact = new fb.Contact(result);var fbReq = fbContact.getData();fbReq.onsuccess = function() {

successCb(result, fbReq.result);};fbReq.onerror = successCb.bind(null, result);

}; // request.onsuccess

if (typeof errorCb === 'function') {request.onerror = errorCb;

}};

### 検索API

Page 28: Meetup11 contacts api読んでみた

### 検索APIの呼び出し

• 肝心なところだけ見ましょう

• B2G/gaia/apps/communications/contacts/js/views/list.js

var options = {filterBy: ['id'],filterOp: 'equals',filterValue: contactID

};var request = navigator.mozContacts.find(options);

request.onsuccess = function findCallback(e) {:

(snip):

}; // request.onsuccess

if (typeof errorCb === 'function') {request.onerror = errorCb;

}

• mozContacts.saveでも見覚えある形ですね• mozContacts.findもDOMRequestを返します

Page 29: Meetup11 contacts api読んでみた

### 全件取得API

• すべての連絡先を取得するAPIを見てみましょう

• B2G/gaia/apps/communications/contacts/js/views/list.js

initConfiguration(function onInitConfiguration() {var sortBy = (orderByLastName === true ? 'familyName' : 'givenName');var options = {sortBy: sortBy,sortOrder: 'ascending‘

};var cursor = navigator.mozContacts.getAll(options);(snip)var contact = evt.target.result;if (contact) {

(snip)cursor.continue();(snip)

}};cursor.onerror = errorCb;

});

Page 30: Meetup11 contacts api読んでみた

### 全件取得APIの呼び出し

• 全件取得のAPIを使っているのはここです

var cursor = navigator.mozContacts.getAll(options);:

(snip):

cursor.onsuccess = function onsuccess(evt) {:

(snip):

var contact = evt.target.result;if (contact) {

:(snip)

:cursor.continue();

} else {:

(snip):

}};cursor.onerror = errorCb;

Page 31: Meetup11 contacts api読んでみた

### 全件取得APIの呼び出し

• これまでのAPIと少し違ってDOMCursorを返してます• DOMRequestのようにonsuccessとonerrorを設定しているのに

加えてcontinueメソッドの呼び出しをしているこの形は複数の値を返すAPIの基本形です– 複数の値を返すAPIではDOMCursorやその派生オブジェクトを返すもの

がたくさんあります

• DOMCursorは複数の値を返すAPIの反復子を表すオブジェクトです– continueメソッドが呼ばれた上でメソッドを抜けると次のオブジェクト

を引数に再度イベントが発行されます– 引数のオブジェクトがnullの場合そのイテレーションが終端に達したとい

うことです

Page 32: Meetup11 contacts api読んでみた

### 検索APIの引数

• mozContacts.findとmozContacts.getAllは検索オプションを引数に取ることができます• ただしmozContacts.getAllはソート条件のみ設定可能です

• B2G/gecko/dom/webidl/Contacts.webidl

dictionary ContactFindSortOptions {DOMString sortBy; // "givenName" or "familyName“DOMString sortOrder = "ascending"; // e.g. "descending“

};

dictionary ContactFindOptions : ContactFindSortOptions {DOMString filterValue; // e.g. "Tom“DOMString filterOp; // e.g. "startsWith“any filterBy; // e.g. ["givenName", "nickname"]unsigned long filterLimit = 0;

};

Page 33: Meetup11 contacts api読んでみた

### 検索APIのまとめ

• 絞り込んでの検索はnavigator.mozContacts.find()で行います– mozContacts.find()の引数はContactFindOptionsです– mozContacts.find()の返り値はDOMRequestオブジェクトです– DOMRequestオブジェクトのresultはmozContactオブジェクト

の配列です

• 全件取得はnavigator.mozContacts.getAll()で行います– mozContacts.getAll()の引数はContactFindSortOptionsです– mozContacts.getAll()の返り値はDOMCursorオブジェクトです– DOMCursorオブジェクトのresultはmozContactオブジェクトで

Page 34: Meetup11 contacts api読んでみた

## 連絡先の削除

• 最後に連絡帳の削除を見ましょう

Page 35: Meetup11 contacts api読んでみた

### 削除API

• B2G/gaia/apps/communications/contacts/js/contacts_remover.js

function deleteContact(currentID) {var request;var outreq = {onSuccess: null, onError: null};var contact = new mozContact();contact.id = currentID;

if (fbData[contact.id]) {var fbContact = new fb.Contact(fbData[contact.id]);request = fbContact.remove();

} else {request = navigator.mozContacts.remove(contact);

}request.onsuccess = function() {outreq.onSuccess();

};request.onerror = function() {outreq.onError();

};return outreq;

}

Page 36: Meetup11 contacts api読んでみた

### 削除APIの呼び出し

• 削除APIの呼び出しだけ見ると

• B2G/gaia/apps/communications/contacts/js/contacts_remover.js

var contact = new mozContact();contact.id = currentID;

if (fbData[contact.id]) {var fbContact = new fb.Contact(fbData[contact.id]);request = fbContact.remove();

} else {request = navigator.mozContacts.remove(contact);

}request.onsuccess = function() {outreq.onSuccess();

};request.onerror = function() {outreq.onError();

};

こんな感じですもう見慣れた形のDOMRequestを返すタイプのAPIでした

Page 37: Meetup11 contacts api読んでみた

### 削除APIの引数

• mozContacts.removeはmozContactオブジェクトを引数に取ります

• B2G/gaia/apps/communications/contacts/js/contacts_remover.js

var contact = new mozContact();contact.id = currentID;

• このやりかたを見るにIDだけあればいいようです

Page 38: Meetup11 contacts api読んでみた

### 削除APIのまとめ

• 削除はnavigator.mozContacts.remove()で行います

– mozContacts.remove()の引数はmozContactです

– mozContacts.remove()の返り値はDOMRequestです

Page 39: Meetup11 contacts api読んでみた

# さいごに

• ちょっと予定と違って中身の説明ができませんでしたがblogかどこかの勉強会でやるのでこうご期待

• といってもContacts APIの実装は素直なのでほかのAPIも一緒にやるかも? Notification APIなんかが近い構造なので一緒にやる可能性高いかも?

• なんかこれ聞いてみたいっていうのがあったら質問箱へどうぞー

– http://www.gcg.bz/labo_blog/?page_id=945