зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound on a CLOSED TREE.
This commit is contained in:
Коммит
09b200b169
|
@ -9,10 +9,13 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
dump("======================= payment.js ======================= \n");
|
||||
let _DEBUG = false;
|
||||
function _debug(s) { dump("== Payment flow == " + s + "\n"); }
|
||||
_debug("Frame script injected");
|
||||
|
||||
let { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
||||
"@mozilla.org/childprocessmessagemanager;1",
|
||||
|
@ -23,23 +26,82 @@ XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
|
|||
"nsIUUIDGenerator");
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "mobileConnection",
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "iccProvider",
|
||||
"@mozilla.org/ril/content-helper;1",
|
||||
"nsIMobileConnectionProvider");
|
||||
#endif
|
||||
"nsIIccProvider");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "smsService",
|
||||
"@mozilla.org/sms/smsservice;1",
|
||||
"nsISmsService");
|
||||
|
||||
const kSilentSmsReceivedTopic = "silent-sms-received";
|
||||
|
||||
const MOBILEMESSAGECALLBACK_CID =
|
||||
Components.ID("{b484d8c9-6be4-4f94-ab60-c9c7ebcc853d}");
|
||||
|
||||
// In order to send messages through nsISmsService, we need to implement
|
||||
// nsIMobileMessageCallback, as the WebSMS API implementation is not usable
|
||||
// from JS.
|
||||
function SilentSmsRequest() {
|
||||
}
|
||||
SilentSmsRequest.prototype = {
|
||||
__exposedProps__: {
|
||||
onsuccess: 'rw',
|
||||
onerror: 'rw'
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileMessageCallback]),
|
||||
|
||||
classID: MOBILEMESSAGECALLBACK_CID,
|
||||
|
||||
set onsuccess(aSuccessCallback) {
|
||||
this._onsuccess = aSuccessCallback;
|
||||
},
|
||||
|
||||
set onerror(aErrorCallback) {
|
||||
this._onerror = aErrorCallback;
|
||||
},
|
||||
|
||||
notifyMessageSent: function notifyMessageSent(aMessage) {
|
||||
if (_DEBUG) {
|
||||
_debug("Silent message successfully sent");
|
||||
}
|
||||
this._onsuccess(aMessage);
|
||||
},
|
||||
|
||||
notifySendMessageFailed: function notifySendMessageFailed(aError) {
|
||||
if (_DEBUG) {
|
||||
_debug("Error sending silent message " + aError);
|
||||
}
|
||||
this._onerror(aError);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
const kClosePaymentFlowEvent = "close-payment-flow-dialog";
|
||||
|
||||
let _requestId;
|
||||
let gRequestId;
|
||||
|
||||
let gBrowser = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
|
||||
let PaymentProvider = {
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
__exposedProps__: {
|
||||
paymentSuccess: 'r',
|
||||
paymentFailed: 'r',
|
||||
iccIds: 'r'
|
||||
iccIds: 'r',
|
||||
mcc: 'r',
|
||||
mnc: 'r',
|
||||
sendSilentSms: 'r',
|
||||
observeSilentSms: 'r',
|
||||
removeSilentSmsObserver: 'r'
|
||||
},
|
||||
#else
|
||||
__exposedProps__: {
|
||||
paymentSuccess: 'r',
|
||||
paymentFailed: 'r'
|
||||
},
|
||||
#endif
|
||||
|
||||
_closePaymentFlowDialog: function _closePaymentFlowDialog(aCallback) {
|
||||
// After receiving the payment provider confirmation about the
|
||||
|
@ -47,8 +109,7 @@ let PaymentProvider = {
|
|||
// payment flow dialog and return to the caller application.
|
||||
let id = kClosePaymentFlowEvent + "-" + uuidgen.generateUUID().toString();
|
||||
|
||||
let browser = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let content = browser.getContentWindow();
|
||||
let content = gBrowser.getContentWindow();
|
||||
if (!content) {
|
||||
return;
|
||||
}
|
||||
|
@ -56,7 +117,7 @@ let PaymentProvider = {
|
|||
let detail = {
|
||||
type: kClosePaymentFlowEvent,
|
||||
id: id,
|
||||
requestId: _requestId
|
||||
requestId: gRequestId
|
||||
};
|
||||
|
||||
// In order to avoid race conditions, we wait for the UI to notify that
|
||||
|
@ -77,49 +138,176 @@ let PaymentProvider = {
|
|||
glue.cleanup();
|
||||
});
|
||||
|
||||
browser.shell.sendChromeEvent(detail);
|
||||
gBrowser.shell.sendChromeEvent(detail);
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
this._cleanUp();
|
||||
#endif
|
||||
},
|
||||
|
||||
paymentSuccess: function paymentSuccess(aResult) {
|
||||
if (_DEBUG) {
|
||||
_debug("paymentSuccess " + aResult);
|
||||
}
|
||||
|
||||
PaymentProvider._closePaymentFlowDialog(function notifySuccess() {
|
||||
if (!_requestId) {
|
||||
if (!gRequestId) {
|
||||
return;
|
||||
}
|
||||
cpmm.sendAsyncMessage("Payment:Success", { result: aResult,
|
||||
requestId: _requestId });
|
||||
requestId: gRequestId });
|
||||
});
|
||||
},
|
||||
|
||||
paymentFailed: function paymentFailed(aErrorMsg) {
|
||||
if (_DEBUG) {
|
||||
_debug("paymentFailed " + aErrorMsg);
|
||||
}
|
||||
|
||||
PaymentProvider._closePaymentFlowDialog(function notifyError() {
|
||||
if (!_requestId) {
|
||||
if (!gRequestId) {
|
||||
return;
|
||||
}
|
||||
cpmm.sendAsyncMessage("Payment:Failed", { errorMsg: aErrorMsg,
|
||||
requestId: _requestId });
|
||||
requestId: gRequestId });
|
||||
});
|
||||
},
|
||||
|
||||
get iccIds() {
|
||||
#ifdef MOZ_B2G_RIL
|
||||
// Until bug 814629 is done, we only have support for a single SIM, so we
|
||||
// can only provide a single ICC ID. However, we return an array so the
|
||||
// payment provider facing API won't need to change once we support
|
||||
// multiple SIMs.
|
||||
return [mobileConnection.iccInfo.iccid];
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
// Until bug 814629 is done, we only have support for a single SIM, so we
|
||||
// can only provide information for a single ICC. However, we return an array
|
||||
// so the payment provider facing API won't need to change once we support
|
||||
// multiple SIMs.
|
||||
|
||||
get iccIds() {
|
||||
return [iccProvider.iccInfo.iccid];
|
||||
},
|
||||
|
||||
get mcc() {
|
||||
return [iccProvider.iccInfo.mcc];
|
||||
},
|
||||
|
||||
get mnc() {
|
||||
return [iccProvider.iccInfo.mnc];
|
||||
},
|
||||
|
||||
_silentNumbers: null,
|
||||
_silentSmsObservers: null,
|
||||
|
||||
sendSilentSms: function sendSilentSms(aNumber, aMessage) {
|
||||
if (_DEBUG) {
|
||||
_debug("Sending silent message " + aNumber + " - " + aMessage);
|
||||
}
|
||||
|
||||
let request = new SilentSmsRequest();
|
||||
smsService.send(aNumber, aMessage, true, request);
|
||||
return request;
|
||||
},
|
||||
|
||||
observeSilentSms: function observeSilentSms(aNumber, aCallback) {
|
||||
if (_DEBUG) {
|
||||
_debug("observeSilentSms " + aNumber);
|
||||
}
|
||||
|
||||
if (!this._silentSmsObservers) {
|
||||
this._silentSmsObservers = {};
|
||||
this._silentNumbers = [];
|
||||
Services.obs.addObserver(this._onSilentSms.bind(this),
|
||||
kSilentSmsReceivedTopic,
|
||||
false);
|
||||
}
|
||||
|
||||
if (!this._silentSmsObservers[aNumber]) {
|
||||
this._silentSmsObservers[aNumber] = [];
|
||||
this._silentNumbers.push(aNumber);
|
||||
smsService.addSilentNumber(aNumber);
|
||||
}
|
||||
|
||||
if (this._silentSmsObservers[aNumber].indexOf(aCallback) == -1) {
|
||||
this._silentSmsObservers[aNumber].push(aCallback);
|
||||
}
|
||||
},
|
||||
|
||||
removeSilentSmsObserver: function removeSilentSmsObserver(aNumber, aCallback) {
|
||||
if (_DEBUG) {
|
||||
_debug("removeSilentSmsObserver " + aNumber);
|
||||
}
|
||||
|
||||
if (!this._silentSmsObservers || !this._silentSmsObservers[aNumber]) {
|
||||
if (_DEBUG) {
|
||||
_debug("No observers for " + aNumber);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let index = this._silentSmsObservers[aNumber].indexOf(aCallback);
|
||||
if (index != -1) {
|
||||
this._silentSmsObservers[aNumber].splice(index, 1);
|
||||
if (this._silentSmsObservers[aNumber].length == 0) {
|
||||
this._silentSmsObservers[aNumber] = null;
|
||||
this._silentNumbers.splice(this._silentNumbers.indexOf(aNumber), 1);
|
||||
smsService.removeSilentNumber(aNumber);
|
||||
}
|
||||
} else if (_DEBUG) {
|
||||
_debug("No callback found for " + aNumber);
|
||||
}
|
||||
},
|
||||
|
||||
_onSilentSms: function _onSilentSms(aSubject, aTopic, aData) {
|
||||
if (_DEBUG) {
|
||||
_debug("Got silent message! " + aSubject.sender + " - " + aSubject.body);
|
||||
}
|
||||
|
||||
let number = aSubject.sender;
|
||||
if (!number || this._silentNumbers.indexOf(number) == -1) {
|
||||
if (_DEBUG) {
|
||||
_debug("No observers for " + number);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this._silentSmsObservers[number].forEach(function(callback) {
|
||||
callback(aSubject);
|
||||
});
|
||||
},
|
||||
|
||||
_cleanUp: function _cleanUp() {
|
||||
if (_DEBUG) {
|
||||
_debug("Cleaning up!");
|
||||
}
|
||||
|
||||
if (!this._silentNumbers) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (this._silentNumbers.length) {
|
||||
let number = this._silentNumbers.pop();
|
||||
smsService.removeSilentNumber(number);
|
||||
}
|
||||
this._silentNumbers = null;
|
||||
this._silentSmsObservers = null;
|
||||
Services.obs.removeObserver(this._onSilentSms, kSilentSmsReceivedTopic);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
// We save the identifier of the DOM request, so we can dispatch the results
|
||||
// of the payment flow to the appropriate content process.
|
||||
addMessageListener("Payment:LoadShim", function receiveMessage(aMessage) {
|
||||
_requestId = aMessage.json.requestId;
|
||||
gRequestId = aMessage.json.requestId;
|
||||
});
|
||||
|
||||
addEventListener("DOMWindowCreated", function(e) {
|
||||
content.wrappedJSObject.mozPaymentProvider = PaymentProvider;
|
||||
});
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
// If the trusted dialog is not closed via paymentSuccess or paymentFailed
|
||||
// a mozContentEvent with type 'cancel' is sent from the UI. We need to listen
|
||||
// for this event to clean up the silent sms observers if any exists.
|
||||
gBrowser.getContentWindow().addEventListener("mozContentEvent", function(e) {
|
||||
if (e.detail.type === "cancel") {
|
||||
PaymentProvider._cleanUp();
|
||||
}
|
||||
});
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"revision": "74877b52dcb397d6de83b682ac5d374cc6d508be",
|
||||
"revision": "10f16f6a15f8a1c4b910548b4d0968baaac21c91",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -205,7 +205,6 @@ BluetoothA2dpManager::HandleSinkPropertyChanged(const BluetoothSignal& aSignal)
|
|||
MOZ_ASSERT(value.type() == BluetoothValue::Tbool);
|
||||
mA2dpConnected = value.get_bool();
|
||||
NotifyStatusChanged();
|
||||
NotifyAudioManager();
|
||||
} else if (name.EqualsLiteral("Playing")) {
|
||||
// Indicates if a stream is active to a A2DP sink on the remote device.
|
||||
MOZ_ASSERT(value.type() == BluetoothValue::Tbool);
|
||||
|
@ -259,6 +258,7 @@ BluetoothA2dpManager::NotifyStatusChanged()
|
|||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Broadcast system message to Gaia
|
||||
NS_NAMED_LITERAL_STRING(type, BLUETOOTH_A2DP_STATUS_CHANGED_ID);
|
||||
InfallibleTArray<BluetoothNamedValue> parameters;
|
||||
|
||||
|
@ -272,25 +272,16 @@ BluetoothA2dpManager::NotifyStatusChanged()
|
|||
|
||||
if (!BroadcastSystemMessage(type, parameters)) {
|
||||
NS_WARNING("Failed to broadcast system message to settings");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothA2dpManager::NotifyAudioManager()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Notify Gecko observers
|
||||
nsCOMPtr<nsIObserverService> obs =
|
||||
do_GetService("@mozilla.org/observer-service;1");
|
||||
NS_ENSURE_TRUE_VOID(obs);
|
||||
|
||||
nsAutoString data;
|
||||
data.AppendInt(mA2dpConnected);
|
||||
|
||||
if (NS_FAILED(obs->NotifyObservers(this,
|
||||
BLUETOOTH_A2DP_STATUS_CHANGED_ID,
|
||||
data.BeginReading()))) {
|
||||
mDeviceAddress.get()))) {
|
||||
NS_WARNING("Failed to notify bluetooth-a2dp-status-changed observsers!");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,13 +73,11 @@ private:
|
|||
void HandleShutdown();
|
||||
|
||||
void NotifyStatusChanged();
|
||||
void NotifyAudioManager();
|
||||
|
||||
nsString mDeviceAddress;
|
||||
|
||||
// A2DP data member
|
||||
bool mA2dpConnected;
|
||||
bool mPlaying;
|
||||
nsString mDeviceAddress;
|
||||
SinkState mSinkState;
|
||||
|
||||
// AVRCP data member
|
||||
|
|
|
@ -55,6 +55,7 @@ extern bool gBluetoothDebugFlag;
|
|||
* When connection status of Bluetooth profiles change, we'll notify observers
|
||||
* of following topics.
|
||||
*/
|
||||
#define BLUETOOTH_HFP_STATUS_CHANGED_ID "bluetooth-hfp-status-changed"
|
||||
#define BLUETOOTH_SCO_STATUS_CHANGED_ID "bluetooth-sco-status-changed"
|
||||
#define BLUETOOTH_A2DP_STATUS_CHANGED_ID "bluetooth-a2dp-status-changed"
|
||||
|
||||
|
|
|
@ -454,17 +454,18 @@ BluetoothHfpManager::Get()
|
|||
}
|
||||
|
||||
void
|
||||
BluetoothHfpManager::NotifyStatusChanged(const nsAString& aType)
|
||||
BluetoothHfpManager::NotifyStatusChanged(const char* aType)
|
||||
{
|
||||
nsString type, name;
|
||||
// Broadcast system message to Gaia
|
||||
BluetoothValue v;
|
||||
InfallibleTArray<BluetoothNamedValue> parameters;
|
||||
type = aType;
|
||||
|
||||
nsAutoString type, name;
|
||||
type = NS_ConvertUTF8toUTF16(aType);
|
||||
name.AssignLiteral("connected");
|
||||
if (type.EqualsLiteral("bluetooth-hfp-status-changed")) {
|
||||
|
||||
if (type.EqualsLiteral(BLUETOOTH_HFP_STATUS_CHANGED_ID)) {
|
||||
v = IsConnected();
|
||||
} else if (type.EqualsLiteral("bluetooth-sco-status-changed")) {
|
||||
} else if (type.EqualsLiteral(BLUETOOTH_SCO_STATUS_CHANGED_ID)) {
|
||||
v = IsScoConnected();
|
||||
} else {
|
||||
NS_WARNING("Wrong type for NotifyStatusChanged");
|
||||
|
@ -478,7 +479,15 @@ BluetoothHfpManager::NotifyStatusChanged(const nsAString& aType)
|
|||
|
||||
if (!BroadcastSystemMessage(type, parameters)) {
|
||||
NS_WARNING("Failed to broadcast system message to settings");
|
||||
return;
|
||||
}
|
||||
|
||||
// Notify Gecko observers
|
||||
nsCOMPtr<nsIObserverService> obs =
|
||||
do_GetService("@mozilla.org/observer-service;1");
|
||||
NS_ENSURE_TRUE_VOID(obs);
|
||||
|
||||
if (NS_FAILED(obs->NotifyObservers(this, aType, mDeviceAddress.get()))) {
|
||||
NS_WARNING("Failed to notify bluetooth-sco-status-changed observsers!");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -496,26 +505,6 @@ BluetoothHfpManager::NotifyDialer(const nsAString& aCommand)
|
|||
|
||||
if (!BroadcastSystemMessage(type, parameters)) {
|
||||
NS_WARNING("Failed to broadcast system message to dialer");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHfpManager::NotifyAudioManager(bool aStatus)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs =
|
||||
do_GetService("@mozilla.org/observer-service;1");
|
||||
NS_ENSURE_TRUE_VOID(obs);
|
||||
|
||||
nsAutoString data;
|
||||
data.AppendInt(aStatus);
|
||||
|
||||
if (NS_FAILED(obs->NotifyObservers(this,
|
||||
BLUETOOTH_SCO_STATUS_CHANGED_ID,
|
||||
data.BeginReading()))) {
|
||||
NS_WARNING("Failed to notify bluetooth-sco-status-changed observsers!");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1493,7 +1482,7 @@ BluetoothHfpManager::OnConnectSuccess(BluetoothSocket* aSocket)
|
|||
// Cache device path for NotifySettings() since we can't get socket address
|
||||
// when a headset disconnect with us
|
||||
mSocket->GetAddress(mDeviceAddress);
|
||||
NotifyStatusChanged(NS_LITERAL_STRING("bluetooth-hfp-status-changed"));
|
||||
NotifyStatusChanged(BLUETOOTH_HFP_STATUS_CHANGED_ID);
|
||||
|
||||
ListenSco();
|
||||
|
||||
|
@ -1548,7 +1537,7 @@ BluetoothHfpManager::OnDisconnect(BluetoothSocket* aSocket)
|
|||
DisconnectSco();
|
||||
|
||||
Listen();
|
||||
NotifyStatusChanged(NS_LITERAL_STRING("bluetooth-hfp-status-changed"));
|
||||
NotifyStatusChanged(BLUETOOTH_HFP_STATUS_CHANGED_ID);
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
@ -1628,8 +1617,7 @@ BluetoothHfpManager::OnScoConnectSuccess()
|
|||
mScoRunnable = nullptr;
|
||||
}
|
||||
|
||||
NotifyAudioManager(true);
|
||||
NotifyStatusChanged(NS_LITERAL_STRING("bluetooth-sco-status-changed"));
|
||||
NotifyStatusChanged(BLUETOOTH_SCO_STATUS_CHANGED_ID);
|
||||
|
||||
mScoSocketStatus = mScoSocket->GetConnectionStatus();
|
||||
}
|
||||
|
@ -1652,8 +1640,7 @@ BluetoothHfpManager::OnScoDisconnect()
|
|||
{
|
||||
if (mScoSocketStatus == SocketConnectionStatus::SOCKET_CONNECTED) {
|
||||
ListenSco();
|
||||
NotifyAudioManager(false);
|
||||
NotifyStatusChanged(NS_LITERAL_STRING("bluetooth-sco-status-changed"));
|
||||
NotifyStatusChanged(BLUETOOTH_SCO_STATUS_CHANGED_ID);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -118,8 +118,7 @@ private:
|
|||
uint32_t GetNumberOfCalls(uint16_t aState);
|
||||
|
||||
void NotifyDialer(const nsAString& aCommand);
|
||||
void NotifyStatusChanged(const nsAString& aType);
|
||||
void NotifyAudioManager(bool aStatus);
|
||||
void NotifyStatusChanged(const char* aType);
|
||||
|
||||
bool SendCommand(const char* aCommand, uint32_t aValue = 0);
|
||||
bool SendLine(const char* aMessage);
|
||||
|
|
|
@ -13,7 +13,7 @@ dictionary SmsThreadListItem
|
|||
unsigned long long unreadCount;
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(a22d9aae-ee0a-11e2-949e-e770d0d3883f)]
|
||||
[scriptable, uuid(ea5fb581-bee7-40a6-b2dc-c98b99a2dc49)]
|
||||
interface nsIMobileMessageCallback : nsISupports
|
||||
{
|
||||
/**
|
||||
|
|
|
@ -13,7 +13,7 @@ interface nsIMobileMessageCallback;
|
|||
#define SMS_SERVICE_CONTRACTID "@mozilla.org/sms/smsservice;1"
|
||||
%}
|
||||
|
||||
[scriptable, builtinclass, uuid(c4b2ed2a-8714-11e2-bd2b-13f1a0759342)]
|
||||
[scriptable, builtinclass, uuid(f0d5d11b-0326-4cb1-bb76-a3f912212287)]
|
||||
interface nsISmsService : nsISupports
|
||||
{
|
||||
boolean hasSupport();
|
||||
|
@ -22,5 +22,10 @@ interface nsISmsService : nsISupports
|
|||
|
||||
void send(in DOMString number,
|
||||
in DOMString message,
|
||||
in boolean silent,
|
||||
in nsIMobileMessageCallback request);
|
||||
|
||||
boolean isSilentNumber(in DOMString number);
|
||||
void addSilentNumber(in DOMString number);
|
||||
void removeSilentNumber(in DOMString number);
|
||||
};
|
||||
|
|
|
@ -14,6 +14,7 @@ const char* kSmsSentObserverTopic = "sms-sent";
|
|||
const char* kSmsFailedObserverTopic = "sms-failed";
|
||||
const char* kSmsDeliverySuccessObserverTopic = "sms-delivery-success";
|
||||
const char* kSmsDeliveryErrorObserverTopic = "sms-delivery-error";
|
||||
const char* kSilentSmsReceivedObserverTopic = "silent-sms-received";
|
||||
|
||||
} // namespace mobilemessage
|
||||
} // namespace dom
|
||||
|
|
|
@ -18,11 +18,7 @@ extern const char* kSmsSentObserverTopic;
|
|||
extern const char* kSmsFailedObserverTopic;
|
||||
extern const char* kSmsDeliverySuccessObserverTopic;
|
||||
extern const char* kSmsDeliveryErrorObserverTopic;
|
||||
|
||||
extern const char* kMmsSendingObserverTopic;
|
||||
extern const char* kMmsSentObserverTopic;
|
||||
extern const char* kMmsFailedObserverTopic;
|
||||
extern const char* kMmsReceivedObserverTopic;
|
||||
extern const char* kSilentSmsReceivedObserverTopic;
|
||||
|
||||
#define DELIVERY_RECEIVED NS_LITERAL_STRING("received")
|
||||
#define DELIVERY_SENDING NS_LITERAL_STRING("sending")
|
||||
|
|
|
@ -124,7 +124,8 @@ MobileMessageManager::Send(JSContext* aCx, JS::Handle<JSObject*> aGlobal,
|
|||
nsCOMPtr<nsIMobileMessageCallback> msgCallback =
|
||||
new MobileMessageCallback(request);
|
||||
|
||||
nsresult rv = smsService->Send(number, aMessage, msgCallback);
|
||||
// By default, we don't send silent messages via MobileMessageManager.
|
||||
nsresult rv = smsService->Send(number, aMessage, false, msgCallback);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JS::Rooted<JSObject*> global(aCx, aGlobal);
|
||||
|
|
|
@ -40,7 +40,9 @@ SmsService::GetSegmentInfoForText(const nsAString & aText,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsService::Send(const nsAString& aNumber, const nsAString& aMessage,
|
||||
SmsService::Send(const nsAString& aNumber,
|
||||
const nsAString& aMessage,
|
||||
const bool aSilent,
|
||||
nsIMobileMessageCallback* aRequest)
|
||||
{
|
||||
if (!AndroidBridge::Bridge()) {
|
||||
|
@ -51,6 +53,28 @@ SmsService::Send(const nsAString& aNumber, const nsAString& aMessage,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsService::IsSilentNumber(const nsAString& aNumber,
|
||||
bool* aIsSilent)
|
||||
{
|
||||
NS_NOTYETIMPLEMENTED("Implement me!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsService::AddSilentNumber(const nsAString& aNumber)
|
||||
{
|
||||
NS_NOTYETIMPLEMENTED("Implement me!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsService::RemoveSilentNumber(const nsAString& aNumber)
|
||||
{
|
||||
NS_NOTYETIMPLEMENTED("Implement me!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
} // namespace mobilemessage
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -32,10 +32,33 @@ SmsService::GetSegmentInfoForText(const nsAString & aText,
|
|||
NS_IMETHODIMP
|
||||
SmsService::Send(const nsAString& aNumber,
|
||||
const nsAString& aMessage,
|
||||
const bool aSilent,
|
||||
nsIMobileMessageCallback* aRequest)
|
||||
{
|
||||
NS_ERROR("We should not be here!");
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsService::IsSilentNumber(const nsAString& aNumber,
|
||||
bool* aIsSilent)
|
||||
{
|
||||
NS_ERROR("We should not be here!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsService::AddSilentNumber(const nsAString& aNumber)
|
||||
{
|
||||
NS_ERROR("We should not be here!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsService::RemoveSilentNumber(const nsAString& aNumber)
|
||||
{
|
||||
NS_ERROR("We should not be here!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
} // namespace mobilemessage
|
||||
|
|
|
@ -42,11 +42,42 @@ SmsService::GetSegmentInfoForText(const nsAString & aText,
|
|||
NS_IMETHODIMP
|
||||
SmsService::Send(const nsAString& aNumber,
|
||||
const nsAString& aMessage,
|
||||
const bool aSilent,
|
||||
nsIMobileMessageCallback* aRequest)
|
||||
{
|
||||
NS_ENSURE_TRUE(mRadioInterface, NS_ERROR_FAILURE);
|
||||
|
||||
return mRadioInterface->SendSMS(aNumber, aMessage, aRequest);
|
||||
return mRadioInterface->SendSMS(aNumber, aMessage, aSilent, aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsService::IsSilentNumber(const nsAString& aNumber,
|
||||
bool* aIsSilent)
|
||||
{
|
||||
*aIsSilent = mSilentNumbers.Contains(aNumber);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsService::AddSilentNumber(const nsAString& aNumber)
|
||||
{
|
||||
if (mSilentNumbers.Contains(aNumber)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(mSilentNumbers.AppendElement(aNumber), NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsService::RemoveSilentNumber(const nsAString& aNumber)
|
||||
{
|
||||
if (!mSilentNumbers.Contains(aNumber)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(mSilentNumbers.RemoveElement(aNumber), NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace mobilemessage
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "nsISmsService.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIRadioInterfaceLayer.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -23,6 +25,7 @@ public:
|
|||
protected:
|
||||
// TODO: Bug 854326 - B2G Multi-SIM: support multiple SIM cards for SMS/MMS
|
||||
nsCOMPtr<nsIRadioInterface> mRadioInterface;
|
||||
nsTArray<nsString> mSilentNumbers;
|
||||
};
|
||||
|
||||
} // namespace mobilemessage
|
||||
|
|
|
@ -26,6 +26,7 @@ struct SendSmsMessageRequest
|
|||
{
|
||||
nsString number;
|
||||
nsString message;
|
||||
bool silent;
|
||||
};
|
||||
|
||||
union SendMessageRequest
|
||||
|
@ -100,6 +101,8 @@ child:
|
|||
|
||||
NotifyDeliveryErrorMessage(MobileMessageData aMessageData);
|
||||
|
||||
NotifyReceivedSilentMessage(MobileMessageData aMessageData);
|
||||
|
||||
parent:
|
||||
/**
|
||||
* Sent when the child no longer needs to use sms.
|
||||
|
@ -121,6 +124,9 @@ parent:
|
|||
|
||||
sync GetSegmentInfoForText(nsString aText)
|
||||
returns (SmsSegmentInfoData aResult);
|
||||
|
||||
AddSilentNumber(nsString aNumber);
|
||||
RemoveSilentNumber(nsString aNumber);
|
||||
};
|
||||
|
||||
} // namespace mobilemessage
|
||||
|
|
|
@ -109,6 +109,13 @@ SmsChild::RecvNotifyDeliveryErrorMessage(const MobileMessageData& aData)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SmsChild::RecvNotifyReceivedSilentMessage(const MobileMessageData& aData)
|
||||
{
|
||||
NotifyObserversWithMobileMessage(kSilentSmsReceivedObserverTopic, aData);
|
||||
return true;
|
||||
}
|
||||
|
||||
PSmsRequestChild*
|
||||
SmsChild::AllocPSmsRequestChild(const IPCSmsRequest& aRequest)
|
||||
{
|
||||
|
|
|
@ -55,6 +55,9 @@ protected:
|
|||
virtual bool
|
||||
RecvNotifyDeliveryErrorMessage(const MobileMessageData& aMessage) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvNotifyReceivedSilentMessage(const MobileMessageData& aMessage) MOZ_OVERRIDE;
|
||||
|
||||
virtual PSmsRequestChild*
|
||||
AllocPSmsRequestChild(const IPCSmsRequest& aRequest) MOZ_OVERRIDE;
|
||||
|
||||
|
|
|
@ -115,13 +115,43 @@ SmsIPCService::GetSegmentInfoForText(const nsAString & aText,
|
|||
NS_IMETHODIMP
|
||||
SmsIPCService::Send(const nsAString& aNumber,
|
||||
const nsAString& aMessage,
|
||||
const bool aSilent,
|
||||
nsIMobileMessageCallback* aRequest)
|
||||
{
|
||||
return SendRequest(SendMessageRequest(SendSmsMessageRequest(nsString(aNumber),
|
||||
nsString(aMessage))),
|
||||
nsString(aMessage),
|
||||
aSilent)),
|
||||
aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsIPCService::IsSilentNumber(const nsAString& aNumber,
|
||||
bool* aIsSilent)
|
||||
{
|
||||
NS_ERROR("We should not be here!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsIPCService::AddSilentNumber(const nsAString& aNumber)
|
||||
{
|
||||
PSmsChild* smsChild = GetSmsChild();
|
||||
NS_ENSURE_TRUE(smsChild, NS_ERROR_FAILURE);
|
||||
|
||||
smsChild->SendAddSilentNumber(nsString(aNumber));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsIPCService::RemoveSilentNumber(const nsAString& aNumber)
|
||||
{
|
||||
PSmsChild* smsChild = GetSmsChild();
|
||||
NS_ENSURE_TRUE(smsChild, NS_ERROR_FAILURE);
|
||||
|
||||
smsChild->SendRemoveSilentNumber(nsString(aNumber));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of nsIMobileMessageDatabaseService.
|
||||
*/
|
||||
|
|
|
@ -151,6 +151,7 @@ SmsParent::SmsParent()
|
|||
obs->AddObserver(this, kSmsFailedObserverTopic, false);
|
||||
obs->AddObserver(this, kSmsDeliverySuccessObserverTopic, false);
|
||||
obs->AddObserver(this, kSmsDeliveryErrorObserverTopic, false);
|
||||
obs->AddObserver(this, kSilentSmsReceivedObserverTopic, false);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -168,6 +169,7 @@ SmsParent::ActorDestroy(ActorDestroyReason why)
|
|||
obs->RemoveObserver(this, kSmsFailedObserverTopic);
|
||||
obs->RemoveObserver(this, kSmsDeliverySuccessObserverTopic);
|
||||
obs->RemoveObserver(this, kSmsDeliveryErrorObserverTopic);
|
||||
obs->RemoveObserver(this, kSilentSmsReceivedObserverTopic);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -251,6 +253,24 @@ SmsParent::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, kSilentSmsReceivedObserverTopic)) {
|
||||
nsCOMPtr<nsIDOMMozSmsMessage> smsMsg = do_QueryInterface(aSubject);
|
||||
if (!smsMsg) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsString sender;
|
||||
if (NS_FAILED(smsMsg->GetSender(sender)) ||
|
||||
!mSilentNumbers.Contains(sender)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MobileMessageData msgData =
|
||||
static_cast<SmsMessage*>(smsMsg.get())->GetData();
|
||||
unused << SendNotifyReceivedSilentMessage(msgData);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -320,6 +340,42 @@ SmsParent::RecvGetSegmentInfoForText(const nsString& aText,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SmsParent::RecvAddSilentNumber(const nsString& aNumber)
|
||||
{
|
||||
if (mSilentNumbers.Contains(aNumber)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(smsService, true);
|
||||
|
||||
nsresult rv = smsService->AddSilentNumber(aNumber);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mSilentNumbers.AppendElement(aNumber);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SmsParent::RecvRemoveSilentNumber(const nsString& aNumber)
|
||||
{
|
||||
if (!mSilentNumbers.Contains(aNumber)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(smsService, true);
|
||||
|
||||
nsresult rv = smsService->RemoveSilentNumber(aNumber);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mSilentNumbers.RemoveElement(aNumber);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SmsParent::RecvPSmsRequestConstructor(PSmsRequestParent* aActor,
|
||||
const IPCSmsRequest& aRequest)
|
||||
|
@ -422,7 +478,7 @@ SmsRequestParent::DoRequest(const SendMessageRequest& aRequest)
|
|||
NS_ENSURE_TRUE(smsService, true);
|
||||
|
||||
const SendSmsMessageRequest &data = aRequest.get_SendSmsMessageRequest();
|
||||
smsService->Send(data.number(), data.message(), this);
|
||||
smsService->Send(data.number(), data.message(), data.silent(), this);
|
||||
}
|
||||
break;
|
||||
case SendMessageRequest::TSendMmsMessageRequest: {
|
||||
|
|
|
@ -37,6 +37,12 @@ protected:
|
|||
virtual bool
|
||||
RecvGetSegmentInfoForText(const nsString& aText, SmsSegmentInfoData* aResult) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvAddSilentNumber(const nsString& aNumber) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvRemoveSilentNumber(const nsString& aNumber) MOZ_OVERRIDE;
|
||||
|
||||
SmsParent();
|
||||
virtual ~SmsParent()
|
||||
{
|
||||
|
@ -68,6 +74,9 @@ protected:
|
|||
|
||||
bool
|
||||
GetMobileMessageDataFromMessage(nsISupports* aMsg, MobileMessageData& aData);
|
||||
|
||||
private:
|
||||
nsTArray<nsString> mSilentNumbers;
|
||||
};
|
||||
|
||||
class SmsRequestParent : public PSmsRequestParent
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothProfileManagerBase.h"
|
||||
#include "BluetoothHfpManager.h"
|
||||
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsCxPusher.h"
|
||||
|
@ -168,58 +169,78 @@ InternalSetAudioRoutes(SwitchState aState)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioManager::HandleBluetoothStatusChanged(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const nsCString aAddress)
|
||||
{
|
||||
bool status;
|
||||
if (!strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID)) {
|
||||
BluetoothHfpManager* hfp =
|
||||
static_cast<BluetoothHfpManager*>(aSubject);
|
||||
status = hfp->IsScoConnected();
|
||||
} else {
|
||||
BluetoothProfileManagerBase* profile =
|
||||
static_cast<BluetoothProfileManagerBase*>(aSubject);
|
||||
status = profile->IsConnected();
|
||||
}
|
||||
|
||||
audio_policy_dev_state_t audioState = status ?
|
||||
AUDIO_POLICY_DEVICE_STATE_AVAILABLE :
|
||||
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
|
||||
|
||||
if (!strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID)) {
|
||||
if (audioState == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
|
||||
String8 cmd;
|
||||
cmd.appendFormat("bt_samplerate=%d", kBtSampleRate);
|
||||
AudioSystem::setParameters(0, cmd);
|
||||
SetForceForUse(nsIAudioManager::USE_COMMUNICATION, nsIAudioManager::FORCE_BT_SCO);
|
||||
} else {
|
||||
int32_t force;
|
||||
GetForceForUse(nsIAudioManager::USE_COMMUNICATION, &force);
|
||||
if (force == nsIAudioManager::FORCE_BT_SCO)
|
||||
SetForceForUse(nsIAudioManager::USE_COMMUNICATION, nsIAudioManager::FORCE_NONE);
|
||||
}
|
||||
} else if (!strcmp(aTopic, BLUETOOTH_A2DP_STATUS_CHANGED_ID)) {
|
||||
AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
|
||||
audioState, aAddress.get());
|
||||
if (audioState == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
|
||||
String8 cmd("bluetooth_enabled=true");
|
||||
AudioSystem::setParameters(0, cmd);
|
||||
cmd.setTo("A2dpSuspended=false");
|
||||
AudioSystem::setParameters(0, cmd);
|
||||
} else {
|
||||
String8 cmd("bluetooth_enabled=false");
|
||||
AudioSystem::setParameters(0, cmd);
|
||||
cmd.setTo("A2dpSuspended=true");
|
||||
AudioSystem::setParameters(0, cmd);
|
||||
}
|
||||
} else if (!strcmp(aTopic, BLUETOOTH_HFP_STATUS_CHANGED_ID)) {
|
||||
AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
|
||||
audioState, aAddress.get());
|
||||
AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
|
||||
audioState, aAddress.get());
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
AudioManager::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const PRUnichar* aData)
|
||||
{
|
||||
if ((strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID) == 0) ||
|
||||
(strcmp(aTopic, BLUETOOTH_HFP_STATUS_CHANGED_ID) == 0) ||
|
||||
(strcmp(aTopic, BLUETOOTH_A2DP_STATUS_CHANGED_ID) == 0)) {
|
||||
nsresult rv;
|
||||
int status = NS_ConvertUTF16toUTF8(aData).ToInteger(&rv);
|
||||
if (NS_FAILED(rv) || status > 1 || status < 0) {
|
||||
NS_WARNING(nsPrintfCString("Wrong data value of %s", aTopic).get());
|
||||
nsCString address = NS_ConvertUTF16toUTF8(nsDependentString(aData));
|
||||
if (address.IsEmpty()) {
|
||||
NS_WARNING(nsPrintfCString("Invalid address of %s", aTopic).get());
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsAutoString tmp_address;
|
||||
BluetoothProfileManagerBase* profile =
|
||||
static_cast<BluetoothProfileManagerBase*>(aSubject);
|
||||
profile->GetAddress(tmp_address);
|
||||
nsAutoCString address = NS_ConvertUTF16toUTF8(tmp_address);
|
||||
|
||||
audio_policy_dev_state_t audioState = status ?
|
||||
AUDIO_POLICY_DEVICE_STATE_AVAILABLE :
|
||||
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
|
||||
|
||||
if (!strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID)) {
|
||||
AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
|
||||
audioState, address.get());
|
||||
AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
|
||||
audioState, address.get());
|
||||
if (audioState == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
|
||||
String8 cmd;
|
||||
cmd.appendFormat("bt_samplerate=%d", kBtSampleRate);
|
||||
AudioSystem::setParameters(0, cmd);
|
||||
SetForceForUse(nsIAudioManager::USE_COMMUNICATION, nsIAudioManager::FORCE_BT_SCO);
|
||||
} else {
|
||||
// only force to none if the current force setting is bt_sco
|
||||
int32_t force;
|
||||
GetForceForUse(nsIAudioManager::USE_COMMUNICATION, &force);
|
||||
if (force == nsIAudioManager::FORCE_BT_SCO)
|
||||
SetForceForUse(nsIAudioManager::USE_COMMUNICATION, nsIAudioManager::FORCE_NONE);
|
||||
}
|
||||
} else if (!strcmp(aTopic, BLUETOOTH_A2DP_STATUS_CHANGED_ID)) {
|
||||
AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
|
||||
audioState, address.get());
|
||||
if (audioState == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
|
||||
String8 cmd("bluetooth_enabled=true");
|
||||
AudioSystem::setParameters(0, cmd);
|
||||
cmd.setTo("A2dpSuspended=false");
|
||||
AudioSystem::setParameters(0, cmd);
|
||||
}
|
||||
}
|
||||
HandleBluetoothStatusChanged(aSubject, aTopic, address);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// To process the volume control on each audio channel according to
|
||||
// change of settings
|
||||
else if (!strcmp(aTopic, "mozsettings-changed")) {
|
||||
|
@ -315,6 +336,9 @@ AudioManager::AudioManager() : mPhoneState(PHONE_STATE_CURRENT),
|
|||
if (NS_FAILED(obs->AddObserver(this, "mozsettings-changed", false))) {
|
||||
NS_WARNING("Failed to add mozsettings-changed oberver!");
|
||||
}
|
||||
if (NS_FAILED(obs->AddObserver(this, BLUETOOTH_HFP_STATUS_CHANGED_ID, false))) {
|
||||
NS_WARNING("Failed to add bluetooth hfp status changed observer!");
|
||||
}
|
||||
|
||||
for (int loop = 0; loop < AUDIO_STREAM_CNT; loop++) {
|
||||
AudioSystem::initStreamVolume(static_cast<audio_stream_type_t>(loop), 0,
|
||||
|
@ -342,6 +366,9 @@ AudioManager::~AudioManager() {
|
|||
if (NS_FAILED(obs->RemoveObserver(this, BLUETOOTH_A2DP_STATUS_CHANGED_ID))) {
|
||||
NS_WARNING("Failed to remove bluetooth a2dp status changed observer!");
|
||||
}
|
||||
if (NS_FAILED(obs->RemoveObserver(this, BLUETOOTH_HFP_STATUS_CHANGED_ID))) {
|
||||
NS_WARNING("Failed to remove bluetooth hfp status changed observer!");
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -375,7 +402,12 @@ AudioManager::SetPhoneState(int32_t aState)
|
|||
if (mPhoneState == aState) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// follow the switch audio path logic for android, Bug 897364
|
||||
int usage;
|
||||
GetForceForUse(nsIAudioManager::USE_COMMUNICATION, &usage);
|
||||
if (aState == PHONE_STATE_NORMAL && usage == nsIAudioManager::FORCE_BT_SCO) {
|
||||
SetForceForUse(nsIAudioManager::USE_COMMUNICATION, nsIAudioManager::FORCE_NONE);
|
||||
}
|
||||
#if ANDROID_VERSION < 17
|
||||
if (AudioSystem::setPhoneState(aState)) {
|
||||
#else
|
||||
|
|
|
@ -64,6 +64,10 @@ protected:
|
|||
private:
|
||||
nsAutoPtr<mozilla::hal::SwitchObserver> mObserver;
|
||||
nsCOMPtr<AudioChannelAgent> mPhoneAudioAgent;
|
||||
|
||||
void HandleBluetoothStatusChanged(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const nsCString aAddress);
|
||||
};
|
||||
|
||||
} /* namespace gonk */
|
||||
|
|
|
@ -51,6 +51,7 @@ const nsITelephonyProvider = Ci.nsITelephonyProvider;
|
|||
|
||||
const kNetworkInterfaceStateChangedTopic = "network-interface-state-changed";
|
||||
const kSmsReceivedObserverTopic = "sms-received";
|
||||
const kSilentSmsReceivedObserverTopic = "silent-sms-received";
|
||||
const kSmsSendingObserverTopic = "sms-sending";
|
||||
const kSmsSentObserverTopic = "sms-sent";
|
||||
const kSmsFailedObserverTopic = "sms-failed";
|
||||
|
@ -145,6 +146,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "gMobileMessageService",
|
|||
"@mozilla.org/mobilemessage/mobilemessageservice;1",
|
||||
"nsIMobileMessageService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gSmsService",
|
||||
"@mozilla.org/sms/smsservice;1",
|
||||
"nsISmsService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gMobileMessageDatabaseService",
|
||||
"@mozilla.org/mobilemessage/rilmobilemessagedatabaseservice;1",
|
||||
"nsIRilMobileMessageDatabaseService");
|
||||
|
@ -1888,6 +1893,31 @@ RadioInterface.prototype = {
|
|||
message.body = message.fullBody = message.fullBody || null;
|
||||
message.timestamp = Date.now();
|
||||
|
||||
if (gSmsService.isSilentNumber(message.sender)) {
|
||||
message.id = -1;
|
||||
message.threadId = 0;
|
||||
message.delivery = DOM_MOBILE_MESSAGE_DELIVERY_RECEIVED;
|
||||
message.deliveryStatus = RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS;
|
||||
message.read = false;
|
||||
|
||||
let domMessage =
|
||||
gMobileMessageService.createSmsMessage(message.id,
|
||||
message.threadId,
|
||||
message.delivery,
|
||||
message.deliveryStatus,
|
||||
message.sender,
|
||||
message.receiver,
|
||||
message.body,
|
||||
message.messageClass,
|
||||
message.timestamp,
|
||||
message.read);
|
||||
|
||||
Services.obs.notifyObservers(domMessage,
|
||||
kSilentSmsReceivedObserverTopic,
|
||||
null);
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Bug #768441
|
||||
// For now we don't store indicators persistently. When the mwi.discard
|
||||
// flag is false, we'll need to persist the indicator to EFmwis.
|
||||
|
@ -1977,6 +2007,25 @@ RadioInterface.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
if (options.silent) {
|
||||
// There is no way to modify nsIDOMMozSmsMessage attributes as they are
|
||||
// read only so we just create a new sms instance to send along with
|
||||
// the notification.
|
||||
let sms = options.sms;
|
||||
options.request.notifyMessageSent(
|
||||
gMobileMessageService.createSmsMessage(sms.id,
|
||||
sms.threadId,
|
||||
DOM_MOBILE_MESSAGE_DELIVERY_SENT,
|
||||
sms.deliveryStatus,
|
||||
sms.sender,
|
||||
sms.receiver,
|
||||
sms.body,
|
||||
sms.messageClass,
|
||||
sms.timestamp,
|
||||
sms.read));
|
||||
return;
|
||||
}
|
||||
|
||||
gMobileMessageDatabaseService.setMessageDelivery(options.sms.id,
|
||||
null,
|
||||
DOM_MOBILE_MESSAGE_DELIVERY_SENT,
|
||||
|
@ -2006,6 +2055,10 @@ RadioInterface.prototype = {
|
|||
}
|
||||
delete this._sentSmsEnvelopes[message.envelopeId];
|
||||
|
||||
if (options.silent) {
|
||||
return;
|
||||
}
|
||||
|
||||
gMobileMessageDatabaseService.setMessageDelivery(options.sms.id,
|
||||
null,
|
||||
options.sms.delivery,
|
||||
|
@ -2035,6 +2088,11 @@ RadioInterface.prototype = {
|
|||
break;
|
||||
}
|
||||
|
||||
if (options.silent) {
|
||||
options.request.notifySendMessageFailed(error);
|
||||
return;
|
||||
}
|
||||
|
||||
gMobileMessageDatabaseService.setMessageDelivery(options.sms.id,
|
||||
null,
|
||||
DOM_MOBILE_MESSAGE_DELIVERY_ERROR,
|
||||
|
@ -3145,7 +3203,7 @@ RadioInterface.prototype = {
|
|||
return result;
|
||||
},
|
||||
|
||||
sendSMS: function sendSMS(number, message, request) {
|
||||
sendSMS: function sendSMS(number, message, silent, request) {
|
||||
let strict7BitEncoding;
|
||||
try {
|
||||
strict7BitEncoding = Services.prefs.getBoolPref("dom.sms.strict7BitEncoding");
|
||||
|
@ -3169,6 +3227,57 @@ RadioInterface.prototype = {
|
|||
options.segmentRef = this.nextSegmentRef;
|
||||
}
|
||||
|
||||
let notifyResult = (function notifyResult(rv, domMessage) {
|
||||
// TODO bug 832140 handle !Components.isSuccessCode(rv)
|
||||
if (!silent) {
|
||||
Services.obs.notifyObservers(domMessage, kSmsSendingObserverTopic, null);
|
||||
}
|
||||
|
||||
// If the radio is disabled or the SIM card is not ready, just directly
|
||||
// return with the corresponding error code.
|
||||
let errorCode;
|
||||
if (!PhoneNumberUtils.isPlainPhoneNumber(options.number)) {
|
||||
if (DEBUG) this.debug("Error! Address is invalid when sending SMS: " +
|
||||
options.number);
|
||||
errorCode = Ci.nsIMobileMessageCallback.INVALID_ADDRESS_ERROR;
|
||||
} else if (!this._radioEnabled) {
|
||||
if (DEBUG) this.debug("Error! Radio is disabled when sending SMS.");
|
||||
errorCode = Ci.nsIMobileMessageCallback.RADIO_DISABLED_ERROR;
|
||||
} else if (this.rilContext.cardState != "ready") {
|
||||
if (DEBUG) this.debug("Error! SIM card is not ready when sending SMS.");
|
||||
errorCode = Ci.nsIMobileMessageCallback.NO_SIM_CARD_ERROR;
|
||||
}
|
||||
if (errorCode) {
|
||||
if (silent) {
|
||||
request.notifySendMessageFailed(errorCode);
|
||||
return;
|
||||
}
|
||||
|
||||
gMobileMessageDatabaseService
|
||||
.setMessageDelivery(domMessage.id,
|
||||
null,
|
||||
DOM_MOBILE_MESSAGE_DELIVERY_ERROR,
|
||||
RIL.GECKO_SMS_DELIVERY_STATUS_ERROR,
|
||||
function notifyResult(rv, domMessage) {
|
||||
// TODO bug 832140 handle !Components.isSuccessCode(rv)
|
||||
request.notifySendMessageFailed(errorCode);
|
||||
Services.obs.notifyObservers(domMessage, kSmsFailedObserverTopic, null);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep current SMS message info for sent/delivered notifications
|
||||
options.envelopeId = this.createSmsEnvelope({
|
||||
request: request,
|
||||
sms: domMessage,
|
||||
requestStatusReport: options.requestStatusReport,
|
||||
silent: silent
|
||||
});
|
||||
|
||||
// This is the entry point starting to send SMS.
|
||||
this.worker.postMessage(options);
|
||||
}).bind(this);
|
||||
|
||||
let sendingMessage = {
|
||||
type: "sms",
|
||||
sender: this.getMsisdn(),
|
||||
|
@ -3178,52 +3287,26 @@ RadioInterface.prototype = {
|
|||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
if (silent) {
|
||||
let deliveryStatus = RIL.GECKO_SMS_DELIVERY_STATUS_PENDING;
|
||||
let delivery = DOM_MOBILE_MESSAGE_DELIVERY_SENDING;
|
||||
let domMessage =
|
||||
gMobileMessageService.createSmsMessage(-1, // id
|
||||
0, // threadId
|
||||
delivery,
|
||||
deliveryStatus,
|
||||
sendingMessage.sender,
|
||||
sendingMessage.receiver,
|
||||
sendingMessage.body,
|
||||
"normal", // message class
|
||||
sendingMessage.timestamp,
|
||||
false);
|
||||
notifyResult(Cr.NS_OK, domMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
let id = gMobileMessageDatabaseService.saveSendingMessage(
|
||||
sendingMessage,
|
||||
function notifyResult(rv, domMessage) {
|
||||
|
||||
// TODO bug 832140 handle !Components.isSuccessCode(rv)
|
||||
Services.obs.notifyObservers(domMessage, kSmsSendingObserverTopic, null);
|
||||
|
||||
// If the radio is disabled or the SIM card is not ready, just directly
|
||||
// return with the corresponding error code.
|
||||
let errorCode;
|
||||
if (!PhoneNumberUtils.isPlainPhoneNumber(options.number)) {
|
||||
if (DEBUG) this.debug("Error! Address is invalid when sending SMS: " +
|
||||
options.number);
|
||||
errorCode = Ci.nsIMobileMessageCallback.INVALID_ADDRESS_ERROR;
|
||||
} else if (!this._radioEnabled) {
|
||||
if (DEBUG) this.debug("Error! Radio is disabled when sending SMS.");
|
||||
errorCode = Ci.nsIMobileMessageCallback.RADIO_DISABLED_ERROR;
|
||||
} else if (this.rilContext.cardState != "ready") {
|
||||
if (DEBUG) this.debug("Error! SIM card is not ready when sending SMS.");
|
||||
errorCode = Ci.nsIMobileMessageCallback.NO_SIM_CARD_ERROR;
|
||||
}
|
||||
if (errorCode) {
|
||||
gMobileMessageDatabaseService
|
||||
.setMessageDelivery(domMessage.id,
|
||||
null,
|
||||
DOM_MOBILE_MESSAGE_DELIVERY_ERROR,
|
||||
RIL.GECKO_SMS_DELIVERY_STATUS_ERROR,
|
||||
function notifyResult(rv, domMessage) {
|
||||
// TODO bug 832140 handle !Components.isSuccessCode(rv)
|
||||
request.notifySendMessageFailed(errorCode);
|
||||
Services.obs.notifyObservers(domMessage, kSmsFailedObserverTopic, null);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep current SMS message info for sent/delivered notifications
|
||||
options.envelopeId = this.createSmsEnvelope({
|
||||
request: request,
|
||||
sms: domMessage,
|
||||
requestStatusReport: options.requestStatusReport
|
||||
});
|
||||
|
||||
// This is the entry point starting to send SMS.
|
||||
this.worker.postMessage(options);
|
||||
|
||||
}.bind(this));
|
||||
sendingMessage, notifyResult);
|
||||
},
|
||||
|
||||
registerDataCallCallback: function registerDataCallCallback(callback) {
|
||||
|
|
|
@ -79,7 +79,7 @@ interface nsIRilContext : nsISupports
|
|||
readonly attribute nsIDOMMozMobileConnectionInfo data;
|
||||
};
|
||||
|
||||
[scriptable, uuid(6dde3eaf-243d-4afa-abdb-95c94c2b1c7a)]
|
||||
[scriptable, uuid(715c972b-97c5-48fd-a8b1-d50e6852153a)]
|
||||
interface nsIRadioInterface : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -119,6 +119,7 @@ interface nsIRadioInterface : nsISupports
|
|||
|
||||
void sendSMS(in DOMString number,
|
||||
in DOMString message,
|
||||
in boolean silent,
|
||||
in nsIMobileMessageCallback request);
|
||||
};
|
||||
|
||||
|
|
|
@ -154,9 +154,9 @@ void
|
|||
nsVolume::LogState() const
|
||||
{
|
||||
if (mState == nsIVolume::STATE_MOUNTED) {
|
||||
LOG("nsVolume: %s state %s @ '%s' gen %d locked %d",
|
||||
LOG("nsVolume: %s state %s @ '%s' gen %d locked %d fake %d",
|
||||
NameStr().get(), StateStr(), MountPointStr().get(),
|
||||
MountGeneration(), (int)IsMountLocked());
|
||||
MountGeneration(), (int)IsMountLocked(), (int)IsFake());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -377,6 +377,7 @@ nsVolumeService::CreateFakeVolume(const nsAString& name, const nsAString& path)
|
|||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
nsRefPtr<nsVolume> vol = new nsVolume(name, path, nsIVolume::STATE_INIT, -1);
|
||||
vol->SetIsFake(true);
|
||||
vol->LogState();
|
||||
UpdateVolume(vol.get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -398,6 +399,7 @@ nsVolumeService::SetFakeVolumeState(const nsAString& name, int32_t state)
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
vol->SetState(state);
|
||||
vol->LogState();
|
||||
UpdateVolume(vol.get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Note: Removing this test will regress bug 754251. See comment above
|
||||
// ThreadActor._breakpointStore.
|
||||
// Test the functionality of the BreakpointStore object.
|
||||
|
||||
function run_test()
|
||||
{
|
||||
|
@ -13,9 +12,119 @@ function run_test()
|
|||
.getService(Components.interfaces.mozIJSSubScriptLoader);
|
||||
loader.loadSubScript("resource://gre/modules/devtools/server/actors/script.js");
|
||||
|
||||
test_bug_754251();
|
||||
test_add_breakpoint();
|
||||
test_remove_breakpoint();
|
||||
test_find_breakpoints();
|
||||
}
|
||||
|
||||
// Note: Removing this test will regress bug 754251. See comment above
|
||||
// ThreadActor._breakpointStore.
|
||||
function test_bug_754251() {
|
||||
let instance1 = new ThreadActor();
|
||||
let instance2 = new ThreadActor();
|
||||
do_check_eq(instance1._breakpointStore, ThreadActor._breakpointStore);
|
||||
do_check_eq(instance2._breakpointStore, ThreadActor._breakpointStore);
|
||||
do_check_eq(instance1._breakpointStore, instance2._breakpointStore);
|
||||
do_check_true(instance1.breakpointStore instanceof BreakpointStore);
|
||||
do_check_eq(instance1.breakpointStore, ThreadActor.breakpointStore);
|
||||
do_check_eq(instance2.breakpointStore, ThreadActor.breakpointStore);
|
||||
}
|
||||
|
||||
function test_add_breakpoint() {
|
||||
// Breakpoint with column
|
||||
let bpStore = new BreakpointStore();
|
||||
let location = {
|
||||
url: "http://example.com/foo.js",
|
||||
line: 10,
|
||||
column: 9
|
||||
};
|
||||
bpStore.addBreakpoint(location);
|
||||
do_check_true(!!bpStore.getBreakpoint(location, false),
|
||||
"We should have the column breakpoint we just added");
|
||||
|
||||
// Breakpoint without column (whole line breakpoint)
|
||||
location = {
|
||||
url: "http://example.com/bar.js",
|
||||
line: 103
|
||||
};
|
||||
bpStore.addBreakpoint(location);
|
||||
do_check_true(!!bpStore.getBreakpoint(location, false),
|
||||
"We should have the whole line breakpoint we just added");
|
||||
}
|
||||
|
||||
function test_remove_breakpoint() {
|
||||
// Breakpoint with column
|
||||
let bpStore = new BreakpointStore();
|
||||
let location = {
|
||||
url: "http://example.com/foo.js",
|
||||
line: 10,
|
||||
column: 9
|
||||
};
|
||||
bpStore.addBreakpoint(location);
|
||||
bpStore.removeBreakpoint(location);
|
||||
do_check_eq(bpStore.getBreakpoint(location, false), null,
|
||||
"We should not have the column breakpoint anymore");
|
||||
|
||||
// Breakpoint without column (whole line breakpoint)
|
||||
location = {
|
||||
url: "http://example.com/bar.js",
|
||||
line: 103
|
||||
};
|
||||
bpStore.addBreakpoint(location);
|
||||
bpStore.removeBreakpoint(location);
|
||||
do_check_eq(bpStore.getBreakpoint(location, false), null,
|
||||
"We should not have the whole line breakpoint anymore");
|
||||
}
|
||||
|
||||
function test_find_breakpoints() {
|
||||
let bps = [
|
||||
{ url: "foo.js", line: 10 },
|
||||
{ url: "foo.js", line: 10, column: 3 },
|
||||
{ url: "foo.js", line: 10, column: 10 },
|
||||
{ url: "foo.js", line: 23, column: 89 },
|
||||
{ url: "bar.js", line: 10, column: 1 },
|
||||
{ url: "bar.js", line: 20, column: 5 },
|
||||
{ url: "bar.js", line: 30, column: 34 },
|
||||
{ url: "bar.js", line: 40, column: 56 }
|
||||
];
|
||||
|
||||
let bpStore = new BreakpointStore();
|
||||
|
||||
for (let bp of bps) {
|
||||
bpStore.addBreakpoint(bp);
|
||||
}
|
||||
|
||||
// All breakpoints
|
||||
|
||||
let bpSet = Set(bps);
|
||||
for (let bp of bpStore.findBreakpoints()) {
|
||||
bpSet.delete(bp);
|
||||
}
|
||||
do_check_eq(bpSet.size, 0,
|
||||
"Should be able to iterate over all breakpoints");
|
||||
|
||||
// Breakpoints by URL
|
||||
|
||||
bpSet = Set(bps.filter(bp => { return bp.url === "foo.js" }));
|
||||
for (let bp of bpStore.findBreakpoints({ url: "foo.js" })) {
|
||||
bpSet.delete(bp);
|
||||
}
|
||||
do_check_eq(bpSet.size, 0,
|
||||
"Should be able to filter the iteration by url");
|
||||
|
||||
// Breakpoints by URL and line
|
||||
|
||||
bpSet = Set(bps.filter(bp => { return bp.url === "foo.js" && bp.line === 10; }));
|
||||
let first = true;
|
||||
for (let bp of bpStore.findBreakpoints({ url: "foo.js", line: 10 })) {
|
||||
if (first) {
|
||||
do_check_eq(bp.column, undefined,
|
||||
"Should always get the whole line breakpoint first");
|
||||
first = false;
|
||||
} else {
|
||||
do_check_neq(bp.column, undefined,
|
||||
"Should not get the whole line breakpoint any time other than first.");
|
||||
}
|
||||
bpSet.delete(bp);
|
||||
}
|
||||
do_check_eq(bpSet.size, 0,
|
||||
"Should be able to filter the iteration by url and line");
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче