mobile/android/modules/ContactService.jsm

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 "use strict";
     7 const DEBUG = false;
     8 function debug(s) { dump("-*- Android ContactService component: " + s + "\n"); }
    10 const Cu = Components.utils;
    11 const Cc = Components.classes;
    12 const Ci = Components.interfaces;
    14 this.EXPORTED_SYMBOLS = [];
    16 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
    17 Cu.import("resource://gre/modules/Services.jsm");
    18 Cu.import("resource://gre/modules/PhoneNumberUtils.jsm");
    20 XPCOMUtils.defineLazyServiceGetter(this, "ppmm", "@mozilla.org/parentprocessmessagemanager;1",
    21                                    "nsIMessageListenerManager");
    23 let ContactService = {
    24   init: function() {
    25     if (DEBUG) debug("Init");
    26     this._requestMessages = {};
    28     // Add listeners for all messages from ContactManager.js
    29     let messages = ["Contacts:Clear", "Contacts:Find", "Contacts:GetAll",
    30                     "Contacts:GetAll:SendNow", "Contacts:GetCount", "Contacts:GetRevision",
    31                     "Contact:Remove", "Contact:Save",];
    32     messages.forEach(function(msgName) {
    33       ppmm.addMessageListener(msgName, this);
    34     }.bind(this));
    36     // Add listeners for all messages from ContactService.java
    37     let returnMessages = ["Android:Contacts:Count",
    38                           "Android:Contacts:Clear:Return:OK", "Android:Contacts:Clear:Return:KO",
    39                           "Android:Contacts:Find:Return:OK", "Android:Contacts:Find:Return:KO",
    40                           "Android:Contacts:GetAll:Next", "Android:Contacts:RegisterForMessages",
    41                           "Android:Contact:Remove:Return:OK", "Android:Contact:Remove:Return:KO",
    42                           "Android:Contact:Save:Return:OK", "Android:Contact:Save:Return:KO",];
    44     returnMessages.forEach(function(msgName) {
    45       Services.obs.addObserver(this, msgName, false);
    46     }.bind(this));
    47   },
    49   _sendMessageToJava: function(aMsg) {
    50     Services.androidBridge.handleGeckoMessage(aMsg);
    51   },
    53   _sendReturnMessage: function(aTopic, aRequestID, aResult) {
    54     this._requestMessages[aRequestID].target.sendAsyncMessage(aTopic, aResult);
    55   },
    57   _sendAndDeleteReturnMessage: function(aTopic, aRequestID, aResult) {
    58     this._sendReturnMessage(aTopic, aRequestID, aResult)
    59     delete this._requestMessages[aRequestID];
    60   },
    62   observe: function(aSubject, aTopic, aData) {
    63     if (DEBUG) {
    64       debug("observe: subject: " + aSubject + " topic: " + aTopic + " data: " + aData);
    65     }
    67     let message = JSON.parse(aData, function date_reviver(k, v) {
    68       // The Java service sends dates as strings, so convert them to Dates before
    69       // sending them back to the child.
    70       if (v != null && v != "null" &&
    71           ["updated", "published", "anniversary", "bday"].indexOf(k) != -1) {
    72         return new Date(v);
    73       }
    74       return v;
    75     });
    76     let requestID = message.requestID;
    78     // The return message topic is the same as the current topic, but without the "Android:" prefix
    79     let returnMessageTopic = aTopic.substring(8);
    81     switch (aTopic) {
    82       case "Android:Contacts:Find:Return:OK":
    83         this._sendAndDeleteReturnMessage(returnMessageTopic, requestID, {requestID: requestID, contacts: message.contacts});
    84         break;
    86       case "Android:Contacts:Find:Return:KO":
    87         this._sendAndDeleteReturnMessage(returnMessageTopic, requestID, {requestID: requestID});
    88         break;
    90       case "Android:Contact:Save:Return:OK":
    91         this._sendReturnMessage(returnMessageTopic, requestID, {requestID: requestID, contactID: message.contactID});
    92         this._sendAndDeleteReturnMessage("Contact:Changed", requestID, {contactID: message.contactID, reason: message.reason});
    93         break;
    95       case "Android:Contact:Save:Return:KO":
    96         this._sendAndDeleteReturnMessage(returnMessageTopic, requestID, {requestID: requestID});
    97         break;
    99       case "Android:Contact:Remove:Return:OK":
   100         this._sendReturnMessage(returnMessageTopic, requestID, {requestID: requestID, contactID: message.contactID});
   101         this._sendAndDeleteReturnMessage("Contact:Changed", requestID, {contactID: message.contactID, reason: "remove"});
   102         break;
   104       case "Android:Contact:Remove:Return:KO":
   105         this._sendAndDeleteReturnMessage(returnMessageTopic, requestID, {requestID: requestID});
   106         break;
   108       case "Android:Contacts:Clear:Return:OK":
   109         this._sendReturnMessage(returnMessageTopic, requestID, {requestID: requestID});
   110         this._sendAndDeleteReturnMessage("Contact:Changed", requestID, {reason: "remove"});
   111         break;
   113       case "Android:Contact:Clear:Return:KO":
   114         this._sendAndDeleteReturnMessage(returnMessageTopic, requestID, {requestID: requestID});
   115         break;
   117       case "Android:Contacts:GetAll:Next":
   118         // GetAll uses a cursor ID instead of a request ID. Translate the request ID back to the cursor ID
   119         this._sendReturnMessage(returnMessageTopic, requestID, {cursorId: requestID, contacts: message.contacts});
   121         // Send a message with no contacts to denote the end of contacts returned by the query
   122         this._sendAndDeleteReturnMessage(returnMessageTopic, requestID, {cursorId: requestID});
   123         break;
   125       case "Android:Contacts:Count":
   126         this._sendAndDeleteReturnMessage(returnMessageTopic, requestID, {requestID: requestID, count: message.count});
   127         break;
   129       default:
   130         throw "Wrong message received: " + aTopic;
   131     }
   132   },
   134   assertPermission: function(aMessage, aPerm) {
   135     if (!aMessage.target.assertPermission(aPerm)) {
   136       Cu.reportError("Contacts message " + aMessage.name +
   137                      " from a content process with no" + aPerm + " privileges.");
   138       return false;
   139     }
   140     return true;
   141   },
   143   receiveMessage: function(aMessage) {
   144     if (DEBUG) debug("receiveMessage " + aMessage.name);
   146     // GetAll uses a cursor ID instead of a request ID, but they can be treated the same from here
   147     if (!aMessage.data.requestID && aMessage.data.cursorId) {
   148       aMessage.data.requestID = aMessage.data.cursorId;
   149     }
   150     let requestID = aMessage.data.requestID;
   152     // Store the message so it the request callback can be called when the Java side is finished
   153     this._requestMessages[requestID] = aMessage;
   155     switch (aMessage.name) {
   156       case "Contacts:Find":
   157         this.findContacts(aMessage);
   158         break;
   160       case "Contacts:GetAll":
   161         this.getAllContacts(aMessage);
   162         break;
   164       case "Contacts:GetAll:SendNow":
   165         // Send an empty message to denote there are no most contacts for the getAll query
   166         this._sendAndDeleteReturnMessage("Contacts:GetAll:Next", requestID, {cursorId: requestID});
   167         break;
   169       case "Contact:Save":
   170         this.saveContact(aMessage);
   171         break;
   173       case "Contact:Remove":
   174         this.removeContact(aMessage);
   175         break;
   177       case "Contacts:Clear":
   178         this.clearContacts(aMessage);
   179         break;
   181       case "Contacts:GetCount":
   182         this.getContactsCount(aMessage);
   183         break;
   185       case "Contacts:GetRevision":
   186         // Android does not support the get revision function
   187         this._sendAndDeleteReturnMessage("Contacts:GetRevision:Return:KO", requestID, {requestID: requestID,
   188                                           errorMsg: "Android does not support the revision function."});
   189         break;
   191       case "Contacts:RegisterForMessages":
   192         delete this._requestMessages[requestID];
   193         break;
   195       default:
   196         delete this._requestMessages[requestID];
   197         throw "Wrong message received: " + aMessage.name;
   198     }
   199   },
   201   findContacts: function(aMessage) {
   202     if (!this.assertPermission(aMessage, "contacts-read")) {
   203       return;
   204     }
   206     let countryName = PhoneNumberUtils.getCountryName();
   207     let substringmatchingPref = "dom.phonenumber.substringmatching." + countryName;
   208     let substringmatchingValue = 0;
   209     if (Services.prefs.getPrefType(substringmatchingPref) == Ci.nsIPrefBranch.PREF_INT) {
   210       substringmatchingValue = Services.prefs.getIntPref(substringmatchingPref);
   211     }
   213     // Add the substring matching value to the find options JSON
   214     aMessage.data.options.findOptions.substringMatching = substringmatchingValue;
   216     this._sendMessageToJava({type: "Android:Contacts:Find", data: aMessage.data});
   217   },
   219   getAllContacts: function(aMessage) {
   220     if (!this.assertPermission(aMessage, "contacts-read")) {
   221       return;
   222     }
   224     this._sendMessageToJava({type: "Android:Contacts:GetAll", data: aMessage.data});
   225   },
   227   saveContact: function(aMessage) {
   228     if ((aMessage.data.options.reason === "create" &&
   229         !this.assertPermission(aMessage, "contacts-create")) ||
   230         !this.assertPermission(aMessage, "contacts-write")) {
   231         return;
   232     }
   234     this._sendMessageToJava({type: "Android:Contact:Save", data: aMessage.data});
   235   },
   237   removeContact: function(aMessage) {
   238     if (!this.assertPermission(aMessage, "contacts-write")) {
   239       return;
   240     }
   242     this._sendMessageToJava({type: "Android:Contact:Remove", data: aMessage.data});
   243   },
   245   clearContacts: function(aMessage) {
   246     if (!this.assertPermission(aMessage, "contacts-write")) {
   247       return;
   248     }
   250     this._sendMessageToJava({type: "Android:Contacts:Clear", data: aMessage.data});
   251   },
   253   getContactsCount: function(aMessage) {
   254     if (!this.assertPermission(aMessage, "contacts-read")) {
   255       return;
   256     }
   258     this._sendMessageToJava({type: "Android:Contacts:GetCount", data: aMessage.data});
   259   },
   260 }
   262 ContactService.init();

mercurial