зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c and inbound.
This commit is contained in:
Коммит
e19b88cdad
|
@ -75,13 +75,11 @@ FilePicker.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
appendFilters: function(filterMask) {
|
appendFilters: function(filterMask) {
|
||||||
this.mFilterTypes = null;
|
|
||||||
|
|
||||||
// Ci.nsIFilePicker.filterHTML is not supported
|
// Ci.nsIFilePicker.filterHTML is not supported
|
||||||
// Ci.nsIFilePicker.filterText is not supported
|
// Ci.nsIFilePicker.filterText is not supported
|
||||||
|
|
||||||
if (filterMask & Ci.nsIFilePicker.filterImages) {
|
if (filterMask & Ci.nsIFilePicker.filterImages) {
|
||||||
this.mFilterTypes = IMAGE_FILTERS;
|
this.mFilterTypes = this.mFilterTypes.concat(IMAGE_FILTERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ci.nsIFilePicker.filterXML is not supported
|
// Ci.nsIFilePicker.filterXML is not supported
|
||||||
|
@ -90,11 +88,11 @@ FilePicker.prototype = {
|
||||||
// Ci.nsIFilePicker.filterAllowURLs is not supported
|
// Ci.nsIFilePicker.filterAllowURLs is not supported
|
||||||
|
|
||||||
if (filterMask & Ci.nsIFilePicker.filterVideo) {
|
if (filterMask & Ci.nsIFilePicker.filterVideo) {
|
||||||
this.mFilterTypes = VIDEO_FILTERS;
|
this.mFilterTypes = this.mFilterTypes.concat(VIDEO_FILTERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filterMask & Ci.nsIFilePicker.filterAudio) {
|
if (filterMask & Ci.nsIFilePicker.filterAudio) {
|
||||||
this.mFilterTypes = AUDIO_FILTERS;
|
this.mFilterTypes = this.mFilterTypes.concat(AUDIO_FILTERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ci.nsIFilePicker.filterAll is by default
|
// Ci.nsIFilePicker.filterAll is by default
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{
|
{
|
||||||
"revision": "500287afb1817acb98bee67684c6c4c0f7240eb9",
|
"revision": "6175336047b511e982827ae4ed559ee1f644a79e",
|
||||||
"repo_path": "/integration/gaia-central"
|
"repo_path": "/integration/gaia-central"
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "base/basictypes.h"
|
||||||
#include <cutils/properties.h>
|
#include <cutils/properties.h>
|
||||||
|
#include <stagefright/foundation/ADebug.h>
|
||||||
#include <stagefright/foundation/AMessage.h>
|
#include <stagefright/foundation/AMessage.h>
|
||||||
#include <stagefright/MediaExtractor.h>
|
#include <stagefright/MediaExtractor.h>
|
||||||
#include <stagefright/MetaData.h>
|
#include <stagefright/MetaData.h>
|
||||||
|
@ -174,8 +175,10 @@ OmxDecoder::~OmxDecoder()
|
||||||
|
|
||||||
void OmxDecoder::statusChanged()
|
void OmxDecoder::statusChanged()
|
||||||
{
|
{
|
||||||
mozilla::ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
sp<AMessage> notify =
|
||||||
mDecoder->GetReentrantMonitor().NotifyAll();
|
new AMessage(kNotifyStatusChanged, mReflector->id());
|
||||||
|
// post AMessage to OmxDecoder via ALooper.
|
||||||
|
notify->post();
|
||||||
}
|
}
|
||||||
|
|
||||||
static sp<IOMX> sOMX = nullptr;
|
static sp<IOMX> sOMX = nullptr;
|
||||||
|
@ -765,12 +768,28 @@ void OmxDecoder::Pause()
|
||||||
// Called on ALooper thread.
|
// Called on ALooper thread.
|
||||||
void OmxDecoder::onMessageReceived(const sp<AMessage> &msg)
|
void OmxDecoder::onMessageReceived(const sp<AMessage> &msg)
|
||||||
{
|
{
|
||||||
Mutex::Autolock autoLock(mSeekLock);
|
switch (msg->what()) {
|
||||||
|
case kNotifyPostReleaseVideoBuffer:
|
||||||
|
{
|
||||||
|
Mutex::Autolock autoLock(mSeekLock);
|
||||||
|
// Free pending video buffers when OmxDecoder is not seeking video.
|
||||||
|
// If OmxDecoder is seeking video, the buffers are freed on seek exit.
|
||||||
|
if (!mIsVideoSeeking) {
|
||||||
|
ReleaseAllPendingVideoBuffersLocked();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Free pending video buffers when OmxDecoder is not seeking video.
|
case kNotifyStatusChanged:
|
||||||
// If OmxDecoder is in seeking video, the buffers are freed on seek exit.
|
{
|
||||||
if (mIsVideoSeeking != true) {
|
mozilla::ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||||
ReleaseAllPendingVideoBuffersLocked();
|
mDecoder->GetReentrantMonitor().NotifyAll();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
TRESPASS();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,8 @@ class OmxDecoder : public OMXCodecProxy::EventListener {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
kNotifyPostReleaseVideoBuffer = 'noti'
|
kNotifyPostReleaseVideoBuffer = 'noti',
|
||||||
|
kNotifyStatusChanged = 'stat'
|
||||||
};
|
};
|
||||||
|
|
||||||
AbstractMediaDecoder *mDecoder;
|
AbstractMediaDecoder *mDecoder;
|
||||||
|
|
|
@ -33,11 +33,18 @@ const kSmsRetrievingObserverTopic = "sms-retrieving";
|
||||||
const kNetworkInterfaceStateChangedTopic = "network-interface-state-changed";
|
const kNetworkInterfaceStateChangedTopic = "network-interface-state-changed";
|
||||||
const kXpcomShutdownObserverTopic = "xpcom-shutdown";
|
const kXpcomShutdownObserverTopic = "xpcom-shutdown";
|
||||||
const kPrefenceChangedObserverTopic = "nsPref:changed";
|
const kPrefenceChangedObserverTopic = "nsPref:changed";
|
||||||
|
const kMobileMessageDeletedObserverTopic = "mobile-message-deleted";
|
||||||
|
|
||||||
// HTTP status codes:
|
// HTTP status codes:
|
||||||
// @see http://tools.ietf.org/html/rfc2616#page-39
|
// @see http://tools.ietf.org/html/rfc2616#page-39
|
||||||
const HTTP_STATUS_OK = 200;
|
const HTTP_STATUS_OK = 200;
|
||||||
|
|
||||||
|
// Non-standard HTTP status for internal use.
|
||||||
|
const _HTTP_STATUS_USER_CANCELLED = -1;
|
||||||
|
|
||||||
|
// Non-standard MMS status for internal use.
|
||||||
|
const _MMS_ERROR_MESSAGE_DELETED = -1;
|
||||||
|
|
||||||
const CONFIG_SEND_REPORT_NEVER = 0;
|
const CONFIG_SEND_REPORT_NEVER = 0;
|
||||||
const CONFIG_SEND_REPORT_DEFAULT_NO = 1;
|
const CONFIG_SEND_REPORT_DEFAULT_NO = 1;
|
||||||
const CONFIG_SEND_REPORT_DEFAULT_YES = 2;
|
const CONFIG_SEND_REPORT_DEFAULT_YES = 2;
|
||||||
|
@ -397,7 +404,7 @@ MmsProxyFilter.prototype = {
|
||||||
};
|
};
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(this, "gMmsTransactionHelper", function () {
|
XPCOMUtils.defineLazyGetter(this, "gMmsTransactionHelper", function () {
|
||||||
return {
|
let helper = {
|
||||||
/**
|
/**
|
||||||
* Send MMS request to MMSC.
|
* Send MMS request to MMSC.
|
||||||
*
|
*
|
||||||
|
@ -413,14 +420,55 @@ XPCOMUtils.defineLazyGetter(this, "gMmsTransactionHelper", function () {
|
||||||
*/
|
*/
|
||||||
sendRequest: function sendRequest(method, url, istream, callback) {
|
sendRequest: function sendRequest(method, url, istream, callback) {
|
||||||
// TODO: bug 810226 - Support GPRS bearer for MMS transmission and reception.
|
// TODO: bug 810226 - Support GPRS bearer for MMS transmission and reception.
|
||||||
|
let cancellable = {
|
||||||
|
callback: callback,
|
||||||
|
|
||||||
gMmsConnection.acquire((function (method, url, istream, callback,
|
isDone: false,
|
||||||
connected) {
|
isCancelled: false,
|
||||||
if (!connected) {
|
|
||||||
// Connection timeout or failed. Report error.
|
cancel: function cancel() {
|
||||||
|
if (this.isDone) {
|
||||||
|
// It's too late to cancel.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isCancelled = true;
|
||||||
|
if (this.isAcquiringConn) {
|
||||||
|
// We cannot cancel data connection setup here, so we invoke done()
|
||||||
|
// here and handle |cancellable.isDone| in callback function of
|
||||||
|
// |gMmsConnection.acquire|.
|
||||||
|
this.done(_HTTP_STATUS_USER_CANCELLED, null);
|
||||||
|
} else if (this.xhr) {
|
||||||
|
// Client has already sent the HTTP request. Try to abort it.
|
||||||
|
this.xhr.abort();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
done: function done(httpStatus, data) {
|
||||||
|
this.isDone = true;
|
||||||
|
if (!this.callback) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isCancelled) {
|
||||||
|
this.callback(_HTTP_STATUS_USER_CANCELLED, null);
|
||||||
|
} else {
|
||||||
|
this.callback(httpStatus, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
cancellable.isAcquiringConn =
|
||||||
|
!gMmsConnection.acquire((function (connected) {
|
||||||
|
|
||||||
|
cancellable.isAcquiringConn = false;
|
||||||
|
|
||||||
|
if (!connected || cancellable.isCancelled) {
|
||||||
gMmsConnection.release();
|
gMmsConnection.release();
|
||||||
if (callback) {
|
|
||||||
callback(0, null);
|
if (!cancellable.isDone) {
|
||||||
|
cancellable.done(cancellable.isCancelled ?
|
||||||
|
_HTTP_STATUS_USER_CANCELLED : 0, null);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -429,84 +477,90 @@ XPCOMUtils.defineLazyGetter(this, "gMmsTransactionHelper", function () {
|
||||||
let proxyFilter = new MmsProxyFilter(url);
|
let proxyFilter = new MmsProxyFilter(url);
|
||||||
gpps.registerFilter(proxyFilter, 0);
|
gpps.registerFilter(proxyFilter, 0);
|
||||||
|
|
||||||
let releaseMmsConnectionAndCallback = (function (httpStatus, data) {
|
cancellable.xhr = this.sendHttpRequest(method, url, istream, proxyFilter,
|
||||||
gpps.unregisterFilter(proxyFilter);
|
cancellable.done.bind(cancellable));
|
||||||
// Always release the MMS network connection before callback.
|
}).bind(this));
|
||||||
gMmsConnection.release();
|
|
||||||
if (callback) {
|
|
||||||
callback(httpStatus, data);
|
|
||||||
}
|
|
||||||
}).bind(this);
|
|
||||||
|
|
||||||
try {
|
return cancellable;
|
||||||
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
},
|
||||||
.createInstance(Ci.nsIXMLHttpRequest);
|
|
||||||
|
|
||||||
// Basic setups
|
sendHttpRequest: function sendHttpRequest(method, url, istream, proxyFilter,
|
||||||
xhr.open(method, url, true);
|
callback) {
|
||||||
xhr.responseType = "arraybuffer";
|
let releaseMmsConnectionAndCallback = function (httpStatus, data) {
|
||||||
if (istream) {
|
gpps.unregisterFilter(proxyFilter);
|
||||||
xhr.setRequestHeader("Content-Type",
|
// Always release the MMS network connection before callback.
|
||||||
"application/vnd.wap.mms-message");
|
gMmsConnection.release();
|
||||||
xhr.setRequestHeader("Content-Length", istream.available());
|
callback(httpStatus, data);
|
||||||
}
|
};
|
||||||
|
|
||||||
// UAProf headers.
|
try {
|
||||||
let uaProfUrl, uaProfTagname = "x-wap-profile";
|
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||||
try {
|
.createInstance(Ci.nsIXMLHttpRequest);
|
||||||
uaProfUrl = Services.prefs.getCharPref('wap.UAProf.url');
|
|
||||||
uaProfTagname = Services.prefs.getCharPref('wap.UAProf.tagname');
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
if (uaProfUrl) {
|
// Basic setups
|
||||||
xhr.setRequestHeader(uaProfTagname, uaProfUrl);
|
xhr.open(method, url, true);
|
||||||
}
|
xhr.responseType = "arraybuffer";
|
||||||
|
if (istream) {
|
||||||
// Setup event listeners
|
xhr.setRequestHeader("Content-Type",
|
||||||
xhr.onerror = function () {
|
"application/vnd.wap.mms-message");
|
||||||
if (DEBUG) debug("xhr error, response headers: " +
|
xhr.setRequestHeader("Content-Length", istream.available());
|
||||||
xhr.getAllResponseHeaders());
|
|
||||||
releaseMmsConnectionAndCallback(xhr.status, null);
|
|
||||||
};
|
|
||||||
xhr.onreadystatechange = function () {
|
|
||||||
if (xhr.readyState != Ci.nsIXMLHttpRequest.DONE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let data = null;
|
|
||||||
switch (xhr.status) {
|
|
||||||
case HTTP_STATUS_OK: {
|
|
||||||
if (DEBUG) debug("xhr success, response headers: "
|
|
||||||
+ xhr.getAllResponseHeaders());
|
|
||||||
|
|
||||||
let array = new Uint8Array(xhr.response);
|
|
||||||
if (false) {
|
|
||||||
for (let begin = 0; begin < array.length; begin += 20) {
|
|
||||||
let partial = array.subarray(begin, begin + 20);
|
|
||||||
if (DEBUG) debug("res: " + JSON.stringify(partial));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data = {array: array, offset: 0};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
if (DEBUG) debug("xhr done, but status = " + xhr.status +
|
|
||||||
", statusText = " + xhr.statusText);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
releaseMmsConnectionAndCallback(xhr.status, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send request
|
|
||||||
xhr.send(istream);
|
|
||||||
} catch (e) {
|
|
||||||
if (DEBUG) debug("xhr error, can't send: " + e.message);
|
|
||||||
releaseMmsConnectionAndCallback(0, null);
|
|
||||||
}
|
}
|
||||||
}).bind(this, method, url, istream, callback));
|
|
||||||
|
// UAProf headers.
|
||||||
|
let uaProfUrl, uaProfTagname = "x-wap-profile";
|
||||||
|
try {
|
||||||
|
uaProfUrl = Services.prefs.getCharPref('wap.UAProf.url');
|
||||||
|
uaProfTagname = Services.prefs.getCharPref('wap.UAProf.tagname');
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
if (uaProfUrl) {
|
||||||
|
xhr.setRequestHeader(uaProfTagname, uaProfUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup event listeners
|
||||||
|
xhr.onerror = function () {
|
||||||
|
if (DEBUG) debug("xhr error, response headers: " +
|
||||||
|
xhr.getAllResponseHeaders());
|
||||||
|
releaseMmsConnectionAndCallback(xhr.status, null);
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onreadystatechange = function () {
|
||||||
|
if (xhr.readyState != Ci.nsIXMLHttpRequest.DONE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let data = null;
|
||||||
|
switch (xhr.status) {
|
||||||
|
case HTTP_STATUS_OK: {
|
||||||
|
if (DEBUG) debug("xhr success, response headers: "
|
||||||
|
+ xhr.getAllResponseHeaders());
|
||||||
|
let array = new Uint8Array(xhr.response);
|
||||||
|
if (false) {
|
||||||
|
for (let begin = 0; begin < array.length; begin += 20) {
|
||||||
|
let partial = array.subarray(begin, begin + 20);
|
||||||
|
if (DEBUG) debug("res: " + JSON.stringify(partial));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data = {array: array, offset: 0};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
if (DEBUG) debug("xhr done, but status = " + xhr.status +
|
||||||
|
", statusText = " + xhr.statusText);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
releaseMmsConnectionAndCallback(xhr.status, data);
|
||||||
|
};
|
||||||
|
// Send request
|
||||||
|
xhr.send(istream);
|
||||||
|
return xhr;
|
||||||
|
} catch (e) {
|
||||||
|
if (DEBUG) debug("xhr error, can't send: " + e.message);
|
||||||
|
releaseMmsConnectionAndCallback(0, null);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -586,6 +640,8 @@ XPCOMUtils.defineLazyGetter(this, "gMmsTransactionHelper", function () {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return helper;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -634,47 +690,144 @@ NotifyResponseTransaction.prototype = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve message back from MMSC.
|
* CancellableTransaction - base class inherited by [Send|Retrieve]Transaction.
|
||||||
|
* @param cancellableId
|
||||||
|
* An ID used to keep track of if an message is deleted from DB.
|
||||||
|
*/
|
||||||
|
function CancellableTransaction(cancellableId) {
|
||||||
|
this.cancellableId = cancellableId;
|
||||||
|
this.isCancelled = false;
|
||||||
|
}
|
||||||
|
CancellableTransaction.prototype = {
|
||||||
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
|
||||||
|
|
||||||
|
// The timer for retrying sending or retrieving process.
|
||||||
|
timer: null,
|
||||||
|
|
||||||
|
// Keep a reference to the callback when calling
|
||||||
|
// |[Send|Retrieve]Transaction.run(callback)|.
|
||||||
|
runCallback: null,
|
||||||
|
|
||||||
|
isObserversAdded: false,
|
||||||
|
|
||||||
|
registerRunCallback: function registerRunCallback(callback) {
|
||||||
|
if (!this.isObserversAdded) {
|
||||||
|
Services.obs.addObserver(this, kXpcomShutdownObserverTopic, false);
|
||||||
|
Services.obs.addObserver(this, kMobileMessageDeletedObserverTopic, false);
|
||||||
|
this.isObserversAdded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.runCallback = callback;
|
||||||
|
this.isCancelled = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
removeObservers: function removeObservers() {
|
||||||
|
if (this.isObserversAdded) {
|
||||||
|
Services.obs.removeObserver(this, kXpcomShutdownObserverTopic);
|
||||||
|
Services.obs.removeObserver(this, kMobileMessageDeletedObserverTopic);
|
||||||
|
this.isObserversAdded = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
runCallbackIfValid: function runCallbackIfValid(mmsStatus, msg) {
|
||||||
|
this.removeObservers();
|
||||||
|
|
||||||
|
if (this.runCallback) {
|
||||||
|
this.runCallback(mmsStatus, msg);
|
||||||
|
this.runCallback = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Keep a reference to the cancellable when calling
|
||||||
|
// |gMmsTransactionHelper.sendRequest(...)|.
|
||||||
|
cancellable: null,
|
||||||
|
|
||||||
|
cancelRunning: function cancelRunning() {
|
||||||
|
this.isCancelled = true;
|
||||||
|
|
||||||
|
if (this.timer) {
|
||||||
|
// The sending or retrieving process is waiting for the next retry.
|
||||||
|
// What we only need to do is to cancel the timer.
|
||||||
|
this.timer.cancel();
|
||||||
|
this.timer = null;
|
||||||
|
this.runCallbackIfValid(_MMS_ERROR_MESSAGE_DELETED, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.cancellable) {
|
||||||
|
// The sending or retrieving process is still running. We attempt to
|
||||||
|
// abort the HTTP request.
|
||||||
|
this.cancellable.cancel();
|
||||||
|
this.cancellable = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// nsIObserver
|
||||||
|
|
||||||
|
observe: function observe(subject, topic, data) {
|
||||||
|
switch (topic) {
|
||||||
|
case kXpcomShutdownObserverTopic: {
|
||||||
|
this.cancelRunning();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kMobileMessageDeletedObserverTopic: {
|
||||||
|
data = JSON.parse(data);
|
||||||
|
if (data.id != this.cancellableId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cancelRunning();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for retrieving message from MMSC, which inherits CancellableTransaction.
|
||||||
*
|
*
|
||||||
* @param contentLocation
|
* @param contentLocation
|
||||||
* X-Mms-Content-Location of the message.
|
* X-Mms-Content-Location of the message.
|
||||||
*/
|
*/
|
||||||
function RetrieveTransaction(contentLocation) {
|
function RetrieveTransaction(cancellableId, contentLocation) {
|
||||||
|
// Call |CancellableTransaction| constructor.
|
||||||
|
CancellableTransaction.call(this, cancellableId);
|
||||||
|
|
||||||
this.contentLocation = contentLocation;
|
this.contentLocation = contentLocation;
|
||||||
}
|
}
|
||||||
RetrieveTransaction.prototype = {
|
RetrieveTransaction.prototype = Object.create(CancellableTransaction.prototype, {
|
||||||
/**
|
|
||||||
* We need to keep a reference to the timer to assure the timer is fired.
|
|
||||||
*/
|
|
||||||
timer: null,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param callback [optional]
|
* @param callback [optional]
|
||||||
* A callback function that takes two arguments: one for X-Mms-Status,
|
* A callback function that takes two arguments: one for X-Mms-Status,
|
||||||
* the other for the parsed M-Retrieve.conf message.
|
* the other for the parsed M-Retrieve.conf message.
|
||||||
*/
|
*/
|
||||||
run: function run(callback) {
|
run: {
|
||||||
this.retryCount = 0;
|
value: function run(callback) {
|
||||||
let that = this;
|
this.registerRunCallback(callback);
|
||||||
this.retrieve((function retryCallback(mmsStatus, msg) {
|
|
||||||
if (MMS.MMS_PDU_STATUS_DEFERRED == mmsStatus &&
|
|
||||||
that.retryCount < PREF_RETRIEVAL_RETRY_COUNT) {
|
|
||||||
if (that.timer == null) {
|
|
||||||
that.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
|
||||||
}
|
|
||||||
|
|
||||||
that.timer.initWithCallback((function (){
|
this.retryCount = 0;
|
||||||
this.retrieve(retryCallback);
|
let that = this;
|
||||||
}).bind(that),
|
this.retrieve((function retryCallback(mmsStatus, msg) {
|
||||||
PREF_RETRIEVAL_RETRY_INTERVALS[that.retryCount],
|
if (MMS.MMS_PDU_STATUS_DEFERRED == mmsStatus &&
|
||||||
Ci.nsITimer.TYPE_ONE_SHOT);
|
that.retryCount < PREF_RETRIEVAL_RETRY_COUNT) {
|
||||||
that.retryCount++;
|
if (that.timer == null) {
|
||||||
return;
|
that.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||||
}
|
}
|
||||||
if (callback) {
|
|
||||||
callback(mmsStatus, msg);
|
that.timer.initWithCallback((function (){
|
||||||
}
|
this.retrieve(retryCallback);
|
||||||
}).bind(this));
|
}).bind(that),
|
||||||
|
PREF_RETRIEVAL_RETRY_INTERVALS[that.retryCount],
|
||||||
|
Ci.nsITimer.TYPE_ONE_SHOT);
|
||||||
|
that.retryCount++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.runCallbackIfValid(mmsStatus, msg);
|
||||||
|
}).bind(this));
|
||||||
|
},
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
writable: true
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -682,44 +835,59 @@ RetrieveTransaction.prototype = {
|
||||||
* A callback function that takes two arguments: one for X-Mms-Status,
|
* A callback function that takes two arguments: one for X-Mms-Status,
|
||||||
* the other for the parsed M-Retrieve.conf message.
|
* the other for the parsed M-Retrieve.conf message.
|
||||||
*/
|
*/
|
||||||
retrieve: function retrieve(callback) {
|
retrieve: {
|
||||||
gMmsTransactionHelper.sendRequest("GET", this.contentLocation, null,
|
value: function retrieve(callback) {
|
||||||
(function (httpStatus, data) {
|
this.timer = null;
|
||||||
if ((httpStatus != HTTP_STATUS_OK) || !data) {
|
|
||||||
callback(MMS.MMS_PDU_STATUS_DEFERRED, null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let retrieved = MMS.PduHelper.parse(data, null);
|
this.cancellable =
|
||||||
if (!retrieved || (retrieved.type != MMS.MMS_PDU_TYPE_RETRIEVE_CONF)) {
|
gMmsTransactionHelper.sendRequest("GET", this.contentLocation, null,
|
||||||
callback(MMS.MMS_PDU_STATUS_UNRECOGNISED, null);
|
(function (httpStatus, data) {
|
||||||
return;
|
if (httpStatus == _HTTP_STATUS_USER_CANCELLED) {
|
||||||
}
|
callback(_MMS_ERROR_MESSAGE_DELETED, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Fix default header field values.
|
if ((httpStatus != HTTP_STATUS_OK) || !data) {
|
||||||
if (retrieved.headers["x-mms-delivery-report"] == null) {
|
callback(MMS.MMS_PDU_STATUS_DEFERRED, null);
|
||||||
retrieved.headers["x-mms-delivery-report"] = false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let retrieveStatus = retrieved.headers["x-mms-retrieve-status"];
|
let retrieved = MMS.PduHelper.parse(data, null);
|
||||||
if ((retrieveStatus != null) &&
|
if (!retrieved || (retrieved.type != MMS.MMS_PDU_TYPE_RETRIEVE_CONF)) {
|
||||||
(retrieveStatus != MMS.MMS_PDU_ERROR_OK)) {
|
callback(MMS.MMS_PDU_STATUS_UNRECOGNISED, null);
|
||||||
callback(MMS.translatePduErrorToStatus(retrieveStatus),
|
return;
|
||||||
retrieved);
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(MMS.MMS_PDU_STATUS_RETRIEVED, retrieved);
|
// Fix default header field values.
|
||||||
}).bind(this));
|
if (retrieved.headers["x-mms-delivery-report"] == null) {
|
||||||
|
retrieved.headers["x-mms-delivery-report"] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let retrieveStatus = retrieved.headers["x-mms-retrieve-status"];
|
||||||
|
if ((retrieveStatus != null) &&
|
||||||
|
(retrieveStatus != MMS.MMS_PDU_ERROR_OK)) {
|
||||||
|
callback(MMS.translatePduErrorToStatus(retrieveStatus), retrieved);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(MMS.MMS_PDU_STATUS_RETRIEVED, retrieved);
|
||||||
|
}).bind(this));
|
||||||
|
},
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
writable: true
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SendTransaction.
|
* SendTransaction.
|
||||||
* Class for sending M-Send.req to MMSC
|
* Class for sending M-Send.req to MMSC, which inherits CancellableTransaction.
|
||||||
* @throws Error("Check max values parameters fail.")
|
* @throws Error("Check max values parameters fail.")
|
||||||
*/
|
*/
|
||||||
function SendTransaction(msg) {
|
function SendTransaction(cancellableId, msg) {
|
||||||
|
// Call |CancellableTransaction| constructor.
|
||||||
|
CancellableTransaction.call(this, cancellableId);
|
||||||
|
|
||||||
msg.headers["x-mms-message-type"] = MMS.MMS_PDU_TYPE_SEND_REQ;
|
msg.headers["x-mms-message-type"] = MMS.MMS_PDU_TYPE_SEND_REQ;
|
||||||
if (!msg.headers["x-mms-transaction-id"]) {
|
if (!msg.headers["x-mms-transaction-id"]) {
|
||||||
// Create an unique transaction id
|
// Create an unique transaction id
|
||||||
|
@ -775,13 +943,13 @@ function SendTransaction(msg) {
|
||||||
|
|
||||||
this.msg = msg;
|
this.msg = msg;
|
||||||
}
|
}
|
||||||
SendTransaction.prototype = {
|
SendTransaction.prototype = Object.create(CancellableTransaction.prototype, {
|
||||||
/**
|
istreamComposed: {
|
||||||
* We need to keep a reference to the timer to assure the timer is fired.
|
value: false,
|
||||||
*/
|
enumerable: true,
|
||||||
timer: null,
|
configurable: true,
|
||||||
|
writable: true
|
||||||
istreamComposed: false,
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param parts
|
* @param parts
|
||||||
|
@ -789,42 +957,47 @@ SendTransaction.prototype = {
|
||||||
* @param callback [optional]
|
* @param callback [optional]
|
||||||
* A callback function that takes zero argument.
|
* A callback function that takes zero argument.
|
||||||
*/
|
*/
|
||||||
loadBlobs: function loadBlobs(parts, callback) {
|
loadBlobs: {
|
||||||
let callbackIfValid = function callbackIfValid() {
|
value: function loadBlobs(parts, callback) {
|
||||||
if (DEBUG) debug("All parts loaded: " + JSON.stringify(parts));
|
let callbackIfValid = function callbackIfValid() {
|
||||||
if (callback) {
|
if (DEBUG) debug("All parts loaded: " + JSON.stringify(parts));
|
||||||
callback();
|
if (callback) {
|
||||||
}
|
callback();
|
||||||
}
|
|
||||||
|
|
||||||
if (!parts || !parts.length) {
|
|
||||||
callbackIfValid();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let numPartsToLoad = parts.length;
|
|
||||||
for each (let part in parts) {
|
|
||||||
if (!(part.content instanceof Ci.nsIDOMBlob)) {
|
|
||||||
numPartsToLoad--;
|
|
||||||
if (!numPartsToLoad) {
|
|
||||||
callbackIfValid();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
let fileReader = Cc["@mozilla.org/files/filereader;1"]
|
|
||||||
.createInstance(Ci.nsIDOMFileReader);
|
if (!parts || !parts.length) {
|
||||||
fileReader.addEventListener("loadend",
|
callbackIfValid();
|
||||||
(function onloadend(part, event) {
|
return;
|
||||||
let arrayBuffer = event.target.result;
|
}
|
||||||
part.content = new Uint8Array(arrayBuffer);
|
|
||||||
numPartsToLoad--;
|
let numPartsToLoad = parts.length;
|
||||||
if (!numPartsToLoad) {
|
for each (let part in parts) {
|
||||||
callbackIfValid();
|
if (!(part.content instanceof Ci.nsIDOMBlob)) {
|
||||||
|
numPartsToLoad--;
|
||||||
|
if (!numPartsToLoad) {
|
||||||
|
callbackIfValid();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}).bind(null, part));
|
let fileReader = Cc["@mozilla.org/files/filereader;1"]
|
||||||
fileReader.readAsArrayBuffer(part.content);
|
.createInstance(Ci.nsIDOMFileReader);
|
||||||
};
|
fileReader.addEventListener("loadend",
|
||||||
|
(function onloadend(part, event) {
|
||||||
|
let arrayBuffer = event.target.result;
|
||||||
|
part.content = new Uint8Array(arrayBuffer);
|
||||||
|
numPartsToLoad--;
|
||||||
|
if (!numPartsToLoad) {
|
||||||
|
callbackIfValid();
|
||||||
|
}
|
||||||
|
}).bind(null, part));
|
||||||
|
fileReader.readAsArrayBuffer(part.content);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
writable: true
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -832,47 +1005,54 @@ SendTransaction.prototype = {
|
||||||
* A callback function that takes two arguments: one for
|
* A callback function that takes two arguments: one for
|
||||||
* X-Mms-Response-Status, the other for the parsed M-Send.conf message.
|
* X-Mms-Response-Status, the other for the parsed M-Send.conf message.
|
||||||
*/
|
*/
|
||||||
run: function run(callback) {
|
run: {
|
||||||
if (!this.istreamComposed) {
|
value: function run(callback) {
|
||||||
this.loadBlobs(this.msg.parts, (function () {
|
this.registerRunCallback(callback);
|
||||||
this.istream = MMS.PduHelper.compose(null, this.msg);
|
|
||||||
this.istreamComposed = true;
|
|
||||||
this.run(callback);
|
|
||||||
}).bind(this));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let callbackIfValid = function callbackIfValid(mmsStatus, msg) {
|
if (!this.istreamComposed) {
|
||||||
if (callback) {
|
this.loadBlobs(this.msg.parts, (function () {
|
||||||
callback(mmsStatus, msg);
|
this.istream = MMS.PduHelper.compose(null, this.msg);
|
||||||
}
|
this.istreamComposed = true;
|
||||||
}
|
if (this.isCancelled) {
|
||||||
|
this.runCallbackIfValid(_MMS_ERROR_MESSAGE_DELETED, null);
|
||||||
if (!this.istream) {
|
} else {
|
||||||
callbackIfValid(MMS.MMS_PDU_ERROR_PERMANENT_FAILURE, null);
|
this.run(callback);
|
||||||
return;
|
}
|
||||||
}
|
}).bind(this));
|
||||||
|
|
||||||
this.retryCount = 0;
|
|
||||||
let retryCallback = (function (mmsStatus, msg) {
|
|
||||||
if ((MMS.MMS_PDU_ERROR_TRANSIENT_FAILURE == mmsStatus ||
|
|
||||||
MMS.MMS_PDU_ERROR_PERMANENT_FAILURE == mmsStatus) &&
|
|
||||||
this.retryCount < PREF_SEND_RETRY_COUNT) {
|
|
||||||
if (this.timer == null) {
|
|
||||||
this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.retryCount++;
|
|
||||||
|
|
||||||
this.timer.initWithCallback(this.send.bind(this, retryCallback),
|
|
||||||
PREF_SEND_RETRY_INTERVAL,
|
|
||||||
Ci.nsITimer.TYPE_ONE_SHOT);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
callbackIfValid(mmsStatus, msg);
|
if (!this.istream) {
|
||||||
}).bind(this);
|
this.runCallbackIfValid(MMS.MMS_PDU_ERROR_PERMANENT_FAILURE, null);
|
||||||
this.send(retryCallback);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.retryCount = 0;
|
||||||
|
let retryCallback = (function (mmsStatus, msg) {
|
||||||
|
if ((MMS.MMS_PDU_ERROR_TRANSIENT_FAILURE == mmsStatus ||
|
||||||
|
MMS.MMS_PDU_ERROR_PERMANENT_FAILURE == mmsStatus) &&
|
||||||
|
this.retryCount < PREF_SEND_RETRY_COUNT) {
|
||||||
|
if (this.timer == null) {
|
||||||
|
this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.retryCount++;
|
||||||
|
|
||||||
|
this.timer.initWithCallback(this.send.bind(this, retryCallback),
|
||||||
|
PREF_SEND_RETRY_INTERVAL,
|
||||||
|
Ci.nsITimer.TYPE_ONE_SHOT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.runCallbackIfValid(mmsStatus, msg);
|
||||||
|
}).bind(this);
|
||||||
|
|
||||||
|
// This is the entry point to start sending.
|
||||||
|
this.send(retryCallback);
|
||||||
|
},
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
writable: true
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -880,30 +1060,44 @@ SendTransaction.prototype = {
|
||||||
* A callback function that takes two arguments: one for
|
* A callback function that takes two arguments: one for
|
||||||
* X-Mms-Response-Status, the other for the parsed M-Send.conf message.
|
* X-Mms-Response-Status, the other for the parsed M-Send.conf message.
|
||||||
*/
|
*/
|
||||||
send: function send(callback) {
|
send: {
|
||||||
gMmsTransactionHelper.sendRequest("POST", gMmsConnection.mmsc, this.istream,
|
value: function send(callback) {
|
||||||
function (httpStatus, data) {
|
this.timer = null;
|
||||||
if (httpStatus != HTTP_STATUS_OK) {
|
|
||||||
callback(MMS.MMS_PDU_ERROR_TRANSIENT_FAILURE, null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!data) {
|
this.cancellable =
|
||||||
callback(MMS.MMS_PDU_ERROR_PERMANENT_FAILURE, null);
|
gMmsTransactionHelper.sendRequest("POST", gMmsConnection.mmsc,
|
||||||
return;
|
this.istream,
|
||||||
}
|
function (httpStatus, data) {
|
||||||
|
if (httpStatus == _HTTP_STATUS_USER_CANCELLED) {
|
||||||
|
callback(_MMS_ERROR_MESSAGE_DELETED, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let response = MMS.PduHelper.parse(data, null);
|
if (httpStatus != HTTP_STATUS_OK) {
|
||||||
if (!response || (response.type != MMS.MMS_PDU_TYPE_SEND_CONF)) {
|
callback(MMS.MMS_PDU_ERROR_TRANSIENT_FAILURE, null);
|
||||||
callback(MMS.MMS_PDU_RESPONSE_ERROR_UNSUPPORTED_MESSAGE, null);
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let responseStatus = response.headers["x-mms-response-status"];
|
if (!data) {
|
||||||
callback(responseStatus, response);
|
callback(MMS.MMS_PDU_ERROR_PERMANENT_FAILURE, null);
|
||||||
});
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let response = MMS.PduHelper.parse(data, null);
|
||||||
|
if (!response || (response.type != MMS.MMS_PDU_TYPE_SEND_CONF)) {
|
||||||
|
callback(MMS.MMS_PDU_RESPONSE_ERROR_UNSUPPORTED_MESSAGE, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let responseStatus = response.headers["x-mms-response-status"];
|
||||||
|
callback(responseStatus, response);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
writable: true
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send M-acknowledge.ind back to MMSC.
|
* Send M-acknowledge.ind back to MMSC.
|
||||||
|
@ -1084,7 +1278,7 @@ MmsService.prototype = {
|
||||||
// Notifying observers an MMS message is retrieving.
|
// Notifying observers an MMS message is retrieving.
|
||||||
Services.obs.notifyObservers(aDomMessage, kSmsRetrievingObserverTopic, null);
|
Services.obs.notifyObservers(aDomMessage, kSmsRetrievingObserverTopic, null);
|
||||||
|
|
||||||
let transaction = new RetrieveTransaction(aContentLocation);
|
let transaction = new RetrieveTransaction(aDomMessage.id, aContentLocation);
|
||||||
transaction.run(aCallback);
|
transaction.run(aCallback);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1449,11 +1643,20 @@ MmsService.prototype = {
|
||||||
|
|
||||||
let self = this;
|
let self = this;
|
||||||
|
|
||||||
let sendTransactionCb = function sendTransactionCb(aRecordId, aErrorCode) {
|
let sendTransactionCb = function sendTransactionCb(aDomMessage, aErrorCode) {
|
||||||
if (DEBUG) debug("The error code of sending transaction: " + aErrorCode);
|
if (DEBUG) debug("The error code of sending transaction: " + aErrorCode);
|
||||||
|
|
||||||
|
// If the messsage has been deleted (because the sending process is
|
||||||
|
// cancelled), we don't need to reset the its delievery state/status.
|
||||||
|
if (aErrorCode == Ci.nsIMobileMessageCallback.NOT_FOUND_ERROR) {
|
||||||
|
aRequest.notifySendMessageFailed(aErrorCode);
|
||||||
|
Services.obs.notifyObservers(aDomMessage, kSmsFailedObserverTopic, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let isSentSuccess = (aErrorCode == Ci.nsIMobileMessageCallback.SUCCESS_NO_ERROR);
|
let isSentSuccess = (aErrorCode == Ci.nsIMobileMessageCallback.SUCCESS_NO_ERROR);
|
||||||
gMobileMessageDatabaseService
|
gMobileMessageDatabaseService
|
||||||
.setMessageDelivery(aRecordId,
|
.setMessageDelivery(aDomMessage.id,
|
||||||
null,
|
null,
|
||||||
isSentSuccess ? DELIVERY_SENT : DELIVERY_ERROR,
|
isSentSuccess ? DELIVERY_SENT : DELIVERY_ERROR,
|
||||||
isSentSuccess ? null : DELIVERY_STATUS_ERROR,
|
isSentSuccess ? null : DELIVERY_STATUS_ERROR,
|
||||||
|
@ -1488,14 +1691,16 @@ MmsService.prototype = {
|
||||||
// For radio disabled error.
|
// For radio disabled error.
|
||||||
if (gMmsConnection.radioDisabled) {
|
if (gMmsConnection.radioDisabled) {
|
||||||
if (DEBUG) debug("Error! Radio is disabled when sending MMS.");
|
if (DEBUG) debug("Error! Radio is disabled when sending MMS.");
|
||||||
sendTransactionCb(aDomMessage.id, Ci.nsIMobileMessageCallback.RADIO_DISABLED_ERROR);
|
sendTransactionCb(aDomMessage,
|
||||||
|
Ci.nsIMobileMessageCallback.RADIO_DISABLED_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For SIM card is not ready.
|
// For SIM card is not ready.
|
||||||
if (gRIL.rilContext.cardState != "ready") {
|
if (gRIL.rilContext.cardState != "ready") {
|
||||||
if (DEBUG) debug("Error! SIM card is not ready when sending MMS.");
|
if (DEBUG) debug("Error! SIM card is not ready when sending MMS.");
|
||||||
sendTransactionCb(aDomMessage.id, Ci.nsIMobileMessageCallback.NO_SIM_CARD_ERROR);
|
sendTransactionCb(aDomMessage,
|
||||||
|
Ci.nsIMobileMessageCallback.NO_SIM_CARD_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1503,18 +1708,25 @@ MmsService.prototype = {
|
||||||
Services.obs.notifyObservers(aDomMessage, kSmsSendingObserverTopic, null);
|
Services.obs.notifyObservers(aDomMessage, kSmsSendingObserverTopic, null);
|
||||||
let sendTransaction;
|
let sendTransaction;
|
||||||
try {
|
try {
|
||||||
sendTransaction = new SendTransaction(savableMessage);
|
sendTransaction = new SendTransaction(aDomMessage.id, savableMessage);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (DEBUG) debug("Exception: fail to create a SendTransaction instance.");
|
if (DEBUG) debug("Exception: fail to create a SendTransaction instance.");
|
||||||
sendTransactionCb(aDomMessage.id, Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
|
sendTransactionCb(aDomMessage,
|
||||||
|
Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sendTransaction.run(function callback(aMmsStatus, aMsg) {
|
sendTransaction.run(function callback(aMmsStatus, aMsg) {
|
||||||
let isSentSuccess = (aMmsStatus == MMS.MMS_PDU_ERROR_OK);
|
|
||||||
if (DEBUG) debug("The sending status of sendTransaction.run(): " + aMmsStatus);
|
if (DEBUG) debug("The sending status of sendTransaction.run(): " + aMmsStatus);
|
||||||
sendTransactionCb(aDomMessage.id, isSentSuccess?
|
let errorCode;
|
||||||
Ci.nsIMobileMessageCallback.SUCCESS_NO_ERROR:
|
if (aMmsStatus == _MMS_ERROR_MESSAGE_DELETED) {
|
||||||
Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
|
errorCode = Ci.nsIMobileMessageCallback.NOT_FOUND_ERROR;
|
||||||
|
} else if (aMmsStatus != MMS.MMS_PDU_ERROR_OK) {
|
||||||
|
errorCode = Ci.nsIMobileMessageCallback.INTERNAL_ERROR;
|
||||||
|
} else {
|
||||||
|
errorCode = Ci.nsIMobileMessageCallback.SUCCESS_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendTransactionCb(aDomMessage, errorCode);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -1571,6 +1783,13 @@ MmsService.prototype = {
|
||||||
// For X-Mms-Report-Allowed
|
// For X-Mms-Report-Allowed
|
||||||
let wish = aMessageRecord.headers["x-mms-delivery-report"];
|
let wish = aMessageRecord.headers["x-mms-delivery-report"];
|
||||||
let responseNotify = function responseNotify(mmsStatus, retrievedMsg) {
|
let responseNotify = function responseNotify(mmsStatus, retrievedMsg) {
|
||||||
|
// If the messsage has been deleted (because the retrieving process is
|
||||||
|
// cancelled), we don't need to reset the its delievery state/status.
|
||||||
|
if (mmsStatus == _MMS_ERROR_MESSAGE_DELETED) {
|
||||||
|
aRequest.notifyGetMessageFailed(Ci.nsIMobileMessageCallback.NOT_FOUND_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If the mmsStatus is still MMS_PDU_STATUS_DEFERRED after retry,
|
// If the mmsStatus is still MMS_PDU_STATUS_DEFERRED after retry,
|
||||||
// we should not store it into database and update its delivery
|
// we should not store it into database and update its delivery
|
||||||
// status to 'error'.
|
// status to 'error'.
|
||||||
|
|
|
@ -20,6 +20,9 @@ const RIL_GETTHREADSCURSOR_CID =
|
||||||
Components.ID("{95ee7c3e-d6f2-4ec4-ade5-0c453c036d35}");
|
Components.ID("{95ee7c3e-d6f2-4ec4-ade5-0c453c036d35}");
|
||||||
|
|
||||||
const DEBUG = false;
|
const DEBUG = false;
|
||||||
|
const DISABLE_MMS_GROUPING_FOR_RECEIVING = true;
|
||||||
|
|
||||||
|
|
||||||
const DB_NAME = "sms";
|
const DB_NAME = "sms";
|
||||||
const DB_VERSION = 11;
|
const DB_VERSION = 11;
|
||||||
const MESSAGE_STORE_NAME = "sms";
|
const MESSAGE_STORE_NAME = "sms";
|
||||||
|
@ -1133,13 +1136,15 @@ MobileMessageDatabaseService.prototype = {
|
||||||
let self = this.getRilIccInfoMsisdn();
|
let self = this.getRilIccInfoMsisdn();
|
||||||
let threadParticipants = [aMessage.sender];
|
let threadParticipants = [aMessage.sender];
|
||||||
if (aMessage.type == "sms") {
|
if (aMessage.type == "sms") {
|
||||||
// TODO Bug 853384 - for some SIMs we cannot retrieve the vaild
|
// For some SIMs we cannot retrieve the vaild MSISDN (i.e. the user's own
|
||||||
// phone number, thus setting the SMS' receiver to be null.
|
// phone number), thus setting the SMS' receiver to be null.
|
||||||
aMessage.receiver = self;
|
aMessage.receiver = self;
|
||||||
} else if (aMessage.type == "mms") {
|
} else if (aMessage.type == "mms" && !DISABLE_MMS_GROUPING_FOR_RECEIVING) {
|
||||||
let receivers = aMessage.receivers;
|
let receivers = aMessage.receivers;
|
||||||
// We need to add the receivers (excluding our own) into the participants
|
// If we don't want to disable the MMS grouping for receiving, we need to
|
||||||
// of a thread. Some cases we might encounter here:
|
// add the receivers (excluding the user's own number) to the participants
|
||||||
|
// for creating the thread. Some cases might be investigated as below:
|
||||||
|
//
|
||||||
// 1. receivers.length == 0
|
// 1. receivers.length == 0
|
||||||
// This usually happens when receiving an MMS notification indication
|
// This usually happens when receiving an MMS notification indication
|
||||||
// which doesn't carry any receivers.
|
// which doesn't carry any receivers.
|
||||||
|
@ -1148,18 +1153,25 @@ MobileMessageDatabaseService.prototype = {
|
||||||
// add it into participants because we know that number is our own.
|
// add it into participants because we know that number is our own.
|
||||||
// 3. receivers.length >= 2
|
// 3. receivers.length >= 2
|
||||||
// If the receivers contain multiple phone numbers, we need to add all
|
// If the receivers contain multiple phone numbers, we need to add all
|
||||||
// of them but not our own into participants.
|
// of them but not the user's own number into participants.
|
||||||
if (receivers.length >= 2) {
|
if (receivers.length >= 2) {
|
||||||
// TODO Bug 853384 - for some SIM cards, the phone number might not be
|
let isSuccess = false;
|
||||||
// available, so we cannot correcly exclude our own from the receivers,
|
|
||||||
// thus wrongly building the thread index.
|
|
||||||
let slicedReceivers = receivers.slice();
|
let slicedReceivers = receivers.slice();
|
||||||
if (self) {
|
if (self) {
|
||||||
let found = slicedReceivers.indexOf(self);
|
let found = slicedReceivers.indexOf(self);
|
||||||
if (found !== -1) {
|
if (found !== -1) {
|
||||||
|
isSuccess = true;
|
||||||
slicedReceivers.splice(found, 1);
|
slicedReceivers.splice(found, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isSuccess) {
|
||||||
|
// For some SIMs we cannot retrieve the vaild MSISDN (i.e. the user's
|
||||||
|
// own phone number), so we cannot correcly exclude the user's own
|
||||||
|
// number from the receivers, thus wrongly building the thread index.
|
||||||
|
if (DEBUG) debug("Error! Cannot strip out user's own phone number!");
|
||||||
|
}
|
||||||
|
|
||||||
threadParticipants = threadParticipants.concat(slicedReceivers);
|
threadParticipants = threadParticipants.concat(slicedReceivers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1220,8 +1232,8 @@ MobileMessageDatabaseService.prototype = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Bug 853384 - for some SIMs we cannot retrieve the vaild
|
// For some SIMs we cannot retrieve the vaild MSISDN (i.e. the user's own
|
||||||
// phone number, thus setting the message's sender to be null.
|
// phone number), thus setting the message's sender to be null.
|
||||||
aMessage.sender = this.getRilIccInfoMsisdn();
|
aMessage.sender = this.getRilIccInfoMsisdn();
|
||||||
let timestamp = aMessage.timestamp;
|
let timestamp = aMessage.timestamp;
|
||||||
|
|
||||||
|
@ -1542,7 +1554,11 @@ MobileMessageDatabaseService.prototype = {
|
||||||
messageRecord.threadId,
|
messageRecord.threadId,
|
||||||
messageId,
|
messageId,
|
||||||
messageRecord.read);
|
messageRecord.read);
|
||||||
};
|
|
||||||
|
Services.obs.notifyObservers(null,
|
||||||
|
"mobile-message-deleted",
|
||||||
|
JSON.stringify({ id: messageId }));
|
||||||
|
};
|
||||||
} else if (DEBUG) {
|
} else if (DEBUG) {
|
||||||
debug("Message id " + messageId + " does not exist");
|
debug("Message id " + messageId + " does not exist");
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче