mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to inbound.
This commit is contained in:
commit
f204ac27b3
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "a824661b83388d17f80c28a1d538eae382b3d07d",
|
||||
"revision": "00ceae21c52602059b7614b661bc39a3c73c84de",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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())) {
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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".
|
||||
*/
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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!");
|
||||
|
@ -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)
|
||||
|
@ -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
@ -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);
|
||||
};
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -15,6 +15,8 @@ namespace psm {
|
||||
|
||||
void InitializeSSLServerCertVerificationThreads();
|
||||
void StopSSLServerCertVerificationThreads();
|
||||
void ConfigureMD5(bool enabled);
|
||||
nsresult InitializeCipherSuite();
|
||||
|
||||
} //namespace psm
|
||||
} // namespace mozilla
|
||||
|
@ -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
|
||||
|
@ -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"/>
|
||||
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user