--- a/mobile/Makefile.in
+++ b/mobile/Makefile.in
@@ -38,17 +38,17 @@
DEPTH = ..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
-DIRS = chrome locales components themes app
+DIRS = chrome locales components modules themes app
ifndef LIBXUL_SDK
PARALLEL_DIRS += $(DEPTH)/xulrunner/tools/redit
endif
ifdef WINCE
DIRS += installer/wince
endif
--- a/mobile/chrome/content/browser-ui.js
+++ b/mobile/chrome/content/browser-ui.js
@@ -44,16 +44,21 @@ XPCOMUtils.defineLazyGetter(this, "Plura
return PluralForm;
});
XPCOMUtils.defineLazyGetter(this, "PlacesUtils", function() {
Cu.import("resource://gre/modules/PlacesUtils.jsm");
return PlacesUtils;
});
+XPCOMUtils.defineLazyGetter(this, "Contacts", function() {
+ Cu.import("resource:///modules/contacts.jsm");
+ return Contacts;
+});
+
const TOOLBARSTATE_LOADING = 1;
const TOOLBARSTATE_LOADED = 2;
[
[
"gHistSvc",
"@mozilla.org/browser/nav-history-service;1",
[Ci.nsINavHistoryService, Ci.nsIBrowserHistory]
@@ -395,16 +400,18 @@ var BrowserUI = {
ConsoleView.init();
// Init the sync system
WeaveGlue.init();
});
FormHelperUI.init();
FindHelperUI.init();
+
+ Contacts.init();
},
uninit: function() {
ExtensionsView.uninit();
ConsoleView.uninit();
},
update: function(aState) {
@@ -1674,17 +1681,17 @@ var FormHelperUI = {
/** Retrieve the autocomplete list from the autocomplete service for an element */
_getAutocompleteSuggestions: function _formHelperGetAutocompleteSuggestions(aElement) {
if (!aElement.isAutocomplete)
return [];
let suggestions = [];
let autocompleteService = Cc["@mozilla.org/satchel/form-autocomplete;1"].getService(Ci.nsIFormAutoComplete);
- let results = autocompleteService.autoCompleteSearch(aElement.name, aElement.value, aElement, null);
+ let results = autocompleteService.autoCompleteSearch(aElement.name, aElement.value, null, null);
if (results.matchCount > 0) {
for (let i = 0; i < results.matchCount; i++) {
let value = results.getValueAt(i);
suggestions.push(value);
}
}
return suggestions;
--- a/mobile/chrome/tests/Makefile.in
+++ b/mobile/chrome/tests/Makefile.in
@@ -56,16 +56,17 @@ include $(topsrcdir)/config/rules.mk
browser_rect.js \
browser_click_content.js \
browser_forms.js \
remote_forms.js \
browser_viewport.js \
browser_navigation.js \
browser_preferences_basic.js \
browser_sessionstore.js \
+ browser_contacts.js \
browser_blank_01.html \
browser_blank_02.html \
browser_select.html \
browser_click_content.html \
browser_forms.html \
browser_viewport_00.html \
browser_viewport_01.html \
browser_viewport_02.html \
new file mode 100644
--- /dev/null
+++ b/mobile/chrome/tests/browser_contacts.js
@@ -0,0 +1,54 @@
+
+// pull in the Contacts service
+Components.utils.import("resource:///modules/contacts.jsm");
+
+function test() {
+ ok(Contacts, "Contacts class exists");
+ for (var fname in tests) {
+ tests[fname]();
+ }
+}
+
+let MockContactsProvider = {
+ getContacts: function() {
+ let contacts = [
+ {
+ fullName: "-Billy One",
+ emails: [],
+ phoneNumbers: ["999-888-7777"]
+ },
+ {
+ fullName: "-Billy Two",
+ emails: ["billy.two@fake.com", "btwo@work.com"],
+ phoneNumbers: ["111-222-3333", "123-123-1234"]
+ },
+ {
+ fullName: "-Joe Schmo",
+ emails: ["joeschmo@foo.com"],
+ phoneNumbers: ["555-555-5555"]
+ }
+ ];
+
+ return contacts;
+ }
+};
+
+Contacts.addProvider(MockContactsProvider);
+
+let fac = Cc["@mozilla.org/satchel/form-autocomplete;1"].getService(Ci.nsIFormAutoComplete);
+
+let tests = {
+ testBasicMatch: function() {
+ let results = fac.autoCompleteSearch("email", "-Billy", null, null);
+ ok(results.matchCount == 2, "Found 2 emails '-Billy'");
+
+ results = fac.autoCompleteSearch("tel", "-Billy", null, null);
+ ok(results.matchCount == 3, "Found 3 phone numbers '-Billy'");
+
+ results = fac.autoCompleteSearch("skip", "-Billy", null, null);
+ ok(results.matchCount == 0, "Found nothing for a non-contact field");
+
+ results = fac.autoCompleteSearch("phone", "-Jo", null, null);
+ ok(results.matchCount == 1, "Found 1 phone number '-Jo'");
+ }
+};
new file mode 100644
--- /dev/null
+++ b/mobile/components/FormAutoComplete.js
@@ -0,0 +1,171 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Form Autocomplete Plus.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Finkle <mfinkle@mozilla.com>
+ * Dan Mills <thunder@mozilla.com>
+ * Justin Dolske <dolske@mozilla.com>
+ * Michael Hanson <mhanson@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+function LOG() {
+ return; // comment out for verbose debugging
+ let msg = Array.join(arguments, " ");
+ dump(msg + "\n");
+ Cu.reportError(msg);
+}
+
+// Lazily get the base Form AutoComplete Search
+XPCOMUtils.defineLazyGetter(this, "FAC", function() {
+ return Components.classesByID["{c11c21b2-71c9-4f87-a0f8-5e13f50495fd}"]
+ .getService(Ci.nsIFormAutoComplete);
+});
+
+XPCOMUtils.defineLazyGetter(this, "Contacts", function() {
+ Cu.import("resource:///modules/contacts.jsm");
+ return Contacts;
+});
+
+function FormAutoComplete() {
+ LOG("new FAC");
+}
+
+FormAutoComplete.prototype = {
+ classDescription: "Form AutoComplete Plus",
+ classID: Components.ID("{cccd414c-3ec2-4cc5-9dc4-36c87cc3c4fe}"),
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIFormAutoComplete]),
+
+ // Specify the html5 types that we want and some values to guess
+ contactTypes: {
+ email: /^(?:.*(?:e-?mail|recipients?).*|(send_)?to(_b?cc)?)$/i,
+ tel: /^(?:tel(?:ephone)?|.*phone.*)$/i
+ },
+
+ checkQueryType: function checkQueryType(aName, aField) {
+ // If we have an input field with the desired html5 type, take it!
+ if (aField != null) {
+ let type = aField.getAttribute("type");
+ if (this.contactTypes[type] != null)
+ return type;
+ }
+
+ // Grab attributes to check for contact inputs
+ let props = [aName];
+ if (aField != null) {
+ let attributes = ["class", "id", "rel"];
+ attributes.forEach(function(attr) {
+ if (aField.hasAttribute(attr))
+ props.push(aField.getAttribute(attr));
+ });
+ }
+
+ // Check the gathered properties for contact-like values
+ for (let [type, regex] in Iterator(this.contactTypes)) {
+ if (props.some(function(prop) prop.search(regex) != -1))
+ return type;
+ }
+ return null;
+ },
+
+ findContact: function findContact(aQuery, aType, aResult, aDupCheck) {
+ // Match the name and show the email for now..
+ Contacts.find({ fullName: aQuery }).forEach(function(contact) {
+ // Might not have an email for some reason... ?
+ try {
+ LOG("findContact", "Contact " + contact.fullName);
+
+ let suggestions;
+ switch (aType) {
+ case "email":
+ suggestions = contact.emails;
+ break;
+ case "tel":
+ suggestions = contact.phoneNumbers;
+ break;
+ default:
+ LOG("unknown type!", aType);
+ return;
+ }
+
+ for each (let suggestion in suggestions) {
+ if (aDupCheck[suggestion])
+ continue;
+ aDupCheck[suggestion] = true;
+
+ let data = contact.fullName + " <" + suggestion + ">";
+ aResult.appendMatch(suggestion, data, null, "contact");
+ }
+ }
+ catch(ex) {
+ LOG("findContact error", ex);
+ }
+ });
+ },
+
+ autoCompleteSearch: function autoCompleteSearch(aName, aQuery, aField, aPrev) {
+ LOG("autocomplete search", Array.slice(arguments));
+
+ let result = Cc["@mozilla.org/autocomplete/simple-result;1"].createInstance(Ci.nsIAutoCompleteSimpleResult);
+ result.setSearchString(aQuery);
+
+ // Don't allow duplicates get merged into the final results
+ let dupCheck = {};
+
+ // Use the base form autocomplete for non-contact searches
+ let normal = FAC.autoCompleteSearch(aName, aQuery, aField, aPrev);
+ if (normal.matchCount > 0) {
+ for (let i = 0; i < normal.matchCount; i++) {
+ dupCheck[normal.getValueAt(i)] = true;
+ result.appendMatch(normal.getValueAt(i), normal.getCommentAt(i), normal.getImageAt(i), normal.getStyleAt(i));
+ }
+ }
+
+ // Do searches for certain input fields
+ let type = this.checkQueryType(aName, aField);
+ if (type != null)
+ this.findContact(aQuery, type, result, dupCheck);
+
+ let resultCode = result.matchCount ? "RESULT_SUCCESS" : "RESULT_NOMATCH";
+ result.setSearchResult(Ci.nsIAutoCompleteResult[resultCode]);
+ return result;
+ }
+};
+
+let components = [FormAutoComplete];
+const NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
--- a/mobile/components/Makefile.in
+++ b/mobile/components/Makefile.in
@@ -65,14 +65,15 @@ EXTRA_COMPONENTS = \
XPIDialogService.js \
DownloadManagerUI.js \
HelperAppDialog.js \
PromptService.js \
BrowserCLH.js \
ContentDispatchChooser.js \
AutoCompleteCache.js \
AddonUpdateService.js \
+ FormAutoComplete.js \
$(NULL)
DIRS = phone \
$(NULL)
include $(topsrcdir)/config/rules.mk
--- a/mobile/components/MobileComponents.manifest
+++ b/mobile/components/MobileComponents.manifest
@@ -77,8 +77,12 @@ contract @mozilla.org/autocomplete/searc
component {f570982e-4f15-48ab-b6a0-ed851ac551b2} AutoCompleteCache.js
contract @mozilla.org/browser/autocomplete-observer;1 {f570982e-4f15-48ab-b6a0-ed851ac551b2}
category bookmark-observers BrowserBookmarkObserver @mozilla.org/browser/autocomplete-observer;1
# AddonUpdateService.js
component {93c8824c-9b87-45ae-bc90-5b82a1e4d877} AddonUpdateService.js
contract @mozilla.org/browser/addon-update-service;1 {93c8824c-9b87-45ae-bc90-5b82a1e4d877}
category update-timer AddonUpdateService @mozilla.org/browser/addon-update-service;1,getService,auto-addon-background-update-timer,extensions.autoupdate.interval,86400
+
+# FormAutoComplete.js
+component {cccd414c-3ec2-4cc5-9dc4-36c87cc3c4fe} FormAutoComplete.js
+contract @mozilla.org/satchel/form-autocomplete;1 {cccd414c-3ec2-4cc5-9dc4-36c87cc3c4fe}
--- a/mobile/makefiles.sh
+++ b/mobile/makefiles.sh
@@ -42,16 +42,17 @@ toolkit/locales/Makefile
security/manager/locales/Makefile
mobile/app/Makefile
$MOZ_BRANDING_DIRECTORY/Makefile
$MOZ_BRANDING_DIRECTORY/locales/Makefile
mobile/chrome/Makefile
mobile/chrome/tests/Makefile
mobile/components/Makefile
mobile/components/phone/Makefile
+mobile/modules/Makefile
mobile/installer/Makefile
mobile/locales/Makefile
mobile/Makefile
mobile/themes/Makefile
mobile/themes/core/Makefile"
if test -n "$MOZ_UPDATE_PACKAGING"; then
add_makefiles "
new file mode 100644
--- /dev/null
+++ b/mobile/modules/Makefile.in
@@ -0,0 +1,53 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Mobile Browser.
+#
+# The Initial Developer of the Original Code is
+# the Mozilla Foundation <http://www.mozilla.org/>.
+# Portions created by the Initial Developer are Copyright (C) 2010
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Finkle <mfinkle@mozilla.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+EXTRA_JS_MODULES = \
+ linuxTypes.jsm \
+ $(NULL)
+
+EXTRA_PP_JS_MODULES = \
+ contacts.jsm \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/mobile/modules/contacts.jsm
@@ -0,0 +1,154 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Mobile Browser.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Finkle <mfinkle@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+let EXPORTED_SYMBOLS = ["Contacts"];
+
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/ctypes.jsm");
+
+let Contacts = {
+ _providers: [],
+ _contacts: [],
+
+ _load: function _load() {
+ this._contacts = [];
+
+ this._providers.forEach(function(provider) {
+ this._contacts = this._contacts.concat(provider.getContacts());
+ }, this)
+ },
+
+ init: function init() {
+ // Not much to do for now
+ this._load();
+ },
+
+ refresh: function refresh() {
+ // Pretty simple for now
+ this._load();
+ },
+
+ addProvider: function(aProvider) {
+ this._providers.push(aProvider);
+ this.refresh();
+ },
+
+ find: function find(aMatch) {
+ let results = [];
+
+ if (!this._contacts.length)
+ return results;
+
+ for (let field in aMatch) {
+ // Simple string-only partial matching
+ let match = aMatch[field];
+ this._contacts.forEach(function(aContact) {
+ if (field in aContact && aContact[field].indexOf(match) != -1)
+ results.push(aContact);
+ });
+ }
+ return results;
+ }
+};
+
+#ifdef XP_UNIX
+Cu.import("resource:///modules/linuxTypes.jsm");
+
+function EBookProvider() {
+ EBook.init();
+}
+
+EBookProvider.prototype = {
+ getContacts: function() {
+ if (!EBook.lib) {
+ Cu.reportError("EBook not loaded")
+ return [];
+ }
+
+ let gError = new GLib.GError.ptr;
+ let book = EBook.openSystem(gError.address());
+ if (!book) {
+ Cu.reportError("EBook.openSystem: " + gError.contents.message.readString())
+ return [];
+ }
+
+ if (!EBook.openBook(book, false, gError.address())) {
+ Cu.reportError("EBook.openBook: " + gError.contents.message.readString())
+ return [];
+ }
+
+ let query = EBook.queryAnyFieldContains("");
+ if (query) {
+ let gList = new GLib.GList.ptr();
+ if (!EBook.getContacts(book, query, gList.address(), gError.address())) {
+ Cu.reportError("EBook.getContacts: " + gError.contents.message.readString())
+ return [];
+ }
+
+ let contacts = [];
+ while (gList && !gList.isNull()) {
+ let fullName = EBook.getContactField(gList.contents.data, EBook.E_CONTACT_FULL_NAME);
+ if (!fullName.isNull()) {
+ let contact = {};
+ contact.fullName = fullName.readString();
+ contact.emails = [];
+ contact.phoneNumbers = [];
+
+ for (let emailIndex=EBook.E_CONTACT_EMAIL_FIRST; emailIndex<=EBook.E_CONTACT_EMAIL_LAST; emailIndex++) {
+ let email = EBook.getContactField(gList.contents.data, emailIndex);
+ if (!email.isNull())
+ contact.emails.push(email.readString());
+ }
+
+ for (let phoneIndex=EBook.E_CONTACT_PHONE_FIRST; phoneIndex<=EBook.E_CONTACT_PHONE_LAST; phoneIndex++) {
+ let phone = EBook.getContactField(gList.contents.data, phoneIndex);
+ if (!phone.isNull())
+ contact.phoneNumbers.push(phone.readString());
+ }
+
+ contacts.push(contact);
+ }
+ gList = ctypes.cast(gList.contents.next, GLib.GList.ptr);
+ }
+ return contacts;
+ }
+ return [];
+ }
+};
+
+Contacts.addProvider(new EBookProvider);
+#endif
new file mode 100644
--- /dev/null
+++ b/mobile/modules/linuxTypes.jsm
@@ -0,0 +1,116 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Mobile Browser.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Finkle <mfinkle@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+let EXPORTED_SYMBOLS = ["GLib", "EBook"];
+
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/ctypes.jsm");
+
+let GLib = {
+ lib: null,
+
+ init: function glib_init() {
+ if (this.lib)
+ return;
+
+ this.lib = true; // TODO hook up the real glib
+
+ this.GError = new ctypes.StructType("GError", [
+ {"domain": ctypes.int32_t},
+ {"code": ctypes.int32_t},
+ {"message": ctypes.char.ptr}
+ ]);
+
+ this.GList = new ctypes.StructType("GList", [
+ {"data": ctypes.voidptr_t},
+ {"next": ctypes.voidptr_t},
+ {"prev": ctypes.voidptr_t}
+ ]);
+ }
+};
+
+let EBook = {
+ lib: null,
+
+ E_CONTACT_FULL_NAME: 4,
+ E_CONTACT_EMAIL_1: 8,
+ E_CONTACT_EMAIL_2: 9,
+ E_CONTACT_EMAIL_3: 10,
+ E_CONTACT_EMAIL_4: 11,
+ E_CONTACT_PHONE_BUSINESS: 17,
+ E_CONTACT_PHONE_BUSINESS_2: 18,
+ E_CONTACT_PHONE_HOME: 23,
+ E_CONTACT_PHONE_HOME_2: 24,
+ E_CONTACT_PHONE_MOBILE: 27,
+
+ E_CONTACT_EMAIL_FIRST: 8,
+ E_CONTACT_EMAIL_LAST: 11,
+ E_CONTACT_PHONE_FIRST: 16,
+ E_CONTACT_PHONE_LAST: 34,
+
+ init: function ebook_init() {
+ if (this.lib)
+ return;
+
+ GLib.init();
+
+ try {
+ // Shipping on N900
+ this.lib = ctypes.open("libebook-1.2.so.5");
+ } catch (e) {
+ try {
+ // Shipping on Ubuntu
+ this.lib = ctypes.open("libebook-1.2.so.9");
+ } catch (e) {
+ Cu.reportError("EBook: couldn't load libebook:\n" + e)
+ this.lib = null;
+ return;
+ }
+ }
+
+ this.EBook = new ctypes.StructType("EBook");
+ this.EQuery = new ctypes.StructType("EQuery");
+
+ this.openSystem = this.lib.declare("e_book_new_system_addressbook", ctypes.default_abi, EBook.EBook.ptr, GLib.GError.ptr.ptr);
+ this.openBook = this.lib.declare("e_book_open", ctypes.default_abi, ctypes.bool, EBook.EBook.ptr, ctypes.bool, GLib.GError.ptr.ptr);
+
+ this.queryAnyFieldContains = this.lib.declare("e_book_query_any_field_contains", ctypes.default_abi, EBook.EQuery.ptr, ctypes.char.ptr);
+
+ this.getContacts = this.lib.declare("e_book_get_contacts", ctypes.default_abi, ctypes.bool, EBook.EBook.ptr, EBook.EQuery.ptr, GLib.GList.ptr.ptr, GLib.GError.ptr.ptr);
+ this.getContactField = this.lib.declare("e_contact_get_const", ctypes.default_abi, ctypes.char.ptr, ctypes.voidptr_t, ctypes.uint32_t);
+ }
+};