зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound.
This commit is contained in:
Коммит
88f55b543c
|
@ -415,7 +415,7 @@ UpdatePrompt.prototype = {
|
|||
// for the user to press Later or Install Now. In this situation we
|
||||
// don't want to clear this._update, becuase handleApplyPromptResult
|
||||
// needs it.
|
||||
if (this._applyPromptTimer == null) {
|
||||
if (this._applyPromptTimer == null && !this._waitingForIdle) {
|
||||
this._update = null;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -20,10 +20,16 @@ XPCOMUtils.defineLazyGetter(Services, "DOMRequest", function() {
|
|||
return Cc["@mozilla.org/dom/dom-request-service;1"].getService(Ci.nsIDOMRequestService);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "pm",
|
||||
"@mozilla.org/permissionmanager;1",
|
||||
"nsIPermissionManager");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
||||
"@mozilla.org/childprocessmessagemanager;1",
|
||||
"nsIMessageSender");
|
||||
|
||||
const CONTACTS_SENDMORE_MINIMUM = 5;
|
||||
|
||||
function stringOrBust(aObj) {
|
||||
if (typeof aObj != "string") {
|
||||
if (DEBUG) debug("Field is not a string and was ignored.");
|
||||
|
@ -559,6 +565,15 @@ ContactManager.prototype = {
|
|||
access = "unknown";
|
||||
}
|
||||
|
||||
// Shortcut for ALLOW_ACTION so we avoid a parent roundtrip
|
||||
let type = "contacts-" + access;
|
||||
let permValue =
|
||||
pm.testExactPermissionFromPrincipal(this._window.document.nodePrincipal, type);
|
||||
if (permValue == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
aAllowCallback();
|
||||
return;
|
||||
}
|
||||
|
||||
let requestID = this.getRequestId({
|
||||
request: aRequest,
|
||||
allow: function() {
|
||||
|
@ -684,6 +699,9 @@ ContactManager.prototype = {
|
|||
if (DEBUG) debug("contact in cache");
|
||||
let contact = data.cachedContacts.shift();
|
||||
this.nextTick(this._fireSuccessOrDone.bind(this, data.cursor, contact));
|
||||
if (data.cachedContacts.length < CONTACTS_SENDMORE_MINIMUM) {
|
||||
cpmm.sendAsyncMessage("Contacts:GetAll:SendNow", { cursorId: aCursorId });
|
||||
}
|
||||
} else {
|
||||
if (DEBUG) debug("waiting for contact");
|
||||
data.waitingForNext = true;
|
||||
|
|
|
@ -23,6 +23,64 @@ const DB_VERSION = 8;
|
|||
const STORE_NAME = "contacts";
|
||||
const SAVED_GETALL_STORE_NAME = "getallcache";
|
||||
const CHUNK_SIZE = 20;
|
||||
const CHUNK_INTERVAL = 500;
|
||||
|
||||
function ContactDispatcher(aContacts, aFullContacts, aCallback, aNewTxn, aClearDispatcher) {
|
||||
this.nextIndex = 0;
|
||||
|
||||
this.cancelTimeout = function() {
|
||||
if (this.interval) {
|
||||
clearTimeout(this.interval);
|
||||
this.interval = null;
|
||||
}
|
||||
};
|
||||
|
||||
if (aFullContacts) {
|
||||
this.sendChunk = function() {
|
||||
if (aContacts.length > 0) {
|
||||
aCallback(aContacts.splice(0, CHUNK_SIZE));
|
||||
this.interval = setTimeout(this.sendChunk, CHUNK_INTERVAL);
|
||||
} else {
|
||||
aCallback(null);
|
||||
this.cancelTimeout();
|
||||
aClearDispatcher();
|
||||
}
|
||||
}.bind(this);
|
||||
} else {
|
||||
this.count = 0;
|
||||
this.sendChunk = function() {
|
||||
let chunk = [];
|
||||
aNewTxn("readonly", STORE_NAME, function(txn, store) {
|
||||
for (let i = this.nextIndex; i < Math.min(this.nextIndex+CHUNK_SIZE, aContacts.length); ++i) {
|
||||
store.get(aContacts[i]).onsuccess = function(e) {
|
||||
chunk.push(e.target.result);
|
||||
this.count++;
|
||||
if (this.count == aContacts.length) {
|
||||
aCallback(chunk)
|
||||
aCallback(null);
|
||||
this.cancelTimeout();
|
||||
aClearDispatcher();
|
||||
} else if (chunk.length == CHUNK_SIZE) {
|
||||
aCallback(chunk);
|
||||
chunk.length = 0;
|
||||
this.nextIndex += CHUNK_SIZE;
|
||||
this.interval = setTimeout(this.sendChunk, CHUNK_INTERVAL);
|
||||
}
|
||||
}.bind(this);
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
this.sendChunk(0);
|
||||
}
|
||||
|
||||
ContactDispatcher.prototype = {
|
||||
sendNow: function() {
|
||||
this.cancelTimeout();
|
||||
this.interval = setTimeout(this.sendChunk, 0);
|
||||
}
|
||||
};
|
||||
|
||||
this.ContactDB = function ContactDB(aGlobal) {
|
||||
if (DEBUG) debug("Constructor");
|
||||
|
@ -32,6 +90,8 @@ this.ContactDB = function ContactDB(aGlobal) {
|
|||
ContactDB.prototype = {
|
||||
__proto__: IndexedDBHelper.prototype,
|
||||
|
||||
_dispatcher: {},
|
||||
|
||||
upgradeSchema: function upgradeSchema(aTransaction, aDb, aOldVersion, aNewVersion) {
|
||||
if (DEBUG) debug("upgrade schema from: " + aOldVersion + " to " + aNewVersion + " called!");
|
||||
let db = aDb;
|
||||
|
@ -513,45 +573,31 @@ ContactDB.prototype = {
|
|||
}.bind(this));
|
||||
},
|
||||
|
||||
getAll: function CDB_getAll(aSuccessCb, aFailureCb, aOptions) {
|
||||
sendNow: function CDB_sendNow(aCursorId) {
|
||||
if (aCursorId in this._dispatcher) {
|
||||
this._dispatcher[aCursorId].sendNow();
|
||||
}
|
||||
},
|
||||
|
||||
_clearDispatcher: function CDB_clearDispatcher(aCursorId) {
|
||||
if (aCursorId in this._dispatcher) {
|
||||
delete this._dispatcher[aCursorId];
|
||||
}
|
||||
},
|
||||
|
||||
getAll: function CDB_getAll(aSuccessCb, aFailureCb, aOptions, aCursorId) {
|
||||
if (DEBUG) debug("getAll")
|
||||
let optionStr = JSON.stringify(aOptions);
|
||||
this.getCacheForQuery(optionStr, function(aCachedResults, aFullContacts) {
|
||||
// aFullContacts is true if the cache didn't exist and had to be created.
|
||||
// In that case, we receive the full contacts since we already have them
|
||||
// in memory to create the cache anyway. This allows us to avoid accessing
|
||||
// the main object store again.
|
||||
// in memory to create the cache. This allows us to avoid accessing the
|
||||
// object store again.
|
||||
if (aCachedResults && aCachedResults.length > 0) {
|
||||
if (DEBUG) debug("query returned " + aCachedResults.length + " contacts");
|
||||
if (aFullContacts) {
|
||||
if (DEBUG) debug("full contacts: " + aCachedResults.length);
|
||||
while(aCachedResults.length) {
|
||||
aSuccessCb(aCachedResults.splice(0, CHUNK_SIZE));
|
||||
}
|
||||
aSuccessCb(null);
|
||||
} else {
|
||||
let count = 0;
|
||||
let sendChunk = function(start) {
|
||||
let chunk = [];
|
||||
this.newTxn("readonly", STORE_NAME, function(txn, store) {
|
||||
for (let i = start; i < Math.min(start+CHUNK_SIZE, aCachedResults.length); ++i) {
|
||||
store.get(aCachedResults[i]).onsuccess = function(e) {
|
||||
chunk.push(e.target.result);
|
||||
count++;
|
||||
if (count == aCachedResults.length) {
|
||||
aSuccessCb(chunk);
|
||||
aSuccessCb(null);
|
||||
} else if (chunk.length == CHUNK_SIZE) {
|
||||
aSuccessCb(chunk);
|
||||
chunk.length = 0;
|
||||
setTimeout(sendChunk.bind(this, start+CHUNK_SIZE), 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}.bind(this);
|
||||
sendChunk(0);
|
||||
}
|
||||
let newTxnFn = this.newTxn.bind(this);
|
||||
let clearDispatcherFn = this._clearDispatcher.bind(this, aCursorId);
|
||||
this._dispatcher[aCursorId] = new ContactDispatcher(aCachedResults, aFullContacts,
|
||||
aSuccessCb, newTxnFn, clearDispatcherFn);
|
||||
} else { // no contacts
|
||||
if (DEBUG) debug("query returned no contacts");
|
||||
aSuccessCb(null);
|
||||
|
|
|
@ -39,7 +39,8 @@ let myGlobal = this;
|
|||
let ContactService = {
|
||||
init: function() {
|
||||
if (DEBUG) debug("Init");
|
||||
this._messages = ["Contacts:Find", "Contacts:GetAll", "Contacts:Clear", "Contact:Save",
|
||||
this._messages = ["Contacts:Find", "Contacts:GetAll", "Contacts:GetAll:SendNow",
|
||||
"Contacts:Clear", "Contact:Save",
|
||||
"Contact:Remove", "Contacts:GetSimContacts",
|
||||
"Contacts:RegisterForMessages", "child-process-shutdown"];
|
||||
this._children = [];
|
||||
|
@ -116,7 +117,12 @@ let ContactService = {
|
|||
mm.sendAsyncMessage("Contacts:GetAll:Next", {cursorId: msg.cursorId, contacts: aContacts});
|
||||
},
|
||||
function(aErrorMsg) { mm.sendAsyncMessage("Contacts:Find:Return:KO", { errorMsg: aErrorMsg }); },
|
||||
msg.findOptions);
|
||||
msg.findOptions, msg.cursorId);
|
||||
break;
|
||||
case "Contacts:GetAll:SendNow":
|
||||
// sendNow is a no op if there isn't an existing cursor in the DB, so we
|
||||
// don't need to assert the permission again.
|
||||
this._db.sendNow(msg.cursorId);
|
||||
break;
|
||||
case "Contact:Save":
|
||||
if (msg.options.reason === "create") {
|
||||
|
|
|
@ -59,8 +59,16 @@ function onFailure() {
|
|||
}
|
||||
|
||||
function checkStr(str1, str2, msg) {
|
||||
if (str1)
|
||||
ok(typeof str1 == "string" ? [str1] : str1, (typeof str2 == "string") ? [str2] : str2, msg);
|
||||
// comparing /[null(,null)+]/ and undefined should pass
|
||||
function nonNull(e) {
|
||||
return e != null;
|
||||
}
|
||||
if ((Array.isArray(str1) && str1.filter(nonNull).length == 0 && str2 == undefined)
|
||||
||(Array.isArray(str2) && str2.filter(nonNull).length == 0 && str1 == undefined)) {
|
||||
ok(true, msg);
|
||||
} else if (str1) {
|
||||
is(JSON.stringify(typeof str1 == "string" ? [str1] : str1), JSON.stringify(typeof str2 == "string" ? [str2] : str2), msg);
|
||||
}
|
||||
}
|
||||
|
||||
function checkAddress(adr1, adr2) {
|
||||
|
@ -157,10 +165,11 @@ function clearDatabase() {
|
|||
req.onerror = onFailure;
|
||||
}
|
||||
|
||||
function add20Contacts() {
|
||||
ok(true, "Adding 20 contacts");
|
||||
for (let i=0; i<19; i++) {
|
||||
function addContacts() {
|
||||
ok(true, "Adding 40 contacts");
|
||||
for (let i = 0; i < 39; ++i) {
|
||||
createResult1 = new mozContact();
|
||||
properties1.familyName[0] = "Testname" + (i < 10 ? "0" + i : i);
|
||||
createResult1.init(properties1);
|
||||
req = mozContacts.save(createResult1);
|
||||
req.onsuccess = function() {
|
||||
|
@ -169,6 +178,7 @@ function add20Contacts() {
|
|||
req.onerror = onFailure;
|
||||
};
|
||||
createResult1 = new mozContact();
|
||||
properties1.familyName[0] = "Testname39";
|
||||
createResult1.init(properties1);
|
||||
req = mozContacts.save(createResult1);
|
||||
req.onsuccess = function() {
|
||||
|
@ -216,19 +226,27 @@ let steps = [
|
|||
},
|
||||
|
||||
clearDatabase,
|
||||
add20Contacts,
|
||||
addContacts,
|
||||
|
||||
function() {
|
||||
ok(true, "Retrieving 20 contacts with getAll");
|
||||
req = mozContacts.getAll({});
|
||||
ok(true, "Retrieving 40 contacts with getAll");
|
||||
req = mozContacts.getAll({
|
||||
sortBy: "familyName",
|
||||
sortOrder: "ascending"
|
||||
});
|
||||
let count = 0;
|
||||
let result;
|
||||
let props;
|
||||
req.onsuccess = function(event) {
|
||||
if (req.result) {
|
||||
ok(true, "result is valid");
|
||||
result = req.result;
|
||||
properties1.familyName[0] = "Testname" + (count < 10 ? "0" + count : count);
|
||||
is(result.familyName[0], properties1.familyName[0], "Same familyName");
|
||||
count++;
|
||||
req.continue();
|
||||
} else {
|
||||
is(count, 20, "last contact - 20 contacts returned");
|
||||
is(count, 40, "last contact - 40 contacts returned");
|
||||
next();
|
||||
}
|
||||
};
|
||||
|
@ -253,7 +271,7 @@ let steps = [
|
|||
count++;
|
||||
req.continue();
|
||||
} else {
|
||||
is(count, 19, "last contact - 19 contacts returned");
|
||||
is(count, 39, "last contact - 39 contacts returned");
|
||||
next();
|
||||
}
|
||||
};
|
||||
|
@ -261,7 +279,7 @@ let steps = [
|
|||
},
|
||||
|
||||
clearDatabase,
|
||||
add20Contacts,
|
||||
addContacts,
|
||||
|
||||
function() {
|
||||
ok(true, "Test cache consistency when deleting contact during getAll");
|
||||
|
@ -288,7 +306,7 @@ let steps = [
|
|||
count++;
|
||||
req.continue();
|
||||
} else {
|
||||
is(count, 20, "last contact - 20 contacts returned");
|
||||
is(count, 40, "last contact - 40 contacts returned");
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
@ -297,7 +315,7 @@ let steps = [
|
|||
},
|
||||
|
||||
clearDatabase,
|
||||
add20Contacts,
|
||||
addContacts,
|
||||
|
||||
function() {
|
||||
ok(true, "Delete the current contact while iterating");
|
||||
|
@ -318,14 +336,14 @@ let steps = [
|
|||
req.continue();
|
||||
};
|
||||
} else {
|
||||
is(count, 20, "returned 20 contacts");
|
||||
is(count, 40, "returned 40 contacts");
|
||||
next();
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
clearDatabase,
|
||||
add20Contacts,
|
||||
addContacts,
|
||||
|
||||
function() {
|
||||
ok(true, "Iterating through the contact list inside a cursor callback");
|
||||
|
@ -341,7 +359,7 @@ let steps = [
|
|||
count2++;
|
||||
req2.continue();
|
||||
} else {
|
||||
is(count2, 20, "inner cursor returned 20 contacts");
|
||||
is(count2, 40, "inner cursor returned 40 contacts");
|
||||
req1.continue();
|
||||
}
|
||||
};
|
||||
|
@ -350,7 +368,7 @@ let steps = [
|
|||
count1++;
|
||||
req1.continue();
|
||||
} else {
|
||||
is(count1, 20, "outer cursor returned 20 contacts");
|
||||
is(count1, 40, "outer cursor returned 40 contacts");
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
@ -358,7 +376,7 @@ let steps = [
|
|||
},
|
||||
|
||||
clearDatabase,
|
||||
add20Contacts,
|
||||
addContacts,
|
||||
|
||||
function() {
|
||||
ok(true, "20 concurrent cursors");
|
||||
|
@ -373,7 +391,7 @@ let steps = [
|
|||
count++;
|
||||
req.continue();
|
||||
} else {
|
||||
is(count, 20, "cursor " + i + " returned 20 contacts");
|
||||
is(count, 40, "cursor " + i + " returned 40 contacts");
|
||||
if (++completed == NUM_CURSORS) {
|
||||
next();
|
||||
}
|
||||
|
|
|
@ -164,13 +164,13 @@ XPCOMUtils.defineLazyGetter(this, "gMmsConnection", function () {
|
|||
},
|
||||
|
||||
/**
|
||||
* Return the roaming status of data connection.
|
||||
* Return the roaming status of voice call.
|
||||
*
|
||||
* @return true if data connection is roaming.
|
||||
* @return true if voice call is roaming.
|
||||
*/
|
||||
isDataConnRoaming: function isDataConnRoaming() {
|
||||
let isRoaming = gRIL.rilContext.data.roaming;
|
||||
debug("isDataConnRoaming = " + isRoaming);
|
||||
isVoiceRoaming: function isVoiceRoaming() {
|
||||
let isRoaming = gRIL.rilContext.voice.roaming;
|
||||
debug("isVoiceRoaming = " + isRoaming);
|
||||
return isRoaming;
|
||||
},
|
||||
|
||||
|
@ -1166,9 +1166,14 @@ MmsService.prototype = {
|
|||
retrievalMode = Services.prefs.getCharPref(PREF_RETRIEVAL_MODE);
|
||||
} catch (e) {}
|
||||
|
||||
let isRoaming = gMmsConnection.isDataConnRoaming();
|
||||
if ((retrievalMode === RETRIEVAL_MODE_AUTOMATIC_HOME && isRoaming) ||
|
||||
RETRIEVAL_MODE_MANUAL === retrievalMode ||
|
||||
// In roaming environment, we send notify response only in
|
||||
// automatic retrieval mode.
|
||||
if ((retrievalMode !== RETRIEVAL_MODE_AUTOMATIC) &&
|
||||
gMmsConnection.isVoiceRoaming()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (RETRIEVAL_MODE_MANUAL === retrievalMode ||
|
||||
RETRIEVAL_MODE_NEVER === retrievalMode) {
|
||||
let mmsStatus = RETRIEVAL_MODE_NEVER === retrievalMode
|
||||
? MMS.MMS_PDU_STATUS_REJECTED
|
||||
|
|
Загрузка…
Ссылка в новой задаче