зеркало из https://github.com/mozilla/gecko-dev.git
Bug 974820 - Part 2: Add error handling of sending/receiving SMS/MMS when device storage is full. r=vyang
This commit is contained in:
Родитель
73664f17db
Коммит
6d6469b8d9
|
@ -25,7 +25,7 @@ interface nsIRilMobileMessageDatabaseRecordCallback : nsISupports
|
|||
void notify(in nsresult aRv, in jsval aMessageRecord, in nsISupports aDomMessage);
|
||||
};
|
||||
|
||||
[scriptable, uuid(a92eba51-e619-4f70-98c5-175a33590582)]
|
||||
[scriptable, uuid(596ef782-9f7a-11e3-8508-ff3a7d599531)]
|
||||
interface nsIRilMobileMessageDatabaseService : nsIMobileMessageDatabaseService
|
||||
{
|
||||
/**
|
||||
|
@ -119,4 +119,11 @@ interface nsIRilMobileMessageDatabaseService : nsIMobileMessageDatabaseService
|
|||
*/
|
||||
void getMessageRecordByTransactionId(in DOMString aTransactionId,
|
||||
in nsIRilMobileMessageDatabaseRecordCallback aCallback);
|
||||
|
||||
/**
|
||||
* |aCrError| nsresult: the NS_ERROR defined in Components.results.
|
||||
*
|
||||
* @returns the error code defined in nsIMobileMessageCallback
|
||||
*/
|
||||
jsval translateCrErrorToMessageCallbackError(in nsresult aCrError);
|
||||
};
|
||||
|
|
|
@ -1697,8 +1697,7 @@ MmsService.prototype = {
|
|||
// At this point we could send a message to content to notify the user
|
||||
// that storing an incoming MMS failed, most likely due to a full disk.
|
||||
// The end user has to retrieve the MMS again.
|
||||
if (DEBUG) debug("Could not store MMS " + domMessage.id +
|
||||
", error code " + rv);
|
||||
if (DEBUG) debug("Could not store MMS , error code " + rv);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1780,8 +1779,7 @@ MmsService.prototype = {
|
|||
let transactionId = notification.headers["x-mms-transaction-id"];
|
||||
gMobileMessageDatabaseService.getMessageRecordByTransactionId(transactionId,
|
||||
(function(aRv, aMessageRecord) {
|
||||
if (Ci.nsIMobileMessageCallback.SUCCESS_NO_ERROR === aRv
|
||||
&& aMessageRecord) {
|
||||
if (Components.isSuccessCode(aRv) && aMessageRecord) {
|
||||
if (DEBUG) debug("We already got the NotificationIndication with transactionId = "
|
||||
+ transactionId + " before.");
|
||||
return;
|
||||
|
@ -2171,9 +2169,16 @@ MmsService.prototype = {
|
|||
gMobileMessageDatabaseService
|
||||
.saveSendingMessage(savableMessage,
|
||||
function notifySendingResult(aRv, aDomMessage) {
|
||||
if (!Components.isSuccessCode(aRv)) {
|
||||
if (DEBUG) debug("Error! Fail to save sending message! rv = " + aRv);
|
||||
aRequest.notifySendMessageFailed(
|
||||
gMobileMessageDatabaseService.translateCrErrorToMessageCallbackError(aRv));
|
||||
Services.obs.notifyObservers(aDomMessage, kSmsFailedObserverTopic, null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (DEBUG) debug("Saving sending message is done. Start to send.");
|
||||
|
||||
// TODO bug 832140 handle !Components.isSuccessCode(aRv)
|
||||
Services.obs.notifyObservers(aDomMessage, kSmsSendingObserverTopic, null);
|
||||
|
||||
if (errorCode !== Ci.nsIMobileMessageCallback.SUCCESS_NO_ERROR) {
|
||||
|
@ -2221,9 +2226,10 @@ MmsService.prototype = {
|
|||
if (DEBUG) debug("Retrieving message with ID " + aMessageId);
|
||||
gMobileMessageDatabaseService.getMessageRecordById(aMessageId,
|
||||
(function notifyResult(aRv, aMessageRecord, aDomMessage) {
|
||||
if (Ci.nsIMobileMessageCallback.SUCCESS_NO_ERROR != aRv) {
|
||||
if (DEBUG) debug("Function getMessageRecordById() return error.");
|
||||
aRequest.notifyGetMessageFailed(aRv);
|
||||
if (!Components.isSuccessCode(aRv)) {
|
||||
if (DEBUG) debug("Function getMessageRecordById() return error: " + aRv);
|
||||
aRequest.notifyGetMessageFailed(
|
||||
gMobileMessageDatabaseService.translateCrErrorToMessageCallbackError(aRv));
|
||||
return;
|
||||
}
|
||||
if ("mms" != aMessageRecord.type) {
|
||||
|
@ -2362,9 +2368,9 @@ MmsService.prototype = {
|
|||
// At this point we could send a message to content to
|
||||
// notify the user that storing an incoming MMS failed, most
|
||||
// likely due to a full disk.
|
||||
if (DEBUG) debug("Could not store MMS " + domMessage.id +
|
||||
", error code " + rv);
|
||||
aRequest.notifyGetMessageFailed(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
|
||||
if (DEBUG) debug("Could not store MMS, error code " + rv);
|
||||
aRequest.notifyGetMessageFailed(
|
||||
gMobileMessageDatabaseService.translateCrErrorToMessageCallbackError(rv));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2396,9 +2402,9 @@ MmsService.prototype = {
|
|||
(function(rv) {
|
||||
let success = Components.isSuccessCode(rv);
|
||||
if (!success) {
|
||||
if (DEBUG) debug("Could not change the delivery status: MMS " +
|
||||
domMessage.id + ", error code " + rv);
|
||||
aRequest.notifyGetMessageFailed(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
|
||||
if (DEBUG) debug("Could not change the delivery status, error code " + rv);
|
||||
aRequest.notifyGetMessageFailed(
|
||||
gMobileMessageDatabaseService.translateCrErrorToMessageCallbackError(rv));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -93,6 +93,13 @@ MobileMessageDB.prototype = {
|
|||
*/
|
||||
lastMessageId: 0,
|
||||
|
||||
/**
|
||||
* An optional hook to check if device storage is full.
|
||||
*
|
||||
* @return true if full.
|
||||
*/
|
||||
isDiskFull: null,
|
||||
|
||||
/**
|
||||
* Prepare the database. This may include opening the database and upgrading
|
||||
* it to the latest schema version.
|
||||
|
@ -238,7 +245,8 @@ MobileMessageDB.prototype = {
|
|||
break;
|
||||
default:
|
||||
event.target.transaction.abort();
|
||||
callback("Old database version: " + event.oldVersion, null);
|
||||
if (DEBUG) debug("unexpected db version: " + event.oldVersion);
|
||||
callback(Cr.NS_ERROR_FAILURE, null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -247,10 +255,12 @@ MobileMessageDB.prototype = {
|
|||
};
|
||||
request.onerror = function(event) {
|
||||
//TODO look at event.target.Code and change error constant accordingly
|
||||
callback("Error opening database!", null);
|
||||
if (DEBUG) debug("Error opening database!");
|
||||
callback(Cr.NS_ERROR_FAILURE, null);
|
||||
};
|
||||
request.onblocked = function(event) {
|
||||
callback("Opening database request is blocked.", null);
|
||||
if (DEBUG) debug("Opening database request is blocked.");
|
||||
callback(Cr.NS_ERROR_FAILURE, null);
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -270,7 +280,13 @@ MobileMessageDB.prototype = {
|
|||
storeNames = [MESSAGE_STORE_NAME];
|
||||
}
|
||||
if (DEBUG) debug("Opening transaction for object stores: " + storeNames);
|
||||
let self = this;
|
||||
this.ensureDB(function(error, db) {
|
||||
if (!error &&
|
||||
txn_type === READ_WRITE &&
|
||||
self.isDiskFull && self.isDiskFull()) {
|
||||
error = Cr.NS_ERROR_FILE_NO_DEVICE_SPACE;
|
||||
}
|
||||
if (error) {
|
||||
if (DEBUG) debug("Could not open database: " + error);
|
||||
callback(error);
|
||||
|
@ -1645,8 +1661,7 @@ MobileMessageDB.prototype = {
|
|||
};
|
||||
|
||||
if (aError) {
|
||||
// TODO bug 832140 check event.target.errorCode
|
||||
notifyResult(Cr.NS_ERROR_FAILURE, null);
|
||||
notifyResult(aError, null);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1678,8 +1693,7 @@ MobileMessageDB.prototype = {
|
|||
};
|
||||
|
||||
if (error) {
|
||||
// TODO bug 832140 check event.target.errorCode
|
||||
notifyResult(Cr.NS_ERROR_FAILURE, null);
|
||||
notifyResult(error, null);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2323,7 +2337,7 @@ MobileMessageDB.prototype = {
|
|||
this.newTxn(READ_ONLY, function(error, txn, messageStore) {
|
||||
if (error) {
|
||||
if (DEBUG) debug(error);
|
||||
aCallback.notify(Ci.nsIMobileMessageCallback.INTERNAL_ERROR, null, null);
|
||||
aCallback.notify(error, null, null);
|
||||
return;
|
||||
}
|
||||
let request = messageStore.index("transactionId").get(aTransactionId);
|
||||
|
@ -2333,13 +2347,12 @@ MobileMessageDB.prototype = {
|
|||
let messageRecord = request.result;
|
||||
if (!messageRecord) {
|
||||
if (DEBUG) debug("Transaction ID " + aTransactionId + " not found");
|
||||
aCallback.notify(Ci.nsIMobileMessageCallback.NOT_FOUND_ERROR, null, null);
|
||||
aCallback.notify(Cr.NS_ERROR_FILE_NOT_FOUND, null, null);
|
||||
return;
|
||||
}
|
||||
// In this case, we don't need a dom message. Just pass null to the
|
||||
// third argument.
|
||||
aCallback.notify(Ci.nsIMobileMessageCallback.SUCCESS_NO_ERROR,
|
||||
messageRecord, null);
|
||||
aCallback.notify(Cr.NS_OK, messageRecord, null);
|
||||
};
|
||||
|
||||
txn.onerror = function onerror(event) {
|
||||
|
@ -2348,7 +2361,7 @@ MobileMessageDB.prototype = {
|
|||
debug("Caught error on transaction", event.target.errorCode);
|
||||
}
|
||||
}
|
||||
aCallback.notify(Ci.nsIMobileMessageCallback.INTERNAL_ERROR, null, null);
|
||||
aCallback.notify(Cr.NS_ERROR_FAILURE, null, null);
|
||||
};
|
||||
});
|
||||
},
|
||||
|
@ -2359,7 +2372,7 @@ MobileMessageDB.prototype = {
|
|||
this.newTxn(READ_ONLY, function(error, txn, messageStore) {
|
||||
if (error) {
|
||||
if (DEBUG) debug(error);
|
||||
aCallback.notify(Ci.nsIMobileMessageCallback.INTERNAL_ERROR, null, null);
|
||||
aCallback.notify(error, null, null);
|
||||
return;
|
||||
}
|
||||
let request = messageStore.mozGetAll(aMessageId);
|
||||
|
@ -2368,13 +2381,13 @@ MobileMessageDB.prototype = {
|
|||
if (DEBUG) debug("Transaction " + txn + " completed.");
|
||||
if (request.result.length > 1) {
|
||||
if (DEBUG) debug("Got too many results for id " + aMessageId);
|
||||
aCallback.notify(Ci.nsIMobileMessageCallback.UNKNOWN_ERROR, null, null);
|
||||
aCallback.notify(Cr.NS_ERROR_UNEXPECTED, null, null);
|
||||
return;
|
||||
}
|
||||
let messageRecord = request.result[0];
|
||||
if (!messageRecord) {
|
||||
if (DEBUG) debug("Message ID " + aMessageId + " not found");
|
||||
aCallback.notify(Ci.nsIMobileMessageCallback.NOT_FOUND_ERROR, null, null);
|
||||
aCallback.notify(Cr.NS_ERROR_FILE_NOT_FOUND, null, null);
|
||||
return;
|
||||
}
|
||||
if (messageRecord.id != aMessageId) {
|
||||
|
@ -2382,12 +2395,11 @@ MobileMessageDB.prototype = {
|
|||
debug("Requested message ID (" + aMessageId + ") is " +
|
||||
"different from the one we got");
|
||||
}
|
||||
aCallback.notify(Ci.nsIMobileMessageCallback.UNKNOWN_ERROR, null, null);
|
||||
aCallback.notify(Cr.NS_ERROR_UNEXPECTED, null, null);
|
||||
return;
|
||||
}
|
||||
let domMessage = self.createDomMessageFromRecord(messageRecord);
|
||||
aCallback.notify(Ci.nsIMobileMessageCallback.SUCCESS_NO_ERROR,
|
||||
messageRecord, domMessage);
|
||||
aCallback.notify(Cr.NS_OK, messageRecord, domMessage);
|
||||
};
|
||||
|
||||
txn.onerror = function onerror(event) {
|
||||
|
@ -2396,24 +2408,41 @@ MobileMessageDB.prototype = {
|
|||
debug("Caught error on transaction", event.target.errorCode);
|
||||
}
|
||||
}
|
||||
aCallback.notify(Ci.nsIMobileMessageCallback.INTERNAL_ERROR, null, null);
|
||||
aCallback.notify(Cr.NS_ERROR_FAILURE, null, null);
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
translateCrErrorToMessageCallbackError: function(aCrError) {
|
||||
switch(aCrError) {
|
||||
case Cr.NS_OK:
|
||||
return Ci.nsIMobileMessageCallback.SUCCESS_NO_ERROR;
|
||||
case Cr.NS_ERROR_UNEXPECTED:
|
||||
return Ci.nsIMobileMessageCallback.UNKNOWN_ERROR;
|
||||
case Cr.NS_ERROR_FILE_NOT_FOUND:
|
||||
return Ci.nsIMobileMessageCallback.NOT_FOUND_ERROR;
|
||||
case Cr.NS_ERROR_FILE_NO_DEVICE_SPACE:
|
||||
return Ci.nsIMobileMessageCallback.STORAGE_FULL_ERROR;
|
||||
default:
|
||||
return Ci.nsIMobileMessageCallback.INTERNAL_ERROR;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIMobileMessageDatabaseService API
|
||||
*/
|
||||
|
||||
getMessage: function(aMessageId, aRequest) {
|
||||
if (DEBUG) debug("Retrieving message with ID " + aMessageId);
|
||||
let self = this;
|
||||
let notifyCallback = {
|
||||
notify: function(aRv, aMessageRecord, aDomMessage) {
|
||||
if (Ci.nsIMobileMessageCallback.SUCCESS_NO_ERROR == aRv) {
|
||||
if (Cr.NS_OK == aRv) {
|
||||
aRequest.notifyMessageGot(aDomMessage);
|
||||
return;
|
||||
}
|
||||
aRequest.notifyGetMessageFailed(aRv, null);
|
||||
aRequest.notifyGetMessageFailed(
|
||||
self.translateCrErrorToMessageCallbackError(aRv), null);
|
||||
}
|
||||
};
|
||||
this.getMessageRecordById(aMessageId, notifyCallback);
|
||||
|
@ -2426,7 +2455,8 @@ MobileMessageDB.prototype = {
|
|||
this.newTxn(READ_WRITE, function(error, txn, stores) {
|
||||
if (error) {
|
||||
if (DEBUG) debug("deleteMessage: failed to open transaction");
|
||||
aRequest.notifyDeleteMessageFailed(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
|
||||
aRequest.notifyDeleteMessageFailed(
|
||||
self.translateCrErrorToMessageCallbackError(error));
|
||||
return;
|
||||
}
|
||||
txn.onerror = function onerror(event) {
|
||||
|
@ -2502,10 +2532,12 @@ MobileMessageDB.prototype = {
|
|||
|
||||
markMessageRead: function(messageId, value, aSendReadReport, aRequest) {
|
||||
if (DEBUG) debug("Setting message " + messageId + " read to " + value);
|
||||
let self = this;
|
||||
this.newTxn(READ_WRITE, function(error, txn, stores) {
|
||||
if (error) {
|
||||
if (DEBUG) debug(error);
|
||||
aRequest.notifyMarkMessageReadFailed(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
|
||||
aRequest.notifyMarkMessageReadFailed(
|
||||
self.translateCrErrorToMessageCallbackError(error));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2597,7 +2629,6 @@ MobileMessageDB.prototype = {
|
|||
this.newTxn(READ_ONLY, function(error, txn, threadStore) {
|
||||
let collector = cursor.collector;
|
||||
if (error) {
|
||||
if (DEBUG) debug(error);
|
||||
collector.collect(null, COLLECT_ID_ERROR, COLLECT_TIMESTAMP_UNUSED);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,10 @@ const RIL_MOBILEMESSAGEDATABASESERVICE_CONTRACTID =
|
|||
const RIL_MOBILEMESSAGEDATABASESERVICE_CID =
|
||||
Components.ID("{29785f90-6b5b-11e2-9201-3b280170b2ec}");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gDiskSpaceWatcher",
|
||||
"@mozilla.org/toolkit/disk-space-watcher;1",
|
||||
"nsIDiskSpaceWatcher");
|
||||
|
||||
const DB_NAME = "sms";
|
||||
|
||||
/**
|
||||
|
@ -29,6 +33,9 @@ function MobileMessageDatabaseService() {
|
|||
|
||||
let mmdb = new MMDB.MobileMessageDB();
|
||||
mmdb.init(DB_NAME, 0, mmdb.updatePendingTransactionToError.bind(mmdb));
|
||||
mmdb.isDiskFull = function() {
|
||||
return gDiskSpaceWatcher.isDiskFull;
|
||||
};
|
||||
this.mmdb = mmdb;
|
||||
}
|
||||
MobileMessageDatabaseService.prototype = {
|
||||
|
@ -88,6 +95,10 @@ MobileMessageDatabaseService.prototype = {
|
|||
this.mmdb.getMessageRecordById(aMessageId, aCallback);
|
||||
},
|
||||
|
||||
translateCrErrorToMessageCallbackError: function(aCrError) {
|
||||
return this.mmdb.translateCrErrorToMessageCallbackError(aCrError);
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIMobileMessageDatabaseService API
|
||||
*/
|
||||
|
|
|
@ -3933,7 +3933,14 @@ RadioInterface.prototype = {
|
|||
}
|
||||
|
||||
let notifyResult = (function notifyResult(rv, domMessage) {
|
||||
// TODO bug 832140 handle !Components.isSuccessCode(rv)
|
||||
if (!Components.isSuccessCode(rv)) {
|
||||
if (DEBUG) this.debug("Error! Fail to save sending message! rv = " + rv);
|
||||
request.notifySendMessageFailed(
|
||||
gMobileMessageDatabaseService.translateCrErrorToMessageCallbackError(rv));
|
||||
Services.obs.notifyObservers(domMessage, kSmsFailedObserverTopic, null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!silent) {
|
||||
Services.obs.notifyObservers(domMessage, kSmsSendingObserverTopic, null);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче