Merge m-c to inbound.

This commit is contained in:
Ryan VanderMeulen 2013-11-04 16:31:13 -05:00
commit f204ac27b3
48 changed files with 1858 additions and 692 deletions

View File

@ -1,4 +1,4 @@
{
"revision": "a824661b83388d17f80c28a1d538eae382b3d07d",
"revision": "00ceae21c52602059b7614b661bc39a3c73c84de",
"repo_path": "/integration/gaia-central"
}

View File

@ -260,11 +260,6 @@ BluetoothAdapter::SetPropertyByValue(const BluetoothNamedValue& aValue)
} else if (name.EqualsLiteral("Devices")) {
mDeviceAddresses = value.get_ArrayOfnsString();
uint32_t length = mDeviceAddresses.Length();
for (int i = 0; i < length; i++) {
mDeviceAddresses[i] = GetAddressFromObjectPath(mDeviceAddresses[i]);
}
nsresult rv;
nsIScriptContext* sc = GetContextForEventHandlers(&rv);
NS_ENSURE_SUCCESS_VOID(rv);

View File

@ -8,7 +8,6 @@
#include "BluetoothOppManager.h"
#include "BluetoothProfileController.h"
#include "BluetoothReplyRunnable.h"
#include "BluetoothService.h"
#include "BluetoothSocket.h"
#include "BluetoothUtils.h"
@ -52,6 +51,18 @@ StaticRefPtr<BluetoothOppManager> sBluetoothOppManager;
static bool sInShutdown = false;
}
class mozilla::dom::bluetooth::SendFileBatch {
public:
SendFileBatch(const nsAString& aDeviceAddress, BlobParent* aActor)
: mDeviceAddress(aDeviceAddress)
{
mBlobs.AppendElement(aActor->GetBlob().get());
}
nsString mDeviceAddress;
nsCOMArray<nsIDOMBlob> mBlobs;
};
NS_IMETHODIMP
BluetoothOppManager::Observe(nsISupports* aSubject,
const char* aTopic,
@ -229,6 +240,44 @@ BluetoothOppManager::Get()
return sBluetoothOppManager;
}
void
BluetoothOppManager::ConnectInternal(const nsAString& aDeviceAddress)
{
MOZ_ASSERT(NS_IsMainThread());
// Stop listening because currently we only support one connection at a time.
if (mRfcommSocket) {
mRfcommSocket->Disconnect();
mRfcommSocket = nullptr;
}
if (mL2capSocket) {
mL2capSocket->Disconnect();
mL2capSocket = nullptr;
}
mIsServer = false;
BluetoothService* bs = BluetoothService::Get();
if (!bs || sInShutdown || mSocket) {
OnSocketConnectError(mSocket);
return;
}
mNeedsUpdatingSdpRecords = true;
nsString uuid;
BluetoothUuidHelper::GetString(BluetoothServiceClass::OBJECT_PUSH, uuid);
if (NS_FAILED(bs->GetServiceChannel(aDeviceAddress, uuid, this))) {
OnSocketConnectError(mSocket);
return;
}
mSocket =
new BluetoothSocket(this, BluetoothSocketType::RFCOMM, true, true);
}
void
BluetoothOppManager::Connect(const nsAString& aDeviceAddress,
BluetoothProfileController* aController)
@ -251,30 +300,8 @@ BluetoothOppManager::Connect(const nsAString& aDeviceAddress,
return;
}
mNeedsUpdatingSdpRecords = true;
nsString uuid;
BluetoothUuidHelper::GetString(BluetoothServiceClass::OBJECT_PUSH, uuid);
if (NS_FAILED(bs->GetServiceChannel(aDeviceAddress, uuid, this))) {
aController->OnConnect(NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
return;
}
// Stop listening because currently we only support one connection at a time.
if (mRfcommSocket) {
mRfcommSocket->Disconnect();
mRfcommSocket = nullptr;
}
if (mL2capSocket) {
mL2capSocket->Disconnect();
mL2capSocket = nullptr;
}
mController = aController;
mSocket =
new BluetoothSocket(this, BluetoothSocketType::RFCOMM, true, true);
OnConnect(EmptyString());
}
void
@ -336,6 +363,8 @@ BluetoothOppManager::Listen()
}
}
mIsServer = true;
return true;
}
@ -343,11 +372,12 @@ void
BluetoothOppManager::StartSendingNextFile()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!IsConnected());
MOZ_ASSERT(mBlobs.Length() > mCurrentBlobIndex + 1);
mIsServer = false;
mBlob = mBlobs[++mCurrentBlobIndex];
MOZ_ASSERT(!IsConnected());
MOZ_ASSERT(!mBatches.IsEmpty());
MOZ_ASSERT(mBatches[0].mBlobs.Length() > mCurrentBlobIndex + 1);
mBlob = mBatches[0].mBlobs[++mCurrentBlobIndex];
// Before sending content, we have to send a header including
// information such as file name, file length and content type.
@ -371,18 +401,90 @@ BluetoothOppManager::SendFile(const nsAString& aDeviceAddress,
{
MOZ_ASSERT(NS_IsMainThread());
if (mCurrentBlobIndex >= 0) {
if (mConnectedDeviceAddress != aDeviceAddress) {
return false;
}
AppendBlobToSend(aDeviceAddress, aActor);
if (!mSocket) {
ProcessNextBatch();
}
mBlobs.AppendElement(aActor->GetBlob().get());
return true;
}
void
BluetoothOppManager::AppendBlobToSend(const nsAString& aDeviceAddress,
BlobParent* aActor)
{
MOZ_ASSERT(NS_IsMainThread());
int indexTail = mBatches.Length() - 1;
/**
* Create a new batch if
* - mBatches is empty, or
* - aDeviceAddress differs from mDeviceAddress of the last batch
*/
if (mBatches.IsEmpty() ||
aDeviceAddress != mBatches[indexTail].mDeviceAddress) {
SendFileBatch batch(aDeviceAddress, aActor);
mBatches.AppendElement(batch);
} else {
mBatches[indexTail].mBlobs.AppendElement(aActor->GetBlob().get());
}
}
void
BluetoothOppManager::DiscardBlobsToSend()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mBatches.IsEmpty());
MOZ_ASSERT(!mIsServer);
int length = (int) mBatches[0].mBlobs.Length();
while (length > mCurrentBlobIndex + 1) {
mBlob = mBatches[0].mBlobs[++mCurrentBlobIndex];
BT_LOGR("%s: idx %d", __FUNCTION__, mCurrentBlobIndex);
ExtractBlobHeaders();
StartFileTransfer();
FileTransferComplete();
}
}
bool
BluetoothOppManager::ProcessNextBatch()
{
MOZ_ASSERT(NS_IsMainThread());
// Remove the processed batch.
// A batch is processed if we've incremented mCurrentBlobIndex for it.
if (mCurrentBlobIndex >= 0) {
ClearQueue();
mBatches.RemoveElementAt(0);
BT_LOGR("%s: REMOVE. %d remaining", __FUNCTION__, mBatches.Length());
}
// Process the next batch
if (!mBatches.IsEmpty()) {
ConnectInternal(mBatches[0].mDeviceAddress);
return true;
}
mBlobs.AppendElement(aActor->GetBlob().get());
StartSendingNextFile();
return true;
// No more batch to process
return false;
}
void
BluetoothOppManager::ClearQueue()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mIsServer);
MOZ_ASSERT(!mBatches.IsEmpty());
MOZ_ASSERT(!mBatches[0].mBlobs.IsEmpty());
mCurrentBlobIndex = -1;
mBlob = nullptr;
mBatches[0].mBlobs.Clear();
}
bool
@ -434,7 +536,6 @@ BluetoothOppManager::AfterFirstPut()
mUpdateProgressCounter = 1;
mPutFinalFlag = false;
mReceivedDataBufferOffset = 0;
mSendTransferCompleteFlag = false;
mSentFileLength = 0;
mWaitingToSendPutFinal = false;
mSuccessFlag = false;
@ -467,13 +568,10 @@ BluetoothOppManager::AfterOppDisconnected()
MOZ_ASSERT(NS_IsMainThread());
mConnected = false;
mIsServer = true;
mLastCommand = 0;
mPacketLeftLength = 0;
mDsFile = nullptr;
ClearQueue();
// We can't reset mSuccessFlag here since this function may be called
// before we send system message of transfer complete
// mSuccessFlag = false;
@ -548,7 +646,7 @@ BluetoothOppManager::WriteToFile(const uint8_t* aData, int aDataLength)
uint32_t wrote = 0;
mOutputStream->Write((const char*)aData, aDataLength, &wrote);
NS_ENSURE_TRUE(aDataLength == wrote, false);
NS_ENSURE_TRUE(aDataLength == (int) wrote, false);
return true;
}
@ -692,6 +790,8 @@ BluetoothOppManager::ValidateFileName()
void
BluetoothOppManager::ServerDataHandler(UnixSocketRawData* aMessage)
{
MOZ_ASSERT(NS_IsMainThread());
uint8_t opCode;
int packetLength;
int receivedLength = aMessage->mSize;
@ -715,8 +815,6 @@ BluetoothOppManager::ServerDataHandler(UnixSocketRawData* aMessage)
ObexHeaderSet pktHeaders(opCode);
if (opCode == ObexRequestCode::Connect) {
mIsServer = true;
// Section 3.3.1 "Connect", IrOBEX 1.2
// [opcode:1][length:2][version:1][flags:1][MaxPktSizeWeCanReceive:2]
// [Headers:var]
@ -842,20 +940,11 @@ BluetoothOppManager::ServerDataHandler(UnixSocketRawData* aMessage)
}
}
void
BluetoothOppManager::ClearQueue()
{
mCurrentBlobIndex = -1;
mBlob = nullptr;
while (!mBlobs.IsEmpty()) {
mBlobs.RemoveElement(mBlobs[0]);
}
}
void
BluetoothOppManager::ClientDataHandler(UnixSocketRawData* aMessage)
{
MOZ_ASSERT(NS_IsMainThread());
uint8_t opCode;
int packetLength;
@ -898,7 +987,7 @@ BluetoothOppManager::ClientDataHandler(UnixSocketRawData* aMessage)
mInputStream = nullptr;
}
if (mCurrentBlobIndex + 1 == mBlobs.Length()) {
if (mCurrentBlobIndex + 1 == (int) mBatches[0].mBlobs.Length()) {
SendDisconnectRequest();
} else {
StartSendingNextFile();
@ -927,7 +1016,7 @@ BluetoothOppManager::ClientDataHandler(UnixSocketRawData* aMessage)
mRemoteMaxPacketLength =
(((int)(aMessage->mData[5]) << 8) | aMessage->mData[6]);
sBluetoothOppManager->SendPutHeaderRequest(mFileName, mFileLength);
SendPutHeaderRequest(mFileName, mFileLength);
} else if (mLastCommand == ObexRequestCode::Put) {
if (mWaitingToSendPutFinal) {
SendPutFinalRequest();
@ -1261,6 +1350,8 @@ BluetoothOppManager::StartFileTransfer()
BT_WARNING("Failed to broadcast [bluetooth-opp-transfer-start]");
return;
}
mSendTransferCompleteFlag = false;
}
void
@ -1338,6 +1429,7 @@ BluetoothOppManager::NotifyAboutFileChange()
void
BluetoothOppManager::OnSocketConnectSuccess(BluetoothSocket* aSocket)
{
BT_LOGR("%s: [%s]", __FUNCTION__, (mIsServer)? "server" : "client");
MOZ_ASSERT(aSocket);
/**
@ -1364,21 +1456,36 @@ BluetoothOppManager::OnSocketConnectSuccess(BluetoothSocket* aSocket)
// device disconnect with us.
mSocket->GetAddress(mConnectedDeviceAddress);
OnConnect(EmptyString());
// Start sending file if we connect as a client
if (!mIsServer) {
StartSendingNextFile();
}
}
void
BluetoothOppManager::OnSocketConnectError(BluetoothSocket* aSocket)
{
BT_LOGR("%s: [%s]", __FUNCTION__, (mIsServer)? "server" : "client");
mRfcommSocket = nullptr;
mL2capSocket = nullptr;
mSocket = nullptr;
OnConnect(NS_LITERAL_STRING("SocketConnectionError"));
if (!mIsServer) {
// Inform gaia of remaining blobs' sending failure
DiscardBlobsToSend();
}
// Listen as a server if there's no more batch to process
if (!ProcessNextBatch()) {
Listen();
}
}
void
BluetoothOppManager::OnSocketDisconnect(BluetoothSocket* aSocket)
{
BT_LOGR("%s: [%s]", __FUNCTION__, (mIsServer)? "server" : "client");
MOZ_ASSERT(aSocket);
if (aSocket != mSocket) {
@ -1397,14 +1504,23 @@ BluetoothOppManager::OnSocketDisconnect(BluetoothSocket* aSocket)
if (mIsServer) {
DeleteReceivedFile();
}
FileTransferComplete();
if (!mIsServer) {
// Inform gaia of remaining blobs' sending failure
DiscardBlobsToSend();
}
}
AfterOppDisconnected();
mConnectedDeviceAddress.AssignLiteral(BLUETOOTH_ADDRESS_NONE);
mSuccessFlag = false;
OnDisconnect(EmptyString());
mSocket = nullptr;
// Listen as a server if there's no more batch to process
if (!ProcessNextBatch()) {
Listen();
}
}
void
@ -1423,14 +1539,14 @@ BluetoothOppManager::OnGetServiceChannel(const nsAString& aDeviceAddress,
mNeedsUpdatingSdpRecords = false;
bs->UpdateSdpRecords(aDeviceAddress, this);
} else {
OnConnect(NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
OnSocketConnectError(mSocket);
}
return;
}
if (!mSocket->Connect(NS_ConvertUTF16toUTF8(aDeviceAddress), aChannel)) {
OnConnect(NS_LITERAL_STRING("SocketConnectionError"));
OnSocketConnectError(mSocket);
}
}
@ -1447,7 +1563,7 @@ BluetoothOppManager::OnUpdateSdpRecords(const nsAString& aDeviceAddress)
BluetoothUuidHelper::GetString(BluetoothServiceClass::OBJECT_PUSH, uuid);
if (NS_FAILED(bs->GetServiceChannel(aDeviceAddress, uuid, this))) {
OnConnect(NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
OnSocketConnectError(mSocket);
}
}
@ -1491,9 +1607,6 @@ BluetoothOppManager::OnDisconnect(const nsAString& aErrorStr)
{
MOZ_ASSERT(NS_IsMainThread());
mSocket = nullptr;
Listen();
/**
* On the one hand, notify the controller that we've done for outbound
* connections. On the other hand, we do nothing for inbound connections.

View File

@ -23,6 +23,7 @@ BEGIN_BLUETOOTH_NAMESPACE
class BluetoothSocket;
class ObexHeaderSet;
class SendFileBatch;
class BluetoothOppManager : public BluetoothSocketObserver
, public BluetoothProfileManagerBase
@ -46,7 +47,7 @@ public:
bool Listen();
bool SendFile(const nsAString& aDeviceAddress, BlobParent* aBlob);
bool SendFile(const nsAString& aDeviceAddress, BlobParent* aActor);
bool StopSendingFile();
bool ConfirmReceivingFile(bool aConfirm);
@ -125,6 +126,10 @@ private:
void NotifyAboutFileChange();
bool AcquireSdcardMountLock();
void SendObexData(uint8_t* aData, uint8_t aOpcode, int aSize);
void AppendBlobToSend(const nsAString& aDeviceAddress, BlobParent* aActor);
void DiscardBlobsToSend();
bool ProcessNextBatch();
void ConnectInternal(const nsAString& aDeviceAddress);
/**
* OBEX session status.
@ -207,7 +212,7 @@ private:
int mCurrentBlobIndex;
nsCOMPtr<nsIDOMBlob> mBlob;
nsCOMArray<nsIDOMBlob> mBlobs;
nsTArray<SendFileBatch> mBatches;
/**
* A seperate member thread is required because our read calls can block

View File

@ -61,7 +61,6 @@ private:
/**
* Static variables
*/
static bluetooth_device_t* sBtDevice;
static const bt_interface_t* sBtInterface;
static bool sIsBtEnabled = false;
@ -69,11 +68,89 @@ static bool sAdapterDiscoverable = false;
static nsString sAdapterBdAddress;
static nsString sAdapterBdName;
static uint32_t sAdapterDiscoverableTimeout;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sChangeDiscoveryRunnableArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sSetPropertyRunnableArray;
/**
* Static callback functions
*/
static void
ClassToIcon(uint32_t aClass, nsAString& aRetIcon)
{
switch ((aClass & 0x1f00) >> 8) {
case 0x01:
aRetIcon.AssignLiteral("computer");
break;
case 0x02:
switch ((aClass & 0xfc) >> 2) {
case 0x01:
case 0x02:
case 0x03:
case 0x05:
aRetIcon.AssignLiteral("phone");
break;
case 0x04:
aRetIcon.AssignLiteral("modem");
break;
}
break;
case 0x03:
aRetIcon.AssignLiteral("network-wireless");
break;
case 0x04:
switch ((aClass & 0xfc) >> 2) {
case 0x01:
case 0x02:
case 0x06:
aRetIcon.AssignLiteral("audio-card");
break;
case 0x0b:
case 0x0c:
case 0x0d:
aRetIcon.AssignLiteral("camera-video");
break;
default:
aRetIcon.AssignLiteral("audio-card");
break;
}
break;
case 0x05:
switch ((aClass & 0xc0) >> 6) {
case 0x00:
switch ((aClass && 0x1e) >> 2) {
case 0x01:
case 0x02:
aRetIcon.AssignLiteral("input-gaming");
break;
}
break;
case 0x01:
aRetIcon.AssignLiteral("input-keyboard");
break;
case 0x02:
switch ((aClass && 0x1e) >> 2) {
case 0x05:
aRetIcon.AssignLiteral("input-tablet");
break;
default:
aRetIcon.AssignLiteral("input-mouse");
break;
}
}
break;
case 0x06:
if (aClass & 0x80) {
aRetIcon.AssignLiteral("printer");
break;
}
if (aClass & 0x20) {
aRetIcon.AssignLiteral("camera-photo");
break;
}
break;
}
}
static void
AdapterStateChangeCallback(bt_state_t aStatus)
{
@ -110,6 +187,16 @@ BdAddressTypeToString(bt_bdaddr_t* aBdAddressType, nsAString& aRetBdAddress)
aRetBdAddress = NS_ConvertUTF8toUTF16((char*)bdstr);
}
static bool
IsReady()
{
if (!sBtInterface || !sIsBtEnabled) {
BT_LOGR("Warning! Bluetooth Service is not ready");
return false;
}
return true;
}
static void
AdapterPropertiesChangeCallback(bt_status_t aStatus, int aNumProperties,
bt_property_t *aProperties)
@ -172,10 +259,110 @@ AdapterPropertiesChangeCallback(bt_status_t aStatus, int aNumProperties,
}
}
bt_callbacks_t sBluetoothCallbacks = {
static void
RemoteDevicePropertiesChangeCallback(bt_status_t aStatus,
bt_bdaddr_t *aBdAddress,
int aNumProperties,
bt_property_t *aProperties)
{
MOZ_ASSERT(!NS_IsMainThread());
// First, get remote device bd_address since it will be the key of
// return name value pair.
nsString remoteDeviceBdAddress;
BdAddressTypeToString(aBdAddress, remoteDeviceBdAddress);
InfallibleTArray<BluetoothNamedValue> deviceProperties;
for (int i = 0; i < aNumProperties; ++i) {
bt_property_t p = aProperties[i];
if (p.type == BT_PROPERTY_BDNAME) {
BluetoothValue propertyValue = NS_ConvertUTF8toUTF16((char*)p.val);
deviceProperties.AppendElement(
BluetoothNamedValue(NS_LITERAL_STRING("Name"), propertyValue));
} else if (p.type == BT_PROPERTY_CLASS_OF_DEVICE) {
uint32_t cod = *(uint32_t*)p.val;
deviceProperties.AppendElement(
BluetoothNamedValue(NS_LITERAL_STRING("Class"), BluetoothValue(cod)));
nsString icon;
ClassToIcon(cod, icon);
deviceProperties.AppendElement(
BluetoothNamedValue(NS_LITERAL_STRING("Icon"), BluetoothValue(icon)));
} else {
BT_LOGR("Other non-handled device properties. Type: %d", p.type);
}
}
}
static void
DeviceFoundCallback(int aNumProperties, bt_property_t *aProperties)
{
MOZ_ASSERT(!NS_IsMainThread());
BluetoothValue propertyValue;
InfallibleTArray<BluetoothNamedValue> propertiesArray;
for (int i = 0; i < aNumProperties; i++) {
bt_property_t p = aProperties[i];
if (p.type == BT_PROPERTY_BDADDR) {
nsString remoteDeviceBdAddress;
BdAddressTypeToString((bt_bdaddr_t*)p.val, remoteDeviceBdAddress);
propertyValue = remoteDeviceBdAddress;
propertiesArray.AppendElement(
BluetoothNamedValue(NS_LITERAL_STRING("Address"), propertyValue));
} else if (p.type == BT_PROPERTY_BDNAME) {
propertyValue = NS_ConvertUTF8toUTF16((char*)p.val);
propertiesArray.AppendElement(
BluetoothNamedValue(NS_LITERAL_STRING("Name"), propertyValue));
} else if (p.type == BT_PROPERTY_CLASS_OF_DEVICE) {
uint32_t cod = *(uint32_t*)p.val;
propertyValue = cod;
propertiesArray.AppendElement(
BluetoothNamedValue(NS_LITERAL_STRING("Class"), propertyValue));
nsString icon;
ClassToIcon(cod, icon);
propertyValue = icon;
propertiesArray.AppendElement(
BluetoothNamedValue(NS_LITERAL_STRING("Icon"), propertyValue));
} else {
BT_LOGD("Not handled remote device property: %d", p.type);
}
}
BluetoothValue value = propertiesArray;
BluetoothSignal signal(NS_LITERAL_STRING("DeviceFound"),
NS_LITERAL_STRING(KEY_ADAPTER), value);
nsRefPtr<DistributeBluetoothSignalTask>
t = new DistributeBluetoothSignalTask(signal);
if (NS_FAILED(NS_DispatchToMainThread(t))) {
NS_WARNING("Failed to dispatch to main thread!");
}
}
static void
DiscoveryStateChangedCallback(bt_discovery_state_t aState)
{
MOZ_ASSERT(!NS_IsMainThread());
if (!sChangeDiscoveryRunnableArray.IsEmpty()) {
BluetoothValue values(true);
DispatchBluetoothReply(sChangeDiscoveryRunnableArray[0],
values, EmptyString());
sChangeDiscoveryRunnableArray.RemoveElementAt(0);
}
}
bt_callbacks_t sBluetoothCallbacks =
{
sizeof(sBluetoothCallbacks),
AdapterStateChangeCallback,
AdapterPropertiesChangeCallback
AdapterPropertiesChangeCallback,
RemoteDevicePropertiesChangeCallback,
DeviceFoundCallback,
DiscoveryStateChangedCallback
};
/**
@ -335,6 +522,22 @@ nsresult
BluetoothServiceBluedroid::StartDiscoveryInternal(
BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
return NS_OK;
}
int ret = sBtInterface->start_discovery();
if (ret != BT_STATUS_SUCCESS) {
ReplyStatusError(aRunnable, ret, NS_LITERAL_STRING("StartDiscovery"));
return NS_OK;
}
sChangeDiscoveryRunnableArray.AppendElement(aRunnable);
return NS_OK;
}
@ -342,6 +545,20 @@ nsresult
BluetoothServiceBluedroid::StopDiscoveryInternal(
BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
return NS_OK;
}
int ret = sBtInterface->cancel_discovery();
if (ret != BT_STATUS_SUCCESS) {
ReplyStatusError(aRunnable, ret, NS_LITERAL_STRING("StopDiscovery"));
return NS_OK;
}
sChangeDiscoveryRunnableArray.AppendElement(aRunnable);
return NS_OK;
}
@ -359,6 +576,13 @@ BluetoothServiceBluedroid::SetProperty(BluetoothObjectType aType,
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
return NS_OK;
}
const nsString propName = aValue.name();
bt_property_t prop;
nsString str;

View File

@ -609,6 +609,7 @@ GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes,
propertyName.AssignASCII(aPropertyTypes[i].name);
*aPropIndex = i;
// Preprocessing
dbus_message_iter_recurse(&aIter, &prop_val);
expectedType = aPropertyTypes[*aPropIndex].type;
receivedType = dbus_message_iter_get_arg_type(&prop_val);
@ -621,6 +622,7 @@ GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes,
bool convert = false;
if (propertyName.EqualsLiteral("Connected") &&
receivedType == DBUS_TYPE_ARRAY) {
MOZ_ASSERT(aPropertyTypes == sDeviceProperties);
convert = true;
}
@ -631,6 +633,7 @@ GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes,
return false;
}
// Extract data
BluetoothValue propertyValue;
switch (receivedType) {
case DBUS_TYPE_STRING:
@ -682,11 +685,21 @@ GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes,
NS_NOTREACHED("Cannot find dbus message type!");
}
// Postprocessing
if (convert) {
MOZ_ASSERT(propertyValue.type() == BluetoothValue::TArrayOfuint8_t);
bool b = propertyValue.get_ArrayOfuint8_t()[0];
propertyValue = BluetoothValue(b);
} else if (propertyName.EqualsLiteral("Devices")) {
MOZ_ASSERT(aPropertyTypes == sAdapterProperties);
MOZ_ASSERT(propertyValue.type() == BluetoothValue::TArrayOfnsString);
uint32_t length = propertyValue.get_ArrayOfnsString().Length();
for (uint32_t i= 0; i < length; i++) {
nsString& data = propertyValue.get_ArrayOfnsString()[i];
data = GetAddressFromObjectPath(data);
}
}
aProperties.AppendElement(BluetoothNamedValue(propertyName, propertyValue));
@ -838,7 +851,7 @@ public:
InfallibleTArray<BluetoothNamedValue>& properties =
deviceProperties.get_ArrayOfBluetoothNamedValue();
InfallibleTArray<BluetoothNamedValue>::size_type i;
uint32_t i;
for (i = 0; i < properties.Length(); i++) {
if (properties[i].name().EqualsLiteral("Name")) {
properties[i].name().AssignLiteral("name");
@ -966,8 +979,8 @@ AgentEventFilter(DBusConnection *conn, DBusMessage *msg, void *data)
}
DBusMessage* reply = nullptr;
int i;
int length = sAuthorizedServiceClass.Length();
uint32_t length = sAuthorizedServiceClass.Length();
uint32_t i;
for (i = 0; i < length; i++) {
if (serviceClass == sAuthorizedServiceClass[i]) {
reply = dbus_message_new_method_return(msg);
@ -1412,7 +1425,7 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
GetObjectPathFromAddress(signalPath, address)));
if (!ContainsIcon(properties)) {
for (uint8_t i = 0; i < properties.Length(); i++) {
for (uint32_t i = 0; i < properties.Length(); i++) {
// It is possible that property Icon missed due to CoD of major
// class is TOY but service class is "Audio", we need to assign
// Icon as audio-card. This is for PTS test TC_AG_COD_BV_02_I.
@ -2091,8 +2104,7 @@ public:
// As HFP specification defined that
// service class is "Audio" can be considered as HFP AG.
if (!ContainsIcon(devicePropertiesArray)) {
InfallibleTArray<BluetoothNamedValue>::size_type j;
for (j = 0; j < devicePropertiesArray.Length(); ++j) {
for (uint32_t j = 0; j < devicePropertiesArray.Length(); ++j) {
BluetoothNamedValue& deviceProperty = devicePropertiesArray[j];
if (deviceProperty.name().EqualsLiteral("Class")) {
if (HasAudioService(deviceProperty.value().get_uint32_t())) {

View File

@ -11,18 +11,42 @@ interface nsIDOMDOMCursor;
interface nsIDOMDOMRequest;
interface nsIDOMBlob;
[scriptable, builtinclass, uuid(3f81dcbc-00cf-11e3-ae66-538115636543)]
[scriptable, builtinclass, uuid(0e4ff35e-ab84-434a-96b4-46807798cc7e)]
interface nsIDOMMozMobileMessageManager : nsIDOMEventTarget
{
nsIDOMDOMRequest getSegmentInfoForText(in DOMString text);
// The first parameter can be either a DOMString (only one number) or an array
// of DOMStrings.
// The method returns a DOMRequest object if one number has been passed.
// An array of DOMRequest objects otherwise.
jsval send(in jsval number, in DOMString message);
nsIDOMDOMRequest sendMMS(in jsval parameters /* MmsParameters */);
/**
* Function to send SMS.
*
* @param number
* Either a DOMString (only one number) or an array of numbers.
* @param message
* The text message to be sent.
* @param sendParameters
* An SmsSendParameters object.
* @param return
* A DOMRequest object indicating the sending result if one number
* has been passed; an array of DOMRequest objects otherwise.
*/
[implicit_jscontext, optional_argc]
jsval send(in jsval number, in DOMString message,
[optional] in jsval sendParameters);
/**
* Function to send MMS.
*
* @param parameters
* An MmsParameters object.
* @param sendParameters
* An MmsSendParameters object.
* @param return
* A DOMRequest object indicating the sending result.
*/
[implicit_jscontext, optional_argc]
nsIDOMDOMRequest sendMMS(in jsval parameters,
[optional] in jsval sendParameters);
[binaryname(GetMessageMoz)]
nsIDOMDOMRequest getMessage(in long id);
@ -33,7 +57,8 @@ interface nsIDOMMozMobileMessageManager : nsIDOMEventTarget
// Iterates through nsIDOMMoz{Mms,Sms}Message.
nsIDOMDOMCursor getMessages(in nsIDOMMozSmsFilter filter, in boolean reverse);
nsIDOMDOMRequest markMessageRead(in long id, in boolean aValue);
nsIDOMDOMRequest markMessageRead(in long id, in boolean value,
[optional] in boolean aSendReadReport);
// Iterates through nsIDOMMozMobileMessageThread.
nsIDOMDOMCursor getThreads();

View File

@ -21,7 +21,7 @@ dictionary MmsDeliveryInfo
DOMString? deliveryStatus;
};
[scriptable, builtinclass, uuid(494bbca1-ac7c-47d2-9e90-4e7d07e1cb4f)]
[scriptable, builtinclass, uuid(85bfc639-0d8f-43fa-8c12-6bd2958bf219)]
interface nsIDOMMozMmsMessage : nsISupports
{
/**
@ -33,6 +33,13 @@ interface nsIDOMMozMmsMessage : nsISupports
readonly attribute unsigned long long threadId;
/**
* Integrated Circuit Card Identifier.
*
* Will be null if ICC is not available.
*/
readonly attribute DOMString iccId;
/**
* Should be "not-downloaded", "received", "sending", "sent" or "error".
*/
@ -60,4 +67,7 @@ interface nsIDOMMozMmsMessage : nsISupports
readonly attribute jsval expiryDate; // Date object
// Expiry date for an MMS to be
// manually downloaded.
// Request read report from sender or not.
readonly attribute boolean isReadReportRequested;
};

View File

@ -4,7 +4,7 @@
#include "nsISupports.idl"
[scriptable, builtinclass, uuid(407b6d98-4140-11e3-9ec2-238ca8916558)]
[scriptable, builtinclass, uuid(db9ff254-2745-11e3-aa37-8793b90fc643)]
interface nsIDOMMozSmsMessage : nsISupports
{
/**
@ -16,6 +16,13 @@ interface nsIDOMMozSmsMessage : nsISupports
readonly attribute unsigned long long threadId;
/**
* Integrated Circuit Card Identifier.
*
* Will be null if ICC is not available.
*/
readonly attribute DOMString iccId;
/**
* Should be "received", "sending", "sent" or "error".
*/

View File

@ -12,14 +12,19 @@ interface nsIDOMBlob;
#define MMS_SERVICE_CONTRACTID "@mozilla.org/mms/mmsservice;1"
%}
[scriptable, uuid(5dc8b3bc-c3a9-45ea-8ee0-7562b0e57257)]
[scriptable, uuid(543278b3-d926-4c65-84b8-b49ad7a17d21)]
interface nsIMmsService : nsISupports
{
readonly attribute unsigned long mmsDefaultServiceId;
void send(in jsval parameters /* MmsParameters */,
void send(in unsigned long serviceId,
in jsval parameters /* MmsParameters */,
in nsIMobileMessageCallback request);
void retrieve(in long id,
in nsIMobileMessageCallback request);
void sendReadReport(in DOMString messageID,
in DOMString toAddress,
in DOMString iccId);
};

View File

@ -16,7 +16,7 @@ interface nsIDOMMozSmsFilter;
interface nsIMobileMessageCallback;
interface nsIMobileMessageCursorCallback;
[scriptable, uuid(ea6f49ae-3a4c-47eb-a489-15578e634100)]
[scriptable, uuid(8439916f-abc1-4c67-aa45-8a276a0a7855)]
interface nsIMobileMessageDatabaseService : nsISupports
{
[binaryname(GetMessageMoz)]
@ -33,6 +33,7 @@ interface nsIMobileMessageDatabaseService : nsISupports
void markMessageRead(in long messageId,
in boolean value,
in boolean sendReadReport,
in nsIMobileMessageCallback request);
nsICursorContinueCallback createThreadCursor(in nsIMobileMessageCursorCallback callback);

View File

@ -14,12 +14,13 @@ interface nsIDOMMozSmsSegmentInfo;
#define MOBILE_MESSAGE_SERVICE_CONTRACTID "@mozilla.org/mobilemessage/mobilemessageservice;1"
%}
[scriptable, builtinclass, uuid(11b7bda8-414b-11e3-8781-1b737e7958ae)]
[scriptable, builtinclass, uuid(7a39eeb4-827e-4c70-9804-288f94174ebe)]
interface nsIMobileMessageService : nsISupports
{
[implicit_jscontext]
nsIDOMMozSmsMessage createSmsMessage(in long id,
in unsigned long long threadId,
in DOMString iccId,
in DOMString delivery,
in DOMString deliveryStatus,
in DOMString sender,
@ -33,6 +34,7 @@ interface nsIMobileMessageService : nsISupports
[implicit_jscontext]
nsIDOMMozMmsMessage createMmsMessage(in long id,
in unsigned long long threadId,
in DOMString iccId,
in DOMString delivery,
in jsval deliveryInfo,
in DOMString sender,
@ -42,7 +44,8 @@ interface nsIMobileMessageService : nsISupports
in DOMString subject,
in DOMString smil,
in jsval attachments,
in jsval expiryDate);
in jsval expiryDate,
in boolean isReadReportRequested);
nsIDOMMozSmsSegmentInfo createSmsSegmentInfo(in long segments,
in long charsPerSegment,

View File

@ -33,6 +33,7 @@ interface nsIRilMobileMessageDatabaseService : nsIMobileMessageDatabaseService
* - |type| DOMString: "sms" or "mms"
* - |sender| DOMString: the phone number of sender
* - |timestamp| Number: the timestamp of received message
* - |iccId| DOMString: the ICC ID of the SIM for receiving message
*
* - If |type| == "sms", we also need:
* - |messageClass| DOMString: the message class of received message
@ -57,6 +58,7 @@ interface nsIRilMobileMessageDatabaseService : nsIMobileMessageDatabaseService
* - |sender| DOMString: the phone number of sender
* - |timestamp| Number: the timestamp of sending message
* - |deliveryStatusRequested| Bool: true when the delivery report is requested.
* - |iccId| DOMString: the ICC ID of the SIM for sending message
*
* - If |type| == "sms", we also need:
* - |receiver| DOMString: the phone number of receiver

View File

@ -13,7 +13,7 @@ interface nsIMobileMessageCallback;
#define SMS_SERVICE_CONTRACTID "@mozilla.org/sms/smsservice;1"
%}
[scriptable, builtinclass, uuid(ec3221fb-2d4a-4ccd-ac64-65c1b2dee5dd)]
[scriptable, builtinclass, uuid(6ac68d50-3d60-11e3-a8ff-ab5ddef5f2ba)]
interface nsISmsService : nsISupports
{
readonly attribute unsigned long smsDefaultServiceId;
@ -23,7 +23,8 @@ interface nsISmsService : nsISupports
void getSegmentInfoForText(in DOMString text,
in nsIMobileMessageCallback request);
void send(in DOMString number,
void send(in unsigned long serviceId,
in DOMString number,
in DOMString message,
in boolean silent,
in nsIMobileMessageCallback request);

View File

@ -34,7 +34,8 @@ NS_IMPL_ADDREF(MmsMessage)
NS_IMPL_RELEASE(MmsMessage)
MmsMessage::MmsMessage(int32_t aId,
const uint64_t aThreadId,
uint64_t aThreadId,
const nsAString& aIccId,
DeliveryState aDelivery,
const nsTArray<MmsDeliveryInfo>& aDeliveryInfo,
const nsAString& aSender,
@ -44,9 +45,11 @@ MmsMessage::MmsMessage(int32_t aId,
const nsAString& aSubject,
const nsAString& aSmil,
const nsTArray<MmsAttachment>& aAttachments,
uint64_t aExpiryDate)
uint64_t aExpiryDate,
bool aIsReadReportRequested)
: mId(aId),
mThreadId(aThreadId),
mIccId(aIccId),
mDelivery(aDelivery),
mDeliveryInfo(aDeliveryInfo),
mSender(aSender),
@ -56,13 +59,15 @@ MmsMessage::MmsMessage(int32_t aId,
mSubject(aSubject),
mSmil(aSmil),
mAttachments(aAttachments),
mExpiryDate(aExpiryDate)
mExpiryDate(aExpiryDate),
mIsReadReportRequested(aIsReadReportRequested)
{
}
MmsMessage::MmsMessage(const mobilemessage::MmsMessageData& aData)
: mId(aData.id())
, mThreadId(aData.threadId())
, mIccId(aData.iccId())
, mDelivery(aData.delivery())
, mSender(aData.sender())
, mReceivers(aData.receivers())
@ -71,6 +76,7 @@ MmsMessage::MmsMessage(const mobilemessage::MmsMessageData& aData)
, mSubject(aData.subject())
, mSmil(aData.smil())
, mExpiryDate(aData.expiryDate())
, mIsReadReportRequested(aData.isReadReportRequested())
{
uint32_t len = aData.attachments().Length();
mAttachments.SetCapacity(len);
@ -160,7 +166,8 @@ convertTimeToInt(JSContext* aCx, const JS::Value& aTime, uint64_t& aReturn)
/* static */ nsresult
MmsMessage::Create(int32_t aId,
const uint64_t aThreadId,
uint64_t aThreadId,
const nsAString& aIccId,
const nsAString& aDelivery,
const JS::Value& aDeliveryInfo,
const nsAString& aSender,
@ -171,6 +178,7 @@ MmsMessage::Create(int32_t aId,
const nsAString& aSmil,
const JS::Value& aAttachments,
const JS::Value& aExpiryDate,
bool aIsReadReportRequested,
JSContext* aCx,
nsIDOMMozMmsMessage** aMessage)
{
@ -280,6 +288,7 @@ MmsMessage::Create(int32_t aId,
nsCOMPtr<nsIDOMMozMmsMessage> message = new MmsMessage(aId,
aThreadId,
aIccId,
delivery,
deliveryInfo,
aSender,
@ -289,7 +298,8 @@ MmsMessage::Create(int32_t aId,
aSubject,
aSmil,
attachments,
expiryDate);
expiryDate,
aIsReadReportRequested);
message.forget(aMessage);
return NS_OK;
}
@ -302,6 +312,7 @@ MmsMessage::GetData(ContentParent* aParent,
aData.id() = mId;
aData.threadId() = mThreadId;
aData.iccId() = mIccId;
aData.delivery() = mDelivery;
aData.sender().Assign(mSender);
aData.receivers() = mReceivers;
@ -310,6 +321,7 @@ MmsMessage::GetData(ContentParent* aParent,
aData.subject() = mSubject;
aData.smil() = mSmil;
aData.expiryDate() = mExpiryDate;
aData.isReadReportRequested() = mIsReadReportRequested;
aData.deliveryInfo().SetCapacity(mDeliveryInfo.Length());
for (uint32_t i = 0; i < mDeliveryInfo.Length(); i++) {
@ -387,6 +399,13 @@ MmsMessage::GetThreadId(uint64_t* aThreadId)
return NS_OK;
}
NS_IMETHODIMP
MmsMessage::GetIccId(nsAString& aIccId)
{
aIccId = mIccId;
return NS_OK;
}
NS_IMETHODIMP
MmsMessage::GetDelivery(nsAString& aDelivery)
{
@ -601,5 +620,13 @@ MmsMessage::GetExpiryDate(JSContext* cx, JS::Value* aDate)
return NS_OK;
}
NS_IMETHODIMP
MmsMessage::GetIsReadReportRequested(bool* aIsReadReportRequested)
{
*aIsReadReportRequested = mIsReadReportRequested;
return NS_OK;
}
} // namespace dom
} // namespace mozilla

View File

@ -27,23 +27,26 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMMOZMMSMESSAGE
MmsMessage(int32_t aId,
const uint64_t aThreadId,
mobilemessage::DeliveryState aDelivery,
const nsTArray<idl::MmsDeliveryInfo>& aDeliveryInfo,
const nsAString& aSender,
const nsTArray<nsString>& aReceivers,
uint64_t aTimestamp,
bool aRead,
const nsAString& aSubject,
const nsAString& aSmil,
const nsTArray<idl::MmsAttachment>& aAttachments,
uint64_t aExpiryDate);
MmsMessage(int32_t aId,
uint64_t aThreadId,
const nsAString& aIccId,
mobilemessage::DeliveryState aDelivery,
const nsTArray<idl::MmsDeliveryInfo>& aDeliveryInfo,
const nsAString& aSender,
const nsTArray<nsString>& aReceivers,
uint64_t aTimestamp,
bool aRead,
const nsAString& aSubject,
const nsAString& aSmil,
const nsTArray<idl::MmsAttachment>& aAttachments,
uint64_t aExpiryDate,
bool aIsReadReportRequested);
MmsMessage(const mobilemessage::MmsMessageData& aData);
static nsresult Create(int32_t aId,
const uint64_t aThreadId,
uint64_t aThreadId,
const nsAString& aIccId,
const nsAString& aDelivery,
const JS::Value& aDeliveryInfo,
const nsAString& aSender,
@ -54,6 +57,7 @@ public:
const nsAString& aSmil,
const JS::Value& aAttachments,
const JS::Value& aExpiryDate,
bool aIsReadReportRequested,
JSContext* aCx,
nsIDOMMozMmsMessage** aMessage);
@ -62,18 +66,20 @@ public:
private:
int32_t mId;
uint64_t mThreadId;
mobilemessage::DeliveryState mDelivery;
nsTArray<idl::MmsDeliveryInfo> mDeliveryInfo;
nsString mSender;
nsTArray<nsString> mReceivers;
uint64_t mTimestamp;
bool mRead;
nsString mSubject;
nsString mSmil;
nsTArray<idl::MmsAttachment> mAttachments;
uint64_t mExpiryDate;
int32_t mId;
uint64_t mThreadId;
nsString mIccId;
mobilemessage::DeliveryState mDelivery;
nsTArray<idl::MmsDeliveryInfo> mDeliveryInfo;
nsString mSender;
nsTArray<nsString> mReceivers;
uint64_t mTimestamp;
bool mRead;
nsString mSubject;
nsString mSmil;
nsTArray<idl::MmsAttachment> mAttachments;
uint64_t mExpiryDate;
bool mIsReadReportRequested;
};
} // namespace dom

View File

@ -12,6 +12,8 @@
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "mozilla/dom/mobilemessage/Constants.h" // For MessageType
#include "mozilla/dom/MobileMessageManagerBinding.h"
#include "mozilla/dom/MozMmsMessageBinding.h"
#include "nsIDOMMozSmsEvent.h"
#include "nsIDOMMozMmsEvent.h"
#include "nsIDOMMozSmsMessage.h"
@ -118,8 +120,10 @@ MobileMessageManager::GetSegmentInfoForText(const nsAString& aText,
nsresult
MobileMessageManager::Send(JSContext* aCx, JS::Handle<JSObject*> aGlobal,
uint32_t aServiceId,
JS::Handle<JSString*> aNumber,
const nsAString& aMessage, JS::Value* aRequest)
const nsAString& aMessage,
JS::Value* aRequest)
{
nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
NS_ENSURE_TRUE(smsService, NS_ERROR_FAILURE);
@ -132,7 +136,8 @@ MobileMessageManager::Send(JSContext* aCx, JS::Handle<JSObject*> aGlobal,
new MobileMessageCallback(request);
// By default, we don't send silent messages via MobileMessageManager.
nsresult rv = smsService->Send(number, aMessage, false, msgCallback);
nsresult rv = smsService->Send(aServiceId, number, aMessage,
false, msgCallback);
NS_ENSURE_SUCCESS(rv, rv);
JS::Rooted<JSObject*> global(aCx, aGlobal);
@ -150,64 +155,107 @@ MobileMessageManager::Send(JSContext* aCx, JS::Handle<JSObject*> aGlobal,
}
NS_IMETHODIMP
MobileMessageManager::Send(const JS::Value& aNumber_, const nsAString& aMessage, JS::Value* aReturn)
MobileMessageManager::Send(const JS::Value& aNumber_,
const nsAString& aMessage,
const JS::Value& aSendParams,
JSContext* aCx,
uint8_t aArgc,
JS::Value* aReturn)
{
nsresult rv;
nsIScriptContext* sc = GetContextForEventHandlers(&rv);
NS_ENSURE_STATE(sc);
AutoPushJSContext cx(sc->GetNativeContext());
NS_ASSERTION(cx, "Failed to get a context!");
JS::Rooted<JS::Value> aNumber(cx, aNumber_);
JS::Rooted<JS::Value> aNumber(aCx, aNumber_);
if (!aNumber.isString() &&
!(aNumber.isObject() && JS_IsArrayObject(cx, &aNumber.toObject()))) {
!(aNumber.isObject() && JS_IsArrayObject(aCx, &aNumber.toObject()))) {
return NS_ERROR_INVALID_ARG;
}
JS::Rooted<JSObject*> global(cx, sc->GetWindowProxy());
nsresult rv;
nsIScriptContext* sc = GetContextForEventHandlers(&rv);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_STATE(sc);
JS::Rooted<JSObject*> global(aCx, sc->GetWindowProxy());
NS_ASSERTION(global, "Failed to get global object!");
JSAutoCompartment ac(cx, global);
JSAutoCompartment ac(aCx, global);
nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
NS_ENSURE_TRUE(smsService, NS_ERROR_FAILURE);
// Use the default one unless |aSendParams.serviceId| is available.
uint32_t serviceId;
rv = smsService->GetSmsDefaultServiceId(&serviceId);
NS_ENSURE_SUCCESS(rv, rv);
if (aArgc == 3) {
JS::Rooted<JS::Value> param(aCx, aSendParams);
RootedDictionary<SmsSendParameters> sendParams(aCx);
if (!sendParams.Init(aCx, param)) {
return NS_ERROR_TYPE_ERR;
}
if (sendParams.mServiceId.WasPassed()) {
serviceId = sendParams.mServiceId.Value();
}
}
if (aNumber.isString()) {
JS::Rooted<JSString*> str(cx, aNumber.toString());
return Send(cx, global, str, aMessage, aReturn);
JS::Rooted<JSString*> str(aCx, aNumber.toString());
return Send(aCx, global, serviceId, str, aMessage, aReturn);
}
// Must be an array then.
JS::Rooted<JSObject*> numbers(cx, &aNumber.toObject());
JS::Rooted<JSObject*> numbers(aCx, &aNumber.toObject());
uint32_t size;
JS_ALWAYS_TRUE(JS_GetArrayLength(cx, numbers, &size));
JS_ALWAYS_TRUE(JS_GetArrayLength(aCx, numbers, &size));
JS::Value* requests = new JS::Value[size];
JS::Rooted<JS::Value> number(cx);
for (uint32_t i=0; i<size; ++i) {
if (!JS_GetElement(cx, numbers, i, &number)) {
JS::Rooted<JS::Value> number(aCx);
for (uint32_t i = 0; i < size; ++i) {
if (!JS_GetElement(aCx, numbers, i, &number)) {
return NS_ERROR_INVALID_ARG;
}
JS::Rooted<JSString*> str(cx, number.toString());
nsresult rv = Send(cx, global, str, aMessage, &requests[i]);
JS::Rooted<JSString*> str(aCx, number.toString());
nsresult rv = Send(aCx, global, serviceId, str, aMessage, &requests[i]);
NS_ENSURE_SUCCESS(rv, rv);
}
aReturn->setObjectOrNull(JS_NewArrayObject(cx, size, requests));
aReturn->setObjectOrNull(JS_NewArrayObject(aCx, size, requests));
NS_ENSURE_TRUE(aReturn->isObject(), NS_ERROR_FAILURE);
return NS_OK;
}
NS_IMETHODIMP
MobileMessageManager::SendMMS(const JS::Value& aParams, nsIDOMDOMRequest** aRequest)
MobileMessageManager::SendMMS(const JS::Value& aParams,
const JS::Value& aSendParams,
JSContext* aCx,
uint8_t aArgc,
nsIDOMDOMRequest** aRequest)
{
nsCOMPtr<nsIMmsService> mmsService = do_GetService(MMS_SERVICE_CONTRACTID);
NS_ENSURE_TRUE(mmsService, NS_ERROR_FAILURE);
// Use the default one unless |aSendParams.serviceId| is available.
uint32_t serviceId;
nsresult rv = mmsService->GetMmsDefaultServiceId(&serviceId);
NS_ENSURE_SUCCESS(rv, rv);
if (aArgc == 2) {
JS::Rooted<JS::Value> param(aCx, aSendParams);
RootedDictionary<MmsSendParameters> sendParams(aCx);
if (!sendParams.Init(aCx, param)) {
return NS_ERROR_TYPE_ERR;
}
if (sendParams.mServiceId.WasPassed()) {
serviceId = sendParams.mServiceId.Value();
}
}
nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner());
nsCOMPtr<nsIMobileMessageCallback> msgCallback = new MobileMessageCallback(request);
nsresult rv = mmsService->Send(aParams, msgCallback);
rv = mmsService->Send(serviceId, aParams, msgCallback);
NS_ENSURE_SUCCESS(rv, rv);
request.forget(aRequest);
@ -349,6 +397,7 @@ MobileMessageManager::GetMessages(nsIDOMMozSmsFilter* aFilter,
NS_IMETHODIMP
MobileMessageManager::MarkMessageRead(int32_t aId, bool aValue,
bool aSendReadReport,
nsIDOMDOMRequest** aRequest)
{
nsCOMPtr<nsIMobileMessageDatabaseService> mobileMessageDBService =
@ -357,7 +406,9 @@ MobileMessageManager::MarkMessageRead(int32_t aId, bool aValue,
nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner());
nsCOMPtr<nsIMobileMessageCallback> msgCallback = new MobileMessageCallback(request);
nsresult rv = mobileMessageDBService->MarkMessageRead(aId, aValue, msgCallback);
nsresult rv = mobileMessageDBService->MarkMessageRead(aId, aValue,
aSendReadReport,
msgCallback);
NS_ENSURE_SUCCESS(rv, rv);
request.forget(aRequest);

View File

@ -35,8 +35,10 @@ private:
* Internal Send() method used to send one message.
*/
nsresult Send(JSContext* aCx, JS::Handle<JSObject*> aGlobal,
uint32_t aServiceId,
JS::Handle<JSString*> aNumber,
const nsAString& aMessage, JS::Value* aRequest);
const nsAString& aMessage,
JS::Value* aRequest);
nsresult DispatchTrustedSmsEventToSelf(const char* aTopic,
const nsAString& aEventName,

View File

@ -31,6 +31,7 @@ MobileMessageService::GetInstance()
NS_IMETHODIMP
MobileMessageService::CreateSmsMessage(int32_t aId,
uint64_t aThreadId,
const nsAString& aIccId,
const nsAString& aDelivery,
const nsAString& aDeliveryStatus,
const nsAString& aSender,
@ -45,6 +46,7 @@ MobileMessageService::CreateSmsMessage(int32_t aId,
{
return SmsMessage::Create(aId,
aThreadId,
aIccId,
aDelivery,
aDeliveryStatus,
aSender,
@ -61,6 +63,7 @@ MobileMessageService::CreateSmsMessage(int32_t aId,
NS_IMETHODIMP
MobileMessageService::CreateMmsMessage(int32_t aId,
uint64_t aThreadId,
const nsAString& aIccId,
const nsAString& aDelivery,
const JS::Value& aDeliveryInfo,
const nsAString& aSender,
@ -71,11 +74,13 @@ MobileMessageService::CreateMmsMessage(int32_t aId,
const nsAString& aSmil,
const JS::Value& aAttachments,
const JS::Value& aExpiryDate,
bool aIsReadReportRequested,
JSContext* aCx,
nsIDOMMozMmsMessage** aMessage)
{
return MmsMessage::Create(aId,
aThreadId,
aIccId,
aDelivery,
aDeliveryInfo,
aSender,
@ -86,6 +91,7 @@ MobileMessageService::CreateMmsMessage(int32_t aId,
aSmil,
aAttachments,
aExpiryDate,
aIsReadReportRequested,
aCx,
aMessage);
}

View File

@ -63,7 +63,8 @@ NS_IMPL_ADDREF(SmsMessage)
NS_IMPL_RELEASE(SmsMessage)
SmsMessage::SmsMessage(int32_t aId,
const uint64_t aThreadId,
uint64_t aThreadId,
const nsString& aIccId,
DeliveryState aDelivery,
DeliveryStatus aDeliveryStatus,
const nsString& aSender,
@ -73,8 +74,9 @@ SmsMessage::SmsMessage(int32_t aId,
uint64_t aTimestamp,
uint64_t aDeliveryTimestamp,
bool aRead)
: mData(aId, aThreadId, aDelivery, aDeliveryStatus, aSender, aReceiver, aBody,
aMessageClass, aTimestamp, aDeliveryTimestamp, aRead)
: mData(aId, aThreadId, aIccId, aDelivery, aDeliveryStatus,
aSender, aReceiver, aBody, aMessageClass, aTimestamp,
aDeliveryTimestamp, aRead)
{
}
@ -85,7 +87,8 @@ SmsMessage::SmsMessage(const SmsMessageData& aData)
/* static */ nsresult
SmsMessage::Create(int32_t aId,
const uint64_t aThreadId,
uint64_t aThreadId,
const nsAString& aIccId,
const nsAString& aDelivery,
const nsAString& aDeliveryStatus,
const nsAString& aSender,
@ -105,6 +108,7 @@ SmsMessage::Create(int32_t aId,
SmsMessageData data;
data.id() = aId;
data.threadId() = aThreadId;
data.iccId() = nsString(aIccId);
data.sender() = nsString(aSender);
data.receiver() = nsString(aReceiver);
data.body() = nsString(aBody);
@ -188,6 +192,13 @@ SmsMessage::GetThreadId(uint64_t* aThreadId)
return NS_OK;
}
NS_IMETHODIMP
SmsMessage::GetIccId(nsAString& aIccId)
{
aIccId = mData.iccId();
return NS_OK;
}
NS_IMETHODIMP
SmsMessage::GetDelivery(nsAString& aDelivery)
{

View File

@ -22,7 +22,8 @@ public:
NS_DECL_NSIDOMMOZSMSMESSAGE
SmsMessage(int32_t aId,
const uint64_t aThreadId,
uint64_t aThreadId,
const nsString& aIccId,
mobilemessage::DeliveryState aDelivery,
mobilemessage::DeliveryStatus aDeliveryStatus,
const nsString& aSender,
@ -35,7 +36,8 @@ public:
SmsMessage(const mobilemessage::SmsMessageData& aData);
static nsresult Create(int32_t aId,
const uint64_t aThreadId,
uint64_t aThreadId,
const nsAString& aIccId,
const nsAString& aDelivery,
const nsAString& aDeliveryStatus,
const nsAString& aSender,

View File

@ -21,7 +21,8 @@ MmsService::GetMmsDefaultServiceId(uint32_t* aServiceId)
}
NS_IMETHODIMP
MmsService::Send(const JS::Value& aParameters,
MmsService::Send(uint32_t aServiceid,
const JS::Value& aParameters,
nsIMobileMessageCallback *aRequest)
{
NS_NOTYETIMPLEMENTED("Implement me!");
@ -36,6 +37,15 @@ MmsService::Retrieve(int32_t aId, nsIMobileMessageCallback *aRequest)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MmsService::SendReadReport(const nsAString & messageID,
const nsAString & toAddress,
const nsAString & iccId)
{
NS_NOTYETIMPLEMENTED("Implement me!");
return NS_ERROR_NOT_IMPLEMENTED;
}
} // namespace mobilemessage
} // namespace dom
} // namespace mozilla

View File

@ -58,6 +58,7 @@ MobileMessageDatabaseService::CreateMessageCursor(nsIDOMMozSmsFilter* aFilter,
NS_IMETHODIMP
MobileMessageDatabaseService::MarkMessageRead(int32_t aMessageId,
bool aValue,
bool aSendReadReport,
nsIMobileMessageCallback* aRequest)
{
// TODO: This would need to be implemented as part of Bug 748391

View File

@ -44,7 +44,8 @@ SmsService::GetSegmentInfoForText(const nsAString& aText,
}
NS_IMETHODIMP
SmsService::Send(const nsAString& aNumber,
SmsService::Send(uint32_t aServiceId,
const nsAString& aNumber,
const nsAString& aMessage,
const bool aSilent,
nsIMobileMessageCallback* aRequest)

View File

@ -20,7 +20,8 @@ MmsService::GetMmsDefaultServiceId(uint32_t* aServiceId)
}
NS_IMETHODIMP
MmsService::Send(const JS::Value& aParameters,
MmsService::Send(uint32_t aServiceId,
const JS::Value& aParameters,
nsIMobileMessageCallback *aRequest)
{
NS_NOTYETIMPLEMENTED("Implement me!");
@ -34,6 +35,15 @@ MmsService::Retrieve(int32_t aId, nsIMobileMessageCallback *aRequest)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MmsService::SendReadReport(const nsAString & messageID,
const nsAString & toAddress,
const nsAString & iccId)
{
NS_NOTYETIMPLEMENTED("Implement me!");
return NS_ERROR_NOT_IMPLEMENTED;
}
} // namespace mobilemessage
} // namespace dom
} // namespace mozilla

View File

@ -41,6 +41,7 @@ MobileMessageDatabaseService::CreateMessageCursor(nsIDOMMozSmsFilter* aFilter,
NS_IMETHODIMP
MobileMessageDatabaseService::MarkMessageRead(int32_t aMessageId,
bool aValue,
bool aSendReadReport,
nsIMobileMessageCallback* aRequest)
{
NS_ERROR("We should not be here!");

View File

@ -36,7 +36,8 @@ SmsService::GetSegmentInfoForText(const nsAString& aText,
}
NS_IMETHODIMP
SmsService::Send(const nsAString& aNumber,
SmsService::Send(uint32_t aServiceId,
const nsAString& aNumber,
const nsAString& aMessage,
const bool aSilent,
nsIMobileMessageCallback* aRequest)

View File

@ -1626,6 +1626,12 @@ const MMS_PDU_TYPES = (function () {
add(MMS_PDU_TYPE_ACKNOWLEDGE_IND, false, ["x-mms-message-type",
"x-mms-transaction-id",
"x-mms-mms-version"]);
add(MMS_PDU_TYPE_READ_REC_IND, false, ["x-mms-message-type",
"message-id",
"x-mms-mms-version",
"to",
"from",
"x-mms-read-status"]);
return pdus;
})();
@ -1672,7 +1678,7 @@ const MMS_HEADER_FIELDS = (function () {
add("x-mms-transaction-id", 0x18, WSP.TextString);
add("x-mms-retrieve-status", 0x19, RetrieveStatusValue);
add("x-mms-retrieve-text", 0x1A, EncodedStringValue);
//add("x-mms-read-status", 0x1B);
add("x-mms-read-status", 0x1B, BooleanValue);
add("x-mms-reply-charging", 0x1C, ReplyChargingValue);
add("x-mms-reply-charging-deadline", 0x1D, ExpiryValue);
add("x-mms-reply-charging-id", 0x1E, WSP.TextString);

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@ const DISABLE_MMS_GROUPING_FOR_RECEIVING = true;
const DB_NAME = "sms";
const DB_VERSION = 15;
const DB_VERSION = 17;
const MESSAGE_STORE_NAME = "sms";
const THREAD_STORE_NAME = "thread";
const PARTICIPANT_STORE_NAME = "participant";
@ -65,6 +65,9 @@ const COLLECT_TIMESTAMP_UNUSED = 0;
XPCOMUtils.defineLazyServiceGetter(this, "gMobileMessageService",
"@mozilla.org/mobilemessage/mobilemessageservice;1",
"nsIMobileMessageService");
XPCOMUtils.defineLazyServiceGetter(this, "gMMSService",
"@mozilla.org/mms/rilmmsservice;1",
"nsIMmsService");
/**
* MobileMessageDatabaseService
@ -230,6 +233,14 @@ MobileMessageDatabaseService.prototype = {
self.upgradeSchema14(event.target.transaction, next);
break;
case 15:
if (DEBUG) debug("Upgrade to version 16. Add ICC ID for each message.");
self.upgradeSchema15(event.target.transaction, next);
break;
case 16:
if (DEBUG) debug("Upgrade to version 17. Add isReadReportSent for incoming MMS.");
self.upgradeSchema16(event.target.transaction, next);
break;
case 17:
// This will need to be moved for each new version
if (DEBUG) debug("Upgrade finished.");
break;
@ -1049,6 +1060,48 @@ MobileMessageDatabaseService.prototype = {
};
},
/**
* Add ICC ID.
*/
upgradeSchema15: function upgradeSchema15(transaction, next) {
let messageStore = transaction.objectStore(MESSAGE_STORE_NAME);
messageStore.openCursor().onsuccess = function(event) {
let cursor = event.target.result;
if (!cursor) {
next();
return;
}
let messageRecord = cursor.value;
messageRecord.iccId = null;
cursor.update(messageRecord);
cursor.continue();
};
},
/**
* Add isReadReportSent for incoming MMS.
*/
upgradeSchema16: function upgradeSchema16(transaction, next) {
let messageStore = transaction.objectStore(MESSAGE_STORE_NAME);
// Update type attributes.
messageStore.openCursor().onsuccess = function(event) {
let cursor = event.target.result;
if (!cursor) {
next();
return;
}
let messageRecord = cursor.value;
if (messageRecord.type == "mms") {
messageRecord.isReadReportSent = false;
cursor.update(messageRecord);
}
cursor.continue();
};
},
matchParsedPhoneNumbers: function matchParsedPhoneNumbers(addr1, parsedAddr1,
addr2, parsedAddr2) {
if ((parsedAddr1.internationalNumber &&
@ -1104,6 +1157,7 @@ MobileMessageDatabaseService.prototype = {
if (aMessageRecord.type == "sms") {
return gMobileMessageService.createSmsMessage(aMessageRecord.id,
aMessageRecord.threadId,
aMessageRecord.iccId,
aMessageRecord.delivery,
aMessageRecord.deliveryStatus,
aMessageRecord.sender,
@ -1157,8 +1211,10 @@ MobileMessageDatabaseService.prototype = {
if (headers["x-mms-expiry"] != undefined) {
expiryDate = aMessageRecord.timestamp + headers["x-mms-expiry"] * 1000;
}
let isReadReportRequested = headers["x-mms-read-report"] || false;
return gMobileMessageService.createMmsMessage(aMessageRecord.id,
aMessageRecord.threadId,
aMessageRecord.iccId,
aMessageRecord.delivery,
aMessageRecord.deliveryInfo,
aMessageRecord.sender,
@ -1168,7 +1224,8 @@ MobileMessageDatabaseService.prototype = {
subject,
smil,
attachments,
expiryDate);
expiryDate,
isReadReportRequested);
}
},
@ -1707,6 +1764,7 @@ MobileMessageDatabaseService.prototype = {
if (aMessage.type == "mms") {
aMessage.transactionIdIndex = aMessage.transactionId;
aMessage.isReadReportSent = false;
}
if (aMessage.type == "sms") {
@ -2034,7 +2092,7 @@ MobileMessageDatabaseService.prototype = {
return cursor;
},
markMessageRead: function markMessageRead(messageId, value, aRequest) {
markMessageRead: function markMessageRead(messageId, value, aSendReadReport, aRequest) {
if (DEBUG) debug("Setting message " + messageId + " read to " + value);
this.newTxn(READ_WRITE, function (error, txn, stores) {
if (error) {
@ -2042,10 +2100,12 @@ MobileMessageDatabaseService.prototype = {
aRequest.notifyMarkMessageReadFailed(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
return;
}
txn.onerror = function onerror(event) {
if (DEBUG) debug("Caught error on transaction ", event.target.errorCode);
aRequest.notifyMarkMessageReadFailed(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
};
let messageStore = stores[0];
let threadStore = stores[1];
messageStore.get(messageId).onsuccess = function onsuccess(event) {
@ -2055,6 +2115,7 @@ MobileMessageDatabaseService.prototype = {
aRequest.notifyMarkMessageReadFailed(Ci.nsIMobileMessageCallback.NOT_FOUND_ERROR);
return;
}
if (messageRecord.id != messageId) {
if (DEBUG) {
debug("Retrieve message ID (" + messageId + ") is " +
@ -2063,6 +2124,7 @@ MobileMessageDatabaseService.prototype = {
aRequest.notifyMarkMessageReadFailed(Ci.nsIMobileMessageCallback.UNKNOWN_ERROR);
return;
}
// If the value to be set is the same as the current message `read`
// value, we just notify successfully.
if (messageRecord.read == value) {
@ -2070,8 +2132,22 @@ MobileMessageDatabaseService.prototype = {
aRequest.notifyMessageMarkedRead(messageRecord.read);
return;
}
messageRecord.read = value ? FILTER_READ_READ : FILTER_READ_UNREAD;
messageRecord.readIndex = [messageRecord.read, messageRecord.timestamp];
let readReportMessageId, readReportTo;
if (aSendReadReport &&
messageRecord.type == "mms" &&
messageRecord.delivery == DELIVERY_RECEIVED &&
messageRecord.read == FILTER_READ_READ &&
!messageRecord.isReadReportSent) {
messageRecord.isReadReportSent = true;
let from = messageRecord.headers["from"];
readReportTo = from && from.address;
readReportMessageId = messageRecord.headers["message-id"];
}
if (DEBUG) debug("Message.read set to: " + value);
messageStore.put(messageRecord).onsuccess = function onsuccess(event) {
if (DEBUG) {
@ -2093,6 +2169,11 @@ MobileMessageDatabaseService.prototype = {
" -> " + threadRecord.unreadCount);
}
threadStore.put(threadRecord).onsuccess = function(event) {
if(readReportMessageId && readReportTo) {
gMMSService.sendReadReport(readReportMessageId,
readReportTo,
messageRecord.iccId);
}
aRequest.notifyMessageMarkedRead(messageRecord.read);
};
};

View File

@ -43,11 +43,8 @@ NS_IMPL_ISUPPORTS2(SmsService,
SmsService::SmsService()
{
nsCOMPtr<nsIRadioInterfaceLayer> ril = do_GetService("@mozilla.org/ril;1");
if (ril) {
ril->GetRadioInterface(0, getter_AddRefs(mRadioInterface));
}
NS_WARN_IF_FALSE(mRadioInterface, "This shouldn't fail!");
mRil = do_GetService("@mozilla.org/ril;1");
NS_WARN_IF_FALSE(mRil, "This shouldn't fail!");
// Initialize observer.
Preferences::AddStrongObservers(this, kObservedPrefs);
@ -97,20 +94,29 @@ NS_IMETHODIMP
SmsService::GetSegmentInfoForText(const nsAString& aText,
nsIMobileMessageCallback* aRequest)
{
NS_ENSURE_TRUE(mRadioInterface, NS_ERROR_FAILURE);
nsCOMPtr<nsIRadioInterface> radioInterface;
if (mRil) {
mRil->GetRadioInterface(0, getter_AddRefs(radioInterface));
}
NS_ENSURE_TRUE(radioInterface, NS_ERROR_FAILURE);
return mRadioInterface->GetSegmentInfoForText(aText, aRequest);
return radioInterface->GetSegmentInfoForText(aText, aRequest);
}
NS_IMETHODIMP
SmsService::Send(const nsAString& aNumber,
SmsService::Send(uint32_t aServiceId,
const nsAString& aNumber,
const nsAString& aMessage,
const bool aSilent,
nsIMobileMessageCallback* aRequest)
{
NS_ENSURE_TRUE(mRadioInterface, NS_ERROR_FAILURE);
nsCOMPtr<nsIRadioInterface> radioInterface;
if (mRil) {
mRil->GetRadioInterface(aServiceId, getter_AddRefs(radioInterface));
}
NS_ENSURE_TRUE(radioInterface, NS_ERROR_FAILURE);
return mRadioInterface->SendSMS(aNumber, aMessage, aSilent, aRequest);
return radioInterface->SendSMS(aNumber, aMessage, aSilent, aRequest);
}
NS_IMETHODIMP

View File

@ -28,8 +28,7 @@ public:
SmsService();
protected:
// TODO: Bug 854326 - B2G Multi-SIM: support multiple SIM cards for SMS/MMS
nsCOMPtr<nsIRadioInterface> mRadioInterface;
nsCOMPtr<nsIRadioInterfaceLayer> mRil;
nsTArray<nsString> mSilentNumbers;
uint32_t mDefaultServiceId;
};

View File

@ -16,6 +16,7 @@ namespace mobilemessage {
struct SendMmsMessageRequest
{
uint32_t serviceId;
nsString[] receivers;
nsString subject;
nsString smil;
@ -24,6 +25,7 @@ struct SendMmsMessageRequest
struct SendSmsMessageRequest
{
uint32_t serviceId;
nsString number;
nsString message;
bool silent;
@ -60,6 +62,7 @@ struct MarkMessageReadRequest
{
int32_t messageId;
bool value;
bool sendReadReport;
};
struct GetSegmentInfoForTextRequest

View File

@ -167,12 +167,14 @@ SmsIPCService::GetSegmentInfoForText(const nsAString& aText,
}
NS_IMETHODIMP
SmsIPCService::Send(const nsAString& aNumber,
SmsIPCService::Send(uint32_t aServiceId,
const nsAString& aNumber,
const nsAString& aMessage,
const bool aSilent,
nsIMobileMessageCallback* aRequest)
{
return SendRequest(SendMessageRequest(SendSmsMessageRequest(nsString(aNumber),
return SendRequest(SendMessageRequest(SendSmsMessageRequest(aServiceId,
nsString(aNumber),
nsString(aMessage),
aSilent)),
aRequest);
@ -241,9 +243,10 @@ SmsIPCService::CreateMessageCursor(nsIDOMMozSmsFilter* aFilter,
NS_IMETHODIMP
SmsIPCService::MarkMessageRead(int32_t aMessageId,
bool aValue,
bool aSendReadReport,
nsIMobileMessageCallback* aRequest)
{
return SendRequest(MarkMessageReadRequest(aMessageId, aValue), aRequest);
return SendRequest(MarkMessageReadRequest(aMessageId, aValue, aSendReadReport), aRequest);
}
NS_IMETHODIMP
@ -255,7 +258,8 @@ SmsIPCService::CreateThreadCursor(nsIMobileMessageCursorCallback* aCursorCallbac
}
bool
GetSendMmsMessageRequestFromParams(const JS::Value& aParam,
GetSendMmsMessageRequestFromParams(uint32_t aServiceId,
const JS::Value& aParam,
SendMmsMessageRequest& request) {
if (aParam.isUndefined() || aParam.isNull() || !aParam.isObject()) {
return false;
@ -296,6 +300,9 @@ GetSendMmsMessageRequestFromParams(const JS::Value& aParam,
request.smil() = params.mSmil;
request.subject() = params.mSubject;
// Set service ID.
request.serviceId() = aServiceId;
return true;
}
@ -311,11 +318,12 @@ SmsIPCService::GetMmsDefaultServiceId(uint32_t* aServiceId)
}
NS_IMETHODIMP
SmsIPCService::Send(const JS::Value& aParameters,
SmsIPCService::Send(uint32_t aServiceId,
const JS::Value& aParameters,
nsIMobileMessageCallback *aRequest)
{
SendMmsMessageRequest req;
if (!GetSendMmsMessageRequestFromParams(aParameters, req)) {
if (!GetSendMmsMessageRequestFromParams(aServiceId, aParameters, req)) {
return NS_ERROR_INVALID_ARG;
}
return SendRequest(SendMessageRequest(req), aRequest);
@ -326,3 +334,12 @@ SmsIPCService::Retrieve(int32_t aId, nsIMobileMessageCallback *aRequest)
{
return SendRequest(RetrieveMessageRequest(aId), aRequest);
}
NS_IMETHODIMP
SmsIPCService::SendReadReport(const nsAString & messageID,
const nsAString & toAddress,
const nsAString & iccId)
{
NS_ERROR("We should not be here!");
return NS_OK;
}

View File

@ -451,8 +451,9 @@ SmsRequestParent::DoRequest(const SendMessageRequest& aRequest)
nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
NS_ENSURE_TRUE(smsService, true);
const SendSmsMessageRequest &data = aRequest.get_SendSmsMessageRequest();
smsService->Send(data.number(), data.message(), data.silent(), this);
const SendSmsMessageRequest &req = aRequest.get_SendSmsMessageRequest();
smsService->Send(req.serviceId(), req.number(), req.message(),
req.silent(), this);
}
break;
case SendMessageRequest::TSendMmsMessageRequest: {
@ -461,14 +462,14 @@ SmsRequestParent::DoRequest(const SendMessageRequest& aRequest)
AutoJSContext cx;
JS::Rooted<JS::Value> params(cx);
if (!GetParamsFromSendMmsMessageRequest(
cx,
aRequest.get_SendMmsMessageRequest(),
params.address())) {
const SendMmsMessageRequest &req = aRequest.get_SendMmsMessageRequest();
if (!GetParamsFromSendMmsMessageRequest(cx,
req,
params.address())) {
NS_WARNING("SmsRequestParent: Fail to build MMS params.");
return true;
}
mmsService->Send(params, this);
mmsService->Send(req.serviceId(), params, this);
}
break;
default:
@ -541,7 +542,7 @@ SmsRequestParent::DoRequest(const MarkMessageReadRequest& aRequest)
do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID);
if (dbService) {
rv = dbService->MarkMessageRead(aRequest.messageId(), aRequest.value(),
this);
aRequest.sendReadReport(), this);
}
if (NS_FAILED(rv)) {

View File

@ -27,6 +27,7 @@ struct SmsMessageData
{
int32_t id;
uint64_t threadId;
nsString iccId;
DeliveryState delivery;
DeliveryStatus deliveryStatus;
nsString sender;
@ -55,6 +56,7 @@ struct MmsMessageData
{
int32_t id;
uint64_t threadId;
nsString iccId;
DeliveryState delivery;
MmsDeliveryInfoData[] deliveryInfo;
nsString sender;
@ -65,6 +67,7 @@ struct MmsMessageData
nsString smil;
MmsAttachmentData[] attachments;
uint64_t expiryDate;
bool isReadReportRequested;
};
union MobileMessageData

View File

@ -1,6 +1,8 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const ICC_ID = "123456789";
function do_check_throws(f, result, stack) {
if (!stack) {
stack = Components.stack.caller;
@ -30,11 +32,34 @@ function run_test() {
* Ensure an SmsMessage object created has sensible initial values.
*/
add_test(function test_interface() {
let sms = newMessage(null, null, "sent", "success", null, null, null,
let sms = newMessage(null, null, ICC_ID, "sent", "success", null, null, null,
"normal", new Date(), 0, true);
do_check_true(sms instanceof Ci.nsIDOMMozSmsMessage);
do_check_eq(sms.id, 0);
do_check_eq(sms.threadId, 0);
do_check_eq(sms.iccId, ICC_ID);
do_check_eq(sms.delivery, "sent");
do_check_eq(sms.deliveryStatus, "success");
do_check_eq(sms.receiver, null);
do_check_eq(sms.sender, null);
do_check_eq(sms.body, null);
do_check_eq(sms.messageClass, "normal");
do_check_true(sms.timestamp instanceof Date);
do_check_true(sms.deliveryTimestamp === null);
do_check_true(sms.read);
run_next_test();
});
/**
* Test if ICC ID is null when it's not available.
*/
add_test(function test_icc_id_not_available() {
let sms = newMessage(null, null, null, "sent", "success", null, null, null,
"normal", new Date(), 0, true);
do_check_true(sms instanceof Ci.nsIDOMMozSmsMessage);
do_check_eq(sms.id, 0);
do_check_eq(sms.threadId, 0);
do_check_eq(sms.iccId, null);
do_check_eq(sms.delivery, "sent");
do_check_eq(sms.deliveryStatus, "success");
do_check_eq(sms.receiver, null);
@ -51,7 +76,7 @@ add_test(function test_interface() {
* Verify that attributes are read-only.
*/
add_test(function test_readonly_attributes() {
let sms = newMessage(null, null, "received", "success", null, null, null,
let sms = newMessage(null, null, ICC_ID, "received", "success", null, null, null,
"normal", new Date(), 0, true);
sms.id = 1;
@ -60,6 +85,9 @@ add_test(function test_readonly_attributes() {
sms.threadId = 1;
do_check_eq(sms.threadId, 0);
sms.iccId = "987654321";
do_check_eq(sms.iccId, ICC_ID);
sms.delivery = "sent";
do_check_eq(sms.delivery, "received");
@ -97,10 +125,11 @@ add_test(function test_readonly_attributes() {
*/
add_test(function test_timestamp_number() {
let ts = Date.now();
let sms = newMessage(42, 1, "sent", "success", "the sender", "the receiver",
let sms = newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", ts, 0, true);
do_check_eq(sms.id, 42);
do_check_eq(sms.threadId, 1);
do_check_eq(sms.iccId, ICC_ID);
do_check_eq(sms.delivery, "sent");
do_check_eq(sms.deliveryStatus, "success");
do_check_eq(sms.sender, "the sender");
@ -119,10 +148,11 @@ add_test(function test_timestamp_number() {
*/
add_test(function test_timestamp_date() {
let date = new Date();
let sms = newMessage(42, 1, "sent", "success", "the sender", "the receiver",
let sms = newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", date, 0, true);
do_check_eq(sms.id, 42);
do_check_eq(sms.threadId, 1);
do_check_eq(sms.iccId, ICC_ID);
do_check_eq(sms.delivery, "sent");
do_check_eq(sms.deliveryStatus, "success");
do_check_eq(sms.sender, "the sender");
@ -142,13 +172,13 @@ add_test(function test_timestamp_date() {
add_test(function test_invalid_timestamp_float() {
// Test timestamp.
do_check_throws(function() {
newMessage(42, 1, "sent", "success", "the sender", "the receiver",
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", 3.1415, 0, true);
}, Cr.NS_ERROR_INVALID_ARG);
// Test deliveryTimestamp.
do_check_throws(function() {
newMessage(42, 1, "sent", "success", "the sender", "the receiver",
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", 0, 3.1415, true);
}, Cr.NS_ERROR_INVALID_ARG);
@ -161,13 +191,13 @@ add_test(function test_invalid_timestamp_float() {
add_test(function test_invalid_timestamp_null() {
// Test timestamp.
do_check_throws(function() {
newMessage(42, 1, "sent", "success", "the sender", "the receiver",
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", null, 0, true);
}, Cr.NS_ERROR_INVALID_ARG);
// Test deliveryTimestamp.
do_check_throws(function() {
newMessage(42, 1, "sent", "success", "the sender", "the receiver",
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", 0, null, true);
}, Cr.NS_ERROR_INVALID_ARG);
@ -180,13 +210,13 @@ add_test(function test_invalid_timestamp_null() {
add_test(function test_invalid_timestamp_undefined() {
// Test timestamp.
do_check_throws(function() {
newMessage(42, 1, "sent", "success", "the sender", "the receiver",
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", undefined, 0, true);
}, Cr.NS_ERROR_INVALID_ARG);
// Test deliveryTimestamp.
do_check_throws(function() {
newMessage(42, 1, "sent", "success", "the sender", "the receiver",
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", 0, undefined, true);
}, Cr.NS_ERROR_INVALID_ARG);
@ -199,13 +229,13 @@ add_test(function test_invalid_timestamp_undefined() {
add_test(function test_invalid_timestamp_object() {
// Test timestamp.
do_check_throws(function() {
newMessage(42, 1, "sent", "success", "the sender", "the receiver",
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", {}, 0, true);
}, Cr.NS_ERROR_INVALID_ARG);
// Test deliveryTimestamp.
do_check_throws(function() {
newMessage(42, 1, "sent", "success", "the sender", "the receiver",
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "normal", 0, {}, true);
}, Cr.NS_ERROR_INVALID_ARG);
@ -217,7 +247,7 @@ add_test(function test_invalid_timestamp_object() {
*/
add_test(function test_invalid_delivery_string() {
do_check_throws(function() {
newMessage(42, 1, "this is invalid", "pending", "the sender",
newMessage(42, 1, ICC_ID, "this is invalid", "pending", "the sender",
"the receiver", "the body", "normal", new Date(), 0, true);
}, Cr.NS_ERROR_INVALID_ARG);
run_next_test();
@ -228,7 +258,7 @@ add_test(function test_invalid_delivery_string() {
*/
add_test(function test_invalid_delivery_string() {
do_check_throws(function() {
newMessage(42, 1, 1, "pending", "the sender", "the receiver", "the body",
newMessage(42, 1, ICC_ID, 1, "pending", "the sender", "the receiver", "the body",
"normal", new Date(), 0, true);
}, Cr.NS_ERROR_INVALID_ARG);
run_next_test();
@ -239,7 +269,7 @@ add_test(function test_invalid_delivery_string() {
*/
add_test(function test_invalid_delivery_status_string() {
do_check_throws(function() {
newMessage(42, 1, "sent", "this is invalid", "the sender", "the receiver",
newMessage(42, 1, ICC_ID, "sent", "this is invalid", "the sender", "the receiver",
"the body", "normal", new Date(), 0, true);
}, Cr.NS_ERROR_INVALID_ARG);
run_next_test();
@ -250,7 +280,7 @@ add_test(function test_invalid_delivery_status_string() {
*/
add_test(function test_invalid_delivery_status_string() {
do_check_throws(function() {
newMessage(42, 1, "sent", 1, "the sender", "the receiver", "the body",
newMessage(42, 1, ICC_ID, "sent", 1, "the sender", "the receiver", "the body",
"normal", new Date(), 0, true);
}, Cr.NS_ERROR_INVALID_ARG);
run_next_test();
@ -261,7 +291,7 @@ add_test(function test_invalid_delivery_status_string() {
*/
add_test(function test_invalid_message_class_string() {
do_check_throws(function() {
newMessage(42, 1, "sent", "success", "the sender", "the receiver",
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", "this is invalid", new Date(), 0, true);
}, Cr.NS_ERROR_INVALID_ARG);
run_next_test();
@ -272,7 +302,7 @@ add_test(function test_invalid_message_class_string() {
*/
add_test(function test_invalid_message_class_string() {
do_check_throws(function() {
newMessage(42, 1, "sent", "success", "the sender", "the receiver",
newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
"the body", 1, new Date(), 0, true);
}, Cr.NS_ERROR_INVALID_ARG);
run_next_test();

View File

@ -166,10 +166,14 @@ function NetworkManager() {
// Default values for internal and external interfaces.
this._tetheringInterface = Object.create(null);
this._tetheringInterface[TETHERING_TYPE_USB] = {externalInterface: DEFAULT_3G_INTERFACE_NAME,
internalInterface: DEFAULT_USB_INTERFACE_NAME};
this._tetheringInterface[TETHERING_TYPE_WIFI] = {externalInterface: DEFAULT_3G_INTERFACE_NAME,
internalInterface: DEFAULT_WIFI_INTERFACE_NAME};
this._tetheringInterface[TETHERING_TYPE_USB] = {
externalInterface: DEFAULT_3G_INTERFACE_NAME,
internalInterface: DEFAULT_USB_INTERFACE_NAME
};
this._tetheringInterface[TETHERING_TYPE_WIFI] = {
externalInterface: DEFAULT_3G_INTERFACE_NAME,
internalInterface: DEFAULT_WIFI_INTERFACE_NAME
};
this.initTetheringSettings();
@ -249,8 +253,8 @@ NetworkManager.prototype = {
#ifdef MOZ_B2G_RIL
// Update data connection when Wifi connected/disconnected
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
for (let i = 0; i < this.mRIL.numRadioInterfaces; i++) {
this.mRIL.getRadioInterface(i).updateRILNetworkInterface();
for (let i = 0; i < this.mRil.numRadioInterfaces; i++) {
this.mRil.getRadioInterface(i).updateRILNetworkInterface();
}
}
#endif
@ -258,7 +262,8 @@ NetworkManager.prototype = {
this.onConnectionChanged(network);
// Probing the public network accessibility after routing table is ready
CaptivePortalDetectionHelper.notify(CaptivePortalDetectionHelper.EVENT_CONNECT, this.active);
CaptivePortalDetectionHelper
.notify(CaptivePortalDetectionHelper.EVENT_CONNECT, this.active);
break;
case Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED:
#ifdef MOZ_B2G_RIL
@ -279,14 +284,16 @@ NetworkManager.prototype = {
this.removeDefaultRoute(network.name);
#endif
}
// Abort ongoing captive portal detection on the wifi interface
CaptivePortalDetectionHelper.notify(CaptivePortalDetectionHelper.EVENT_DISCONNECT, network);
CaptivePortalDetectionHelper
.notify(CaptivePortalDetectionHelper.EVENT_DISCONNECT, network);
this.setAndConfigureActive();
#ifdef MOZ_B2G_RIL
// Update data connection when Wifi connected/disconnected
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
for (let i = 0; i < this.mRIL.numRadioInterfaces; i++) {
this.mRIL.getRadioInterface(i).updateRILNetworkInterface();
for (let i = 0; i < this.mRil.numRadioInterfaces; i++) {
this.mRil.getRadioInterface(i).updateRILNetworkInterface();
}
}
#endif
@ -519,20 +526,44 @@ NetworkManager.prototype = {
#ifdef MOZ_B2G_RIL
setExtraHostRoute: function setExtraHostRoute(network) {
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS) {
debug("Network '" + network.name + "' registered, adding mmsproxy and/or mmsc route");
let mmsHosts = this.resolveHostname(
[Services.prefs.getCharPref("ril.mms.mmsproxy"),
Services.prefs.getCharPref("ril.mms.mmsc")]);
if (!(network instanceof Ci.nsIRilNetworkInterface)) {
debug("Network for MMS must be an instance of nsIRilNetworkInterface");
return;
}
network = network.QueryInterface(Ci.nsIRilNetworkInterface);
debug("Network '" + network.name + "' registered, " +
"adding mmsproxy and/or mmsc route");
let mmsHosts = this.resolveHostname([network.mmsProxy, network.mmsc]);
if (mmsHosts.length == 0) {
debug("No valid hostnames can be added. Stop adding host route.");
return;
}
this.addHostRouteWithResolve(network, mmsHosts);
}
},
removeExtraHostRoute: function removeExtraHostRoute(network) {
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS) {
debug("Network '" + network.name + "' unregistered, removing mmsproxy and/or mmsc route");
let mmsHosts = this.resolveHostname(
[Services.prefs.getCharPref("ril.mms.mmsproxy"),
Services.prefs.getCharPref("ril.mms.mmsc")]);
if (!(network instanceof Ci.nsIRilNetworkInterface)) {
debug("Network for MMS must be an instance of nsIRilNetworkInterface");
return;
}
network = network.QueryInterface(Ci.nsIRilNetworkInterface);
debug("Network '" + network.name + "' unregistered, " +
"removing mmsproxy and/or mmsc route");
let mmsHosts = this.resolveHostname([network.mmsProxy, network.mmsc]);
if (mmsHosts.length == 0) {
debug("No valid hostnames can be removed. Stop removing host route.");
return;
}
this.removeHostRouteWithResolve(network, mmsHosts);
}
},
@ -705,11 +736,18 @@ NetworkManager.prototype = {
let retval = [];
for (let hostname of hosts) {
// Sanity check for null, undefined and empty string... etc.
if (!hostname) {
continue;
}
try {
let uri = Services.io.newURI(hostname, null, null);
hostname = uri.host;
} catch (e) {}
// An extra check for hostnames that cannot be made by newURI(...).
// For example, an IP address like "10.1.1.1".
if (hostname.match(this.REGEXP_IPV4) ||
hostname.match(this.REGEXP_IPV6)) {
retval.push(hostname);
@ -1146,7 +1184,8 @@ NetworkManager.prototype = {
if (!isError(code)) {
// Update the external interface.
this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = data.current.externalIfname;
this._tetheringInterface[TETHERING_TYPE_USB]
.externalInterface = data.current.externalIfname;
debug("Change the interface name to " + data.current.externalIfname);
}
},
@ -1202,7 +1241,8 @@ let CaptivePortalDetectionHelper = (function() {
let _ongoingInterface = null;
let _available = ("nsICaptivePortalDetector" in Ci);
let getService = function () {
return Cc['@mozilla.org/toolkit/captive-detector;1'].getService(Ci.nsICaptivePortalDetector);
return Cc['@mozilla.org/toolkit/captive-detector;1']
.getService(Ci.nsICaptivePortalDetector);
};
let _performDetection = function (interfaceName, callback) {
@ -1269,7 +1309,7 @@ let CaptivePortalDetectionHelper = (function() {
}());
#ifdef MOZ_B2G_RIL
XPCOMUtils.defineLazyServiceGetter(NetworkManager.prototype, "mRIL",
XPCOMUtils.defineLazyServiceGetter(NetworkManager.prototype, "mRil",
"@mozilla.org/ril;1",
"nsIRadioInterfaceLayer");
#endif

View File

@ -581,6 +581,21 @@ RadioInterfaceLayer.prototype = {
getRadioInterface: function getRadioInterface(clientId) {
return this.radioInterfaces[clientId];
},
getClientIdByIccId: function getClientIdByIccId(iccId) {
if (!iccId) {
throw Cr.NS_ERROR_INVALID_ARG;
}
for (let clientId = 0; clientId < this.numRadioInterfaces; clientId++) {
let radioInterface = this.radioInterfaces[clientId];
if (radioInterface.rilContext.iccInfo.iccid == iccId) {
return clientId;
}
}
throw Cr.NS_ERROR_NOT_AVAILABLE;
}
};
@ -732,13 +747,14 @@ function RadioInterface(options) {
roamingEnabled: false
};
// apnSettings is used to keep all APN settings.
// byApn[] makes it easier to get the APN settings via APN, user
// name, and password.
// byType[] makes it easier to get the APN settings via APN types.
// This matrix is used to keep all the APN settings.
// - |byApn| object makes it easier to get the corresponding APN setting
// via a given set of APN, user name and password.
// - |byType| object makes it easier to get the corresponding APN setting
// via a given APN type.
this.apnSettings = {
byType: {},
byAPN: {}
byType: {},
byApn: {}
};
this.rilContext = {
@ -1144,9 +1160,31 @@ RadioInterface.prototype = {
if (number === undefined || number === "undefined") {
return null;
}
return number;
},
/**
* A utility function to get the ICC ID of the SIM card (if installed).
*/
getIccId: function getIccId() {
let iccInfo = this.rilContext.iccInfo;
if (!iccInfo || !(iccInfo instanceof GsmIccInfo)) {
return null;
}
let iccId = iccInfo.iccid;
// Workaround an xpconnect issue with undefined string objects.
// See bug 808220
if (iccId === undefined || iccId === "undefined") {
return null;
}
return iccId;
},
updateNetworkInfo: function updateNetworkInfo(message) {
let voiceMessage = message[RIL.NETWORK_INFO_VOICE_REGISTRATION_STATE];
let dataMessage = message[RIL.NETWORK_INFO_DATA_REGISTRATION_STATE];
@ -1510,7 +1548,7 @@ RadioInterface.prototype = {
*/
powerOffRadioSafely: function powerOffRadioSafely() {
let dataDisconnecting = false;
for each (let apnSetting in this.apnSettings.byAPN) {
for each (let apnSetting in this.apnSettings.byApn) {
for each (let type in apnSetting.types) {
if (this.getDataCallStateByType(type) ==
RIL.GECKO_NETWORK_STATE_CONNECTED) {
@ -1532,23 +1570,22 @@ RadioInterface.prototype = {
/**
* This function will do the following steps:
* 1. Clear the old APN settings.
* 2. Combine APN, user name, and password as the key of byAPN{} and store
* corresponding APN setting into byApn{}, which makes it easiler to get
* the APN setting.
* 3. Use APN type as the index of byType{} and store the link of
* corresponding APN setting into byType{}, which makes it easier to get
* the APN setting via APN types.
* 1. Clear the cached APN settings in the RIL.
* 2. Combine APN, user name, and password as the key of |byApn| object to
* refer to the corresponding APN setting.
* 3. Use APN type as the index of |byType| object to refer to the
* corresponding APN setting.
* 4. Create RilNetworkInterface for each APN setting created at step 2.
*/
updateApnSettings: function updateApnSettings(allApnSettings) {
let thisSimApnSettings = allApnSettings[this.clientId];
if (!thisSimApnSettings) {
let simApnSettings = allApnSettings[this.clientId];
if (!simApnSettings) {
return;
}
// Clear old APN settings.
for each (let apnSetting in this.apnSettings.byAPN) {
// Clear all connections of this APN settings.
// Clear the cached APN settings in the RIL.
for each (let apnSetting in this.apnSettings.byApn) {
// Clear all existing connections based on APN types.
for each (let type in apnSetting.types) {
if (this.getDataCallStateByType(type) ==
RIL.GECKO_NETWORK_STATE_CONNECTED) {
@ -1561,33 +1598,40 @@ RadioInterface.prototype = {
this.unregisterDataCallCallback(apnSetting.iface);
delete apnSetting.iface;
}
this.apnSettings.byAPN = {};
this.apnSettings.byApn = {};
this.apnSettings.byType = {};
// Create new APN settings.
for (let apnIndex = 0; thisSimApnSettings[apnIndex]; apnIndex++) {
let inputApnSetting = thisSimApnSettings[apnIndex];
// Cache the APN settings by APNs and by types in the RIL.
for (let i = 0; simApnSettings[i]; i++) {
let inputApnSetting = simApnSettings[i];
if (!this.validateApnSetting(inputApnSetting)) {
continue;
}
// Combine APN, user name, and password as the key of byAPN{} to get
// the corresponding APN setting.
let apnKey = inputApnSetting.apn + (inputApnSetting.user || '') +
// Combine APN, user name, and password as the key of |byApn| object to
// refer to the corresponding APN setting.
let apnKey = inputApnSetting.apn +
(inputApnSetting.user || '') +
(inputApnSetting.password || '');
if (!this.apnSettings.byAPN[apnKey]) {
this.apnSettings.byAPN[apnKey] = {};
this.apnSettings.byAPN[apnKey] = inputApnSetting;
this.apnSettings.byAPN[apnKey].iface =
new RILNetworkInterface(this, this.apnSettings.byAPN[apnKey]);
if (!this.apnSettings.byApn[apnKey]) {
this.apnSettings.byApn[apnKey] = inputApnSetting;
} else {
this.apnSettings.byAPN[apnKey].types.push(inputApnSetting.types);
this.apnSettings.byApn[apnKey].types =
this.apnSettings.byApn[apnKey].types.concat(inputApnSetting.types);
}
// Use APN type as the index of |byType| object to refer to the
// corresponding APN setting.
for each (let type in inputApnSetting.types) {
this.apnSettings.byType[type] = {};
this.apnSettings.byType[type] = this.apnSettings.byAPN[apnKey];
this.apnSettings.byType[type] = this.apnSettings.byApn[apnKey];
}
}
// Create RilNetworkInterface for each APN setting that just cached.
for each (let apnSetting in this.apnSettings.byApn) {
apnSetting.iface = new RILNetworkInterface(this, apnSetting);
}
},
/**
@ -1735,6 +1779,7 @@ RadioInterface.prototype = {
sourcePort: message.header.originatorPort,
destinationAddress: this.rilContext.iccInfo.msisdn,
destinationPort: message.header.destinationPort,
serviceId: this.clientId
};
WAP.WapPushManager.receiveWdpPDU(message.fullData, message.fullData.length,
0, options);
@ -1835,6 +1880,7 @@ RadioInterface.prototype = {
message.receiver = this.getPhoneNumber();
message.body = message.fullBody = message.fullBody || null;
message.timestamp = Date.now();
message.iccId = this.getIccId();
if (gSmsService.isSilentNumber(message.sender)) {
message.id = -1;
@ -1846,6 +1892,7 @@ RadioInterface.prototype = {
let domMessage =
gMobileMessageService.createSmsMessage(message.id,
message.threadId,
message.iccId,
message.delivery,
message.deliveryStatus,
message.sender,
@ -1911,6 +1958,7 @@ RadioInterface.prototype = {
let domMessage =
gMobileMessageService.createSmsMessage(message.id,
message.threadId,
message.iccId,
message.delivery,
message.deliveryStatus,
message.sender,
@ -1959,7 +2007,7 @@ RadioInterface.prototype = {
if (datacall.state == RIL.GECKO_NETWORK_STATE_UNKNOWN &&
this._changingRadioPower) {
let anyDataConnected = false;
for each (let apnSetting in this.apnSettings.byAPN) {
for each (let apnSetting in this.apnSettings.byApn) {
for each (let type in apnSetting.types) {
if (this.getDataCallStateByType(type) == RIL.GECKO_NETWORK_STATE_CONNECTED) {
anyDataConnected = true;
@ -2189,7 +2237,7 @@ RadioInterface.prototype = {
this._releaseSmsHandledWakeLock();
// Shutdown all RIL network interfaces
for each (let apnSetting in this.apnSettings.byAPN) {
for each (let apnSetting in this.apnSettings.byApn) {
if (apnSetting.iface) {
apnSetting.iface.shutdown();
}
@ -2379,7 +2427,7 @@ RadioInterface.prototype = {
this.dataCallSettings.roamingEnabled = false;
this.apnSettings = {
byType: {},
byAPN: {},
byApn: {},
};
},
@ -3020,6 +3068,7 @@ RadioInterface.prototype = {
context.request.notifyMessageSent(
gMobileMessageService.createSmsMessage(sms.id,
sms.threadId,
sms.iccId,
DOM_MOBILE_MESSAGE_DELIVERY_SENT,
sms.deliveryStatus,
sms.sender,
@ -3062,7 +3111,8 @@ RadioInterface.prototype = {
receiver: number,
body: message,
deliveryStatusRequested: options.requestStatusReport,
timestamp: Date.now()
timestamp: Date.now(),
iccId: this.getIccId()
};
if (silent) {
@ -3071,6 +3121,7 @@ RadioInterface.prototype = {
let domMessage =
gMobileMessageService.createSmsMessage(-1, // id
0, // threadId
sendingMessage.iccId,
delivery,
deliveryStatus,
sendingMessage.sender,
@ -3273,8 +3324,6 @@ RILNetworkInterface.prototype = {
NETWORK_STATE_DISCONNECTING: Ci.nsINetworkInterface.DISCONNECTING,
NETWORK_STATE_DISCONNECTED: Ci.nsINetworkInterface.DISCONNECTED,
state: Ci.nsINetworkInterface.NETWORK_STATE_UNKNOWN,
NETWORK_TYPE_WIFI: Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
NETWORK_TYPE_MOBILE: Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE,
NETWORK_TYPE_MOBILE_MMS: Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS,
@ -3295,6 +3344,12 @@ RILNetworkInterface.prototype = {
// Event timer for connection retries
timer: null,
/**
* nsINetworkInterface Implementation
*/
state: Ci.nsINetworkInterface.NETWORK_STATE_UNKNOWN,
get type() {
if (this.connectedTypes.indexOf("default") != -1) {
return this.NETWORK_TYPE_MOBILE;
@ -3328,6 +3383,10 @@ RILNetworkInterface.prototype = {
return this.apnSetting.port || '';
},
/**
* nsIRilNetworkInterface Implementation
*/
get serviceId() {
return this.radioInterface.clientId;
},
@ -3337,6 +3396,60 @@ RILNetworkInterface.prototype = {
return iccInfo && iccInfo.iccid;
},
get mmsc() {
if (!this.inConnectedTypes("mms")) {
if (DEBUG) this.debug("Error! Only MMS network can get MMSC.");
throw Cr.NS_ERROR_UNEXPECTED;
}
let mmsc = this.apnSetting.mmsc;
if (!mmsc) {
try {
mmsc = Services.prefs.getCharPref("ril.mms.mmsc");
} catch (e) {
mmsc = "";
}
}
return mmsc;
},
get mmsProxy() {
if (!this.inConnectedTypes("mms")) {
if (DEBUG) this.debug("Error! Only MMS network can get MMS proxy.");
throw Cr.NS_ERROR_UNEXPECTED;
}
let proxy = this.apnSetting.mmsproxy;
if (!proxy) {
try {
proxy = Services.prefs.getCharPref("ril.mms.mmsproxy");
} catch (e) {
proxy = "";
}
}
return proxy;
},
get mmsPort() {
if (!this.inConnectedTypes("mms")) {
if (DEBUG) this.debug("Error! Only MMS network can get MMS port.");
throw Cr.NS_ERROR_UNEXPECTED;
}
let port = this.apnSetting.mmsport;
if (!port) {
try {
port = Services.prefs.getIntPref("ril.mms.mmsport");
} catch (e) {
port = -1;
}
}
return port;
},
debug: function debug(s) {
dump("-*- RILNetworkInterface[" + this.radioInterface.clientId + ":" +
this.type + "]: " + s + "\n");

View File

@ -9,11 +9,16 @@ interface nsIDOMMozIccInfo;
interface nsIDOMMozMobileConnectionInfo;
interface nsIMobileMessageCallback;
[scriptable, uuid(a15769f1-538e-4b4b-81da-c52866d38f88)]
[scriptable, uuid(6e0f45b8-410e-11e3-8c8e-b715b2cd0128)]
interface nsIRilNetworkInterface : nsINetworkInterface
{
readonly attribute unsigned long serviceId;
readonly attribute DOMString iccId;
/* The following attributes are for MMS proxy settings. */
readonly attribute DOMString mmsc; // Empty string if not set.
readonly attribute DOMString mmsProxy; // Empty string if not set.
readonly attribute long mmsPort; // -1 if not set.
};
[scriptable, uuid(1e602d20-d066-4399-8997-daf36b3158ef)]
@ -125,10 +130,15 @@ interface nsIRadioInterface : nsISupports
[optional] in nsIRilSendWorkerMessageCallback callback);
};
[scriptable, uuid(44b03951-1444-4c03-bd37-0bcb3a01b56f)]
[scriptable, uuid(70d3a18c-4063-11e3-89de-0f9ec19fd803)]
interface nsIRadioInterfaceLayer : nsISupports
{
readonly attribute unsigned long numRadioInterfaces;
nsIRadioInterface getRadioInterface(in long clientId);
nsIRadioInterface getRadioInterface(in unsigned long clientId);
/**
* If not available, throws exception; otherwise, a valid number.
*/
unsigned long getClientIdByIccId(in DOMString iccId);
};

View File

@ -19,6 +19,8 @@ interface DummyInterface : EventTarget {
void funcDNSLookupDict(optional DNSLookupDict arg);
void funcConnStatusDict(optional ConnStatusDict arg);
void frameRequestCallback(FrameRequestCallback arg);
void SmsSendParameters(optional SmsSendParameters arg);
void MmsSendParameters(optional MmsSendParameters arg);
void MmsParameters(optional MmsParameters arg);
void MmsAttachment(optional MmsAttachment arg);
void AsyncScrollEventDetail(optional AsyncScrollEventDetail arg);

View File

@ -12,3 +12,13 @@ dictionary MmsParameters {
};
// If we start using MmsParameters here, remove it from DummyBinding.
dictionary SmsSendParameters {
unsigned long serviceId; // The ID of the RIL service which needs to be
// specified under the multi-sim scenario.
};
dictionary MmsSendParameters {
unsigned long serviceId; // The ID of the RIL service which needs to be
// specified under the multi-sim scenario.
};

View File

@ -325,7 +325,8 @@ void PeerConnectionCtx::onDeviceEvent(ccapi_device_event_e aDeviceEvent,
switch (aDeviceEvent) {
case CCAPI_DEVICE_EV_STATE:
CSFLogDebug(logTag, "%s - %d : %d", __FUNCTION__, state, currentSipccState);
CSFLogDebug(logTag, "%s - %d : %d", __FUNCTION__, state,
static_cast<uint32_t>(currentSipccState));
if (CC_STATE_INS == state) {
// SIPCC is up

View File

@ -45,6 +45,9 @@
#include "nsDOMDataChannel.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Telemetry.h"
#include "mozilla/PublicSSL.h"
#include "nsXULAppAPI.h"
#include "nsContentUtils.h"
#include "nsDOMJSUtils.h"
#include "nsIDocument.h"
#include "nsIScriptError.h"
@ -81,9 +84,46 @@ using namespace mozilla::dom;
typedef PCObserverString ObString;
static const char* logTag = "PeerConnectionImpl";
#ifdef MOZILLA_INTERNAL_API
static nsresult InitNSSInContent()
{
NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_NOT_SAME_THREAD);
if (XRE_GetProcessType() != GeckoProcessType_Content) {
MOZ_ASSUME_UNREACHABLE("Must be called in content process");
}
static bool nssStarted = false;
if (nssStarted) {
return NS_OK;
}
if (NSS_NoDB_Init(nullptr) != SECSuccess) {
CSFLogError(logTag, "NSS_NoDB_Init failed.");
return NS_ERROR_FAILURE;
}
if (NS_FAILED(mozilla::psm::InitializeCipherSuite())) {
CSFLogError(logTag, "Fail to set up nss cipher suite.");
return NS_ERROR_FAILURE;
}
mozilla::psm::ConfigureMD5(false);
nssStarted = true;
return NS_OK;
}
#endif // MOZILLA_INTERNAL_API
namespace mozilla {
class DataChannel;
}
class nsIDOMDataChannel;
static const char* logTag = "PeerConnectionImpl";
static const int DTLS_FINGERPRINT_LENGTH = 64;
static const int MEDIA_STREAM_MUTE = 0x80;
@ -643,17 +683,24 @@ PeerConnectionImpl::Initialize(PeerConnectionObserver& aObserver,
mSTSThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &res);
MOZ_ASSERT(mSTSThread);
#ifdef MOZILLA_INTERNAL_API
// This code interferes with the C++ unit test startup code.
nsCOMPtr<nsISupports> nssDummy = do_GetService("@mozilla.org/psm;1", &res);
NS_ENSURE_SUCCESS(res, res);
// Initialize NSS if we are in content process. For chrome process, NSS should already
// been initialized.
if (XRE_GetProcessType() == GeckoProcessType_Default) {
// This code interferes with the C++ unit test startup code.
nsCOMPtr<nsISupports> nssDummy = do_GetService("@mozilla.org/psm;1", &res);
NS_ENSURE_SUCCESS(res, res);
} else {
NS_ENSURE_SUCCESS(res = InitNSSInContent(), res);
}
// Currently no standalone unit tests for DataChannel,
// which is the user of mWindow
MOZ_ASSERT(aWindow);
mWindow = aWindow;
NS_ENSURE_STATE(mWindow);
#endif
#endif // MOZILLA_INTERNAL_API
// Generate a random handle
unsigned char handle_bin[8];

View File

@ -15,6 +15,8 @@ namespace psm {
void InitializeSSLServerCertVerificationThreads();
void StopSSLServerCertVerificationThreads();
void ConfigureMD5(bool enabled);
nsresult InitializeCipherSuite();
} //namespace psm
} // namespace mozilla

View File

@ -18,6 +18,8 @@
#include "nsICertOverrideService.h"
#include "mozilla/Preferences.h"
#include "nsThreadUtils.h"
#include "mozilla/PublicSSL.h"
#include "mozilla/StaticPtr.h"
#ifndef MOZ_DISABLE_CRYPTOLEGACY
#include "nsIDOMNode.h"
@ -896,6 +898,90 @@ setNonPkixOcspEnabled(int32_t ocspEnabled)
#define USE_NSS_LIBPKIX_DEFAULT false
#define OCSP_STAPLING_ENABLED_DEFAULT true
static const bool SUPPRESS_WARNING_PREF_DEFAULT = false;
static const bool MD5_ENABLED_DEFAULT = false;
static const bool REQUIRE_SAFE_NEGOTIATION_DEFAULT = false;
static const bool ALLOW_UNRESTRICTED_RENEGO_DEFAULT = false;
static const bool FALSE_START_ENABLED_DEFAULT = true;
static const bool CIPHER_ENABLED_DEFAULT = false;
namespace {
class CipherSuiteChangeObserver : public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
virtual ~CipherSuiteChangeObserver() {}
static nsresult StartObserve();
static nsresult StopObserve();
private:
static StaticRefPtr<CipherSuiteChangeObserver> sObserver;
CipherSuiteChangeObserver() {}
};
NS_IMPL_ISUPPORTS1(CipherSuiteChangeObserver, nsIObserver)
// static
StaticRefPtr<CipherSuiteChangeObserver> CipherSuiteChangeObserver::sObserver;
// static
nsresult
CipherSuiteChangeObserver::StartObserve()
{
NS_ASSERTION(NS_IsMainThread(), "CipherSuiteChangeObserver::StartObserve() can only be accessed in main thread");
if (!sObserver) {
nsRefPtr<CipherSuiteChangeObserver> observer = new CipherSuiteChangeObserver();
nsresult rv = Preferences::AddStrongObserver(observer.get(), "security.");
if (NS_FAILED(rv)) {
sObserver = nullptr;
return rv;
}
sObserver = observer;
}
return NS_OK;
}
// static
nsresult
CipherSuiteChangeObserver::StopObserve()
{
NS_ASSERTION(NS_IsMainThread(), "CipherSuiteChangeObserver::StopObserve() can only be accessed in main thread");
if (sObserver) {
nsresult rv = Preferences::RemoveObserver(sObserver.get(), "security.");
sObserver = nullptr;
if (NS_FAILED(rv)) {
return rv;
}
}
return NS_OK;
}
nsresult
CipherSuiteChangeObserver::Observe(nsISupports *aSubject,
const char *aTopic,
const PRUnichar *someData)
{
NS_ASSERTION(NS_IsMainThread(), "CipherSuiteChangeObserver::Observe can only be accessed in main thread");
if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
NS_ConvertUTF16toUTF8 prefName(someData);
/* Look through the cipher table and set according to pref setting */
for (CipherPref* cp = CipherPrefs; cp->pref; ++cp) {
if (prefName.Equals(cp->pref)) {
bool cipherEnabled = Preferences::GetBool(cp->pref, CIPHER_ENABLED_DEFAULT);
SSL_CipherPrefSetDefault(cp->id, cipherEnabled);
SSL_ClearSessionCache();
break;
}
}
}
return NS_OK;
}
} // anonymous namespace
// Caller must hold a lock on nsNSSComponent::mutex when calling this function
void nsNSSComponent::setValidationOptions()
{
@ -1027,33 +1113,6 @@ nsNSSComponent::SkipOcspOff()
return NS_OK;
}
static void configureMD5(bool enabled)
{
if (enabled) { // set flags
NSS_SetAlgorithmPolicy(SEC_OID_MD5,
NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE, 0);
NSS_SetAlgorithmPolicy(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION,
NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE, 0);
NSS_SetAlgorithmPolicy(SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC,
NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE, 0);
}
else { // clear flags
NSS_SetAlgorithmPolicy(SEC_OID_MD5,
0, NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE);
NSS_SetAlgorithmPolicy(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION,
0, NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE);
NSS_SetAlgorithmPolicy(SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC,
0, NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE);
}
}
static const bool SUPPRESS_WARNING_PREF_DEFAULT = false;
static const bool MD5_ENABLED_DEFAULT = false;
static const bool REQUIRE_SAFE_NEGOTIATION_DEFAULT = false;
static const bool ALLOW_UNRESTRICTED_RENEGO_DEFAULT = false;
static const bool FALSE_START_ENABLED_DEFAULT = true;
static const bool CIPHER_ENABLED_DEFAULT = false;
nsresult
nsNSSComponent::InitializeNSS(bool showWarningBox)
{
@ -1186,8 +1245,6 @@ nsNSSComponent::InitializeNSS(bool showWarningBox)
mNSSInitialized = true;
::NSS_SetDomesticPolicy();
PK11_SetPasswordFunc(PK11PasswordPrompt);
SharedSSLState::GlobalInit();
@ -1206,7 +1263,7 @@ nsNSSComponent::InitializeNSS(bool showWarningBox)
bool md5Enabled = Preferences::GetBool("security.enable_md5_signatures",
MD5_ENABLED_DEFAULT);
configureMD5(md5Enabled);
ConfigureMD5(md5Enabled);
SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, true);
@ -1228,30 +1285,11 @@ nsNSSComponent::InitializeNSS(bool showWarningBox)
// FALSE_START_ENABLED_DEFAULT);
SSL_OptionSetDefault(SSL_ENABLE_FALSE_START, false);
// Disable any ciphers that NSS might have enabled by default
for (uint16_t i = 0; i < SSL_NumImplementedCiphers; ++i)
{
uint16_t cipher_id = SSL_ImplementedCiphers[i];
SSL_CipherPrefSetDefault(cipher_id, false);
if (NS_FAILED(InitializeCipherSuite())) {
PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to initialize cipher suite settings\n"));
return NS_ERROR_FAILURE;
}
bool cipherEnabled;
// Now only set SSL/TLS ciphers we knew about at compile time
for (CipherPref* cp = CipherPrefs; cp->pref; ++cp) {
cipherEnabled = Preferences::GetBool(cp->pref, CIPHER_ENABLED_DEFAULT);
SSL_CipherPrefSetDefault(cp->id, cipherEnabled);
}
// Enable ciphers for PKCS#12
SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
PORT_SetUCS2_ASCIIConversionFunction(pip_ucs2_ascii_conversion_fn);
// dynamic options from prefs
setValidationOptions();
@ -1300,6 +1338,9 @@ nsNSSComponent::ShutdownNSS()
mHttpForNSS.unregisterHttpClient();
Preferences::RemoveObserver(this, "security.");
if (NS_FAILED(CipherSuiteChangeObserver::StopObserve())) {
PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("nsNSSComponent::ShutdownNSS cannot stop observing cipher suite change\n"));
}
#ifndef MOZ_DISABLE_CRYPTOLEGACY
ShutdownSmartCardThreads();
@ -1638,7 +1679,7 @@ nsNSSComponent::Observe(nsISupports *aSubject, const char *aTopic,
} else if (prefName.Equals("security.enable_md5_signatures")) {
bool md5Enabled = Preferences::GetBool("security.enable_md5_signatures",
MD5_ENABLED_DEFAULT);
configureMD5(md5Enabled);
ConfigureMD5(md5Enabled);
clearSessionCache = true;
} else if (prefName.Equals("security.ssl.require_safe_negotiation")) {
bool requireSafeNegotiation =
@ -1672,17 +1713,6 @@ nsNSSComponent::Observe(nsISupports *aSubject, const char *aTopic,
bool sendLM = Preferences::GetBool("network.ntlm.send-lm-response",
SEND_LM_DEFAULT);
nsNTLMAuthModule::SetSendLM(sendLM);
} else {
/* Look through the cipher table and set according to pref setting */
bool cipherEnabled;
for (CipherPref* cp = CipherPrefs; cp->pref; ++cp) {
if (prefName.Equals(cp->pref)) {
cipherEnabled = Preferences::GetBool(cp->pref, CIPHER_ENABLED_DEFAULT);
SSL_CipherPrefSetDefault(cp->id, cipherEnabled);
clearSessionCache = true;
break;
}
}
}
if (clearSessionCache)
SSL_ClearSessionCache();
@ -1970,3 +2000,64 @@ setPassword(PK11SlotInfo *slot, nsIInterfaceRequestor *ctx)
loser:
return rv;
}
namespace mozilla {
namespace psm {
void ConfigureMD5(bool enabled)
{
if (enabled) { // set flags
NSS_SetAlgorithmPolicy(SEC_OID_MD5,
NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE, 0);
NSS_SetAlgorithmPolicy(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION,
NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE, 0);
NSS_SetAlgorithmPolicy(SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC,
NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE, 0);
}
else { // clear flags
NSS_SetAlgorithmPolicy(SEC_OID_MD5,
0, NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE);
NSS_SetAlgorithmPolicy(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION,
0, NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE);
NSS_SetAlgorithmPolicy(SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC,
0, NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE);
}
}
nsresult InitializeCipherSuite()
{
NS_ASSERTION(NS_IsMainThread(), "InitializeCipherSuite() can only be accessed in main thread");
if (NSS_SetDomesticPolicy() != SECSuccess) {
return NS_ERROR_FAILURE;
}
// Disable any ciphers that NSS might have enabled by default
for (uint16_t i = 0; i < SSL_NumImplementedCiphers; ++i) {
uint16_t cipher_id = SSL_ImplementedCiphers[i];
SSL_CipherPrefSetDefault(cipher_id, false);
}
bool cipherEnabled;
// Now only set SSL/TLS ciphers we knew about at compile time
for (CipherPref* cp = CipherPrefs; cp->pref; ++cp) {
cipherEnabled = Preferences::GetBool(cp->pref, CIPHER_ENABLED_DEFAULT);
SSL_CipherPrefSetDefault(cp->id, cipherEnabled);
}
// Enable ciphers for PKCS#12
SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
PORT_SetUCS2_ASCIIConversionFunction(pip_ucs2_ascii_conversion_fn);
// Observe preference change around cipher suite setting.
return CipherSuiteChangeObserver::StartObserve();
}
} // namespace psm
} // namespace mozilla

View File

@ -16,6 +16,8 @@
<head>
<title>&aboutSupport.pageTitle;</title>
<link rel="icon" type="image/png" id="favicon"
href="chrome://branding/content/icon32.png"/>
<link rel="stylesheet" href="chrome://global/skin/aboutSupport.css"
type="text/css"/>

View File

@ -193,14 +193,11 @@ AndroidBridge::Init(JNIEnv *jEnv)
jSurfaceClass = getClassGlobalRef("android/view/Surface");
if (mAPIVersion <= 8 /* Froyo */) {
jSurfacePointerField = getField("mSurface", "I");
} else {
} else if (mAPIVersion > 8 && mAPIVersion < 19 /* KitKat */) {
jSurfacePointerField = getField("mNativeSurface", "I");
// Apparently mNativeSurface doesn't exist in Key Lime Pie, so just clear the
// exception if we have one and move on.
if (jEnv->ExceptionCheck()) {
jEnv->ExceptionClear();
}
} else {
// We don't know how to get this, just set it to 0
jSurfacePointerField = 0;
}
jclass eglClass = getClassGlobalRef("com/google/android/gles_jni/EGLSurfaceImpl");